diff options
Diffstat (limited to 'src/osd/modules/debugger')
76 files changed, 5727 insertions, 3163 deletions
diff --git a/src/osd/modules/debugger/debug_module.h b/src/osd/modules/debugger/debug_module.h index fb659a1b312..1c5b1973c8e 100644 --- a/src/osd/modules/debugger/debug_module.h +++ b/src/osd/modules/debugger/debug_module.h @@ -4,13 +4,15 @@ * debug_module.h * */ +#ifndef MAME_OSD_DEBUGGER_DEBUG_MODULE_H +#define MAME_OSD_DEBUGGER_DEBUG_MODULE_H -#ifndef DEBUG_MODULE_H_ -#define DEBUG_MODULE_H_ +#pragma once #include "osdepend.h" #include "modules/osdmodule.h" + //============================================================ // CONSTANTS //============================================================ @@ -20,14 +22,11 @@ class debug_module { public: - - virtual ~debug_module() { } + virtual ~debug_module() = default; virtual void init_debugger(running_machine &machine) = 0; virtual void wait_for_debugger(device_t &device, bool firststop) = 0; virtual void debugger_update() = 0; }; - - -#endif /* DEBUG_MODULE_H_ */ +#endif // MAME_OSD_DEBUGGER_DEBUG_MODULE_H diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp index 4c7e4e3707e..729280f2134 100644 --- a/src/osd/modules/debugger/debuggdbstub.cpp +++ b/src/osd/modules/debugger/debuggdbstub.cpp @@ -7,15 +7,26 @@ //============================================================ #include "emu.h" +#include "debug_module.h" + #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "debug/textbuf.h" -#include "debug_module.h" #include "debugger.h" + #include "modules/lib/osdobj_common.h" #include "modules/osdmodule.h" +#include "fileio.h" + #include <cinttypes> +#include <string_view> + + +namespace osd { + +namespace { //------------------------------------------------------------------------- #define MAX_PACKET_SIZE 16384 @@ -37,71 +48,85 @@ static const char *const gdb_register_type_str[] = { struct gdb_register_map { const char *arch; - const char *feature; - struct gdb_register_description + struct gdb_feature { - const char *state_name; - const char *gdb_name; - bool stop_packet; - gdb_register_type gdb_type; - int override_bitsize; - - gdb_register_description(const char *_state_name=nullptr, const char *_gdb_name=nullptr, bool _stop_packet=false, gdb_register_type _gdb_type=TYPE_INT, int _override_bitsize=-1) - : state_name(_state_name) - , gdb_name(_gdb_name) - , stop_packet(_stop_packet) - , gdb_type(_gdb_type) - , override_bitsize(_override_bitsize) + const char *feature_name; + struct gdb_register_description + { + const char *state_name; + const char *gdb_name; + bool stop_packet; + gdb_register_type gdb_type; + int override_bitsize; + + gdb_register_description(const char *_state_name = nullptr, const char *_gdb_name = nullptr, bool _stop_packet = false, gdb_register_type _gdb_type = TYPE_INT, int _override_bitsize = -1) + : state_name(_state_name) + , gdb_name(_gdb_name) + , stop_packet(_stop_packet) + , gdb_type(_gdb_type) + , override_bitsize(_override_bitsize) + { + } + }; + std::vector<gdb_register_description> registers; + + gdb_feature(const char *_feature_name, std::initializer_list<gdb_register_description> _registers) + : feature_name(_feature_name) + , registers(_registers) { } }; - std::vector<gdb_register_description> registers; + std::vector<gdb_feature> features; }; //------------------------------------------------------------------------- static const gdb_register_map gdb_register_map_i486 = { "i386", - "org.gnu.gdb.i386.core", { - { "EAX", "eax", false, TYPE_INT }, - { "ECX", "ecx", false, TYPE_INT }, - { "EDX", "edx", false, TYPE_INT }, - { "EBX", "ebx", false, TYPE_INT }, - { "ESP", "esp", true, TYPE_DATA_POINTER }, - { "EBP", "ebp", true, TYPE_DATA_POINTER }, - { "ESI", "esi", false, TYPE_INT }, - { "EDI", "edi", false, TYPE_INT }, - { "EIP", "eip", true, TYPE_CODE_POINTER }, - { "EFLAGS", "eflags", false, TYPE_INT }, // TODO describe bitfield - { "CS", "cs", false, TYPE_INT }, - { "SS", "ss", false, TYPE_INT }, - { "DS", "ds", false, TYPE_INT }, - { "ES", "es", false, TYPE_INT }, - { "FS", "fs", false, TYPE_INT }, - { "GS", "gs", false, TYPE_INT }, - // TODO fix x87 registers! - // The x87 registers are just plain wrong for a few reasons: - // - The st* registers use a dummy variable in i386_device, so we - // don't retrieve the real value (also the bitsize is wrong); - // - The seg/off/op registers don't seem to be exported in the - // state. - { "ST0", "st0", false, TYPE_I387_EXT }, - { "ST1", "st1", false, TYPE_I387_EXT }, - { "ST2", "st2", false, TYPE_I387_EXT }, - { "ST3", "st3", false, TYPE_I387_EXT }, - { "ST4", "st4", false, TYPE_I387_EXT }, - { "ST5", "st5", false, TYPE_I387_EXT }, - { "ST6", "st6", false, TYPE_I387_EXT }, - { "ST7", "st7", false, TYPE_I387_EXT }, - { "x87_CW", "fctrl", false, TYPE_INT }, - { "x87_SW", "fstat", false, TYPE_INT }, - { "x87_TAG", "ftag", false, TYPE_INT }, - { "EAX", "fiseg", false, TYPE_INT }, - { "EAX", "fioff", false, TYPE_INT }, - { "EAX", "foseg", false, TYPE_INT }, - { "EAX", "fooff", false, TYPE_INT }, - { "EAX", "fop", false, TYPE_INT }, + { + "org.gnu.gdb.i386.core", + { + { "EAX", "eax", false, TYPE_INT }, + { "ECX", "ecx", false, TYPE_INT }, + { "EDX", "edx", false, TYPE_INT }, + { "EBX", "ebx", false, TYPE_INT }, + { "ESP", "esp", true, TYPE_DATA_POINTER }, + { "EBP", "ebp", true, TYPE_DATA_POINTER }, + { "ESI", "esi", false, TYPE_INT }, + { "EDI", "edi", false, TYPE_INT }, + { "EIP", "eip", true, TYPE_CODE_POINTER }, + { "EFLAGS", "eflags", false, TYPE_INT }, // TODO describe bitfield + { "CS", "cs", false, TYPE_INT }, + { "SS", "ss", false, TYPE_INT }, + { "DS", "ds", false, TYPE_INT }, + { "ES", "es", false, TYPE_INT }, + { "FS", "fs", false, TYPE_INT }, + { "GS", "gs", false, TYPE_INT }, + // TODO fix x87 registers! + // The x87 registers are just plain wrong for a few reasons: + // - The st* registers use a dummy variable in i386_device, so we + // don't retrieve the real value (also the bitsize is wrong); + // - The seg/off/op registers don't seem to be exported in the + // state. + { "ST0", "st0", false, TYPE_I387_EXT }, + { "ST1", "st1", false, TYPE_I387_EXT }, + { "ST2", "st2", false, TYPE_I387_EXT }, + { "ST3", "st3", false, TYPE_I387_EXT }, + { "ST4", "st4", false, TYPE_I387_EXT }, + { "ST5", "st5", false, TYPE_I387_EXT }, + { "ST6", "st6", false, TYPE_I387_EXT }, + { "ST7", "st7", false, TYPE_I387_EXT }, + { "x87_CW", "fctrl", false, TYPE_INT }, + { "x87_SW", "fstat", false, TYPE_INT }, + { "x87_TAG", "ftag", false, TYPE_INT }, + { "EAX", "fiseg", false, TYPE_INT }, + { "EAX", "fioff", false, TYPE_INT }, + { "EAX", "foseg", false, TYPE_INT }, + { "EAX", "fooff", false, TYPE_INT }, + { "EAX", "fop", false, TYPE_INT }, + } + } } }; @@ -109,25 +134,29 @@ static const gdb_register_map gdb_register_map_i486 = static const gdb_register_map gdb_register_map_arm7 = { "arm", - "org.gnu.gdb.arm.core", { - { "R0", "r0", false, TYPE_INT }, - { "R1", "r1", false, TYPE_INT }, - { "R2", "r2", false, TYPE_INT }, - { "R3", "r3", false, TYPE_INT }, - { "R4", "r4", false, TYPE_INT }, - { "R5", "r5", false, TYPE_INT }, - { "R6", "r6", false, TYPE_INT }, - { "R7", "r7", false, TYPE_INT }, - { "R8", "r8", false, TYPE_INT }, - { "R9", "r9", false, TYPE_INT }, - { "R10", "r10", false, TYPE_INT }, - { "R11", "r11", false, TYPE_INT }, - { "R12", "r12", false, TYPE_INT }, - { "R13", "sp", true, TYPE_DATA_POINTER }, - { "R14", "lr", true, TYPE_INT }, - { "R15", "pc", true, TYPE_CODE_POINTER }, - { "CPSR", "cpsr", false, TYPE_INT }, // TODO describe bitfield + { + "org.gnu.gdb.arm.core", + { + { "R0", "r0", false, TYPE_INT }, + { "R1", "r1", false, TYPE_INT }, + { "R2", "r2", false, TYPE_INT }, + { "R3", "r3", false, TYPE_INT }, + { "R4", "r4", false, TYPE_INT }, + { "R5", "r5", false, TYPE_INT }, + { "R6", "r6", false, TYPE_INT }, + { "R7", "r7", false, TYPE_INT }, + { "R8", "r8", false, TYPE_INT }, + { "R9", "r9", false, TYPE_INT }, + { "R10", "r10", false, TYPE_INT }, + { "R11", "r11", false, TYPE_INT }, + { "R12", "r12", false, TYPE_INT }, + { "R13", "sp", true, TYPE_DATA_POINTER }, + { "R14", "lr", true, TYPE_INT }, + { "R15", "pc", true, TYPE_CODE_POINTER }, + { "CPSR", "cpsr", false, TYPE_INT }, // TODO describe bitfield + } + } } }; @@ -135,46 +164,50 @@ static const gdb_register_map gdb_register_map_arm7 = static const gdb_register_map gdb_register_map_ppc601 = { "powerpc:common", - "org.gnu.gdb.power.core", { - { "R0", "r0", false, TYPE_INT }, - { "R1", "r1", false, TYPE_INT }, - { "R2", "r2", false, TYPE_INT }, - { "R3", "r3", false, TYPE_INT }, - { "R4", "r4", false, TYPE_INT }, - { "R5", "r5", false, TYPE_INT }, - { "R6", "r6", false, TYPE_INT }, - { "R7", "r7", false, TYPE_INT }, - { "R8", "r8", false, TYPE_INT }, - { "R9", "r9", false, TYPE_INT }, - { "R10", "r10", false, TYPE_INT }, - { "R11", "r11", false, TYPE_INT }, - { "R12", "r12", false, TYPE_INT }, - { "R13", "r13", false, TYPE_INT }, - { "R14", "r14", false, TYPE_INT }, - { "R15", "r15", false, TYPE_INT }, - { "R16", "r16", false, TYPE_INT }, - { "R17", "r17", false, TYPE_INT }, - { "R18", "r18", false, TYPE_INT }, - { "R19", "r19", false, TYPE_INT }, - { "R20", "r20", false, TYPE_INT }, - { "R21", "r21", false, TYPE_INT }, - { "R22", "r22", false, TYPE_INT }, - { "R23", "r23", false, TYPE_INT }, - { "R24", "r24", false, TYPE_INT }, - { "R25", "r25", false, TYPE_INT }, - { "R26", "r26", false, TYPE_INT }, - { "R27", "r27", false, TYPE_INT }, - { "R28", "r28", false, TYPE_INT }, - { "R29", "r29", false, TYPE_INT }, - { "R30", "r30", false, TYPE_INT }, - { "R31", "r31", false, TYPE_INT }, - { "PC", "pc", true, TYPE_CODE_POINTER }, - { "MSR", "msr", false, TYPE_INT }, - { "CR", "cr", false, TYPE_INT }, - { "LR", "lr", true, TYPE_CODE_POINTER }, - { "CTR", "ctr", false, TYPE_INT }, - { "XER", "xer", false, TYPE_INT }, + { + "org.gnu.gdb.power.core", + { + { "R0", "r0", false, TYPE_INT }, + { "R1", "r1", false, TYPE_INT }, + { "R2", "r2", false, TYPE_INT }, + { "R3", "r3", false, TYPE_INT }, + { "R4", "r4", false, TYPE_INT }, + { "R5", "r5", false, TYPE_INT }, + { "R6", "r6", false, TYPE_INT }, + { "R7", "r7", false, TYPE_INT }, + { "R8", "r8", false, TYPE_INT }, + { "R9", "r9", false, TYPE_INT }, + { "R10", "r10", false, TYPE_INT }, + { "R11", "r11", false, TYPE_INT }, + { "R12", "r12", false, TYPE_INT }, + { "R13", "r13", false, TYPE_INT }, + { "R14", "r14", false, TYPE_INT }, + { "R15", "r15", false, TYPE_INT }, + { "R16", "r16", false, TYPE_INT }, + { "R17", "r17", false, TYPE_INT }, + { "R18", "r18", false, TYPE_INT }, + { "R19", "r19", false, TYPE_INT }, + { "R20", "r20", false, TYPE_INT }, + { "R21", "r21", false, TYPE_INT }, + { "R22", "r22", false, TYPE_INT }, + { "R23", "r23", false, TYPE_INT }, + { "R24", "r24", false, TYPE_INT }, + { "R25", "r25", false, TYPE_INT }, + { "R26", "r26", false, TYPE_INT }, + { "R27", "r27", false, TYPE_INT }, + { "R28", "r28", false, TYPE_INT }, + { "R29", "r29", false, TYPE_INT }, + { "R30", "r30", false, TYPE_INT }, + { "R31", "r31", false, TYPE_INT }, + { "PC", "pc", true, TYPE_CODE_POINTER }, + { "MSR", "msr", false, TYPE_INT }, + { "CR", "cr", false, TYPE_INT }, + { "LR", "lr", true, TYPE_CODE_POINTER }, + { "CTR", "ctr", false, TYPE_INT }, + { "XER", "xer", false, TYPE_INT }, + } + } } }; @@ -182,43 +215,78 @@ static const gdb_register_map gdb_register_map_ppc601 = static const gdb_register_map gdb_register_map_r4600 = { "mips", - "org.gnu.gdb.mips.cpu", { - { "zero", "r0", false, TYPE_INT, 32 }, - { "at", "r1", false, TYPE_INT, 32 }, - { "v0", "r2", false, TYPE_INT, 32 }, - { "v1", "r3", false, TYPE_INT, 32 }, - { "a0", "r4", false, TYPE_INT, 32 }, - { "a1", "r5", false, TYPE_INT, 32 }, - { "a2", "r6", false, TYPE_INT, 32 }, - { "a3", "r7", false, TYPE_INT, 32 }, - { "t0", "r8", false, TYPE_INT, 32 }, - { "t1", "r9", false, TYPE_INT, 32 }, - { "t2", "r10", false, TYPE_INT, 32 }, - { "t3", "r11", false, TYPE_INT, 32 }, - { "t4", "r12", false, TYPE_INT, 32 }, - { "t5", "r13", false, TYPE_INT, 32 }, - { "t6", "r14", false, TYPE_INT, 32 }, - { "t7", "r15", false, TYPE_INT, 32 }, - { "s0", "r16", false, TYPE_INT, 32 }, - { "s1", "r17", false, TYPE_INT, 32 }, - { "s2", "r18", false, TYPE_INT, 32 }, - { "s3", "r19", false, TYPE_INT, 32 }, - { "s4", "r20", false, TYPE_INT, 32 }, - { "s5", "r21", false, TYPE_INT, 32 }, - { "s6", "r22", false, TYPE_INT, 32 }, - { "s7", "r23", false, TYPE_INT, 32 }, - { "t8", "r24", false, TYPE_INT, 32 }, - { "t9", "r25", false, TYPE_INT, 32 }, - { "k0", "r26", false, TYPE_INT, 32 }, - { "k1", "r27", false, TYPE_INT, 32 }, - { "gp", "r28", false, TYPE_INT, 32 }, - { "sp", "r29", false, TYPE_INT, 32 }, - { "fp", "r30", false, TYPE_INT, 32 }, - { "ra", "r31", false, TYPE_INT, 32 }, - { "LO", "lo", false, TYPE_INT, 32 }, - { "HI", "hi", false, TYPE_INT, 32 }, - { "PC", "pc", true, TYPE_CODE_POINTER, 32 }, + { + "org.gnu.gdb.mips.cpu", + { + { "zero", "r0", false, TYPE_INT, 32 }, + { "at", "r1", false, TYPE_INT, 32 }, + { "v0", "r2", false, TYPE_INT, 32 }, + { "v1", "r3", false, TYPE_INT, 32 }, + { "a0", "r4", false, TYPE_INT, 32 }, + { "a1", "r5", false, TYPE_INT, 32 }, + { "a2", "r6", false, TYPE_INT, 32 }, + { "a3", "r7", false, TYPE_INT, 32 }, + { "t0", "r8", false, TYPE_INT, 32 }, + { "t1", "r9", false, TYPE_INT, 32 }, + { "t2", "r10", false, TYPE_INT, 32 }, + { "t3", "r11", false, TYPE_INT, 32 }, + { "t4", "r12", false, TYPE_INT, 32 }, + { "t5", "r13", false, TYPE_INT, 32 }, + { "t6", "r14", false, TYPE_INT, 32 }, + { "t7", "r15", false, TYPE_INT, 32 }, + { "s0", "r16", false, TYPE_INT, 32 }, + { "s1", "r17", false, TYPE_INT, 32 }, + { "s2", "r18", false, TYPE_INT, 32 }, + { "s3", "r19", false, TYPE_INT, 32 }, + { "s4", "r20", false, TYPE_INT, 32 }, + { "s5", "r21", false, TYPE_INT, 32 }, + { "s6", "r22", false, TYPE_INT, 32 }, + { "s7", "r23", false, TYPE_INT, 32 }, + { "t8", "r24", false, TYPE_INT, 32 }, + { "t9", "r25", false, TYPE_INT, 32 }, + { "k0", "r26", false, TYPE_INT, 32 }, + { "k1", "r27", false, TYPE_INT, 32 }, + { "gp", "r28", false, TYPE_INT, 32 }, + { "sp", "r29", false, TYPE_INT, 32 }, + { "fp", "r30", false, TYPE_INT, 32 }, + { "ra", "r31", false, TYPE_INT, 32 }, + { "LO", "lo", false, TYPE_INT, 32 }, + { "HI", "hi", false, TYPE_INT, 32 }, + { "PC", "pc", true, TYPE_CODE_POINTER, 32 }, + } + } + } +}; + +//------------------------------------------------------------------------- +static const gdb_register_map gdb_register_map_m68030 = +{ + "m68k", + { + { + "org.gnu.gdb.m68k.core", + { + { "D0", "d0", false, TYPE_INT }, + { "D1", "d1", false, TYPE_INT }, + { "D2", "d2", false, TYPE_INT }, + { "D3", "d3", false, TYPE_INT }, + { "D4", "d4", false, TYPE_INT }, + { "D5", "d5", false, TYPE_INT }, + { "D6", "d6", false, TYPE_INT }, + { "D7", "d7", false, TYPE_INT }, + { "A0", "a0", false, TYPE_INT }, + { "A1", "a1", false, TYPE_INT }, + { "A2", "a2", false, TYPE_INT }, + { "A3", "a3", false, TYPE_INT }, + { "A4", "a4", false, TYPE_INT }, + { "A5", "a5", false, TYPE_INT }, + { "A6", "fp", true, TYPE_INT }, + { "SP", "sp", true, TYPE_INT }, + { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr + { "CURPC","pc", true, TYPE_CODE_POINTER }, + } + } } }; @@ -226,26 +294,62 @@ static const gdb_register_map gdb_register_map_r4600 = static const gdb_register_map gdb_register_map_m68020pmmu = { "m68k", - "org.gnu.gdb.m68k.core", { - { "D0", "d0", false, TYPE_INT }, - { "D1", "d1", false, TYPE_INT }, - { "D2", "d2", false, TYPE_INT }, - { "D3", "d3", false, TYPE_INT }, - { "D4", "d4", false, TYPE_INT }, - { "D5", "d5", false, TYPE_INT }, - { "D6", "d6", false, TYPE_INT }, - { "D7", "d7", false, TYPE_INT }, - { "A0", "a0", false, TYPE_INT }, - { "A1", "a1", false, TYPE_INT }, - { "A2", "a2", false, TYPE_INT }, - { "A3", "a3", false, TYPE_INT }, - { "A4", "a4", false, TYPE_INT }, - { "A5", "a5", false, TYPE_INT }, - { "A6", "fp", true, TYPE_INT }, - { "A7", "sp", true, TYPE_INT }, - { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr - { "PC", "pc", true, TYPE_CODE_POINTER }, + { + "org.gnu.gdb.m68k.core", + { + { "D0", "d0", false, TYPE_INT }, + { "D1", "d1", false, TYPE_INT }, + { "D2", "d2", false, TYPE_INT }, + { "D3", "d3", false, TYPE_INT }, + { "D4", "d4", false, TYPE_INT }, + { "D5", "d5", false, TYPE_INT }, + { "D6", "d6", false, TYPE_INT }, + { "D7", "d7", false, TYPE_INT }, + { "A0", "a0", false, TYPE_INT }, + { "A1", "a1", false, TYPE_INT }, + { "A2", "a2", false, TYPE_INT }, + { "A3", "a3", false, TYPE_INT }, + { "A4", "a4", false, TYPE_INT }, + { "A5", "a5", false, TYPE_INT }, + { "A6", "fp", true, TYPE_INT }, + { "SP", "sp", true, TYPE_INT }, + { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr + { "CURPC","pc", true, TYPE_CODE_POINTER }, + } + } + } +}; + +//------------------------------------------------------------------------- +static const gdb_register_map gdb_register_map_m68000 = +{ + "m68k", + { + { + "org.gnu.gdb.m68k.core", + { + { "D0", "d0", false, TYPE_INT }, + { "D1", "d1", false, TYPE_INT }, + { "D2", "d2", false, TYPE_INT }, + { "D3", "d3", false, TYPE_INT }, + { "D4", "d4", false, TYPE_INT }, + { "D5", "d5", false, TYPE_INT }, + { "D6", "d6", false, TYPE_INT }, + { "D7", "d7", false, TYPE_INT }, + { "A0", "a0", false, TYPE_INT }, + { "A1", "a1", false, TYPE_INT }, + { "A2", "a2", false, TYPE_INT }, + { "A3", "a3", false, TYPE_INT }, + { "A4", "a4", false, TYPE_INT }, + { "A5", "a5", false, TYPE_INT }, + { "A6", "fp", true, TYPE_INT }, + { "SP", "sp", true, TYPE_INT }, + { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr + { "CURPC","pc", true, TYPE_CODE_POINTER }, + //NOTE m68-elf-gdb complains about fpcontrol register not present but 68000 doesn't have floating point so... + } + } } }; @@ -253,20 +357,24 @@ static const gdb_register_map gdb_register_map_m68020pmmu = static const gdb_register_map gdb_register_map_z80 = { "z80", - "mame.z80", { - { "AF", "af", false, TYPE_INT }, - { "BC", "bc", false, TYPE_INT }, - { "DE", "de", false, TYPE_INT }, - { "HL", "hl", false, TYPE_INT }, - { "AF2", "af'", false, TYPE_INT }, - { "BC2", "bc'", false, TYPE_INT }, - { "DE2", "de'", false, TYPE_INT }, - { "HL2", "hl'", false, TYPE_INT }, - { "IX", "ix", false, TYPE_INT }, - { "IY", "iy", false, TYPE_INT }, - { "SP", "sp", true, TYPE_DATA_POINTER }, - { "PC", "pc", true, TYPE_CODE_POINTER }, + { + "mame.z80", + { + { "AF", "af", false, TYPE_INT }, + { "BC", "bc", false, TYPE_INT }, + { "DE", "de", false, TYPE_INT }, + { "HL", "hl", false, TYPE_INT }, + { "AF2", "af'", false, TYPE_INT }, + { "BC2", "bc'", false, TYPE_INT }, + { "DE2", "de'", false, TYPE_INT }, + { "HL2", "hl'", false, TYPE_INT }, + { "IX", "ix", false, TYPE_INT }, + { "IY", "iy", false, TYPE_INT }, + { "SP", "sp", true, TYPE_DATA_POINTER }, + { "PC", "pc", true, TYPE_CODE_POINTER }, + } + } } }; @@ -274,14 +382,270 @@ static const gdb_register_map gdb_register_map_z80 = static const gdb_register_map gdb_register_map_m6502 = { "m6502", - "mame.m6502", { - { "A", "a", false, TYPE_INT }, - { "X", "x", false, TYPE_INT }, - { "Y", "y", false, TYPE_INT }, - { "P", "p", false, TYPE_INT }, - { "PC", "pc", true, TYPE_CODE_POINTER }, - { "SP", "sp", true, TYPE_DATA_POINTER }, + { + "mame.m6502", + { + { "A", "a", false, TYPE_INT }, + { "X", "x", false, TYPE_INT }, + { "Y", "y", false, TYPE_INT }, + { "P", "p", false, TYPE_INT }, + { "SP", "sp", true, TYPE_DATA_POINTER }, + { "PC", "pc", true, TYPE_CODE_POINTER }, + } + } + } +}; + + +//------------------------------------------------------------------------- +static const gdb_register_map gdb_register_map_m6809 = +{ + "m6809", + { + { + "mame.m6809", + { + { "A", "a", false, TYPE_INT }, + { "B", "b", false, TYPE_INT }, + { "D", "d", false, TYPE_INT }, + { "X", "x", false, TYPE_INT }, + { "Y", "y", false, TYPE_INT }, + { "U", "u", true, TYPE_DATA_POINTER }, + { "PC", "pc", true, TYPE_CODE_POINTER }, + { "S", "s", true, TYPE_DATA_POINTER }, + { "CC", "cc", false, TYPE_INT }, // TODO describe bitfield + { "DP", "dp", false, TYPE_INT }, + } + } + } +}; + + +//------------------------------------------------------------------------- +static const gdb_register_map gdb_register_map_score7 = +{ + "score7", + { + { + "mame.score7", + { + { "r0", "r0", true, TYPE_DATA_POINTER }, + { "r1", "r1", false, TYPE_INT }, + { "r2", "r2", false, TYPE_INT }, + { "r3", "r3", false, TYPE_INT }, + { "r4", "r4", false, TYPE_INT }, + { "r5", "r5", false, TYPE_INT }, + { "r6", "r6", false, TYPE_INT }, + { "r7", "r7", false, TYPE_INT }, + { "r8", "r8", false, TYPE_INT }, + { "r9", "r9", false, TYPE_INT }, + { "r10", "r10", false, TYPE_INT }, + { "r11", "r11", false, TYPE_INT }, + { "r12", "r12", false, TYPE_INT }, + { "r13", "r13", false, TYPE_INT }, + { "r14", "r14", false, TYPE_INT }, + { "r15", "r15", false, TYPE_INT }, + { "r16", "r16", false, TYPE_INT }, + { "r17", "r17", false, TYPE_INT }, + { "r18", "r18", false, TYPE_INT }, + { "r19", "r19", false, TYPE_INT }, + { "r20", "r20", false, TYPE_INT }, + { "r21", "r21", false, TYPE_INT }, + { "r22", "r22", false, TYPE_INT }, + { "r23", "r23", false, TYPE_INT }, + { "r24", "r24", false, TYPE_INT }, + { "r25", "r25", false, TYPE_INT }, + { "r26", "r26", false, TYPE_INT }, + { "r27", "r27", false, TYPE_INT }, + { "r28", "r28", false, TYPE_INT }, + { "r29", "r29", false, TYPE_INT }, + { "r30", "r30", false, TYPE_INT }, + { "r31", "r31", false, TYPE_INT }, + { "cr0", "PSR", false, TYPE_INT }, + { "cr1", "COND", false, TYPE_INT }, + { "cr2", "ECR", false, TYPE_INT }, + { "cr3", "EXCPVEC", false, TYPE_INT }, + { "cr4", "CCR", false, TYPE_INT }, + { "cr5", "EPC", false, TYPE_INT }, + { "cr6", "EMA", false, TYPE_INT }, + { "cr7", "TLBLOCK", false, TYPE_INT }, + { "cr8", "TLBPT", false, TYPE_INT }, + { "cr9", "PEADDR", false, TYPE_INT }, + { "cr10", "TLBRPT", false, TYPE_INT }, + { "cr11", "PEVN", false, TYPE_INT }, + { "cr12", "PECTX", false, TYPE_INT }, + { "cr15", "LIMPFN", false, TYPE_INT }, + { "cr16", "LDMPFN", false, TYPE_INT }, + { "cr18", "PREV", false, TYPE_INT }, + { "cr29", "DREG", false, TYPE_INT }, + { "PC", "PC", true, TYPE_CODE_POINTER }, // actually Debug exception program counter (DEPC) + { "cr31", "DSAVE", false, TYPE_INT }, + { "sr0", "COUNTER", false, TYPE_INT }, + { "sr1", "LDCR", false, TYPE_INT }, + { "sr2", "STCR", false, TYPE_INT }, + { "ceh", "CEH", false, TYPE_INT }, + { "cel", "CEL", false, TYPE_INT }, + } + } + } +}; + + +//------------------------------------------------------------------------- +static const gdb_register_map gdb_register_map_nios2 = +{ + "nios2", + { + { + "org.gnu.gdb.nios2.cpu", + { + { "zero", "zero", false, TYPE_INT }, + { "at", "at", false, TYPE_INT }, + { "r2", "r2", false, TYPE_INT }, + { "r3", "r3", false, TYPE_INT }, + { "r4", "r4", false, TYPE_INT }, + { "r5", "r5", false, TYPE_INT }, + { "r6", "r6", false, TYPE_INT }, + { "r7", "r7", false, TYPE_INT }, + { "r8", "r8", false, TYPE_INT }, + { "r9", "r9", false, TYPE_INT }, + { "r10", "r10", false, TYPE_INT }, + { "r11", "r11", false, TYPE_INT }, + { "r12", "r12", false, TYPE_INT }, + { "r13", "r13", false, TYPE_INT }, + { "r14", "r14", false, TYPE_INT }, + { "r15", "r15", false, TYPE_INT }, + { "r16", "r16", false, TYPE_INT }, + { "r17", "r17", false, TYPE_INT }, + { "r18", "r18", false, TYPE_INT }, + { "r19", "r19", false, TYPE_INT }, + { "r20", "r20", false, TYPE_INT }, + { "r21", "r21", false, TYPE_INT }, + { "r22", "r22", false, TYPE_INT }, + { "r23", "r23", false, TYPE_INT }, + { "et", "et", false, TYPE_INT }, + { "bt", "bt", false, TYPE_INT }, + { "gp", "gp", false, TYPE_DATA_POINTER }, + { "sp", "sp", true, TYPE_DATA_POINTER }, + { "fp", "fp", false, TYPE_DATA_POINTER }, + { "ea", "ea", false, TYPE_CODE_POINTER }, + { "ba", "sstatus", false, TYPE_INT }, // this is Altera's fault + { "ra", "ra", false, TYPE_CODE_POINTER }, + { "status", "status", false, TYPE_INT }, + { "estatus", "estatus", false, TYPE_INT }, + { "bstatus", "bstatus", false, TYPE_INT }, + { "ienable", "ienable", false, TYPE_INT }, + { "ipending", "ipending", false, TYPE_INT }, + { "cpuid", "cpuid", false, TYPE_INT }, + { "ctl6", "ctl6", false, TYPE_INT }, + { "exception","exception",false, TYPE_INT }, + { "pteaddr", "pteaddr", false, TYPE_INT }, + { "tlbacc", "tlbacc", false, TYPE_INT }, + { "tlbmisc", "tlbmisc", false, TYPE_INT }, + { "eccinj", "eccinj", false, TYPE_INT }, + { "badaddr", "badaddr", false, TYPE_INT }, + { "config", "config", false, TYPE_INT }, + { "mpubase", "mpubase", false, TYPE_INT }, + { "mpuacc", "mpuacc", false, TYPE_INT }, + { "PC", "pc", true, TYPE_CODE_POINTER }, + } + } + } +}; + +//------------------------------------------------------------------------- +static const gdb_register_map gdb_register_map_psxcpu = +{ + "mips", + { + { + "org.gnu.gdb.mips.cpu", + { + { "zero", "r0", false, TYPE_INT }, + { "at", "r1", false, TYPE_INT }, + { "v0", "r2", false, TYPE_INT }, + { "v1", "r3", false, TYPE_INT }, + { "a0", "r4", false, TYPE_INT }, + { "a1", "r5", false, TYPE_INT }, + { "a2", "r6", false, TYPE_INT }, + { "a3", "r7", false, TYPE_INT }, + { "t0", "r8", false, TYPE_INT }, + { "t1", "r9", false, TYPE_INT }, + { "t2", "r10", false, TYPE_INT }, + { "t3", "r11", false, TYPE_INT }, + { "t4", "r12", false, TYPE_INT }, + { "t5", "r13", false, TYPE_INT }, + { "t6", "r14", false, TYPE_INT }, + { "t7", "r15", false, TYPE_INT }, + { "s0", "r16", false, TYPE_INT }, + { "s1", "r17", false, TYPE_INT }, + { "s2", "r18", false, TYPE_INT }, + { "s3", "r19", false, TYPE_INT }, + { "s4", "r20", false, TYPE_INT }, + { "s5", "r21", false, TYPE_INT }, + { "s6", "r22", false, TYPE_INT }, + { "s7", "r23", false, TYPE_INT }, + { "t8", "r24", false, TYPE_INT }, + { "t9", "r25", false, TYPE_INT }, + { "k0", "r26", false, TYPE_INT }, + { "k1", "r27", false, TYPE_INT }, + { "gp", "r28", false, TYPE_INT }, + { "sp", "r29", false, TYPE_INT }, + { "fp", "r30", false, TYPE_INT }, + { "ra", "r31", false, TYPE_CODE_POINTER }, + { "lo", "lo", false, TYPE_INT }, + { "hi", "hi", false, TYPE_INT }, + { "pc", "pc", true, TYPE_CODE_POINTER }, + } + }, + { + "org.gnu.gdb.mips.cp0", + { + { "SR", "status", false, TYPE_INT }, + { "BadA", "badvaddr", false, TYPE_INT }, + { "Cause", "cause", false, TYPE_INT }, + } + }, + { + "org.gnu.gdb.mips.fpu", + { + { "zero", "f0", false, TYPE_INT }, + { "zero", "f1", false, TYPE_INT }, + { "zero", "f2", false, TYPE_INT }, + { "zero", "f3", false, TYPE_INT }, + { "zero", "f4", false, TYPE_INT }, + { "zero", "f5", false, TYPE_INT }, + { "zero", "f6", false, TYPE_INT }, + { "zero", "f7", false, TYPE_INT }, + { "zero", "f8", false, TYPE_INT }, + { "zero", "f9", false, TYPE_INT }, + { "zero", "f10", false, TYPE_INT }, + { "zero", "f11", false, TYPE_INT }, + { "zero", "f12", false, TYPE_INT }, + { "zero", "f13", false, TYPE_INT }, + { "zero", "f14", false, TYPE_INT }, + { "zero", "f15", false, TYPE_INT }, + { "zero", "f16", false, TYPE_INT }, + { "zero", "f17", false, TYPE_INT }, + { "zero", "f18", false, TYPE_INT }, + { "zero", "f19", false, TYPE_INT }, + { "zero", "f20", false, TYPE_INT }, + { "zero", "f21", false, TYPE_INT }, + { "zero", "f22", false, TYPE_INT }, + { "zero", "f23", false, TYPE_INT }, + { "zero", "f24", false, TYPE_INT }, + { "zero", "f25", false, TYPE_INT }, + { "zero", "f26", false, TYPE_INT }, + { "zero", "f27", false, TYPE_INT }, + { "zero", "f28", false, TYPE_INT }, + { "zero", "f29", false, TYPE_INT }, + { "zero", "f30", false, TYPE_INT }, + { "zero", "f31", false, TYPE_INT }, + { "zero", "fcsr", false, TYPE_INT }, + { "zero", "fir" , false, TYPE_INT }, + } + } } }; @@ -291,17 +655,40 @@ static const std::map<std::string, const gdb_register_map &> gdb_register_maps = { "arm7_le", gdb_register_map_arm7 }, { "r4600", gdb_register_map_r4600 }, { "ppc601", gdb_register_map_ppc601 }, + { "m68030", gdb_register_map_m68030 }, { "m68020pmmu", gdb_register_map_m68020pmmu }, + { "m68000", gdb_register_map_m68000 }, { "z80", gdb_register_map_z80 }, + { "z80n", gdb_register_map_z80 }, + { "z84c015", gdb_register_map_z80 }, { "m6502", gdb_register_map_m6502 }, + { "m6507", gdb_register_map_m6502 }, + { "m6510", gdb_register_map_m6502 }, + { "m65ce02", gdb_register_map_m6502 }, + { "rp2a03", gdb_register_map_m6502 }, + { "w65c02", gdb_register_map_m6502 }, + { "w65c02s", gdb_register_map_m6502 }, + { "m6809", gdb_register_map_m6809 }, + { "score7", gdb_register_map_score7 }, + { "nios2", gdb_register_map_nios2 }, + { "cxd8530q", gdb_register_map_psxcpu }, + { "cxd8530aq", gdb_register_map_psxcpu }, + { "cxd8530bq", gdb_register_map_psxcpu }, + { "cxd8530cq", gdb_register_map_psxcpu }, + { "cxd8606q", gdb_register_map_psxcpu }, + { "cxd8606aq", gdb_register_map_psxcpu }, + { "cxd8606bq", gdb_register_map_psxcpu }, + { "cxd8606cq", gdb_register_map_psxcpu }, + { "cxd8661r", gdb_register_map_psxcpu }, }; //------------------------------------------------------------------------- class debug_gdbstub : public osd_module, public debug_module { public: - debug_gdbstub() - : osd_module(OSD_DEBUG_PROVIDER, "gdbstub"), debug_module(), + debug_gdbstub() : + osd_module(OSD_DEBUG_PROVIDER, "gdbstub"), debug_module(), + m_readbuf_state(PACKET_START), m_machine(nullptr), m_maincpu(nullptr), m_state(nullptr), @@ -309,6 +696,7 @@ public: m_address_space(nullptr), m_debugger_cpu(nullptr), m_debugger_console(nullptr), + m_debugger_host(), m_debugger_port(0), m_socket(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE), m_is_be(false), @@ -329,7 +717,7 @@ public: virtual ~debug_gdbstub() { } - virtual int init(const osd_options &options) override; + virtual int init(osd_interface &osd, const osd_options &options) override; virtual void exit() override; virtual void init_debugger(running_machine &machine) override; @@ -346,9 +734,9 @@ public: bool is_thread_id_ok(const char *buf); void handle_character(char ch); - void send_nack(void); - void send_ack(void); - void handle_packet(void); + void send_nack(); + void send_ack(); + void handle_packet(); enum cmd_reply { @@ -374,6 +762,7 @@ public: cmd_reply handle_P(const char *buf); cmd_reply handle_q(const char *buf); cmd_reply handle_s(const char *buf); + cmd_reply handle_T(const char *buf); cmd_reply handle_z(const char *buf); cmd_reply handle_Z(const char *buf); @@ -387,12 +776,12 @@ public: readbuf_state m_readbuf_state; - void generate_target_xml(void); + void generate_target_xml(); - int readchar(void); + int readchar(); - void send_reply(const char *str); - void send_stop_packet(void); + void send_reply(std::string_view str); + void send_stop_packet(); private: running_machine *m_machine; @@ -402,6 +791,7 @@ private: address_space *m_address_space; debugger_cpu *m_debugger_cpu; debugger_console *m_debugger_console; + std::string m_debugger_host; int m_debugger_port; emu_file m_socket; bool m_is_be; @@ -413,6 +803,7 @@ private: struct gdb_register { + std::string gdb_feature_name; std::string gdb_name; int gdb_regnum; gdb_register_type gdb_type; @@ -422,12 +813,11 @@ private: std::vector<gdb_register> m_gdb_registers; std::set<int> m_stop_reply_registers; std::string m_gdb_arch; - std::string m_gdb_feature; std::map<offs_t, uint64_t> m_address_map; - device_debug::breakpoint *m_triggered_breakpoint; - device_debug::watchpoint *m_triggered_watchpoint; + debug_breakpoint *m_triggered_breakpoint; + debug_watchpoint *m_triggered_watchpoint; std::string m_target_xml; @@ -442,14 +832,15 @@ private: }; //------------------------------------------------------------------------- -int debug_gdbstub::init(const osd_options &options) +int debug_gdbstub::init(osd_interface &osd, const osd_options &options) { + m_debugger_host = options.debugger_host(); m_debugger_port = options.debugger_port(); return 0; } //------------------------------------------------------------------------- -void debug_gdbstub::exit(void) +void debug_gdbstub::exit() { } @@ -460,7 +851,7 @@ void debug_gdbstub::init_debugger(running_machine &machine) } //------------------------------------------------------------------------- -int debug_gdbstub::readchar(void) +int debug_gdbstub::readchar() { // NOTE: we don't use m_socket.getc() because it does not work with // sockets (it assumes seeking is possible). @@ -480,11 +871,11 @@ int debug_gdbstub::readchar(void) } //------------------------------------------------------------------------- -static std::string escape_packet(const std::string src) +static std::string escape_packet(std::string_view src) { std::string result; result.reserve(src.length()); - for ( char ch: src ) + for ( char ch : src ) { if ( ch == '#' || ch == '$' || ch == '}' ) { @@ -497,7 +888,7 @@ static std::string escape_packet(const std::string src) } //------------------------------------------------------------------------- -void debug_gdbstub::generate_target_xml(void) +void debug_gdbstub::generate_target_xml() { // Note: we do not attempt to replicate the regnum values from old // GDB clients that did not support target.xml. @@ -505,11 +896,23 @@ void debug_gdbstub::generate_target_xml(void) target_xml += "<?xml version=\"1.0\"?>\n"; target_xml += "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n"; target_xml += "<target version=\"1.0\">\n"; - target_xml += string_format("<architecture>%s</architecture>\n", m_gdb_arch.c_str()); - target_xml += string_format(" <feature name=\"%s\">\n", m_gdb_feature.c_str()); + target_xml += string_format("<architecture>%s</architecture>\n", m_gdb_arch); + std::string feature_name; for ( const auto ®: m_gdb_registers ) - target_xml += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name.c_str(), reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]); - target_xml += " </feature>\n"; + { + if (feature_name != reg.gdb_feature_name) + { + if (!feature_name.empty()) + target_xml += " </feature>\n"; + + feature_name = reg.gdb_feature_name; + target_xml += string_format(" <feature name=\"%s\">\n", feature_name); + } + + target_xml += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name, reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]); + } + if (!feature_name.empty()) + target_xml += " </feature>\n"; target_xml += "</target>\n"; m_target_xml = escape_packet(target_xml); } @@ -522,13 +925,18 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) if ( firststop && !m_initialized ) { - m_maincpu = m_machine->root_device().subdevice(":maincpu"); + // find the "main" CPU, which is the first CPU (gdbstub doesn't have any notion of switching CPUs) + m_maincpu = device_interface_enumerator<cpu_device>(m_machine->root_device()).first(); + if (!m_maincpu) + fatalerror("gdbstub: cannot find any CPUs\n"); + const char *cpuname = m_maincpu->shortname(); auto it = gdb_register_maps.find(cpuname); if ( it == gdb_register_maps.end() ) fatalerror("gdbstub: cpuname %s not found in gdb stub descriptions\n", cpuname); - m_state = &m_maincpu->state(); + m_maincpu->interface(m_state); + assert(m_state != nullptr); m_memory = &m_maincpu->memory(); m_address_space = &m_memory->space(AS_PROGRAM); m_debugger_cpu = &m_machine->debugger().cpu(); @@ -544,59 +952,60 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) uint64_t datamask = entry->datamask(); int index = entry->index(); const std::string &format_string = entry->format_string(); - osd_printf_info("[%3d] datasize %d mask %016" PRIx64 " [%s] [%s]\n", index, datasize, datamask, symbol, format_string.c_str()); + osd_printf_info("[%3d] datasize %d mask %016" PRIx64 " [%s] [%s]\n", index, datasize, datamask, symbol, format_string); } #endif const gdb_register_map ®ister_map = it->second; m_gdb_arch = register_map.arch; - m_gdb_feature = register_map.feature; int cur_gdb_regnum = 0; - for ( const auto ®: register_map.registers ) - { - bool added = false; - for ( const auto &entry: m_state->state_entries() ) + for ( const auto &feature: register_map.features ) + for ( const auto ®: feature.registers ) { - const char *symbol = entry->symbol(); - if ( strcmp(symbol, reg.state_name) == 0 ) + bool added = false; + for ( const auto &entry: m_state->state_entries() ) { - gdb_register new_reg; - new_reg.gdb_name = reg.gdb_name; - new_reg.gdb_regnum = cur_gdb_regnum; - new_reg.gdb_type = reg.gdb_type; - if ( reg.override_bitsize != -1 ) - new_reg.gdb_bitsize = reg.override_bitsize; - else - new_reg.gdb_bitsize = entry->datasize() * 8; - new_reg.state_index = entry->index(); - m_gdb_registers.push_back(std::move(new_reg)); - if ( reg.stop_packet ) - m_stop_reply_registers.insert(cur_gdb_regnum); - added = true; - cur_gdb_regnum++; - break; + const char *symbol = entry->symbol(); + if ( strcmp(symbol, reg.state_name) == 0 ) + { + gdb_register new_reg; + new_reg.gdb_feature_name = feature.feature_name; + new_reg.gdb_name = reg.gdb_name; + new_reg.gdb_regnum = cur_gdb_regnum; + new_reg.gdb_type = reg.gdb_type; + if ( reg.override_bitsize != -1 ) + new_reg.gdb_bitsize = reg.override_bitsize; + else + new_reg.gdb_bitsize = entry->datasize() * 8; + new_reg.state_index = entry->index(); + m_gdb_registers.push_back(std::move(new_reg)); + if ( reg.stop_packet ) + m_stop_reply_registers.insert(cur_gdb_regnum); + added = true; + cur_gdb_regnum++; + break; + } } + if ( !added ) + osd_printf_info("gdbstub: could not find register [%s]\n", reg.gdb_name); } - if ( !added ) - osd_printf_info("gdbstub: could not find register [%s]\n", reg.gdb_name); - } #if 0 for ( const auto ®: m_gdb_registers ) - osd_printf_info(" %3d (%d) %d %d [%s]\n", reg.gdb_regnum, reg.state_index, reg.gdb_bitsize, reg.gdb_type, reg.gdb_name.c_str()); + osd_printf_info(" %3d (%d) %d %d [%s]\n", reg.gdb_regnum, reg.state_index, reg.gdb_bitsize, reg.gdb_type, reg.gdb_name); #endif - std::string socket_name = string_format("socket.localhost:%d", m_debugger_port); - osd_file::error filerr = m_socket.open(socket_name.c_str()); - if ( filerr != osd_file::error::NONE ) - fatalerror("gdbstub: failed to start listening on port %d\n", m_debugger_port); - osd_printf_info("gdbstub: listening on port %d\n", m_debugger_port); + std::string socket_name = string_format("socket.%s:%d", m_debugger_host, m_debugger_port); + std::error_condition const filerr = m_socket.open(socket_name); + if ( filerr ) + fatalerror("gdbstub: failed to start listening on address %s port %d\n", m_debugger_host, m_debugger_port); + osd_printf_info("gdbstub: listening on address %s port %d\n", m_debugger_host, m_debugger_port); m_initialized = true; } else { - device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug(); + device_debug *debug = m_debugger_console->get_visible_cpu()->debug(); m_triggered_watchpoint = debug->triggered_watchpoint(); m_triggered_breakpoint = debug->triggered_breakpoint(); if ( m_send_stop_packet ) @@ -622,7 +1031,7 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) } //------------------------------------------------------------------------- -void debug_gdbstub::debugger_update(void) +void debug_gdbstub::debugger_update() { while ( true ) { @@ -634,28 +1043,26 @@ void debug_gdbstub::debugger_update(void) } //------------------------------------------------------------------------- -void debug_gdbstub::send_nack(void) +void debug_gdbstub::send_nack() { - m_socket.puts("-"); + m_socket.write("-", 1); } //------------------------------------------------------------------------- -void debug_gdbstub::send_ack(void) +void debug_gdbstub::send_ack() { - m_socket.puts("+"); + m_socket.write("+", 1); } //------------------------------------------------------------------------- -void debug_gdbstub::send_reply(const char *str) +void debug_gdbstub::send_reply(std::string_view str) { - size_t length = strlen(str); - uint8_t checksum = 0; - for ( size_t i = 0; i < length; i++ ) - checksum += str[i]; + for ( char ch : str ) + checksum += ch; std::string reply = string_format("$%s#%02x", str, checksum); - m_socket.puts(reply.c_str()); + m_socket.write(reply.c_str(), reply.length()); } @@ -683,7 +1090,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_c(const char *buf) if ( *buf != '\0' ) return REPLY_UNSUPPORTED; - m_debugger_cpu->get_visible_cpu()->debug()->go(); + m_debugger_console->get_visible_cpu()->debug()->go(); m_send_stop_packet = true; return REPLY_NONE; } @@ -696,7 +1103,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_D(const char *buf) if ( *buf != '\0' ) return REPLY_UNSUPPORTED; - m_debugger_cpu->get_visible_cpu()->debug()->go(); + m_debugger_console->get_visible_cpu()->debug()->go(); m_dettached = true; return REPLY_OK; @@ -713,7 +1120,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_g(const char *buf) std::string reply; for ( const auto ®: m_gdb_registers ) reply += get_register_string(reg.gdb_regnum); - send_reply(reply.c_str()); + send_reply(reply); return REPLY_NONE; } @@ -752,7 +1159,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_H(const char *buf) debug_gdbstub::cmd_reply debug_gdbstub::handle_k(const char *buf) { m_machine->schedule_exit(); - m_debugger_cpu->get_visible_cpu()->debug()->go(); + m_debugger_console->get_visible_cpu()->debug()->go(); m_dettached = true; m_socket.close(); return REPLY_NONE; @@ -768,7 +1175,8 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_m(const char *buf) return REPLY_ENN; offs_t offset = address; - if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) ) + address_space *tspace; + if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) ) return REPLY_ENN; // Disable side effects while reading memory. @@ -778,10 +1186,10 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_m(const char *buf) reply.reserve(length * 2); for ( int i = 0; i < length; i++ ) { - uint8_t value = m_address_space->read_byte(offset + i); + uint8_t value = tspace->read_byte(offset + i); reply += string_format("%02x", value); } - send_reply(reply.c_str()); + send_reply(reply); return REPLY_NONE; } @@ -813,7 +1221,8 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_M(const char *buf) return REPLY_ENN; offs_t offset = address; - if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) ) + address_space *tspace; + if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) ) return REPLY_ENN; std::vector<uint8_t> data; @@ -821,7 +1230,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_M(const char *buf) return REPLY_ENN; for ( int i = 0; i < length; i++ ) - m_address_space->write_byte(offset + i, data[i]); + tspace->write_byte(offset + i, data[i]); return REPLY_OK; } @@ -836,7 +1245,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_p(const char *buf) if ( sscanf(buf, "%x", &gdb_regnum) != 1 || gdb_regnum >= m_gdb_registers.size() ) return REPLY_ENN; std::string reply = get_register_string(gdb_regnum); - send_reply(reply.c_str()); + send_reply(reply); return REPLY_NONE; } @@ -888,7 +1297,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf) if ( !hex_decode(&data, buf, strlen(buf) / 2) ) return REPLY_ENN; std::string command(data.begin(), data.end()); - text_buffer *textbuf = m_debugger_console->get_console_textbuf(); + text_buffer &textbuf = m_debugger_console->get_console_textbuf(); text_buffer_clear(textbuf); m_debugger_console->execute_command(command, false); uint32_t nlines = text_buffer_num_lines(textbuf); @@ -903,7 +1312,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf) reply += string_format("%02x", *line++); reply += "0A"; } - send_reply(reply.c_str()); + send_reply(reply); return REPLY_NONE; } @@ -920,7 +1329,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf) { std::string reply = string_format("PacketSize=%x", MAX_PACKET_SIZE); reply += ";qXfer:features:read+"; - send_reply(reply.c_str()); + send_reply(reply); return REPLY_NONE; } else if ( name == "Xfer" ) @@ -941,7 +1350,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf) else reply += 'l'; reply += m_target_xml.substr(offset, length); - send_reply(reply.c_str()); + send_reply(reply); m_target_xml_sent = true; return REPLY_NONE; } @@ -969,15 +1378,26 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_s(const char *buf) if ( *buf != '\0' ) return REPLY_UNSUPPORTED; - m_debugger_cpu->get_visible_cpu()->debug()->single_step(); + m_debugger_console->get_visible_cpu()->debug()->single_step(); m_send_stop_packet = true; return REPLY_NONE; } //------------------------------------------------------------------------- +// Find out if the thread XX is alive. +debug_gdbstub::cmd_reply debug_gdbstub::handle_T(const char *buf) +{ + if ( is_thread_id_ok(buf) ) + return REPLY_OK; + + // thread is dead + return REPLY_ENN; +} + +//------------------------------------------------------------------------- static bool remove_breakpoint(device_debug *debug, uint64_t address, int /*kind*/) { - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); if (bp != nullptr) return debug->breakpoint_clear(bp->index()); return false; @@ -1014,14 +1434,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_z(const char *buf) // watchpoints offs_t offset = address; + address_space *tspace; if ( type == 2 || type == 3 || type == 4 ) { - if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) ) + if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) ) return REPLY_ENN; m_address_map.erase(offset); } - device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug(); + device_debug *debug = m_debugger_console->get_visible_cpu()->debug(); switch ( type ) { // Note: software and hardware breakpoints are treated both the @@ -1055,14 +1476,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf) // watchpoints offs_t offset = address; + address_space *tspace; if ( type == 2 || type == 3 || type == 4 ) { - if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) ) + if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) ) return REPLY_ENN; m_address_map[offset] = address; } - device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug(); + device_debug *debug = m_debugger_console->get_visible_cpu()->debug(); switch ( type ) { // Note: software and hardware breakpoints are treated both the @@ -1073,15 +1495,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf) return REPLY_OK; case 2: // write watchpoint - debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind, nullptr, nullptr); + debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind); return REPLY_OK; case 3: // read watchpoint - debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind, nullptr, nullptr); + debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind); return REPLY_OK; case 4: // access watchpoint - debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind, nullptr, nullptr); + debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind); return REPLY_OK; } @@ -1090,7 +1512,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf) //------------------------------------------------------------------------- -void debug_gdbstub::send_stop_packet(void) +void debug_gdbstub::send_stop_packet() { int signal = 5; // GDB_SIGNAL_TRAP std::string reply = string_format("T%02x", signal); @@ -1115,11 +1537,11 @@ void debug_gdbstub::send_stop_packet(void) if ( m_target_xml_sent ) for ( const auto &gdb_regnum: m_stop_reply_registers ) reply += string_format("%02x:%s;", gdb_regnum, get_register_string(gdb_regnum)); - send_reply(reply.c_str()); + send_reply(reply); } //------------------------------------------------------------------------- -void debug_gdbstub::handle_packet(void) +void debug_gdbstub::handle_packet() { // For any command not supported by the stub, an empty response // (‘$#00’) should be returned. That way it is possible to extend @@ -1144,6 +1566,7 @@ void debug_gdbstub::handle_packet(void) case 'P': reply = handle_P(buf); break; case 'q': reply = handle_q(buf); break; case 's': reply = handle_s(buf); break; + case 'T': reply = handle_T(buf); break; case 'z': reply = handle_z(buf); break; case 'Z': reply = handle_Z(buf); break; } @@ -1156,22 +1579,6 @@ void debug_gdbstub::handle_packet(void) } //------------------------------------------------------------------------- -#define BYTESWAP_64(x) ((((x) << 56) & 0xFF00000000000000) \ - | (((x) << 40) & 0x00FF000000000000) \ - | (((x) << 24) & 0x0000FF0000000000) \ - | (((x) << 8) & 0x000000FF00000000) \ - | (((x) >> 8) & 0x00000000FF000000) \ - | (((x) >> 24) & 0x0000000000FF0000) \ - | (((x) >> 40) & 0x000000000000FF00) \ - | (((x) >> 56) & 0x00000000000000FF)) -#define BYTESWAP_32(x) ((((x) << 24) & 0xFF000000) \ - | (((x) << 8) & 0x00FF0000) \ - | (((x) >> 8) & 0x0000FF00) \ - | (((x) >> 24) & 0x000000FF)) -#define BYTESWAP_16(x) ((((x) << 8) & 0xFF00) \ - | (((x) >> 8) & 0x00FF)) - -//------------------------------------------------------------------------- std::string debug_gdbstub::get_register_string(int gdb_regnum) { const gdb_register ® = m_gdb_registers[gdb_regnum]; @@ -1184,9 +1591,9 @@ std::string debug_gdbstub::get_register_string(int gdb_regnum) value &= (1ULL << reg.gdb_bitsize) - 1; if ( !m_is_be ) { - value = (reg.gdb_bitsize == 64) ? BYTESWAP_64(value) - : (reg.gdb_bitsize == 32) ? BYTESWAP_32(value) - : (reg.gdb_bitsize == 16) ? BYTESWAP_16(value) + value = (reg.gdb_bitsize == 64) ? swapendian_int64(value) + : (reg.gdb_bitsize == 32) ? swapendian_int32(value) + : (reg.gdb_bitsize == 16) ? swapendian_int16(value) : value; } return string_format(fmt, value); @@ -1205,9 +1612,9 @@ bool debug_gdbstub::parse_register_string(uint64_t *pvalue, const char *buf, int return false; if ( !m_is_be ) { - value = (reg.gdb_bitsize == 64) ? BYTESWAP_64(value) - : (reg.gdb_bitsize == 32) ? BYTESWAP_32(value) - : (reg.gdb_bitsize == 16) ? BYTESWAP_16(value) + value = (reg.gdb_bitsize == 64) ? swapendian_int64(value) + : (reg.gdb_bitsize == 32) ? swapendian_int32(value) + : (reg.gdb_bitsize == 16) ? swapendian_int16(value) : value; } *pvalue = value; @@ -1304,5 +1711,9 @@ void debug_gdbstub::handle_character(char ch) } } +} // anonymous namespace + +} // namespace osd + //------------------------------------------------------------------------- -MODULE_DEFINITION(DEBUG_GDBSTUB, debug_gdbstub) +MODULE_DEFINITION(DEBUG_GDBSTUB, osd::debug_gdbstub) diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp index 39dcb3310cf..e027cb5339c 100644 --- a/src/osd/modules/debugger/debugimgui.cpp +++ b/src/osd/modules/debugger/debugimgui.cpp @@ -3,9 +3,11 @@ // ImGui based debugger #include "emu.h" +#include "debug_module.h" + #include "imgui/imgui.h" -#include "render.h" -#include "uiinput.h" + +#include "imagedev/floppy.h" #include "debug/debugvw.h" #include "debug/dvdisasm.h" @@ -14,30 +16,37 @@ #include "debug/dvwpoints.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debugger.h" +#include "render.h" +#include "ui/uimain.h" +#include "uiinput.h" + +#include "formats/flopimg.h" #include "config.h" -#include "debugger.h" #include "modules/lib/osdobj_common.h" -#include "debug_module.h" #include "modules/osdmodule.h" #include "zippath.h" -#include "imagedev/floppy.h" + +namespace osd { + +namespace { class debug_area { DISABLE_COPYING(debug_area); public: - debug_area(running_machine &machine, debug_view_type type) - : next(nullptr), - type(0), - ofs_x(0), - ofs_y(0), - is_collapsed(false), - exec_cmd(false), - scroll_end(false), - scroll_follow(false) - { + debug_area(running_machine &machine, debug_view_type type) : + next(nullptr), + type(0), + ofs_x(0), + ofs_y(0), + is_collapsed(false), + exec_cmd(false), + scroll_end(false), + scroll_follow(false) + { this->view = machine.debug_view().alloc_view(type, nullptr, this); this->type = type; this->m_machine = &machine; @@ -55,7 +64,7 @@ public: default: break; } - } + } ~debug_area() { //this->target->debug_free(*this->container); @@ -64,7 +73,7 @@ public: running_machine &machine() const { assert(m_machine != nullptr); return *m_machine; } - debug_area * next; + debug_area * next; int type; debug_view * view; @@ -91,9 +100,11 @@ public: class debug_imgui : public osd_module, public debug_module { public: - debug_imgui() - : osd_module(OSD_DEBUG_PROVIDER, "imgui"), debug_module(), + debug_imgui() : + osd_module(OSD_DEBUG_PROVIDER, "imgui"), debug_module(), m_machine(nullptr), + m_take_ui(false), + m_current_pointer(-1), m_mouse_x(0), m_mouse_y(0), m_mouse_button(false), @@ -118,7 +129,7 @@ public: virtual ~debug_imgui() { } - virtual int init(const osd_options &options) override { return 0; } + virtual int init(osd_interface &osd, const osd_options &options) override { return 0; } virtual void exit() override {}; virtual void init_debugger(running_machine &machine) override; @@ -142,14 +153,13 @@ private: struct image_type_entry { - floppy_image_format_t* format; + const floppy_image_format_t* format; std::string shortname; std::string longname; }; - void handle_mouse(); + void handle_events(); void handle_mouse_views(); - void handle_keys(); void handle_keys_views(); void handle_console(running_machine* machine); void update(); @@ -172,19 +182,21 @@ private: void refresh_filelist(); void refresh_typelist(); void update_cpu_view(device_t* device); - static bool get_view_source(void* data, int idx, const char** out_text); + static const char* get_view_source(void* data, int idx); static int history_set(ImGuiInputTextCallbackData* data); running_machine* m_machine; - int32_t m_mouse_x; - int32_t m_mouse_y; + bool m_take_ui; + int32_t m_current_pointer; + int32_t m_mouse_x; + int32_t m_mouse_y; bool m_mouse_button; bool m_prev_mouse_button; bool m_running; const char* font_name; float font_size; ImVec2 m_text_size; // size of character (assumes monospaced font is in use) - uint8_t m_key_char; + uint8_t m_key_char; bool m_hide; int m_win_count; // number of active windows, does not decrease, used to ID individual windows bool m_has_images; // true if current system has any image devices @@ -199,6 +211,7 @@ private: file_entry* m_selected_file; int m_format_sel; char m_path[1024]; // path text field buffer + std::unordered_map<input_item_id,ImGuiKey> m_mapping; }; // globals @@ -225,11 +238,7 @@ static void view_list_remove(debug_area* item) static debug_area *dview_alloc(running_machine &machine, debug_view_type type) { - debug_area *dv; - - dv = global_alloc(debug_area(machine, type)); - - return dv; + return new debug_area(machine, type); } static inline void map_attr_to_fg_bg(unsigned char attr, rgb_t *fg, rgb_t *bg) @@ -259,107 +268,92 @@ static inline void map_attr_to_fg_bg(unsigned char attr, rgb_t *fg, rgb_t *bg) } } -bool debug_imgui::get_view_source(void* data, int idx, const char** out_text) -{ - debug_view* vw = static_cast<debug_view*>(data); - *out_text = vw->source_list().find(idx)->name(); - return true; -} - -void debug_imgui::handle_mouse() +const char* debug_imgui::get_view_source(void* data, int idx) { - m_prev_mouse_button = m_mouse_button; - m_machine->ui_input().find_mouse(&m_mouse_x, &m_mouse_y, &m_mouse_button); + auto* vw = static_cast<debug_view*>(data); + return vw->source(idx)->name(); } -void debug_imgui::handle_mouse_views() -{ - rectangle rect; - bool clicked = false; - if(m_mouse_button == true && m_prev_mouse_button == false) - clicked = true; - - // check all views, and pass mouse clicks to them - if(!m_mouse_button) - return; - rect.min_x = view_main_disasm->ofs_x; - rect.min_y = view_main_disasm->ofs_y; - rect.max_x = view_main_disasm->ofs_x + view_main_disasm->view_width; - rect.max_y = view_main_disasm->ofs_y + view_main_disasm->view_height; - if(rect.contains(m_mouse_x,m_mouse_y) && clicked && view_main_disasm->has_focus) - { - debug_view_xy topleft = view_main_disasm->view->visible_position(); - debug_view_xy newpos; - newpos.x = topleft.x + (m_mouse_x-view_main_disasm->ofs_x) / m_text_size.x; - newpos.y = topleft.y + (m_mouse_y-view_main_disasm->ofs_y) / m_text_size.y; - view_main_disasm->view->set_cursor_position(newpos); - view_main_disasm->view->set_cursor_visible(true); - } - for(std::vector<debug_area*>::iterator it = view_list.begin();it != view_list.end();++it) - { - rect.min_x = (*it)->ofs_x; - rect.min_y = (*it)->ofs_y; - rect.max_x = (*it)->ofs_x + (*it)->view_width; - rect.max_y = (*it)->ofs_y + (*it)->view_height; - if(rect.contains(m_mouse_x,m_mouse_y) && clicked && (*it)->has_focus) - { - if((*it)->view->cursor_supported()) - { - debug_view_xy topleft = (*it)->view->visible_position(); - debug_view_xy newpos; - newpos.x = topleft.x + (m_mouse_x-(*it)->ofs_x) / m_text_size.x; - newpos.y = topleft.y + (m_mouse_y-(*it)->ofs_y) / m_text_size.y; - (*it)->view->set_cursor_position(newpos); - (*it)->view->set_cursor_visible(true); - } - } - } -} - -void debug_imgui::handle_keys() +void debug_imgui::handle_events() { ImGuiIO& io = ImGui::GetIO(); - ui_event event; - debug_area* focus_view = nullptr; // find view that has focus (should only be one at a time) - for(std::vector<debug_area*>::iterator view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) + debug_area* focus_view = nullptr; + for(auto view_ptr = view_list.begin();view_ptr != view_list.end(); ++view_ptr) if((*view_ptr)->has_focus) focus_view = *view_ptr; // check views in main views also (only the disassembler view accepts inputs) - if(view_main_disasm->has_focus) - focus_view = view_main_disasm; + if(view_main_disasm) + if(view_main_disasm->has_focus) + focus_view = view_main_disasm; - if(m_machine->input().code_pressed(KEYCODE_LCONTROL)) - io.KeyCtrl = true; - else - io.KeyCtrl = false; - if(m_machine->input().code_pressed(KEYCODE_LSHIFT)) - io.KeyShift = true; - else - io.KeyShift = false; - if(m_machine->input().code_pressed(KEYCODE_LALT)) - io.KeyAlt = true; - else - io.KeyAlt = false; + io.KeyCtrl = m_machine->input().code_pressed(KEYCODE_LCONTROL); + io.KeyShift = m_machine->input().code_pressed(KEYCODE_LSHIFT); + io.KeyAlt = m_machine->input().code_pressed(KEYCODE_LALT); for(input_item_id id = ITEM_ID_A; id <= ITEM_ID_CANCEL; ++id) { if(m_machine->input().code_pressed(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id))) - io.KeysDown[id] = true; + { + if(m_mapping.count(id)) + io.AddKeyEvent(m_mapping[id], true); + } else - io.KeysDown[id] = false; + { + if(m_mapping.count(id)) + io.AddKeyEvent(m_mapping[id], false); + } } + m_prev_mouse_button = m_mouse_button; m_key_char = 0; - while (m_machine->ui_input().pop_event(&event)) + ui_event event; + while(m_machine->ui_input().pop_event(&event)) { switch (event.event_type) { - case ui_event::IME_CHAR: - m_key_char = event.ch; - if(focus_view != nullptr) + case ui_event::type::POINTER_UPDATE: + if(&m_machine->render().ui_target() != event.target) + break; + if(event.pointer_id != m_current_pointer) + { + if((0 > m_current_pointer) || ((event.pointer_pressed & 1) && !m_mouse_button)) + m_current_pointer = event.pointer_id; + } + if(event.pointer_id == m_current_pointer) + { + bool changed = (m_mouse_x != event.pointer_x) || (m_mouse_y != event.pointer_y) || (m_mouse_button != bool(event.pointer_buttons & 1)); + m_mouse_x = event.pointer_x; + m_mouse_y = event.pointer_y; + m_mouse_button = bool(event.pointer_buttons & 1); + if(changed) + { + io.MousePos = ImVec2(m_mouse_x,m_mouse_y); + io.MouseDown[0] = m_mouse_button; + } + } + break; + case ui_event::type::POINTER_LEAVE: + case ui_event::type::POINTER_ABORT: + if((&m_machine->render().ui_target() == event.target) && (event.pointer_id == m_current_pointer)) + { + m_current_pointer = -1; + bool changed = (m_mouse_x != event.pointer_x) || (m_mouse_y != event.pointer_y) || m_mouse_button; + m_mouse_x = event.pointer_x; + m_mouse_y = event.pointer_y; + m_mouse_button = false; + if(changed) + { + io.MousePos = ImVec2(m_mouse_x,m_mouse_y); + io.MouseDown[0] = m_mouse_button; + } + } + break; + case ui_event::type::IME_CHAR: + m_key_char = event.ch; // FIXME: assigning 4-byte UCS4 character to 8-bit variable + if(focus_view) focus_view->view->process_char(m_key_char); return; default: @@ -368,108 +362,153 @@ void debug_imgui::handle_keys() } // global keys - if(ImGui::IsKeyPressed(ITEM_ID_F3,false)) + if(ImGui::IsKeyPressed(ImGuiKey_F3,false)) { - if(ImGui::IsKeyDown(ITEM_ID_LSHIFT)) + if(ImGui::IsKeyDown(ImGuiKey_LeftShift)) m_machine->schedule_hard_reset(); else { m_machine->schedule_soft_reset(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); } } - if(ImGui::IsKeyPressed(ITEM_ID_F5,false)) + if(ImGui::IsKeyPressed(ImGuiKey_F5,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_running = true; } - if(ImGui::IsKeyPressed(ITEM_ID_F6,false)) + if(ImGui::IsKeyPressed(ImGuiKey_F6,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); m_running = true; } - if(ImGui::IsKeyPressed(ITEM_ID_F7,false)) + if(ImGui::IsKeyPressed(ImGuiKey_F7,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); m_running = true; } - if(ImGui::IsKeyPressed(ITEM_ID_F8,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); - if(ImGui::IsKeyPressed(ITEM_ID_F9,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); - if(ImGui::IsKeyPressed(ITEM_ID_F10,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); - if(ImGui::IsKeyPressed(ITEM_ID_F11,false)) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); - if(ImGui::IsKeyPressed(ITEM_ID_F12,false)) + if(ImGui::IsKeyPressed(ImGuiKey_F8,false)) + m_machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); + if(ImGui::IsKeyPressed(ImGuiKey_F9,false)) + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); + if(ImGui::IsKeyPressed(ImGuiKey_F10,false)) + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); + if(ImGui::IsKeyPressed(ImGuiKey_F11,false)) + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); + if(ImGui::IsKeyPressed(ImGuiKey_F12,false)) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_hide = true; } - if(ImGui::IsKeyPressed(ITEM_ID_D,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyPressed(ImGuiKey_D,false) && io.KeyCtrl) add_disasm(++m_win_count); - if(ImGui::IsKeyPressed(ITEM_ID_M,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyPressed(ImGuiKey_M,false) && io.KeyCtrl) add_memory(++m_win_count); - if(ImGui::IsKeyPressed(ITEM_ID_B,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyPressed(ImGuiKey_B,false) && io.KeyCtrl) add_bpoints(++m_win_count); - if(ImGui::IsKeyPressed(ITEM_ID_W,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyPressed(ImGuiKey_W,false) && io.KeyCtrl) add_wpoints(++m_win_count); - if(ImGui::IsKeyPressed(ITEM_ID_L,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyPressed(ImGuiKey_L,false) && io.KeyCtrl) add_log(++m_win_count); } +void debug_imgui::handle_mouse_views() +{ + rectangle rect; + bool clicked = false; + if(m_mouse_button == true && m_prev_mouse_button == false) + clicked = true; + + // check all views, and pass mouse clicks to them + if(!m_mouse_button) + return; + rect.min_x = view_main_disasm->ofs_x; + rect.min_y = view_main_disasm->ofs_y; + rect.max_x = view_main_disasm->ofs_x + view_main_disasm->view_width; + rect.max_y = view_main_disasm->ofs_y + view_main_disasm->view_height; + if(rect.contains(m_mouse_x,m_mouse_y) && clicked && view_main_disasm->has_focus) + { + debug_view_xy topleft = view_main_disasm->view->visible_position(); + debug_view_xy newpos; + newpos.x = topleft.x + (m_mouse_x-view_main_disasm->ofs_x) / m_text_size.x; + newpos.y = topleft.y + (m_mouse_y-view_main_disasm->ofs_y) / m_text_size.y; + view_main_disasm->view->set_cursor_position(newpos); + view_main_disasm->view->set_cursor_visible(true); + } + for(auto it = view_list.begin();it != view_list.end();++it) + { + rect.min_x = (*it)->ofs_x; + rect.min_y = (*it)->ofs_y; + rect.max_x = (*it)->ofs_x + (*it)->view_width; + rect.max_y = (*it)->ofs_y + (*it)->view_height; + if(rect.contains(m_mouse_x,m_mouse_y) && clicked && (*it)->has_focus) + { + if((*it)->view->cursor_supported()) + { + debug_view_xy topleft = (*it)->view->visible_position(); + debug_view_xy newpos; + newpos.x = topleft.x + (m_mouse_x-(*it)->ofs_x) / m_text_size.x; + newpos.y = topleft.y + (m_mouse_y-(*it)->ofs_y) / m_text_size.y; + (*it)->view->set_cursor_position(newpos); + (*it)->view->set_cursor_visible(true); + } + } + } +} + void debug_imgui::handle_keys_views() { debug_area* focus_view = nullptr; // find view that has focus (should only be one at a time) - for(std::vector<debug_area*>::iterator view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) + for(auto view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) if((*view_ptr)->has_focus) focus_view = *view_ptr; // check views in main views also (only the disassembler view accepts inputs) - if(view_main_disasm->has_focus) - focus_view = view_main_disasm; + if(view_main_disasm != nullptr) + if(view_main_disasm->has_focus) + focus_view = view_main_disasm; // if no view has focus, then there's nothing to do if(focus_view == nullptr) return; // pass keypresses to debug view with focus - if(ImGui::IsKeyPressed(ITEM_ID_UP)) + if(ImGui::IsKeyPressed(ImGuiKey_UpArrow)) focus_view->view->process_char(DCH_UP); - if(ImGui::IsKeyPressed(ITEM_ID_DOWN)) + if(ImGui::IsKeyPressed(ImGuiKey_DownArrow)) focus_view->view->process_char(DCH_DOWN); - if(ImGui::IsKeyPressed(ITEM_ID_LEFT)) + if(ImGui::IsKeyPressed(ImGuiKey_LeftArrow)) { - if(ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) focus_view->view->process_char(DCH_CTRLLEFT); else focus_view->view->process_char(DCH_LEFT); } - if(ImGui::IsKeyPressed(ITEM_ID_RIGHT)) + if(ImGui::IsKeyPressed(ImGuiKey_RightArrow)) { - if(ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) focus_view->view->process_char(DCH_CTRLRIGHT); else focus_view->view->process_char(DCH_RIGHT); } - if(ImGui::IsKeyPressed(ITEM_ID_PGUP)) + if(ImGui::IsKeyPressed(ImGuiKey_PageUp)) focus_view->view->process_char(DCH_PUP); - if(ImGui::IsKeyPressed(ITEM_ID_PGDN)) + if(ImGui::IsKeyPressed(ImGuiKey_PageDown)) focus_view->view->process_char(DCH_PDOWN); - if(ImGui::IsKeyPressed(ITEM_ID_HOME)) + if(ImGui::IsKeyPressed(ImGuiKey_Home)) { - if(ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) focus_view->view->process_char(DCH_CTRLHOME); else focus_view->view->process_char(DCH_HOME); } - if(ImGui::IsKeyPressed(ITEM_ID_END)) + if(ImGui::IsKeyPressed(ImGuiKey_End)) { - if(ImGui::IsKeyDown(ITEM_ID_LCONTROL)) + if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) focus_view->view->process_char(DCH_CTRLEND); else focus_view->view->process_char(DCH_END); @@ -484,7 +523,7 @@ void debug_imgui::handle_console(running_machine* machine) // if console input is empty, then do a single step if(strlen(view_main_console->console_input) == 0) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); view_main_console->exec_cmd = false; history_pos = view_main_console->console_history.size(); return; @@ -522,7 +561,7 @@ void debug_imgui::handle_console(running_machine* machine) // don't bother adding to history if the current command matches the previous one if(view_main_console->console_prev != view_main_console->console_input) { - view_main_console->console_history.push_back(std::string(view_main_console->console_input)); + view_main_console->console_history.emplace_back(std::string(view_main_console->console_input)); view_main_console->console_prev = view_main_console->console_input; } history_pos = view_main_console->console_history.size(); @@ -546,6 +585,8 @@ int debug_imgui::history_set(ImGuiInputTextCallbackData* data) if(history_pos < view_main_console->console_history.size()) history_pos++; break; + default: + break; } if(history_pos == view_main_console->console_history.size()) @@ -605,7 +646,10 @@ void debug_imgui::draw_view(debug_area* view_ptr, bool exp_change) // temporarily set cursor to the last line, this will set the scroll bar range if(view_ptr->type != DVT_MEMORY) // no scroll bars in memory views + { ImGui::SetCursorPosY((totalsize.y) * fsize.y); + ImGui::Dummy(ImVec2(0,0)); // some object is required for validation + } // set the visible area to be displayed vsize.x = view_ptr->view_width / fsize.x; @@ -754,13 +798,9 @@ void debug_imgui::add_log(int id) void debug_imgui::draw_disasm(debug_area* view_ptr, bool* opened) { - const debug_view_source* src; - ImGui::SetNextWindowSize(ImVec2(view_ptr->width,view_ptr->height + ImGui::GetTextLineHeight()),ImGuiCond_Once); if(ImGui::Begin(view_ptr->title.c_str(),opened,ImGuiWindowFlags_MenuBar)) { - int idx; - bool done = false; bool exp_change = false; view_ptr->is_collapsed = false; @@ -768,7 +808,7 @@ void debug_imgui::draw_disasm(debug_area* view_ptr, bool* opened) { if(ImGui::BeginMenu("Options")) { - debug_view_disasm* disasm = downcast<debug_view_disasm*>(view_ptr->view); + auto* disasm = downcast<debug_view_disasm*>(view_ptr->view); int rightcol = disasm->right_column(); if(ImGui::MenuItem("Raw opcodes", nullptr,(rightcol == DASM_RIGHTCOL_RAW) ? true : false)) @@ -788,7 +828,7 @@ void debug_imgui::draw_disasm(debug_area* view_ptr, bool* opened) ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll; if(m_running) flags |= ImGuiInputTextFlags_ReadOnly; - ImGui::Combo("##cpu",&view_ptr->src_sel,get_view_source,view_ptr->view,view_ptr->view->source_list().count()); + ImGui::Combo("##cpu",&view_ptr->src_sel,get_view_source,view_ptr->view,view_ptr->view->source_count()); ImGui::SameLine(); ImGui::PushItemWidth(-1.0f); if(ImGui::InputText("##addr",view_ptr->console_input,512,flags)) @@ -800,17 +840,15 @@ void debug_imgui::draw_disasm(debug_area* view_ptr, bool* opened) ImGui::Separator(); // disassembly portion - src = view_ptr->view->first_source(); - idx = 0; - while (!done) + unsigned idx = 0; + const debug_view_source* src = view_ptr->view->source(idx); + do { if(view_ptr->src_sel == idx) view_ptr->view->set_source(*src); - idx++; - src = src->next(); - if(src == nullptr) - done = true; + src = view_ptr->view->source(++idx); } + while (src); ImGui::BeginChild("##disasm_output", ImVec2(ImGui::GetWindowWidth() - 16,ImGui::GetWindowHeight() - ImGui::GetTextLineHeight() - ImGui::GetCursorPosY())); // account for title bar and widgets already drawn draw_view(view_ptr,exp_change); @@ -841,13 +879,9 @@ void debug_imgui::add_disasm(int id) void debug_imgui::draw_memory(debug_area* view_ptr, bool* opened) { - const debug_view_source* src; - ImGui::SetNextWindowSize(ImVec2(view_ptr->width,view_ptr->height + ImGui::GetTextLineHeight()),ImGuiCond_Once); if(ImGui::Begin(view_ptr->title.c_str(),opened,ImGuiWindowFlags_MenuBar)) { - int idx; - bool done = false; bool exp_change = false; view_ptr->is_collapsed = false; @@ -855,26 +889,42 @@ void debug_imgui::draw_memory(debug_area* view_ptr, bool* opened) { if(ImGui::BeginMenu("Options")) { - debug_view_memory* mem = downcast<debug_view_memory*>(view_ptr->view); + auto* mem = downcast<debug_view_memory*>(view_ptr->view); bool physical = mem->physical(); bool rev = mem->reverse(); - int format = mem->get_data_format(); + debug_view_memory::data_format format = mem->get_data_format(); uint32_t chunks = mem->chunks_per_row(); - - if(ImGui::MenuItem("1-byte chunks", nullptr,(format == 1) ? true : false)) - mem->set_data_format(1); - if(ImGui::MenuItem("2-byte chunks", nullptr,(format == 2) ? true : false)) - mem->set_data_format(2); - if(ImGui::MenuItem("4-byte chunks", nullptr,(format == 4) ? true : false)) - mem->set_data_format(4); - if(ImGui::MenuItem("8-byte chunks", nullptr,(format == 8) ? true : false)) - mem->set_data_format(8); - if(ImGui::MenuItem("32-bit floating point", nullptr,(format == 9) ? true : false)) - mem->set_data_format(9); - if(ImGui::MenuItem("64-bit floating point", nullptr,(format == 10) ? true : false)) - mem->set_data_format(10); - if(ImGui::MenuItem("80-bit floating point", nullptr,(format == 11) ? true : false)) - mem->set_data_format(11); + int radix = mem->address_radix(); + + if(ImGui::MenuItem("1-byte hexadecimal", nullptr,(format == debug_view_memory::data_format::HEX_8BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::HEX_8BIT); + if(ImGui::MenuItem("2-byte hexadecimal", nullptr,(format == debug_view_memory::data_format::HEX_16BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::HEX_16BIT); + if(ImGui::MenuItem("4-byte hexadecimal", nullptr,(format == debug_view_memory::data_format::HEX_32BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::HEX_32BIT); + if(ImGui::MenuItem("8-byte hexadecimal", nullptr,(format == debug_view_memory::data_format::HEX_64BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::HEX_64BIT); + if(ImGui::MenuItem("1-byte octal", nullptr,(format == debug_view_memory::data_format::OCTAL_8BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::OCTAL_8BIT); + if(ImGui::MenuItem("2-byte octal", nullptr,(format == debug_view_memory::data_format::OCTAL_16BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::OCTAL_16BIT); + if(ImGui::MenuItem("4-byte octal", nullptr,(format == debug_view_memory::data_format::OCTAL_32BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::OCTAL_32BIT); + if(ImGui::MenuItem("8-byte octal", nullptr,(format == debug_view_memory::data_format::OCTAL_64BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::OCTAL_64BIT); + if(ImGui::MenuItem("32-bit floating point", nullptr,(format == debug_view_memory::data_format::FLOAT_32BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::FLOAT_32BIT); + if(ImGui::MenuItem("64-bit floating point", nullptr,(format == debug_view_memory::data_format::FLOAT_64BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::FLOAT_64BIT); + if(ImGui::MenuItem("80-bit floating point", nullptr,(format == debug_view_memory::data_format::FLOAT_80BIT) ? true : false)) + mem->set_data_format(debug_view_memory::data_format::FLOAT_80BIT); + ImGui::Separator(); + if(ImGui::MenuItem("Hexadecimal Addresses", nullptr,(radix == 16))) + mem->set_address_radix(16); + if(ImGui::MenuItem("Decimal Addresses", nullptr,(radix == 10))) + mem->set_address_radix(10); + if(ImGui::MenuItem("Octal Addresses", nullptr,(radix == 8))) + mem->set_address_radix(8); ImGui::Separator(); if(ImGui::MenuItem("Logical addresses", nullptr,!physical)) mem->set_physical(false); @@ -906,22 +956,20 @@ void debug_imgui::draw_memory(debug_area* view_ptr, bool* opened) ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::PushItemWidth(-1.0f); - ImGui::Combo("##region",&view_ptr->src_sel,get_view_source,view_ptr->view,view_ptr->view->source_list().count()); + ImGui::Combo("##region",&view_ptr->src_sel,get_view_source,view_ptr->view,view_ptr->view->source_count()); ImGui::PopItemWidth(); ImGui::Separator(); // memory editor portion - src = view_ptr->view->first_source(); - idx = 0; - while (!done) + unsigned idx = 0; + const debug_view_source* src = view_ptr->view->source(idx); + do { if(view_ptr->src_sel == idx) view_ptr->view->set_source(*src); - idx++; - src = src->next(); - if(src == nullptr) - done = true; + src = view_ptr->view->source(++idx); } + while (src); ImGui::BeginChild("##memory_output", ImVec2(ImGui::GetWindowWidth() - 16,ImGui::GetWindowHeight() - ImGui::GetTextLineHeight() - ImGui::GetCursorPosY())); // account for title bar and widgets already drawn draw_view(view_ptr,exp_change); @@ -954,24 +1002,25 @@ void debug_imgui::mount_image() { if(m_selected_file != nullptr) { - osd_file::error err; + std::error_condition err; switch(m_selected_file->type) { case file_entry_type::DRIVE: case file_entry_type::DIRECTORY: { util::zippath_directory::ptr dir; - err = util::zippath_directory::open(m_selected_file->fullpath.c_str(), dir); + err = util::zippath_directory::open(m_selected_file->fullpath, dir); } - if(err == osd_file::error::NONE) + if(!err) { m_filelist_refresh = true; strcpy(m_path,m_selected_file->fullpath.c_str()); } break; case file_entry_type::FILE: - m_dialog_image->load(m_selected_file->fullpath.c_str()); + m_dialog_image->load(m_selected_file->fullpath); ImGui::CloseCurrentPopup(); + m_mount_open = false; break; } } @@ -979,18 +1028,18 @@ void debug_imgui::mount_image() void debug_imgui::create_image() { - image_init_result res; + std::pair<std::error_condition, std::string> res; - if(m_dialog_image->image_type() == IO_FLOPPY) + auto *fd = dynamic_cast<floppy_image_device *>(m_dialog_image); + if(fd != nullptr) { - floppy_image_device *fd = static_cast<floppy_image_device *>(m_dialog_image); res = fd->create(m_path,nullptr,nullptr); - if(res == image_init_result::PASS) + if(!res.first) fd->setup_write(m_typelist.at(m_format_sel).format); } else res = m_dialog_image->create(m_path,nullptr,nullptr); - if(res == image_init_result::PASS) + if(!res.first) ImGui::CloseCurrentPopup(); // TODO: add a messagebox to display on an error } @@ -1004,32 +1053,29 @@ void debug_imgui::refresh_filelist() m_filelist_refresh = false; util::zippath_directory::ptr dir; - osd_file::error const err = util::zippath_directory::open(m_path,dir); - if(err == osd_file::error::NONE) + std::error_condition const err = util::zippath_directory::open(m_path,dir); + if(!err) { - int x = 0; // add drives - const char *volume_name; - while((volume_name = osd_get_volume_name(x))!=nullptr) + for(std::string const &volume_name : osd_get_volume_names()) { file_entry temp; temp.type = file_entry_type::DRIVE; - temp.basename = std::string(volume_name); - temp.fullpath = std::string(volume_name); + temp.basename = volume_name; + temp.fullpath = volume_name; m_filelist.emplace_back(std::move(temp)); - x++; } first = m_filelist.size(); - const osd::directory::entry *dirent; + const directory::entry *dirent; while((dirent = dir->readdir()) != nullptr) { file_entry temp; switch(dirent->type) { - case osd::directory::entry::entry_type::FILE: + case directory::entry::entry_type::FILE: temp.type = file_entry_type::FILE; break; - case osd::directory::entry::entry_type::DIR: + case directory::entry::entry_type::DIR: temp.type = file_entry_type::DIRECTORY; break; default: @@ -1048,7 +1094,7 @@ void debug_imgui::refresh_filelist() void debug_imgui::refresh_typelist() { - floppy_image_device *fd = static_cast<floppy_image_device *>(m_dialog_image); + auto *fd = static_cast<floppy_image_device *>(m_dialog_image); m_typelist.clear(); if(m_dialog_image->formatlist().empty()) @@ -1056,8 +1102,7 @@ void debug_imgui::refresh_typelist() if(fd == nullptr) return; - floppy_image_format_t* format_list = fd->get_formats(); - for(floppy_image_format_t* flist = format_list; flist; flist = flist->next) + for(const floppy_image_format_t* flist : fd->get_formats()) { if(flist->supports_save()) { @@ -1075,7 +1120,7 @@ void debug_imgui::draw_images_menu() if(ImGui::BeginMenu("Images")) { int x = 0; - for (device_image_interface &img : image_interface_iterator(m_machine->root_device())) + for (device_image_interface &img : image_interface_enumerator(m_machine->root_device())) { x++; std::string str = string_format(" %s : %s##%i",img.device().name(),img.exists() ? img.filename() : "[Empty slot]",x); @@ -1118,16 +1163,21 @@ void debug_imgui::draw_mount_dialog(const char* label) { // render dialog //ImGui::SetNextWindowContentWidth(200.0f); - if(ImGui::BeginPopupModal(label,NULL,ImGuiWindowFlags_AlwaysAutoResize)) + if(ImGui::BeginPopupModal(label,nullptr,ImGuiWindowFlags_AlwaysAutoResize)) { if(m_filelist_refresh) refresh_filelist(); if(ImGui::InputText("##mountpath",m_path,1024,ImGuiInputTextFlags_EnterReturnsTrue)) m_filelist_refresh = true; ImGui::Separator(); + + ImVec2 listbox_size; + listbox_size.x = 0.0f; + listbox_size.y = ImGui::GetTextLineHeightWithSpacing() * 15.25f; + + if(ImGui::BeginListBox("##filelist",listbox_size)) { - ImGui::ListBoxHeader("##filelist",m_filelist.size(),15); - for(std::vector<file_entry>::iterator f = m_filelist.begin();f != m_filelist.end();++f) + for(auto f = m_filelist.begin();f != m_filelist.end();++f) { std::string txt_name; bool sel = false; @@ -1150,14 +1200,19 @@ void debug_imgui::draw_mount_dialog(const char* label) { m_selected_file = &(*f); if(ImGui::IsMouseDoubleClicked(0)) + { mount_image(); + } } } - ImGui::ListBoxFooter(); + ImGui::EndListBox(); } ImGui::Separator(); if(ImGui::Button("Cancel##mount")) + { ImGui::CloseCurrentPopup(); + m_mount_open = false; + } ImGui::SameLine(); if(ImGui::Button("OK##mount")) mount_image(); @@ -1169,27 +1224,28 @@ void debug_imgui::draw_create_dialog(const char* label) { // render dialog //ImGui::SetNextWindowContentWidth(200.0f); - if(ImGui::BeginPopupModal(label,NULL,ImGuiWindowFlags_AlwaysAutoResize)) + if(ImGui::BeginPopupModal(label,nullptr,ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::LabelText("##static1","Filename:"); ImGui::SameLine(); if(ImGui::InputText("##createfilename",m_path,1024,ImGuiInputTextFlags_EnterReturnsTrue)) { auto entry = osd_stat(m_path); - auto file_type = (entry != nullptr) ? entry->type : osd::directory::entry::entry_type::NONE; - if(file_type == osd::directory::entry::entry_type::NONE) + auto file_type = (entry != nullptr) ? entry->type : directory::entry::entry_type::NONE; + if(file_type == directory::entry::entry_type::NONE) create_image(); - if(file_type == osd::directory::entry::entry_type::FILE) + if(file_type == directory::entry::entry_type::FILE) m_create_confirm_wait = true; // cannot overwrite a directory, so nothing will be none in that case. } // format combo box for floppy devices - if(m_dialog_image->image_type() == IO_FLOPPY) + auto *fd = dynamic_cast<floppy_image_device *>(m_dialog_image); + if(fd != nullptr) { std::string combo_str; combo_str.clear(); - for(std::vector<image_type_entry>::iterator f = m_typelist.begin();f != m_typelist.end();++f) + for(auto f = m_typelist.begin();f != m_typelist.end();++f) { // TODO: perhaps do this at the time the format list is generated, rather than every frame combo_str.append((*f).longname); @@ -1217,17 +1273,21 @@ void debug_imgui::draw_create_dialog(const char* label) { ImGui::Separator(); if(ImGui::Button("Cancel##mount")) + { ImGui::CloseCurrentPopup(); + m_create_open = false; + } ImGui::SameLine(); if(ImGui::Button("OK##mount")) { auto entry = osd_stat(m_path); - auto file_type = (entry != nullptr) ? entry->type : osd::directory::entry::entry_type::NONE; - if(file_type == osd::directory::entry::entry_type::NONE) + auto file_type = (entry != nullptr) ? entry->type : directory::entry::entry_type::NONE; + if(file_type == directory::entry::entry_type::NONE) create_image(); - if(file_type == osd::directory::entry::entry_type::FILE) + if(file_type == directory::entry::entry_type::FILE) m_create_confirm_wait = true; // cannot overwrite a directory, so nothing will be none in that case. + m_create_open = false; } } ImGui::EndPopup(); @@ -1237,6 +1297,10 @@ void debug_imgui::draw_create_dialog(const char* label) void debug_imgui::draw_console() { ImGuiWindowFlags flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; + bool show_menu = false; + + if(view_main_disasm == nullptr || view_main_regs == nullptr || view_main_console == nullptr) + return; ImGui::SetNextWindowSize(ImVec2(view_main_regs->width + view_main_disasm->width,view_main_disasm->height + view_main_console->height + ImGui::GetTextLineHeight()*3),ImGuiCond_Once); if(ImGui::Begin(view_main_console->title.c_str(), nullptr,flags)) @@ -1247,6 +1311,7 @@ void debug_imgui::draw_console() { if(ImGui::BeginMenu("Debug")) { + show_menu = true; if(ImGui::MenuItem("New disassembly window", "Ctrl+D")) add_disasm(++m_win_count); if(ImGui::MenuItem("New memory window", "Ctrl+M")) @@ -1260,46 +1325,47 @@ void debug_imgui::draw_console() ImGui::Separator(); if(ImGui::MenuItem("Run", "F5")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_running = true; } if(ImGui::MenuItem("Go to next CPU", "F6")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); m_running = true; } if(ImGui::MenuItem("Run until next interrupt", "F7")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); m_running = true; } if(ImGui::MenuItem("Run until VBLANK", "F8")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + m_machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); if(ImGui::MenuItem("Run and hide debugger", "F12")) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); m_hide = true; } ImGui::Separator(); if(ImGui::MenuItem("Single step", "F11")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step(); if(ImGui::MenuItem("Step over", "F10")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); if(ImGui::MenuItem("Step out", "F9")) - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + m_machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); ImGui::EndMenu(); } if(ImGui::BeginMenu("Window")) { + show_menu = true; if(ImGui::MenuItem("Show all")) { - for(std::vector<debug_area*>::iterator view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) + for(auto view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) ImGui::SetWindowCollapsed((*view_ptr)->title.c_str(),false); } ImGui::Separator(); // list all extra windows, so we can un-collapse the windows if necessary - for(std::vector<debug_area*>::iterator view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) + for(auto view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr) { bool collapsed = false; if((*view_ptr)->is_collapsed) @@ -1310,7 +1376,10 @@ void debug_imgui::draw_console() ImGui::EndMenu(); } if(m_has_images) + { + show_menu = true; draw_images_menu(); + } ImGui::EndMenuBar(); } @@ -1341,20 +1410,18 @@ void debug_imgui::draw_console() ImGui::PushItemWidth(-1.0f); if(ImGui::InputText("##console_input",view_main_console->console_input,512,flags,history_set)) view_main_console->exec_cmd = true; - if ((ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) + if ((ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0) && !show_menu)) ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget if(m_mount_open) { ImGui::OpenPopup("Mount Image"); - m_mount_open = false; + draw_mount_dialog("Mount Image"); // draw mount image dialog if open } if(m_create_open) { ImGui::OpenPopup("Create Image"); - m_create_open = false; + draw_create_dialog("Create Image"); // draw create image dialog if open } - draw_mount_dialog("Mount Image"); // draw mount image dialog if open - draw_create_dialog("Create Image"); // draw create image dialog if open ImGui::PopItemWidth(); ImGui::EndChild(); ImGui::End(); @@ -1367,7 +1434,6 @@ void debug_imgui::update() //debug_area* view_ptr = view_list; std::vector<debug_area*>::iterator view_ptr; bool opened; - int count = 0; ImGui::PushStyleColor(ImGuiCol_WindowBg,ImVec4(1.0f,1.0f,1.0f,0.9f)); ImGui::PushStyleColor(ImGuiCol_Text,ImVec4(0.0f,0.0f,0.0f,1.0f)); ImGui::PushStyleColor(ImGuiCol_TextDisabled,ImVec4(0.0f,0.0f,1.0f,1.0f)); @@ -1412,13 +1478,12 @@ void debug_imgui::update() break; } ++view_ptr; - count++; } // check for a closed window if(to_delete != nullptr) { view_list_remove(to_delete); - global_free(to_delete); + delete to_delete; } ImGui::PopStyleColor(12); @@ -1433,31 +1498,44 @@ void debug_imgui::init_debugger(running_machine &machine) fatalerror("Error: ImGui debugger requires the BGFX renderer.\n"); // check for any image devices (cassette, floppy, etc...) - image_interface_iterator iter(m_machine->root_device()); + image_interface_enumerator iter(m_machine->root_device()); if (iter.first() != nullptr) m_has_images = true; // map keys to ImGui inputs - io.KeyMap[ImGuiKey_A] = ITEM_ID_A; - io.KeyMap[ImGuiKey_C] = ITEM_ID_C; - io.KeyMap[ImGuiKey_V] = ITEM_ID_V; - io.KeyMap[ImGuiKey_X] = ITEM_ID_X; - io.KeyMap[ImGuiKey_C] = ITEM_ID_C; - io.KeyMap[ImGuiKey_Y] = ITEM_ID_Y; - io.KeyMap[ImGuiKey_Z] = ITEM_ID_Z; - io.KeyMap[ImGuiKey_Backspace] = ITEM_ID_BACKSPACE; - io.KeyMap[ImGuiKey_Delete] = ITEM_ID_DEL; - io.KeyMap[ImGuiKey_Tab] = ITEM_ID_TAB; - io.KeyMap[ImGuiKey_PageUp] = ITEM_ID_PGUP; - io.KeyMap[ImGuiKey_PageDown] = ITEM_ID_PGDN; - io.KeyMap[ImGuiKey_Home] = ITEM_ID_HOME; - io.KeyMap[ImGuiKey_End] = ITEM_ID_END; - io.KeyMap[ImGuiKey_Escape] = ITEM_ID_ESC; - io.KeyMap[ImGuiKey_Enter] = ITEM_ID_ENTER; - io.KeyMap[ImGuiKey_LeftArrow] = ITEM_ID_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = ITEM_ID_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = ITEM_ID_UP; - io.KeyMap[ImGuiKey_DownArrow] = ITEM_ID_DOWN; + m_mapping[ITEM_ID_A] = ImGuiKey_A; + m_mapping[ITEM_ID_C] = ImGuiKey_C; + m_mapping[ITEM_ID_V] = ImGuiKey_V; + m_mapping[ITEM_ID_X] = ImGuiKey_X; + m_mapping[ITEM_ID_Y] = ImGuiKey_Y; + m_mapping[ITEM_ID_Z] = ImGuiKey_Z; + m_mapping[ITEM_ID_D] = ImGuiKey_D; + m_mapping[ITEM_ID_M] = ImGuiKey_M; + m_mapping[ITEM_ID_B] = ImGuiKey_B; + m_mapping[ITEM_ID_W] = ImGuiKey_W; + m_mapping[ITEM_ID_L] = ImGuiKey_L; + m_mapping[ITEM_ID_BACKSPACE] = ImGuiKey_Backspace; + m_mapping[ITEM_ID_DEL] = ImGuiKey_Delete; + m_mapping[ITEM_ID_TAB] = ImGuiKey_Tab; + m_mapping[ITEM_ID_PGUP] = ImGuiKey_PageUp; + m_mapping[ITEM_ID_PGDN] = ImGuiKey_PageDown; + m_mapping[ITEM_ID_HOME] = ImGuiKey_Home; + m_mapping[ITEM_ID_END] = ImGuiKey_End; + m_mapping[ITEM_ID_ESC] = ImGuiKey_Escape; + m_mapping[ITEM_ID_ENTER] = ImGuiKey_Enter; + m_mapping[ITEM_ID_LEFT] = ImGuiKey_LeftArrow; + m_mapping[ITEM_ID_RIGHT] = ImGuiKey_RightArrow; + m_mapping[ITEM_ID_UP] = ImGuiKey_UpArrow; + m_mapping[ITEM_ID_DOWN] = ImGuiKey_DownArrow; + m_mapping[ITEM_ID_F3] = ImGuiKey_F3; + m_mapping[ITEM_ID_F5] = ImGuiKey_F5; + m_mapping[ITEM_ID_F6] = ImGuiKey_F6; + m_mapping[ITEM_ID_F7] = ImGuiKey_F7; + m_mapping[ITEM_ID_F8] = ImGuiKey_F8; + m_mapping[ITEM_ID_F9] = ImGuiKey_F9; + m_mapping[ITEM_ID_F10] = ImGuiKey_F10; + m_mapping[ITEM_ID_F11] = ImGuiKey_F11; + m_mapping[ITEM_ID_F12] = ImGuiKey_F12; // set key delay and repeat rates io.KeyRepeatDelay = 0.400f; @@ -1503,38 +1581,68 @@ void debug_imgui::wait_for_debugger(device_t &device, bool firststop) } if(firststop) { -// debug_show_all(); - device.machine().ui_input().reset(); + //debug_show_all(); m_running = false; } + if(!m_take_ui) + { + if (!m_machine->ui().set_ui_event_handler([this] () { return m_take_ui; })) + { + // can't break if we can't take over UI input + m_machine->debugger().console().get_visible_cpu()->debug()->go(); + m_running = true; + return; + } + m_take_ui = true; + + } m_hide = false; -// m_machine->ui_input().frame_update(); - handle_mouse(); - handle_keys(); + m_machine->osd().input_update(false); + handle_events(); handle_console(m_machine); update_cpu_view(&device); - imguiBeginFrame(m_mouse_x,m_mouse_y,m_mouse_button ? IMGUI_MBUT_LEFT : 0, 0, width, height,m_key_char); - update(); - imguiEndFrame(); + imguiBeginFrame(m_mouse_x, m_mouse_y, m_mouse_button ? IMGUI_MBUT_LEFT : 0, 0, width, height,m_key_char); handle_mouse_views(); handle_keys_views(); - m_machine->ui_input().reset(); // clear remaining inputs, so they don't fall through to the UI + update(); + imguiEndFrame(); device.machine().osd().update(false); + osd_sleep(osd_ticks_per_second() / 1000 * 50); } void debug_imgui::debugger_update() { - if (m_machine && (m_machine->phase() == machine_phase::RUNNING) && !m_machine->debugger().cpu().is_stopped() && !m_hide) + if(!view_main_disasm || !view_main_regs || !view_main_console || !m_machine || (m_machine->phase() != machine_phase::RUNNING)) + return; + + if(!m_machine->debugger().cpu().is_stopped()) { - uint32_t width = m_machine->render().ui_target().width(); - uint32_t height = m_machine->render().ui_target().height(); - handle_mouse(); - handle_keys(); - imguiBeginFrame(m_mouse_x,m_mouse_y,m_mouse_button ? IMGUI_MBUT_LEFT : 0, 0, width, height, m_key_char); - update(); - imguiEndFrame(); + if(m_take_ui) + { + m_take_ui = false; + m_current_pointer = -1; + m_prev_mouse_button = m_mouse_button; + if(m_mouse_button) + { + m_mouse_button = false; + ImGuiIO& io = ImGui::GetIO(); + io.MouseDown[0] = false; + } + } + if(!m_hide) + { + uint32_t width = m_machine->render().ui_target().width(); + uint32_t height = m_machine->render().ui_target().height(); + imguiBeginFrame(m_mouse_x, m_mouse_y, 0, 0, width, height, m_key_char); + update(); + imguiEndFrame(); + } } } -MODULE_DEFINITION(DEBUG_IMGUI, debug_imgui) +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(DEBUG_IMGUI, osd::debug_imgui) diff --git a/src/osd/modules/debugger/debugosx.mm b/src/osd/modules/debugger/debugosx.mm index def790ef939..a4721e4d292 100644 --- a/src/osd/modules/debugger/debugosx.mm +++ b/src/osd/modules/debugger/debugosx.mm @@ -24,11 +24,6 @@ // MAMEOS headers #include "modules/lib/osdobj_common.h" #include "osx/debugosx.h" -#ifdef OSD_MAC -#include "osdmac.h" -#else -#include "osdsdl.h" -#endif #include "debug_module.h" #import "osx/debugconsole.h" @@ -61,17 +56,17 @@ public: [m_console release]; } - virtual int init(const osd_options &options); - virtual void exit(); + virtual int init(osd_interface &osd, const osd_options &options) override; + virtual void exit() override; - virtual void init_debugger(running_machine &machine); - virtual void wait_for_debugger(device_t &device, bool firststop); - virtual void debugger_update(); + virtual void init_debugger(running_machine &machine) override; + virtual void wait_for_debugger(device_t &device, bool firststop) override; + virtual void debugger_update() override; private: void create_console(); void build_menus(); - void config_load(config_type cfgtype, util::xml::data_node const *parentnode); + void config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode); void config_save(config_type cfgtype, util::xml::data_node *parentnode); running_machine *m_machine; @@ -91,7 +86,7 @@ std::atomic_bool debugger_osx::s_added_menus(false); // initialise debugger module //============================================================ -int debugger_osx::init(const osd_options &options) +int debugger_osx::init(osd_interface &osd, const osd_options &options) { return 0; } @@ -129,8 +124,8 @@ void debugger_osx::init_debugger(running_machine &machine) m_machine = &machine; machine.configuration().config_register( "debugger", - config_load_delegate(&debugger_osx::config_load, this), - config_save_delegate(&debugger_osx::config_save, this)); + configuration_manager::load_delegate(&debugger_osx::config_load, this), + configuration_manager::save_delegate(&debugger_osx::config_save, this)); } @@ -165,7 +160,7 @@ void debugger_osx::wait_for_debugger(device_t &device, bool firststop) } // get and process messages - NSEvent *ev = [NSApp nextEventMatchingMask:NSAnyEventMask + NSEvent *ev = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES]; @@ -211,7 +206,7 @@ void debugger_osx::build_menus() { NSMenuItem *item; - NSMenu *const debugMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Debug"]; + NSMenu *const debugMenu = [[NSMenu alloc] initWithTitle:@"Debug"]; item = [[NSApp mainMenu] insertItemWithTitle:@"Debug" action:NULL keyEquivalent:@"" atIndex:1]; [item setSubmenu:debugMenu]; [debugMenu release]; @@ -241,9 +236,9 @@ void debugger_osx::build_menus() [[debugMenu addItemWithTitle:@"Hard Reset" action:@selector(debugHardReset:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF3FunctionKey]] - setKeyEquivalentModifierMask:NSShiftKeyMask]; + setKeyEquivalentModifierMask:NSEventModifierFlagShift]; - NSMenu *const runMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Run"]; + NSMenu *const runMenu = [[NSMenu alloc] initWithTitle:@"Run"]; item = [[NSApp mainMenu] insertItemWithTitle:@"Run" action:NULL keyEquivalent:@"" @@ -295,7 +290,7 @@ void debugger_osx::build_menus() [[runMenu addItemWithTitle:@"Step Out" action:@selector(debugStepOut:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF10FunctionKey]] - setKeyEquivalentModifierMask:NSShiftKeyMask]; + setKeyEquivalentModifierMask:NSEventModifierFlagShift]; } } @@ -305,9 +300,9 @@ void debugger_osx::build_menus() // restore state based on configuration XML //============================================================ -void debugger_osx::config_load(config_type cfgtype, util::xml::data_node const *parentnode) +void debugger_osx::config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode) { - if ((config_type::GAME == cfgtype) && parentnode) + if ((config_type::SYSTEM == cfgtype) && parentnode) { if (m_console) { @@ -331,7 +326,7 @@ void debugger_osx::config_load(config_type cfgtype, util::xml::data_node const * void debugger_osx::config_save(config_type cfgtype, util::xml::data_node *parentnode) { - if ((config_type::GAME == cfgtype) && m_console) + if ((config_type::SYSTEM == cfgtype) && m_console) { NSAutoreleasePool *const pool = [[NSAutoreleasePool alloc] init]; NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:m_machine], diff --git a/src/osd/modules/debugger/debugqt.cpp b/src/osd/modules/debugger/debugqt.cpp index 9156fd31c16..aeae07324e4 100644 --- a/src/osd/modules/debugger/debugqt.cpp +++ b/src/osd/modules/debugger/debugqt.cpp @@ -32,250 +32,102 @@ #include "qt/deviceswindow.h" #include "qt/deviceinformationwindow.h" -class debug_qt : public osd_module, public debug_module -#if defined(WIN32) && !defined(SDLMAME_WIN32) -, public QAbstractNativeEventFilter -#endif -{ -public: - debug_qt() - : osd_module(OSD_DEBUG_PROVIDER, "qt"), debug_module(), - m_machine(nullptr) - { - } - - virtual ~debug_qt() { } +#include "util/xmlfile.h" - virtual int init(const osd_options &options) { 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(); -#if defined(WIN32) && !defined(SDLMAME_WIN32) - virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE; +#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) +extern int sdl_entered_debugger; +#elif defined(_WIN32) +void winwindow_update_cursor_state(running_machine &machine); +bool winwindow_qt_filter(void *message); #endif -private: - running_machine *m_machine; -}; - - -namespace { -//============================================================ -// "Global" variables to make QT happy -//============================================================ - -int qtArgc = 1; -char qtArg0[] = "mame"; -char *qtArgv[] = { qtArg0, nullptr }; - -bool oneShot = true; -MainWindow *mainQtWindow = nullptr; - -//============================================================ -// XML configuration save/load -//============================================================ -// Global variable used to feed the xml configuration callbacks -std::vector<WindowQtConfig*> xmlConfigurations; +namespace osd { +namespace { - void xml_configuration_load(running_machine &machine, config_type cfg_type, util::xml::data_node const *parentnode) +class debug_qt : public osd_module, public debug_module, protected debugger::qt::DebuggerQt +#if defined(_WIN32) && !defined(SDLMAME_WIN32) +, public QAbstractNativeEventFilter +#endif { - // We only care about game files - if (cfg_type != config_type::GAME) - return; - - // Might not have any data - if (parentnode == nullptr) - return; - - for (int i = 0; i < xmlConfigurations.size(); i++) - delete xmlConfigurations[i]; - xmlConfigurations.clear(); - - // Configuration load - util::xml::data_node const * wnode = nullptr; - for (wnode = parentnode->get_child("window"); wnode != nullptr; wnode = wnode->get_next_sibling("window")) +public: + debug_qt() : + osd_module(OSD_DEBUG_PROVIDER, "qt"), + debug_module(), + m_machine(nullptr), + m_mainwindow(nullptr) { - WindowQtConfig::WindowType type = (WindowQtConfig::WindowType)wnode->get_attribute_int("type", WindowQtConfig::WIN_TYPE_UNKNOWN); - switch (type) - { - case WindowQtConfig::WIN_TYPE_MAIN: xmlConfigurations.push_back(new MainWindowQtConfig()); break; - case WindowQtConfig::WIN_TYPE_MEMORY: xmlConfigurations.push_back(new MemoryWindowQtConfig()); break; - case WindowQtConfig::WIN_TYPE_DASM: xmlConfigurations.push_back(new DasmWindowQtConfig()); break; - case WindowQtConfig::WIN_TYPE_LOG: xmlConfigurations.push_back(new LogWindowQtConfig()); break; - case WindowQtConfig::WIN_TYPE_BREAK_POINTS: xmlConfigurations.push_back(new BreakpointsWindowQtConfig()); break; - case WindowQtConfig::WIN_TYPE_DEVICES: xmlConfigurations.push_back(new DevicesWindowQtConfig()); break; - case WindowQtConfig::WIN_TYPE_DEVICE_INFORMATION: xmlConfigurations.push_back(new DeviceInformationWindowQtConfig()); break; - default: continue; - } - xmlConfigurations.back()->recoverFromXmlNode(*wnode); } -} + virtual ~debug_qt() { } -void xml_configuration_save(running_machine &machine, config_type cfg_type, util::xml::data_node *parentnode) -{ - // We only write to game configurations - if (cfg_type != config_type::GAME) - return; + virtual int init(osd_interface &osd, const osd_options &options) override { return 0; } + virtual void exit() override; - for (int i = 0; i < xmlConfigurations.size(); i++) + virtual void init_debugger(running_machine &machine) override; + virtual void wait_for_debugger(device_t &device, bool firststop) override; + virtual void debugger_update() override; +#if defined(_WIN32) && !defined(SDLMAME_WIN32) + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override { - WindowQtConfig* config = xmlConfigurations[i]; - - // Create an xml node - util::xml::data_node *const debugger_node = parentnode->add_child("window", nullptr); - if (debugger_node == nullptr) - continue; - - // Insert the appropriate information - config->addToXmlDataNode(*debugger_node); + winwindow_qt_filter(message); + return false; } -} +#endif + virtual running_machine &machine() const override { return *m_machine; } -void gather_save_configurations() -{ - for (int i = 0; i < xmlConfigurations.size(); i++) - delete xmlConfigurations[i]; - xmlConfigurations.clear(); +private: + void configuration_load(config_type which_type, config_level level, util::xml::data_node const *parentnode); + void configuration_save(config_type which_type, util::xml::data_node *parentnode); + void load_window_configurations(util::xml::data_node const &parentnode); - // Loop over all the open windows - foreach (QWidget* widget, QApplication::topLevelWidgets()) - { - if (!widget->isVisible()) - continue; - - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - - // Figure out its type - if (dynamic_cast<MainWindow*>(widget)) - xmlConfigurations.push_back(new MainWindowQtConfig()); - else if (dynamic_cast<MemoryWindow*>(widget)) - xmlConfigurations.push_back(new MemoryWindowQtConfig()); - else if (dynamic_cast<DasmWindow*>(widget)) - xmlConfigurations.push_back(new DasmWindowQtConfig()); - else if (dynamic_cast<LogWindow*>(widget)) - xmlConfigurations.push_back(new LogWindowQtConfig()); - else if (dynamic_cast<BreakpointsWindow*>(widget)) - xmlConfigurations.push_back(new BreakpointsWindowQtConfig()); - else if (dynamic_cast<DevicesWindow*>(widget)) - xmlConfigurations.push_back(new DevicesWindowQtConfig()); - else if (dynamic_cast<DeviceInformationWindow*>(widget)) - xmlConfigurations.push_back(new DeviceInformationWindowQtConfig()); - - xmlConfigurations.back()->buildFromQWidget(widget); - } -} + running_machine *m_machine; + debugger::qt::MainWindow *m_mainwindow; + util::xml::file::ptr m_config; +}; //============================================================ -// Utilities +// "Global" variables to make QT happy //============================================================ -void load_and_clear_main_window_config(std::vector<WindowQtConfig*>& configList) -{ - for (int i = 0; i < configList.size(); i++) - { - WindowQtConfig* config = configList[i]; - if (config->m_type == WindowQtConfig::WIN_TYPE_MAIN) - { - config->applyToQWidget(mainQtWindow); - configList.erase(configList.begin()+i); - break; - } - } -} - - -void setup_additional_startup_windows(running_machine& machine, std::vector<WindowQtConfig*>& configList) -{ - for (int i = 0; i < configList.size(); i++) - { - WindowQtConfig* config = configList[i]; - - WindowQt* foo = nullptr; - switch (config->m_type) - { - case WindowQtConfig::WIN_TYPE_MEMORY: - foo = new MemoryWindow(&machine); break; - case WindowQtConfig::WIN_TYPE_DASM: - foo = new DasmWindow(&machine); break; - case WindowQtConfig::WIN_TYPE_LOG: - foo = new LogWindow(&machine); break; - case WindowQtConfig::WIN_TYPE_BREAK_POINTS: - foo = new BreakpointsWindow(&machine); break; - case WindowQtConfig::WIN_TYPE_DEVICES: - foo = new DevicesWindow(&machine); break; - case WindowQtConfig::WIN_TYPE_DEVICE_INFORMATION: - foo = new DeviceInformationWindow(&machine); break; - default: break; - } - config->applyToQWidget(foo); - foo->show(); - } -} - - -void bring_main_window_to_front() -{ - foreach (QWidget* widget, QApplication::topLevelWidgets()) - { - if (!dynamic_cast<MainWindow*>(widget)) - continue; - widget->activateWindow(); - widget->raise(); - } -} - -} // anonymous namespace +int qtArgc = 1; +char qtArg0[] = "mame"; +char *qtArgv[] = { qtArg0, nullptr }; //============================================================ // Core functionality //============================================================ -#if defined(WIN32) && !defined(SDLMAME_WIN32) -bool winwindow_qt_filter(void *message); - -bool debug_qt::nativeEventFilter(const QByteArray &eventType, void *message, long *) +void debug_qt::exit() { - winwindow_qt_filter(message); - return false; + // If you've done a hard reset, clear out existing widgets + emit exitDebugger(); + m_mainwindow = nullptr; } -#endif + void debug_qt::init_debugger(running_machine &machine) { - if (qApp == nullptr) + if (!qApp) { // If you're starting from scratch, create a new qApp new QApplication(qtArgc, qtArgv); -#if defined(WIN32) && !defined(SDLMAME_WIN32) +#if defined(_WIN32) && !defined(SDLMAME_WIN32) QAbstractEventDispatcher::instance()->installNativeEventFilter(this); #endif } - else - { - // If you've done a hard reset, clear out existing widgets & get ready for re-init - foreach (QWidget* widget, QApplication::topLevelWidgets()) - { - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - delete widget; - } - oneShot = true; - } m_machine = &machine; + // Setup the configuration XML saving and loading machine.configuration().config_register("debugger", - config_load_delegate(&xml_configuration_load, &machine), - config_save_delegate(&xml_configuration_save, &machine)); + configuration_manager::load_delegate(&debug_qt::configuration_load, this), + configuration_manager::save_delegate(&debug_qt::configuration_save, this)); } @@ -283,12 +135,6 @@ void debug_qt::init_debugger(running_machine &machine) // Core functionality //============================================================ -#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) -extern int sdl_entered_debugger; -#elif defined(WIN32) -void winwindow_update_cursor_state(running_machine &machine); -#endif - void debug_qt::wait_for_debugger(device_t &device, bool firststop) { #if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) @@ -296,81 +142,117 @@ void debug_qt::wait_for_debugger(device_t &device, bool firststop) #endif // Dialog initialization - if (oneShot) + if (!m_mainwindow) { - mainQtWindow = new MainWindow(m_machine); - load_and_clear_main_window_config(xmlConfigurations); - setup_additional_startup_windows(*m_machine, xmlConfigurations); - mainQtWindow->show(); - oneShot = false; + m_mainwindow = new debugger::qt::MainWindow(*this); + if (m_config) + { + load_window_configurations(*m_config->get_first_child()); + m_config.reset(); + } + m_mainwindow->show(); } - // Insure all top level widgets are visible & bring main window to front - foreach (QWidget* widget, QApplication::topLevelWidgets()) - { - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - widget->show(); - } + // Ensure all top level widgets are visible & bring main window to front + emit showAllWindows(); if (firststop) { - bring_main_window_to_front(); + m_mainwindow->activateWindow(); + m_mainwindow->raise(); } - // Set the main window to display the proper cpu - mainQtWindow->setProcessor(&device); + // Set the main window to display the proper CPU + m_mainwindow->setProcessor(&device); // Run our own QT event loop osd_sleep(osd_ticks_per_second() / 1000 * 50); qApp->processEvents(QEventLoop::AllEvents, 1); - // Refresh everyone if requested - if (mainQtWindow->wantsRefresh()) - { - QWidgetList allWidgets = qApp->allWidgets(); - for (int i = 0; i < allWidgets.length(); i++) - allWidgets[i]->update(); - mainQtWindow->clearRefreshFlag(); - } +#if defined(_WIN32) && !defined(SDLMAME_WIN32) + winwindow_update_cursor_state(*m_machine); // make sure the cursor isn't hidden while in debugger +#endif +} + + +//============================================================ +// Available for video.* +//============================================================ + +void debug_qt::debugger_update() +{ + qApp->processEvents(QEventLoop::AllEvents); +} - // Hide all top level widgets if requested - if (mainQtWindow->wantsHide()) + +void debug_qt::configuration_load(config_type which_type, config_level level, util::xml::data_node const *parentnode) +{ + // We only care about system configuration files for now + if ((config_type::SYSTEM == which_type) && parentnode) { - foreach (QWidget* widget, QApplication::topLevelWidgets()) + if (m_mainwindow) + { + load_window_configurations(*parentnode); + } + else { - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - widget->hide(); + m_config = util::xml::file::create(); + parentnode->copy_into(*m_config); } - mainQtWindow->clearHideFlag(); } +} + + +void debug_qt::configuration_save(config_type which_type, util::xml::data_node *parentnode) +{ + // We only save system configuration for now + if ((config_type::SYSTEM == which_type) && parentnode) + emit saveConfiguration(*parentnode); +} - // Exit if the machine has been instructed to do so (scheduled event == exit || hard_reset) - if (m_machine->scheduled_event_pending()) + +void debug_qt::load_window_configurations(util::xml::data_node const &parentnode) +{ + for (util::xml::data_node const *wnode = parentnode.get_child(debugger::NODE_WINDOW); wnode; wnode = wnode->get_next_sibling(debugger::NODE_WINDOW)) { - // Keep a list of windows we want to save. - // We need to do this here because by the time xml_configuration_save gets called - // all the QT windows are already gone. - gather_save_configurations(); + debugger::qt::WindowQt *win = nullptr; + switch (wnode->get_attribute_int(debugger::ATTR_WINDOW_TYPE, -1)) + { + case debugger::WINDOW_TYPE_CONSOLE: + win = m_mainwindow; + break; + case debugger::WINDOW_TYPE_MEMORY_VIEWER: + win = new debugger::qt::MemoryWindow(*this); + break; + case debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: + win = new debugger::qt::DasmWindow(*this); + break; + case debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: + win = new debugger::qt::LogWindow(*this); + break; + case debugger::WINDOW_TYPE_POINTS_VIEWER: + win = new debugger::qt::BreakpointsWindow(*this); + break; + case debugger::WINDOW_TYPE_DEVICES_VIEWER: + win = new debugger::qt::DevicesWindow(*this); + break; + case debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: + win = new debugger::qt::DeviceInformationWindow(*this); + break; + } + if (win) + win->restoreConfiguration(*wnode); } -#if defined(WIN32) && !defined(SDLMAME_WIN32) - winwindow_update_cursor_state(*m_machine); // make sure the cursor isn't hidden while in debugger -#endif } +} // anonymous namespace -//============================================================ -// Available for video.* -//============================================================ +} // namespace osd -void debug_qt::debugger_update() -{ - qApp->processEvents(QEventLoop::AllEvents, 1); -} +#else // USE_QTDEBUG + +namespace osd { namespace { MODULE_NOT_SUPPORTED(debug_qt, OSD_DEBUG_PROVIDER, "qt") } } -#else /* SDLMAME_UNIX */ - MODULE_NOT_SUPPORTED(debug_qt, OSD_DEBUG_PROVIDER, "qt") #endif -MODULE_DEFINITION(DEBUG_QT, debug_qt) +MODULE_DEFINITION(DEBUG_QT, osd::debug_qt) diff --git a/src/osd/modules/debugger/debugwin.cpp b/src/osd/modules/debugger/debugwin.cpp index 975e7ba6bc6..8ff26d40fb3 100644 --- a/src/osd/modules/debugger/debugwin.cpp +++ b/src/osd/modules/debugger/debugwin.cpp @@ -2,13 +2,12 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugwin.c - Win32 debug window handling +// debugwin.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "debug_module.h" -#include "modules/osdmodule.h" #if defined(OSD_WINDOWS) /*|| defined(SDLMAME_WIN32)*/ @@ -22,31 +21,50 @@ #include "win/pointswininfo.h" #include "win/uimetrics.h" +// emu +#include "config.h" #include "debugger.h" #include "debug/debugcpu.h" +#include "util/xmlfile.h" + +// osd/windows #include "window.h" -#include "../input/input_common.h" -#include "../input/input_windows.h" +#include "winmain.h" + +#include "../input/input_windows.h" // for the keyboard translation table + +namespace osd { -class debugger_windows : public osd_module, public debug_module, protected debugger_windows_interface +namespace { + +class debugger_windows : + public osd_module, + public debug_module, + protected debugger::win::debugger_windows_interface { public: debugger_windows() : osd_module(OSD_DEBUG_PROVIDER, "windows"), debug_module(), + m_osd(nullptr), m_machine(nullptr), m_metrics(), m_waiting_for_debugger(false), m_window_list(), - m_main_console(nullptr) + m_main_console(nullptr), + m_next_window_pos{ 0, 0 }, + m_config(), + m_save_windows(true), + m_group_windows(true), + m_group_windows_setting(true) { } virtual ~debugger_windows() { } - virtual int init(const osd_options &options) override { return 0; } + virtual int init(osd_interface &osd, osd_options const &options) override; virtual void exit() override; virtual void init_debugger(running_machine &machine) override; @@ -56,31 +74,63 @@ public: protected: virtual running_machine &machine() const override { return *m_machine; } - virtual ui_metrics &metrics() const override { return *m_metrics; } + virtual debugger::win::ui_metrics &metrics() const override { return *m_metrics; } + virtual void set_color_theme(int index) override; + virtual bool get_save_window_arrangement() const override { return m_save_windows; } + virtual void set_save_window_arrangement(bool save) override { m_save_windows = save; } + virtual bool get_group_windows() const override { return m_group_windows; } + virtual bool get_group_windows_setting() const override { return m_group_windows_setting; } + virtual void set_group_windows_setting(bool group) override { m_group_windows_setting = group; } virtual bool const &waiting_for_debugger() const override { return m_waiting_for_debugger; } virtual bool seq_pressed() const override; - virtual void create_memory_window() override { create_window<memorywin_info>(); } - virtual void create_disasm_window() override { create_window<disasmwin_info>(); } - virtual void create_log_window() override { create_window<logwin_info>(); } - virtual void create_points_window() override { create_window<pointswin_info>(); } - virtual void remove_window(debugwin_info &info) override; + virtual void create_memory_window() override { create_window<debugger::win::memorywin_info>(); } + virtual void create_disasm_window() override { create_window<debugger::win::disasmwin_info>(); } + virtual void create_log_window() override { create_window<debugger::win::logwin_info>(); } + virtual void create_points_window() override { create_window<debugger::win::pointswin_info>(); } + virtual void remove_window(debugger::win::debugwin_info &info) override; virtual void show_all() override; virtual void hide_all() override; + virtual void stagger_window(HWND window, int width, int height) override; + private: template <typename T> T *create_window(); - running_machine *m_machine; - std::unique_ptr<ui_metrics> m_metrics; - bool m_waiting_for_debugger; - std::vector<std::unique_ptr<debugwin_info>> m_window_list; - consolewin_info *m_main_console; + void config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode); + void config_save(config_type cfgtype, util::xml::data_node *parentnode); + + void load_configuration(util::xml::data_node const &parentnode); + + windows_osd_interface *m_osd; + running_machine *m_machine; + std::unique_ptr<debugger::win::ui_metrics> m_metrics; + bool m_waiting_for_debugger; + std::vector<std::unique_ptr<debugger::win::debugwin_info> > m_window_list; + debugger::win::consolewin_info *m_main_console; + + POINT m_next_window_pos; + LONG m_window_start_x; + + util::xml::file::ptr m_config; + bool m_save_windows; + bool m_group_windows; + bool m_group_windows_setting; }; +int debugger_windows::init(osd_interface &osd, osd_options const &options) +{ + m_osd = dynamic_cast<windows_osd_interface *>(&osd); + if (!m_osd) + return -1; + + return 0; +} + + void debugger_windows::exit() { // loop over windows and free them @@ -96,23 +146,52 @@ void debugger_windows::exit() void debugger_windows::init_debugger(running_machine &machine) { m_machine = &machine; - m_metrics = std::make_unique<ui_metrics>(downcast<osd_options &>(m_machine->options())); + m_metrics = std::make_unique<debugger::win::ui_metrics>(downcast<osd_options &>(m_machine->options())); + machine.configuration().config_register( + "debugger", + configuration_manager::load_delegate(&debugger_windows::config_load, this), + configuration_manager::save_delegate(&debugger_windows::config_save, this)); } void debugger_windows::wait_for_debugger(device_t &device, bool firststop) { // create a console window - if (m_main_console == nullptr) - m_main_console = create_window<consolewin_info>(); + if (!m_main_console) + { + m_main_console = create_window<debugger::win::consolewin_info>(); + + // set the starting position for new auxiliary windows + HMONITOR const nearest_monitor = MonitorFromWindow( + dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(), + MONITOR_DEFAULTTONEAREST); + if (nearest_monitor) + { + MONITORINFO info; + std::memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + if (GetMonitorInfo(nearest_monitor, &info)) + { + m_next_window_pos.x = info.rcWork.left + 100; + m_next_window_pos.y = info.rcWork.top + 100; + m_window_start_x = m_next_window_pos.x; + } + } + } // update the views in the console to reflect the current CPU - if (m_main_console != nullptr) + if (m_main_console) m_main_console->set_cpu(device); // when we are first stopped, adjust focus to us - if (firststop && (m_main_console != nullptr)) + if (firststop && m_main_console) { + if (m_config) + { + for (util::xml::data_node const *node = m_config->get_first_child(); node; node = node->get_next_sibling()) + load_configuration(*node); + m_config.reset(); + } m_main_console->set_foreground(); if (winwindow_has_focus()) m_main_console->set_default_focus(); @@ -123,7 +202,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop) show_all(); // run input polling to ensure that our status is in sync - downcast<windows_osd_interface&>(machine().osd()).poll_input(*m_machine); + downcast<windows_osd_interface&>(machine().osd()).poll_input_modules(false); // get and process messages MSG message; @@ -142,7 +221,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop) // process everything else default: - winwindow_dispatch_message(*m_machine, &message); + winwindow_dispatch_message(*m_machine, message); break; } @@ -161,7 +240,7 @@ void debugger_windows::debugger_update() { HWND const focuswnd = GetFocus(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); + m_machine->debugger().debug_break(); // if we were focused on some window's edit box, reset it to default for (auto &info : m_window_list) @@ -171,6 +250,14 @@ void debugger_windows::debugger_update() } +void debugger_windows::set_color_theme(int index) +{ + m_metrics->set_color_theme(index); + for (auto const &window : m_window_list) + window->redraw(); +} + + bool debugger_windows::seq_pressed() const { input_seq const &seq = m_machine->ioport().type_seq(IPT_UI_DEBUG_BREAK); @@ -222,7 +309,7 @@ bool debugger_windows::seq_pressed() const } -void debugger_windows::remove_window(debugwin_info &info) +void debugger_windows::remove_window(debugger::win::debugwin_info &info) { for (auto it = m_window_list.begin(); it != m_window_list.end(); ++it) if (it->get() == &info) { @@ -241,28 +328,164 @@ void debugger_windows::show_all() void debugger_windows::hide_all() { - SetForegroundWindow(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window()); + SetForegroundWindow(dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window()); for (auto &info : m_window_list) info->hide(); } -template <typename T> T *debugger_windows::create_window() +void debugger_windows::stagger_window(HWND window, int width, int height) +{ + // get width/height for client size + RECT target; + target.left = 0; + target.top = 0; + target.right = width; + target.bottom = height; + if (!AdjustWindowRectEx(&target, GetWindowLong(window, GWL_STYLE), GetMenu(window) ? TRUE : FALSE,GetWindowLong(window, GWL_EXSTYLE))) + { + // really shouldn't end up here, but have to do something + SetWindowPos(window, HWND_TOP, m_next_window_pos.x, m_next_window_pos.y, width, height, SWP_SHOWWINDOW); + return; + } + target.right -= target.left; + target.bottom -= target.top; + target.left = target.top = 0; + + // get the work area for the nearest monitor to the target position + HMONITOR const mon = MonitorFromPoint(m_next_window_pos, MONITOR_DEFAULTTONEAREST); + if (mon) + { + MONITORINFO info; + std::memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + if (GetMonitorInfo(mon, &info)) + { + // restart cascade if necessary + if (((m_next_window_pos.x + target.right) > info.rcWork.right) || ((m_next_window_pos.y + target.bottom) > info.rcWork.bottom)) + { + m_next_window_pos.x = m_window_start_x += 16; + m_next_window_pos.y = info.rcWork.top + 100; + if ((m_next_window_pos.x + target.right) > info.rcWork.right) + m_next_window_pos.x = m_window_start_x = info.rcWork.left + 100; + } + } + } + + // move the window and adjust the next position + MoveWindow(window, m_next_window_pos.x, m_next_window_pos.y, target.right, target.bottom, FALSE); + SetWindowPos(window, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); + m_next_window_pos.x += 16; + m_next_window_pos.y += 16; +} + + +template <typename T> +T *debugger_windows::create_window() { // allocate memory std::unique_ptr<T> info = std::make_unique<T>(static_cast<debugger_windows_interface &>(*this)); if (info->is_valid()) { + T &result(*info); m_window_list.push_back(std::move(info)); - T *ptr = dynamic_cast<T*>(m_window_list.back().get()); - return ptr; + return &result; } return nullptr; } -#else /* not windows */ -MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows") +void debugger_windows::config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode) +{ + if (parentnode) + { + if (config_type::DEFAULT == cfgtype) + { + m_save_windows = 0 != parentnode->get_attribute_int(debugger::ATTR_DEBUGGER_SAVE_WINDOWS, m_save_windows ? 1 : 0); + m_group_windows = m_group_windows_setting = 0 != parentnode->get_attribute_int(debugger::ATTR_DEBUGGER_GROUP_WINDOWS, m_group_windows ? 1 : 0); + util::xml::data_node const *const colors = parentnode->get_child(debugger::NODE_COLORS); + if (colors) + m_metrics->set_color_theme(colors->get_attribute_int(debugger::ATTR_COLORS_THEME, m_metrics->get_color_theme())); + } + else if (config_type::SYSTEM == cfgtype) + { + if (m_main_console) + { + load_configuration(*parentnode); + } + else + { + if (!m_config) + m_config = util::xml::file::create(); + parentnode->copy_into(*m_config); + } + } + } +} + + +void debugger_windows::config_save(config_type cfgtype, util::xml::data_node *parentnode) +{ + if (config_type::DEFAULT == cfgtype) + { + parentnode->set_attribute_int(debugger::ATTR_DEBUGGER_SAVE_WINDOWS, m_save_windows ? 1 : 0); + parentnode->set_attribute_int(debugger::ATTR_DEBUGGER_GROUP_WINDOWS, m_group_windows_setting ? 1 : 0); + util::xml::data_node *const colors = parentnode->add_child(debugger::NODE_COLORS, nullptr); + if (colors) + colors->set_attribute_int(debugger::ATTR_COLORS_THEME, m_metrics->get_color_theme()); + } + else if (m_save_windows && (config_type::SYSTEM == cfgtype)) + { + for (auto &info : m_window_list) + info->save_configuration(*parentnode); + } +} + + +void debugger_windows::load_configuration(util::xml::data_node const &parentnode) +{ + for (util::xml::data_node const *node = parentnode.get_child(debugger::NODE_WINDOW); node; node = node->get_next_sibling(debugger::NODE_WINDOW)) + { + debugger::win::debugwin_info *win = nullptr; + switch (node->get_attribute_int(debugger::ATTR_WINDOW_TYPE, -1)) + { + case debugger::WINDOW_TYPE_CONSOLE: + m_main_console->restore_configuration_from_node(*node); + break; + case debugger::WINDOW_TYPE_MEMORY_VIEWER: + win = create_window<debugger::win::memorywin_info>(); + break; + case debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: + win = create_window<debugger::win::disasmwin_info>(); + break; + case debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: + win = create_window<debugger::win::logwin_info>(); + break; + case debugger::WINDOW_TYPE_POINTS_VIEWER: + win = create_window<debugger::win::pointswin_info>(); + break; + case debugger::WINDOW_TYPE_DEVICES_VIEWER: + // not supported + break; + case debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: + // not supported + break; + default: + break; + } + if (win) + win->restore_configuration_from_node(*node); + } +} + +} // anonymous namespace + +} // namespace osd + +#else // not Windows + +namespace osd { namespace { MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows") } } + #endif -MODULE_DEFINITION(DEBUG_WINDOWS, debugger_windows) +MODULE_DEFINITION(DEBUG_WINDOWS, osd::debugger_windows) diff --git a/src/osd/modules/debugger/none.cpp b/src/osd/modules/debugger/none.cpp index 3ce8d6572bc..61bd1bbbd3e 100644 --- a/src/osd/modules/debugger/none.cpp +++ b/src/osd/modules/debugger/none.cpp @@ -8,23 +8,28 @@ #include "emu.h" #include "debug_module.h" -#include "modules/osdmodule.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" #include "debugger.h" + +namespace osd { + +namespace { + class debug_none : public osd_module, public debug_module { public: - debug_none() - : osd_module(OSD_DEBUG_PROVIDER, "none"), debug_module(), + debug_none() : + osd_module(OSD_DEBUG_PROVIDER, "none"), debug_module(), m_machine(nullptr) { } virtual ~debug_none() { } - virtual int init(const osd_options &options) override { return 0; } + virtual int init(osd_interface &osd, const osd_options &options) override { return 0; } virtual void exit() override { } virtual void init_debugger(running_machine &machine) override; @@ -42,11 +47,15 @@ void debug_none::init_debugger(running_machine &machine) void debug_none::wait_for_debugger(device_t &device, bool firststop) { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine->debugger().console().get_visible_cpu()->debug()->go(); } void debug_none::debugger_update() { } -MODULE_DEFINITION(DEBUG_NONE, debug_none) +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(DEBUG_NONE, osd::debug_none) diff --git a/src/osd/modules/debugger/osx/debugcommandhistory.h b/src/osd/modules/debugger/osx/debugcommandhistory.h index f99767cb4be..e505aa4435c 100644 --- a/src/osd/modules/debugger/osx/debugcommandhistory.h +++ b/src/osd/modules/debugger/osx/debugcommandhistory.h @@ -8,6 +8,8 @@ #import "debugosx.h" +#include "util/utilfwd.h" + #import <Cocoa/Cocoa.h> @@ -32,4 +34,7 @@ - (void)reset; - (void)clear; +- (void)saveConfigurationToNode:(util::xml::data_node *)node; +- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node; + @end diff --git a/src/osd/modules/debugger/osx/debugcommandhistory.mm b/src/osd/modules/debugger/osx/debugcommandhistory.mm index 74a34904ae7..e2292f973b0 100644 --- a/src/osd/modules/debugger/osx/debugcommandhistory.mm +++ b/src/osd/modules/debugger/osx/debugcommandhistory.mm @@ -12,6 +12,8 @@ #import "debugcommandhistory.h" +#include "util/xmlfile.h" + @implementation MAMEDebugCommandHistory @@ -54,9 +56,9 @@ - (void)add:(NSString *)entry { if (([history count] == 0) || ![[history objectAtIndex:0] isEqualToString:entry]) { - [history insertObject:entry atIndex:0]; - while ([history count] > length) + while ([history count] >= length) [history removeLastObject]; + [history insertObject:entry atIndex:0]; } position = 0; } @@ -110,4 +112,30 @@ [history removeAllObjects]; } + +- (void)saveConfigurationToNode:(util::xml::data_node *)node { + util::xml::data_node *const hist = node->add_child(osd::debugger::NODE_WINDOW_HISTORY, nullptr); + if (hist) { + for (NSInteger i = [history count]; 0 < i; --i) + hist->add_child(osd::debugger::NODE_HISTORY_ITEM, [[history objectAtIndex:(i - 1)] UTF8String]); + } +} + + +- (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { + [self clear]; + util::xml::data_node const *const hist = node->get_child(osd::debugger::NODE_WINDOW_HISTORY); + if (hist) { + util::xml::data_node const *item = hist->get_child(osd::debugger::NODE_HISTORY_ITEM); + while (item) { + if (item->get_value() && *item->get_value()) { + while ([history count] >= length) + [history removeLastObject]; + [history insertObject:[NSString stringWithUTF8String:item->get_value()] atIndex:0]; + } + item = item->get_next_sibling(osd::debugger::NODE_HISTORY_ITEM); + } + } +} + @end diff --git a/src/osd/modules/debugger/osx/debugconsole.mm b/src/osd/modules/debugger/osx/debugconsole.mm index 1bd285e8c3b..9673dc852ab 100644 --- a/src/osd/modules/debugger/osx/debugconsole.mm +++ b/src/osd/modules/debugger/osx/debugconsole.mm @@ -24,6 +24,7 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "util/xmlfile.h" @@ -141,19 +142,25 @@ NSRect const available = [[NSScreen mainScreen] visibleFrame]; NSSize const regCurrent = [regScroll frame].size; NSSize const regSize = [NSScrollView frameSizeForContentSize:[regView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[regScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[regScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; NSSize const dasmCurrent = [dasmScroll frame].size; NSSize const dasmSize = [NSScrollView frameSizeForContentSize:[dasmView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[dasmScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[dasmScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; NSSize const consoleCurrent = [consoleContainer frame].size; NSSize consoleSize = [NSScrollView frameSizeForContentSize:[consoleView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[consoleScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[consoleScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; NSRect windowFrame = [window frame]; NSSize adjustment; @@ -181,7 +188,7 @@ [dasmSplit setFrame:rhsFrame]; // select the current processor - [self setCPU:machine->debugger().cpu().get_visible_cpu()]; + [self setCPU:machine->debugger().console().get_visible_cpu()]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(auxiliaryWindowWillClose:) @@ -219,7 +226,7 @@ NSString *command = [sender stringValue]; if ([command length] == 0) { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine->debugger().console().get_visible_cpu()->debug()->single_step(); [history reset]; } else @@ -234,10 +241,10 @@ - (IBAction)debugToggleBreakpoint:(id)sender { device_t &device = *[dasmView source]->device(); - if ([dasmView cursorVisible] && (machine->debugger().cpu().get_visible_cpu() == &device)) + if ([dasmView cursorVisible] && (machine->debugger().console().get_visible_cpu() == &device)) { offs_t const address = [dasmView selectedAddress]; - const device_debug::breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find(address); + const debug_breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find(address); // if it doesn't exist, add a new one NSString *command; @@ -252,9 +259,9 @@ - (IBAction)debugToggleBreakpointEnable:(id)sender { device_t &device = *[dasmView source]->device(); - if ([dasmView cursorVisible] && (machine->debugger().cpu().get_visible_cpu() == &device)) + if ([dasmView cursorVisible] && (machine->debugger().console().get_visible_cpu() == &device)) { - const device_debug::breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); + const debug_breakpoint *bp = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); if (bp != nullptr) { NSString *command; @@ -270,7 +277,7 @@ - (IBAction)debugRunToCursor:(id)sender { device_t &device = *[dasmView source]->device(); - if ([dasmView cursorVisible] && (machine->debugger().cpu().get_visible_cpu() == &device)) + if ([dasmView cursorVisible] && (machine->debugger().console().get_visible_cpu() == &device)) { NSString *command = [NSString stringWithFormat:@"go 0x%lX", (unsigned long)[dasmView selectedAddress]]; machine->debugger().console().execute_command([command UTF8String], 1); @@ -379,32 +386,35 @@ - (void)loadConfiguration:(util::xml::data_node const *)parentnode { util::xml::data_node const *node = nullptr; - for (node = parentnode->get_child("window"); node; node = node->get_next_sibling("window")) + for (node = parentnode->get_child(osd::debugger::NODE_WINDOW); node; node = node->get_next_sibling(osd::debugger::NODE_WINDOW)) { MAMEDebugWindowHandler *win = nil; - switch (node->get_attribute_int("type", -1)) + switch (node->get_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, -1)) { - case MAME_DEBUGGER_WINDOW_TYPE_CONSOLE: + case osd::debugger::WINDOW_TYPE_CONSOLE: [self restoreConfigurationFromNode:node]; break; - case MAME_DEBUGGER_WINDOW_TYPE_MEMORY_VIEWER: + case osd::debugger::WINDOW_TYPE_MEMORY_VIEWER: win = [[MAMEMemoryViewer alloc] initWithMachine:*machine console:self]; break; - case MAME_DEBUGGER_WINDOW_TYPE_DISASSEMBLY_VIEWER: + case osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: win = [[MAMEDisassemblyViewer alloc] initWithMachine:*machine console:self]; break; - case MAME_DEBUGGER_WINDOW_TYPE_ERROR_LOG_VIEWER: + case osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: win = [[MAMEErrorLogViewer alloc] initWithMachine:*machine console:self]; break; - case MAME_DEBUGGER_WINDOW_TYPE_POINTS_VIEWER: + case osd::debugger::WINDOW_TYPE_POINTS_VIEWER: win = [[MAMEPointsViewer alloc] initWithMachine:*machine console:self]; break; - case MAME_DEBUGGER_WINDOW_TYPE_DEVICES_VIEWER: + case osd::debugger::WINDOW_TYPE_DEVICES_VIEWER: win = [[MAMEDevicesViewer alloc] initWithMachine:*machine console:self]; break; - case MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER: - // FIXME: needs device info on init, make another variant - //win = [[MAMEDeviceInfoViewer alloc] initWithMachine:*machine console:self]; + case osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: + { + // FIXME: feels like a leaky abstraction, but device is needed for init + device_t *const device = machine->root_device().subdevice(node->get_attribute_string(osd::debugger::ATTR_WINDOW_DEVICE_TAG, ":")); + win = [[MAMEDeviceInfoViewer alloc] initWithDevice:(device ? *device : machine->root_device()) machine:*machine console:self]; + } break; default: break; @@ -422,34 +432,36 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_CONSOLE); - util::xml::data_node *const splits = node->add_child("splits", nullptr); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_CONSOLE); + util::xml::data_node *const splits = node->add_child(osd::debugger::NODE_WINDOW_SPLITS, nullptr); if (splits) { - splits->set_attribute_float("state", + splits->set_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_STATE, [regSplit isSubviewCollapsed:[[regSplit subviews] objectAtIndex:0]] ? 0.0 : NSMaxX([[[regSplit subviews] objectAtIndex:0] frame])); - splits->set_attribute_float("disassembly", + splits->set_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_DISASSEMBLY, [dasmSplit isSubviewCollapsed:[[dasmSplit subviews] objectAtIndex:0]] ? 0.0 : NSMaxY([[[dasmSplit subviews] objectAtIndex:0] frame])); } [dasmView saveConfigurationToNode:node]; + [history saveConfigurationToNode:node]; } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; - util::xml::data_node const *const splits = node->get_child("splits"); + util::xml::data_node const *const splits = node->get_child(osd::debugger::NODE_WINDOW_SPLITS); if (splits) { - [regSplit setPosition:splits->get_attribute_float("state", NSMaxX([[[regSplit subviews] objectAtIndex:0] frame])) + [regSplit setPosition:splits->get_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_STATE, NSMaxX([[[regSplit subviews] objectAtIndex:0] frame])) ofDividerAtIndex:0]; - [dasmSplit setPosition:splits->get_attribute_float("disassembly", NSMaxY([[[dasmSplit subviews] objectAtIndex:0] frame])) + [dasmSplit setPosition:splits->get_attribute_float(osd::debugger::ATTR_SPLITS_CONSOLE_DISASSEMBLY, NSMaxY([[[dasmSplit subviews] objectAtIndex:0] frame])) ofDividerAtIndex:0]; } [dasmView restoreConfigurationFromNode:node]; + [history restoreConfigurationFromNode:node]; } @@ -499,7 +511,7 @@ [[NSNotificationCenter defaultCenter] postNotificationName:MAMEHideDebuggerNotification object:self userInfo:info]; - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } } @@ -562,9 +574,9 @@ SEL const action = [item action]; BOOL const inContextMenu = ([item menu] == [dasmView menu]); BOOL const haveCursor = [dasmView cursorVisible]; - BOOL const isCurrent = (machine->debugger().cpu().get_visible_cpu() == [dasmView source]->device()); + BOOL const isCurrent = (machine->debugger().console().get_visible_cpu() == [dasmView source]->device()); - const device_debug::breakpoint *breakpoint = nullptr; + const debug_breakpoint *breakpoint = nullptr; if (haveCursor) { breakpoint = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); diff --git a/src/osd/modules/debugger/osx/debugosx.h b/src/osd/modules/debugger/osx/debugosx.h index 9d48402c032..6e0a47089d9 100644 --- a/src/osd/modules/debugger/osx/debugosx.h +++ b/src/osd/modules/debugger/osx/debugosx.h @@ -6,8 +6,13 @@ // //============================================================ -#ifndef __SDL_DEBUGOSX__ -#define __SDL_DEBUGOSX__ +#ifndef MAME_OSD_DEBUGGER_OSX_DEBUGOSX_H +#define MAME_OSD_DEBUGGER_OSX_DEBUGOSX_H + +#pragma once + +#include "../xmlconfig.h" + #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 @@ -20,30 +25,6 @@ // standard Cocoa headers #import <Cocoa/Cocoa.h> -// workarounds for 10.6 warnings -#ifdef MAC_OS_X_VERSION_MAX_ALLOWED - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 - -@protocol NSWindowDelegate <NSObject> -@end - -@protocol NSSplitViewDelegate <NSObject> -@end - -@protocol NSControlTextEditingDelegate <NSObject> -@end - -@protocol NSTextFieldDelegate <NSControlTextEditingDelegate> -@end - -@protocol NSOutlineViewDataSource <NSObject> -@end - -#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1060 - -#endif // MAC_OS_X_VERSION_MAX_ALLOWED - #endif // __OBJC__ -#endif // __SDL_DEBUGOSX__ +#endif // MAME_OSD_DEBUGGER_OSX_DEBUGOSX_H diff --git a/src/osd/modules/debugger/osx/debugview.mm b/src/osd/modules/debugger/osx/debugview.mm index f3e4c6b8b64..504eaab8fe3 100644 --- a/src/osd/modules/debugger/osx/debugview.mm +++ b/src/osd/modules/debugger/osx/debugview.mm @@ -10,13 +10,14 @@ #include "emu.h" #include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" #include "modules/lib/osdobj_common.h" #include "util/xmlfile.h" -#include <string.h> +#include <cstring> static NSColor *DefaultForeground; @@ -50,6 +51,26 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) @implementation MAMEDebugView + (void)initialize { + // 10.15 and better get full adaptive Dark Mode support +#if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15 + DefaultForeground = [[NSColor textColor] retain]; + ChangedForeground = [[NSColor systemRedColor] retain]; + CommentForeground = [[NSColor systemGreenColor] retain]; + // DCA_INVALID and DCA_DISABLED currently are not set by the core, so these 4 are unused + InvalidForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:1.0] retain]; + DisabledChangedForeground = [[NSColor colorWithCalibratedRed:0.5 green:0.125 blue:0.125 alpha:1.0] retain]; + DisabledInvalidForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.5 alpha:1.0] retain]; + DisabledCommentForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.25 blue:0.0 alpha:1.0] retain]; + + DefaultBackground = [[NSColor textBackgroundColor] retain]; + VisitedBackground = [[NSColor systemTealColor] retain]; + AncillaryBackground = [[NSColor unemphasizedSelectedContentBackgroundColor] retain]; + SelectedBackground = [[NSColor selectedContentBackgroundColor] retain]; + CurrentBackground = [[NSColor selectedControlColor] retain]; + SelectedCurrentBackground = [[NSColor unemphasizedSelectedContentBackgroundColor] retain]; + InactiveSelectedBackground = [[NSColor unemphasizedSelectedContentBackgroundColor] retain]; + InactiveSelectedCurrentBackground = [[NSColor systemGrayColor] retain]; +#else DefaultForeground = [[NSColor colorWithCalibratedWhite:0.0 alpha:1.0] retain]; ChangedForeground = [[NSColor colorWithCalibratedRed:0.875 green:0.0 blue:0.0 alpha:1.0] retain]; InvalidForeground = [[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:1.0] retain]; @@ -66,6 +87,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) SelectedCurrentBackground = [[NSColor colorWithCalibratedRed:0.875 green:0.625 blue:0.875 alpha:1.0] retain]; InactiveSelectedBackground = [[NSColor colorWithCalibratedWhite:0.875 alpha:1.0] retain]; InactiveSelectedCurrentBackground = [[NSColor colorWithCalibratedRed:0.875 green:0.5 blue:0.625 alpha:1.0] retain]; +#endif NonWhiteCharacters = [[[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet] retain]; } @@ -255,7 +277,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) [self setFont:[[self class] defaultFontForMachine:m]]; - NSMenu *contextMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Context"]; + NSMenu *contextMenu = [[NSMenu alloc] initWithTitle:@"Context"]; [self addContextMenuItemsToMenu:contextMenu]; [self setMenu:contextMenu]; [contextMenu release]; @@ -410,15 +432,15 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) NSRange const run = NSMakeRange(0, [text length]); [text addAttribute:NSFontAttributeName value:font range:run]; NSPasteboard *const board = [NSPasteboard generalPasteboard]; - [board declareTypes:[NSArray arrayWithObject:NSRTFPboardType] owner:nil]; - [board setData:[text RTFFromRange:run documentAttributes:[NSDictionary dictionary]] forType:NSRTFPboardType]; + [board declareTypes:[NSArray arrayWithObject:NSPasteboardTypeRTF] owner:nil]; + [board setData:[text RTFFromRange:run documentAttributes:[NSDictionary dictionary]] forType:NSPasteboardTypeRTF]; [text deleteCharactersInRange:run]; } - (IBAction)paste:(id)sender { NSPasteboard *const board = [NSPasteboard generalPasteboard]; - NSString *const avail = [board availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]; + NSString *const avail = [board availableTypeFromArray:[NSArray arrayWithObject:NSPasteboardTypeString]]; if (avail == nil) { NSBeep(); @@ -492,22 +514,22 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) - (void)saveConfigurationToNode:(util::xml::data_node *)node { if (view->cursor_supported()) { - util::xml::data_node *const selection = node->add_child("selection", nullptr); + util::xml::data_node *const selection = node->add_child(osd::debugger::NODE_WINDOW_SELECTION, nullptr); if (selection) { debug_view_xy const pos = view->cursor_position(); - selection->set_attribute_int("visible", view->cursor_visible() ? 1 : 0); - selection->set_attribute_int("start_x", pos.x); - selection->set_attribute_int("start_y", pos.y); + selection->set_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_VISIBLE, view->cursor_visible() ? 1 : 0); + selection->set_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_X, pos.x); + selection->set_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_Y, pos.y); } } - util::xml::data_node *const scroll = node->add_child("scroll", nullptr); + util::xml::data_node *const scroll = node->add_child(osd::debugger::NODE_WINDOW_SCROLL, nullptr); if (scroll) { NSRect const visible = [self visibleRect]; - scroll->set_attribute_float("position_x", visible.origin.x); - scroll->set_attribute_float("position_y", visible.origin.y); + scroll->set_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_X, visible.origin.x); + scroll->set_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_Y, visible.origin.y); } } @@ -515,23 +537,23 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { if (view->cursor_supported()) { - util::xml::data_node const *const selection = node->get_child("selection"); + util::xml::data_node const *const selection = node->get_child(osd::debugger::NODE_WINDOW_SELECTION); if (selection) { debug_view_xy pos = view->cursor_position(); - view->set_cursor_visible(0 != selection->get_attribute_int("visible", view->cursor_visible() ? 1 : 0)); - pos.x = selection->get_attribute_int("start_x", pos.x); - pos.y = selection->get_attribute_int("start_y", pos.y); + view->set_cursor_visible(0 != selection->get_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_VISIBLE, view->cursor_visible() ? 1 : 0)); + pos.x = selection->get_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_X, pos.x); + pos.y = selection->get_attribute_int(osd::debugger::ATTR_SELECTION_CURSOR_Y, pos.y); view->set_cursor_position(pos); } } - util::xml::data_node const *const scroll = node->get_child("scroll"); + util::xml::data_node const *const scroll = node->get_child(osd::debugger::NODE_WINDOW_SCROLL); if (scroll) { NSRect visible = [self visibleRect]; - visible.origin.x = scroll->get_attribute_float("position_x", visible.origin.x); - visible.origin.y = scroll->get_attribute_float("position_y", visible.origin.y); + visible.origin.x = scroll->get_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_X, visible.origin.x); + visible.origin.y = scroll->get_attribute_float(osd::debugger::ATTR_SCROLL_ORIGIN_Y, visible.origin.y); [self scrollRectToVisible:visible]; } } @@ -674,7 +696,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) NSUInteger start = 0, length = 0; for (uint32_t col = origin.x; col < origin.x + size.x; col++) { - [[text mutableString] appendFormat:@"%c", data[col - origin.x].byte]; + [[text mutableString] appendFormat:@"%C", unichar(data[col - origin.x].byte)]; if ((start < length) && (attr != data[col - origin.x].attrib)) { NSRange const run = NSMakeRange(start, length - start); @@ -742,8 +764,8 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) - (void)mouseDown:(NSEvent *)event { NSPoint const location = [self convertPoint:[event locationInWindow] fromView:nil]; NSUInteger const modifiers = [event modifierFlags]; - view->process_click(((modifiers & NSCommandKeyMask) && [[self window] isMainWindow]) ? DCK_RIGHT_CLICK - : (modifiers & NSAlternateKeyMask) ? DCK_MIDDLE_CLICK + view->process_click(((modifiers & NSEventModifierFlagCommand) && [[self window] isMainWindow]) ? DCK_RIGHT_CLICK + : (modifiers & NSEventModifierFlagOption) ? DCK_MIDDLE_CLICK : DCK_LEFT_CLICK, [self convertLocation:location]); } @@ -754,8 +776,8 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) NSPoint const location = [self convertPoint:[event locationInWindow] fromView:nil]; NSUInteger const modifiers = [event modifierFlags]; if (view->cursor_supported() - && !(modifiers & NSAlternateKeyMask) - && (!(modifiers & NSCommandKeyMask) || ![[self window] isMainWindow])) + && !(modifiers & NSEventModifierFlagOption) + && (!(modifiers & NSEventModifierFlagCommand) || ![[self window] isMainWindow])) { view->set_cursor_position([self convertLocation:location]); view->set_cursor_visible(true); @@ -782,34 +804,34 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) if ([str length] == 1) { - if (modifiers & NSNumericPadKeyMask) + if (modifiers & NSEventModifierFlagNumericPad) { switch ([str characterAtIndex:0]) { case NSUpArrowFunctionKey: - if (modifiers & NSCommandKeyMask) + if (modifiers & NSEventModifierFlagCommand) view->process_char(DCH_CTRLHOME); else view->process_char(DCH_UP); return; case NSDownArrowFunctionKey: - if (modifiers & NSCommandKeyMask) + if (modifiers & NSEventModifierFlagCommand) view->process_char(DCH_CTRLEND); else view->process_char(DCH_DOWN); return; case NSLeftArrowFunctionKey: - if (modifiers & NSCommandKeyMask) + if (modifiers & NSEventModifierFlagCommand) [self typeCharacterAndScrollToCursor:DCH_HOME]; - else if (modifiers & NSAlternateKeyMask) + else if (modifiers & NSEventModifierFlagOption) [self typeCharacterAndScrollToCursor:DCH_CTRLLEFT]; else [self typeCharacterAndScrollToCursor:DCH_LEFT]; return; case NSRightArrowFunctionKey: - if (modifiers & NSCommandKeyMask) + if (modifiers & NSEventModifierFlagCommand) [self typeCharacterAndScrollToCursor:DCH_END]; - else if (modifiers & NSAlternateKeyMask) + else if (modifiers & NSEventModifierFlagOption) [self typeCharacterAndScrollToCursor:DCH_CTRLRIGHT]; else [self typeCharacterAndScrollToCursor:DCH_RIGHT]; @@ -819,18 +841,18 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) return; } } - else if (modifiers & NSFunctionKeyMask) + else if (modifiers & NSEventModifierFlagFunction) { switch ([str characterAtIndex:0]) { case NSPageUpFunctionKey: - if (modifiers & NSAlternateKeyMask) + if (modifiers & NSEventModifierFlagOption) { view->process_char(DCH_PUP); return; } case NSPageDownFunctionKey: - if (modifiers & NSAlternateKeyMask) + if (modifiers & NSEventModifierFlagOption) { view->process_char(DCH_PDOWN); return; @@ -871,7 +893,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) - (void)insertNewline:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine->debugger().console().get_visible_cpu()->debug()->single_step(); } @@ -899,7 +921,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) if (action == @selector(paste:)) { NSPasteboard *const board = [NSPasteboard generalPasteboard]; - return [board availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] != nil; + return [board availableTypeFromArray:[NSArray arrayWithObject:NSPasteboardTypeString]] != nil; } else { diff --git a/src/osd/modules/debugger/osx/debugwindowhandler.h b/src/osd/modules/debugger/osx/debugwindowhandler.h index c48bbb031b2..00c7327f2ba 100644 --- a/src/osd/modules/debugger/osx/debugwindowhandler.h +++ b/src/osd/modules/debugger/osx/debugwindowhandler.h @@ -23,19 +23,6 @@ extern NSString *const MAMEAuxiliaryDebugWindowWillCloseNotification; extern NSString *const MAMESaveDebuggerConfigurationNotification; -// for compatibility with the Qt debugger -enum -{ - MAME_DEBUGGER_WINDOW_TYPE_CONSOLE = 1, - MAME_DEBUGGER_WINDOW_TYPE_MEMORY_VIEWER, - MAME_DEBUGGER_WINDOW_TYPE_DISASSEMBLY_VIEWER, - MAME_DEBUGGER_WINDOW_TYPE_ERROR_LOG_VIEWER, - MAME_DEBUGGER_WINDOW_TYPE_POINTS_VIEWER, - MAME_DEBUGGER_WINDOW_TYPE_DEVICES_VIEWER, - MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER -}; - - @interface MAMEDebugWindowHandler : NSObject <NSWindowDelegate> { NSWindow *window; diff --git a/src/osd/modules/debugger/osx/debugwindowhandler.mm b/src/osd/modules/debugger/osx/debugwindowhandler.mm index 27d487c86ff..1341f420ed9 100644 --- a/src/osd/modules/debugger/osx/debugwindowhandler.mm +++ b/src/osd/modules/debugger/osx/debugwindowhandler.mm @@ -14,6 +14,7 @@ #import "debugview.h" #include "debugger.h" +#include "debug/debugcon.h" #include "util/xmlfile.h" @@ -42,7 +43,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo NSMenuItem *runParentItem = [menu addItemWithTitle:@"Run" action:@selector(debugRun:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF5FunctionKey]]; - NSMenu *runMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Run"]; + NSMenu *runMenu = [[NSMenu alloc] initWithTitle:@"Run"]; [runParentItem setSubmenu:runMenu]; [runMenu release]; [runParentItem setKeyEquivalentModifierMask:0]; @@ -64,7 +65,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo setKeyEquivalentModifierMask:0]; NSMenuItem *stepParentItem = [menu addItemWithTitle:@"Step" action:NULL keyEquivalent:@""]; - NSMenu *stepMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Step"]; + NSMenu *stepMenu = [[NSMenu alloc] initWithTitle:@"Step"]; [stepParentItem setSubmenu:stepMenu]; [stepMenu release]; [[stepMenu addItemWithTitle:@"Into" @@ -78,10 +79,10 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo [[stepMenu addItemWithTitle:@"Out" action:@selector(debugStepOut:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF10FunctionKey]] - setKeyEquivalentModifierMask:NSShiftKeyMask]; + setKeyEquivalentModifierMask:NSEventModifierFlagShift]; NSMenuItem *resetParentItem = [menu addItemWithTitle:@"Reset" action:NULL keyEquivalent:@""]; - NSMenu *resetMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Reset"]; + NSMenu *resetMenu = [[NSMenu alloc] initWithTitle:@"Reset"]; [resetParentItem setSubmenu:resetMenu]; [resetMenu release]; [[resetMenu addItemWithTitle:@"Soft" @@ -91,12 +92,12 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo [[resetMenu addItemWithTitle:@"Hard" action:@selector(debugHardReset:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF3FunctionKey]] - setKeyEquivalentModifierMask:NSShiftKeyMask]; + setKeyEquivalentModifierMask:NSEventModifierFlagShift]; [menu addItem:[NSMenuItem separatorItem]]; NSMenuItem *newParentItem = [menu addItemWithTitle:@"New" action:NULL keyEquivalent:@""]; - NSMenu *newMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"New"]; + NSMenu *newMenu = [[NSMenu alloc] initWithTitle:@"New"]; [newParentItem setSubmenu:newMenu]; [newMenu release]; [newMenu addItemWithTitle:@"Memory Window" @@ -113,7 +114,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo keyEquivalent:@"b"]; [newMenu addItemWithTitle:@"Devices Window" action:@selector(debugNewDevicesWindow:) - keyEquivalent:@"D"]; + keyEquivalent:@""]; [menu addItem:[NSMenuItem separatorItem]]; @@ -126,7 +127,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo NSPopUpButton *actionButton = [[NSPopUpButton alloc] initWithFrame:frame pullsDown:YES]; [actionButton setTitle:@""]; [actionButton addItemWithTitle:@""]; - [actionButton setBezelStyle:NSShadowlessSquareBezelStyle]; + [actionButton setBezelStyle:NSBezelStyleShadowlessSquare]; [actionButton setFocusRingType:NSFocusRingTypeNone]; [[actionButton cell] setArrowPosition:NSPopUpArrowAtCenter]; [[self class] addCommonActionItems:[actionButton menu]]; @@ -139,10 +140,10 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo return nil; window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 320, 240) - styleMask:(NSTitledWindowMask | - NSClosableWindowMask | - NSMiniaturizableWindowMask | - NSResizableWindowMask) + styleMask:(NSWindowStyleMaskTitled | + NSWindowStyleMaskClosable | + NSWindowStyleMaskMiniaturizable | + NSWindowStyleMaskResizable) backing:NSBackingStoreBuffered defer:YES]; [window setReleasedWhenClosed:NO]; @@ -189,12 +190,12 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo - (IBAction)debugBreak:(id)sender { if (machine->debug_flags & DEBUG_FLAG_ENABLED) - machine->debugger().cpu().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); + machine->debugger().console().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); } - (IBAction)debugRun:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } @@ -203,43 +204,43 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo object:self userInfo:[NSDictionary dictionaryWithObject:[NSValue valueWithPointer:machine] forKey:@"MAMEDebugMachine"]]; - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } - (IBAction)debugRunToNextCPU:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + machine->debugger().console().get_visible_cpu()->debug()->go_next_device(); } - (IBAction)debugRunToNextInterrupt:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + machine->debugger().console().get_visible_cpu()->debug()->go_interrupt(); } - (IBAction)debugRunToNextVBLANK:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + machine->debugger().console().get_visible_cpu()->debug()->go_vblank(); } - (IBAction)debugStepInto:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine->debugger().console().get_visible_cpu()->debug()->single_step(); } - (IBAction)debugStepOver:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + machine->debugger().console().get_visible_cpu()->debug()->single_step_over(); } - (IBAction)debugStepOut:(id)sender { - machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + machine->debugger().console().get_visible_cpu()->debug()->single_step_out(); } - (IBAction)debugSoftReset:(id)sender { machine->schedule_soft_reset(); - machine->debugger().cpu().get_visible_cpu()->debug()->go(); + machine->debugger().console().get_visible_cpu()->debug()->go(); } @@ -275,7 +276,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo if (m == machine) { util::xml::data_node *parentnode = (util::xml::data_node *)[[[notification userInfo] objectForKey:@"MAMEDebugParentNode"] pointerValue]; - util::xml::data_node *node = parentnode->add_child("window", nullptr); + util::xml::data_node *node = parentnode->add_child(osd::debugger::NODE_WINDOW, nullptr); if (node) [self saveConfigurationToNode:node]; } @@ -284,19 +285,19 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo - (void)saveConfigurationToNode:(util::xml::data_node *)node { NSRect frame = [window frame]; - node->set_attribute_float("position_x", frame.origin.x); - node->set_attribute_float("position_y", frame.origin.y); - node->set_attribute_float("size_x", frame.size.width); - node->set_attribute_float("size_y", frame.size.height); + node->set_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_X, frame.origin.x); + node->set_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_Y, frame.origin.y); + node->set_attribute_float(osd::debugger::ATTR_WINDOW_WIDTH, frame.size.width); + node->set_attribute_float(osd::debugger::ATTR_WINDOW_HEIGHT, frame.size.height); } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { NSRect frame = [window frame]; - frame.origin.x = node->get_attribute_float("position_x", frame.origin.x); - frame.origin.y = node->get_attribute_float("position_y", frame.origin.y); - frame.size.width = node->get_attribute_float("size_x", frame.size.width); - frame.size.height = node->get_attribute_float("size_y", frame.size.height); + frame.origin.x = node->get_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_X, frame.origin.x); + frame.origin.y = node->get_attribute_float(osd::debugger::ATTR_WINDOW_POSITION_Y, frame.origin.y); + frame.size.width = node->get_attribute_float(osd::debugger::ATTR_WINDOW_WIDTH, frame.size.width); + frame.size.height = node->get_attribute_float(osd::debugger::ATTR_WINDOW_HEIGHT, frame.size.height); NSSize min = [window minSize]; frame.size.width = std::max(frame.size.width, min.width); @@ -492,15 +493,17 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->add_child("expression", util::xml::normalize_string([[self expression] UTF8String])); + node->add_child(osd::debugger::NODE_WINDOW_EXPRESSION, [[self expression] UTF8String]); + [history saveConfigurationToNode:node]; } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; - util::xml::data_node const *const expr = node->get_child("expression"); + util::xml::data_node const *const expr = node->get_child(osd::debugger::NODE_WINDOW_EXPRESSION); if (expr && expr->get_value()) [self setExpression:[NSString stringWithUTF8String:expr->get_value()]]; + [history restoreConfigurationFromNode:node]; } @end diff --git a/src/osd/modules/debugger/osx/deviceinfoviewer.mm b/src/osd/modules/debugger/osx/deviceinfoviewer.mm index 61fdd8c8613..12f1ea1957a 100644 --- a/src/osd/modules/debugger/osx/deviceinfoviewer.mm +++ b/src/osd/modules/debugger/osx/deviceinfoviewer.mm @@ -54,14 +54,14 @@ - (NSTextField *)makeLabel:(NSString *)text { NSTextField *const result = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 14)]; [result setAutoresizingMask:(NSViewMaxYMargin | NSViewMaxXMargin)]; - [[result cell] setControlSize:NSSmallControlSize]; + [[result cell] setControlSize:NSControlSizeSmall]; [result setEditable:NO]; [result setSelectable:NO]; [result setBezeled:NO]; [result setBordered:NO]; [result setDrawsBackground:NO]; - [result setAlignment:NSRightTextAlignment]; - [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; + [result setAlignment:NSTextAlignmentRight]; + [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeSmall]]]; [result setStringValue:text]; [result sizeToFit]; return result; @@ -71,14 +71,14 @@ - (NSTextField *)makeField:(NSString *)text { NSTextField *const result = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 14)]; [result setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)]; - [[result cell] setControlSize:NSSmallControlSize]; + [[result cell] setControlSize:NSControlSizeSmall]; [result setEditable:NO]; [result setSelectable:YES]; [result setBezeled:NO]; [result setBordered:NO]; [result setDrawsBackground:NO]; - [result setAlignment:NSLeftTextAlignment]; - [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; + [result setAlignment:NSTextAlignmentLeft]; + [result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeSmall]]]; [result setStringValue:text]; [result sizeToFit]; return result; @@ -210,9 +210,11 @@ // create a scroll view for holding everything NSSize desired = [NSScrollView frameSizeForContentSize:[contentView frame].size - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:NSNoBorder]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:NSNoBorder + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; [window setContentSize:desired]; contentScroll = [[NSScrollView alloc] initWithFrame:[[window contentView] bounds]]; [contentScroll setDrawsBackground:NO]; @@ -237,7 +239,8 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER); + node->set_attribute(osd::debugger::ATTR_WINDOW_DEVICE_TAG, device->tag()); } @end diff --git a/src/osd/modules/debugger/osx/devicesviewer.mm b/src/osd/modules/debugger/osx/devicesviewer.mm index 23dba724b9d..02f63a41a6b 100644 --- a/src/osd/modules/debugger/osx/devicesviewer.mm +++ b/src/osd/modules/debugger/osx/devicesviewer.mm @@ -161,9 +161,11 @@ // calculate the optimal size for everything NSSize const desired = [NSScrollView frameSizeForContentSize:NSMakeSize(480, 320) - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[devicesScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[devicesScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; [self cascadeWindowWithDesiredSize:desired forView:devicesScroll]; // don't forget the result @@ -185,7 +187,7 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DEVICES_VIEWER); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_DEVICES_VIEWER); } diff --git a/src/osd/modules/debugger/osx/disassemblyview.mm b/src/osd/modules/debugger/osx/disassemblyview.mm index 99bdc485147..c501d17230a 100644 --- a/src/osd/modules/debugger/osx/disassemblyview.mm +++ b/src/osd/modules/debugger/osx/disassemblyview.mm @@ -46,7 +46,7 @@ - (NSSize)maximumFrameSize { debug_view_xy max(0, 0); debug_view_source const *source = view->source(); - for (debug_view_source const *source = view->first_source(); source != nullptr; source = source->next()) + for (auto &source : view->source_list()) { view->set_source(*source); debug_view_xy const current = view->total_size(); @@ -75,7 +75,7 @@ item = [menu addItemWithTitle:@"Disable Breakpoint" action:@selector(debugToggleBreakpointEnable:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF9FunctionKey]]; - [item setKeyEquivalentModifierMask:NSShiftKeyMask]; + [item setKeyEquivalentModifierMask:NSEventModifierFlagShift]; [menu addItem:[NSMenuItem separatorItem]]; @@ -118,18 +118,23 @@ - (int)selectedSubviewIndex { const debug_view_source *source = view->source(); if (source != nullptr) - return view->source_list().indexof(*source); + return view->source_index(*source); else return -1; } - (void)selectSubviewAtIndex:(int)index { - const int selected = view->source_list().indexof(*view->source()); - if (selected != index) { - view->set_source(*view->source_list().find(index)); - if ([[self window] firstResponder] != self) - view->set_cursor_visible(false); + const int selected = [self selectedSubviewIndex]; + if (selected != index) + { + const debug_view_source *source = view->source(index); + if (source != nullptr) + { + view->set_source(*source); + if ([[self window] firstResponder] != self) + view->set_cursor_visible(false); + } } } @@ -155,23 +160,21 @@ - (BOOL)selectSubviewForSpace:(address_space *)space { if (space == nullptr) return NO; - debug_view_disasm_source const *source = downcast<debug_view_disasm_source const *>(view->first_source()); - while ((source != nullptr) && (&source->space() != space)) - source = downcast<debug_view_disasm_source *>(source->next()); - if (source != nullptr) + for (auto &ptr : view->source_list()) { - if (view->source() != source) + debug_view_disasm_source const *const source = downcast<debug_view_disasm_source const *>(ptr.get()); + if (&source->space() == space) { - view->set_source(*source); - if ([[self window] firstResponder] != self) - view->set_cursor_visible(false); + if (view->source() != source) + { + view->set_source(*source); + if ([[self window] firstResponder] != self) + view->set_cursor_visible(false); + } + return YES; } - return YES; - } - else - { - return NO; } + return NO; } @@ -211,7 +214,7 @@ action:@selector(debugToggleBreakpointEnable:) keyEquivalent:[NSString stringWithFormat:@"%C", (short)NSF9FunctionKey] atIndex:index++]; - [disableItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [disableItem setKeyEquivalentModifierMask:NSEventModifierFlagShift]; NSMenu *runMenu = [[menu itemWithTitle:@"Run"] submenu]; NSMenuItem *runItem; @@ -256,12 +259,12 @@ - (void)insertSubviewItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index { - for (const debug_view_source *source = view->source_list().first(); source != nullptr; source = source->next()) + for (auto &source : view->source_list()) { [[menu insertItemWithTitle:[NSString stringWithUTF8String:source->name()] action:NULL keyEquivalent:@"" - atIndex:index++] setTag:view->source_list().indexof(*source)]; + atIndex:index++] setTag:view->source_index(*source)]; } if (index < [menu numberOfItems]) [menu insertItem:[NSMenuItem separatorItem] atIndex:index++]; @@ -271,14 +274,14 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; debug_view_disasm *const dasmView = downcast<debug_view_disasm *>(view); - node->set_attribute_int("rightbar", dasmView->right_column()); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmView->right_column()); } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; debug_view_disasm *const dasmView = downcast<debug_view_disasm *>(view); - dasmView->set_right_column((disasm_right_column)node->get_attribute_int("rightbar", dasmView->right_column())); + dasmView->set_right_column((disasm_right_column)node->get_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmView->right_column())); } @end diff --git a/src/osd/modules/debugger/osx/disassemblyviewer.mm b/src/osd/modules/debugger/osx/disassemblyviewer.mm index eb039f4ca17..a0659c00cfc 100644 --- a/src/osd/modules/debugger/osx/disassemblyviewer.mm +++ b/src/osd/modules/debugger/osx/disassemblyviewer.mm @@ -16,6 +16,7 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" #include "util/xmlfile.h" @@ -44,11 +45,9 @@ [expressionField sizeToFit]; // create the subview popup - subviewButton = [[NSPopUpButton alloc] initWithFrame:NSOffsetRect(expressionFrame, - expressionFrame.size.width, - 0)]; + subviewButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)]; [subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinXMargin | NSViewMinYMargin)]; - [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle]; + [subviewButton setBezelStyle:NSBezelStyleShadowlessSquare]; [subviewButton setFocusRingType:NSFocusRingTypeNone]; [subviewButton setFont:defaultFont]; [subviewButton setTarget:self]; @@ -109,7 +108,7 @@ [actionButton release]; // set default state - [dasmView selectSubviewForDevice:machine->debugger().cpu().get_visible_cpu()]; + [dasmView selectSubviewForDevice:machine->debugger().console().get_visible_cpu()]; [dasmView setExpression:@"curpc"]; [expressionField setStringValue:@"curpc"]; [expressionField selectText:self]; @@ -119,9 +118,11 @@ // calculate the optimal size for everything NSSize const desired = [NSScrollView frameSizeForContentSize:[dasmView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[dasmScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[dasmScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; [self cascadeWindowWithDesiredSize:desired forView:dasmScroll]; // don't forget the result @@ -176,12 +177,12 @@ { device_t &device = *[dasmView source]->device(); offs_t const address = [dasmView selectedAddress]; - const device_debug::breakpoint *bp = device.debug()->breakpoint_find(address); + const debug_breakpoint *bp = device.debug()->breakpoint_find(address); // if it doesn't exist, add a new one if (bp == nullptr) { - uint32_t const bpnum = device.debug()->breakpoint_set(address, nullptr, nullptr); + uint32_t const bpnum = device.debug()->breakpoint_set(address); machine->debugger().console().printf("Breakpoint %X set\n", bpnum); } else @@ -203,7 +204,7 @@ { device_t &device = *[dasmView source]->device(); offs_t const address = [dasmView selectedAddress]; - const device_debug::breakpoint *bp = device.debug()->breakpoint_find(address); + const debug_breakpoint *bp = device.debug()->breakpoint_find(address); if (bp != nullptr) { device.debug()->breakpoint_enable(bp->index(), !bp->enabled()); @@ -231,15 +232,15 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DISASSEMBLY_VIEWER); - node->set_attribute_int("cpu", [dasmView selectedSubviewIndex]); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_CPU, [dasmView selectedSubviewIndex]); [dasmView saveConfigurationToNode:node]; } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; - int const region = node->get_attribute_int("cpu", [dasmView selectedSubviewIndex]); + int const region = node->get_attribute_int(osd::debugger::ATTR_WINDOW_DISASSEMBLY_CPU, [dasmView selectedSubviewIndex]); [dasmView selectSubviewAtIndex:region]; [window setTitle:[NSString stringWithFormat:@"Disassembly: %@", [dasmView selectedSubviewName]]]; [subviewButton selectItemAtIndex:[subviewButton indexOfItemWithTag:[dasmView selectedSubviewIndex]]]; @@ -252,7 +253,7 @@ BOOL const inContextMenu = ([item menu] == [dasmView menu]); BOOL const haveCursor = [dasmView cursorVisible]; - const device_debug::breakpoint *breakpoint = nullptr; + const debug_breakpoint *breakpoint = nullptr; if (haveCursor) { breakpoint = [dasmView source]->device()->debug()->breakpoint_find([dasmView selectedAddress]); diff --git a/src/osd/modules/debugger/osx/errorlogviewer.mm b/src/osd/modules/debugger/osx/errorlogviewer.mm index 1fd12c9c9c1..68d6f312b7c 100644 --- a/src/osd/modules/debugger/osx/errorlogviewer.mm +++ b/src/osd/modules/debugger/osx/errorlogviewer.mm @@ -43,11 +43,13 @@ // calculate the optimal size for everything { NSSize desired = [NSScrollView frameSizeForContentSize:[logView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[logScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[logScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; - // this thing starts with no content, so its prefered height may be very small + // this thing starts with no content, so its preferred height may be very small desired.height = std::max(desired.height, CGFloat(240)); [self cascadeWindowWithDesiredSize:desired forView:logScroll]; } @@ -64,7 +66,7 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_ERROR_LOG_VIEWER); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER); } @end diff --git a/src/osd/modules/debugger/osx/exceptionpointsview.h b/src/osd/modules/debugger/osx/exceptionpointsview.h new file mode 100644 index 00000000000..73e3958c9b8 --- /dev/null +++ b/src/osd/modules/debugger/osx/exceptionpointsview.h @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +//============================================================ +// +// exceptionpointsview.h - MacOS X Cocoa debug window handling +// +//============================================================ + +#import "debugosx.h" + +#import "debugview.h" + + +#import <Cocoa/Cocoa.h> + + +@interface MAMEExceptionpointsView : MAMEDebugView +{ +} + +- (id)initWithFrame:(NSRect)f machine:(running_machine &)m; + +@end diff --git a/src/osd/modules/debugger/osx/exceptionpointsview.mm b/src/osd/modules/debugger/osx/exceptionpointsview.mm new file mode 100644 index 00000000000..c15f9c56f4f --- /dev/null +++ b/src/osd/modules/debugger/osx/exceptionpointsview.mm @@ -0,0 +1,27 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +//============================================================ +// +// exceptionpointsview.m - MacOS X Cocoa debug window handling +// +//============================================================ + +#import "exceptionpointsview.h" + +#include "debug/debugvw.h" + + +@implementation MAMEExceptionpointsView + +- (id)initWithFrame:(NSRect)f machine:(running_machine &)m { + if (!(self = [super initWithFrame:f type:DVT_EXCEPTION_POINTS machine:m wholeLineScroll:YES])) + return nil; + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + +@end diff --git a/src/osd/modules/debugger/osx/memoryview.mm b/src/osd/modules/debugger/osx/memoryview.mm index b2c512d094b..24521e81ba4 100644 --- a/src/osd/modules/debugger/osx/memoryview.mm +++ b/src/osd/modules/debugger/osx/memoryview.mm @@ -9,7 +9,6 @@ #include "emu.h" #import "memoryview.h" -#include "debug/debugcpu.h" #include "debug/debugvw.h" #include "util/xmlfile.h" @@ -36,7 +35,7 @@ if (action == @selector(showChunkSize:)) { - [item setState:((tag == memview->get_data_format()) ? NSOnState : NSOffState)]; + [item setState:((tag == int(memview->get_data_format())) ? NSOnState : NSOffState)]; return YES; } else if (action == @selector(showPhysicalAddresses:)) @@ -58,6 +57,11 @@ { return (memview->chunks_per_row() + [item tag]) > 0; } + else if (action == @selector(showAddressRadix:)) + { + [item setState:((memview->address_radix() == [item tag]) ? NSOnState : NSOffState)]; + return YES; + } else { return [super validateMenuItem:item]; @@ -68,7 +72,7 @@ - (NSSize)maximumFrameSize { debug_view_xy max(0, 0); debug_view_source const *source = view->source(); - for (debug_view_source const *source = view->first_source(); source != nullptr; source = source->next()) + for (auto &source : view->source_list()) { view->set_source(*source); debug_view_xy const current = view->total_size(); @@ -101,19 +105,23 @@ - (int)selectedSubviewIndex { debug_view_source const *source = view->source(); if (source != nullptr) - return view->source_list().indexof(*source); + return view->source_index(*source); else return -1; } - (void)selectSubviewAtIndex:(int)index { - int const selected = view->source_list().indexof(*view->source()); + int const selected = [self selectedSubviewIndex]; if (selected != index) { - view->set_source(*view->source_list().find(index)); - if ([[self window] firstResponder] != self) - view->set_cursor_visible(false); + const debug_view_source *source = view->source(index); + if (source != nullptr) + { + view->set_source(*source); + if ([[self window] firstResponder] != self) + view->set_cursor_visible(false); + } } } @@ -139,23 +147,21 @@ - (BOOL)selectSubviewForSpace:(address_space *)space { if (space == nullptr) return NO; - debug_view_memory_source const *source = downcast<debug_view_memory_source const *>(view->first_source()); - while ((source != nullptr) && (source->space() != space)) - source = downcast<debug_view_memory_source *>(source->next()); - if (source != nullptr) + for (auto &ptr : view->source_list()) { - if (view->source() != source) + debug_view_memory_source const *const source = downcast<debug_view_memory_source const *>(ptr.get()); + if (source->space() == space) { - view->set_source(*source); - if ([[self window] firstResponder] != self) - view->set_cursor_visible(false); + if (view->source() != source) + { + view->set_source(*source); + if ([[self window] firstResponder] != self) + view->set_cursor_visible(false); + } + return YES; } - return YES; - } - else - { - return NO; } + return NO; } @@ -175,7 +181,7 @@ - (IBAction)showChunkSize:(id)sender { - downcast<debug_view_memory *>(view)->set_data_format([sender tag]); + downcast<debug_view_memory *>(view)->set_data_format(debug_view_memory::data_format([sender tag])); } @@ -183,6 +189,9 @@ downcast<debug_view_memory *>(view)->set_physical([sender tag]); } +- (IBAction)showAddressRadix:(id)sender { + downcast<debug_view_memory *>(view)->set_address_radix([sender tag]); +} - (IBAction)showReverseView:(id)sender { downcast<debug_view_memory *>(view)->set_reverse([sender tag]); @@ -203,55 +212,125 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; debug_view_memory *const memView = downcast<debug_view_memory *>(view); - node->set_attribute_int("reverse", memView->reverse() ? 1 : 0); - node->set_attribute_int("addressmode", memView->physical() ? 1 : 0); - node->set_attribute_int("dataformat", memView->get_data_format()); - node->set_attribute_int("rowchunks", memView->chunks_per_row()); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView->reverse() ? 1 : 0); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView->physical() ? 1 : 0); + node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView->address_radix()); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView->get_data_format())); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView->chunks_per_row()); } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; debug_view_memory *const memView = downcast<debug_view_memory *>(view); - memView->set_reverse(0 != node->get_attribute_int("reverse", memView->reverse() ? 1 : 0)); - memView->set_physical(0 != node->get_attribute_int("addressmode", memView->physical() ? 1 : 0)); - memView->set_data_format(node->get_attribute_int("dataformat", memView->get_data_format())); - memView->set_chunks_per_row(node->get_attribute_int("rowchunks", memView->chunks_per_row())); + memView->set_reverse(0 != node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView->reverse() ? 1 : 0)); + memView->set_physical(0 != node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView->physical() ? 1 : 0)); + memView->set_address_radix(node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView->address_radix())); + memView->set_data_format(debug_view_memory::data_format(node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView->get_data_format())))); + memView->set_chunks_per_row(node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView->chunks_per_row())); } - (void)insertActionItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index { - NSInteger tag; - for (tag = 1; tag <= 8; tag <<= 1) { - NSString *title = [NSString stringWithFormat:@"%ld-byte Chunks", (long)tag]; - NSMenuItem *chunkItem = [menu insertItemWithTitle:title - action:@selector(showChunkSize:) - keyEquivalent:[NSString stringWithFormat:@"%ld", (long)tag] - atIndex:index++]; - [chunkItem setTarget:self]; - [chunkItem setTag:tag]; - } + NSMenuItem *chunkItem1 = [menu insertItemWithTitle:@"1-byte Chunks (Hex)" + action:@selector(showChunkSize:) + keyEquivalent:@"1" + atIndex:index++]; + [chunkItem1 setTarget:self]; + [chunkItem1 setTag:int(debug_view_memory::data_format::HEX_8BIT)]; - NSMenuItem *chunkItem = [menu insertItemWithTitle:@"32-bit floats" - action:@selector(showChunkSize:) - keyEquivalent:@"F" - atIndex:index++]; - [chunkItem setTarget:self]; - [chunkItem setTag:9]; - - NSMenuItem *chunkItem2 = [menu insertItemWithTitle:@"64-bit floats" - action:@selector(showChunkSize:) - keyEquivalent:@"D" - atIndex:index++]; + NSMenuItem *chunkItem2 = [menu insertItemWithTitle:@"2-byte Chunks (Hex)" + action:@selector(showChunkSize:) + keyEquivalent:@"2" + atIndex:index++]; [chunkItem2 setTarget:self]; - [chunkItem2 setTag:10]; + [chunkItem2 setTag:int(debug_view_memory::data_format::HEX_16BIT)]; + + NSMenuItem *chunkItem4 = [menu insertItemWithTitle:@"4-byte Chunks (Hex)" + action:@selector(showChunkSize:) + keyEquivalent:@"4" + atIndex:index++]; + [chunkItem4 setTarget:self]; + [chunkItem4 setTag:int(debug_view_memory::data_format::HEX_32BIT)]; + + NSMenuItem *chunkItem8 = [menu insertItemWithTitle:@"8-byte Chunks (Hex)" + action:@selector(showChunkSize:) + keyEquivalent:@"8" + atIndex:index++]; + [chunkItem8 setTarget:self]; + [chunkItem8 setTag:int(debug_view_memory::data_format::HEX_64BIT)]; + + NSMenuItem *chunkItem12 = [menu insertItemWithTitle:@"1-byte Chunks (Octal)" + action:@selector(showChunkSize:) + keyEquivalent:@"3" + atIndex:index++]; + [chunkItem12 setTarget:self]; + [chunkItem12 setTag:int(debug_view_memory::data_format::OCTAL_8BIT)]; + + NSMenuItem *chunkItem13 = [menu insertItemWithTitle:@"2-byte Chunks (Octal)" + action:@selector(showChunkSize:) + keyEquivalent:@"5" + atIndex:index++]; + [chunkItem13 setTarget:self]; + [chunkItem13 setTag:int(debug_view_memory::data_format::OCTAL_16BIT)]; + + NSMenuItem *chunkItem14 = [menu insertItemWithTitle:@"4-byte Chunks (Octal)" + action:@selector(showChunkSize:) + keyEquivalent:@"7" + atIndex:index++]; + [chunkItem14 setTarget:self]; + [chunkItem14 setTag:int(debug_view_memory::data_format::OCTAL_32BIT)]; + + NSMenuItem *chunkItem15 = [menu insertItemWithTitle:@"8-byte Chunks (Octal)" + action:@selector(showChunkSize:) + keyEquivalent:@"9" + atIndex:index++]; + [chunkItem15 setTarget:self]; + [chunkItem15 setTag:int(debug_view_memory::data_format::OCTAL_64BIT)]; + + NSMenuItem *chunkItem9 = [menu insertItemWithTitle:@"32-bit Floating Point" + action:@selector(showChunkSize:) + keyEquivalent:@"F" + atIndex:index++]; + [chunkItem9 setTarget:self]; + [chunkItem9 setTag:int(debug_view_memory::data_format::FLOAT_32BIT)]; + + NSMenuItem *chunkItem10 = [menu insertItemWithTitle:@"64-bit Floating Point" + action:@selector(showChunkSize:) + keyEquivalent:@"D" + atIndex:index++]; + [chunkItem10 setTarget:self]; + [chunkItem10 setTag:int(debug_view_memory::data_format::FLOAT_64BIT)]; + + NSMenuItem *chunkItem11 = [menu insertItemWithTitle:@"80-bit Floating Point" + action:@selector(showChunkSize:) + keyEquivalent:@"E" + atIndex:index++]; + [chunkItem11 setTarget:self]; + [chunkItem11 setTag:int(debug_view_memory::data_format::FLOAT_80BIT)]; + + [menu insertItem:[NSMenuItem separatorItem] atIndex:index++]; + + NSMenuItem *hexadecimalItem = [menu insertItemWithTitle:@"Hexadecimal Addresses" + action:@selector(showAddressRadix:) + keyEquivalent:@"H" + atIndex:index++]; + [hexadecimalItem setTarget:self]; + [hexadecimalItem setTag:16]; + + NSMenuItem *decimalItem = [menu insertItemWithTitle:@"Decimal Addresses" + action:@selector(showAddressRadix:) + keyEquivalent:@"" + atIndex:index++]; + [decimalItem setTarget:self]; + [decimalItem setTag:10]; - NSMenuItem *chunkItem3 = [menu insertItemWithTitle:@"80-bit floats" - action:@selector(showChunkSize:) - keyEquivalent:@"E" - atIndex:index++]; - [chunkItem3 setTarget:self]; - [chunkItem3 setTag:11]; + NSMenuItem *octalItem = [menu insertItemWithTitle:@"Octal Addresses" + action:@selector(showAddressRadix:) + keyEquivalent:@"O" + atIndex:index++]; + [octalItem setTarget:self]; + [octalItem setTag:8]; [menu insertItem:[NSMenuItem separatorItem] atIndex:index++]; @@ -299,12 +378,12 @@ - (void)insertSubviewItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index { - for (const debug_view_source *source = view->source_list().first(); source != nullptr; source = source->next()) + for (auto &source : view->source_list()) { [[menu insertItemWithTitle:[NSString stringWithUTF8String:source->name()] action:NULL keyEquivalent:@"" - atIndex:index++] setTag:view->source_list().indexof(*source)]; + atIndex:index++] setTag:view->source_index(*source)]; } if (index < [menu numberOfItems]) [menu insertItem:[NSMenuItem separatorItem] atIndex:index++]; diff --git a/src/osd/modules/debugger/osx/memoryviewer.mm b/src/osd/modules/debugger/osx/memoryviewer.mm index 80d5434a826..1d45650dcbb 100644 --- a/src/osd/modules/debugger/osx/memoryviewer.mm +++ b/src/osd/modules/debugger/osx/memoryviewer.mm @@ -14,7 +14,7 @@ #import "memoryview.h" #include "debugger.h" -#include "debug/debugcpu.h" +#include "debug/debugcon.h" #include "debug/dvmemory.h" #include "util/xmlfile.h" @@ -46,7 +46,7 @@ // create the subview popup subviewButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)]; [subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinXMargin | NSViewMinYMargin)]; - [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle]; + [subviewButton setBezelStyle:NSBezelStyleShadowlessSquare]; [subviewButton setFocusRingType:NSFocusRingTypeNone]; [subviewButton setFont:defaultFont]; [subviewButton setTarget:self]; @@ -108,7 +108,7 @@ [actionButton release]; // set default state - [memoryView selectSubviewForDevice:machine->debugger().cpu().get_visible_cpu()]; + [memoryView selectSubviewForDevice:machine->debugger().console().get_visible_cpu()]; [memoryView setExpression:@"0"]; [expressionField setStringValue:@"0"]; [expressionField selectText:self]; @@ -118,9 +118,11 @@ // calculate the optimal size for everything NSSize const desired = [NSScrollView frameSizeForContentSize:[memoryView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[memoryScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[memoryScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; [self cascadeWindowWithDesiredSize:desired forView:memoryScroll]; // don't forget the result @@ -178,15 +180,15 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_MEMORY_VIEWER); - node->set_attribute_int("memoryregion", [memoryView selectedSubviewIndex]); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_MEMORY_VIEWER); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REGION, [memoryView selectedSubviewIndex]); [memoryView saveConfigurationToNode:node]; } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; - int const region = node->get_attribute_int("memoryregion", [memoryView selectedSubviewIndex]); + int const region = node->get_attribute_int(osd::debugger::ATTR_WINDOW_MEMORY_REGION, [memoryView selectedSubviewIndex]); [memoryView selectSubviewAtIndex:region]; [window setTitle:[NSString stringWithFormat:@"Memory: %@", [memoryView selectedSubviewName]]]; [subviewButton selectItemAtIndex:[subviewButton indexOfItemWithTag:[memoryView selectedSubviewIndex]]]; diff --git a/src/osd/modules/debugger/osx/pointsviewer.mm b/src/osd/modules/debugger/osx/pointsviewer.mm index 8bd4dad3a1b..0fafe35a799 100644 --- a/src/osd/modules/debugger/osx/pointsviewer.mm +++ b/src/osd/modules/debugger/osx/pointsviewer.mm @@ -10,6 +10,8 @@ #import "pointsviewer.h" #import "breakpointsview.h" +#import "exceptionpointsview.h" +#import "registerpointsview.h" #import "watchpointsview.h" #include "util/xmlfile.h" @@ -18,9 +20,9 @@ @implementation MAMEPointsViewer - (id)initWithMachine:(running_machine &)m console:(MAMEDebugConsole *)c { - MAMEDebugView *breakView, *watchView; - NSScrollView *breakScroll, *watchScroll; - NSTabViewItem *breakTab, *watchTab; + MAMEDebugView *breakView, *watchView, *registerView, *exceptionView; + NSScrollView *breakScroll, *watchScroll, *registerScroll, *exceptionScroll; + NSTabViewItem *breakTab, *watchTab, *registerTab, *exceptionTab; NSPopUpButton *actionButton; NSRect subviewFrame; @@ -32,7 +34,7 @@ // create the subview popup subviewButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)]; [subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; - [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle]; + [subviewButton setBezelStyle:NSBezelStyleShadowlessSquare]; [subviewButton setFocusRingType:NSFocusRingTypeNone]; [subviewButton setFont:defaultFont]; [subviewButton setTarget:self]; @@ -44,6 +46,12 @@ [[[subviewButton menu] addItemWithTitle:@"All Watchpoints" action:NULL keyEquivalent:@""] setTag:1]; + [[[subviewButton menu] addItemWithTitle:@"All Registerpoints" + action:NULL + keyEquivalent:@""] setTag:2]; + [[[subviewButton menu] addItemWithTitle:@"All Exceptionpoints" + action:NULL + keyEquivalent:@""] setTag:3]; [subviewButton sizeToFit]; subviewFrame = [subviewButton frame]; subviewFrame.origin.x = subviewFrame.size.height; @@ -82,7 +90,7 @@ [breakTab setView:breakScroll]; [breakScroll release]; - // create the breakpoints view + // create the watchpoints view watchView = [[MAMEWatchpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) machine:*machine]; watchScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]]; @@ -98,7 +106,39 @@ [watchTab setView:watchScroll]; [watchScroll release]; - // create a tabless tabview for the two subviews + // create the registerpoints view + registerView = [[MAMERegisterpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) + machine:*machine]; + registerScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]]; + [registerScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [registerScroll setHasHorizontalScroller:YES]; + [registerScroll setHasVerticalScroller:YES]; + [registerScroll setAutohidesScrollers:YES]; + [registerScroll setBorderType:NSNoBorder]; + [registerScroll setDrawsBackground:NO]; + [registerScroll setDocumentView:registerView]; + [registerView release]; + registerTab = [[NSTabViewItem alloc] initWithIdentifier:@""]; + [registerTab setView:registerScroll]; + [registerScroll release]; + + // create the exceptionpoints view + exceptionView = [[MAMEExceptionpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) + machine:*machine]; + exceptionScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]]; + [exceptionScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [exceptionScroll setHasHorizontalScroller:YES]; + [exceptionScroll setHasVerticalScroller:YES]; + [exceptionScroll setAutohidesScrollers:YES]; + [exceptionScroll setBorderType:NSNoBorder]; + [exceptionScroll setDrawsBackground:NO]; + [exceptionScroll setDocumentView:exceptionView]; + [exceptionView release]; + exceptionTab = [[NSTabViewItem alloc] initWithIdentifier:@""]; + [exceptionTab setView:exceptionScroll]; + [exceptionScroll release]; + + // create a tabless tabview for the four subviews tabs = [[NSTabView alloc] initWithFrame:[breakScroll frame]]; [tabs setTabViewType:NSNoTabsNoBorder]; [tabs setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; @@ -106,6 +146,10 @@ [breakTab release]; [tabs addTabViewItem:watchTab]; [watchTab release]; + [tabs addTabViewItem:registerTab]; + [registerTab release]; + [tabs addTabViewItem:exceptionTab]; + [exceptionTab release]; [[window contentView] addSubview:tabs]; [tabs release]; @@ -117,15 +161,31 @@ // calculate the optimal size for everything NSSize const breakDesired = [NSScrollView frameSizeForContentSize:[breakView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[breakScroll borderType]]; + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[breakScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; NSSize const watchDesired = [NSScrollView frameSizeForContentSize:[watchView maximumFrameSize] - hasHorizontalScroller:YES - hasVerticalScroller:YES - borderType:[watchScroll borderType]]; - NSSize const desired = NSMakeSize(std::max(breakDesired.width, watchDesired.width), - std::max(breakDesired.height, watchDesired.height)); + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[watchScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; + NSSize const registerDesired = [NSScrollView frameSizeForContentSize:[registerView maximumFrameSize] + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[registerScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; + NSSize const exceptionDesired = [NSScrollView frameSizeForContentSize:[exceptionView maximumFrameSize] + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[exceptionScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; + NSSize const desired = NSMakeSize(std::max({ breakDesired.width, watchDesired.width, registerDesired.width, exceptionDesired.width }), + std::max({ breakDesired.height, watchDesired.height, registerDesired.height, exceptionDesired.height })); [self cascadeWindowWithDesiredSize:desired forView:tabs]; // don't forget the result @@ -146,14 +206,14 @@ - (void)saveConfigurationToNode:(util::xml::data_node *)node { [super saveConfigurationToNode:node]; - node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_POINTS_VIEWER); - node->set_attribute_int("bwtype", [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, osd::debugger::WINDOW_TYPE_POINTS_VIEWER); + node->set_attribute_int(osd::debugger::ATTR_WINDOW_POINTS_TYPE, [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]); } - (void)restoreConfigurationFromNode:(util::xml::data_node const *)node { [super restoreConfigurationFromNode:node]; - int const tab = node->get_attribute_int("bwtype", [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]); + int const tab = node->get_attribute_int(osd::debugger::ATTR_WINDOW_POINTS_TYPE, [tabs indexOfTabViewItem:[tabs selectedTabViewItem]]); if ((0 <= tab) && ([tabs numberOfTabViewItems] > tab)) { [subviewButton selectItemAtIndex:tab]; diff --git a/src/osd/modules/debugger/osx/registerpointsview.h b/src/osd/modules/debugger/osx/registerpointsview.h new file mode 100644 index 00000000000..58faf954416 --- /dev/null +++ b/src/osd/modules/debugger/osx/registerpointsview.h @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +//============================================================ +// +// registerpointsview.h - MacOS X Cocoa debug window handling +// +//============================================================ + +#import "debugosx.h" + +#import "debugview.h" + + +#import <Cocoa/Cocoa.h> + + +@interface MAMERegisterpointsView : MAMEDebugView +{ +} + +- (id)initWithFrame:(NSRect)f machine:(running_machine &)m; + +@end diff --git a/src/osd/modules/debugger/osx/registerpointsview.mm b/src/osd/modules/debugger/osx/registerpointsview.mm new file mode 100644 index 00000000000..a701fe733ce --- /dev/null +++ b/src/osd/modules/debugger/osx/registerpointsview.mm @@ -0,0 +1,27 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +//============================================================ +// +// registerpointsview.m - MacOS X Cocoa debug window handling +// +//============================================================ + +#import "registerpointsview.h" + +#include "debug/debugvw.h" + + +@implementation MAMERegisterpointsView + +- (id)initWithFrame:(NSRect)f machine:(running_machine &)m { + if (!(self = [super initWithFrame:f type:DVT_REGISTER_POINTS machine:m wholeLineScroll:YES])) + return nil; + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + +@end diff --git a/src/osd/modules/debugger/osx/registersview.mm b/src/osd/modules/debugger/osx/registersview.mm index 5c3e00a2b89..c710179c5bd 100644 --- a/src/osd/modules/debugger/osx/registersview.mm +++ b/src/osd/modules/debugger/osx/registersview.mm @@ -10,7 +10,7 @@ #include "emu.h" #include "debugger.h" -#include "debug/debugcpu.h" +#include "debug/debugcon.h" #include "debug/debugvw.h" @@ -30,11 +30,11 @@ - (NSSize)maximumFrameSize { debug_view_xy max; - device_t *curcpu = machine->debugger().cpu().get_visible_cpu(); + device_t *curcpu = machine->debugger().console().get_visible_cpu(); const debug_view_source *source = view->source_for_device(curcpu); max.x = max.y = 0; - for (const debug_view_source *source = view->source_list().first(); source != nullptr; source = source->next()) + for (auto &source : view->source_list()) { debug_view_xy current; view->set_source(*source); diff --git a/src/osd/modules/debugger/qt/breakpointswindow.cpp b/src/osd/modules/debugger/qt/breakpointswindow.cpp index 5d091694d66..7dc3db34179 100644 --- a/src/osd/modules/debugger/qt/breakpointswindow.cpp +++ b/src/osd/modules/debugger/qt/breakpointswindow.cpp @@ -1,26 +1,29 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" +#include "breakpointswindow.h" + +#include "util/xmlfile.h" + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include <QtGui/QActionGroup> +#else #include <QtWidgets/QActionGroup> +#endif #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QMenu> #include <QtWidgets/QMenuBar> #include <QtWidgets/QVBoxLayout> -#include "breakpointswindow.h" -#include "debug/debugcon.h" -#include "debug/debugcpu.h" -#include "debug/dvbpoints.h" -#include "debug/dvwpoints.h" +namespace osd::debugger::qt { - -BreakpointsWindow::BreakpointsWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr) +BreakpointsWindow::BreakpointsWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr) { setWindowTitle("Debug: All Breakpoints"); - if (parent != nullptr) + if (parent) { QPoint parentPos = parent->pos(); setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400); @@ -29,13 +32,13 @@ BreakpointsWindow::BreakpointsWindow(running_machine* machine, QWidget* parent) // // The main frame and its input and breakpoints widgets // - QFrame* mainWindowFrame = new QFrame(this); + QFrame *mainWindowFrame = new QFrame(this); // The main breakpoints view m_breakpointsView = new DebuggerView(DVT_BREAK_POINTS, m_machine, this); // Layout - QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); + QVBoxLayout *vLayout = new QVBoxLayout(mainWindowFrame); vLayout->setObjectName("vlayout"); vLayout->setSpacing(3); vLayout->setContentsMargins(2,2,2,2); @@ -46,23 +49,38 @@ BreakpointsWindow::BreakpointsWindow(running_machine* machine, QWidget* parent) // // Menu bars // - QActionGroup* typeGroup = new QActionGroup(this); + QActionGroup *typeGroup = new QActionGroup(this); typeGroup->setObjectName("typegroup"); - QAction* typeBreak = new QAction("Breakpoints", this); + + QAction *typeBreak = new QAction("Breakpoints", this); typeBreak->setObjectName("typebreak"); - QAction* typeWatch = new QAction("Watchpoints", this); - typeWatch->setObjectName("typewatch"); typeBreak->setCheckable(true); - typeWatch->setCheckable(true); typeBreak->setActionGroup(typeGroup); - typeWatch->setActionGroup(typeGroup); typeBreak->setShortcut(QKeySequence("Ctrl+1")); + + QAction *typeWatch = new QAction("Watchpoints", this); + typeWatch->setObjectName("typewatch"); + typeWatch->setCheckable(true); + typeWatch->setActionGroup(typeGroup); typeWatch->setShortcut(QKeySequence("Ctrl+2")); + + QAction *typeRegister = new QAction("Registerpoints", this); + typeRegister->setObjectName("typeregister"); + typeRegister->setCheckable(true); + typeRegister->setActionGroup(typeGroup); + typeRegister->setShortcut(QKeySequence("Ctrl+3")); + + QAction *typeException = new QAction("Exceptionpoints", this); + typeException->setObjectName("typeexception"); + typeException->setCheckable(true); + typeException->setActionGroup(typeGroup); + typeException->setShortcut(QKeySequence("Ctrl+4")); + typeBreak->setChecked(true); connect(typeGroup, &QActionGroup::triggered, this, &BreakpointsWindow::typeChanged); // Assemble the options menu - QMenu* optionsMenu = menuBar()->addMenu("&Options"); + QMenu *optionsMenu = menuBar()->addMenu("&Options"); optionsMenu->addActions(typeGroup->actions()); } @@ -72,6 +90,50 @@ BreakpointsWindow::~BreakpointsWindow() } +void BreakpointsWindow::restoreConfiguration(util::xml::data_node const &node) +{ + WindowQt::restoreConfiguration(node); + + auto const type = node.get_attribute_int(ATTR_WINDOW_POINTS_TYPE, -1); + QActionGroup *typeGroup = findChild<QActionGroup *>("typegroup"); + if ((0 <= type) && (typeGroup->actions().size() > type)) + typeGroup->actions()[type]->trigger(); + + m_breakpointsView->restoreConfigurationFromNode(node); + +} + + +void BreakpointsWindow::saveConfigurationToNode(util::xml::data_node &node) +{ + WindowQt::saveConfigurationToNode(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_POINTS_VIEWER); + if (m_breakpointsView) + { + switch (m_breakpointsView->view()->type()) + { + case DVT_BREAK_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 0); + break; + case DVT_WATCH_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 1); + break; + case DVT_REGISTER_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2); + break; + case DVT_EXCEPTION_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 3); + break; + default: + break; + } + } + + m_breakpointsView->saveConfigurationToNode(node); +} + + void BreakpointsWindow::typeChanged(QAction* changedTo) { // Clean @@ -89,49 +151,20 @@ void BreakpointsWindow::typeChanged(QAction* changedTo) m_breakpointsView = new DebuggerView(DVT_WATCH_POINTS, m_machine, this); setWindowTitle("Debug: All Watchpoints"); } + else if (changedTo->text() == "Registerpoints") + { + m_breakpointsView = new DebuggerView(DVT_REGISTER_POINTS, m_machine, this); + setWindowTitle("Debug: All Registerpoints"); + } + else if (changedTo->text() == "Exceptionpoints") + { + m_breakpointsView = new DebuggerView(DVT_EXCEPTION_POINTS, m_machine, this); + setWindowTitle("Debug: All Exceptionpoints"); + } // Re-register - QVBoxLayout* layout = findChild<QVBoxLayout*>("vlayout"); + QVBoxLayout *layout = findChild<QVBoxLayout *>("vlayout"); layout->addWidget(m_breakpointsView); } - - -//========================================================================= -// BreakpointsWindowQtConfig -//========================================================================= -void BreakpointsWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - BreakpointsWindow* window = dynamic_cast<BreakpointsWindow*>(widget); - - QActionGroup* typeGroup = window->findChild<QActionGroup*>("typegroup"); - if (typeGroup->checkedAction()->text() == "Breakpoints") - m_bwType = 0; - else if (typeGroup->checkedAction()->text() == "Watchpoints") - m_bwType = 1; -} - - -void BreakpointsWindowQtConfig::applyToQWidget(QWidget* widget) -{ - WindowQtConfig::applyToQWidget(widget); - BreakpointsWindow* window = dynamic_cast<BreakpointsWindow*>(widget); - - QActionGroup* typeGroup = window->findChild<QActionGroup*>("typegroup"); - typeGroup->actions()[m_bwType]->trigger(); -} - - -void BreakpointsWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const -{ - WindowQtConfig::addToXmlDataNode(node); - node.set_attribute_int("bwtype", m_bwType); -} - - -void BreakpointsWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); - m_bwType = node.get_attribute_int("bwtype", m_bwType); -} +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/breakpointswindow.h b/src/osd/modules/debugger/qt/breakpointswindow.h index 60bbdc4379f..0a07b4facfb 100644 --- a/src/osd/modules/debugger/qt/breakpointswindow.h +++ b/src/osd/modules/debugger/qt/breakpointswindow.h @@ -1,12 +1,14 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_BREAK_POINTS_WINDOW_H__ -#define __DEBUG_QT_BREAK_POINTS_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_BREAKPOINTSWINDOW_H +#define MAME_DEBUGGER_QT_BREAKPOINTSWINDOW_H #include "debuggerview.h" #include "windowqt.h" +namespace osd::debugger::qt { + //============================================================ // The Breakpoints Window. //============================================================ @@ -15,42 +17,22 @@ class BreakpointsWindow : public WindowQt Q_OBJECT public: - BreakpointsWindow(running_machine* machine, QWidget* parent=nullptr); + BreakpointsWindow(DebuggerQt &debugger, QWidget *parent = nullptr); virtual ~BreakpointsWindow(); + virtual void restoreConfiguration(util::xml::data_node const &node) override; -private slots: - void typeChanged(QAction* changedTo); +protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; +private slots: + void typeChanged(QAction *changedTo); private: // Widgets - DebuggerView* m_breakpointsView; -}; - - -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class BreakpointsWindowQtConfig : public WindowQtConfig -{ -public: - BreakpointsWindowQtConfig() : - WindowQtConfig(WIN_TYPE_BREAK_POINTS), - m_bwType(0) - { - } - - ~BreakpointsWindowQtConfig() {} - - // Settings - int m_bwType; - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); + DebuggerView *m_breakpointsView; }; +} // namespace osd::debugger::qt -#endif +#endif // MAME_DEBUGGER_QT_BREAKPOINTSWINDOW_H diff --git a/src/osd/modules/debugger/qt/dasmwindow.cpp b/src/osd/modules/debugger/qt/dasmwindow.cpp index 5c575b400b1..e90054a3292 100644 --- a/src/osd/modules/debugger/qt/dasmwindow.cpp +++ b/src/osd/modules/debugger/qt/dasmwindow.cpp @@ -1,25 +1,38 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" +#include "dasmwindow.h" + +#include "debugger.h" +#include "debug/debugcon.h" +#include "debug/debugcpu.h" +#include "debug/dvdisasm.h" +#include "debug/points.h" + +#include "util/xmlfile.h" + +#include <QtGui/QKeyEvent> #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QVBoxLayout> +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include <QtGui/QAction> +#include <QtGui/QActionGroup> +#else #include <QtWidgets/QAction> +#endif #include <QtWidgets/QMenu> #include <QtWidgets/QMenuBar> -#include "dasmwindow.h" -#include "debug/debugcon.h" -#include "debug/debugcpu.h" -#include "debug/dvdisasm.h" +namespace osd::debugger::qt { - -DasmWindow::DasmWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr) +DasmWindow::DasmWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr), + m_inputHistory() { setWindowTitle("Debug: Disassembly View"); - if (parent != nullptr) + if (parent) { QPoint parentPos = parent->pos(); setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400); @@ -28,43 +41,42 @@ DasmWindow::DasmWindow(running_machine* machine, QWidget* parent) : // // The main frame and its input and log widgets // - QFrame* mainWindowFrame = new QFrame(this); + QFrame *mainWindowFrame = new QFrame(this); // The top frame & groupbox that contains the input widgets - QFrame* topSubFrame = new QFrame(mainWindowFrame); + QFrame *topSubFrame = new QFrame(mainWindowFrame); // The input edit m_inputEdit = new QLineEdit(topSubFrame); connect(m_inputEdit, &QLineEdit::returnPressed, this, &DasmWindow::expressionSubmitted); + connect(m_inputEdit, &QLineEdit::textEdited, this, &DasmWindow::expressionEdited); + m_inputEdit->installEventFilter(this); // The cpu combo box m_cpuComboBox = new QComboBox(topSubFrame); m_cpuComboBox->setObjectName("cpu"); m_cpuComboBox->setMinimumWidth(300); - connect(m_cpuComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &DasmWindow::cpuChanged); + connect(m_cpuComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &DasmWindow::cpuChanged); // The main disasm window m_dasmView = new DebuggerView(DVT_DISASSEMBLY, m_machine, this); connect(m_dasmView, &DebuggerView::updated, this, &DasmWindow::dasmViewUpdated); // Force a recompute of the disassembly region - downcast<debug_view_disasm*>(m_dasmView->view())->set_expression("curpc"); + m_dasmView->view<debug_view_disasm>()->set_expression("curpc"); - // Populate the combo box & set the proper cpu + // Populate the combo box & set the proper CPU populateComboBox(); - //const debug_view_source *source = mem->views[0]->view->source_for_device(curcpu); - //gtk_combo_box_set_active(zone_w, mem->views[0]->view->source_list().indexof(*source)); - //mem->views[0]->view->set_source(*source); - + setToCurrentCpu(); // Layout - QHBoxLayout* subLayout = new QHBoxLayout(topSubFrame); + QHBoxLayout *subLayout = new QHBoxLayout(topSubFrame); subLayout->addWidget(m_inputEdit); subLayout->addWidget(m_cpuComboBox); subLayout->setSpacing(3); subLayout->setContentsMargins(2,2,2,2); - QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); + QVBoxLayout *vLayout = new QVBoxLayout(mainWindowFrame); vLayout->setSpacing(3); vLayout->setContentsMargins(2,2,2,2); vLayout->addWidget(topSubFrame); @@ -80,18 +92,21 @@ DasmWindow::DasmWindow(running_machine* machine, QWidget* parent) : m_breakpointEnableAct = new QAction("Disable Breakpoint at Cursor", this); m_runToCursorAct = new QAction("Run to Cursor", this); m_breakpointToggleAct->setShortcut(Qt::Key_F9); - m_breakpointEnableAct->setShortcut(Qt::SHIFT + Qt::Key_F9); + m_breakpointEnableAct->setShortcut(Qt::SHIFT | Qt::Key_F9); m_runToCursorAct->setShortcut(Qt::Key_F4); connect(m_breakpointToggleAct, &QAction::triggered, this, &DasmWindow::toggleBreakpointAtCursor); connect(m_breakpointEnableAct, &QAction::triggered, this, &DasmWindow::enableBreakpointAtCursor); connect(m_runToCursorAct, &QAction::triggered, this, &DasmWindow::runToCursor); // Right bar options - QActionGroup* rightBarGroup = new QActionGroup(this); + QActionGroup *rightBarGroup = new QActionGroup(this); rightBarGroup->setObjectName("rightbargroup"); - QAction* rightActRaw = new QAction("Raw Opcodes", this); - QAction* rightActEncrypted = new QAction("Encrypted Opcodes", this); - QAction* rightActComments = new QAction("Comments", this); + QAction *rightActRaw = new QAction("Raw Opcodes", this); + QAction *rightActEncrypted = new QAction("Encrypted Opcodes", this); + QAction *rightActComments = new QAction("Comments", this); + rightActRaw->setData(int(DASM_RIGHTCOL_RAW)); + rightActEncrypted->setData(int(DASM_RIGHTCOL_ENCRYPTED)); + rightActComments->setData(int(DASM_RIGHTCOL_COMMENTS)); rightActRaw->setCheckable(true); rightActEncrypted->setCheckable(true); rightActComments->setCheckable(true); @@ -105,7 +120,7 @@ DasmWindow::DasmWindow(running_machine* machine, QWidget* parent) : connect(rightBarGroup, &QActionGroup::triggered, this, &DasmWindow::rightBarChanged); // Assemble the options menu - QMenu* optionsMenu = menuBar()->addMenu("&Options"); + QMenu *optionsMenu = menuBar()->addMenu("&Options"); optionsMenu->addAction(m_breakpointToggleAct); optionsMenu->addAction(m_breakpointEnableAct); optionsMenu->addAction(m_runToCursorAct); @@ -119,18 +134,124 @@ DasmWindow::~DasmWindow() } +void DasmWindow::restoreConfiguration(util::xml::data_node const &node) +{ + WindowQt::restoreConfiguration(node); + + debug_view_disasm &dasmview = *m_dasmView->view<debug_view_disasm>(); + + auto const cpu = node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_dasmView->sourceIndex()); + if ((0 <= cpu) && (m_cpuComboBox->count() > cpu)) + m_cpuComboBox->setCurrentIndex(cpu); + + auto const rightbar = node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()); + QActionGroup *const rightBarGroup = findChild<QActionGroup *>("rightbargroup"); + for (QAction *action : rightBarGroup->actions()) + { + if (action->data().toInt() == rightbar) + { + action->trigger(); + break; + } + } + + util::xml::data_node const *const expression = node.get_child(NODE_WINDOW_EXPRESSION); + if (expression && expression->get_value()) + { + m_inputEdit->setText(QString::fromUtf8(expression->get_value())); + expressionSubmitted(); + } + + m_dasmView->restoreConfigurationFromNode(node); + m_inputHistory.restoreConfigurationFromNode(node); +} + + +void DasmWindow::saveConfigurationToNode(util::xml::data_node &node) +{ + WindowQt::saveConfigurationToNode(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DISASSEMBLY_VIEWER); + + debug_view_disasm &dasmview = *m_dasmView->view<debug_view_disasm>(); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_dasmView->sourceIndex()); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()); + node.add_child(NODE_WINDOW_EXPRESSION, dasmview.expression()); + + m_dasmView->saveConfigurationToNode(node); + m_inputHistory.saveConfigurationToNode(node); +} + + +// Used to intercept the user hitting the up arrow in the input widget +bool DasmWindow::eventFilter(QObject *obj, QEvent *event) +{ + // Only filter keypresses + if (event->type() != QEvent::KeyPress) + return QObject::eventFilter(obj, event); + + QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event); + + // Catch up & down keys + if (keyEvent.key() == Qt::Key_Escape) + { + m_inputEdit->setText(QString::fromUtf8(m_dasmView->view<debug_view_disasm>()->expression())); + m_inputEdit->selectAll(); + m_inputHistory.reset(); + return true; + } + else if (keyEvent.key() == Qt::Key_Up) + { + QString const *const hist = m_inputHistory.previous(m_inputEdit->text()); + if (hist) + { + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); + } + return true; + } + else if (keyEvent.key() == Qt::Key_Down) + { + QString const *const hist = m_inputHistory.next(m_inputEdit->text()); + if (hist) + { + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); + } + return true; + } + else + { + return QObject::eventFilter(obj, event); + } +} + + void DasmWindow::cpuChanged(int index) { - m_dasmView->view()->set_source(*m_dasmView->view()->source_list().find(index)); - m_dasmView->viewport()->update(); + if (index < m_dasmView->view()->source_count()) + { + m_dasmView->view()->set_source(*m_dasmView->view()->source(index)); + m_dasmView->viewport()->update(); + } } void DasmWindow::expressionSubmitted() { const QString expression = m_inputEdit->text(); - downcast<debug_view_disasm*>(m_dasmView->view())->set_expression(expression.toLocal8Bit().data()); - m_dasmView->viewport()->update(); + m_dasmView->view<debug_view_disasm>()->set_expression(expression.toUtf8().data()); + m_inputEdit->selectAll(); + + // Add history + if (!expression.isEmpty()) + m_inputHistory.add(expression); +} + + +void DasmWindow::expressionEdited(QString const &text) +{ + m_inputHistory.edit(); } @@ -138,30 +259,28 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo) { if (m_dasmView->view()->cursor_visible()) { - offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address(); + offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address(); device_t *const device = m_dasmView->view()->source()->device(); device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); // If none exists, add a new one - if (bp == nullptr) + if (!bp) { - int32_t bpindex = cpuinfo->breakpoint_set(address, nullptr, nullptr); - m_machine->debugger().console().printf("Breakpoint %X set\n", bpindex); + int32_t bpindex = cpuinfo->breakpoint_set(address); + m_machine.debugger().console().printf("Breakpoint %X set\n", bpindex); } else { int32_t bpindex = bp->index(); cpuinfo->breakpoint_clear(bpindex); - m_machine->debugger().console().printf("Breakpoint %X cleared\n", bpindex); + m_machine.debugger().console().printf("Breakpoint %X cleared\n", bpindex); } - m_machine->debug_view().update_all(); - m_machine->debugger().refresh_display(); + m_machine.debug_view().update_all(); + m_machine.debugger().refresh_display(); } - - refreshAll(); } @@ -169,23 +288,21 @@ void DasmWindow::enableBreakpointAtCursor(bool changedTo) { if (m_dasmView->view()->cursor_visible()) { - offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address(); + offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address(); device_t *const device = m_dasmView->view()->source()->device(); device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); - if (bp != nullptr) + if (bp) { cpuinfo->breakpoint_enable(bp->index(), !bp->enabled()); - m_machine->debugger().console().printf("Breakpoint %X %s\n", (uint32_t)bp->index(), bp->enabled() ? "enabled" : "disabled"); - m_machine->debug_view().update_all(); - m_machine->debugger().refresh_display(); + m_machine.debugger().console().printf("Breakpoint %X %s\n", (uint32_t)bp->index(), bp->enabled() ? "enabled" : "disabled"); + m_machine.debug_view().update_all(); + m_machine.debugger().refresh_display(); } } - - refreshAll(); } @@ -193,7 +310,7 @@ void DasmWindow::runToCursor(bool changedTo) { if (m_dasmView->view()->cursor_visible()) { - offs_t const address = downcast<debug_view_disasm*>(m_dasmView->view())->selected_address(); + offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address(); m_dasmView->view()->source()->device()->debug()->go(address); } } @@ -201,19 +318,8 @@ void DasmWindow::runToCursor(bool changedTo) void DasmWindow::rightBarChanged(QAction* changedTo) { - debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmView->view()); - if (changedTo->text() == "Raw Opcodes") - { - dasmView->set_right_column(DASM_RIGHTCOL_RAW); - } - else if (changedTo->text() == "Encrypted Opcodes") - { - dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED); - } - else if (changedTo->text() == "Comments") - { - dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS); - } + debug_view_disasm *const dasmView = m_dasmView->view<debug_view_disasm>(); + dasmView->set_right_column(disasm_right_column(changedTo->data().toInt())); m_dasmView->viewport()->update(); } @@ -225,14 +331,14 @@ void DasmWindow::dasmViewUpdated() bool breakpointEnabled = false; if (haveCursor) { - offs_t const address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address(); + offs_t const address = m_dasmView->view<debug_view_disasm>()->selected_address(); device_t *const device = m_dasmView->view()->source()->device(); device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); - if (bp != nullptr) + if (bp) { haveBreakpoint = true; breakpointEnabled = bp->enabled(); @@ -249,57 +355,29 @@ void DasmWindow::dasmViewUpdated() void DasmWindow::populateComboBox() { - if (m_dasmView == nullptr) + if (!m_dasmView) return; m_cpuComboBox->clear(); - for (const debug_view_source &source : m_dasmView->view()->source_list()) + for (auto &source : m_dasmView->view()->source_list()) { - m_cpuComboBox->addItem(source.name()); + m_cpuComboBox->addItem(source->name()); } } -//========================================================================= -// DasmWindowQtConfig -//========================================================================= -void DasmWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - DasmWindow* window = dynamic_cast<DasmWindow*>(widget); - QComboBox* cpu = window->findChild<QComboBox*>("cpu"); - m_cpu = cpu->currentIndex(); - - QActionGroup* rightBarGroup = window->findChild<QActionGroup*>("rightbargroup"); - if (rightBarGroup->checkedAction()->text() == "Raw Opcodes") - m_rightBar = 0; - else if (rightBarGroup->checkedAction()->text() == "Encrypted Opcodes") - m_rightBar = 1; - else if (rightBarGroup->checkedAction()->text() == "Comments") - m_rightBar = 2; -} - -void DasmWindowQtConfig::applyToQWidget(QWidget* widget) -{ - WindowQtConfig::applyToQWidget(widget); - DasmWindow* window = dynamic_cast<DasmWindow*>(widget); - QComboBox* cpu = window->findChild<QComboBox*>("cpu"); - cpu->setCurrentIndex(m_cpu); - - QActionGroup* rightBarGroup = window->findChild<QActionGroup*>("rightbargroup"); - rightBarGroup->actions()[m_rightBar]->trigger(); -} - -void DasmWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const +void DasmWindow::setToCurrentCpu() { - WindowQtConfig::addToXmlDataNode(node); - node.set_attribute_int("cpu", m_cpu); - node.set_attribute_int("rightbar", m_rightBar); + device_t *curCpu = m_machine.debugger().console().get_visible_cpu(); + if (curCpu) + { + const debug_view_source *source = m_dasmView->view()->source_for_device(curCpu); + if (source) + { + const int listIndex = m_dasmView->view()->source_index(*source); + m_cpuComboBox->setCurrentIndex(listIndex); + } + } } -void DasmWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); - m_cpu = node.get_attribute_int("cpu", m_cpu); - m_rightBar = node.get_attribute_int("rightbar", m_rightBar); -} +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/dasmwindow.h b/src/osd/modules/debugger/qt/dasmwindow.h index 27b652c04e8..df3fc0699a8 100644 --- a/src/osd/modules/debugger/qt/dasmwindow.h +++ b/src/osd/modules/debugger/qt/dasmwindow.h @@ -1,14 +1,18 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_DASM_WINDOW_H__ -#define __DEBUG_QT_DASM_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_DASMWINDOW_H +#define MAME_DEBUGGER_QT_DASMWINDOW_H -#include <QtWidgets/QLineEdit> -#include <QtWidgets/QComboBox> +#pragma once #include "debuggerview.h" #include "windowqt.h" +#include <QtWidgets/QComboBox> +#include <QtWidgets/QLineEdit> + + +namespace osd::debugger::qt { //============================================================ // The Disassembly Window. @@ -18,62 +22,47 @@ class DasmWindow : public WindowQt Q_OBJECT public: - DasmWindow(running_machine* machine, QWidget* parent=nullptr); + DasmWindow(DebuggerQt &debugger, QWidget *parent = nullptr); virtual ~DasmWindow(); + virtual void restoreConfiguration(util::xml::data_node const &node) override; + +protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; + + // Used to intercept the user hitting the up arrow in the input widget + virtual bool eventFilter(QObject *obj, QEvent *event) override; private slots: void cpuChanged(int index); void expressionSubmitted(); + void expressionEdited(QString const &text); void toggleBreakpointAtCursor(bool changedTo); void enableBreakpointAtCursor(bool changedTo); void runToCursor(bool changedTo); - void rightBarChanged(QAction* changedTo); + void rightBarChanged(QAction *changedTo); void dasmViewUpdated(); - private: void populateComboBox(); - + void setToCurrentCpu(); // Widgets - QLineEdit* m_inputEdit; - QComboBox* m_cpuComboBox; - DebuggerView* m_dasmView; + QLineEdit *m_inputEdit; + QComboBox *m_cpuComboBox; + DebuggerView *m_dasmView; // Menu items - QAction* m_breakpointToggleAct; - QAction* m_breakpointEnableAct; - QAction* m_runToCursorAct; -}; + QAction *m_breakpointToggleAct; + QAction *m_breakpointEnableAct; + QAction *m_runToCursorAct; - -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class DasmWindowQtConfig : public WindowQtConfig -{ -public: - DasmWindowQtConfig() : - WindowQtConfig(WIN_TYPE_DASM), - m_cpu(0), - m_rightBar(0) - { - } - - ~DasmWindowQtConfig() {} - - // Settings - int m_cpu; - int m_rightBar; - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); + // Expression history + CommandHistory m_inputHistory; }; +} // namespace osd::debugger::qt -#endif +#endif // MAME_DEBUGGER_QT_DASMWINDOW_H diff --git a/src/osd/modules/debugger/qt/debuggerview.cpp b/src/osd/modules/debugger/qt/debuggerview.cpp index 7dc16c0a3de..6a184dcfcca 100644 --- a/src/osd/modules/debugger/qt/debuggerview.cpp +++ b/src/osd/modules/debugger/qt/debuggerview.cpp @@ -1,80 +1,96 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" -#include <QtWidgets/QScrollBar> -#include <QtWidgets/QApplication> -#include <QtGui/QPainter> -#include <QtGui/QKeyEvent> - #include "debuggerview.h" +#include "../xmlconfig.h" + #include "modules/lib/osdobj_common.h" +#include "xmlfile.h" + +#include <QtCore/QMimeData> +#include <QtGui/QClipboard> +#include <QtGui/QKeyEvent> +#include <QtGui/QPainter> +#include <QtWidgets/QApplication> +#include <QtWidgets/QScrollBar> -DebuggerView::DebuggerView(const debug_view_type& type, - running_machine* machine, - QWidget* parent) : + +namespace osd::debugger::qt { + +DebuggerView::DebuggerView( + debug_view_type type, + running_machine &machine, + QWidget *parent) : QAbstractScrollArea(parent), - m_preferBottom(false), + m_machine(machine), m_view(nullptr), - m_machine(machine) + m_preferBottom(false) { - // I like setting the font per-view since it doesn't override the menuing fonts. - const char *const selectedFont(downcast<osd_options &>(m_machine->options()).debugger_font()); - const float selectedFontSize(downcast<osd_options &>(m_machine->options()).debugger_font_size()); + // I like setting the font per-view since it doesn't override the menu fonts. + const char *const selectedFont(downcast<osd_options &>(m_machine.options()).debugger_font()); + const float selectedFontSize(downcast<osd_options &>(m_machine.options()).debugger_font_size()); QFont viewFontRequest((!*selectedFont || !strcmp(selectedFont, OSDOPTVAL_AUTO)) ? "Courier New" : selectedFont); viewFontRequest.setFixedPitch(true); viewFontRequest.setStyleHint(QFont::TypeWriter); viewFontRequest.setPointSize((selectedFontSize <= 0) ? 11 : selectedFontSize); setFont(viewFontRequest); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - m_view = m_machine->debug_view().alloc_view(type, - DebuggerView::debuggerViewUpdate, - this); + m_view = m_machine.debug_view().alloc_view( + type, + DebuggerView::debuggerViewUpdate, + this); - connect(verticalScrollBar(), &QScrollBar::valueChanged, - this, &DebuggerView::verticalScrollSlot); - connect(horizontalScrollBar(), &QScrollBar::valueChanged, - this, &DebuggerView::horizontalScrollSlot); + connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &DebuggerView::verticalScrollSlot); + connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &DebuggerView::horizontalScrollSlot); } DebuggerView::~DebuggerView() { - if (m_machine && m_view) - m_machine->debug_view().free_view(*m_view); + if (m_view) + m_machine.debug_view().free_view(*m_view); +} + + +int DebuggerView::sourceIndex() const +{ + if (m_view) + { + debug_view_source const *const source = m_view->source(); + if (source) + return m_view->source_index(*source); + } + return -1; } -void DebuggerView::paintEvent(QPaintEvent* event) + +void DebuggerView::paintEvent(QPaintEvent *event) { // Tell the MAME debug view how much real estate is available QFontMetrics actualFont = fontMetrics(); - const double fontWidth = actualFont.width(QString(100, '_')) / 100.; - const int fontHeight = std::max(1, actualFont.lineSpacing()); - m_view->set_visible_size(debug_view_xy(width()/fontWidth, height()/fontHeight)); - + double const fontWidth = actualFont.horizontalAdvance(QString(100, '_')) / 100.; + int const fontHeight = std::max(1, actualFont.lineSpacing()); + int const contentWidth = width() - verticalScrollBar()->width(); + int const lineWidth = contentWidth / fontWidth; + bool const fullWidth = lineWidth >= m_view->total_size().x; + int const contentHeight = height() - (fullWidth ? 0 : horizontalScrollBar()->height()); + m_view->set_visible_size(debug_view_xy(lineWidth, contentHeight / fontHeight)); // Handle the scroll bars - const int horizontalScrollCharDiff = m_view->total_size().x - m_view->visible_size().x; - const int horizontalScrollSize = horizontalScrollCharDiff < 0 ? 0 : horizontalScrollCharDiff; - horizontalScrollBar()->setRange(0, horizontalScrollSize); - - // If the horizontal scroll bar appears, make sure to adjust the vertical scrollbar accordingly - const int verticalScrollAdjust = horizontalScrollSize > 0 ? 1 : 0; + int const horizontalScrollCharDiff = m_view->total_size().x - m_view->visible_size().x; + horizontalScrollBar()->setRange(0, (std::max)(0, horizontalScrollCharDiff)); + horizontalScrollBar()->setPageStep(lineWidth - 1); - const int verticalScrollCharDiff = m_view->total_size().y - m_view->visible_size().y; - const int verticalScrollSize = verticalScrollCharDiff < 0 ? 0 : verticalScrollCharDiff+verticalScrollAdjust; - bool atEnd = false; - if (verticalScrollBar()->value() == verticalScrollBar()->maximum()) - { - atEnd = true; - } + int const verticalScrollCharDiff = m_view->total_size().y - m_view->visible_size().y; + int const verticalScrollSize = (std::max)(0, verticalScrollCharDiff); + bool const atEnd = verticalScrollBar()->value() == verticalScrollBar()->maximum(); verticalScrollBar()->setRange(0, verticalScrollSize); + verticalScrollBar()->setPageStep((contentHeight / fontHeight) - 1); if (m_preferBottom && atEnd) - { verticalScrollBar()->setValue(verticalScrollSize); - } - // Draw the viewport widget QPainter painter(viewport()); @@ -87,84 +103,130 @@ void DebuggerView::paintEvent(QPaintEvent* event) bgBrush.setStyle(Qt::SolidPattern); painter.setPen(QPen(QColor(0,0,0))); - size_t viewDataOffset = 0; - const debug_view_xy& visibleCharDims = m_view->visible_size(); - const debug_view_char* viewdata = m_view->viewdata(); - for (int y = 0; y < visibleCharDims.y; y++) + const debug_view_xy visibleCharDims = m_view->visible_size(); + const debug_view_char *viewdata = m_view->viewdata(); + for (int y = 0; y < visibleCharDims.y; y++, viewdata += visibleCharDims.x) { int width = 1; - for (int x = 0; x < visibleCharDims.x; viewDataOffset += width, x += width) + for (int x = 0; x < visibleCharDims.x; x += width) { - const unsigned char textAttr = viewdata[viewDataOffset].attrib; + const unsigned char textAttr = viewdata[x].attrib; // Text color handling QColor fgColor(0,0,0); QColor bgColor(255,255,255); - if(textAttr & DCA_VISITED) - { + if (textAttr & DCA_VISITED) bgColor.setRgb(0xc6, 0xe2, 0xff); - } - if(textAttr & DCA_ANCILLARY) - { + + if (textAttr & DCA_ANCILLARY) bgColor.setRgb(0xe0, 0xe0, 0xe0); - } - if(textAttr & DCA_SELECTED) - { + + if (textAttr & DCA_SELECTED) bgColor.setRgb(0xff, 0x80, 0x80); - } - if(textAttr & DCA_CURRENT) - { + + if (textAttr & DCA_CURRENT) bgColor.setRgb(0xff, 0xff, 0x00); - } + if ((textAttr & DCA_SELECTED) && (textAttr & DCA_CURRENT)) - { bgColor.setRgb(0xff,0xc0,0x80); - } - if(textAttr & DCA_CHANGED) - { + + if (textAttr & DCA_CHANGED) fgColor.setRgb(0xff, 0x00, 0x00); - } - if(textAttr & DCA_INVALID) - { + + if (textAttr & DCA_INVALID) fgColor.setRgb(0x00, 0x00, 0xff); - } - if(textAttr & DCA_DISABLED) + + if (textAttr & DCA_DISABLED) { - fgColor.setRgb((fgColor.red() + bgColor.red()) >> 1, - (fgColor.green() + bgColor.green()) >> 1, - (fgColor.blue() + bgColor.blue()) >> 1); + fgColor.setRgb( + (fgColor.red() + bgColor.red()) >> 1, + (fgColor.green() + bgColor.green()) >> 1, + (fgColor.blue() + bgColor.blue()) >> 1); } - if(textAttr & DCA_COMMENT) - { + + if (textAttr & DCA_COMMENT) fgColor.setRgb(0x00, 0x80, 0x00); - } bgBrush.setColor(bgColor); painter.setBackground(bgBrush); painter.setPen(QPen(fgColor)); - QString text(QChar(viewdata[viewDataOffset].byte)); - for (width = 1; x + width < visibleCharDims.x; width++) + QString text(QChar(viewdata[x].byte)); + for (width = 1; (x + width) < visibleCharDims.x; width++) { - if (textAttr != viewdata[viewDataOffset + width].attrib) + if (textAttr != viewdata[x + width].attrib) break; - text.append(QChar(viewdata[viewDataOffset + width].byte)); + text.append(QChar(viewdata[x + width].byte)); } // Your characters are not guaranteed to take up the entire length x fontWidth x fontHeight, so fill before. - painter.fillRect(x*fontWidth, y*fontHeight, width*fontWidth, fontHeight, bgBrush); + painter.fillRect( + x * fontWidth, + y * fontHeight, + ((x + width) < visibleCharDims.x) ? (width * fontWidth) : (contentWidth - (x * fontWidth)), + fontHeight, + bgBrush); + + if (((y + 1) == visibleCharDims.y) && (contentHeight > (visibleCharDims.y * fontHeight))) + { + if (textAttr & DCA_ANCILLARY) + bgColor.setRgb(0xe0, 0xe0, 0xe0); + else + bgColor.setRgb(0xff, 0xff, 0xff); + bgBrush.setColor(bgColor); + painter.fillRect( + x * fontWidth, + visibleCharDims.y * fontHeight, + ((x + width) < visibleCharDims.x) ? (width * fontWidth) : (contentWidth - (x * fontWidth)), + contentHeight - (visibleCharDims.y * fontHeight), + bgBrush); + } // There is a touchy interplay between font height, drawing difference, visible position, etc // Fonts don't get drawn "down and to the left" like boxes, so some wiggling is needed. - painter.drawText(x*fontWidth, (y*fontHeight + (fontHeight*0.80)), text); + painter.drawText(x * fontWidth, (y * fontHeight + (fontHeight * 0.80)), text); + } + } +} + + +void DebuggerView::restoreConfigurationFromNode(util::xml::data_node const &node) +{ + if (m_view->cursor_supported()) + { + util::xml::data_node const *const selection = node.get_child(NODE_WINDOW_SELECTION); + if (selection) + { + debug_view_xy pos = m_view->cursor_position(); + m_view->set_cursor_visible(0 != selection->get_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0)); + selection->get_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x); + selection->get_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y); + m_view->set_cursor_position(pos); + } + } +} + + +void DebuggerView::saveConfigurationToNode(util::xml::data_node &node) +{ + if (m_view->cursor_supported()) + { + util::xml::data_node *const selection = node.add_child(NODE_WINDOW_SELECTION, nullptr); + if (selection) + { + debug_view_xy const pos = m_view->cursor_position(); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y); } } } + void DebuggerView::keyPressEvent(QKeyEvent* event) { - if (m_view == nullptr) + if (!m_view) return QWidget::keyPressEvent(event); Qt::KeyboardModifiers keyMods = QApplication::keyboardModifiers(); @@ -173,52 +235,54 @@ void DebuggerView::keyPressEvent(QKeyEvent* event) int keyPress = -1; switch (event->key()) { - case Qt::Key_Up: - keyPress = DCH_UP; - break; - case Qt::Key_Down: - keyPress = DCH_DOWN; - break; - case Qt::Key_Left: - keyPress = DCH_LEFT; - if (ctrlDown) keyPress = DCH_CTRLLEFT; - break; - case Qt::Key_Right: - keyPress = DCH_RIGHT; - if (ctrlDown) keyPress = DCH_CTRLRIGHT; - break; - case Qt::Key_PageUp: - keyPress = DCH_PUP; - break; - case Qt::Key_PageDown: - keyPress = DCH_PDOWN; - break; - case Qt::Key_Home: - keyPress = DCH_HOME; - if (ctrlDown) keyPress = DCH_CTRLHOME; - break; - case Qt::Key_End: - keyPress = DCH_END; - if (ctrlDown) keyPress = DCH_CTRLEND; - break; - case Qt::Key_0: keyPress = '0'; break; - case Qt::Key_1: keyPress = '1'; break; - case Qt::Key_2: keyPress = '2'; break; - case Qt::Key_3: keyPress = '3'; break; - case Qt::Key_4: keyPress = '4'; break; - case Qt::Key_5: keyPress = '5'; break; - case Qt::Key_6: keyPress = '6'; break; - case Qt::Key_7: keyPress = '7'; break; - case Qt::Key_8: keyPress = '8'; break; - case Qt::Key_9: keyPress = '9'; break; - case Qt::Key_A: keyPress = 'a'; break; - case Qt::Key_B: keyPress = 'b'; break; - case Qt::Key_C: keyPress = 'c'; break; - case Qt::Key_D: keyPress = 'd'; break; - case Qt::Key_E: keyPress = 'e'; break; - case Qt::Key_F: keyPress = 'f'; break; - default: - return QWidget::keyPressEvent(event); + case Qt::Key_Up: + keyPress = DCH_UP; + break; + case Qt::Key_Down: + keyPress = DCH_DOWN; + break; + case Qt::Key_Left: + keyPress = DCH_LEFT; + if (ctrlDown) + keyPress = DCH_CTRLLEFT; + break; + case Qt::Key_Right: + keyPress = DCH_RIGHT; + if (ctrlDown) + keyPress = DCH_CTRLRIGHT; + break; + case Qt::Key_PageUp: + keyPress = DCH_PUP; + break; + case Qt::Key_PageDown: + keyPress = DCH_PDOWN; + break; + case Qt::Key_Home: + keyPress = DCH_HOME; + if (ctrlDown) keyPress = DCH_CTRLHOME; + break; + case Qt::Key_End: + keyPress = DCH_END; + if (ctrlDown) keyPress = DCH_CTRLEND; + break; + case Qt::Key_0: keyPress = '0'; break; + case Qt::Key_1: keyPress = '1'; break; + case Qt::Key_2: keyPress = '2'; break; + case Qt::Key_3: keyPress = '3'; break; + case Qt::Key_4: keyPress = '4'; break; + case Qt::Key_5: keyPress = '5'; break; + case Qt::Key_6: keyPress = '6'; break; + case Qt::Key_7: keyPress = '7'; break; + case Qt::Key_8: keyPress = '8'; break; + case Qt::Key_9: keyPress = '9'; break; + case Qt::Key_A: keyPress = 'a'; break; + case Qt::Key_B: keyPress = 'b'; break; + case Qt::Key_C: keyPress = 'c'; break; + case Qt::Key_D: keyPress = 'd'; break; + case Qt::Key_E: keyPress = 'e'; break; + case Qt::Key_F: keyPress = 'f'; break; + default: + return QWidget::keyPressEvent(event); } m_view->set_cursor_visible(true); @@ -232,26 +296,65 @@ void DebuggerView::keyPressEvent(QKeyEvent* event) } -void DebuggerView::mousePressEvent(QMouseEvent* event) +void DebuggerView::mousePressEvent(QMouseEvent *event) { - if (m_view == nullptr) + if (!m_view) return; + QFontMetrics actualFont = fontMetrics(); + const double fontWidth = actualFont.horizontalAdvance(QString(100, '_')) / 100.; + const int fontHeight = std::max(1, actualFont.lineSpacing()); + + debug_view_xy const topLeft = m_view->visible_position(); + debug_view_xy const visibleCharDims = m_view->visible_size(); + debug_view_xy clickViewPosition; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QPointF mousePosition = event->position(); +#else + const QPointF mousePosition = event->localPos(); +#endif + clickViewPosition.x = (std::min)(int(topLeft.x + (mousePosition.x() / fontWidth)), topLeft.x + visibleCharDims.x - 1); + clickViewPosition.y = (std::min)(int(topLeft.y + (mousePosition.y() / fontHeight)), topLeft.y + visibleCharDims.y - 1); + if (event->button() == Qt::LeftButton) { - QFontMetrics actualFont = fontMetrics(); - const double fontWidth = actualFont.width(QString(100, '_')) / 100.; - const int fontHeight = std::max(1, actualFont.lineSpacing()); - - debug_view_xy topLeft = m_view->visible_position(); - debug_view_xy clickViewPosition; - clickViewPosition.x = topLeft.x + (event->x() / fontWidth); - clickViewPosition.y = topLeft.y + (event->y() / fontHeight); m_view->process_click(DCK_LEFT_CLICK, clickViewPosition); - - viewport()->update(); - update(); } + else if (event->button() == Qt::MiddleButton) + { + m_view->process_click(DCK_MIDDLE_CLICK, clickViewPosition); + } + else if (event->button() == Qt::RightButton) + { + if (m_view->cursor_supported()) + { + m_view->set_cursor_position(clickViewPosition); + m_view->set_cursor_visible(true); + } + } + + viewport()->update(); + update(); +} + + +void DebuggerView::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu *const menu = new QMenu(this); + addItemsToContextMenu(menu); + menu->popup(event->globalPos()); +} + + +void DebuggerView::addItemsToContextMenu(QMenu *menu) +{ + QAction *const copyAct = new QAction("Copy Visible", menu); + QAction *const pasteAct = new QAction("Paste", menu); + pasteAct->setEnabled(QApplication::clipboard()->mimeData()->hasText()); + connect(copyAct, &QAction::triggered, this, &DebuggerView::copyVisibleSlot); + connect(pasteAct, &QAction::triggered, this, &DebuggerView::pasteSlot); + menu->addAction(copyAct); + menu->addAction(pasteAct); } @@ -267,13 +370,51 @@ void DebuggerView::horizontalScrollSlot(int value) } -void DebuggerView::debuggerViewUpdate(debug_view& debugView, void* osdPrivate) +void DebuggerView::copyVisibleSlot() { - // Get a handle to the DebuggerView being updated & redraw - DebuggerView* dView = (DebuggerView*)osdPrivate; + // get visible text + debug_view_xy const visarea = m_view->visible_size(); + debug_view_char const *viewdata = m_view->viewdata(); + if (!viewdata) + return; + + // turn into a plain string, trimming trailing whitespace + std::string text; + for (uint32_t row = 0; row < visarea.y; row++, viewdata += visarea.x) + { + std::string::size_type const start = text.length(); + for (uint32_t col = 0; col < visarea.x; ++col) + text += wchar_t(viewdata[col].byte); + std::string::size_type const nonblank = text.find_last_not_of("\t\n\v\r "); + if (nonblank != std::string::npos) + text.resize((std::max)(start, nonblank + 1)); + text += "\n"; + } + + // copy to the clipboard + QApplication::clipboard()->setText(text.c_str()); +} + + +void DebuggerView::pasteSlot() +{ + for (QChar ch : QApplication::clipboard()->text()) + { + if ((32 <= ch.unicode()) && (127 >= ch.unicode())) + m_view->process_char(ch.unicode()); + } +} + + +void DebuggerView::debuggerViewUpdate(debug_view &debugView, void *osdPrivate) +{ + // Get a handle to the DebuggerView being updated and redraw + DebuggerView *dView = reinterpret_cast<DebuggerView *>(osdPrivate); dView->verticalScrollBar()->setValue(dView->view()->visible_position().y); dView->horizontalScrollBar()->setValue(dView->view()->visible_position().x); dView->viewport()->update(); dView->update(); emit dView->updated(); } + +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/debuggerview.h b/src/osd/modules/debugger/qt/debuggerview.h index 2e1f35eb306..cc68dd69d30 100644 --- a/src/osd/modules/debugger/qt/debuggerview.h +++ b/src/osd/modules/debugger/qt/debuggerview.h @@ -1,50 +1,63 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_DEBUGGER_VIEW_H__ -#define __DEBUG_QT_DEBUGGER_VIEW_H__ +#ifndef MAME_DEBUGGER_QT_DEBUGGERVIEW_H +#define MAME_DEBUGGER_QT_DEBUGGERVIEW_H -#include <QtWidgets/QAbstractScrollArea> +#pragma once #include "debug/debugvw.h" +#include <QtWidgets/QAbstractScrollArea> +#include <QtWidgets/QMenu> + + +namespace osd::debugger::qt { class DebuggerView : public QAbstractScrollArea { Q_OBJECT public: - DebuggerView(const debug_view_type& type, - running_machine* machine, - QWidget* parent=nullptr); + DebuggerView(debug_view_type type, running_machine &machine, QWidget *parent = nullptr); virtual ~DebuggerView(); - void paintEvent(QPaintEvent* event); + virtual void paintEvent(QPaintEvent *event) override; // Setters and accessors void setPreferBottom(bool pb) { m_preferBottom = pb; } - debug_view* view() { return m_view; } + debug_view *view() { return m_view; } + template <typename T> T *view() { return downcast<T *>(m_view); } + int sourceIndex() const; + + virtual void restoreConfigurationFromNode(util::xml::data_node const &node); + virtual void saveConfigurationToNode(util::xml::data_node &node); signals: void updated(); protected: - void keyPressEvent(QKeyEvent* event); - void mousePressEvent(QMouseEvent* event); + virtual void keyPressEvent(QKeyEvent *event) override; + virtual void mousePressEvent(QMouseEvent *event) override; + virtual void contextMenuEvent(QContextMenuEvent *event) override; + + virtual void addItemsToContextMenu(QMenu *menu); private slots: void verticalScrollSlot(int value); void horizontalScrollSlot(int value); - + void copyVisibleSlot(); + void pasteSlot(); private: // Callback to allow MAME to refresh the view - static void debuggerViewUpdate(debug_view& debugView, void* osdPrivate); + static void debuggerViewUpdate(debug_view &debugView, void *osdPrivate); - bool m_preferBottom; + running_machine &m_machine; + debug_view *m_view; - debug_view* m_view; - running_machine* m_machine; + bool m_preferBottom; }; +} // namespace osd::debugger::qt -#endif +#endif // MAME_DEBUGGER_QT_DEBUGGERVIEW_H diff --git a/src/osd/modules/debugger/qt/deviceinformationwindow.cpp b/src/osd/modules/debugger/qt/deviceinformationwindow.cpp index 66142462a3b..2e06d8fb1ed 100644 --- a/src/osd/modules/debugger/qt/deviceinformationwindow.cpp +++ b/src/osd/modules/debugger/qt/deviceinformationwindow.cpp @@ -1,25 +1,28 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" +#include "deviceinformationwindow.h" + +#include "util/xmlfile.h" + #include <QtWidgets/QFrame> #include <QtWidgets/QLabel> #include <QtWidgets/QVBoxLayout> -#include "deviceinformationwindow.h" +namespace osd::debugger::qt { -DeviceInformationWindow::DeviceInformationWindow(running_machine* machine, device_t* device, QWidget* parent) : - WindowQt(machine, nullptr) +DeviceInformationWindow::DeviceInformationWindow(DebuggerQt &debugger, device_t *device, QWidget *parent) : + WindowQt(debugger, nullptr), + m_device(device) { - m_device = device; - - if (parent != nullptr) + if (parent) { QPoint parentPos = parent->pos(); setGeometry(parentPos.x()+100, parentPos.y()+100, 600, 400); } - if(m_device) + if (m_device) fill_device_information(); } @@ -28,12 +31,29 @@ DeviceInformationWindow::~DeviceInformationWindow() { } -void DeviceInformationWindow::fill_device_information() + +void DeviceInformationWindow::restoreConfiguration(util::xml::data_node const &node) { - char title[4069]; - sprintf(title, "Debug: Device %s", m_device->tag()); - setWindowTitle(title); + WindowQt::restoreConfiguration(node); + auto const tag = node.get_attribute_string(ATTR_WINDOW_DEVICE_TAG, ":"); + set_device(tag); +} + + +void DeviceInformationWindow::saveConfigurationToNode(util::xml::data_node &node) +{ + WindowQt::saveConfigurationToNode(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DEVICE_INFO_VIEWER); + + node.set_attribute(ATTR_WINDOW_DEVICE_TAG, m_device->tag()); +} + + +void DeviceInformationWindow::fill_device_information() +{ + setWindowTitle(util::string_format("Debug: Device %s", m_device->tag()).c_str()); QFrame *mainWindowFrame = new QFrame(this); QVBoxLayout *vLayout = new QVBoxLayout(mainWindowFrame); @@ -53,9 +73,11 @@ void DeviceInformationWindow::fill_device_information() int cpos = 3; device_interface *intf = m_device->interfaces().first(); - if(intf) { + if (intf) + { gl1->addWidget(new QLabel(QString("Interfaces"), primaryFrame), cpos, 0); - while(intf) { + while(intf) + { gl1->addWidget(new QLabel(QString(intf->interface_type()), primaryFrame), cpos, 1); cpos++; intf = intf->interface_next(); @@ -65,16 +87,19 @@ void DeviceInformationWindow::fill_device_information() vLayout->addWidget(primaryFrame); device_memory_interface *d_memory; - if(m_device->interface(d_memory)) { + if (m_device->interface(d_memory)) + { QFrame *f = new QFrame(mainWindowFrame); f->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); QVBoxLayout *vb = new QVBoxLayout(f); bool first = true; - for(int i=0; i<d_memory->max_space_count(); i++) - if(d_memory->has_space(i)) { + for (int i=0; i<d_memory->max_space_count(); i++) + if (d_memory->has_space(i)) + { QFrame *ff = new QFrame(f); QHBoxLayout *hb = new QHBoxLayout(ff); - if(first) { + if (first) + { hb->addWidget(new QLabel("Memory maps")); first = false; } @@ -92,46 +117,10 @@ void DeviceInformationWindow::fill_device_information() void DeviceInformationWindow::set_device(const char *tag) { - m_device = m_machine->root_device().subdevice(tag); - if(!m_device) - m_device = &m_machine->root_device(); + m_device = m_machine.root_device().subdevice(tag); + if (!m_device) + m_device = &m_machine.root_device(); fill_device_information(); } -const char *DeviceInformationWindow::device_tag() const -{ - return m_device->tag(); -} - - -//========================================================================= -// DeviceInformationWindowQtConfig -//========================================================================= -void DeviceInformationWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - DeviceInformationWindow* window = dynamic_cast<DeviceInformationWindow*>(widget); - m_device_tag = window->device_tag(); -} - - -void DeviceInformationWindowQtConfig::applyToQWidget(QWidget* widget) -{ - WindowQtConfig::applyToQWidget(widget); - DeviceInformationWindow* window = dynamic_cast<DeviceInformationWindow*>(widget); - window->set_device(m_device_tag.c_str()); -} - - -void DeviceInformationWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const -{ - WindowQtConfig::addToXmlDataNode(node); - node.set_attribute("device-tag", m_device_tag.c_str()); -} - - -void DeviceInformationWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); - m_device_tag = node.get_attribute_string("device-tag", ":"); -} +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/deviceinformationwindow.h b/src/osd/modules/debugger/qt/deviceinformationwindow.h index 5ed1bfbde91..e036a76e782 100644 --- a/src/osd/modules/debugger/qt/deviceinformationwindow.h +++ b/src/osd/modules/debugger/qt/deviceinformationwindow.h @@ -1,10 +1,15 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_DEVICE_INFORMATION_WINDOW_H__ -#define __DEBUG_QT_DEVICE_INFORMATION_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_DEVICEINFORMATIONWINDOW_H +#define MAME_DEBUGGER_QT_DEVICEINFORMATIONWINDOW_H + +#pragma once #include "windowqt.h" + +namespace osd::debugger::qt { + //============================================================ // The Device Information Window. //============================================================ @@ -13,11 +18,15 @@ class DeviceInformationWindow : public WindowQt Q_OBJECT public: - DeviceInformationWindow(running_machine* machine, device_t* device = nullptr, QWidget* parent=nullptr); + DeviceInformationWindow(DebuggerQt &debugger, device_t *device = nullptr, QWidget* parent=nullptr); virtual ~DeviceInformationWindow(); void set_device(const char *tag); - const char *device_tag() const; + + virtual void restoreConfiguration(util::xml::data_node const &node) override; + +protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; private: device_t *m_device; @@ -25,29 +34,6 @@ private: void fill_device_information(); }; +} // namespace osd::debugger::qt - - -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class DeviceInformationWindowQtConfig : public WindowQtConfig -{ -public: - std::string m_device_tag; - - DeviceInformationWindowQtConfig() : - WindowQtConfig(WIN_TYPE_DEVICE_INFORMATION) - { - } - - ~DeviceInformationWindowQtConfig() {} - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); -}; - - -#endif +#endif // MAME_DEBUGGER_QT_DEVICEINFORMATIONWINDOW_H diff --git a/src/osd/modules/debugger/qt/deviceswindow.cpp b/src/osd/modules/debugger/qt/deviceswindow.cpp index 6313e9bf98e..2c39c8cb0e8 100644 --- a/src/osd/modules/debugger/qt/deviceswindow.cpp +++ b/src/osd/modules/debugger/qt/deviceswindow.cpp @@ -2,11 +2,17 @@ // copyright-holders:Andrew Gardner #include "emu.h" #include "deviceswindow.h" + #include "deviceinformationwindow.h" -DevicesWindowModel::DevicesWindowModel(running_machine *machine, QObject *parent) +#include "util/xmlfile.h" + + +namespace osd::debugger::qt { + +DevicesWindowModel::DevicesWindowModel(running_machine &machine, QObject *parent) : + m_machine(machine) { - m_machine = machine; } DevicesWindowModel::~DevicesWindowModel() @@ -15,12 +21,13 @@ DevicesWindowModel::~DevicesWindowModel() QVariant DevicesWindowModel::data(const QModelIndex &index, int role) const { - if(!index.isValid() || role != Qt::DisplayRole) + if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); device_t *dev = static_cast<device_t *>(index.internalPointer()); - switch(index.column()) { - case 0: return dev == &m_machine->root_device() ? QString("<root>") : QString(dev->basetag()); + switch (index.column()) + { + case 0: return (dev == &m_machine.root_device()) ? QString("<root>") : QString(dev->basetag()); case 1: return QString(dev->name()); } @@ -29,38 +36,41 @@ QVariant DevicesWindowModel::data(const QModelIndex &index, int role) const Qt::ItemFlags DevicesWindowModel::flags(const QModelIndex &index) const { - if(!index.isValid()) - return 0; + if (!index.isValid()) + return Qt::NoItemFlags; return QAbstractItemModel::flags(index); } QVariant DevicesWindowModel::headerData(int section, Qt::Orientation orientation, int role) const { - if(role != Qt::DisplayRole || section < 0 || section >= 2) + if (role != Qt::DisplayRole || section < 0 || section >= 2) return QVariant(); return QString(section ? "Name" : "Tag"); } QModelIndex DevicesWindowModel::index(int row, int column, const QModelIndex &parent) const { - if(!hasIndex(row, column, parent)) + if (!hasIndex(row, column, parent)) return QModelIndex(); device_t *target = nullptr; - if(!parent.isValid()) { - if(row == 0) - target = &m_machine->root_device(); + if (!parent.isValid()) + { + if (row == 0) + target = &m_machine.root_device(); - } else { + } + else + { device_t *dparent = static_cast<device_t *>(parent.internalPointer()); int count = row; for(target = dparent->subdevices().first(); count && target; target = target->next()) count--; } - if(target) + if (target) return createIndex(row, column, target); return QModelIndex(); @@ -68,19 +78,20 @@ QModelIndex DevicesWindowModel::index(int row, int column, const QModelIndex &pa QModelIndex DevicesWindowModel::parent(const QModelIndex &index) const { - if(!index.isValid()) + if (!index.isValid()) return QModelIndex(); device_t *dchild = static_cast<device_t *>(index.internalPointer()); device_t *dparent = dchild->owner(); - if(!dparent) + if (!dparent) return QModelIndex(); device_t *dpp = dparent->owner(); int row = 0; - if(dpp) { - for(device_t *child = dpp->subdevices().first(); child && child != dparent; child = child->next()) + if (dpp) + { + for (device_t *child = dpp->subdevices().first(); child && child != dparent; child = child->next()) row++; } return createIndex(row, 0, dparent); @@ -88,7 +99,7 @@ QModelIndex DevicesWindowModel::parent(const QModelIndex &index) const int DevicesWindowModel::rowCount(const QModelIndex &parent) const { - if(!parent.isValid()) + if (!parent.isValid()) return 1; device_t *dparent = static_cast<device_t *>(parent.internalPointer()); @@ -102,9 +113,9 @@ int DevicesWindowModel::columnCount(const QModelIndex &parent) const -DevicesWindow::DevicesWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr), - m_devices_model(machine) +DevicesWindow::DevicesWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr), + m_devices_model(debugger.machine()) { m_selected_device = nullptr; @@ -143,35 +154,15 @@ void DevicesWindow::currentRowChanged(const QModelIndex ¤t, const QModelIn void DevicesWindow::activated(const QModelIndex &index) { device_t *dev = static_cast<device_t *>(index.internalPointer()); - (new DeviceInformationWindow(m_machine, dev, this))->show(); -} - - - -//========================================================================= -// DevicesWindowQtConfig -//========================================================================= -void DevicesWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - // DevicesWindow* window = dynamic_cast<DevicesWindow*>(widget); + (new DeviceInformationWindow(m_debugger, dev, this))->show(); } -void DevicesWindowQtConfig::applyToQWidget(QWidget* widget) +void DevicesWindow::saveConfigurationToNode(util::xml::data_node &node) { - WindowQtConfig::applyToQWidget(widget); - // DevicesWindow* window = dynamic_cast<DevicesWindow*>(widget); -} + WindowQt::saveConfigurationToNode(node); - -void DevicesWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const -{ - WindowQtConfig::addToXmlDataNode(node); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DEVICES_VIEWER); } - -void DevicesWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); -} +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/deviceswindow.h b/src/osd/modules/debugger/qt/deviceswindow.h index 87e710a001b..d337817fac0 100644 --- a/src/osd/modules/debugger/qt/deviceswindow.h +++ b/src/osd/modules/debugger/qt/deviceswindow.h @@ -1,12 +1,16 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_DEVICES_WINDOW_H__ -#define __DEBUG_QT_DEVICES_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_DEVICESWINDOW_H +#define MAME_DEBUGGER_QT_DEVICESWINDOW_H -#include <QtWidgets/QTreeView> +#pragma once #include "windowqt.h" +#include <QtWidgets/QTreeView> + + +namespace osd::debugger::qt { //============================================================ // The model for the treeview @@ -17,21 +21,19 @@ class DevicesWindowModel : public QAbstractItemModel Q_OBJECT public: - explicit DevicesWindowModel(running_machine *machine, QObject *parent = 0); + explicit DevicesWindowModel(running_machine &machine, QObject *parent = nullptr); ~DevicesWindowModel(); QVariant data(const QModelIndex &index, int role) const; Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; private: - running_machine *m_machine; + running_machine &m_machine; }; //============================================================ @@ -42,40 +44,22 @@ class DevicesWindow : public WindowQt Q_OBJECT public: - DevicesWindow(running_machine* machine, QWidget* parent=nullptr); + DevicesWindow(DebuggerQt &debugger, QWidget *parent = nullptr); virtual ~DevicesWindow(); public slots: void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); void activated(const QModelIndex &index); +protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; + private: QTreeView *m_devices_view; DevicesWindowModel m_devices_model; device_t *m_selected_device; }; +} // namespace osd::debugger::qt - - -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class DevicesWindowQtConfig : public WindowQtConfig -{ -public: - DevicesWindowQtConfig() : - WindowQtConfig(WIN_TYPE_DEVICES) - { - } - - ~DevicesWindowQtConfig() {} - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); -}; - - -#endif +#endif // MAME_DEBUGGER_QT_DEVICESWINDOW_H diff --git a/src/osd/modules/debugger/qt/logwindow.cpp b/src/osd/modules/debugger/qt/logwindow.cpp index d0478a24e40..c3a6b442f0f 100644 --- a/src/osd/modules/debugger/qt/logwindow.cpp +++ b/src/osd/modules/debugger/qt/logwindow.cpp @@ -1,21 +1,21 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" -#include <QtWidgets/QVBoxLayout> - #include "logwindow.h" -#include "debug/debugcon.h" -#include "debug/debugcpu.h" -#include "debug/dvdisasm.h" +#include "util/xmlfile.h" + +#include <QtWidgets/QVBoxLayout> + +namespace osd::debugger::qt { -LogWindow::LogWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr) +LogWindow::LogWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr) { setWindowTitle("Debug: Machine Log"); - if (parent != nullptr) + if (parent) { QPoint parentPos = parent->pos(); setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400); @@ -24,12 +24,10 @@ LogWindow::LogWindow(running_machine* machine, QWidget* parent) : // // The main frame and its input and log widgets // - QFrame* mainWindowFrame = new QFrame(this); + QFrame *mainWindowFrame = new QFrame(this); // The main log view - m_logView = new DebuggerView(DVT_LOG, - m_machine, - this); + m_logView = new DebuggerView(DVT_LOG, m_machine, this); // Layout QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); @@ -46,28 +44,21 @@ LogWindow::~LogWindow() } -//========================================================================= -// LogWindowQtConfig -//========================================================================= -void LogWindowQtConfig::buildFromQWidget(QWidget* widget) +void LogWindow::restoreConfiguration(util::xml::data_node const &node) { - WindowQtConfig::buildFromQWidget(widget); -} + WindowQt::restoreConfiguration(node); - -void LogWindowQtConfig::applyToQWidget(QWidget* widget) -{ - WindowQtConfig::applyToQWidget(widget); + m_logView->restoreConfigurationFromNode(node); } -void LogWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const +void LogWindow::saveConfigurationToNode(util::xml::data_node &node) { - WindowQtConfig::addToXmlDataNode(node); -} + WindowQt::saveConfigurationToNode(node); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_ERROR_LOG_VIEWER); -void LogWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); + m_logView->saveConfigurationToNode(node); } + +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/logwindow.h b/src/osd/modules/debugger/qt/logwindow.h index 53228ceafca..f85d490ea75 100644 --- a/src/osd/modules/debugger/qt/logwindow.h +++ b/src/osd/modules/debugger/qt/logwindow.h @@ -1,12 +1,16 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_LOG_WINDOW_H__ -#define __DEBUG_QT_LOG_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_LOGWINDOW_H +#define MAME_DEBUGGER_QT_LOGWINDOW_H + +#pragma once #include "debuggerview.h" #include "windowqt.h" +namespace osd::debugger::qt { + //============================================================ // The Log Window. //============================================================ @@ -15,34 +19,19 @@ class LogWindow : public WindowQt Q_OBJECT public: - LogWindow(running_machine* machine, QWidget* parent=nullptr); + LogWindow(DebuggerQt &debugger, QWidget *parent = nullptr); virtual ~LogWindow(); + virtual void restoreConfiguration(util::xml::data_node const &node) override; + +protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; private: // Widgets - DebuggerView* m_logView; -}; - - -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class LogWindowQtConfig : public WindowQtConfig -{ -public: - LogWindowQtConfig() : - WindowQtConfig(WIN_TYPE_LOG) - { - } - - ~LogWindowQtConfig() {} - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); + DebuggerView *m_logView; }; +} // namespace osd::debugger::qt -#endif +#endif // MAME_DEBUGGER_QT_LOGWINDOW_H diff --git a/src/osd/modules/debugger/qt/mainwindow.cpp b/src/osd/modules/debugger/qt/mainwindow.cpp index 6a79ebf955d..0085dac364b 100644 --- a/src/osd/modules/debugger/qt/mainwindow.cpp +++ b/src/osd/modules/debugger/qt/mainwindow.cpp @@ -1,47 +1,57 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" -#include <QtWidgets/QAction> -#include <QtWidgets/QMenu> -#include <QtWidgets/QMenuBar> -#include <QtWidgets/QDockWidget> -#include <QtWidgets/QScrollBar> -#include <QtWidgets/QFileDialog> -#include <QtGui/QCloseEvent> - #include "mainwindow.h" +#include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" #include "debug/dvdisasm.h" +#include "debug/points.h" +#include "util/xmlfile.h" -MainWindow::MainWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr), - m_historyIndex(0), - m_inputHistory() +#include <QtGui/QCloseEvent> +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include <QtGui/QAction> +#include <QtGui/QActionGroup> +#else +#include <QtWidgets/QAction> +#endif +#include <QtWidgets/QDockWidget> +#include <QtWidgets/QFileDialog> +#include <QtWidgets/QMenu> +#include <QtWidgets/QMenuBar> +#include <QtWidgets/QScrollBar> + + +namespace osd::debugger::qt { + +MainWindow::MainWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr), + m_inputHistory(), + m_exiting(false) { setGeometry(300, 300, 1000, 600); // // The main frame and its input and log widgets // - QFrame* mainWindowFrame = new QFrame(this); + QFrame *mainWindowFrame = new QFrame(this); // The input line m_inputEdit = new QLineEdit(mainWindowFrame); connect(m_inputEdit, &QLineEdit::returnPressed, this, &MainWindow::executeCommandSlot); + connect(m_inputEdit, &QLineEdit::textEdited, this, &MainWindow::commandEditedSlot); m_inputEdit->installEventFilter(this); // The log view - m_consoleView = new DebuggerView(DVT_CONSOLE, - m_machine, - mainWindowFrame); + m_consoleView = new DebuggerView(DVT_CONSOLE, m_machine, mainWindowFrame); m_consoleView->setFocusPolicy(Qt::NoFocus); m_consoleView->setPreferBottom(true); - QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); + QVBoxLayout *vLayout = new QVBoxLayout(mainWindowFrame); vLayout->addWidget(m_consoleView); vLayout->addWidget(m_inputEdit); vLayout->setSpacing(3); @@ -57,18 +67,21 @@ MainWindow::MainWindow(running_machine* machine, QWidget* parent) : m_breakpointEnableAct = new QAction("Disable Breakpoint at Cursor", this); m_runToCursorAct = new QAction("Run to Cursor", this); m_breakpointToggleAct->setShortcut(Qt::Key_F9); - m_breakpointEnableAct->setShortcut(Qt::SHIFT + Qt::Key_F9); + m_breakpointEnableAct->setShortcut(Qt::SHIFT | Qt::Key_F9); m_runToCursorAct->setShortcut(Qt::Key_F4); connect(m_breakpointToggleAct, &QAction::triggered, this, &MainWindow::toggleBreakpointAtCursor); connect(m_breakpointEnableAct, &QAction::triggered, this, &MainWindow::enableBreakpointAtCursor); connect(m_runToCursorAct, &QAction::triggered, this, &MainWindow::runToCursor); // Right bar options - QActionGroup* rightBarGroup = new QActionGroup(this); + QActionGroup *rightBarGroup = new QActionGroup(this); rightBarGroup->setObjectName("rightbargroup"); - QAction* rightActRaw = new QAction("Raw Opcodes", this); - QAction* rightActEncrypted = new QAction("Encrypted Opcodes", this); - QAction* rightActComments = new QAction("Comments", this); + QAction *rightActRaw = new QAction("Raw Opcodes", this); + QAction *rightActEncrypted = new QAction("Encrypted Opcodes", this); + QAction *rightActComments = new QAction("Comments", this); + rightActRaw->setData(int(DASM_RIGHTCOL_RAW)); + rightActEncrypted->setData(int(DASM_RIGHTCOL_ENCRYPTED)); + rightActComments->setData(int(DASM_RIGHTCOL_COMMENTS)); rightActRaw->setCheckable(true); rightActEncrypted->setCheckable(true); rightActComments->setCheckable(true); @@ -82,7 +95,7 @@ MainWindow::MainWindow(running_machine* machine, QWidget* parent) : connect(rightBarGroup, &QActionGroup::triggered, this, &MainWindow::rightBarChanged); // Assemble the options menu - QMenu* optionsMenu = menuBar()->addMenu("&Options"); + QMenu *optionsMenu = menuBar()->addMenu("&Options"); optionsMenu->addAction(m_breakpointToggleAct); optionsMenu->addAction(m_breakpointEnableAct); optionsMenu->addAction(m_runToCursorAct); @@ -92,22 +105,20 @@ MainWindow::MainWindow(running_machine* machine, QWidget* parent) : // // Images menu // - image_interface_iterator imageIterTest(m_machine->root_device()); - if (imageIterTest.first() != nullptr) - { + image_interface_enumerator imageIterTest(m_machine.root_device()); + if (imageIterTest.first()) createImagesMenu(); - } // // Dock window menu // - QMenu* dockMenu = menuBar()->addMenu("Doc&ks"); + QMenu *dockMenu = menuBar()->addMenu("Doc&ks"); setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); // The processor dock - QDockWidget* cpuDock = new QDockWidget("processor", this); + QDockWidget *cpuDock = new QDockWidget("processor", this); cpuDock->setObjectName("cpudock"); cpuDock->setAllowedAreas(Qt::LeftDockWidgetArea); m_procFrame = new ProcessorDockWidget(m_machine, cpuDock); @@ -117,7 +128,7 @@ MainWindow::MainWindow(running_machine* machine, QWidget* parent) : dockMenu->addAction(cpuDock->toggleViewAction()); // The disassembly dock - QDockWidget* dasmDock = new QDockWidget("dasm", this); + QDockWidget *dasmDock = new QDockWidget("dasm", this); dasmDock->setObjectName("dasmdock"); dasmDock->setAllowedAreas(Qt::TopDockWidgetArea); m_dasmFrame = new DasmDockWidget(m_machine, dasmDock); @@ -134,7 +145,7 @@ MainWindow::~MainWindow() } -void MainWindow::setProcessor(device_t* processor) +void MainWindow::setProcessor(device_t *processor) { // Cpu swap m_procFrame->view()->view()->set_source(*m_procFrame->view()->view()->source_for_device(processor)); @@ -145,150 +156,172 @@ void MainWindow::setProcessor(device_t* processor) m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y); // Window title - string_format("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag()); - setWindowTitle(string_format("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag()).c_str()); + setWindowTitle(string_format("Debug: %s - %s '%s'", m_machine.system().name, processor->name(), processor->tag()).c_str()); } -// Used to intercept the user clicking 'X' in the upper corner -void MainWindow::closeEvent(QCloseEvent* event) +void MainWindow::restoreConfiguration(util::xml::data_node const &node) { - debugActQuit(); + WindowQt::restoreConfiguration(node); + + debug_view_disasm &dasmview = *m_dasmFrame->view()->view<debug_view_disasm>(); - // Insure the window doesn't disappear before we get a chance to save its parameters - event->ignore(); + restoreState(QByteArray::fromPercentEncoding(node.get_attribute_string("qtwindowstate", ""))); + + auto const rightbar = node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()); + QActionGroup *const rightBarGroup = findChild<QActionGroup *>("rightbargroup"); + for (QAction *action : rightBarGroup->actions()) + { + if (action->data().toInt() == rightbar) + { + action->trigger(); + break; + } + } + + m_dasmFrame->view()->restoreConfigurationFromNode(node); + m_inputHistory.restoreConfigurationFromNode(node); } -// Used to intercept the user hitting the up arrow in the input widget -bool MainWindow::eventFilter(QObject* obj, QEvent* event) +void MainWindow::saveConfigurationToNode(util::xml::data_node &node) { - // Only filter keypresses - QKeyEvent* keyEvent = nullptr; - if (event->type() == QEvent::KeyPress) + WindowQt::saveConfigurationToNode(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_CONSOLE); + + debug_view_disasm &dasmview = *m_dasmFrame->view()->view<debug_view_disasm>(); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()); + node.set_attribute("qtwindowstate", saveState().toPercentEncoding().data()); + + m_dasmFrame->view()->saveConfigurationToNode(node); + m_inputHistory.saveConfigurationToNode(node); +} + + +// Used to intercept the user clicking 'X' in the upper corner +void MainWindow::closeEvent(QCloseEvent *event) +{ + if (!m_exiting) { - keyEvent = static_cast<QKeyEvent*>(event); + // Don't actually close the window - it will be brought back on user break + debugActRunAndHide(); + event->ignore(); } - else - { +} + + +// Used to intercept the user hitting the up arrow in the input widget +bool MainWindow::eventFilter(QObject *obj, QEvent *event) +{ + // Only filter keypresses + if (event->type() != QEvent::KeyPress) return QObject::eventFilter(obj, event); - } + + QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event); // Catch up & down keys - if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) + if (keyEvent.key() == Qt::Key_Escape) { - if (keyEvent->key() == Qt::Key_Up) - { - if (m_historyIndex > 0) - m_historyIndex--; - } - else if (keyEvent->key() == Qt::Key_Down) - { - if (m_historyIndex < m_inputHistory.size()) - m_historyIndex++; - } - - // Populate the input edit or clear it if you're at the end - if (m_historyIndex == m_inputHistory.size()) + m_inputEdit->clear(); + m_inputHistory.reset(); + return true; + } + else if (keyEvent.key() == Qt::Key_Up) + { + QString const *const hist = m_inputHistory.previous(m_inputEdit->text()); + if (hist) { - m_inputEdit->setText(""); + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); } - else + return true; + } + else if (keyEvent.key() == Qt::Key_Down) + { + QString const *const hist = m_inputHistory.next(m_inputEdit->text()); + if (hist) { - m_inputEdit->setText(m_inputHistory[m_historyIndex]); + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); } + return true; } - else if (keyEvent->key() == Qt::Key_Enter) + else if (keyEvent.key() == Qt::Key_Enter) { executeCommand(false); + return true; } else { return QObject::eventFilter(obj, event); } - - return true; } void MainWindow::toggleBreakpointAtCursor(bool changedTo) { - debug_view_disasm *const dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); - if (dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device())) + debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>(); + if (dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device())) { - offs_t const address = downcast<debug_view_disasm *>(dasmView)->selected_address(); + offs_t const address = dasmView->selected_address(); device_debug *const cpuinfo = dasmView->source()->device()->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); // If none exists, add a new one std::string command; - if (bp == nullptr) - { + if (!bp) command = string_format("bpset 0x%X", address); - } else - { command = string_format("bpclear 0x%X", bp->index()); - } - m_machine->debugger().console().execute_command(command.c_str(), true); + m_machine.debugger().console().execute_command(command, true); + m_machine.debug_view().update_all(); + m_machine.debugger().refresh_display(); } - - refreshAll(); } void MainWindow::enableBreakpointAtCursor(bool changedTo) { - debug_view_disasm *const dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); - if (dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device())) + debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>(); + if (dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device())) { offs_t const address = dasmView->selected_address(); device_debug *const cpuinfo = dasmView->source()->device()->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); - if (bp != nullptr) + if (bp) { int32_t const bpindex = bp->index(); std::string command = string_format(bp->enabled() ? "bpdisable 0x%X" : "bpenable 0x%X", bpindex); - m_machine->debugger().console().execute_command(command.c_str(), true); + m_machine.debugger().console().execute_command(command, true); + m_machine.debug_view().update_all(); + m_machine.debugger().refresh_display(); } } - - refreshAll(); } void MainWindow::runToCursor(bool changedTo) { - debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); - if (dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device())) + debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>(); + if (dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device())) { - offs_t address = downcast<debug_view_disasm*>(dasmView)->selected_address(); + offs_t address = dasmView->selected_address(); std::string command = string_format("go 0x%X", address); - m_machine->debugger().console().execute_command(command.c_str(), true); + m_machine.debugger().console().execute_command(command, true); } } -void MainWindow::rightBarChanged(QAction* changedTo) +void MainWindow::rightBarChanged(QAction *changedTo) { - debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); - if (changedTo->text() == "Raw Opcodes") - { - dasmView->set_right_column(DASM_RIGHTCOL_RAW); - } - else if (changedTo->text() == "Encrypted Opcodes") - { - dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED); - } - else if (changedTo->text() == "Comments") - { - dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS); - } + debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>(); + dasmView->set_right_column(disasm_right_column(changedTo->data().toInt())); m_dasmFrame->view()->viewport()->update(); } @@ -297,33 +330,35 @@ void MainWindow::executeCommandSlot() executeCommand(true); } -void MainWindow::executeCommand(bool withClear) +void MainWindow::commandEditedSlot(QString const &text) { - QString command = m_inputEdit->text(); + m_inputHistory.edit(); +} - // A blank command is a "silent step" +void MainWindow::executeCommand(bool withClear) +{ + QString const command = m_inputEdit->text(); if (command == "") { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); - return; + // A blank command is a "silent step" + m_machine.debugger().console().get_visible_cpu()->debug()->single_step(); + m_inputHistory.reset(); } + else + { + // Send along the command + m_machine.debugger().console().execute_command(command.toUtf8().data(), true); - // Send along the command - m_machine->debugger().console().execute_command(command.toLocal8Bit().data(), true); - - // Add history & set the index to be the top of the stack - addToHistory(command); + // Add history + m_inputHistory.add(command); - // Clear out the text and reset the history pointer only if asked - if (withClear) - { - m_inputEdit->clear(); - m_historyIndex = m_inputHistory.size(); + // Clear out the text and reset the history pointer only if asked + if (withClear) + { + m_inputEdit->clear(); + m_inputHistory.edit(); + } } - - // Refresh - m_consoleView->viewport()->update(); - refreshAll(); } @@ -331,25 +366,25 @@ void MainWindow::mountImage(bool changedTo) { // The image interface index was assigned to the QAction's data memeber const int imageIndex = dynamic_cast<QAction*>(sender())->data().toInt(); - image_interface_iterator iter(m_machine->root_device()); + image_interface_enumerator iter(m_machine.root_device()); device_image_interface *img = iter.byindex(imageIndex); - if (img == nullptr) + if (!img) { - m_machine->debugger().console().printf("Something is wrong with the mount menu.\n"); - refreshAll(); + m_machine.debugger().console().printf("Something is wrong with the mount menu.\n"); return; } // File dialog - QString filename = QFileDialog::getOpenFileName(this, - "Select an image file", - QDir::currentPath(), - tr("All files (*.*)")); - - if (img->load(filename.toUtf8().data()) != image_init_result::PASS) + QString filename = QFileDialog::getOpenFileName( + this, + "Select an image file", + QDir::currentPath(), + tr("All files (*.*)")); + + auto [err, message] = img->load(filename.toUtf8().data()); + if (err) { - m_machine->debugger().console().printf("Image could not be mounted.\n"); - refreshAll(); + m_machine.debugger().console().printf("Image could not be mounted: %s\n", !message.empty() ? message : err.message()); return; } @@ -358,45 +393,43 @@ void MainWindow::mountImage(bool changedTo) unmountAct->setEnabled(true); // Set the mount name - QMenu* parentMenuItem = dynamic_cast<QMenu*>(sender()->parent()); + QMenu *parentMenuItem = dynamic_cast<QMenu *>(sender()->parent()); QString baseString = parentMenuItem->title(); baseString.truncate(baseString.lastIndexOf(QString(" : "))); const QString newTitle = baseString + QString(" : ") + QString(img->filename()); parentMenuItem->setTitle(newTitle); - m_machine->debugger().console().printf("Image %s mounted successfully.\n", filename.toUtf8().data()); - refreshAll(); + m_machine.debugger().console().printf("Image %s mounted successfully.\n", filename.toUtf8().data()); } void MainWindow::unmountImage(bool changedTo) { // The image interface index was assigned to the QAction's data memeber - const int imageIndex = dynamic_cast<QAction*>(sender())->data().toInt(); - image_interface_iterator iter(m_machine->root_device()); + const int imageIndex = dynamic_cast<QAction *>(sender())->data().toInt(); + image_interface_enumerator iter(m_machine.root_device()); device_image_interface *img = iter.byindex(imageIndex); img->unload(); // Deactivate the unmount menu option - dynamic_cast<QAction*>(sender())->setEnabled(false); + dynamic_cast<QAction *>(sender())->setEnabled(false); // Set the mount name - QMenu* parentMenuItem = dynamic_cast<QMenu*>(sender()->parent()); + QMenu *parentMenuItem = dynamic_cast<QMenu *>(sender()->parent()); QString baseString = parentMenuItem->title(); baseString.truncate(baseString.lastIndexOf(QString(" : "))); const QString newTitle = baseString + QString(" : ") + QString("[empty slot]"); parentMenuItem->setTitle(newTitle); - m_machine->debugger().console().printf("Image successfully unmounted.\n"); - refreshAll(); + m_machine.debugger().console().printf("Image successfully unmounted.\n"); } void MainWindow::dasmViewUpdated() { - debug_view_disasm *const dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); - bool const haveCursor = dasmView->cursor_visible() && (m_machine->debugger().cpu().get_visible_cpu() == dasmView->source()->device()); + debug_view_disasm *const dasmView = m_dasmFrame->view()->view<debug_view_disasm>(); + bool const haveCursor = dasmView->cursor_visible() && (m_machine.debugger().console().get_visible_cpu() == dasmView->source()->device()); bool haveBreakpoint = false; bool breakpointEnabled = false; if (haveCursor) @@ -406,9 +439,9 @@ void MainWindow::dasmViewUpdated() device_debug *const cpuinfo = device->debug(); // Find an existing breakpoint at this address - const device_debug::breakpoint *bp = cpuinfo->breakpoint_find(address); + const debug_breakpoint *bp = cpuinfo->breakpoint_find(address); - if (bp != nullptr) + if (bp) { haveBreakpoint = true; breakpointEnabled = bp->enabled(); @@ -425,44 +458,32 @@ void MainWindow::dasmViewUpdated() void MainWindow::debugActClose() { - m_machine->schedule_exit(); + m_machine.schedule_exit(); } -void MainWindow::addToHistory(const QString& command) +void MainWindow::debuggerExit() { - if (command == "") - return; - - // Always push back when there is no previous history - if (m_inputHistory.size() == 0) - { - m_inputHistory.push_back(m_inputEdit->text()); - return; - } - - // If there is previous history, make sure it's not what you just executed - if (m_inputHistory.back() != m_inputEdit->text()) - { - m_inputHistory.push_back(m_inputEdit->text()); - } + // this isn't called from a Qt event loop, so close() will leak the window object + m_exiting = true; + delete this; } void MainWindow::createImagesMenu() { - QMenu* imagesMenu = menuBar()->addMenu("&Images"); + QMenu *imagesMenu = menuBar()->addMenu("&Images"); int interfaceIndex = 0; - for (device_image_interface &img : image_interface_iterator(m_machine->root_device())) + for (device_image_interface &img : image_interface_enumerator(m_machine.root_device())) { std::string menuName = string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[empty slot]"); - QMenu* interfaceMenu = imagesMenu->addMenu(menuName.c_str()); + QMenu *interfaceMenu = imagesMenu->addMenu(menuName.c_str()); interfaceMenu->setObjectName(img.device().name()); - QAction* mountAct = new QAction("Mount...", interfaceMenu); - QAction* unmountAct = new QAction("Unmount", interfaceMenu); + QAction *mountAct = new QAction("Mount...", interfaceMenu); + QAction *unmountAct = new QAction("Unmount", interfaceMenu); mountAct->setObjectName("mount"); mountAct->setData(QVariant(interfaceIndex)); unmountAct->setObjectName("unmount"); @@ -483,52 +504,6 @@ void MainWindow::createImagesMenu() } -//========================================================================= -// MainWindowQtConfig -//========================================================================= -void MainWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - MainWindow* window = dynamic_cast<MainWindow*>(widget); - m_windowState = window->saveState(); - - QActionGroup* rightBarGroup = window->findChild<QActionGroup*>("rightbargroup"); - if (rightBarGroup->checkedAction()->text() == "Raw Opcodes") - m_rightBar = 0; - else if (rightBarGroup->checkedAction()->text() == "Encrypted Opcodes") - m_rightBar = 1; - else if (rightBarGroup->checkedAction()->text() == "Comments") - m_rightBar = 2; -} - - -void MainWindowQtConfig::applyToQWidget(QWidget* widget) -{ - WindowQtConfig::applyToQWidget(widget); - MainWindow* window = dynamic_cast<MainWindow*>(widget); - window->restoreState(m_windowState); - - QActionGroup* rightBarGroup = window->findChild<QActionGroup*>("rightbargroup"); - rightBarGroup->actions()[m_rightBar]->trigger(); -} - - -void MainWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const -{ - WindowQtConfig::addToXmlDataNode(node); - node.set_attribute_int("rightbar", m_rightBar); - node.set_attribute("qtwindowstate", m_windowState.toPercentEncoding().data()); -} - - -void MainWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); - const char* state = node.get_attribute_string("qtwindowstate", ""); - m_windowState = QByteArray::fromPercentEncoding(state); - m_rightBar = node.get_attribute_int("rightbar", m_rightBar); -} - DasmDockWidget::~DasmDockWidget() { } @@ -536,3 +511,5 @@ DasmDockWidget::~DasmDockWidget() ProcessorDockWidget::~ProcessorDockWidget() { } + +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/mainwindow.h b/src/osd/modules/debugger/qt/mainwindow.h index 95a4e53ca99..762874b6aee 100644 --- a/src/osd/modules/debugger/qt/mainwindow.h +++ b/src/osd/modules/debugger/qt/mainwindow.h @@ -1,18 +1,23 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_MAIN_WINDOW_H__ -#define __DEBUG_QT_MAIN_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_MAINWINDOW_H +#define MAME_DEBUGGER_QT_MAINWINDOW_H -#include <vector> +#pragma once + +#include "debuggerview.h" +#include "windowqt.h" + +#include "debug/dvdisasm.h" #include <QtWidgets/QLineEdit> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QComboBox> -#include "debug/dvdisasm.h" +#include <deque> -#include "debuggerview.h" -#include "windowqt.h" + +namespace osd::debugger::qt { class DasmDockWidget; class ProcessorDockWidget; @@ -26,56 +31,60 @@ class MainWindow : public WindowQt Q_OBJECT public: - MainWindow(running_machine* machine, QWidget* parent=nullptr); + MainWindow(DebuggerQt &debugger, QWidget *parent = nullptr); virtual ~MainWindow(); - void setProcessor(device_t* processor); + void setProcessor(device_t *processor); + virtual void restoreConfiguration(util::xml::data_node const &node) override; protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; + // Used to intercept the user clicking 'X' in the upper corner - void closeEvent(QCloseEvent* event); + virtual void closeEvent(QCloseEvent *event) override; // Used to intercept the user hitting the up arrow in the input widget - bool eventFilter(QObject* obj, QEvent* event); - + virtual bool eventFilter(QObject *obj, QEvent *event) override; private slots: void toggleBreakpointAtCursor(bool changedTo); void enableBreakpointAtCursor(bool changedTo); void runToCursor(bool changedTo); - void rightBarChanged(QAction* changedTo); + void rightBarChanged(QAction *changedTo); void executeCommandSlot(); + void commandEditedSlot(QString const &text); void mountImage(bool changedTo); void unmountImage(bool changedTo); void dasmViewUpdated(); - // Closing the main window actually exits the program - void debugActClose(); - + // Closing the main window hides the debugger and runs the emulated system + virtual void debugActClose() override; + virtual void debuggerExit() override; private: void createImagesMenu(); + void executeCommand(bool withClear); + // Widgets and docks - QLineEdit* m_inputEdit; - DebuggerView* m_consoleView; - ProcessorDockWidget* m_procFrame; - DasmDockWidget* m_dasmFrame; + QLineEdit *m_inputEdit; + DebuggerView *m_consoleView; + ProcessorDockWidget *m_procFrame; + DasmDockWidget *m_dasmFrame; // Menu items - QAction* m_breakpointToggleAct; - QAction* m_breakpointEnableAct; - QAction* m_runToCursorAct; + QAction *m_breakpointToggleAct; + QAction *m_breakpointEnableAct; + QAction *m_runToCursorAct; // Terminal history - int m_historyIndex; - std::vector<QString> m_inputHistory; - void addToHistory(const QString& command); - void executeCommand(bool withClear); + CommandHistory m_inputHistory; + + bool m_exiting; }; @@ -87,45 +96,31 @@ class DasmDockWidget : public QWidget Q_OBJECT public: - DasmDockWidget(running_machine* machine, QWidget* parent=nullptr) : + DasmDockWidget(running_machine &machine, QWidget *parent = nullptr) : QWidget(parent), m_machine(machine) { - m_dasmView = new DebuggerView(DVT_DISASSEMBLY, - m_machine, - this); + m_dasmView = new DebuggerView(DVT_DISASSEMBLY, m_machine, this); // Force a recompute of the disassembly region downcast<debug_view_disasm*>(m_dasmView->view())->set_expression("curpc"); - QVBoxLayout* dvLayout = new QVBoxLayout(this); + QVBoxLayout *dvLayout = new QVBoxLayout(this); dvLayout->addWidget(m_dasmView); dvLayout->setContentsMargins(4,0,4,0); } - virtual ~DasmDockWidget(); + DebuggerView *view() { return m_dasmView; } - DebuggerView* view() { return m_dasmView; } - - - QSize minimumSizeHint() const - { - return QSize(150,150); - } - - - QSize sizeHint() const - { - return QSize(150,200); - } - + QSize minimumSizeHint() const { return QSize(150, 150); } + QSize sizeHint() const { return QSize(150, 200); } private: - DebuggerView* m_dasmView; + running_machine &m_machine; - running_machine* m_machine; + DebuggerView *m_dasmView; }; @@ -137,72 +132,32 @@ class ProcessorDockWidget : public QWidget Q_OBJECT public: - ProcessorDockWidget(running_machine* machine, - QWidget* parent=nullptr) : + ProcessorDockWidget(running_machine &machine, QWidget *parent = nullptr) : QWidget(parent), - m_processorView(nullptr), - m_machine(machine) + m_machine(machine), + m_processorView(nullptr) { - m_processorView = new DebuggerView(DVT_STATE, - m_machine, - this); + m_processorView = new DebuggerView(DVT_STATE, m_machine, this); m_processorView->setFocusPolicy(Qt::NoFocus); - QVBoxLayout* cvLayout = new QVBoxLayout(this); + QVBoxLayout *cvLayout = new QVBoxLayout(this); cvLayout->addWidget(m_processorView); cvLayout->setContentsMargins(4,0,4,2); } - virtual ~ProcessorDockWidget(); + DebuggerView *view() { return m_processorView; } - DebuggerView* view() { return m_processorView; } - - - QSize minimumSizeHint() const - { - return QSize(150,300); - } - - - QSize sizeHint() const - { - return QSize(200,300); - } - + QSize minimumSizeHint() const { return QSize(150, 300); } + QSize sizeHint() const { return QSize(200, 300); } private: - DebuggerView* m_processorView; - - running_machine* m_machine; -}; - + running_machine &m_machine; -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class MainWindowQtConfig : public WindowQtConfig -{ -public: - MainWindowQtConfig() : - WindowQtConfig(WIN_TYPE_MAIN), - m_rightBar(0), - m_windowState() - {} - - ~MainWindowQtConfig() {} - - // Settings - int m_rightBar; - QByteArray m_windowState; - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); + DebuggerView *m_processorView; }; +} // namespace osd::debugger::qt - -#endif +#endif // MAME_DEBUGGER_QT_MAINWINDOW_H diff --git a/src/osd/modules/debugger/qt/memorywindow.cpp b/src/osd/modules/debugger/qt/memorywindow.cpp index c799ab66c65..ec250055383 100644 --- a/src/osd/modules/debugger/qt/memorywindow.cpp +++ b/src/osd/modules/debugger/qt/memorywindow.cpp @@ -1,9 +1,23 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" +#include "memorywindow.h" + +#include "debugger.h" +#include "debug/dvmemory.h" +#include "debug/debugcon.h" +#include "debug/debugcpu.h" + +#include "util/xmlfile.h" + #include <QtGui/QClipboard> +#include <QtGui/QKeyEvent> #include <QtGui/QMouseEvent> +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include <QtGui/QActionGroup> +#else #include <QtWidgets/QActionGroup> +#endif #include <QtWidgets/QApplication> #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QMenu> @@ -12,19 +26,16 @@ #include <QtWidgets/QToolTip> #include <QtWidgets/QVBoxLayout> -#include "memorywindow.h" - -#include "debug/dvmemory.h" -#include "debug/debugcon.h" -#include "debug/debugcpu.h" +namespace osd::debugger::qt { -MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : - WindowQt(machine, nullptr) +MemoryWindow::MemoryWindow(DebuggerQt &debugger, QWidget *parent) : + WindowQt(debugger, nullptr), + m_inputHistory() { setWindowTitle("Debug: Memory View"); - if (parent != nullptr) + if (parent) { QPoint parentPos = parent->pos(); setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400); @@ -33,32 +44,34 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : // // The main frame and its input and log widgets // - QFrame* mainWindowFrame = new QFrame(this); + QFrame *mainWindowFrame = new QFrame(this); // The top frame & groupbox that contains the input widgets - QFrame* topSubFrame = new QFrame(mainWindowFrame); + QFrame *topSubFrame = new QFrame(mainWindowFrame); // The input edit m_inputEdit = new QLineEdit(topSubFrame); connect(m_inputEdit, &QLineEdit::returnPressed, this, &MemoryWindow::expressionSubmitted); + connect(m_inputEdit, &QLineEdit::textEdited, this, &MemoryWindow::expressionEdited); + m_inputEdit->installEventFilter(this); // The memory space combo box m_memoryComboBox = new QComboBox(topSubFrame); m_memoryComboBox->setObjectName("memoryregion"); m_memoryComboBox->setMinimumWidth(300); - connect(m_memoryComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MemoryWindow::memoryRegionChanged); + connect(m_memoryComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MemoryWindow::memoryRegionChanged); // The main memory window m_memTable = new DebuggerMemView(DVT_MEMORY, m_machine, this); // Layout - QHBoxLayout* subLayout = new QHBoxLayout(topSubFrame); + QHBoxLayout *subLayout = new QHBoxLayout(topSubFrame); subLayout->addWidget(m_inputEdit); subLayout->addWidget(m_memoryComboBox); subLayout->setSpacing(3); subLayout->setContentsMargins(2,2,2,2); - QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); + QVBoxLayout *vLayout = new QVBoxLayout(mainWindowFrame); vLayout->setSpacing(3); vLayout->setContentsMargins(2,2,2,2); vLayout->addWidget(topSubFrame); @@ -71,26 +84,38 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : // // Create a data format group - QActionGroup* dataFormat = new QActionGroup(this); + QActionGroup *dataFormat = new QActionGroup(this); dataFormat->setObjectName("dataformat"); - QAction* formatActOne = new QAction("1-byte chunks", this); - QAction* formatActTwo = new QAction("2-byte chunks", this); - QAction* formatActFour = new QAction("4-byte chunks", this); - QAction* formatActEight = new QAction("8-byte chunks", this); - QAction* formatAct32bitFloat = new QAction("32 bit floating point", this); - QAction* formatAct64bitFloat = new QAction("64 bit floating point", this); - QAction* formatAct80bitFloat = new QAction("80 bit floating point", this); - formatActOne->setObjectName("formatActOne"); - formatActTwo->setObjectName("formatActTwo"); - formatActFour->setObjectName("formatActFour"); - formatActEight->setObjectName("formatActEight"); - formatAct32bitFloat->setObjectName("formatAct32bitFloat"); - formatAct64bitFloat->setObjectName("formatAct64bitFloat"); - formatAct80bitFloat->setObjectName("formatAct80bitFloat"); + QAction *formatActOne = new QAction("1-byte Chunks (Hex)", this); + QAction *formatActTwo = new QAction("2-byte Chunks (Hex)", this); + QAction *formatActFour = new QAction("4-byte Chunks (Hex)", this); + QAction *formatActEight = new QAction("8-byte Chunks (Hex)", this); + QAction *formatActOneOctal = new QAction("1-byte Chunks (Octal)", this); + QAction *formatActTwoOctal = new QAction("2-byte Chunks (Octal)", this); + QAction *formatActFourOctal = new QAction("4-byte Chunks (Octal)", this); + QAction *formatActEightOctal = new QAction("8-byte Chunks (Octal)", this); + QAction *formatAct32bitFloat = new QAction("32-bit Floating Point", this); + QAction *formatAct64bitFloat = new QAction("64-bit Floating Point", this); + QAction *formatAct80bitFloat = new QAction("80-bit Floating Point", this); + formatActOne->setData(int(debug_view_memory::data_format::HEX_8BIT)); + formatActTwo->setData(int(debug_view_memory::data_format::HEX_16BIT)); + formatActFour->setData(int(debug_view_memory::data_format::HEX_32BIT)); + formatActEight->setData(int(debug_view_memory::data_format::HEX_64BIT)); + formatActOneOctal->setData(int(debug_view_memory::data_format::OCTAL_8BIT)); + formatActTwoOctal->setData(int(debug_view_memory::data_format::OCTAL_16BIT)); + formatActFourOctal->setData(int(debug_view_memory::data_format::OCTAL_32BIT)); + formatActEightOctal->setData(int(debug_view_memory::data_format::OCTAL_64BIT)); + formatAct32bitFloat->setData(int(debug_view_memory::data_format::FLOAT_32BIT)); + formatAct64bitFloat->setData(int(debug_view_memory::data_format::FLOAT_64BIT)); + formatAct80bitFloat->setData(int(debug_view_memory::data_format::FLOAT_80BIT)); formatActOne->setCheckable(true); formatActTwo->setCheckable(true); formatActFour->setCheckable(true); formatActEight->setCheckable(true); + formatActOneOctal->setCheckable(true); + formatActTwoOctal->setCheckable(true); + formatActFourOctal->setCheckable(true); + formatActEightOctal->setCheckable(true); formatAct32bitFloat->setCheckable(true); formatAct64bitFloat->setCheckable(true); formatAct80bitFloat->setCheckable(true); @@ -98,6 +123,10 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : formatActTwo->setActionGroup(dataFormat); formatActFour->setActionGroup(dataFormat); formatActEight->setActionGroup(dataFormat); + formatActOneOctal->setActionGroup(dataFormat); + formatActTwoOctal->setActionGroup(dataFormat); + formatActFourOctal->setActionGroup(dataFormat); + formatActEightOctal->setActionGroup(dataFormat); formatAct32bitFloat->setActionGroup(dataFormat); formatAct64bitFloat->setActionGroup(dataFormat); formatAct80bitFloat->setActionGroup(dataFormat); @@ -105,14 +134,23 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : formatActTwo->setShortcut(QKeySequence("Ctrl+2")); formatActFour->setShortcut(QKeySequence("Ctrl+4")); formatActEight->setShortcut(QKeySequence("Ctrl+8")); - formatAct32bitFloat->setShortcut(QKeySequence("Ctrl+9")); + formatActOneOctal->setShortcut(QKeySequence("Ctrl+3")); + formatActTwoOctal->setShortcut(QKeySequence("Ctrl+5")); + formatActFourOctal->setShortcut(QKeySequence("Ctrl+7")); + formatActEightOctal->setShortcut(QKeySequence("Ctrl+9")); + formatAct32bitFloat->setShortcut(QKeySequence("Ctrl+Shift+F")); + formatAct64bitFloat->setShortcut(QKeySequence("Ctrl+Shift+D")); + formatAct80bitFloat->setShortcut(QKeySequence("Ctrl+Shift+E")); formatActOne->setChecked(true); connect(dataFormat, &QActionGroup::triggered, this, &MemoryWindow::formatChanged); - // Create a address display group - QActionGroup* addressGroup = new QActionGroup(this); + + // Create an address display group + QActionGroup *addressGroup = new QActionGroup(this); addressGroup->setObjectName("addressgroup"); - QAction* addressActLogical = new QAction("Logical Addresses", this); - QAction* addressActPhysical = new QAction("Physical Addresses", this); + QAction *addressActLogical = new QAction("Logical Addresses", this); + QAction *addressActPhysical = new QAction("Physical Addresses", this); + addressActLogical->setData(false); + addressActPhysical->setData(true); addressActLogical->setCheckable(true); addressActPhysical->setCheckable(true); addressActLogical->setActionGroup(addressGroup); @@ -122,27 +160,49 @@ MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) : addressActLogical->setChecked(true); connect(addressGroup, &QActionGroup::triggered, this, &MemoryWindow::addressChanged); + // Create an address radix group + QActionGroup *radixGroup = new QActionGroup(this); + radixGroup->setObjectName("radixgroup"); + QAction *radixActHexadecimal = new QAction("Hexadecimal Addresses", this); + QAction *radixActDecimal = new QAction("Decimal Addresses", this); + QAction *radixActOctal = new QAction("Octal Addresses", this); + radixActHexadecimal->setData(16); + radixActDecimal->setData(10); + radixActOctal->setData(8); + radixActHexadecimal->setCheckable(true); + radixActDecimal->setCheckable(true); + radixActOctal->setCheckable(true); + radixActHexadecimal->setActionGroup(radixGroup); + radixActDecimal->setActionGroup(radixGroup); + radixActOctal->setActionGroup(radixGroup); + radixActHexadecimal->setShortcut(QKeySequence("Ctrl+Shift+H")); + radixActOctal->setShortcut(QKeySequence("Ctrl+Shift+O")); + radixActHexadecimal->setChecked(true); + connect(radixGroup, &QActionGroup::triggered, this, &MemoryWindow::radixChanged); + // Create a reverse view radio - QAction* reverseAct = new QAction("Reverse View", this); + QAction *reverseAct = new QAction("Reverse View", this); reverseAct->setObjectName("reverse"); reverseAct->setCheckable(true); reverseAct->setShortcut(QKeySequence("Ctrl+R")); connect(reverseAct, &QAction::toggled, this, &MemoryWindow::reverseChanged); // Create increase and decrease bytes-per-line actions - QAction* increaseBplAct = new QAction("Increase Bytes Per Line", this); - QAction* decreaseBplAct = new QAction("Decrease Bytes Per Line", this); + QAction *increaseBplAct = new QAction("Increase Bytes Per Line", this); + QAction *decreaseBplAct = new QAction("Decrease Bytes Per Line", this); increaseBplAct->setShortcut(QKeySequence("Ctrl+P")); decreaseBplAct->setShortcut(QKeySequence("Ctrl+O")); connect(increaseBplAct, &QAction::triggered, this, &MemoryWindow::increaseBytesPerLine); connect(decreaseBplAct, &QAction::triggered, this, &MemoryWindow::decreaseBytesPerLine); // Assemble the options menu - QMenu* optionsMenu = menuBar()->addMenu("&Options"); + QMenu *optionsMenu = menuBar()->addMenu("&Options"); optionsMenu->addActions(dataFormat->actions()); optionsMenu->addSeparator(); optionsMenu->addActions(addressGroup->actions()); optionsMenu->addSeparator(); + optionsMenu->addActions(radixGroup->actions()); + optionsMenu->addSeparator(); optionsMenu->addAction(reverseAct); optionsMenu->addSeparator(); optionsMenu->addAction(increaseBplAct); @@ -164,98 +224,213 @@ MemoryWindow::~MemoryWindow() } -void MemoryWindow::memoryRegionChanged(int index) +void MemoryWindow::restoreConfiguration(util::xml::data_node const &node) { - m_memTable->view()->set_source(*m_memTable->view()->source_list().find(index)); - m_memTable->viewport()->update(); + WindowQt::restoreConfiguration(node); + + debug_view_memory &memView = *m_memTable->view<debug_view_memory>(); + + auto const region = node.get_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_memTable->sourceIndex()); + if ((0 <= region) && (m_memoryComboBox->count() > region)) + m_memoryComboBox->setCurrentIndex(region); + + auto const reverse = node.get_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView.reverse() ? 1 : 0); + if (memView.reverse() != bool(reverse)) + { + memView.set_reverse(bool(reverse)); + findChild<QAction *>("reverse")->setChecked(bool(reverse)); + } - // Update the data format radio buttons to the memory region's default - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); - switch(memView->get_data_format()) + auto const mode = node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView.physical() ? 1 : 0); + QActionGroup *const addressGroup = findChild<QActionGroup *>("addressgroup"); + for (QAction *action : addressGroup->actions()) { - case 1: dataFormatMenuItem("formatActOne")->setChecked(true); break; - case 2: dataFormatMenuItem("formatActTwo")->setChecked(true); break; - case 4: dataFormatMenuItem("formatActFour")->setChecked(true); break; - case 8: dataFormatMenuItem("formatActEight")->setChecked(true); break; - case 9: dataFormatMenuItem("formatAct32bitFloat")->setChecked(true); break; - case 10: dataFormatMenuItem("formatAct64bitFloat")->setChecked(true); break; - case 11: dataFormatMenuItem("formatAct80bitFloat")->setChecked(true); break; - default: break; + if (action->data().toBool() == mode) + { + action->trigger(); + break; + } } + + auto const radix = node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView.address_radix()); + QActionGroup *const radixGroup = findChild<QActionGroup *>("radixgroup"); + for (QAction *action : radixGroup->actions()) + { + if (action->data().toInt() == radix) + { + action->trigger(); + break; + } + } + + auto const format = node.get_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView.get_data_format())); + QActionGroup *const dataFormat = findChild<QActionGroup *>("dataformat"); + for (QAction *action : dataFormat->actions()) + { + if (action->data().toInt() == format) + { + action->trigger(); + break; + } + } + + auto const chunks = node.get_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView.chunks_per_row()); + memView.set_chunks_per_row(chunks); + + util::xml::data_node const *const expression = node.get_child(NODE_WINDOW_EXPRESSION); + if (expression && expression->get_value()) + { + m_inputEdit->setText(QString::fromUtf8(expression->get_value())); + expressionSubmitted(); + } + + m_memTable->restoreConfigurationFromNode(node); + m_inputHistory.restoreConfigurationFromNode(node); } -void MemoryWindow::expressionSubmitted() +void MemoryWindow::saveConfigurationToNode(util::xml::data_node &node) { - const QString expression = m_inputEdit->text(); - downcast<debug_view_memory*>(m_memTable->view())->set_expression(expression.toLocal8Bit().data()); + WindowQt::saveConfigurationToNode(node); - // Make the cursor pop - m_memTable->view()->set_cursor_visible(true); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_MEMORY_VIEWER); - // Check where the cursor is and adjust the scroll accordingly - debug_view_xy cursorPosition = m_memTable->view()->cursor_position(); - // TODO: check if the region is already visible? - m_memTable->verticalScrollBar()->setValue(cursorPosition.y); + debug_view_memory &memView = *m_memTable->view<debug_view_memory>(); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_memTable->sourceIndex()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memView.reverse() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memView.physical() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memView.address_radix()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memView.get_data_format())); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memView.chunks_per_row()); + node.add_child(NODE_WINDOW_EXPRESSION, memView.expression()); - m_memTable->update(); - m_memTable->viewport()->update(); + m_memTable->saveConfigurationToNode(node); + m_inputHistory.saveConfigurationToNode(node); } -void MemoryWindow::formatChanged(QAction* changedTo) +void MemoryWindow::memoryRegionChanged(int index) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); - if (changedTo->text() == "1-byte chunks") - { - memView->set_data_format(1); - } - else if (changedTo->text() == "2-byte chunks") + if (index < m_memTable->view()->source_count()) { - memView->set_data_format(2); - } - else if (changedTo->text() == "4-byte chunks") - { - memView->set_data_format(4); + m_memTable->view()->set_source(*m_memTable->view()->source(index)); + m_memTable->viewport()->update(); + + // Update the data format radio buttons to the memory region's default + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + + QActionGroup *const dataFormat = findChild<QActionGroup *>("dataformat"); + for (QAction *action : dataFormat->actions()) + { + if (debug_view_memory::data_format(action->data().toInt()) == memView->get_data_format()) + { + action->setChecked(true); + break; + } + } + + QActionGroup *radixGroup = findChild<QActionGroup *>("radixgroup"); + for (QAction *action : radixGroup->actions()) + { + if (action->data().toInt() == memView->address_radix()) + { + action->setChecked(true); + break; + } + } } - else if (changedTo->text() == "8-byte chunks") +} + + +// Used to intercept the user hitting the up arrow in the input widget +bool MemoryWindow::eventFilter(QObject *obj, QEvent *event) +{ + // Only filter keypresses + if (event->type() != QEvent::KeyPress) + return QObject::eventFilter(obj, event); + + QKeyEvent const &keyEvent = *static_cast<QKeyEvent *>(event); + + // Catch up & down keys + if (keyEvent.key() == Qt::Key_Escape) { - memView->set_data_format(8); + m_inputEdit->setText(QString::fromUtf8(m_memTable->view<debug_view_memory>()->expression())); + m_inputEdit->selectAll(); + m_inputHistory.reset(); + return true; } - else if (changedTo->text() == "32 bit floating point") + else if (keyEvent.key() == Qt::Key_Up) { - memView->set_data_format(9); + QString const *const hist = m_inputHistory.previous(m_inputEdit->text()); + if (hist) + { + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); + } + return true; } - else if (changedTo->text() == "64 bit floating point") + else if (keyEvent.key() == Qt::Key_Down) { - memView->set_data_format(10); + QString const *const hist = m_inputHistory.next(m_inputEdit->text()); + if (hist) + { + m_inputEdit->setText(*hist); + m_inputEdit->setSelection(hist->size(), 0); + } + return true; } - else if (changedTo->text() == "80 bit floating point") + else { - memView->set_data_format(11); + return QObject::eventFilter(obj, event); } +} + + +void MemoryWindow::expressionSubmitted() +{ + const QString expression = m_inputEdit->text(); + m_memTable->view<debug_view_memory>()->set_expression(expression.toUtf8().data()); + m_inputEdit->selectAll(); + + // Add history + if (!expression.isEmpty()) + m_inputHistory.add(expression); +} + + +void MemoryWindow::expressionEdited(QString const &text) +{ + m_inputHistory.edit(); +} + + +void MemoryWindow::formatChanged(QAction* changedTo) +{ + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + memView->set_data_format(debug_view_memory::data_format(changedTo->data().toInt())); m_memTable->viewport()->update(); } void MemoryWindow::addressChanged(QAction* changedTo) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); - if (changedTo->text() == "Logical Addresses") - { - memView->set_physical(false); - } - else if (changedTo->text() == "Physical Addresses") - { - memView->set_physical(true); - } + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + memView->set_physical(changedTo->data().toBool()); + m_memTable->viewport()->update(); +} + + +void MemoryWindow::radixChanged(QAction* changedTo) +{ + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); + memView->set_address_radix(changedTo->data().toInt()); m_memTable->viewport()->update(); } void MemoryWindow::reverseChanged(bool changedTo) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); memView->set_reverse(changedTo); m_memTable->viewport()->update(); } @@ -263,7 +438,7 @@ void MemoryWindow::reverseChanged(bool changedTo) void MemoryWindow::increaseBytesPerLine(bool changedTo) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); memView->set_chunks_per_row(memView->chunks_per_row() + 1); m_memTable->viewport()->update(); } @@ -271,7 +446,7 @@ void MemoryWindow::increaseBytesPerLine(bool changedTo) void MemoryWindow::decreaseBytesPerLine(bool checked) { - debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view()); + debug_view_memory *const memView = m_memTable->view<debug_view_memory>(); memView->set_chunks_per_row(memView->chunks_per_row() - 1); m_memTable->viewport()->update(); } @@ -279,173 +454,98 @@ void MemoryWindow::decreaseBytesPerLine(bool checked) void MemoryWindow::populateComboBox() { - if (m_memTable == nullptr) + if (!m_memTable) return; m_memoryComboBox->clear(); - for (const debug_view_source &source : m_memTable->view()->source_list()) - { - m_memoryComboBox->addItem(source.name()); - } + for (auto &source : m_memTable->view()->source_list()) + m_memoryComboBox->addItem(source->name()); } void MemoryWindow::setToCurrentCpu() { - device_t* curCpu = m_machine->debugger().cpu().get_visible_cpu(); - const debug_view_source *source = m_memTable->view()->source_for_device(curCpu); - const int listIndex = m_memTable->view()->source_list().indexof(*source); - m_memoryComboBox->setCurrentIndex(listIndex); -} - - -// I have a hard time storing QActions as class members. This is a substitute. -QAction* MemoryWindow::dataFormatMenuItem(const QString& itemName) -{ - QList<QMenu*> menus = menuBar()->findChildren<QMenu*>(); - for (int i = 0; i < menus.length(); i++) + device_t *curCpu = m_machine.debugger().console().get_visible_cpu(); + if (curCpu) { - if (menus[i]->title() != "&Options") continue; - QList<QAction*> actions = menus[i]->actions(); - for (int j = 0; j < actions.length(); j++) + const debug_view_source *source = m_memTable->view()->source_for_device(curCpu); + if (source) { - if (actions[j]->objectName() == itemName) - return actions[j]; + const int listIndex = m_memTable->view()->source_index(*source); + m_memoryComboBox->setCurrentIndex(listIndex); } } - return nullptr; } //========================================================================= // DebuggerMemView //========================================================================= -void DebuggerMemView::mousePressEvent(QMouseEvent* event) +void DebuggerMemView::addItemsToContextMenu(QMenu *menu) { - const bool leftClick = event->button() == Qt::LeftButton; - const bool rightClick = event->button() == Qt::RightButton; + DebuggerView::addItemsToContextMenu(menu); - if (leftClick || rightClick) + if (view()->cursor_visible()) { - QFontMetrics actualFont = fontMetrics(); - const double fontWidth = actualFont.width(QString(100, '_')) / 100.; - const int fontHeight = std::max(1, actualFont.lineSpacing()); - - debug_view_xy topLeft = view()->visible_position(); - debug_view_xy clickViewPosition; - clickViewPosition.x = topLeft.x + (event->x() / fontWidth); - clickViewPosition.y = topLeft.y + (event->y() / fontHeight); - if (leftClick) - { - view()->process_click(DCK_LEFT_CLICK, clickViewPosition); - } - else if (rightClick) + debug_view_memory &memView = *view<debug_view_memory>(); + debug_view_memory_source const &source = downcast<debug_view_memory_source const &>(*memView.source()); + address_space *const addressSpace = source.space(); + if (addressSpace) { - // Display the last known PC to write to this memory location & copy it onto the clipboard - debug_view_memory* memView = downcast<debug_view_memory*>(view()); - const offs_t address = memView->addressAtCursorPosition(clickViewPosition); - const debug_view_memory_source* source = downcast<const debug_view_memory_source*>(memView->source()); - address_space* addressSpace = source->space(); - const int nativeDataWidth = addressSpace->data_width() / 8; - const uint64_t memValue = source->device()->machine().debugger().cpu().read_memory(*addressSpace, - addressSpace->address_to_byte(address), - nativeDataWidth, - true); - const offs_t pc = source->device()->debug()->track_mem_pc_from_space_address_data(addressSpace->spacenum(), - address, - memValue); - if (pc != (offs_t)(-1)) + // get the last known PC to write to this memory location + debug_view_xy const pos = memView.cursor_position(); + offs_t const address = addressSpace->byte_to_address(memView.addressAtCursorPosition(pos)); + offs_t a = address & addressSpace->logaddrmask(); + bool good = false; + address_space *tspace; + if (!addressSpace->device().memory().translate(addressSpace->spacenum(), device_memory_interface::TR_READ, a, tspace)) { - // TODO: You can specify a box that the tooltip stays alive within - might be good? - const QString addressAndPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16); - QToolTip::showText(QCursor::pos(), addressAndPc, nullptr); - - // Copy the PC into the clipboard as well - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(QString("%1").arg(pc, 2, 16)); + m_lastPc = "Bad address"; } else { - QToolTip::showText(QCursor::pos(), "UNKNOWN PC", nullptr); + uint64_t memValue = tspace->unmap(); + auto dis = tspace->device().machine().disable_side_effects(); + switch (tspace->data_width()) + { + case 8: memValue = tspace->read_byte(a); break; + case 16: memValue = tspace->read_word_unaligned(a); break; + case 32: memValue = tspace->read_dword_unaligned(a); break; + case 64: memValue = tspace->read_qword_unaligned(a); break; + } + + offs_t const pc = source.device()->debug()->track_mem_pc_from_space_address_data( + tspace->spacenum(), + address, + memValue); + if (pc != offs_t(-1)) + { + if (tspace->is_octal()) + m_lastPc = QString("Address %1 written at PC=%2").arg(address, 2, 8).arg(pc, 2, 8); + else + m_lastPc = QString("Address %1 written at PC=%2").arg(address, 2, 16).arg(pc, 2, 16); + good = true; + } + else + { + m_lastPc = "Unknown PC"; + } } - } - viewport()->update(); - update(); + if (!menu->isEmpty()) + menu->addSeparator(); + QAction *const act = new QAction(m_lastPc, menu); + act->setEnabled(good); + connect(act, &QAction::triggered, this, &DebuggerMemView::copyLastPc); + menu->addAction(act); + } } } -//========================================================================= -// MemoryWindowQtConfig -//========================================================================= -void MemoryWindowQtConfig::buildFromQWidget(QWidget* widget) -{ - WindowQtConfig::buildFromQWidget(widget); - MemoryWindow* window = dynamic_cast<MemoryWindow*>(widget); - QComboBox* memoryRegion = window->findChild<QComboBox*>("memoryregion"); - m_memoryRegion = memoryRegion->currentIndex(); - - QAction* reverse = window->findChild<QAction*>("reverse"); - m_reverse = reverse->isChecked(); - - QActionGroup* addressGroup = window->findChild<QActionGroup*>("addressgroup"); - if (addressGroup->checkedAction()->text() == "Logical Addresses") - m_addressMode = 0; - else if (addressGroup->checkedAction()->text() == "Physical Addresses") - m_addressMode = 1; - - QActionGroup* dataFormat = window->findChild<QActionGroup*>("dataformat"); - if (dataFormat->checkedAction()->text() == "1-byte chunks") - m_dataFormat = 0; - else if (dataFormat->checkedAction()->text() == "2-byte chunks") - m_dataFormat = 1; - else if (dataFormat->checkedAction()->text() == "4-byte chunks") - m_dataFormat = 2; - else if (dataFormat->checkedAction()->text() == "8-byte chunks") - m_dataFormat = 3; - else if (dataFormat->checkedAction()->text() == "32 bit floating point") - m_dataFormat = 4; - else if (dataFormat->checkedAction()->text() == "64 bit floating point") - m_dataFormat = 5; - else if (dataFormat->checkedAction()->text() == "80 bit floating point") - m_dataFormat = 6; -} - - -void MemoryWindowQtConfig::applyToQWidget(QWidget* widget) +void DebuggerMemView::copyLastPc() { - WindowQtConfig::applyToQWidget(widget); - MemoryWindow* window = dynamic_cast<MemoryWindow*>(widget); - QComboBox* memoryRegion = window->findChild<QComboBox*>("memoryregion"); - memoryRegion->setCurrentIndex(m_memoryRegion); - - QAction* reverse = window->findChild<QAction*>("reverse"); - if (m_reverse) reverse->trigger(); - - QActionGroup* addressGroup = window->findChild<QActionGroup*>("addressgroup"); - addressGroup->actions()[m_addressMode]->trigger(); - - QActionGroup* dataFormat = window->findChild<QActionGroup*>("dataformat"); - dataFormat->actions()[m_dataFormat]->trigger(); + QApplication::clipboard()->setText(m_lastPc); } - -void MemoryWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const -{ - WindowQtConfig::addToXmlDataNode(node); - node.set_attribute_int("memoryregion", m_memoryRegion); - node.set_attribute_int("reverse", m_reverse); - node.set_attribute_int("addressmode", m_addressMode); - node.set_attribute_int("dataformat", m_dataFormat); -} - - -void MemoryWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) -{ - WindowQtConfig::recoverFromXmlNode(node); - m_memoryRegion = node.get_attribute_int("memoryregion", m_memoryRegion); - m_reverse = node.get_attribute_int("reverse", m_reverse); - m_addressMode = node.get_attribute_int("addressmode", m_addressMode); - m_dataFormat = node.get_attribute_int("dataformat", m_dataFormat); -} +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/memorywindow.h b/src/osd/modules/debugger/qt/memorywindow.h index ff0c974c838..ed5c5b30cb0 100644 --- a/src/osd/modules/debugger/qt/memorywindow.h +++ b/src/osd/modules/debugger/qt/memorywindow.h @@ -1,14 +1,19 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_MEMORY_WINDOW_H__ -#define __DEBUG_QT_MEMORY_WINDOW_H__ +#ifndef MAME_DEBUGGER_QT_MEMORYWINDOW_H +#define MAME_DEBUGGER_QT_MEMORYWINDOW_H -#include <QtWidgets/QLineEdit> -#include <QtWidgets/QComboBox> +#pragma once #include "debuggerview.h" #include "windowqt.h" +#include <QtWidgets/QComboBox> +#include <QtWidgets/QLineEdit> + + +namespace osd::debugger::qt { + class DebuggerMemView; @@ -20,31 +25,40 @@ class MemoryWindow : public WindowQt Q_OBJECT public: - MemoryWindow(running_machine* machine, QWidget* parent=nullptr); + MemoryWindow(DebuggerQt &debugger, QWidget *parent = nullptr); virtual ~MemoryWindow(); + virtual void restoreConfiguration(util::xml::data_node const &node) override; + +protected: + virtual void saveConfigurationToNode(util::xml::data_node &node) override; + + // Used to intercept the user hitting the up arrow in the input widget + virtual bool eventFilter(QObject *obj, QEvent *event) override; private slots: void memoryRegionChanged(int index); void expressionSubmitted(); - void formatChanged(QAction* changedTo); - void addressChanged(QAction* changedTo); + void expressionEdited(QString const &text); + + void formatChanged(QAction *changedTo); + void addressChanged(QAction *changedTo); + void radixChanged(QAction *changedTo); void reverseChanged(bool changedTo); void increaseBytesPerLine(bool changedTo); - void decreaseBytesPerLine(bool checked=false); - + void decreaseBytesPerLine(bool checked = false); private: void populateComboBox(); void setToCurrentCpu(); - QAction* dataFormatMenuItem(const QString& itemName); - -private: // Widgets - QLineEdit* m_inputEdit; - QComboBox* m_memoryComboBox; - DebuggerMemView* m_memTable; + QLineEdit *m_inputEdit; + QComboBox *m_memoryComboBox; + DebuggerMemView *m_memTable; + + // Expression history + CommandHistory m_inputHistory; }; @@ -53,47 +67,25 @@ private: //========================================================================= class DebuggerMemView : public DebuggerView { + Q_OBJECT + public: - DebuggerMemView(const debug_view_type& type, - running_machine* machine, - QWidget* parent=nullptr) + DebuggerMemView(const debug_view_type& type, running_machine &machine, QWidget *parent = nullptr) : DebuggerView(type, machine, parent) {} + virtual ~DebuggerMemView() {} protected: - void mousePressEvent(QMouseEvent* event); -}; + virtual void addItemsToContextMenu(QMenu *menu) override; +private slots: + void copyLastPc(); -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class MemoryWindowQtConfig : public WindowQtConfig -{ -public: - MemoryWindowQtConfig() : - WindowQtConfig(WIN_TYPE_MEMORY), - m_reverse(0), - m_addressMode(0), - m_dataFormat(0), - m_memoryRegion(0) - { - } - - ~MemoryWindowQtConfig() {} - - // Settings - int m_reverse; - int m_addressMode; - int m_dataFormat; - int m_memoryRegion; - - void buildFromQWidget(QWidget* widget); - void applyToQWidget(QWidget* widget); - void addToXmlDataNode(util::xml::data_node &node) const; - void recoverFromXmlNode(util::xml::data_node const &node); +private: + QString m_lastPc; }; +} // namespace osd::debugger::qt -#endif +#endif // MAME_DEBUGGER_QT_MEMORYWINDOW_H diff --git a/src/osd/modules/debugger/qt/windowqt.cpp b/src/osd/modules/debugger/qt/windowqt.cpp index dda9ee64dc7..294871e6d22 100644 --- a/src/osd/modules/debugger/qt/windowqt.cpp +++ b/src/osd/modules/debugger/qt/windowqt.cpp @@ -1,104 +1,114 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" -#include <QtWidgets/QMenu> -#include <QtWidgets/QMenuBar> - #include "windowqt.h" -#include "logwindow.h" -#include "dasmwindow.h" -#include "memorywindow.h" + #include "breakpointswindow.h" +#include "dasmwindow.h" #include "deviceswindow.h" +#include "logwindow.h" +#include "memorywindow.h" +#include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" -bool WindowQt::s_refreshAll = false; -bool WindowQt::s_hideAll = false; +#include "util/xmlfile.h" +#include <QtWidgets/QMenu> +#include <QtWidgets/QMenuBar> + + +namespace osd::debugger::qt { // Since all debug windows are intended to be top-level, this inherited // constructor is always called with a nullptr parent. The passed-in parent widget, // however, is often used to place each child window & the code to do this can // be found in most of the inherited classes. -WindowQt::WindowQt(running_machine* machine, QWidget* parent) : +WindowQt::WindowQt(DebuggerQt &debugger, QWidget *parent) : QMainWindow(parent), - m_machine(machine) + m_debugger(debugger), + m_machine(debugger.machine()) { setAttribute(Qt::WA_DeleteOnClose, true); + // Subscribe to signals + connect(&debugger, &DebuggerQt::exitDebugger, this, &WindowQt::debuggerExit); + connect(&debugger, &DebuggerQt::hideAllWindows, this, &WindowQt::hide); + connect(&debugger, &DebuggerQt::showAllWindows, this, &WindowQt::show); + connect(&debugger, &DebuggerQt::saveConfiguration, this, &WindowQt::saveConfiguration); + // The Debug menu bar - QAction* debugActOpenMemory = new QAction("New &Memory Window", this); + QAction *debugActOpenMemory = new QAction("New &Memory Window", this); debugActOpenMemory->setShortcut(QKeySequence("Ctrl+M")); connect(debugActOpenMemory, &QAction::triggered, this, &WindowQt::debugActOpenMemory); - QAction* debugActOpenDasm = new QAction("New &Dasm Window", this); + QAction *debugActOpenDasm = new QAction("New &Disassembly Window", this); debugActOpenDasm->setShortcut(QKeySequence("Ctrl+D")); connect(debugActOpenDasm, &QAction::triggered, this, &WindowQt::debugActOpenDasm); - QAction* debugActOpenLog = new QAction("New &Log Window", this); + QAction *debugActOpenLog = new QAction("New Error &Log Window", this); debugActOpenLog->setShortcut(QKeySequence("Ctrl+L")); connect(debugActOpenLog, &QAction::triggered, this, &WindowQt::debugActOpenLog); - QAction* debugActOpenPoints = new QAction("New &Break|Watchpoints Window", this); + QAction *debugActOpenPoints = new QAction("New (&Break|Watch)points Window", this); debugActOpenPoints->setShortcut(QKeySequence("Ctrl+B")); connect(debugActOpenPoints, &QAction::triggered, this, &WindowQt::debugActOpenPoints); - QAction* debugActOpenDevices = new QAction("New D&evices Window", this); - debugActOpenDevices->setShortcut(QKeySequence("Shift+Ctrl+D")); + QAction *debugActOpenDevices = new QAction("New D&evices Window", this); connect(debugActOpenDevices, &QAction::triggered, this, &WindowQt::debugActOpenDevices); - QAction* dbgActRun = new QAction("Run", this); + QAction *dbgActRun = new QAction("Run", this); dbgActRun->setShortcut(Qt::Key_F5); connect(dbgActRun, &QAction::triggered, this, &WindowQt::debugActRun); - QAction* dbgActRunAndHide = new QAction("Run And Hide Debugger", this); + QAction *dbgActRunAndHide = new QAction("Run And Hide Debugger", this); dbgActRunAndHide->setShortcut(Qt::Key_F12); connect(dbgActRunAndHide, &QAction::triggered, this, &WindowQt::debugActRunAndHide); - QAction* dbgActRunToNextCpu = new QAction("Run to Next CPU", this); + QAction *dbgActRunToNextCpu = new QAction("Run to Next CPU", this); dbgActRunToNextCpu->setShortcut(Qt::Key_F6); connect(dbgActRunToNextCpu, &QAction::triggered, this, &WindowQt::debugActRunToNextCpu); - QAction* dbgActRunNextInt = new QAction("Run to Next Interrupt on This CPU", this); + QAction *dbgActRunNextInt = new QAction("Run to Next Interrupt on This CPU", this); dbgActRunNextInt->setShortcut(Qt::Key_F7); connect(dbgActRunNextInt, &QAction::triggered, this, &WindowQt::debugActRunNextInt); - QAction* dbgActRunNextVBlank = new QAction("Run to Next VBlank", this); + QAction *dbgActRunNextVBlank = new QAction("Run to Next VBlank", this); dbgActRunNextVBlank->setShortcut(Qt::Key_F8); connect(dbgActRunNextVBlank, &QAction::triggered, this, &WindowQt::debugActRunNextVBlank); - QAction* dbgActStepInto = new QAction("Step Into", this); + QAction *dbgActStepInto = new QAction("Step Into", this); dbgActStepInto->setShortcut(Qt::Key_F11); connect(dbgActStepInto, &QAction::triggered, this, &WindowQt::debugActStepInto); - QAction* dbgActStepOver = new QAction("Step Over", this); + QAction *dbgActStepOver = new QAction("Step Over", this); dbgActStepOver->setShortcut(Qt::Key_F10); connect(dbgActStepOver, &QAction::triggered, this, &WindowQt::debugActStepOver); - QAction* dbgActStepOut = new QAction("Step Out", this); + QAction *dbgActStepOut = new QAction("Step Out", this); dbgActStepOut->setShortcut(QKeySequence("Shift+F11")); connect(dbgActStepOut, &QAction::triggered, this, &WindowQt::debugActStepOut); - QAction* dbgActSoftReset = new QAction("Soft Reset", this); + QAction *dbgActSoftReset = new QAction("Soft Reset", this); dbgActSoftReset->setShortcut(Qt::Key_F3); connect(dbgActSoftReset, &QAction::triggered, this, &WindowQt::debugActSoftReset); - QAction* dbgActHardReset = new QAction("Hard Reset", this); + QAction *dbgActHardReset = new QAction("Hard Reset", this); dbgActHardReset->setShortcut(QKeySequence("Shift+F3")); connect(dbgActHardReset, &QAction::triggered, this, &WindowQt::debugActHardReset); - QAction* dbgActClose = new QAction("Close &Window", this); + QAction *dbgActClose = new QAction("Close &Window", this); dbgActClose->setShortcut(QKeySequence::Close); connect(dbgActClose, &QAction::triggered, this, &WindowQt::debugActClose); - QAction* dbgActQuit = new QAction("&Quit", this); + QAction *dbgActQuit = new QAction("&Quit", this); dbgActQuit->setShortcut(QKeySequence::Quit); connect(dbgActQuit, &QAction::triggered, this, &WindowQt::debugActQuit); // Construct the menu - QMenu* debugMenu = menuBar()->addMenu("&Debug"); + QMenu *debugMenu = menuBar()->addMenu("&Debug"); debugMenu->addAction(debugActOpenMemory); debugMenu->addAction(debugActOpenDasm); debugMenu->addAction(debugActOpenLog); @@ -127,9 +137,10 @@ WindowQt::~WindowQt() { } + void WindowQt::debugActOpenMemory() { - MemoryWindow* foo = new MemoryWindow(m_machine, this); + MemoryWindow *foo = new MemoryWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -139,7 +150,7 @@ void WindowQt::debugActOpenMemory() void WindowQt::debugActOpenDasm() { - DasmWindow* foo = new DasmWindow(m_machine, this); + DasmWindow *foo = new DasmWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -149,7 +160,7 @@ void WindowQt::debugActOpenDasm() void WindowQt::debugActOpenLog() { - LogWindow* foo = new LogWindow(m_machine, this); + LogWindow *foo = new LogWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -159,7 +170,7 @@ void WindowQt::debugActOpenLog() void WindowQt::debugActOpenPoints() { - BreakpointsWindow* foo = new BreakpointsWindow(m_machine, this); + BreakpointsWindow *foo = new BreakpointsWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -169,7 +180,7 @@ void WindowQt::debugActOpenPoints() void WindowQt::debugActOpenDevices() { - DevicesWindow* foo = new DevicesWindow(m_machine, this); + DevicesWindow *foo = new DevicesWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -179,54 +190,54 @@ void WindowQt::debugActOpenDevices() void WindowQt::debugActRun() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine.debugger().console().get_visible_cpu()->debug()->go(); } void WindowQt::debugActRunAndHide() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); - hideAll(); + m_machine.debugger().console().get_visible_cpu()->debug()->go(); + m_debugger.hideAll(); } void WindowQt::debugActRunToNextCpu() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine.debugger().console().get_visible_cpu()->debug()->go_next_device(); } void WindowQt::debugActRunNextInt() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine.debugger().console().get_visible_cpu()->debug()->go_interrupt(); } void WindowQt::debugActRunNextVBlank() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + m_machine.debugger().console().get_visible_cpu()->debug()->go_vblank(); } void WindowQt::debugActStepInto() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step(); } void WindowQt::debugActStepOver() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step_over(); } void WindowQt::debugActStepOut() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step_out(); } void WindowQt::debugActSoftReset() { - m_machine->schedule_soft_reset(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine.schedule_soft_reset(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step(); } void WindowQt::debugActHardReset() { - m_machine->schedule_hard_reset(); + m_machine.schedule_hard_reset(); } void WindowQt::debugActClose() @@ -236,43 +247,158 @@ void WindowQt::debugActClose() void WindowQt::debugActQuit() { - m_machine->schedule_exit(); + m_machine.schedule_exit(); +} + +void WindowQt::debuggerExit() +{ + // this isn't called from a Qt event loop, so close() will leak the window object + delete this; +} + + +void WindowQt::restoreConfiguration(util::xml::data_node const &node) +{ + QPoint p(geometry().topLeft()); + p.setX(node.get_attribute_int(ATTR_WINDOW_POSITION_X, p.x())); + p.setY(node.get_attribute_int(ATTR_WINDOW_POSITION_Y, p.y())); + + QSize s(size()); + s.setWidth(node.get_attribute_int(ATTR_WINDOW_WIDTH, s.width())); + s.setHeight(node.get_attribute_int(ATTR_WINDOW_HEIGHT, s.height())); + + // TODO: sanity checks, restrict to screen area + + setGeometry(p.x(), p.y(), s.width(), s.height()); +} + + +void WindowQt::saveConfiguration(util::xml::data_node &parentnode) +{ + util::xml::data_node *const node = parentnode.add_child(NODE_WINDOW, nullptr); + if (node) + saveConfigurationToNode(*node); } -//========================================================================= -// WindowQtConfig -//========================================================================= -void WindowQtConfig::buildFromQWidget(QWidget* widget) +void WindowQt::saveConfigurationToNode(util::xml::data_node &node) { - m_position.setX(widget->geometry().topLeft().x()); - m_position.setY(widget->geometry().topLeft().y()); - m_size.setX(widget->size().width()); - m_size.setY(widget->size().height()); + node.set_attribute_int(ATTR_WINDOW_POSITION_X, geometry().topLeft().x()); + node.set_attribute_int(ATTR_WINDOW_POSITION_Y, geometry().topLeft().y()); + node.set_attribute_int(ATTR_WINDOW_WIDTH, size().width()); + node.set_attribute_int(ATTR_WINDOW_HEIGHT, size().height()); } -void WindowQtConfig::applyToQWidget(QWidget* widget) +CommandHistory::CommandHistory() : + m_history(), + m_current(), + m_position(-1) { - widget->setGeometry(m_position.x(), m_position.y(), m_size.x(), m_size.y()); } -void WindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const +CommandHistory::~CommandHistory() { - node.set_attribute_int("type", m_type); - node.set_attribute_int("position_x", m_position.x()); - node.set_attribute_int("position_y", m_position.y()); - node.set_attribute_int("size_x", m_size.x()); - node.set_attribute_int("size_y", m_size.y()); } -void WindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) +void CommandHistory::add(QString const &entry) { - m_size.setX(node.get_attribute_int("size_x", m_size.x())); - m_size.setY(node.get_attribute_int("size_y", m_size.y())); - m_position.setX(node.get_attribute_int("position_x", m_position.x())); - m_position.setY(node.get_attribute_int("position_y", m_position.y())); - m_type = (WindowQtConfig::WindowType)node.get_attribute_int("type", m_type); + if (m_history.empty() || (m_history.front() != entry)) + { + while (m_history.size() >= CAPACITY) + m_history.pop_back(); + m_history.push_front(entry); + } + m_position = 0; } + + +QString const *CommandHistory::previous(QString const ¤t) +{ + if ((m_position + 1) < m_history.size()) + { + if (0 > m_position) + m_current = std::make_unique<QString>(current); + return &m_history[++m_position]; + } + else + { + return nullptr; + } +} + + +QString const *CommandHistory::next(QString const ¤t) +{ + if (0 < m_position) + { + return &m_history[--m_position]; + } + else if (!m_position && m_current && (m_history.front() != *m_current)) + { + --m_position; + return m_current.get(); + } + else + { + return nullptr; + } +} + + +void CommandHistory::edit() +{ + if (!m_position) + --m_position; +} + + +void CommandHistory::reset() +{ + m_position = -1; + m_current.reset(); +} + + +void CommandHistory::clear() +{ + m_position = -1; + m_current.reset(); + m_history.clear(); +} + + +void CommandHistory::restoreConfigurationFromNode(util::xml::data_node const &node) +{ + clear(); + util::xml::data_node const *const historynode = node.get_child(NODE_WINDOW_HISTORY); + if (historynode) + { + util::xml::data_node const *itemnode = historynode->get_child(NODE_HISTORY_ITEM); + while (itemnode) + { + if (itemnode->get_value() && *itemnode->get_value()) + { + while (m_history.size() >= CAPACITY) + m_history.pop_back(); + m_history.push_front(QString::fromUtf8(itemnode->get_value())); + } + itemnode = itemnode->get_next_sibling(NODE_HISTORY_ITEM); + } + } +} + + +void CommandHistory::saveConfigurationToNode(util::xml::data_node &node) +{ + util::xml::data_node *const historynode = node.add_child(NODE_WINDOW_HISTORY, nullptr); + if (historynode) + { + for (auto it = m_history.crbegin(); m_history.crend() != it; ++it) + historynode->add_child(NODE_HISTORY_ITEM, it->toUtf8().data()); + } +} + +} // namespace osd::debugger::qt diff --git a/src/osd/modules/debugger/qt/windowqt.h b/src/osd/modules/debugger/qt/windowqt.h index 29debc70bc6..b5e933e8a0c 100644 --- a/src/osd/modules/debugger/qt/windowqt.h +++ b/src/osd/modules/debugger/qt/windowqt.h @@ -1,12 +1,38 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner -#ifndef __DEBUG_QT_WINDOW_QT_H__ -#define __DEBUG_QT_WINDOW_QT_H__ +#ifndef MAME_DEBUGGER_QT_WINDOWQT_H +#define MAME_DEBUGGER_QT_WINDOWQT_H + +#include "../xmlconfig.h" #include <QtWidgets/QMainWindow> -#include "config.h" -#include "debugger.h" +#include <deque> +#include <memory> + + +namespace osd::debugger::qt { + +//============================================================ +// The Qt debugger module interface +//============================================================ +class DebuggerQt : public QObject +{ + Q_OBJECT + +public: + virtual ~DebuggerQt() { } + + virtual running_machine &machine() const = 0; + + void hideAll() { emit hideAllWindows(); } + +signals: + void exitDebugger(); + void hideAllWindows(); + void showAllWindows(); + void saveConfiguration(util::xml::data_node &parentnode); +}; //============================================================ @@ -17,18 +43,9 @@ class WindowQt : public QMainWindow Q_OBJECT public: - WindowQt(running_machine* machine, QWidget* parent=nullptr); virtual ~WindowQt(); - // The interface to an all-window refresh - void refreshAll() { s_refreshAll = true; } - bool wantsRefresh() { return s_refreshAll; } - void clearRefreshFlag() { s_refreshAll = false; } - - void hideAll() { s_hideAll = true; } - bool wantsHide() { return s_hideAll; } - void clearHideFlag() { s_hideAll = false; } - + virtual void restoreConfiguration(util::xml::data_node const &node); protected slots: void debugActOpenMemory(); @@ -48,52 +65,48 @@ protected slots: void debugActHardReset(); virtual void debugActClose(); void debugActQuit(); + virtual void debuggerExit(); +private slots: + void saveConfiguration(util::xml::data_node &parentnode); protected: - running_machine* m_machine; + WindowQt(DebuggerQt &debugger, QWidget *parent = nullptr); + + virtual void saveConfigurationToNode(util::xml::data_node &node); - static bool s_refreshAll; - static bool s_hideAll; + DebuggerQt &m_debugger; + running_machine &m_machine; }; -//========================================================================= -// A way to store the configuration of a window long enough to read/write. -//========================================================================= -class WindowQtConfig +//============================================================ +// Command history helper +//============================================================ +class CommandHistory { public: - enum WindowType - { - WIN_TYPE_UNKNOWN, - WIN_TYPE_MAIN, - WIN_TYPE_MEMORY, - WIN_TYPE_DASM, - WIN_TYPE_LOG, - WIN_TYPE_BREAK_POINTS, - WIN_TYPE_DEVICES, - WIN_TYPE_DEVICE_INFORMATION - }; + CommandHistory(); + ~CommandHistory(); -public: - WindowQtConfig(const WindowType& type=WIN_TYPE_UNKNOWN) : - m_type(type), - m_size(800, 600), - m_position(120, 120) - {} - virtual ~WindowQtConfig() {} - - // Settings - WindowType m_type; - QPoint m_size; - QPoint m_position; - - virtual void buildFromQWidget(QWidget* widget); - virtual void applyToQWidget(QWidget* widget); - virtual void addToXmlDataNode(util::xml::data_node &node) const; - virtual void recoverFromXmlNode(util::xml::data_node const &node); + void add(QString const &entry); + QString const *previous(QString const ¤t); + QString const *next(QString const ¤t); + void edit(); + void reset(); + void clear(); + + void restoreConfigurationFromNode(util::xml::data_node const &node); + void saveConfigurationToNode(util::xml::data_node &node); + +private: + static inline constexpr unsigned CAPACITY = 100U; + + std::deque<QString> m_history; + std::unique_ptr<QString> m_current; + int m_position; }; +} // namespace osd::debugger::qt -#endif +#endif // MAME_DEBUGGER_QT_WINDOWQT_H diff --git a/src/osd/modules/debugger/win/consolewininfo.cpp b/src/osd/modules/debugger/win/consolewininfo.cpp index a9811f5fc93..a5dfd04cc55 100644 --- a/src/osd/modules/debugger/win/consolewininfo.cpp +++ b/src/osd/modules/debugger/win/consolewininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// consolewininfo.c - Win32 debug window handling +// consolewininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,47 +12,245 @@ #include "debugviewinfo.h" #include "uimetrics.h" -#include "debugger.h" +// devices +#include "imagedev/cassette.h" + +// emu #include "debug/debugcon.h" +#include "debugger.h" +#include "image.h" +#include "softlist_dev.h" #include "debug/debugcpu.h" -#include "imagedev/cassette.h" -#include "strconv.h" +// util +#include "util/xmlfile.h" + +// osd/windows #include "winutf8.h" +// osd +#include "strconv.h" + +// C++ +#include <vector> + +// Windows +#include <commctrl.h> +#include <shlobj.h> +#include <shobjidl.h> +#include <shtypes.h> +#include <wrl/client.h> + + +namespace osd::debugger::win { + +namespace { + +class comdlg_filter_helper +{ +public: + comdlg_filter_helper(comdlg_filter_helper const &) = delete; + comdlg_filter_helper &operator=(comdlg_filter_helper const &) = delete; + + comdlg_filter_helper(device_image_interface &device, bool include_archives) + { + m_count = 0U; + + std::wstring const extensions = osd::text::to_wstring(device.file_extensions()); + std::wstring_view extview = extensions; + m_description = L"Media Image Files ("; + for (auto comma = extview.find(','); !extview.empty(); comma = extview.find(',')) + { + bool const found = std::wstring_view::npos != comma; + std::wstring_view const ext = found ? extview.substr(0, comma) : extview; + extview.remove_prefix(found ? (comma + 1) : extview.length()); + if (m_extensions.empty()) + { + m_default = ext; + m_description.append(L"*."); + m_extensions.append(L"*."); + } + else + { + m_description.append(L"; *."); + m_extensions.append(L";*."); + } + m_description.append(ext); + m_extensions.append(ext); + } + m_description.append(1, L')'); + m_specs[m_count].pszName = m_description.c_str(); + m_specs[m_count].pszSpec = m_extensions.c_str(); + ++m_count; + + if (include_archives) + { + m_specs[m_count].pszName = L"Archive Files (*.zip; *.7z)"; + m_specs[m_count].pszSpec = L"*.zip;*.7z"; + ++m_count; + } + + m_specs[m_count].pszName = L"All Files (*.*)"; + m_specs[m_count].pszSpec = L"*.*"; + ++m_count; + } + + UINT file_types() const noexcept + { + return m_count; + } + + COMDLG_FILTERSPEC const *filter_spec() const noexcept + { + return m_specs; + } + + LPCWSTR default_extension() const noexcept + { + return m_default.c_str(); + } + +private: + COMDLG_FILTERSPEC m_specs[3]; + std::wstring m_description; + std::wstring m_extensions; + std::wstring m_default; + UINT m_count; +}; + + +template <typename T> +void choose_image(device_image_interface &device, HWND owner, REFCLSID class_id, bool allow_archives, T &&handler) +{ + HRESULT hr; + + // create file dialog + Microsoft::WRL::ComPtr<IFileDialog> dialog; + hr = CoCreateInstance(class_id, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog)); + + // set file types + if (SUCCEEDED(hr)) + { + DWORD flags; + hr = dialog->GetOptions(&flags); + if (SUCCEEDED(hr)) + hr = dialog->SetOptions(flags | FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM); + comdlg_filter_helper filters(device, allow_archives); + if (SUCCEEDED(hr)) + hr = dialog->SetFileTypes(filters.file_types(), filters.filter_spec()); + if (SUCCEEDED(hr)) + hr = dialog->SetFileTypeIndex(1); + if (SUCCEEDED(hr)) + hr = dialog->SetDefaultExtension(filters.default_extension()); + } + + // set starting folder + if (SUCCEEDED(hr)) + { + std::string dir = device.working_directory(); + if (dir.empty()) + { + dir = device.device().machine().image().setup_working_directory(); + device.set_working_directory(dir); + } + std::string full; + if (!dir.empty() && !osd_get_full_path(full, dir)) + { + // FIXME: strip off archive names - opening a file inside an archive decompresses it to a temporary location + std::wstring wfull = osd::text::to_wstring(full); + Microsoft::WRL::ComPtr<IShellItem> item; + if (SUCCEEDED(SHCreateItemFromParsingName(wfull.c_str(), nullptr, IID_PPV_ARGS(&item)))) + { + //dialog->SetFolder(item); disabled until + } + } + } + + // show the dialog + if (SUCCEEDED(hr)) + { + hr = dialog->Show(owner); + if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) + return; + } + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr<IShellItem> result; + hr = dialog->GetResult(&result); + if (SUCCEEDED(hr)) + { + PWSTR selection = nullptr; + hr = result->GetDisplayName(SIGDN_FILESYSPATH, &selection); + if (SUCCEEDED(hr)) + { + std::string const utf_selection = osd::text::from_wstring(selection); + CoTaskMemFree(selection); + handler(utf_selection); + } + } + } + + if (!SUCCEEDED(hr)) + { + int pressed; + TaskDialog( + owner, + nullptr, // instance + nullptr, // title + L"Error showing file dialog", + nullptr, // content + TDCBF_OK_BUTTON, + TD_ERROR_ICON, + &pressed); + } +} + +} // anonymous namespace + + consolewin_info::consolewin_info(debugger_windows_interface &debugger) : disasmbasewin_info(debugger, true, "Debug", nullptr), m_current_cpu(nullptr), m_devices_menu(nullptr) { - if ((window() == nullptr) || (m_views[0] == nullptr)) + if (!window() || !m_views[0]) goto cleanup; // create the views - m_views[1].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_STATE))); + m_views[1].reset(new debugview_info(debugger, *this, window(), DVT_STATE)); if (!m_views[1]->is_valid()) goto cleanup; - m_views[2].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_CONSOLE))); + m_views[2].reset(new debugview_info(debugger, *this, window(), DVT_CONSOLE)); if (!m_views[2]->is_valid()) goto cleanup; { - // Add image menu only if image devices exist - image_interface_iterator iter(machine().root_device()); + // add image menu only if image devices exist + image_interface_enumerator iter(machine().root_device()); if (iter.first() != nullptr) { m_devices_menu = CreatePopupMenu(); for (device_image_interface &img : iter) { - if (!img.user_loadable()) - continue; - osd::text::tstring tc_buf = osd::text::to_tstring(string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[no image]")); - AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf.c_str()); + if (img.user_loadable()) + { + osd::text::tstring tc_buf = osd::text::to_tstring(string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[no image]")); + AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf.c_str()); + } } AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)m_devices_menu, TEXT("Media")); } + // add the settings menu + HMENU const settingsmenu = CreatePopupMenu(); + AppendMenu(settingsmenu, MF_ENABLED, ID_SAVE_WINDOWS, TEXT("Save Window Arrangement")); + AppendMenu(settingsmenu, MF_ENABLED, ID_GROUP_WINDOWS, TEXT("Group Debugger Windows (requires restart)")); + AppendMenu(settingsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(settingsmenu, MF_ENABLED, ID_LIGHT_BACKGROUND, TEXT("Light Background")); + AppendMenu(settingsmenu, MF_ENABLED, ID_DARK_BACKGROUND, TEXT("Dark Background")); + AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)settingsmenu, TEXT("Settings")); + // get the work bounds RECT work_bounds, bounds; SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0); @@ -78,7 +276,7 @@ consolewin_info::consolewin_info(debugger_windows_interface &debugger) : } // recompute the children - set_cpu(*machine().debugger().cpu().get_visible_cpu()); + set_cpu(*machine().debugger().console().get_visible_cpu()); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -163,11 +361,11 @@ void consolewin_info::update_menu() { disasmbasewin_info::update_menu(); - if (m_devices_menu != nullptr) + if (m_devices_menu) { // create the image menu uint32_t cnt = 0; - for (device_image_interface &img : image_interface_iterator(machine().root_device())) + for (device_image_interface &img : image_interface_enumerator(machine().root_device())) { if (!img.user_loadable()) continue; @@ -184,8 +382,8 @@ void consolewin_info::update_menu() if (img.is_readonly()) flags_for_writing |= MF_GRAYED; - // not working properly, removed for now until investigation can be done - //if (get_softlist_info(&img)) + // FIXME: needs a real software item picker to be useful + //if (get_softlist_info(img)) // AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_ITEM, TEXT("Mount Item...")); AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount File...")); @@ -199,7 +397,7 @@ void consolewin_info::update_menu() if (img.device().type() == CASSETTE) { - cassette_state const state = cassette_state(downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_UISTATE); + cassette_state const state = downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_UISTATE; AppendMenu(devicesubmenu, MF_SEPARATOR, 0, nullptr); AppendMenu(devicesubmenu, flags_for_exists | ((state == CASSETTE_STOPPED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_STOPPAUSE, TEXT("Pause/Stop")); AppendMenu(devicesubmenu, flags_for_exists | ((state == CASSETTE_PLAY) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_PLAY, TEXT("Play")); @@ -208,9 +406,9 @@ void consolewin_info::update_menu() AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_FASTFORWARD, TEXT("Fast Forward")); AppendMenu(devicesubmenu, MF_SEPARATOR, 0, nullptr); // Motor state can be overriden by the driver - cassette_state const motor_state = cassette_state(downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_MOTOR); + cassette_state const motor_state = downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_MOTOR; AppendMenu(devicesubmenu, flags_for_exists | ((motor_state == CASSETTE_MOTOR_ENABLED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_MOTOR, TEXT("Motor")); - cassette_state const speaker_state = cassette_state(downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_SPEAKER); + cassette_state const speaker_state = downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_SPEAKER; AppendMenu(devicesubmenu, flags_for_exists | ((speaker_state == CASSETTE_SPEAKER_ENABLED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_SOUND, TEXT("Audio while Loading")); } } @@ -249,239 +447,105 @@ void consolewin_info::update_menu() cnt++; } } + + HMENU const menu = GetMenu(window()); + CheckMenuItem(menu, ID_SAVE_WINDOWS, MF_BYCOMMAND | (debugger().get_save_window_arrangement() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_GROUP_WINDOWS, MF_BYCOMMAND | (debugger().get_group_windows_setting() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_LIGHT_BACKGROUND, MF_BYCOMMAND | ((ui_metrics::THEME_LIGHT_BACKGROUND == metrics().get_color_theme()) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_DARK_BACKGROUND, MF_BYCOMMAND | ((ui_metrics::THEME_DARK_BACKGROUND == metrics().get_color_theme()) ? MF_CHECKED : MF_UNCHECKED)); } bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam) { - if ((HIWORD(wparam) == 0) && (LOWORD(wparam) >= ID_DEVICE_OPTIONS)) + if (HIWORD(wparam) == 0) { - uint32_t const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX; - image_interface_iterator iter(machine().root_device()); - device_image_interface *const img = iter.byindex(devid); - if (img != nullptr) + if (LOWORD(wparam) >= ID_DEVICE_OPTIONS) { - switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX) + uint32_t const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX; + image_interface_enumerator iter(machine().root_device()); + device_image_interface *const img = iter.byindex(devid); + if (img != nullptr) { - case DEVOPTION_ITEM : - { - std::string filter; - build_generic_filter(nullptr, false, filter); - { - osd::text::tstring t_filter = osd::text::to_tstring(filter); - - // convert a pipe-char delimited string into a NUL delimited string - for (int i = 0; t_filter[i] != '\0'; i++) - { - if (t_filter[i] == '|') - t_filter[i] = '\0'; - } - - std::string opt_name = img->instance_name(); - std::string as = slmap.find(opt_name)->second; - - /* Make sure a folder was specified, and that it exists */ - if ((!osd::directory::open(as.c_str())) || (as.find(':') == std::string::npos)) - { - /* Default to emu directory */ - osd_get_full_path(as, "."); - } - osd::text::tstring t_dir = osd::text::to_tstring(as); - - // display the dialog - TCHAR selectedFilename[MAX_PATH]; - selectedFilename[0] = '\0'; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = nullptr; - ofn.lpstrFile = selectedFilename; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFilter = t_filter.c_str(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = t_dir.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - - if (GetOpenFileName(&ofn)) - { - std::string buf = std::string(osd::text::from_tstring(selectedFilename)); - // Get the Item name out of the full path - size_t t1 = buf.find(".zip"); // get rid of zip name and anything after - if (t1 != std::string::npos) - buf.erase(t1); - t1 = buf.find(".7z"); // get rid of 7zip name and anything after - if (t1 != std::string::npos) - buf.erase(t1); - t1 = buf.find_last_of("\\"); // put the swlist name in - buf[t1] = ':'; - t1 = buf.find_last_of("\\"); // get rid of path; we only want the item name - buf.erase(0, t1+1); - - // load software - img->load_software( buf.c_str()); - } - } - } - return true; - case DEVOPTION_OPEN : - { - std::string filter; - build_generic_filter(img, false, filter); - { - osd::text::tstring t_filter = osd::text::to_tstring(filter); - - // convert a pipe-char delimited string into a NUL delimited string - for (int i = 0; t_filter[i] != '\0'; i++) - { - if (t_filter[i] == '|') - t_filter[i] = '\0'; - } - - char buf[400]; - std::string as; - strcpy(buf, machine().options().emu_options::sw_path()); - // This pulls out the first path from a multipath field - const char* t1 = strtok(buf, ";"); - if (t1) - as = t1; // the first path of many - else - as = buf; // the only path - - /* Make sure a folder was specified, and that it exists */ - if ((!osd::directory::open(as.c_str())) || (as.find(':') == std::string::npos)) - { - /* Default to emu directory */ - osd_get_full_path(as, "."); - } - osd::text::tstring t_dir = osd::text::to_tstring(as); - - TCHAR selectedFilename[MAX_PATH]; - selectedFilename[0] = '\0'; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = nullptr; - ofn.lpstrFile = selectedFilename; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFilter = t_filter.c_str(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = t_dir.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - - if (GetOpenFileName(&ofn)) - { - auto utf8_buf = osd::text::from_tstring(selectedFilename); - img->load(utf8_buf.c_str()); - } - } - } - return true; - case DEVOPTION_CREATE: - { - std::string filter; - build_generic_filter(img, true, filter); - { - osd::text::tstring t_filter = osd::text::to_tstring(filter); - // convert a pipe-char delimited string into a NUL delimited string - for (int i = 0; t_filter[i] != '\0'; i++) - { - if (t_filter[i] == '|') - t_filter[i] = '\0'; - } - - char buf[400]; - std::string as; - strcpy(buf, machine().options().emu_options::sw_path()); - // This pulls out the first path from a multipath field - const char* t1 = strtok(buf, ";"); - if (t1) - as = t1; // the first path of many - else - as = buf; // the only path - - /* Make sure a folder was specified, and that it exists */ - if ((!osd::directory::open(as.c_str())) || (as.find(':') == std::string::npos)) - { - /* Default to emu directory */ - osd_get_full_path(as, "."); - } - osd::text::tstring t_dir = osd::text::to_tstring(as); - - TCHAR selectedFilename[MAX_PATH]; - selectedFilename[0] = '\0'; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = nullptr; - ofn.lpstrFile = selectedFilename; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFilter = t_filter.c_str(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = t_dir.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST; - - if (GetSaveFileName(&ofn)) - { - auto utf8_buf = osd::text::from_tstring(selectedFilename); - img->create(utf8_buf.c_str(), img->device_get_indexed_creatable_format(0), nullptr); - } - } - } - return true; - case DEVOPTION_CLOSE: - img->unload(); - return true; - } - if (img->device().type() == CASSETTE) - { - cassette_image_device *const cassette = downcast<cassette_image_device *>(&img->device()); - bool s; switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX) { - case DEVOPTION_CASSETTE_STOPPAUSE: - cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); + case DEVOPTION_ITEM: + // TODO: this is supposed to show a software list item picker - it never worked properly return true; - case DEVOPTION_CASSETTE_PLAY: - cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); + case DEVOPTION_OPEN : + open_image_file(*img); return true; - case DEVOPTION_CASSETTE_RECORD: - cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); + case DEVOPTION_CREATE: + create_image_file(*img); return true; - case DEVOPTION_CASSETTE_REWIND: - cassette->seek(0.0, SEEK_SET); // to start + case DEVOPTION_CLOSE: + img->unload(); return true; - case DEVOPTION_CASSETTE_FASTFORWARD: - cassette->seek(+300.0, SEEK_CUR); // 5 minutes forward or end, whichever comes first - break; - case DEVOPTION_CASSETTE_MOTOR: - s =((cassette->get_state() & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED); - cassette->change_state(s ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); - break; - case DEVOPTION_CASSETTE_SOUND: - s =((cassette->get_state() & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_MUTED); - cassette->change_state(s ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); - break; + } + if (img->device().type() == CASSETTE) + { + auto *const cassette = downcast<cassette_image_device *>(&img->device()); + bool s; + switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX) + { + case DEVOPTION_CASSETTE_STOPPAUSE: + cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); + return true; + case DEVOPTION_CASSETTE_PLAY: + cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); + return true; + case DEVOPTION_CASSETTE_RECORD: + cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); + return true; + case DEVOPTION_CASSETTE_REWIND: + cassette->seek(0.0, SEEK_SET); // to start + return true; + case DEVOPTION_CASSETTE_FASTFORWARD: + cassette->seek(+300.0, SEEK_CUR); // 5 minutes forward or end, whichever comes first + return true; + case DEVOPTION_CASSETTE_MOTOR: + s = ((cassette->get_state() & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED); + cassette->change_state(s ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); + return true; + case DEVOPTION_CASSETTE_SOUND: + s = ((cassette->get_state() & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_MUTED); + cassette->change_state(s ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); + return true; + } } } } + else switch (LOWORD(wparam)) + { + case ID_SAVE_WINDOWS: + debugger().set_save_window_arrangement(!debugger().get_save_window_arrangement()); + return true; + case ID_GROUP_WINDOWS: + debugger().set_group_windows_setting(!debugger().get_group_windows_setting()); + return true; + case ID_LIGHT_BACKGROUND: + debugger().set_color_theme(ui_metrics::THEME_LIGHT_BACKGROUND); + return true; + case ID_DARK_BACKGROUND: + debugger().set_color_theme(ui_metrics::THEME_DARK_BACKGROUND); + return true; + } } return disasmbasewin_info::handle_command(wparam, lparam); } +void consolewin_info::save_configuration_to_node(util::xml::data_node &node) +{ + disasmbasewin_info::save_configuration_to_node(node); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_CONSOLE); +} + + void consolewin_info::process_string(std::string const &string) { if (string.empty()) // an empty string is a single step - machine().debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine().debugger().console().get_visible_cpu()->debug()->single_step(); else // otherwise, just process the command machine().debugger().console().execute_command(string, true); @@ -490,94 +554,60 @@ void consolewin_info::process_string(std::string const &string) } -void consolewin_info::build_generic_filter(device_image_interface *img, bool is_save, std::string &filter) +void consolewin_info::open_image_file(device_image_interface &device) { - std::string file_extension; - - if (img) - file_extension = img->file_extensions(); - - if (!is_save) - file_extension.append(",zip,7z"); - - add_filter_entry(filter, "Common image types", file_extension.c_str()); - - filter.append("All files (*.*)|*.*|"); - - if (!is_save) - filter.append("Compressed Images (*.zip;*.7z)|*.zip;*.7z|"); + choose_image( + device, + window(), + CLSID_FileOpenDialog, + true, + [this, &device] (std::string_view selection) + { + auto [err, message] = device.load(selection); + if (err) + machine().debugger().console().printf("Error mounting image file: %s\n", !message.empty() ? message : err.message()); + }); } -void consolewin_info::add_filter_entry(std::string &dest, const char *description, const char *extensions) +void consolewin_info::create_image_file(device_image_interface &device) { - // add the description - dest.append(description); - dest.append(" ("); - - // add the extensions to the description - copy_extension_list(dest, extensions); - - // add the trailing rparen and '|' character - dest.append(")|"); - - // now add the extension list itself - copy_extension_list(dest, extensions); - - // append a '|' - dest.append("|"); + choose_image( + device, + window(), + CLSID_FileSaveDialog, + false, + [this, &device] (std::string_view selection) + { + auto [err, message] = device.create(selection, device.device_get_indexed_creatable_format(0), nullptr); + if (err) + machine().debugger().console().printf("Error creating image file: %s\n", !message.empty() ? message : err.message()); + }); } -void consolewin_info::copy_extension_list(std::string &dest, const char *extensions) -{ - // our extension lists are comma delimited; Win32 expects to see lists - // delimited by semicolons - char const *s = extensions; - while (*s) - { - // append a semicolon if not at the beginning - if (s != extensions) - dest.push_back(';'); - - // append ".*" - dest.append("*."); - - // append the file extension - while (*s && (*s != ',')) - dest.push_back(*s++); - - // if we found a comma, advance - while(*s == ',') - s++; - } -} - -//============================================================ -// get_softlist_info -//============================================================ -bool consolewin_info::get_softlist_info(device_image_interface *img) +bool consolewin_info::get_softlist_info(device_image_interface &device) { bool has_software = false; bool passes_tests = false; - std::string sl_dir, opt_name = img->instance_name(); + std::string sl_dir, opt_name = device.instance_name(); // Get the path to suitable software - for (software_list_device &swlist : software_list_device_iterator(machine().root_device())) + for (software_list_device &swlist : software_list_device_enumerator(machine().root_device())) { for (const software_info &swinfo : swlist.get_info()) { const software_part &part = swinfo.parts().front(); if (swlist.is_compatible(part) == SOFTWARE_IS_COMPATIBLE) { - for (device_image_interface &image : image_interface_iterator(machine().root_device())) + for (device_image_interface &image : image_interface_enumerator(machine().root_device())) { if (!image.user_loadable()) continue; if (!has_software && (opt_name == image.instance_name())) { - const char *interface = image.image_interface(); - if (interface && part.matches_interface(interface)) + const char *intf = image.image_interface(); + if (intf && part.matches_interface(intf)) { sl_dir = "\\" + swlist.list_name(); has_software = true; @@ -598,7 +628,7 @@ bool consolewin_info::get_softlist_info(device_image_interface *img) while (sl_root && !passes_tests) { std::string test_path = sl_root + sl_dir; - if (osd::directory::open(test_path.c_str())) + if (osd::directory::open(test_path)) { passes_tests = true; slmap[opt_name] = test_path; @@ -609,3 +639,5 @@ bool consolewin_info::get_softlist_info(device_image_interface *img) return passes_tests; } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/consolewininfo.h b/src/osd/modules/debugger/win/consolewininfo.h index 7f8ccc13aec..e79ba667a11 100644 --- a/src/osd/modules/debugger/win/consolewininfo.h +++ b/src/osd/modules/debugger/win/consolewininfo.h @@ -5,15 +5,18 @@ // consolewininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_CONSOLEWININFO_H +#define MAME_DEBUGGER_WIN_CONSOLEWININFO_H -#ifndef __DEBUG_WIN_CONSOLE_WIN_INFO_H__ -#define __DEBUG_WIN_CONSOLE_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "disasmbasewininfo.h" +namespace osd::debugger::win { + class consolewin_info : public disasmbasewin_info { public: @@ -26,6 +29,7 @@ protected: virtual void recompute_children() override; virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; private: enum @@ -46,14 +50,15 @@ private: virtual void process_string(std::string const &string) override; - static void build_generic_filter(device_image_interface *img, bool is_save, std::string &filter); - static void add_filter_entry(std::string &dest, char const *description, char const *extensions); - static void copy_extension_list(std::string &dest, char const *extensions); - bool get_softlist_info(device_image_interface *img); + void open_image_file(device_image_interface &device); + void create_image_file(device_image_interface &device); + bool get_softlist_info(device_image_interface &img); device_t *m_current_cpu; - HMENU m_devices_menu; + HMENU m_devices_menu; std::map<std::string,std::string> slmap; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_CONSOLEWININFO_H diff --git a/src/osd/modules/debugger/win/debugbaseinfo.cpp b/src/osd/modules/debugger/win/debugbaseinfo.cpp index 4914d54cfad..0de7331cbc8 100644 --- a/src/osd/modules/debugger/win/debugbaseinfo.cpp +++ b/src/osd/modules/debugger/win/debugbaseinfo.cpp @@ -10,6 +10,8 @@ #include "debugbaseinfo.h" +namespace osd::debugger::win { + debugbase_info::debugbase_info(debugger_windows_interface &debugger) : m_debugger(debugger), m_machine(debugger.machine()), @@ -21,12 +23,10 @@ debugbase_info::debugbase_info(debugger_windows_interface &debugger) : void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const &bounds) { - RECT curbounds; - int flags = 0; - // first get the current bounds, relative to the parent + RECT curbounds; GetWindowRect(wnd, &curbounds); - if (parent != nullptr) + if (parent) { RECT parentbounds; GetWindowRect(parent, &parentbounds); @@ -37,6 +37,7 @@ void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const & } // if the position matches, don't change it + int flags = 0; if (curbounds.top == bounds.top && curbounds.left == bounds.left) flags |= SWP_NOMOVE; if ((curbounds.bottom - curbounds.top) == (bounds.bottom - bounds.top) && @@ -45,17 +46,21 @@ void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const & // if we need to, reposition the window if (flags != (SWP_NOMOVE | SWP_NOSIZE)) - SetWindowPos(wnd, nullptr, - bounds.left, bounds.top, - bounds.right - bounds.left, bounds.bottom - bounds.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags); + { + SetWindowPos( + wnd, nullptr, + bounds.left, bounds.top, + bounds.right - bounds.left, bounds.bottom - bounds.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags); + } } - void debugbase_info::smart_show_window(HWND wnd, bool show) { - BOOL const visible = IsWindowVisible(wnd); - if ((visible && !show) || (!visible && show)) + bool const visible = bool(IsWindowVisible(wnd)); + if (visible != show) ShowWindow(wnd, show ? SW_SHOW : SW_HIDE); } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/debugbaseinfo.h b/src/osd/modules/debugger/win/debugbaseinfo.h index 03fd5a8018d..da874a6b8fd 100644 --- a/src/osd/modules/debugger/win/debugbaseinfo.h +++ b/src/osd/modules/debugger/win/debugbaseinfo.h @@ -5,13 +5,15 @@ // debugbaseinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGBASEINFO_H +#define MAME_DEBUGGER_WIN_DEBUGBASEINFO_H -#ifndef __DEBUG_WIN_DEBUG_BASE_INFO_H__ -#define __DEBUG_WIN_DEBUG_BASE_INFO_H__ +#pragma once #include "debugwin.h" +namespace osd::debugger::win { class debugbase_info { @@ -35,5 +37,6 @@ private: bool const &m_waiting_for_debugger; }; +} // namespace osd::debugger::win -#endif +#endif // MAME_DEBUGGER_WIN_DEBUGBASEINFO_H diff --git a/src/osd/modules/debugger/win/debugviewinfo.cpp b/src/osd/modules/debugger/win/debugviewinfo.cpp index 97238ff8862..8f3f05c16d2 100644 --- a/src/osd/modules/debugger/win/debugviewinfo.cpp +++ b/src/osd/modules/debugger/win/debugviewinfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugview.c - Win32 debug window handling +// debugviewinfo.cpp - Win32 debug window handling // //============================================================ @@ -12,12 +12,20 @@ #include "debugwininfo.h" #include "uimetrics.h" #include "debugger.h" + +#include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "util/xmlfile.h" + #include "strconv.h" #include "winutil.h" +#include <mmsystem.h> + + +namespace osd::debugger::win { // debugger view styles #define DEBUG_VIEW_STYLE WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN @@ -45,14 +53,15 @@ debugview_info::debugview_info(debugger_windows_interface &debugger, debugwin_in m_view(nullptr), m_wnd(nullptr), m_hscroll(nullptr), - m_vscroll(nullptr) + m_vscroll(nullptr), + m_contextmenu(nullptr) { register_window_class(); // create the child view m_wnd = CreateWindowEx(DEBUG_VIEW_STYLE_EX, TEXT("MAMEDebugView"), nullptr, DEBUG_VIEW_STYLE, 0, 0, 100, 100, parent, nullptr, GetModuleHandleUni(), this); - if (m_wnd == nullptr) + if (!m_wnd) goto cleanup; // create the scroll bars @@ -60,27 +69,27 @@ debugview_info::debugview_info(debugger_windows_interface &debugger, debugwin_in 0, 0, 100, CW_USEDEFAULT, m_wnd, nullptr, GetModuleHandleUni(), this); m_vscroll = CreateWindowEx(VSCROLL_STYLE_EX, TEXT("SCROLLBAR"), nullptr, VSCROLL_STYLE, 0, 0, CW_USEDEFAULT, 100, m_wnd, nullptr, GetModuleHandleUni(), this); - if ((m_hscroll == nullptr) || (m_vscroll == nullptr)) + if (!m_hscroll || !m_vscroll) goto cleanup; // create the debug view m_view = machine().debug_view().alloc_view(type, &debugview_info::static_update, this); - if (m_view == nullptr) + if (!m_view) goto cleanup; return; cleanup: - if (m_hscroll != nullptr) + if (m_hscroll) DestroyWindow(m_hscroll); m_hscroll = nullptr; - if (m_vscroll != nullptr) + if (m_vscroll) DestroyWindow(m_vscroll); m_vscroll = nullptr; - if (m_wnd != nullptr) + if (m_wnd) DestroyWindow(m_wnd); m_wnd = nullptr; - if (m_view != nullptr) + if (m_view) machine().debug_view().free_view(*m_view); m_view = nullptr; } @@ -88,7 +97,9 @@ cleanup: debugview_info::~debugview_info() { - if (m_wnd != nullptr) + if (m_contextmenu) + DestroyMenu(m_contextmenu); + if (m_wnd) DestroyWindow(m_wnd); if (m_view) machine().debug_view().free_view(*m_view); @@ -111,14 +122,14 @@ uint32_t debugview_info::maxwidth() { uint32_t max = m_view->total_size().x; debug_view_source const *const cursource = m_view->source(); - for (const debug_view_source &source : m_view->source_list()) + for (auto &source : m_view->source_list()) { - m_view->set_source(source); + m_view->set_source(*source); uint32_t const chars = m_view->total_size().x; if (max < chars) max = chars; } - if (cursource != nullptr) + if (cursource) m_view->set_source(*cursource); return (max * metrics().debug_font_width()) + metrics().vscroll_width(); } @@ -163,27 +174,35 @@ void debugview_info::send_vscroll(int delta) void debugview_info::send_pageup() { if (m_vscroll) - { SendMessage(m_wnd, WM_VSCROLL, SB_PAGELEFT, (LPARAM)m_vscroll); - } } void debugview_info::send_pagedown() { if (m_vscroll) - { SendMessage(m_wnd, WM_VSCROLL, SB_PAGERIGHT, (LPARAM)m_vscroll); +} + + +int debugview_info::source_index() const +{ + if (m_view) + { + debug_view_source const *const source = m_view->source(); + if (source) + return m_view->source_index(*source); } + return -1; } char const *debugview_info::source_name() const { - if (m_view != nullptr) + if (m_view) { debug_view_source const *const source = m_view->source(); - if (source != nullptr) + if (source) return source->name(); } return ""; @@ -192,10 +211,10 @@ char const *debugview_info::source_name() const device_t *debugview_info::source_device() const { - if (m_view != nullptr) + if (m_view) { debug_view_source const *const source = m_view->source(); - if (source != nullptr) + if (source) return source->device(); } return nullptr; @@ -204,10 +223,10 @@ device_t *debugview_info::source_device() const bool debugview_info::source_is_visible_cpu() const { - if (m_view != nullptr) + if (m_view) { const debug_view_source *const source = m_view->source(); - return (source != nullptr) && (machine().debugger().cpu().get_visible_cpu() == source->device()); + return source && (machine().debugger().console().get_visible_cpu() == source->device()); } return false; } @@ -215,10 +234,10 @@ bool debugview_info::source_is_visible_cpu() const bool debugview_info::set_source_index(int index) { - if (m_view != nullptr) + if (m_view) { - const debug_view_source *const source = m_view->source_list().find(index); - if (source != nullptr) + const debug_view_source *const source = m_view->source(index); + if (source) { m_view->set_source(*source); return true; @@ -230,10 +249,10 @@ bool debugview_info::set_source_index(int index) bool debugview_info::set_source_for_device(device_t &device) { - if (m_view != nullptr) + if (m_view) { const debug_view_source *const source = m_view->source_for_device(&device); - if (source != nullptr) + if (source) { m_view->set_source(*source); return true; @@ -245,8 +264,8 @@ bool debugview_info::set_source_for_device(device_t &device) bool debugview_info::set_source_for_visible_cpu() { - device_t *const curcpu = machine().debugger().cpu().get_visible_cpu(); - if (curcpu != nullptr) + device_t *const curcpu = machine().debugger().console().get_visible_cpu(); + if (curcpu) return set_source_for_device(*curcpu); else return false; @@ -264,7 +283,7 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata) // populate the combobox debug_view_source const *const cursource = m_view->source(); int maxlength = 0; - for (debug_view_source const *source = m_view->first_source(); source != nullptr; source = source->next()) + for (auto &source : m_view->source_list()) { int const length = strlen(source->name()); if (length > maxlength) @@ -272,9 +291,9 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata) auto t_name = osd::text::to_tstring(source->name()); SendMessage(result, CB_ADDSTRING, 0, (LPARAM)t_name.c_str()); } - if (cursource != nullptr) + if (cursource) { - SendMessage(result, CB_SETCURSEL, m_view->source_list().indexof(*cursource), 0); + SendMessage(result, CB_SETCURSEL, m_view->source_index(*cursource), 0); SendMessage(result, CB_SETDROPPEDWIDTH, ((maxlength + 2) * metrics().debug_font_width()) + metrics().vscroll_width(), 0); m_view->set_source(*cursource); } @@ -282,6 +301,165 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata) } +void debugview_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + if (m_view->cursor_supported()) + { + util::xml::data_node const *const selection = node.get_child(NODE_WINDOW_SELECTION); + if (selection) + { + debug_view_xy pos = m_view->cursor_position(); + m_view->set_cursor_visible(0 != selection->get_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0)); + selection->get_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x); + selection->get_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y); + m_view->set_cursor_position(pos); + } + } + + util::xml::data_node const *const scroll = node.get_child(NODE_WINDOW_SCROLL); + if (scroll) + { + debug_view_xy origin = m_view->visible_position(); + origin.x = scroll->get_attribute_int(ATTR_SCROLL_ORIGIN_X, origin.x * metrics().debug_font_width()) / metrics().debug_font_width(); + origin.y = scroll->get_attribute_int(ATTR_SCROLL_ORIGIN_Y, origin.y * metrics().debug_font_height()) / metrics().debug_font_height(); + m_view->set_visible_position(origin); + } +} + + +void debugview_info::save_configuration_to_node(util::xml::data_node &node) +{ + if (m_view->cursor_supported()) + { + util::xml::data_node *const selection = node.add_child(NODE_WINDOW_SELECTION, nullptr); + if (selection) + { + debug_view_xy const pos = m_view->cursor_position(); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y); + } + } + + util::xml::data_node *const scroll = node.add_child(NODE_WINDOW_SCROLL, nullptr); + if (scroll) + { + debug_view_xy const origin = m_view->visible_position(); + scroll->set_attribute_int(ATTR_SCROLL_ORIGIN_X, origin.x * metrics().debug_font_width()); + scroll->set_attribute_int(ATTR_SCROLL_ORIGIN_Y, origin.y * metrics().debug_font_height()); + } +} + + +void debugview_info::add_items_to_context_menu(HMENU menu) +{ + AppendMenu(menu, MF_ENABLED, ID_CONTEXT_COPY_VISIBLE, TEXT("Copy Visible")); + AppendMenu(menu, MF_ENABLED, ID_CONTEXT_PASTE, TEXT("Paste")); +} + + +void debugview_info::update_context_menu(HMENU menu) +{ + EnableMenuItem(menu, ID_CONTEXT_PASTE, MF_BYCOMMAND | (IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED)); +} + + +void debugview_info::handle_context_menu(unsigned command) +{ + switch (command) + { + case ID_CONTEXT_COPY_VISIBLE: + { + // get visible text + debug_view_xy const visarea = m_view->visible_size(); + debug_view_char const *viewdata = m_view->viewdata(); + if (!viewdata) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + break; + } + + // turn into a plain string, trimming trailing whitespace + std::wstring text; + for (uint32_t row = 0; row < visarea.y; row++, viewdata += visarea.x) + { + std::wstring::size_type const start = text.length(); + for (uint32_t col = 0; col < visarea.x; ++col) + text += wchar_t(viewdata[col].byte); + std::wstring::size_type const nonblank = text.find_last_not_of(L"\t\n\v\r "); + if (nonblank != std::wstring::npos) + text.resize((std::max)(start, nonblank + 1)); + text += L"\r\n"; + } + + // copy to the clipboard + HGLOBAL const clip = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(wchar_t)); + if (!clip) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + break; + } + if (!OpenClipboard(m_wnd)) + { + GlobalFree(clip); + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + break; + } + EmptyClipboard(); + LPWSTR const lock = reinterpret_cast<LPWSTR>(GlobalLock(clip)); + std::copy_n(text.c_str(), text.length() + 1, lock); + GlobalUnlock(clip); + if (!SetClipboardData(CF_UNICODETEXT, clip)) + { + GlobalFree(clip); + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + } + CloseClipboard(); + break; + } + + case ID_CONTEXT_PASTE: + if (!IsClipboardFormatAvailable(CF_UNICODETEXT) || !OpenClipboard(m_wnd)) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + } + else + { + HGLOBAL const clip = GetClipboardData(CF_UNICODETEXT); + LPCWSTR lock = clip ? reinterpret_cast<LPCWSTR>(GlobalLock(clip)) : nullptr; + if (!clip || !lock) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + } + else + { + try + { + while (*lock) + { + if ((32 <= *lock) && (127 >= *lock)) + m_view->process_char(*lock); + ++lock; + } + } + catch (...) + { + GlobalUnlock(clip); + CloseClipboard(); + throw; + } + GlobalUnlock(clip); + } + CloseClipboard(); + } + break; + + default: + osd_printf_warning("debugview_info: unhandled context menu item %u\n", command); + } +} + + void debugview_info::draw_contents(HDC windc) { debug_view_char const *viewdata = m_view->viewdata(); @@ -290,18 +468,22 @@ void debugview_info::draw_contents(HDC windc) // get the client rect RECT client; GetClientRect(m_wnd, &client); + bool const need_filldown = client.bottom > (metrics().debug_font_height() * visarea.y); // create a compatible DC and an offscreen bitmap HDC const dc = CreateCompatibleDC(windc); - if (dc == nullptr) + if (!dc) return; HBITMAP const bitmap = CreateCompatibleBitmap(windc, client.right, client.bottom); - if (bitmap == nullptr) + if (!bitmap) { DeleteDC(dc); return; } HGDIOBJ const oldbitmap = SelectObject(dc, bitmap); + bool const show_hscroll = m_hscroll && IsWindowVisible(m_hscroll); + if (show_hscroll) + client.bottom -= metrics().hscroll_height(); // set the font HGDIOBJ const oldfont = SelectObject(dc, metrics().debug_font()); @@ -312,11 +494,13 @@ void debugview_info::draw_contents(HDC windc) // iterate over rows and columns for (uint32_t row = 0; row < visarea.y; row++) { + bool do_filldown = (row == (visarea.y - 1)) && need_filldown; + // loop twice; once to fill the background and once to draw the text for (int iter = 0; iter < 2; iter++) { COLORREF fgcolor; - COLORREF bgcolor = RGB(0xff,0xff,0xff); + COLORREF bgcolor = metrics().view_colors(DCA_NORMAL).second; HBRUSH bgbrush = nullptr; int last_attrib = -1; TCHAR buffer[256]; @@ -340,41 +524,49 @@ void debugview_info::draw_contents(HDC windc) { COLORREF oldbg = bgcolor; - // reset to standard colors - fgcolor = RGB(0x00,0x00,0x00); - bgcolor = RGB(0xff,0xff,0xff); - - // pick new fg/bg colors - if (viewdata[col].attrib & DCA_VISITED) bgcolor = RGB(0xc6, 0xe2, 0xff); - if (viewdata[col].attrib & DCA_ANCILLARY) bgcolor = RGB(0xe0,0xe0,0xe0); - if (viewdata[col].attrib & DCA_SELECTED) bgcolor = RGB(0xff,0x80,0x80); - if (viewdata[col].attrib & DCA_CURRENT) bgcolor = RGB(0xff,0xff,0x00); - if ((viewdata[col].attrib & DCA_SELECTED) && (viewdata[col].attrib & DCA_CURRENT)) bgcolor = RGB(0xff,0xc0,0x80); - if (viewdata[col].attrib & DCA_CHANGED) fgcolor = RGB(0xff,0x00,0x00); - if (viewdata[col].attrib & DCA_INVALID) fgcolor = RGB(0x00,0x00,0xff); - if (viewdata[col].attrib & DCA_DISABLED) fgcolor = RGB((GetRValue(fgcolor) + GetRValue(bgcolor)) / 2, (GetGValue(fgcolor) + GetGValue(bgcolor)) / 2, (GetBValue(fgcolor) + GetBValue(bgcolor)) / 2); - if (viewdata[col].attrib & DCA_COMMENT) fgcolor = RGB(0x00,0x80,0x00); + // pick new colors + std::tie(fgcolor, bgcolor) = metrics().view_colors(viewdata[col].attrib); // flush any pending drawing if (count > 0) { bounds.right = bounds.left + (count * metrics().debug_font_width()); if (iter == 0) + { FillRect(dc, &bounds, bgbrush); + if (do_filldown) + { + COLORREF const filldown = metrics().view_colors(last_attrib & DCA_ANCILLARY).second; + if (oldbg != filldown) + { + DeleteObject(bgbrush); + bgbrush = CreateSolidBrush(filldown); + oldbg = filldown; + } + RECT padding = bounds; + padding.top = padding.bottom; + padding.bottom = client.bottom; + FillRect(dc, &padding, bgbrush); + } + } else + { ExtTextOut(dc, bounds.left, bounds.top, 0, nullptr, buffer, count, nullptr); + } bounds.left = bounds.right; count = 0; } // set the new colors - if (iter == 0 && oldbg != bgcolor) + if (iter == 1) + { + SetTextColor(dc, fgcolor); + } + else if (oldbg != bgcolor) { DeleteObject(bgbrush); bgbrush = CreateSolidBrush(bgcolor); } - else if (iter == 1) - SetTextColor(dc, fgcolor); last_attrib = viewdata[col].attrib; } @@ -383,33 +575,43 @@ void debugview_info::draw_contents(HDC windc) } // flush any remaining stuff - if (count > 0) - { - bounds.right = bounds.left + (count * metrics().debug_font_width()); - if (iter == 0) - FillRect(dc, &bounds, bgbrush); - else - ExtTextOut(dc, bounds.left, bounds.top, 0, nullptr, buffer, count, nullptr); - } - - // erase to the end of the line + bounds.right = bounds.left + (count * metrics().debug_font_width()); if (iter == 0) { - bounds.left = bounds.right; + // erase to the end of the line bounds.right = client.right; FillRect(dc, &bounds, bgbrush); + if (do_filldown) + { + COLORREF const filldown = metrics().view_colors(last_attrib & DCA_ANCILLARY).second; + if (bgcolor != filldown) + { + DeleteObject(bgbrush); + bgbrush = CreateSolidBrush(filldown); + } + bounds.top = bounds.bottom; + bounds.bottom = client.bottom; + FillRect(dc, &bounds, bgbrush); + } DeleteObject(bgbrush); } + else if (count > 0) + { + ExtTextOut(dc, bounds.left, bounds.top, 0, nullptr, buffer, count, nullptr); + } } // advance viewdata viewdata += visarea.x; } - // erase anything beyond the bottom with white - GetClientRect(m_wnd, &client); - client.top = visarea.y * metrics().debug_font_height(); - FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH)); + // prevent garbage from showing in the corner + if (show_hscroll) + { + client.top = client.bottom; + client.bottom = client.top + metrics().hscroll_height(); + FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH)); + } // reset the font SetBkMode(dc, oldbkmode); @@ -428,47 +630,48 @@ void debugview_info::draw_contents(HDC windc) void debugview_info::update() { - RECT bounds, vscroll_bounds, hscroll_bounds; - debug_view_xy totalsize, visiblesize, topleft; - bool show_vscroll, show_hscroll; SCROLLINFO scrollinfo; + // get the updated total rows/cols and left row/col + debug_view_xy const totalsize = m_view->total_size(); + debug_view_xy topleft = m_view->visible_position(); + // get the view window bounds + RECT bounds; GetClientRect(m_wnd, &bounds); + debug_view_xy visiblesize; visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width(); visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height(); - // get the updated total rows/cols and left row/col - totalsize = m_view->total_size(); - topleft = m_view->visible_position(); - // determine if we need to show the scrollbars - show_vscroll = show_hscroll = false; - if (totalsize.x > visiblesize.x && bounds.bottom >= metrics().hscroll_height()) + bool const fit_hscroll = (bounds.bottom - bounds.top) > metrics().hscroll_height(); + bool show_hscroll = fit_hscroll && (totalsize.x > visiblesize.x); + if (show_hscroll) { bounds.bottom -= metrics().hscroll_height(); visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height(); - show_hscroll = true; - } - if (totalsize.y > visiblesize.y && bounds.right >= metrics().vscroll_width()) - { - bounds.right -= metrics().vscroll_width(); - visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width(); - show_vscroll = true; } - if (!show_vscroll && totalsize.y > visiblesize.y && bounds.right >= metrics().vscroll_width()) + bool const fit_vscroll = (bounds.right - bounds.left) > metrics().vscroll_width(); + bool const show_vscroll = fit_vscroll && (totalsize.y > visiblesize.y); + if (show_vscroll) { bounds.right -= metrics().vscroll_width(); visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width(); - show_vscroll = true; + if (fit_hscroll && !show_hscroll && (totalsize.x > visiblesize.x)) + { + bounds.bottom -= metrics().hscroll_height(); + visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height(); + show_hscroll = true; + } } // compute the bounds of the scrollbars + RECT vscroll_bounds; GetClientRect(m_wnd, &vscroll_bounds); vscroll_bounds.left = vscroll_bounds.right - metrics().vscroll_width(); if (show_hscroll) vscroll_bounds.bottom -= metrics().hscroll_height(); - + RECT hscroll_bounds; GetClientRect(m_wnd, &hscroll_bounds); hscroll_bounds.top = hscroll_bounds.bottom - metrics().hscroll_height(); if (show_vscroll) @@ -481,26 +684,34 @@ void debugview_info::update() topleft.x = std::max(totalsize.x - visiblesize.x, 0); // fill out the scroll info struct for the vertical scrollbar - scrollinfo.cbSize = sizeof(scrollinfo); - scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - scrollinfo.nMin = 0; - scrollinfo.nMax = totalsize.y - 1; - scrollinfo.nPage = visiblesize.y; - scrollinfo.nPos = topleft.y; - SetScrollInfo(m_vscroll, SB_CTL, &scrollinfo, TRUE); + if (m_vscroll) + { + scrollinfo.cbSize = sizeof(scrollinfo); + scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + scrollinfo.nMin = 0; + scrollinfo.nMax = totalsize.y - 1; + scrollinfo.nPage = visiblesize.y; + scrollinfo.nPos = topleft.y; + SetScrollInfo(m_vscroll, SB_CTL, &scrollinfo, TRUE); + } // fill out the scroll info struct for the horizontal scrollbar - scrollinfo.cbSize = sizeof(scrollinfo); - scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - scrollinfo.nMin = 0; - scrollinfo.nMax = totalsize.x - 1; - scrollinfo.nPage = visiblesize.x; - scrollinfo.nPos = topleft.x; - SetScrollInfo(m_hscroll, SB_CTL, &scrollinfo, TRUE); + if (m_hscroll) + { + scrollinfo.cbSize = sizeof(scrollinfo); + scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + scrollinfo.nMin = 0; + scrollinfo.nMax = totalsize.x - 1; + scrollinfo.nPage = visiblesize.x; + scrollinfo.nPos = topleft.x; + SetScrollInfo(m_hscroll, SB_CTL, &scrollinfo, TRUE); + } // update window info - visiblesize.y++; - visiblesize.x++; + if (((bounds.right - bounds.left) > (visiblesize.x * metrics().debug_font_width())) && ((topleft.x + visiblesize.x) < totalsize.x)) + visiblesize.x++; + if (((bounds.bottom - bounds.top) > (visiblesize.y * metrics().debug_font_height())) && ((topleft.y + visiblesize.y) < totalsize.y)) + visiblesize.y++; m_view->set_visible_size(visiblesize); m_view->set_visible_position(topleft); @@ -580,7 +791,41 @@ uint32_t debugview_info::process_scroll(WORD type, HWND wnd) scrollinfo.nPos = result; SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE); - return (uint32_t)result; + return uint32_t(result); +} + + +bool debugview_info::process_context_menu(int x, int y) +{ + // don't show a menu if not in client rect + RECT clientrect; + GetClientRect(m_wnd, &clientrect); + POINT loc{ x, y }; + ScreenToClient(m_wnd, &loc); + if (!PtInRect(&clientrect, loc)) + return false; + + // create the context menu if we haven’t already + if (!m_contextmenu) + { + m_contextmenu = CreatePopupMenu(); + if (!m_contextmenu) + return false; + add_items_to_context_menu(m_contextmenu); + } + + // show the context menu + update_context_menu(m_contextmenu); + BOOL const command(TrackPopupMenu( + m_contextmenu, + (GetSystemMetrics(SM_MENUDROPALIGNMENT) ? TPM_RIGHTALIGN : TPM_LEFTALIGN) | TPM_LEFTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, + x, y, + 0, + m_wnd, + nullptr)); + if (command) + handle_context_menu(command); + return true; } @@ -603,7 +848,7 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) case WM_SYSKEYDOWN: if (wparam != VK_F10) return DefWindowProc(m_wnd, message, wparam, lparam); - // (fall through) + [[fallthrough]]; case WM_KEYDOWN: { if (m_owner.handle_key(wparam, lparam)) @@ -717,17 +962,33 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) // mouse click case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: { - debug_view_xy topleft = m_view->visible_position(); + debug_view_xy const topleft = m_view->visible_position(); + debug_view_xy const visiblesize = m_view->visible_size(); debug_view_xy newpos; - newpos.x = topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width(); - newpos.y = topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height(); - m_view->process_click(DCK_LEFT_CLICK, newpos); + newpos.x = std::max(std::min<int>(topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width(), topleft.x + visiblesize.x - 1), 0); + newpos.y = std::max(std::min<int>(topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height(), topleft.y + visiblesize.y - 1), 0); + m_view->process_click((message == WM_LBUTTONDOWN) ? DCK_LEFT_CLICK : DCK_MIDDLE_CLICK, newpos); SetFocus(m_wnd); break; } - // hscroll + // right click + case WM_RBUTTONDOWN: + if (m_view->cursor_supported()) + { + debug_view_xy const topleft = m_view->visible_position(); + debug_view_xy const visiblesize = m_view->visible_size(); + debug_view_xy newpos; + newpos.x = std::max(std::min<int>(topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width(), topleft.x + visiblesize.x - 1), 0); + newpos.y = std::max(std::min<int>(topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height(), topleft.y + visiblesize.y - 1), 0); + m_view->set_cursor_position(newpos); + m_view->set_cursor_visible(true); + } + return DefWindowProc(m_wnd, message, wparam, lparam); + + // horizontal scroll case WM_HSCROLL: { debug_view_xy topleft = m_view->visible_position(); @@ -737,7 +998,7 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) break; } - // vscroll + // vertical scroll case WM_VSCROLL: { debug_view_xy topleft = m_view->visible_position(); @@ -747,6 +1008,11 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) break; } + case WM_CONTEXTMENU: + if (!process_context_menu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) + return DefWindowProc(m_wnd, message, wparam, lparam); + break; + // everything else: defaults default: return DefWindowProc(m_wnd, message, wparam, lparam); @@ -758,7 +1024,7 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) void debugview_info::static_update(debug_view &view, void *osdprivate) { - debugview_info *const info = (debugview_info *)osdprivate; + auto *const info = (debugview_info *)osdprivate; assert(info->m_view == &view); info->update(); } @@ -774,7 +1040,7 @@ LRESULT CALLBACK debugview_info::static_view_proc(HWND wnd, UINT message, WPARAM return 0; } - debugview_info *const info = (debugview_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); + auto *const info = (debugview_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); if (info == nullptr) return DefWindowProc(wnd, message, wparam, lparam); @@ -810,3 +1076,5 @@ void debugview_info::register_window_class() s_window_class_registered = true; } } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/debugviewinfo.h b/src/osd/modules/debugger/win/debugviewinfo.h index 37d6930e445..a009c368441 100644 --- a/src/osd/modules/debugger/win/debugviewinfo.h +++ b/src/osd/modules/debugger/win/debugviewinfo.h @@ -5,9 +5,10 @@ // debugviewinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H +#define MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H -#ifndef __DEBUG_WIN_DEBUG_VIEW_INFO_H__ -#define __DEBUG_WIN_DEBUG_VIEW_INFO_H__ +#pragma once #include "debugwin.h" @@ -16,6 +17,8 @@ #include "debug/debugvw.h" +namespace osd::debugger::win { + class debugview_info : protected debugbase_info { public: @@ -41,6 +44,7 @@ public: bool cursor_supported() const { return m_view->cursor_supported(); } bool cursor_visible() const { return m_view->cursor_visible(); } + int source_index() const; char const *source_name() const; device_t *source_device() const; bool source_is_visible_cpu() const; @@ -50,13 +54,27 @@ public: HWND create_source_combobox(HWND parent, LONG_PTR userdata); + virtual void restore_configuration_from_node(util::xml::data_node const &node); + virtual void save_configuration_to_node(util::xml::data_node &node); + protected: + enum + { + ID_CONTEXT_COPY_VISIBLE = 1, + ID_CONTEXT_PASTE + }; + template <typename T> T *view() const { return downcast<T *>(m_view); } + virtual void add_items_to_context_menu(HMENU menu); + virtual void update_context_menu(HMENU menu); + virtual void handle_context_menu(unsigned command); + private: void draw_contents(HDC windc); void update(); uint32_t process_scroll(WORD type, HWND wnd); + bool process_context_menu(int x, int y); LRESULT view_proc(UINT message, WPARAM wparam, LPARAM lparam); static void static_update(debug_view &view, void *osdprivate); @@ -69,8 +87,11 @@ private: HWND m_wnd; HWND m_hscroll; HWND m_vscroll; + HMENU m_contextmenu; static bool s_window_class_registered; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H diff --git a/src/osd/modules/debugger/win/debugwin.h b/src/osd/modules/debugger/win/debugwin.h index ea78f126d5b..d8af29b795e 100644 --- a/src/osd/modules/debugger/win/debugwin.h +++ b/src/osd/modules/debugger/win/debugwin.h @@ -5,9 +5,12 @@ // debugwin.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGWIN_H +#define MAME_DEBUGGER_WIN_DEBUGWIN_H -#ifndef __DEBUG_WIN_DEBUG_WIN_H__ -#define __DEBUG_WIN_DEBUG_WIN_H__ +#pragma once + +#include "../xmlconfig.h" // standard windows headers #include <windows.h> @@ -19,6 +22,7 @@ #endif +namespace osd::debugger::win { class debugview_info; class debugwin_info; @@ -33,6 +37,12 @@ public: virtual running_machine &machine() const = 0; virtual ui_metrics &metrics() const = 0; + virtual void set_color_theme(int index) = 0; + virtual bool get_save_window_arrangement() const = 0; + virtual void set_save_window_arrangement(bool save) = 0; + virtual bool get_group_windows() const = 0; + virtual bool get_group_windows_setting() const = 0; + virtual void set_group_windows_setting(bool group) = 0; virtual bool const &waiting_for_debugger() const = 0; virtual bool seq_pressed() const = 0; @@ -45,6 +55,10 @@ public: virtual void show_all() = 0; virtual void hide_all() = 0; + + virtual void stagger_window(HWND window, int width, int height) = 0; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DEBUGWIN_H diff --git a/src/osd/modules/debugger/win/debugwininfo.cpp b/src/osd/modules/debugger/win/debugwininfo.cpp index ac60b980439..f27f7933f08 100644 --- a/src/osd/modules/debugger/win/debugwininfo.cpp +++ b/src/osd/modules/debugger/win/debugwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugwininfo.c - Win32 debug window handling +// debugwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,13 +12,21 @@ #include "debugviewinfo.h" #include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" + +#include "util/xmlfile.h" + #include "window.h" #include "winutf8.h" - #include "winutil.h" + #include "modules/lib/osdobj_common.h" +#include <cstring> + + +namespace osd::debugger::win { bool debugwin_info::s_window_class_registered = false; @@ -36,9 +44,16 @@ debugwin_info::debugwin_info(debugger_windows_interface &debugger, bool is_main_ { register_window_class(); - m_wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE, - 0, 0, 100, 100, std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), create_standard_menubar(), GetModuleHandleUni(), this); - if (m_wnd == nullptr) + m_wnd = win_create_window_ex_utf8( + DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE, + 0, 0, 100, 100, + debugger.get_group_windows() + ? dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window() + : nullptr, + create_standard_menubar(), + GetModuleHandleUni(), + this); + if (!m_wnd) return; RECT work_bounds; @@ -53,6 +68,12 @@ debugwin_info::~debugwin_info() } +void debugwin_info::redraw() +{ + RedrawWindow(m_wnd, nullptr, nullptr, RDW_INVALIDATE | RDW_ALLCHILDREN); +} + + void debugwin_info::destroy() { for (int curview = 0; curview < MAX_VIEWS; curview++) @@ -250,6 +271,89 @@ bool debugwin_info::handle_key(WPARAM wparam, LPARAM lparam) } +void debugwin_info::save_configuration(util::xml::data_node &parentnode) +{ + util::xml::data_node *const node = parentnode.add_child(NODE_WINDOW, nullptr); + if (node) + save_configuration_to_node(*node); +} + + +void debugwin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + // get current size to use for defaults + RECT bounds; + POINT origin; + origin.x = 0; + origin.y = 0; + if (!GetClientRect(window(), &bounds) && ClientToScreen(window(), &origin)) + return; + + // get saved size and adjust for window chrome + RECT desired; + desired.left = node.get_attribute_int(ATTR_WINDOW_POSITION_X, origin.x); + desired.top = node.get_attribute_int(ATTR_WINDOW_POSITION_Y, origin.y); + desired.right = desired.left + node.get_attribute_int(ATTR_WINDOW_WIDTH, bounds.right); + desired.bottom = desired.top + node.get_attribute_int(ATTR_WINDOW_HEIGHT, bounds.bottom); + // TODO: sanity checks... + if (!AdjustWindowRectEx(&desired, DEBUG_WINDOW_STYLE, GetMenu(window()) ? TRUE : FALSE, DEBUG_WINDOW_STYLE_EX)) + return; + + // actually move the window + MoveWindow( + window(), + desired.left, + desired.top, + desired.right - desired.left, + desired.bottom - desired.top, + TRUE); + + // restrict to one monitor and avoid toolbars + HMONITOR const nearest_monitor = MonitorFromWindow(window(), MONITOR_DEFAULTTONEAREST); + if (nearest_monitor) + { + MONITORINFO info; + std::memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + if (GetMonitorInfo(nearest_monitor, &info)) + { + if (desired.right > info.rcWork.right) + { + desired.left -= desired.right - info.rcWork.right; + desired.right = info.rcWork.right; + } + if (desired.bottom > info.rcWork.bottom) + { + desired.top -= desired.bottom - info.rcWork.bottom; + desired.bottom = info.rcWork.bottom; + } + if (desired.left < info.rcWork.left) + { + desired.right += info.rcWork.left - desired.left; + desired.left = info.rcWork.left; + } + if (desired.top < info.rcWork.top) + { + desired.bottom += info.rcWork.top - desired.top; + desired.top = info.rcWork.top; + } + desired.bottom = std::min(info.rcWork.bottom, desired.bottom); + desired.right = std::min(info.rcWork.right, desired.right); + MoveWindow( + window(), + desired.left, + desired.top, + desired.right - desired.left, + desired.bottom - desired.top, + TRUE); + } + } + + // sort out contents + recompute_children(); +} + + void debugwin_info::recompute_children() { if (m_views[0] != nullptr) @@ -299,39 +403,40 @@ bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_RUN_AND_HIDE: debugger().hide_all(); + [[fallthrough]]; case ID_RUN: - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); return true; case ID_NEXT_CPU: - machine().debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + machine().debugger().console().get_visible_cpu()->debug()->go_next_device(); return true; case ID_RUN_VBLANK: - machine().debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + machine().debugger().console().get_visible_cpu()->debug()->go_vblank(); return true; case ID_RUN_IRQ: - machine().debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + machine().debugger().console().get_visible_cpu()->debug()->go_interrupt(); return true; case ID_STEP: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine().debugger().console().get_visible_cpu()->debug()->single_step(); return true; case ID_STEP_OVER: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + machine().debugger().console().get_visible_cpu()->debug()->single_step_over(); return true; case ID_STEP_OUT: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + machine().debugger().console().get_visible_cpu()->debug()->single_step_out(); return true; case ID_REWIND_STEP: machine().rewind_step(); // clear all PC & memory tracks - for (device_t &device : device_iterator(machine().root_device())) + for (device_t &device : device_enumerator(machine().root_device())) { device.debug()->track_pc_data_clear(); device.debug()->track_mem_data_clear(); @@ -348,7 +453,7 @@ bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_SOFT_RESET: machine().schedule_soft_reset(); - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); return true; case ID_EXIT: @@ -390,6 +495,22 @@ void debugwin_info::draw_border(HDC dc, RECT &bounds) } +void debugwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + RECT bounds; + POINT origin; + origin.x = 0; + origin.y = 0; + if (GetClientRect(window(), &bounds) && ClientToScreen(window(), &origin)) + { + node.set_attribute_int(ATTR_WINDOW_POSITION_X, origin.x); + node.set_attribute_int(ATTR_WINDOW_POSITION_Y, origin.y); + node.set_attribute_int(ATTR_WINDOW_WIDTH, bounds.right); + node.set_attribute_int(ATTR_WINDOW_HEIGHT, bounds.bottom); + } +} + + void debugwin_info::draw_border(HDC dc, HWND child) { RECT bounds; @@ -437,11 +558,10 @@ LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam) // get min/max info: set the minimum window size case WM_GETMINMAXINFO: { - MINMAXINFO *minmax = (MINMAXINFO *)lparam; + auto *minmax = (MINMAXINFO *)lparam; minmax->ptMinTrackSize.x = m_minwidth; minmax->ptMinTrackSize.y = m_minheight; - minmax->ptMaxSize.x = minmax->ptMaxTrackSize.x = m_maxwidth; - minmax->ptMaxSize.y = minmax->ptMaxTrackSize.y = m_maxheight; + // Leave default ptMaxSize and ptMaxTrackSize so maximum size is not restricted break; } @@ -507,7 +627,7 @@ LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam) if (m_is_main_console) { debugger().hide_all(); - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); } else { @@ -575,14 +695,14 @@ LRESULT CALLBACK debugwin_info::static_window_proc(HWND wnd, UINT message, WPARA { // set the info pointer CREATESTRUCT const *const createinfo = (CREATESTRUCT *)lparam; - debugwin_info *const info = (debugwin_info *)createinfo->lpCreateParams; + auto *const info = (debugwin_info *)createinfo->lpCreateParams; SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams); if (info->m_handler) SetWindowLongPtr(wnd, GWLP_WNDPROC, (LONG_PTR)info->m_handler); return 0; } - debugwin_info *const info = (debugwin_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); + auto *const info = (debugwin_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); if (info == nullptr) return DefWindowProc(wnd, message, wparam, lparam); @@ -618,3 +738,5 @@ void debugwin_info::register_window_class() s_window_class_registered = true; } } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h index 2090985d3f9..cf3587253f6 100644 --- a/src/osd/modules/debugger/win/debugwininfo.h +++ b/src/osd/modules/debugger/win/debugwininfo.h @@ -5,20 +5,21 @@ // debugwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGWININFO_H +#define MAME_DEBUGGER_WIN_DEBUGWININFO_H -#ifndef __DEBUG_WIN_DEBUG_WIN_INFO_H__ -#define __DEBUG_WIN_DEBUG_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "debugbaseinfo.h" +namespace osd::debugger::win { class debugwin_info : protected debugbase_info { public: - debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler); virtual ~debugwin_info(); bool is_valid() const { return m_wnd != nullptr; } @@ -40,6 +41,7 @@ public: void show() const { smart_show_window(m_wnd, true); } void hide() const { smart_show_window(m_wnd, false); } void set_foreground() const { SetForegroundWindow(m_wnd); } + void redraw(); void destroy(); virtual bool set_default_focus(); @@ -49,6 +51,9 @@ public: virtual bool handle_key(WPARAM wparam, LPARAM lparam); + void save_configuration(util::xml::data_node &parentnode); + virtual void restore_configuration_from_node(util::xml::data_node const &node); + protected: static DWORD const DEBUG_WINDOW_STYLE = (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX); static DWORD const DEBUG_WINDOW_STYLE_EX = 0; @@ -75,13 +80,20 @@ protected: ID_SOFT_RESET, ID_EXIT, - ID_1_BYTE_CHUNKS, - ID_2_BYTE_CHUNKS, - ID_4_BYTE_CHUNKS, - ID_8_BYTE_CHUNKS, - ID_FLOATING_POINT_32BIT, - ID_FLOATING_POINT_64BIT, - ID_FLOATING_POINT_80BIT, + ID_1_BYTE_CHUNKS_HEX, + ID_2_BYTE_CHUNKS_HEX, + ID_4_BYTE_CHUNKS_HEX, + ID_8_BYTE_CHUNKS_HEX, + ID_1_BYTE_CHUNKS_OCT, + ID_2_BYTE_CHUNKS_OCT, + ID_4_BYTE_CHUNKS_OCT, + ID_8_BYTE_CHUNKS_OCT, + ID_FLOAT_32BIT, + ID_FLOAT_64BIT, + ID_FLOAT_80BIT, + ID_HEX_ADDRESSES, + ID_DEC_ADDRESSES, + ID_OCT_ADDRESSES, ID_LOGICAL_ADDRESSES, ID_PHYSICAL_ADDRESSES, ID_REVERSE_VIEW, @@ -97,12 +109,21 @@ protected: ID_SHOW_BREAKPOINTS, ID_SHOW_WATCHPOINTS, + ID_SHOW_REGISTERPOINTS, + ID_SHOW_EXCEPTIONPOINTS, ID_CLEAR_LOG, + ID_SAVE_WINDOWS, + ID_GROUP_WINDOWS, + ID_LIGHT_BACKGROUND, + ID_DARK_BACKGROUND, + ID_DEVICE_OPTIONS // always keep this at the end }; + debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler); + bool is_main_console() const { return m_is_main_console; } HWND window() const { return m_wnd; } uint32_t minwidth() const { return m_minwidth; } @@ -117,6 +138,8 @@ protected: void draw_border(HDC dc, RECT &bounds); void draw_border(HDC dc, HWND child); + virtual void save_configuration_to_node(util::xml::data_node &node); + std::unique_ptr<debugview_info> m_views[MAX_VIEWS]; private: @@ -133,12 +156,14 @@ private: HWND m_wnd; WNDPROC const m_handler; - uint32_t m_minwidth, m_maxwidth; - uint32_t m_minheight, m_maxheight; + uint32_t m_minwidth, m_maxwidth; + uint32_t m_minheight, m_maxheight; - uint16_t m_ignore_char_lparam; + uint16_t m_ignore_char_lparam; static bool s_window_class_registered; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DEBUGWININFO_H diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.cpp b/src/osd/modules/debugger/win/disasmbasewininfo.cpp index c466e059f23..48771c4f133 100644 --- a/src/osd/modules/debugger/win/disasmbasewininfo.cpp +++ b/src/osd/modules/debugger/win/disasmbasewininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// disasmbasewininfo.c - Win32 debug window handling +// disasmbasewininfo.cpp - Win32 debug window handling // //============================================================ @@ -15,18 +15,21 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" //#include "winutf8.h" +namespace osd::debugger::win { + disasmbasewin_info::disasmbasewin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) : editwin_info(debugger, is_main_console, title, handler) { if (!window()) return; - m_views[0].reset(global_alloc(disasmview_info(debugger, *this, window()))); - if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) + m_views[0].reset(new disasmview_info(debugger, *this, window())); + if (!m_views[0] || !m_views[0]->is_valid()) { m_views[0].reset(); return; @@ -105,7 +108,7 @@ void disasmbasewin_info::update_menu() { editwin_info::update_menu(); - disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get()); + auto *const dasmview = downcast<disasmview_info *>(m_views[0].get()); HMENU const menu = GetMenu(window()); bool const disasm_cursor_visible = dasmview->cursor_visible(); @@ -115,9 +118,9 @@ void disasmbasewin_info::update_menu() device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); - if (bp == nullptr) + if (!bp) { ModifyMenu(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9")); ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Disable breakpoint at cursor\tShift+F9")); @@ -130,7 +133,7 @@ void disasmbasewin_info::update_menu() else ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Enable breakpoint at cursor\tShift+F9")); } - bool const available = (bp != nullptr) && (!is_main_console() || dasmview->source_is_visible_cpu()); + bool const available = bp && (!is_main_console() || dasmview->source_is_visible_cpu()); EnableMenuItem(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND | (available ? MF_ENABLED : MF_GRAYED)); } else @@ -151,7 +154,7 @@ void disasmbasewin_info::update_menu() bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) { - disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get()); + auto *const dasmview = downcast<disasmview_info *>(m_views[0].get()); switch (HIWORD(wparam)) { @@ -166,14 +169,14 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); // if it doesn't exist, add a new one if (!is_main_console()) { if (bp == nullptr) { - int32_t bpindex = debug->breakpoint_set(address, nullptr, nullptr); + int32_t bpindex = debug->breakpoint_set(address); machine().debugger().console().printf("Breakpoint %X set\n", bpindex); } else @@ -192,7 +195,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) command = string_format("bpset 0x%X", address); else command = string_format("bpclear 0x%X", bp->index()); - machine().debugger().console().execute_command(command.c_str(), true); + machine().debugger().console().execute_command(command, true); } } return true; @@ -204,7 +207,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); // if it doesn't exist, add a new one if (bp != nullptr) @@ -220,7 +223,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) { std::string command; command = string_format(bp->enabled() ? "bpdisable 0x%X" : "bpenable 0x%X", (uint32_t)bp->index()); - machine().debugger().console().execute_command(command.c_str(), true); + machine().debugger().console().execute_command(command, true); } } } @@ -234,7 +237,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) { std::string command; command = string_format("go 0x%X", address); - machine().debugger().console().execute_command(command.c_str(), true); + machine().debugger().console().execute_command(command, true); } else { @@ -262,3 +265,19 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) } return editwin_info::handle_command(wparam, lparam); } + + +void disasmbasewin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + editwin_info::restore_configuration_from_node(node); + m_views[0]->restore_configuration_from_node(node); +} + + +void disasmbasewin_info::save_configuration_to_node(util::xml::data_node &node) +{ + editwin_info::save_configuration_to_node(node); + m_views[0]->save_configuration_to_node(node); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.h b/src/osd/modules/debugger/win/disasmbasewininfo.h index 26cd481b7f6..1ef8245b5a0 100644 --- a/src/osd/modules/debugger/win/disasmbasewininfo.h +++ b/src/osd/modules/debugger/win/disasmbasewininfo.h @@ -5,15 +5,18 @@ // disasmbasewininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DISASMBASEWININFO_H +#define MAME_DEBUGGER_WIN_DISASMBASEWININFO_H -#ifndef __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__ -#define __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "editwininfo.h" +namespace osd::debugger::win { + class disasmbasewin_info : public editwin_info { public: @@ -21,10 +24,14 @@ public: virtual ~disasmbasewin_info(); virtual bool handle_key(WPARAM wparam, LPARAM lparam) override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; protected: virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DISASMBASEWININFO_H diff --git a/src/osd/modules/debugger/win/disasmviewinfo.cpp b/src/osd/modules/debugger/win/disasmviewinfo.cpp index 8884bee5195..3cf9dbd70ff 100644 --- a/src/osd/modules/debugger/win/disasmviewinfo.cpp +++ b/src/osd/modules/debugger/win/disasmviewinfo.cpp @@ -2,13 +2,17 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// disasmviewinfo.c - Win32 debug window handling +// disasmviewinfo.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "disasmviewinfo.h" +#include "util/xmlfile.h" + + +namespace osd::debugger::win { disasmview_info::disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) : debugview_info(debugger, owner, parent, DVT_DISASSEMBLY) @@ -21,6 +25,12 @@ disasmview_info::~disasmview_info() } +char const *disasmview_info::expression() const +{ + return view<debug_view_disasm>()->expression(); +} + + disasm_right_column disasmview_info::right_column() const { return view<debug_view_disasm>()->right_column(); @@ -43,3 +53,23 @@ void disasmview_info::set_right_column(disasm_right_column contents) { view<debug_view_disasm>()->set_right_column(contents); } + + +void disasmview_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + debug_view_disasm &dasmview(*view<debug_view_disasm>()); + dasmview.set_right_column(disasm_right_column(node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()))); + + debugview_info::restore_configuration_from_node(node); +} + + +void disasmview_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugview_info::save_configuration_to_node(node); + + debug_view_disasm &dasmview(*view<debug_view_disasm>()); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/disasmviewinfo.h b/src/osd/modules/debugger/win/disasmviewinfo.h index d1e7090ef2f..809f92b0c14 100644 --- a/src/osd/modules/debugger/win/disasmviewinfo.h +++ b/src/osd/modules/debugger/win/disasmviewinfo.h @@ -5,9 +5,10 @@ // disasmviewinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DISASMVIEWINFO_H +#define MAME_DEBUGGER_WIN_DISASMVIEWINFO_H -#ifndef __DEBUG_WIN_DISASM_VIEW_INFO_H__ -#define __DEBUG_WIN_DISASM_VIEW_INFO_H__ +#pragma once #include "debugwin.h" @@ -16,17 +17,25 @@ #include "debug/dvdisasm.h" +namespace osd::debugger::win { + class disasmview_info : public debugview_info { public: disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent); virtual ~disasmview_info(); + char const *expression() const; disasm_right_column right_column() const; offs_t selected_address() const; void set_expression(const std::string &expression); void set_right_column(disasm_right_column contents); + + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DISASMVIEWINFO_H diff --git a/src/osd/modules/debugger/win/disasmwininfo.cpp b/src/osd/modules/debugger/win/disasmwininfo.cpp index b94eadbba03..6b38609ace8 100644 --- a/src/osd/modules/debugger/win/disasmwininfo.cpp +++ b/src/osd/modules/debugger/win/disasmwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// disasmwininfo.c - Win32 debug window handling +// disasmwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,9 +12,14 @@ #include "debugviewinfo.h" #include "disasmviewinfo.h" #include "uimetrics.h" + +#include "util/xmlfile.h" + #include "winutf8.h" +namespace osd::debugger::win { + disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) : disasmbasewin_info(debugger, false, "Disassembly", nullptr), m_combownd(nullptr) @@ -34,11 +39,11 @@ disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) : update_caption(); // recompute the children once to get the maxwidth - disasmwin_info::recompute_children(); + recompute_children(); // position the window and recompute children again - SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW); - disasmwin_info::recompute_children(); + debugger.stagger_window(window(), maxwidth(), 200); + recompute_children(); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -143,3 +148,34 @@ void disasmwin_info::update_caption() { win_set_window_text_utf8(window(), std::string("Disassembly: ").append(m_views[0]->source_name()).c_str()); } + + +void disasmwin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + m_views[0]->set_source_index(node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_views[0]->source_index())); + int const cursource = m_views[0]->source_index(); + if (0 <= cursource) + SendMessage(m_combownd, CB_SETCURSEL, cursource, 0); + update_caption(); + + util::xml::data_node const *const expr = node.get_child(NODE_WINDOW_EXPRESSION); + if (expr && expr->get_value()) + { + set_editwnd_text(expr->get_value()); + process_string(expr->get_value()); + } + + disasmbasewin_info::restore_configuration_from_node(node); +} + + +void disasmwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + disasmbasewin_info::save_configuration_to_node(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DISASSEMBLY_VIEWER); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_views[0]->source_index()); + node.add_child(NODE_WINDOW_EXPRESSION, downcast<disasmview_info *>(m_views[0].get())->expression()); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/disasmwininfo.h b/src/osd/modules/debugger/win/disasmwininfo.h index 34e8275f2f9..e5a5ceaaa0e 100644 --- a/src/osd/modules/debugger/win/disasmwininfo.h +++ b/src/osd/modules/debugger/win/disasmwininfo.h @@ -5,25 +5,31 @@ // disasmwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DISASMWININFO_H +#define MAME_DEBUGGER_WIN_DISASMWININFO_H -#ifndef __DEBUG_WIN_DISASM_WIN_INFO_H__ -#define __DEBUG_WIN_DISASM_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "disasmbasewininfo.h" +namespace osd::debugger::win { + class disasmwin_info : public disasmbasewin_info { public: disasmwin_info(debugger_windows_interface &debugger); virtual ~disasmwin_info(); + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + protected: virtual void recompute_children() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; virtual void draw_contents(HDC dc) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; private: virtual void process_string(const std::string &string) override; @@ -33,4 +39,6 @@ private: HWND m_combownd; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DISASMWININFO_H diff --git a/src/osd/modules/debugger/win/editwininfo.cpp b/src/osd/modules/debugger/win/editwininfo.cpp index af3dd1bf66e..c62d2b1f4f7 100644 --- a/src/osd/modules/debugger/win/editwininfo.cpp +++ b/src/osd/modules/debugger/win/editwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// editwininfo.c - Win32 debug window handling +// editwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,18 +12,22 @@ #include "debugviewinfo.h" #include "uimetrics.h" +#include "xmlfile.h" + #include "strconv.h" #include "winutil.h" +namespace osd::debugger::win { + namespace { constexpr DWORD EDIT_BOX_STYLE = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL; constexpr DWORD EDIT_BOX_STYLE_EX = 0; constexpr int MAX_EDIT_STRING = 256; -constexpr int HISTORY_LENGTH = 20; +constexpr int HISTORY_LENGTH = 100; } // anonymous namespace @@ -34,7 +38,7 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co m_edit_defstr(), m_original_editproc(nullptr), m_history(), - m_last_history(0) + m_last_history(-1) { if (window() == nullptr) return; @@ -105,6 +109,43 @@ void editwin_info::draw_contents(HDC dc) } +void editwin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + m_history.clear(); + util::xml::data_node const *const hist = node.get_child(NODE_WINDOW_HISTORY); + if (hist) + { + util::xml::data_node const *item = hist->get_child(NODE_HISTORY_ITEM); + while (item) + { + if (item->get_value() && *item->get_value()) + { + while (m_history.size() >= HISTORY_LENGTH) + m_history.pop_back(); + m_history.emplace_front(osd::text::to_tstring(item->get_value())); + } + item = item->get_next_sibling(NODE_HISTORY_ITEM); + } + } + m_last_history = -1; + + debugwin_info::restore_configuration_from_node(node); +} + + +void editwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugwin_info::save_configuration_to_node(node); + + util::xml::data_node *const hist = node.add_child(NODE_WINDOW_HISTORY, nullptr); + if (hist) + { + for (auto it = m_history.crbegin(); m_history.crend() != it; ++it) + hist->add_child(NODE_HISTORY_ITEM, osd::text::from_tstring(*it).c_str()); + } +} + + LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) { // handle a few messages @@ -114,7 +155,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) case WM_SYSKEYDOWN: if (wparam != VK_F10) return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam); - // (fall through) + [[fallthrough]]; case WM_KEYDOWN: switch (wparam) { @@ -185,7 +226,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) case 13: // carriage return { // fetch the text - SendMessage(m_editwnd, WM_GETTEXT, WPARAM(ARRAY_LENGTH(buffer)), LPARAM(buffer)); + SendMessage(m_editwnd, WM_GETTEXT, WPARAM(std::size(buffer)), LPARAM(buffer)); // add to the history if it's not a repeat of the last one if (buffer[0] && (m_history.empty() || _tcscmp(buffer, m_history[0].c_str()))) @@ -194,12 +235,12 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) m_history.pop_back(); m_history.emplace_front(buffer); } - m_last_history = m_history.size() - 1; + m_last_history = -1; // process { auto utf8_buffer = osd::text::from_tstring(buffer); - process_string(utf8_buffer.c_str()); + process_string(utf8_buffer); } } break; @@ -237,7 +278,9 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { - editwin_info *const info = (editwin_info *)uintptr_t(GetWindowLongPtr(wnd, GWLP_USERDATA)); + auto *const info = (editwin_info *)uintptr_t(GetWindowLongPtr(wnd, GWLP_USERDATA)); assert(info->m_editwnd == wnd); return info->edit_proc(message, wparam, lparam); } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/editwininfo.h b/src/osd/modules/debugger/win/editwininfo.h index 1aaee55f1e9..e2c0ce3c4b8 100644 --- a/src/osd/modules/debugger/win/editwininfo.h +++ b/src/osd/modules/debugger/win/editwininfo.h @@ -5,9 +5,10 @@ // editwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_EDITWININFO_H +#define MAME_DEBUGGER_WIN_EDITWININFO_H -#ifndef MAME_DEBUG_WIN_EDIT_WIN_INFO_H -#define MAME_DEBUG_WIN_EDIT_WIN_INFO_H +#pragma once #include "debugwin.h" @@ -17,6 +18,8 @@ #include <string> +namespace osd::debugger::win { + class editwin_info : public debugwin_info { public: @@ -27,6 +30,8 @@ public: virtual bool set_default_focus() override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + protected: constexpr static DWORD COMBO_BOX_STYLE = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; constexpr static DWORD COMBO_BOX_STYLE_EX = 0; @@ -38,6 +43,8 @@ protected: virtual void draw_contents(HDC dc) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; + private: typedef std::deque<std::basic_string<TCHAR> > history_deque; @@ -54,4 +61,6 @@ private: int m_last_history; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_EDITWININFO_H diff --git a/src/osd/modules/debugger/win/logviewinfo.cpp b/src/osd/modules/debugger/win/logviewinfo.cpp index affd4acd17a..c6bbdfacb88 100644 --- a/src/osd/modules/debugger/win/logviewinfo.cpp +++ b/src/osd/modules/debugger/win/logviewinfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Samuele Zannoli //============================================================ // -// logviewinfo.c - Win32 debug log window handling +// logviewinfo.cpp - Win32 debug log window handling // //============================================================ @@ -12,6 +12,8 @@ #include "debug/dvtext.h" +namespace osd::debugger::win { + logview_info::logview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) : debugview_info(debugger, owner, parent, DVT_LOG) { @@ -27,3 +29,5 @@ void logview_info::clear() { view<debug_view_log>()->clear(); } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/logviewinfo.h b/src/osd/modules/debugger/win/logviewinfo.h index da598038864..15de2a3a095 100644 --- a/src/osd/modules/debugger/win/logviewinfo.h +++ b/src/osd/modules/debugger/win/logviewinfo.h @@ -5,15 +5,18 @@ // logviewinfo.h - Win32 debug log window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_LOGVIEWINFO_H +#define MAME_DEBUGGER_WIN_LOGVIEWINFO_H -#ifndef __DEBUG_WIN_LOG_VIEW_INFO_H__ -#define __DEBUG_WIN_LOG_VIEW_INFO_H__ +#pragma once #include "debugwin.h" #include "debugviewinfo.h" +namespace osd::debugger::win { + class logview_info : public debugview_info { public: @@ -23,4 +26,6 @@ public: void clear(); }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_LOGVIEWINFO_H diff --git a/src/osd/modules/debugger/win/logwininfo.cpp b/src/osd/modules/debugger/win/logwininfo.cpp index 6d2cd59b554..40515906bb1 100644 --- a/src/osd/modules/debugger/win/logwininfo.cpp +++ b/src/osd/modules/debugger/win/logwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// logwininfo.c - Win32 debug window handling +// logwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,6 +12,10 @@ #include "debugviewinfo.h" #include "logviewinfo.h" +#include "util/xmlfile.h" + + +namespace osd::debugger::win { logwin_info::logwin_info(debugger_windows_interface &debugger) : debugwin_info(debugger, false, std::string("Errorlog: ").append(debugger.machine().system().type.fullname()).append(" [").append(debugger.machine().system().name).append("]").c_str(), nullptr) @@ -19,7 +23,7 @@ logwin_info::logwin_info(debugger_windows_interface &debugger) : if (!window()) return; - m_views[0].reset(global_alloc(logview_info(debugger, *this, window()))); + m_views[0].reset(new logview_info(debugger, *this, window())); if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) { m_views[0].reset(); @@ -41,11 +45,9 @@ logwin_info::logwin_info(debugger_windows_interface &debugger) : // clamp the min/max size set_maxwidth(bounds.right - bounds.left); - // position the window at the bottom-right - SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW); - - // recompute the children - debugwin_info::recompute_children(); + // position the window and recompute children + debugger.stagger_window(window(), bounds.right - bounds.left, bounds.bottom - bounds.top); + recompute_children(); } @@ -63,3 +65,12 @@ bool logwin_info::handle_command(WPARAM wparam, LPARAM lparam) } return debugwin_info::handle_command(wparam, lparam); } + + +void logwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugwin_info::save_configuration_to_node(node); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_ERROR_LOG_VIEWER); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/logwininfo.h b/src/osd/modules/debugger/win/logwininfo.h index a816b6f3da3..4e822f1b534 100644 --- a/src/osd/modules/debugger/win/logwininfo.h +++ b/src/osd/modules/debugger/win/logwininfo.h @@ -5,15 +5,18 @@ // logwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_LOGWININFO_H +#define MAME_DEBUGGER_WIN_LOGWININFO_H -#ifndef __DEBUG_WIN_LOG_WIN_INFO_H__ -#define __DEBUG_WIN_LOG_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "debugwininfo.h" +namespace osd::debugger::win { + class logwin_info : public debugwin_info { public: @@ -22,6 +25,9 @@ public: protected: virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_LOGWININFO_H diff --git a/src/osd/modules/debugger/win/memoryviewinfo.cpp b/src/osd/modules/debugger/win/memoryviewinfo.cpp index 423679f26a9..90e23a557a9 100644 --- a/src/osd/modules/debugger/win/memoryviewinfo.cpp +++ b/src/osd/modules/debugger/win/memoryviewinfo.cpp @@ -2,15 +2,19 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// memoryviewinfo.c - Win32 debug window handling +// memoryviewinfo.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "memoryviewinfo.h" -#include "debug/dvmemory.h" +#include "util/xmlfile.h" +#include "strconv.h" + + +namespace osd::debugger::win { memoryview_info::memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) : debugview_info(debugger, owner, parent, DVT_MEMORY) @@ -23,7 +27,13 @@ memoryview_info::~memoryview_info() } -uint8_t memoryview_info::data_format() const +char const *memoryview_info::expression() const +{ + return view<debug_view_memory>()->expression(); +} + + +debug_view_memory::data_format memoryview_info::data_format() const { return view<debug_view_memory>()->get_data_format(); } @@ -46,13 +56,18 @@ bool memoryview_info::physical() const return view<debug_view_memory>()->physical(); } +int memoryview_info::address_radix() const +{ + return view<debug_view_memory>()->address_radix(); +} + void memoryview_info::set_expression(const std::string &string) { view<debug_view_memory>()->set_expression(string); } -void memoryview_info::set_data_format(uint8_t dataformat) +void memoryview_info::set_data_format(debug_view_memory::data_format dataformat) { view<debug_view_memory>()->set_data_format(dataformat); } @@ -71,3 +86,123 @@ void memoryview_info::set_physical(bool physical) { view<debug_view_memory>()->set_physical(physical); } + +void memoryview_info::set_address_radix(int radix) +{ + view<debug_view_memory>()->set_address_radix(radix); +} + + +void memoryview_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + debug_view_memory &memview(*view<debug_view_memory>()); + memview.set_reverse(0 != node.get_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memview.reverse() ? 1 : 0)); + memview.set_physical(0 != node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memview.physical() ? 1 : 0)); + memview.set_address_radix(node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memview.address_radix())); + memview.set_data_format(debug_view_memory::data_format(node.get_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memview.get_data_format())))); + memview.set_chunks_per_row(node.get_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memview.chunks_per_row())); + + debugview_info::restore_configuration_from_node(node); +} + + +void memoryview_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugview_info::save_configuration_to_node(node); + + debug_view_memory &memview(*view<debug_view_memory>()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memview.reverse() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memview.physical() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memview.address_radix()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memview.get_data_format())); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memview.chunks_per_row()); +} + + +void memoryview_info::add_items_to_context_menu(HMENU menu) +{ + debugview_info::add_items_to_context_menu(menu); + + AppendMenu(menu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(menu, MF_GRAYED, ID_CONTEXT_LAST_PC, TEXT("Last PC")); +} + +void memoryview_info::update_context_menu(HMENU menu) +{ + debugview_info::update_context_menu(menu); + + bool enable = false; + debug_view_memory &memview(*view<debug_view_memory>()); + debug_view_memory_source const &source = downcast<debug_view_memory_source const &>(*memview.source()); + address_space *const space = source.space(); + if (space) + { + if (memview.cursor_visible()) + { + // get the last known PC to write to this memory location + debug_view_xy const pos = memview.cursor_position(); + offs_t const address = space->byte_to_address(memview.addressAtCursorPosition(pos)); + offs_t a = address & space->logaddrmask(); + address_space *tspace; + if (!space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, a, tspace)) + { + m_lastpc = "Bad address"; + } + else + { + uint64_t memval = tspace->unmap(); + auto dis = tspace->device().machine().disable_side_effects(); + switch (tspace->data_width()) + { + case 8: memval = tspace->read_byte(a); break; + case 16: memval = tspace->read_word_unaligned(a); break; + case 32: memval = tspace->read_dword_unaligned(a); break; + case 64: memval = tspace->read_qword_unaligned(a); break; + } + + offs_t const pc = source.device()->debug()->track_mem_pc_from_space_address_data( + tspace->spacenum(), + address, + memval); + if (pc != offs_t(-1)) + { + if (tspace->is_octal()) + m_lastpc = util::string_format("Address %o written at PC=%o", address, pc); + else + m_lastpc = util::string_format("Address %x written at PC=%x", address, pc); + enable = true; + } + else + { + m_lastpc = "Unknown PC"; + } + } + } + else + { + m_lastpc = "No address"; + } + } + else + { + m_lastpc = "Not an address space"; + } + ModifyMenuW(menu, ID_CONTEXT_LAST_PC, MF_BYCOMMAND, ID_CONTEXT_LAST_PC, osd::text::to_wstring(m_lastpc).c_str()); + EnableMenuItem(menu, ID_CONTEXT_LAST_PC, MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED)); +} + +void memoryview_info::handle_context_menu(unsigned command) +{ + switch (command) + { + case ID_CONTEXT_LAST_PC: + // TODO: copy to clipboard + return; + + default: + debugview_info::handle_context_menu(command); + }; + +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/memoryviewinfo.h b/src/osd/modules/debugger/win/memoryviewinfo.h index 2ab810654f3..514c6c13ec6 100644 --- a/src/osd/modules/debugger/win/memoryviewinfo.h +++ b/src/osd/modules/debugger/win/memoryviewinfo.h @@ -5,14 +5,20 @@ // memoryviewinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H +#define MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H -#ifndef __DEBUG_WIN_MEMORY_VIEW_INFO_H__ -#define __DEBUG_WIN_MEMORY_VIEW_INFO_H__ +#pragma once #include "debugwin.h" - #include "debugviewinfo.h" +#include "debug/dvmemory.h" + +#include <string> + + +namespace osd::debugger::win { class memoryview_info : public debugview_info { @@ -20,16 +26,37 @@ public: memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent); virtual ~memoryview_info(); - uint8_t data_format() const; + char const *expression() const; + debug_view_memory::data_format data_format() const; uint32_t chunks_per_row() const; bool reverse() const; bool physical() const; + int address_radix() const; void set_expression(const std::string &string); - void set_data_format(uint8_t dataformat); + void set_data_format(debug_view_memory::data_format dataformat); void set_chunks_per_row(uint32_t rowchunks); void set_reverse(bool reverse); void set_physical(bool physical); + void set_address_radix(int radix); + + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; + +protected: + enum + { + ID_CONTEXT_LAST_PC = 101 + }; + + virtual void add_items_to_context_menu(HMENU menu) override; + virtual void update_context_menu(HMENU menu) override; + virtual void handle_context_menu(unsigned command) override; + +private: + std::string m_lastpc; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H diff --git a/src/osd/modules/debugger/win/memorywininfo.cpp b/src/osd/modules/debugger/win/memorywininfo.cpp index 6f461295ec2..92078854e2e 100644 --- a/src/osd/modules/debugger/win/memorywininfo.cpp +++ b/src/osd/modules/debugger/win/memorywininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// memorywininfo.c - Win32 debug window handling +// memorywininfo.cpp - Win32 debug window handling // //============================================================ @@ -13,9 +13,13 @@ #include "memoryviewinfo.h" #include "uimetrics.h" +#include "util/xmlfile.h" + #include "winutf8.h" +namespace osd::debugger::win { + memorywin_info::memorywin_info(debugger_windows_interface &debugger) : editwin_info(debugger, false, "Memory", nullptr), m_combownd(nullptr) @@ -23,7 +27,7 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : if (!window()) return; - m_views[0].reset(global_alloc(memoryview_info(debugger, *this, window()))); + m_views[0].reset(new memoryview_info(debugger, *this, window())); if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) { m_views[0].reset(); @@ -32,21 +36,29 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : // create the options menu HMENU const optionsmenu = CreatePopupMenu(); - AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS, TEXT("1-byte chunks\tCtrl+1")); - AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS, TEXT("2-byte chunks\tCtrl+2")); - AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS, TEXT("4-byte chunks\tCtrl+4")); - AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS, TEXT("8-byte chunks\tCtrl+8")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_32BIT, TEXT("32 bit floating point\tCtrl+9")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_64BIT, TEXT("64 bit floating point")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_80BIT, TEXT("80 bit floating point")); + AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS_HEX, TEXT("1-byte Chunks (Hex)\tCtrl+1")); + AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS_HEX, TEXT("2-byte Chunks (Hex)\tCtrl+2")); + AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS_HEX, TEXT("4-byte Chunks (Hex)\tCtrl+4")); + AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS_HEX, TEXT("8-byte Chunks (Hex)\tCtrl+8")); + AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS_OCT, TEXT("1-byte Chunks (Octal)\tCtrl+3")); + AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS_OCT, TEXT("2-byte Chunks (Octal)\tCtrl+5")); + AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS_OCT, TEXT("4-byte Chunks (Octal)\tCtrl+7")); + AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS_OCT, TEXT("8-byte Chunks (Octal)\tCtrl+9")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_32BIT, TEXT("32-bit Floating Point\tCtrl+Shift+F")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_64BIT, TEXT("64-bit Floating Point\tCtrl+Shift+D")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_80BIT, TEXT("80-bit Floating Point\tCtrl+Shift+E")); + AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(optionsmenu, MF_ENABLED, ID_HEX_ADDRESSES, TEXT("Hexadecimal Addresses\tCtrl+Shift+H")); + AppendMenu(optionsmenu, MF_ENABLED, ID_DEC_ADDRESSES, TEXT("Decimal Addresses")); + AppendMenu(optionsmenu, MF_ENABLED, ID_OCT_ADDRESSES, TEXT("Octal Addresses\tCtrl+Shift+O")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); AppendMenu(optionsmenu, MF_ENABLED, ID_LOGICAL_ADDRESSES, TEXT("Logical Addresses\tCtrl+L")); AppendMenu(optionsmenu, MF_ENABLED, ID_PHYSICAL_ADDRESSES, TEXT("Physical Addresses\tCtrl+Y")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); AppendMenu(optionsmenu, MF_ENABLED, ID_REVERSE_VIEW, TEXT("Reverse View\tCtrl+R")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); - AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase bytes per line\tCtrl+P")); - AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease bytes per line\tCtrl+O")); + AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase Bytes Per Line\tCtrl+P")); + AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease Bytes Per Line\tCtrl+O")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // set up the view to track the initial expression @@ -63,11 +75,11 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : update_caption(); // recompute the children once to get the maxwidth - memorywin_info::recompute_children(); + recompute_children(); // position the window and recompute children again - SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW); - memorywin_info::recompute_children(); + debugger.stagger_window(window(), maxwidth(), 200); + recompute_children(); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -83,47 +95,87 @@ bool memorywin_info::handle_key(WPARAM wparam, LPARAM lparam) { if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { - switch (wparam) + if (GetAsyncKeyState(VK_SHIFT)) { - case '1': - SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS, 0); - return true; + switch (wparam) + { + case 'F': + SendMessage(window(), WM_COMMAND, ID_FLOAT_32BIT, 0); + return true; - case '2': - SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS, 0); - return true; + case 'D': + SendMessage(window(), WM_COMMAND, ID_FLOAT_64BIT, 0); + return true; - case '4': - SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS, 0); - return true; + case 'E': + SendMessage(window(), WM_COMMAND, ID_FLOAT_80BIT, 0); + return true; - case '8': - SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS, 0); - return true; + case 'H': + SendMessage(window(), WM_COMMAND, ID_HEX_ADDRESSES, 0); + return true; - case '9': - SendMessage(window(), WM_COMMAND, ID_FLOATING_POINT_32BIT, 0); - return true; + case 'O': + SendMessage(window(), WM_COMMAND, ID_OCT_ADDRESSES, 0); + return true; + } + } + else + { + switch (wparam) + { + case '1': + SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS_HEX, 0); + return true; - case 'L': - SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0); - return true; + case '2': + SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS_HEX, 0); + return true; - case 'Y': - SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0); - return true; + case '4': + SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS_HEX, 0); + return true; - case 'R': - SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0); - return true; + case '8': + SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS_HEX, 0); + return true; - case 'P': - SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0); - return true; + case '3': + SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS_OCT, 0); + return true; - case 'O': - SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0); - return true; + case '5': + SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS_OCT, 0); + return true; + + case '7': + SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS_OCT, 0); + return true; + + case '9': + SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS_OCT, 0); + return true; + + case 'L': + SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0); + return true; + + case 'Y': + SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0); + return true; + + case 'R': + SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0); + return true; + + case 'P': + SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0); + return true; + + case 'O': + SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0); + return true; + } } } return editwin_info::handle_key(wparam, lparam); @@ -178,25 +230,37 @@ void memorywin_info::update_menu() { editwin_info::update_menu(); - memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get()); + auto *const memview = downcast<memoryview_info *>(m_views[0].get()); HMENU const menu = GetMenu(window()); - CheckMenuItem(menu, ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 1 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 2 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 4 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 8 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_32BIT, MF_BYCOMMAND | (memview->data_format() == 9 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_64BIT, MF_BYCOMMAND | (memview->data_format() == 10 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_80BIT, MF_BYCOMMAND | (memview->data_format() == 11 ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(menu, ID_1_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_8BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_2_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_16BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_4_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_8_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_1_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_8BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_2_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_16BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_4_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_8_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_32BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_64BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_80BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_80BIT) ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(menu, ID_HEX_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 16) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_DEC_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 10) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_OCT_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 8) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED)); CheckMenuItem(menu, ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED)); + EnableMenuItem(menu, ID_DECREASE_MEM_WIDTH, MF_BYCOMMAND | ((memview->chunks_per_row() > 1) ? MF_ENABLED : MF_GRAYED)); } bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam) { - memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get()); + auto *const memview = downcast<memoryview_info *>(m_views[0].get()); switch (HIWORD(wparam)) { // combo box selection changed @@ -219,32 +283,60 @@ bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam) case 0: switch (LOWORD(wparam)) { - case ID_1_BYTE_CHUNKS: - memview->set_data_format(1); + case ID_1_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_8BIT); + return true; + + case ID_2_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_16BIT); + return true; + + case ID_4_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_32BIT); + return true; + + case ID_8_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_64BIT); return true; - case ID_2_BYTE_CHUNKS: - memview->set_data_format(2); + case ID_1_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_8BIT); return true; - case ID_4_BYTE_CHUNKS: - memview->set_data_format(4); + case ID_2_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_16BIT); return true; - case ID_8_BYTE_CHUNKS: - memview->set_data_format(8); + case ID_4_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_32BIT); return true; - case ID_FLOATING_POINT_32BIT: - memview->set_data_format(9); + case ID_8_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_64BIT); return true; - case ID_FLOATING_POINT_64BIT: - memview->set_data_format(10); + case ID_FLOAT_32BIT: + memview->set_data_format(debug_view_memory::data_format::FLOAT_32BIT); return true; - case ID_FLOATING_POINT_80BIT: - memview->set_data_format(11); + case ID_FLOAT_64BIT: + memview->set_data_format(debug_view_memory::data_format::FLOAT_64BIT); + return true; + + case ID_FLOAT_80BIT: + memview->set_data_format(debug_view_memory::data_format::FLOAT_80BIT); + return true; + + case ID_HEX_ADDRESSES: + memview->set_address_radix(16); + return true; + + case ID_DEC_ADDRESSES: + memview->set_address_radix(10); + return true; + + case ID_OCT_ADDRESSES: + memview->set_address_radix(8); return true; case ID_LOGICAL_ADDRESSES: @@ -300,3 +392,37 @@ void memorywin_info::update_caption() { win_set_window_text_utf8(window(), std::string("Memory: ").append(m_views[0]->source_name()).c_str()); } + + +void memorywin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + m_views[0]->set_source_index(node.get_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_views[0]->source_index())); + int const cursource = m_views[0]->source_index(); + if (0 <= cursource) + SendMessage(m_combownd, CB_SETCURSEL, cursource, 0); + update_caption(); + + util::xml::data_node const *const expr = node.get_child(NODE_WINDOW_EXPRESSION); + if (expr && expr->get_value()) + { + set_editwnd_text(expr->get_value()); + process_string(expr->get_value()); + } + + editwin_info::restore_configuration_from_node(node); + + m_views[0]->restore_configuration_from_node(node); +} + + +void memorywin_info::save_configuration_to_node(util::xml::data_node &node) +{ + editwin_info::save_configuration_to_node(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_MEMORY_VIEWER); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_views[0]->source_index()); + node.add_child(NODE_WINDOW_EXPRESSION, downcast<memoryview_info *>(m_views[0].get())->expression()); + m_views[0]->save_configuration_to_node(node); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/memorywininfo.h b/src/osd/modules/debugger/win/memorywininfo.h index 501d7acc76f..a0a4072be0f 100644 --- a/src/osd/modules/debugger/win/memorywininfo.h +++ b/src/osd/modules/debugger/win/memorywininfo.h @@ -5,15 +5,18 @@ // memorywininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_MEMORYWININFO_H +#define MAME_DEBUGGER_WIN_MEMORYWININFO_H -#ifndef __DEBUG_WIN_MEMORY_WIN_INFO_H__ -#define __DEBUG_WIN_MEMORY_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "editwininfo.h" +namespace osd::debugger::win { + class memorywin_info : public editwin_info { public: @@ -21,12 +24,14 @@ public: virtual ~memorywin_info(); virtual bool handle_key(WPARAM wparam, LPARAM lparam) override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; protected: virtual void recompute_children() override; virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; virtual void draw_contents(HDC dc) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; private: virtual void process_string(const std::string &string) override; @@ -36,4 +41,6 @@ private: HWND m_combownd; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_MEMORYWININFO_H diff --git a/src/osd/modules/debugger/win/pointswininfo.cpp b/src/osd/modules/debugger/win/pointswininfo.cpp index 24a8f865e6f..70ec6606280 100644 --- a/src/osd/modules/debugger/win/pointswininfo.cpp +++ b/src/osd/modules/debugger/win/pointswininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// pointswininfo.c - Win32 debug window handling +// pointswininfo.cpp - Win32 debug window handling // //============================================================ @@ -11,16 +11,20 @@ #include "debugviewinfo.h" +#include "util/xmlfile.h" + #include "winutf8.h" +namespace osd::debugger::win { + pointswin_info::pointswin_info(debugger_windows_interface &debugger) : debugwin_info(debugger, false, std::string("All Breakpoints").c_str(), nullptr) { if (!window()) return; - m_views[0].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_BREAK_POINTS))); + m_views[0].reset(new debugview_info(debugger, *this, window(), DVT_BREAK_POINTS)); if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) { m_views[0].reset(); @@ -31,6 +35,8 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) : HMENU const optionsmenu = CreatePopupMenu(); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_BREAKPOINTS, TEXT("Breakpoints\tCtrl+1")); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_WATCHPOINTS, TEXT("Watchpoints\tCtrl+2")); + AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_REGISTERPOINTS, TEXT("Registerpoints\tCtrl+3")); + AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_EXCEPTIONPOINTS, TEXT("Exceptionpoints\tCtrl+4")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // compute a client rect @@ -43,11 +49,9 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) : // clamp the min/max size set_maxwidth(bounds.right - bounds.left); - // position the window at the bottom-right - SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW); - - // recompute the children - debugwin_info::recompute_children(); + // position the window and recompute children + debugger.stagger_window(window(), bounds.right - bounds.left, bounds.bottom - bounds.top); + recompute_children(); } @@ -69,6 +73,14 @@ bool pointswin_info::handle_key(WPARAM wparam, LPARAM lparam) case '2': SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0); return true; + + case '3': + SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0); + return true; + + case '4': + SendMessage(window(), WM_COMMAND, ID_SHOW_EXCEPTIONPOINTS, 0); + return true; } } @@ -83,6 +95,8 @@ void pointswin_info::update_menu() HMENU const menu = GetMenu(window()); CheckMenuItem(menu, ID_SHOW_BREAKPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_BREAK_POINTS ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, ID_SHOW_WATCHPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_WATCH_POINTS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_SHOW_REGISTERPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_REGISTER_POINTS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_SHOW_EXCEPTIONPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_EXCEPTION_POINTS ? MF_CHECKED : MF_UNCHECKED)); } @@ -96,7 +110,7 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam) { case ID_SHOW_BREAKPOINTS: m_views[0].reset(); - m_views[0].reset(global_alloc(debugview_info(debugger(), *this, window(), DVT_BREAK_POINTS))); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_BREAK_POINTS)); if (!m_views[0]->is_valid()) m_views[0].reset(); win_set_window_text_utf8(window(), "All Breakpoints"); @@ -105,14 +119,81 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_SHOW_WATCHPOINTS: m_views[0].reset(); - m_views[0].reset(global_alloc(debugview_info(debugger(), *this, window(), DVT_WATCH_POINTS))); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_WATCH_POINTS)); if (!m_views[0]->is_valid()) m_views[0].reset(); win_set_window_text_utf8(window(), "All Watchpoints"); recompute_children(); return true; + + case ID_SHOW_REGISTERPOINTS: + m_views[0].reset(); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_REGISTER_POINTS)); + if (!m_views[0]->is_valid()) + m_views[0].reset(); + win_set_window_text_utf8(window(), "All Registerpoints"); + recompute_children(); + return true; + + case ID_SHOW_EXCEPTIONPOINTS: + m_views[0].reset(); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_EXCEPTION_POINTS)); + if (!m_views[0]->is_valid()) + m_views[0].reset(); + win_set_window_text_utf8(window(), "All Exceptionpoints"); + recompute_children(); + return true; } break; } return debugwin_info::handle_command(wparam, lparam); } + + +void pointswin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + switch (node.get_attribute_int(ATTR_WINDOW_POINTS_TYPE, -1)) + { + case 0: + SendMessage(window(), WM_COMMAND, ID_SHOW_BREAKPOINTS, 0); + break; + case 1: + SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0); + break; + case 2: + SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0); + break; + case 3: + SendMessage(window(), WM_COMMAND, ID_SHOW_EXCEPTIONPOINTS, 0); + break; + } + + debugwin_info::restore_configuration_from_node(node); +} + + +void pointswin_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugwin_info::save_configuration_to_node(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_POINTS_VIEWER); + switch (m_views[0]->type()) + { + case DVT_BREAK_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 0); + break; + case DVT_WATCH_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 1); + break; + case DVT_REGISTER_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2); + break; + case DVT_EXCEPTION_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 3); + break; + default: + break; + } +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/pointswininfo.h b/src/osd/modules/debugger/win/pointswininfo.h index 8ba1b31fc00..506c68519e8 100644 --- a/src/osd/modules/debugger/win/pointswininfo.h +++ b/src/osd/modules/debugger/win/pointswininfo.h @@ -5,15 +5,18 @@ // pointswininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_POINTSWININFO_H +#define MAME_DEBUGGER_WIN_POINTSWININFO_H -#ifndef __DEBUG_WIN_POINTS_WIN_INFO_H__ -#define __DEBUG_WIN_POINTS_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "debugwininfo.h" +namespace osd::debugger::win { + class pointswin_info : public debugwin_info { public: @@ -21,10 +24,14 @@ public: virtual ~pointswin_info(); virtual bool handle_key(WPARAM wparam, LPARAM lparam) override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; protected: virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_POINTSWININFO_H diff --git a/src/osd/modules/debugger/win/uimetrics.cpp b/src/osd/modules/debugger/win/uimetrics.cpp index 67eb045c619..e3d21cda06d 100644 --- a/src/osd/modules/debugger/win/uimetrics.cpp +++ b/src/osd/modules/debugger/win/uimetrics.cpp @@ -2,15 +2,48 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// uimetrics.c - Win32 debug window handling +// uimetrics.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "uimetrics.h" +#include "debug/debugvw.h" + #include "strconv.h" +#include <algorithm> + + +namespace osd::debugger::win { + +COLORREF const ui_metrics::s_themes[][COLOR_COUNT] = { + { + RGB(0x00, 0x00, 0x00), // foreground normal + RGB(0xff, 0x00, 0x00), // foreground changed + RGB(0x00, 0x00, 0xff), // foreground invalid + RGB(0x00, 0x80, 0x00), // foreground comment + RGB(0xff, 0xff, 0xff), // background normal + RGB(0xff, 0x80, 0x80), // background selected + RGB(0xe0, 0xe0, 0xe0), // background ancillary + RGB(0xff, 0xff, 0x00), // background current + RGB(0xff, 0xc0, 0x80), // background current selected + RGB(0xc0, 0xe0, 0xff) // background visited + }, + { + RGB(0xe0, 0xe0, 0xe0), // foreground normal + RGB(0xff, 0x60, 0xff), // foreground changed + RGB(0x00, 0xc0, 0xe0), // foreground invalid + RGB(0x00, 0xe0, 0x00), // foreground comment + RGB(0x00, 0x00, 0x00), // background normal + RGB(0xe0, 0x00, 0x00), // background selected + RGB(0x40, 0x40, 0x40), // background ancillary + RGB(0x00, 0x00, 0xc0), // background current + RGB(0xb0, 0x60, 0x00), // background current selected + RGB(0x00, 0x40, 0x80) // background visited + } }; + ui_metrics::ui_metrics(osd_options const &options) : m_debug_font(nullptr), @@ -22,7 +55,7 @@ ui_metrics::ui_metrics(osd_options const &options) : { // create a temporary DC HDC const temp_dc = GetDC(nullptr); - if (temp_dc != nullptr) + if (temp_dc) { float const size = options.debugger_font_size(); char const *const face = options.debugger_font(); @@ -47,6 +80,9 @@ ui_metrics::ui_metrics(osd_options const &options) : SelectObject(temp_dc, old_font); ReleaseDC(nullptr, temp_dc); } + + // set default color theme + set_color_theme(THEME_LIGHT_BACKGROUND); } @@ -69,3 +105,56 @@ ui_metrics::~ui_metrics() if (m_debug_font) DeleteObject(m_debug_font); } + + +std::pair<COLORREF, COLORREF> ui_metrics::view_colors(u8 attrib) const +{ + std::pair<COLORREF, COLORREF> result; + + if (attrib & DCA_SELECTED) + result.second = (attrib & DCA_CURRENT) ? m_colors[COLOR_BG_CURRENT_SELECTED] : m_colors[COLOR_BG_SELECTED]; + else if (attrib & DCA_CURRENT) + result.second = m_colors[COLOR_BG_CURRENT]; + else if (attrib & DCA_ANCILLARY) + result.second = m_colors[COLOR_BG_ANCILLARY]; + else if (attrib & DCA_VISITED) + result.second = m_colors[COLOR_BG_VISITED]; + else + result.second = m_colors[COLOR_BG_NORMAL]; + + if (DCA_COMMENT & attrib) + { + result.first = m_colors[COLOR_FG_COMMENT]; + } + else + { + if (attrib & DCA_INVALID) + result.first = m_colors[COLOR_FG_INVALID]; + else if (attrib & DCA_CHANGED) + result.first = m_colors[COLOR_FG_CHANGED]; + else + result.first = m_colors[COLOR_FG_NORMAL]; + + if (attrib & DCA_DISABLED) + { + result.first = RGB( + (GetRValue(result.first) + GetRValue(result.second) + 1) >> 1, + (GetGValue(result.first) + GetGValue(result.second) + 1) >> 1, + (GetBValue(result.first) + GetBValue(result.second) + 1) >> 1); + } + } + + return result; +} + + +void ui_metrics::set_color_theme(int index) +{ + if ((0 <= index) && (std::size(s_themes) > index)) + { + std::copy(std::begin(s_themes[index]), std::end(s_themes[index]), m_colors); + m_color_theme = index; + } +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/uimetrics.h b/src/osd/modules/debugger/win/uimetrics.h index a360d66924e..e45ae810fa6 100644 --- a/src/osd/modules/debugger/win/uimetrics.h +++ b/src/osd/modules/debugger/win/uimetrics.h @@ -5,19 +5,29 @@ // uimetrics.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_UIMETRICS_H +#define MAME_DEBUGGER_WIN_UIMETRICS_H -#ifndef __DEBUG_WIN_UI_METRICS_H__ -#define __DEBUG_WIN_UI_METRICS_H__ +#pragma once #include "debugwin.h" - #include "modules/lib/osdobj_common.h" +#include <utility> + + +namespace osd::debugger::win { class ui_metrics { public: + enum + { + THEME_LIGHT_BACKGROUND, + THEME_DARK_BACKGROUND + }; + ui_metrics(osd_options const &options); ui_metrics(ui_metrics const &that); ~ui_metrics(); @@ -30,7 +40,28 @@ public: uint32_t hscroll_height() const { return m_hscroll_height; } uint32_t vscroll_width() const { return m_vscroll_width; } + std::pair<COLORREF, COLORREF> view_colors(u8 attrib) const; + int get_color_theme() const { return m_color_theme; } + void set_color_theme(int index); + private: + enum + { + COLOR_FG_NORMAL, + COLOR_FG_CHANGED, + COLOR_FG_INVALID, + COLOR_FG_COMMENT, + + COLOR_BG_NORMAL, + COLOR_BG_SELECTED, + COLOR_BG_ANCILLARY, + COLOR_BG_CURRENT, + COLOR_BG_CURRENT_SELECTED, + COLOR_BG_VISITED, + + COLOR_COUNT + }; + HFONT m_debug_font; uint32_t m_debug_font_height; uint32_t m_debug_font_width; @@ -38,6 +69,13 @@ private: uint32_t const m_hscroll_height; uint32_t const m_vscroll_width; + + COLORREF m_colors[COLOR_COUNT]; + int m_color_theme; + + static COLORREF const s_themes[][COLOR_COUNT]; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_UIMETRICS_H diff --git a/src/osd/modules/debugger/xmlconfig.cpp b/src/osd/modules/debugger/xmlconfig.cpp new file mode 100644 index 00000000000..977e7b55e70 --- /dev/null +++ b/src/osd/modules/debugger/xmlconfig.cpp @@ -0,0 +1,54 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb + +#include "xmlconfig.h" + +namespace osd::debugger { + +char const *const NODE_WINDOW = "window"; +char const *const NODE_COLORS = "colors"; + +char const *const NODE_WINDOW_SPLITS = "splits"; +char const *const NODE_WINDOW_SELECTION = "selection"; +char const *const NODE_WINDOW_SCROLL = "scroll"; +char const *const NODE_WINDOW_EXPRESSION = "expression"; +char const *const NODE_WINDOW_HISTORY = "history"; + +char const *const NODE_HISTORY_ITEM = "item"; + +char const *const ATTR_DEBUGGER_SAVE_WINDOWS = "savewindows"; +char const *const ATTR_DEBUGGER_GROUP_WINDOWS = "groupwindows"; + +char const *const ATTR_WINDOW_TYPE = "type"; +char const *const ATTR_WINDOW_POSITION_X = "position_x"; +char const *const ATTR_WINDOW_POSITION_Y = "position_y"; +char const *const ATTR_WINDOW_WIDTH = "size_x"; +char const *const ATTR_WINDOW_HEIGHT = "size_y"; + +char const *const ATTR_WINDOW_MEMORY_REGION = "memoryregion"; +char const *const ATTR_WINDOW_MEMORY_REVERSE_COLUMNS = "reverse"; +char const *const ATTR_WINDOW_MEMORY_ADDRESS_MODE = "addressmode"; +char const *const ATTR_WINDOW_MEMORY_ADDRESS_RADIX = "addressradix"; +char const *const ATTR_WINDOW_MEMORY_DATA_FORMAT = "dataformat"; +char const *const ATTR_WINDOW_MEMORY_ROW_CHUNKS = "rowchunks"; + +char const *const ATTR_WINDOW_DISASSEMBLY_CPU = "cpu"; +char const *const ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN = "rightbar"; + +char const *const ATTR_WINDOW_POINTS_TYPE = "bwtype"; + +char const *const ATTR_WINDOW_DEVICE_TAG = "device-tag"; + +char const *const ATTR_COLORS_THEME = "theme"; + +char const *const ATTR_SPLITS_CONSOLE_STATE = "state"; +char const *const ATTR_SPLITS_CONSOLE_DISASSEMBLY = "disassembly"; + +char const *const ATTR_SELECTION_CURSOR_VISIBLE = "visible"; +char const *const ATTR_SELECTION_CURSOR_X = "start_x"; +char const *const ATTR_SELECTION_CURSOR_Y = "start_y"; + +char const *const ATTR_SCROLL_ORIGIN_X = "position_x"; +char const *const ATTR_SCROLL_ORIGIN_Y = "position_y"; + +} // namespace osd::debugger diff --git a/src/osd/modules/debugger/xmlconfig.h b/src/osd/modules/debugger/xmlconfig.h new file mode 100644 index 00000000000..6ae476cdec7 --- /dev/null +++ b/src/osd/modules/debugger/xmlconfig.h @@ -0,0 +1,72 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#ifndef MAME_OSD_DEBUGGER_XMLCONFIG_H +#define MAME_OSD_DEBUGGER_XMLCONFIG_H + +#pragma once + +namespace osd::debugger { + +// Qt debugger started using these numeric types - they should be switched to mnemonics at some point +enum +{ + +WINDOW_TYPE_CONSOLE = 1, +WINDOW_TYPE_MEMORY_VIEWER, +WINDOW_TYPE_DISASSEMBLY_VIEWER, +WINDOW_TYPE_ERROR_LOG_VIEWER, +WINDOW_TYPE_POINTS_VIEWER, +WINDOW_TYPE_DEVICES_VIEWER, +WINDOW_TYPE_DEVICE_INFO_VIEWER + +}; + +extern char const *const NODE_WINDOW; +extern char const *const NODE_COLORS; + +extern char const *const NODE_WINDOW_SPLITS; +extern char const *const NODE_WINDOW_SELECTION; +extern char const *const NODE_WINDOW_SCROLL; +extern char const *const NODE_WINDOW_EXPRESSION; +extern char const *const NODE_WINDOW_HISTORY; + +extern char const *const NODE_HISTORY_ITEM; + +extern char const *const ATTR_DEBUGGER_SAVE_WINDOWS; +extern char const *const ATTR_DEBUGGER_GROUP_WINDOWS; + +extern char const *const ATTR_WINDOW_TYPE; +extern char const *const ATTR_WINDOW_POSITION_X; +extern char const *const ATTR_WINDOW_POSITION_Y; +extern char const *const ATTR_WINDOW_WIDTH; +extern char const *const ATTR_WINDOW_HEIGHT; + +extern char const *const ATTR_WINDOW_MEMORY_REGION; +extern char const *const ATTR_WINDOW_MEMORY_REVERSE_COLUMNS; +extern char const *const ATTR_WINDOW_MEMORY_ADDRESS_MODE; +extern char const *const ATTR_WINDOW_MEMORY_ADDRESS_RADIX; +extern char const *const ATTR_WINDOW_MEMORY_DATA_FORMAT; +extern char const *const ATTR_WINDOW_MEMORY_ROW_CHUNKS; + +extern char const *const ATTR_WINDOW_DISASSEMBLY_CPU; +extern char const *const ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN; + +extern char const *const ATTR_WINDOW_POINTS_TYPE; + +extern char const *const ATTR_WINDOW_DEVICE_TAG; + +extern char const *const ATTR_COLORS_THEME; + +extern char const *const ATTR_SPLITS_CONSOLE_STATE; +extern char const *const ATTR_SPLITS_CONSOLE_DISASSEMBLY; + +extern char const *const ATTR_SELECTION_CURSOR_VISIBLE; +extern char const *const ATTR_SELECTION_CURSOR_X; +extern char const *const ATTR_SELECTION_CURSOR_Y; + +extern char const *const ATTR_SCROLL_ORIGIN_X; +extern char const *const ATTR_SCROLL_ORIGIN_Y; + +} // namespace osd::debugger + +#endif // MAME_OSD_DEBUGGER_XMLCONFIG_H |