From aac1eab8a241973d2be91ae0e883587e43de6c9a Mon Sep 17 00:00:00 2001
From: Andrei Holub <andrei.holub@gmail.com>
Date: Sun, 1 Jun 2025 20:57:16 -0400
Subject: [PATCH 1/5] emu/debug: Replaced saver/loadr with more generic
 savem/loadm which handels both region and share memory

---
 src/emu/debug/debugcmd.cpp | 150 ++++++++++++++++++++++++++++++++++++-
 src/emu/debug/debugcmd.h   |   5 ++
 src/emu/debug/debugcon.cpp |  34 ++++++++-
 src/emu/debug/debugcon.h   |   5 +-
 4 files changed, 189 insertions(+), 5 deletions(-)

diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 76a6053477f9c..f23e3238a9c00 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -274,13 +274,15 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("saved",     CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_DATA, _1));
 	m_console.register_command("savei",     CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_IO, _1));
 	m_console.register_command("saveo",     CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_OPCODES, _1));
-	m_console.register_command("saver",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_saveregion, this, _1));
+	m_console.register_command("saver",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_region_deprecated, this, _1));
+	m_console.register_command("savem",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_savememory, this, _1));
 
 	m_console.register_command("load",      CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, -1, _1));
 	m_console.register_command("loadd",     CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_DATA, _1));
 	m_console.register_command("loadi",     CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_IO, _1));
 	m_console.register_command("loado",     CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_OPCODES, _1));
-	m_console.register_command("loadr",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_loadregion, this, _1));
+	m_console.register_command("loadr",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_region_deprecated, this, _1));
+	m_console.register_command("loadm",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_loadmemory, this, _1));
 
 	m_console.register_command("dump",      CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, -1, _1));
 	m_console.register_command("dumpd",     CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, AS_DATA, _1));
@@ -2094,6 +2096,12 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string
 }
 
 
+void debugger_commands::execute_region_deprecated(const std::vector<std::string_view> &params)
+{
+	m_console.printf("saver/loadr is deprecated, use savem/loadm instead.\n");
+}
+
+
 /*-------------------------------------------------
     execute_saveregion - execute the save command on region memory
 -------------------------------------------------*/
@@ -2133,6 +2141,70 @@ void debugger_commands::execute_saveregion(const std::vector<std::string_view> &
 	m_console.printf("Data saved successfully\n");
 }
 
+/*-------------------------------------------------
+    execute_saveshare - execute the save command on share memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_saveshare(const std::vector<std::string_view> &params)
+{
+	u64 offset, length;
+	memory_share *share;
+
+	// validate parameters
+	if (!m_console.validate_number_parameter(params[1], offset))
+		return;
+	if (!m_console.validate_number_parameter(params[2], length))
+		return;
+	if (!m_console.validate_memory_share_parameter(params[3], share))
+		return;
+
+	if (offset >= share->bytes())
+	{
+		m_console.printf("Invalid offset\n");
+		return;
+	}
+	if ((length <= 0) || ((length + offset) >= share->bytes()))
+		length = share->bytes() - offset;
+
+	/* open the file */
+	std::string const filename(params[0]);
+	FILE *f = fopen(filename.c_str(), "wb");
+	if (!f)
+	{
+		m_console.printf("Error opening file '%s'\n", params[0]);
+		return;
+	}
+	fwrite(reinterpret_cast<u8 *>(share->ptr()) + offset, 1, length, f);
+
+	fclose(f);
+	m_console.printf("Data saved successfully\n");
+}
+
+
+/*-------------------------------------------------
+    execute_savememory - execute the save command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_savememory(const std::vector<std::string_view> &params)
+{
+	u64 offset, length;
+
+	// validate parameters
+	if (!m_console.validate_number_parameter(params[1], offset))
+		return;
+	if (!m_console.validate_number_parameter(params[2], length))
+		return;
+
+	memory_region *region;
+	memory_share *share;
+	if (m_console.validate_memory_region_parameter(params[3], region, false))
+		execute_saveregion(params);
+	else if (m_console.validate_memory_share_parameter(params[3], share, false))
+		execute_saveshare(params);
+	else
+		m_console.printf("No matching memory found for '%s'\n", params[3]);
+}
+
 
 /*-------------------------------------------------
     execute_load - execute the load command
@@ -2297,6 +2369,80 @@ void debugger_commands::execute_loadregion(const std::vector<std::string_view> &
 }
 
 
+/*-------------------------------------------------
+    execute_loadshare - execute the load command on share memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_loadshare(const std::vector<std::string_view> &params)
+{
+	u64 offset, length;
+	memory_share *share;
+
+	// validate parameters
+	if (!m_console.validate_number_parameter(params[1], offset))
+		return;
+	if (!m_console.validate_number_parameter(params[2], length))
+		return;
+	if (!m_console.validate_memory_share_parameter(params[3], share))
+		return;
+
+	if (offset >= share->bytes())
+	{
+		m_console.printf("Invalid offset\n");
+		return;
+	}
+	if ((length <= 0) || ((length + offset) >= share->bytes()))
+		length = share->bytes() - offset;
+
+	// open the file
+	std::string filename(params[0]);
+	FILE *const f = fopen(filename.c_str(), "rb");
+	if (!f)
+	{
+		m_console.printf("Error opening file '%s'\n", params[0]);
+		return;
+	}
+
+	fseek(f, 0L, SEEK_END);
+	u64 size = ftell(f);
+	rewind(f);
+
+	// check file size
+	if (length >= size)
+		length = size;
+
+	fread(reinterpret_cast<u8 *>(share->ptr()) + offset, 1, length, f);
+
+	fclose(f);
+	m_console.printf("Data loaded successfully to memory : 0x%X to 0x%X\n", offset, offset + length - 1);
+}
+
+
+/*-------------------------------------------------
+    execute_loadregion - execute the load command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_loadmemory(const std::vector<std::string_view> &params)
+{
+	u64 offset, length;
+
+	// validate parameters
+	if (!m_console.validate_number_parameter(params[1], offset))
+		return;
+	if (!m_console.validate_number_parameter(params[2], length))
+		return;
+
+	memory_region *region;
+	memory_share *share;
+	if (m_console.validate_memory_region_parameter(params[3], region, false))
+		execute_loadregion(params);
+	else if (m_console.validate_memory_share_parameter(params[3], share, false))
+		execute_loadshare(params);
+	else
+		m_console.printf("No matching memory found for '%s'\n", params[3]);
+}
+
+
 /*-------------------------------------------------
     execute_dump - execute the dump command
 -------------------------------------------------*/
diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h
index cf38c6d903a27..08770b51e2efe 100644
--- a/src/emu/debug/debugcmd.h
+++ b/src/emu/debug/debugcmd.h
@@ -127,9 +127,14 @@ class debugger_commands
 	void execute_stateload(const std::vector<std::string_view> &params);
 	void execute_rewind(const std::vector<std::string_view> &params);
 	void execute_save(int spacenum, const std::vector<std::string_view> &params);
+	void execute_region_deprecated(const std::vector<std::string_view> &params);
 	void execute_saveregion(const std::vector<std::string_view> &params);
+	void execute_saveshare(const std::vector<std::string_view> &params);
+	void execute_savememory(const std::vector<std::string_view> &params);
 	void execute_load(int spacenum, const std::vector<std::string_view> &params);
 	void execute_loadregion(const std::vector<std::string_view> &params);
+	void execute_loadshare(const std::vector<std::string_view> &params);
+	void execute_loadmemory(const std::vector<std::string_view> &params);
 	void execute_dump(int spacenum, const std::vector<std::string_view> &params);
 	void execute_strdump(int spacenum, const std::vector<std::string_view> &params);
 	void execute_cheatrange(bool init, const std::vector<std::string_view> &params);
diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp
index ec5bc15475101..1f50399f8952e 100644
--- a/src/emu/debug/debugcon.cpp
+++ b/src/emu/debug/debugcon.cpp
@@ -925,7 +925,7 @@ bool debugger_console::validate_target_address_parameter(std::string_view param,
 ///   failure.
 /// \return true if the parameter refers to a memory region in the
 ///   current system, or false otherwise.
-bool debugger_console::validate_memory_region_parameter(std::string_view param, memory_region *&result)
+bool debugger_console::validate_memory_region_parameter(std::string_view param, memory_region *&result, bool print_error)
 {
 	auto const &regions = m_machine.memory().regions();
 	std::string_view relative = param;
@@ -938,7 +938,37 @@ bool debugger_console::validate_memory_region_parameter(std::string_view param,
 	}
 	else
 	{
-		printf("No matching memory region found for '%s'\n", param);
+		if (print_error)
+			printf("No matching memory region found for '%s'\n", param);
+		return false;
+	}
+}
+
+
+/// \brief Validate a parameter as a memory share
+///
+/// Validates a parameter as a memory share tag and retrieves the
+/// specified memory share.
+/// \param [in] The parameter string.
+/// \param [out] result The memory share on success, or unchanged on
+///   failure.
+/// \return true if the parameter refers to a memory share in the
+///   current system, or false otherwise.
+bool debugger_console::validate_memory_share_parameter(std::string_view param, memory_share *&result, bool print_error)
+{
+	auto const &shares = m_machine.memory().shares();
+	std::string_view relative = param;
+	device_t &base = get_device_search_base(relative);
+	auto const iter = shares.find(base.subtag(strmakelower(relative)));
+	if (shares.end() != iter)
+	{
+		result = iter->second.get();
+		return true;
+	}
+	else
+	{
+		if (print_error)
+			printf("No matching memory share found for '%s'\n", param);
 		return false;
 	}
 }
diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h
index 37b2e235348cc..13ba7deef60bc 100644
--- a/src/emu/debug/debugcon.h
+++ b/src/emu/debug/debugcon.h
@@ -131,7 +131,10 @@ class debugger_console
 	bool validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr);
 
 	// validates a parameter as a memory region name and retrieves the given region
-	bool validate_memory_region_parameter(std::string_view param, memory_region *&result);
+	bool validate_memory_region_parameter(std::string_view param, memory_region *&result, bool print_error = true);
+
+	// validates a parameter as a memory region name and retrieves the given share
+	bool validate_memory_share_parameter(std::string_view param, memory_share *&result, bool print_error = true);
 
 	// validates a parameter as a debugger expression
 	bool validate_expression_parameter(std::string_view param, parsed_expression &result);

From 098c604234e70c73b290bd3afe7ab218a1826134 Mon Sep 17 00:00:00 2001
From: Andrei Holub <andrei.holub@gmail.com>
Date: Wed, 4 Jun 2025 11:56:12 -0400
Subject: [PATCH 2/5] stubs, no implementation

---
 docs/source/debugger/index.rst  |   5 +
 docs/source/debugger/memory.rst |  12 ++
 src/emu/debug/debugcmd.cpp      | 188 ++++++++------------------------
 src/emu/debug/debugcmd.h        |  11 +-
 src/emu/debug/debugcon.cpp      |  10 +-
 src/emu/debug/debugcon.h        |   4 +-
 src/emu/debug/debughlp.cpp      |  18 +++
 src/emu/debug/express.cpp       | 135 ++++++++++++++++++++++-
 src/emu/debug/express.h         |   5 +-
 9 files changed, 229 insertions(+), 159 deletions(-)

diff --git a/docs/source/debugger/index.rst b/docs/source/debugger/index.rst
index 2947d0253acfb..a035a7e13c022 100644
--- a/docs/source/debugger/index.rst
+++ b/docs/source/debugger/index.rst
@@ -158,6 +158,10 @@ Examples:
     Address 9660 in the default address space of the device with the
     absolute tag ``:ram``, or the ``ram`` space of the root machine
     device.
+``1883:vram.m``
+    Address 1883 in the memory region with the absolute tag ``:vram``.
+``1923:sprites.s``
+    Address 1923 in the memory share with the absolute tag ``:sprites``.
 
 The examples here include a lot of corner cases, but in general the
 debugger should take the most likely meaning for a device or address
@@ -327,6 +331,7 @@ The size may optionally be preceded by an access type specification:
 * ``o`` specifies direct read/write pointer access defaulting to space 3
   (opcodes)
 * ``m`` specifies a memory region
+* ``s`` specifies a memory share
 
 Finally, this may be preceded by a tag and/or address space name
 followed by a dot (``.``).
diff --git a/docs/source/debugger/memory.rst b/docs/source/debugger/memory.rst
index dfb5914b5a9dd..b32273a40c609 100644
--- a/docs/source/debugger/memory.rst
+++ b/docs/source/debugger/memory.rst
@@ -65,6 +65,7 @@ find
 ----
 
 **f[ind][{d|i|o}] <address>[:<space>],<length>[,<data>[,…]]**
+**f[ind] <address>:<memory>.{m|s},<length>[,<data>[,…]]**
 
 Search through memory for the specified sequence of data.  The
 **<address>** is the address to begin searching from, optionally
@@ -114,6 +115,7 @@ fill
 ----
 
 **fill[{d|i|o}] <address>[:<space>],<length>[,<data>[,…]]**
+**fill <address>:<memory>.{m|s},<length>[,<data>[,…]]**
 
 Overwrite a block of memory with copies of the supplied data sequence.
 The **<address>** specifies the address to begin writing at, optionally
@@ -146,6 +148,7 @@ dump
 ----
 
 **dump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]]**
+**dump <filename>,<address>:<memory>.{m|s},<length>[,<group>[,<ascii>[,<rowsize>]]]**
 
 Dump memory to the text file specified by the **<filename>** parameter.
 The **<address>** specifies the address to start dumping from,
@@ -190,6 +193,7 @@ strdump
 -------
 
 **strdump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<term>]**
+**strdump <filename>,<address>:<memory>.{m|s},<length>[,<term>]**
 
 Dump memory to the text file specified by the **<filename>** parameter.
 The **<address>** specifies the address to start dumping from,
@@ -216,6 +220,7 @@ save
 ----
 
 **save[{d|i|o}] <filename>,<address>[:<space>],<length>**
+**save <filename>,<address>:<memory>.{m|s},<length>**
 
 Save raw memory to the binary file specified by the **<filename>**
 parameter.  The **<address>** specifies the address to start saving
@@ -260,6 +265,9 @@ start saving from, and the **<length>** specifies how much memory to
 save.  The range **<address>** through **<address>+<length>-1**,
 inclusive, will be output to the file.
 
+Alternetevely use :ref:`debugger-command-save` syntax:
+``save <filename>,<address>:<region>.m,<length>``
+
 Examples:
 
 ``saver data.bin,200,100,:monitor``
@@ -278,6 +286,7 @@ load
 ----
 
 **load[{d|i|o}] <filename>,<address>[:<space>][,<length>]**
+**load <filename>,<address>:<memory>.{m|s}[,<length>]**
 
 Load raw memory from the binary file specified by the **<filename>**
 parameter.  The **<address>** specifies the address to start loading to,
@@ -334,6 +343,9 @@ through **<address>+<length>-1**, inclusive, will be read in from the
 file.  If the **<length>** is zero, or is greater than the total length
 of the file, the entire contents of the file will be loaded but no more.
 
+Alternetevely use :ref:`debugger-command-load` syntax:
+``load <filename>,<address>:<region>.m[,<length>]``
+
 Examples:
 
 ``loadr data.bin,200,100,:monitor``
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index f23e3238a9c00..d8807fe7299ed 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -274,15 +274,13 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("saved",     CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_DATA, _1));
 	m_console.register_command("savei",     CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_IO, _1));
 	m_console.register_command("saveo",     CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_OPCODES, _1));
-	m_console.register_command("saver",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_region_deprecated, this, _1));
-	m_console.register_command("savem",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_savememory, this, _1));
+	m_console.register_command("saver",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_saveregion, this, _1));
 
 	m_console.register_command("load",      CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, -1, _1));
 	m_console.register_command("loadd",     CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_DATA, _1));
 	m_console.register_command("loadi",     CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_IO, _1));
 	m_console.register_command("loado",     CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_OPCODES, _1));
-	m_console.register_command("loadr",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_region_deprecated, this, _1));
-	m_console.register_command("loadm",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_loadmemory, this, _1));
+	m_console.register_command("loadr",     CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_loadregion, this, _1));
 
 	m_console.register_command("dump",      CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, -1, _1));
 	m_console.register_command("dumpd",     CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, AS_DATA, _1));
@@ -2095,10 +2093,12 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string
 	m_console.printf("Data saved successfully\n");
 }
 
+/*-------------------------------------------------
+    execute_savememory - execute the save command on memory
+-------------------------------------------------*/
 
-void debugger_commands::execute_region_deprecated(const std::vector<std::string_view> &params)
+void debugger_commands::execute_savememory(const std::vector<std::string_view> &params)
 {
-	m_console.printf("saver/loadr is deprecated, use savem/loadm instead.\n");
 }
 
 
@@ -2141,70 +2141,6 @@ void debugger_commands::execute_saveregion(const std::vector<std::string_view> &
 	m_console.printf("Data saved successfully\n");
 }
 
-/*-------------------------------------------------
-    execute_saveshare - execute the save command on share memory
--------------------------------------------------*/
-
-void debugger_commands::execute_saveshare(const std::vector<std::string_view> &params)
-{
-	u64 offset, length;
-	memory_share *share;
-
-	// validate parameters
-	if (!m_console.validate_number_parameter(params[1], offset))
-		return;
-	if (!m_console.validate_number_parameter(params[2], length))
-		return;
-	if (!m_console.validate_memory_share_parameter(params[3], share))
-		return;
-
-	if (offset >= share->bytes())
-	{
-		m_console.printf("Invalid offset\n");
-		return;
-	}
-	if ((length <= 0) || ((length + offset) >= share->bytes()))
-		length = share->bytes() - offset;
-
-	/* open the file */
-	std::string const filename(params[0]);
-	FILE *f = fopen(filename.c_str(), "wb");
-	if (!f)
-	{
-		m_console.printf("Error opening file '%s'\n", params[0]);
-		return;
-	}
-	fwrite(reinterpret_cast<u8 *>(share->ptr()) + offset, 1, length, f);
-
-	fclose(f);
-	m_console.printf("Data saved successfully\n");
-}
-
-
-/*-------------------------------------------------
-    execute_savememory - execute the save command on memory
--------------------------------------------------*/
-
-void debugger_commands::execute_savememory(const std::vector<std::string_view> &params)
-{
-	u64 offset, length;
-
-	// validate parameters
-	if (!m_console.validate_number_parameter(params[1], offset))
-		return;
-	if (!m_console.validate_number_parameter(params[2], length))
-		return;
-
-	memory_region *region;
-	memory_share *share;
-	if (m_console.validate_memory_region_parameter(params[3], region, false))
-		execute_saveregion(params);
-	else if (m_console.validate_memory_share_parameter(params[3], share, false))
-		execute_saveshare(params);
-	else
-		m_console.printf("No matching memory found for '%s'\n", params[3]);
-}
-
 
 /*-------------------------------------------------
     execute_load - execute the load command
@@ -2319,6 +2255,14 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string
 		m_console.printf("Data loaded successfully to memory : 0x%X to 0x%X\n", offset, i-1);
 }
 
+/*-------------------------------------------------
+    execute_loadmemory - execute the load command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_loadmemory(const std::vector<std::string_view> &params)
+{
+}
+
 
 /*-------------------------------------------------
     execute_loadregion - execute the load command on region memory
@@ -2369,80 +2313,6 @@ void debugger_commands::execute_loadregion(const std::vector<std::string_view> &
 }
 
 
-/*-------------------------------------------------
-    execute_loadshare - execute the load command on share memory
--------------------------------------------------*/
-
-void debugger_commands::execute_loadshare(const std::vector<std::string_view> &params)
-{
-	u64 offset, length;
-	memory_share *share;
-
-	// validate parameters
-	if (!m_console.validate_number_parameter(params[1], offset))
-		return;
-	if (!m_console.validate_number_parameter(params[2], length))
-		return;
-	if (!m_console.validate_memory_share_parameter(params[3], share))
-		return;
-
-	if (offset >= share->bytes())
-	{
-		m_console.printf("Invalid offset\n");
-		return;
-	}
-	if ((length <= 0) || ((length + offset) >= share->bytes()))
-		length = share->bytes() - offset;
-
-	// open the file
-	std::string filename(params[0]);
-	FILE *const f = fopen(filename.c_str(), "rb");
-	if (!f)
-	{
-		m_console.printf("Error opening file '%s'\n", params[0]);
-		return;
-	}
-
-	fseek(f, 0L, SEEK_END);
-	u64 size = ftell(f);
-	rewind(f);
-
-	// check file size
-	if (length >= size)
-		length = size;
-
-	fread(reinterpret_cast<u8 *>(share->ptr()) + offset, 1, length, f);
-
-	fclose(f);
-	m_console.printf("Data loaded successfully to memory : 0x%X to 0x%X\n", offset, offset + length - 1);
-}
-
-
-/*-------------------------------------------------
-    execute_loadregion - execute the load command on memory
--------------------------------------------------*/
-
-void debugger_commands::execute_loadmemory(const std::vector<std::string_view> &params)
-{
-	u64 offset, length;
-
-	// validate parameters
-	if (!m_console.validate_number_parameter(params[1], offset))
-		return;
-	if (!m_console.validate_number_parameter(params[2], length))
-		return;
-
-	memory_region *region;
-	memory_share *share;
-	if (m_console.validate_memory_region_parameter(params[3], region, false))
-		execute_loadregion(params);
-	else if (m_console.validate_memory_share_parameter(params[3], share, false))
-		execute_loadshare(params);
-	else
-		m_console.printf("No matching memory found for '%s'\n", params[3]);
-}
-
-
 /*-------------------------------------------------
     execute_dump - execute the dump command
 -------------------------------------------------*/
@@ -2606,6 +2476,13 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string
 	m_console.printf("Data dumped successfully\n");
 }
 
+/*-------------------------------------------------
+    execute_dumpmemory - execute the dump command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_dumpmemory(const std::vector<std::string_view> &params)
+{
+}
 
 //-------------------------------------------------
 //  execute_strdump - execute the strdump command
@@ -2782,6 +2659,13 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str
 	fclose(f);
 	m_console.printf("Data dumped successfully\n");
 }
+/*-------------------------------------------------
+    execute_strdumpmemory - execute the strdump command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_strdumpmemory(const std::vector<std::string_view> &params)
+{
+}
 
 
 /*-------------------------------------------------
@@ -3408,6 +3292,14 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string
 		m_console.printf("Not found\n");
 }
 
+/*-------------------------------------------------
+    execute_findmemory - execute the find command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_findmemory(const std::vector<std::string_view> &params)
+{
+}
+
 
 //-------------------------------------------------
 //  execute_fill - execute the fill command
@@ -3517,6 +3409,14 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string
 	}
 }
 
+/*-------------------------------------------------
+    execute_fillmemory - execute the fill command on memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_fillmemory(const std::vector<std::string_view> &params)
+{
+}
+
 
 /*-------------------------------------------------
     execute_dasm - execute the dasm command
diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h
index 08770b51e2efe..b9a5eaeda8862 100644
--- a/src/emu/debug/debugcmd.h
+++ b/src/emu/debug/debugcmd.h
@@ -127,23 +127,24 @@ class debugger_commands
 	void execute_stateload(const std::vector<std::string_view> &params);
 	void execute_rewind(const std::vector<std::string_view> &params);
 	void execute_save(int spacenum, const std::vector<std::string_view> &params);
-	void execute_region_deprecated(const std::vector<std::string_view> &params);
-	void execute_saveregion(const std::vector<std::string_view> &params);
-	void execute_saveshare(const std::vector<std::string_view> &params);
 	void execute_savememory(const std::vector<std::string_view> &params);
+	void execute_saveregion(const std::vector<std::string_view> &params);
 	void execute_load(int spacenum, const std::vector<std::string_view> &params);
-	void execute_loadregion(const std::vector<std::string_view> &params);
-	void execute_loadshare(const std::vector<std::string_view> &params);
 	void execute_loadmemory(const std::vector<std::string_view> &params);
+	void execute_loadregion(const std::vector<std::string_view> &params);
 	void execute_dump(int spacenum, const std::vector<std::string_view> &params);
+	void execute_dumpmemory(const std::vector<std::string_view> &params);
 	void execute_strdump(int spacenum, const std::vector<std::string_view> &params);
+	void execute_strdumpmemory(const std::vector<std::string_view> &params);
 	void execute_cheatrange(bool init, const std::vector<std::string_view> &params);
 	void execute_cheatnext(bool initial, const std::vector<std::string_view> &params);
 	void execute_cheatlist(const std::vector<std::string_view> &params);
 	void execute_cheatundo(const std::vector<std::string_view> &params);
 	void execute_dasm(const std::vector<std::string_view> &params);
 	void execute_find(int spacenum, const std::vector<std::string_view> &params);
+	void execute_findmemory(const std::vector<std::string_view> &params);
 	void execute_fill(int spacenum, const std::vector<std::string_view> &params);
+	void execute_fillmemory(const std::vector<std::string_view> &params);
 	void execute_trace(const std::vector<std::string_view> &params, bool trace_over);
 	void execute_traceflush(const std::vector<std::string_view> &params);
 	void execute_history(const std::vector<std::string_view> &params);
diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp
index 1f50399f8952e..1042766aa8721 100644
--- a/src/emu/debug/debugcon.cpp
+++ b/src/emu/debug/debugcon.cpp
@@ -925,7 +925,7 @@ bool debugger_console::validate_target_address_parameter(std::string_view param,
 ///   failure.
 /// \return true if the parameter refers to a memory region in the
 ///   current system, or false otherwise.
-bool debugger_console::validate_memory_region_parameter(std::string_view param, memory_region *&result, bool print_error)
+bool debugger_console::validate_memory_region_parameter(std::string_view param, memory_region *&result)
 {
 	auto const &regions = m_machine.memory().regions();
 	std::string_view relative = param;
@@ -938,8 +938,7 @@ bool debugger_console::validate_memory_region_parameter(std::string_view param,
 	}
 	else
 	{
-		if (print_error)
-			printf("No matching memory region found for '%s'\n", param);
+		printf("No matching memory region found for '%s'\n", param);
 		return false;
 	}
 }
@@ -954,7 +953,7 @@ bool debugger_console::validate_memory_region_parameter(std::string_view param,
 ///   failure.
 /// \return true if the parameter refers to a memory share in the
 ///   current system, or false otherwise.
-bool debugger_console::validate_memory_share_parameter(std::string_view param, memory_share *&result, bool print_error)
+bool debugger_console::validate_memory_share_parameter(std::string_view param, memory_share *&result)
 {
 	auto const &shares = m_machine.memory().shares();
 	std::string_view relative = param;
@@ -967,8 +966,7 @@ bool debugger_console::validate_memory_share_parameter(std::string_view param, m
 	}
 	else
 	{
-		if (print_error)
-			printf("No matching memory share found for '%s'\n", param);
+		printf("No matching memory share found for '%s'\n", param);
 		return false;
 	}
 }
diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h
index 13ba7deef60bc..78ee1d9bb8dd2 100644
--- a/src/emu/debug/debugcon.h
+++ b/src/emu/debug/debugcon.h
@@ -131,10 +131,10 @@ class debugger_console
 	bool validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr);
 
 	// validates a parameter as a memory region name and retrieves the given region
-	bool validate_memory_region_parameter(std::string_view param, memory_region *&result, bool print_error = true);
+	bool validate_memory_region_parameter(std::string_view param, memory_region *&result);
 
 	// validates a parameter as a memory region name and retrieves the given share
-	bool validate_memory_share_parameter(std::string_view param, memory_share *&result, bool print_error = true);
+	bool validate_memory_share_parameter(std::string_view param, memory_share *&result);
 
 	// validates a parameter as a debugger expression
 	bool validate_expression_parameter(std::string_view param, parsed_expression &result);
diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp
index 8e5fa1b9c64f2..e78a31d7568fd 100644
--- a/src/emu/debug/debughlp.cpp
+++ b/src/emu/debug/debughlp.cpp
@@ -94,26 +94,32 @@ const help_item f_static_help_list[] =
 		"\n"
 		"  dasm <filename>,<address>,<length>[,<opcodes>[,<CPU>]] -- disassemble to the given file\n"
 		"  f[ind] <address>,<length>[,<data>[,...]] -- search memory for data\n"
+		"  f[ind] <address>:<memory>.{m|s},<length>[,<data>[,...]] -- search memory region or share for data\n"
 		"  f[ind]d <address>,<length>[,<data>[,...]] -- search data memory for data\n"
 		"  f[ind]i <address>,<length>[,<data>[,...]] -- search I/O memory for data\n"
 		"  fill <address>,<length>[,<data>[,...]] -- fill memory with data\n"
+		"  fill <address>:<memory>.{m|s},<length>[,<data>[,...]] -- fill memory region or share with data\n"
 		"  filld <address>[:<space>],<length>[,<data>[,...]] -- fill data memory with data\n"
 		"  filli <address>[:<space>],<length>[,<data>[,...][ -- fill I/O memory with data\n"
 		"  fillo <address>[:<space>],<length>[,<data>[,...][ -- fill opcode memory with data\n"
 		"  dump <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump memory as text\n"
+		"  dump <filename>,<address>:<memory>.{m|s},<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump memory region or share as text\n"
 		"  dumpd <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump data memory as text\n"
 		"  dumpi <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump I/O memory as text\n"
 		"  dumpo <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump opcodes memory as text\n"
 		"  strdump <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from memory\n"
+		"  strdump <filename>,<address>:<memory>.{m|s},<length>[,<term>] -- dump ASCII strings from memory region or share\n"
 		"  strdumpd <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from data memory\n"
 		"  strdumpi <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from I/O memory\n"
 		"  strdumpo <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from opcodes memory\n"
 		"  save <filename>,<address>[:<space>],<length> -- save binary memory to the given file\n"
+		"  save <filename>,<address>:<memory>.{m|s},<length> -- load binary memory region or share to the given file\n"
 		"  saved <filename>,<address>[:<space>],<length> -- save binary data memory to the given file\n"
 		"  savei <filename>,<address>[:<space>],<length> -- save binary I/O memory to the given file\n"
 		"  saveo <filename>,<address>[:<space>],<length> -- save binary opcode memory to the given file\n"
 		"  saver <filename>,<address>[:<space>],<length>,<region> -- save binary memory region to the given file\n"
 		"  load <filename>,<address>[:<space>][,<length>] -- load binary memory from the given file\n"
+		"  load <filename>,<address>:<memory>.{m|s}[,<length>] -- load binary memory region or share from the given file\n"
 		"  loadd <filename>,<address>[:<space>][,<length>] -- load binary data memory from the given file\n"
 		"  loadi <filename>,<address>[:<space>][,<length>] -- load binary I/O memory from the given file\n"
 		"  loado <filename>,<address>[:<space>][,<length>] -- load binary opcode memory from the given file\n"
@@ -633,6 +639,7 @@ const help_item f_static_help_list[] =
 		"find",
 		"\n"
 		"  f[ind][{d|i|o}] <address>[:<space>],<length>[,<data>[,...]]\n"
+		"  f[ind] <address>:<memory>.{m|s},<length>[,<data>[,...]]\n"
 		"\n"
 		"The find commands search through memory for the specified sequence of data.  The <address> "
 		"is the address to begin searching from, optionally followed by a device and/or address "
@@ -674,6 +681,7 @@ const help_item f_static_help_list[] =
 		"fill",
 		"\n"
 		"  fill[{d|i|o}] <address>[:<space>],<length>[,<data>[,...]]\n"
+		"  fill <address>:<memory>.{m|s},<length>[,<data>[,...]]\n"
 		"\n"
 		"The fill commands overwrite a block of memory with copies of the supplied data sequence.  "
 		"The <address> specifies the address to begin writing at, optionally followed by a device "
@@ -700,6 +708,7 @@ const help_item f_static_help_list[] =
 		"dump",
 		"\n"
 		"  dump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]]\n"
+		"  dump <filename>,<address>:<memory>.{m|s},<length>[,<group>[,<ascii>[,<rowsize>]]]\n"
 		"\n"
 		"The dump commands dump memory to the text file specified in the <filename> parameter.  The "
 		"<address> specifies the address to start dumping from, optionally followed by a device "
@@ -739,6 +748,7 @@ const help_item f_static_help_list[] =
 		"strdump",
 		"\n"
 		"  strdump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<term>]\n"
+		"  strdump <filename>,<address>:<memory>.{m|s},<length>[,<term>]\n"
 		"\n"
 		"The strdump commands dump memory to the text file specified in the <filename> parameter.  "
 		"The <address> specifies the address to start dumping from, optionally followed by a device "
@@ -761,6 +771,7 @@ const help_item f_static_help_list[] =
 		"save",
 		"\n"
 		"  save[{d|i|o}] <filename>,<address>[:<space>],<length>\n"
+		"  save <filename>,<address>:<memory>.{m|s},<length>\n"
 		"\n"
 		"The save commands save raw memory to the binary file specified in the <filename> "
 		"parameter.  The <address> specifies the address to start saving from, optionally followed "
@@ -798,6 +809,9 @@ const help_item f_static_help_list[] =
 		"saving from, and the <length> specifies how much memory to save.  The range <address> "
 		"through <address>+<length>-1, inclusive, will be output to the file.\n"
 		"\n"
+		"Alternetevely use 'save' syntax:\n"
+		"  save <filename>,<address>:<region>.m,<length>\n"
+		"\n"
 		"Examples:\n"
 		"\n"
 		"saver data.bin,200,100,:monitor\n"
@@ -811,6 +825,7 @@ const help_item f_static_help_list[] =
 		"load",
 		"\n"
 		"  load[{d|i|o}] <filename>,<address>[:<space>][,<length>]\n"
+		"  load <filename>,<address>:<memory>.{m|s}[,<length>]\n"
 		"\n"
 		"The load commands load raw memory from the binary file specified in the <filename> "
 		"parameter.  The <address> specifies the address to start loading to, optionally followed "
@@ -857,6 +872,9 @@ const help_item f_static_help_list[] =
 		"is zero, or is greater than the total length of the file, the entire contents of the file "
 		"will be loaded but no more.\n"
 		"\n"
+		"Alternetevely use 'load' syntax:\n"
+		"  load <filename>,<address>:<region>.m[,<length>]\n"
+		"\n"
 		"Examples:\n"
 		"\n"
 		"loadr data.bin,200,100,:monitor\n"
diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp
index 219ed6a89ef9a..4408d62146076 100644
--- a/src/emu/debug/express.cpp
+++ b/src/emu/debug/express.cpp
@@ -319,7 +319,7 @@ std::string expression_error::code_string() const
 		case TOO_MANY_STRINGS:      return "too many strings";
 		case INVALID_MEMORY_SIZE:   return "invalid memory size (b/w/d/q expected)";
 		case NO_SUCH_MEMORY_SPACE:  return "non-existent memory space";
-		case INVALID_MEMORY_SPACE:  return "invalid memory space (p/d/i/o/r/m expected)";
+		case INVALID_MEMORY_SPACE:  return "invalid memory space (p/d/i/o/r/m/s expected)";
 		case INVALID_MEMORY_NAME:   return "invalid memory name";
 		case MISSING_MEMORY_NAME:   return "missing memory name";
 		default:                    return "unknown error";
@@ -673,6 +673,11 @@ u64 symbol_table::memory_value(const char *name, expression_space spacenum, u32
 			return read_memory_region(name, address, size);
 		break;
 
+	case EXPSPACE_SHARE:
+		if (name)
+			return read_memory_share(name, address, size);
+		break;
+
 	default:
 		break;
 	}
@@ -782,6 +787,55 @@ u64 symbol_table::read_memory_region(const char *rgntag, offs_t address, int siz
 }
 
 
+//-------------------------------------------------
+//  read_memory_share - read memory from a
+//  memory share
+//-------------------------------------------------
+
+u64 symbol_table::read_memory_share(const char *shatag, offs_t address, int size)
+{
+	auto search = get_device_search(m_machine, m_memintf, shatag);
+	memory_share *const share = search.first.memshare(search.second);
+	u64 result = ~u64(0) >> (64 - 8*size);
+
+	// make sure we get a valid base before proceeding
+	if (share)
+	{
+		// call ourself recursively until we are byte-sized
+		if (size > 1)
+		{
+			int halfsize = size / 2;
+			u64 r0, r1;
+
+			// read each half, from lower address to upper address
+			r0 = read_memory_share(shatag, address + 0, halfsize);
+			r1 = read_memory_share(shatag, address + halfsize, halfsize);
+
+			// assemble based on the target endianness
+			if (share->endianness() == ENDIANNESS_LITTLE)
+				result = r0 | (r1 << (8 * halfsize));
+			else
+				result = r1 | (r0 << (8 * halfsize));
+		}
+
+		// only process if we're within range
+		else if (address < share->bytes())
+		{
+			// lowmask specified which address bits are within the databus width
+			u32 lowmask = share->bytewidth() - 1;
+			u8 *base = reinterpret_cast<u8 *>(share->ptr()) + (address & ~lowmask);
+
+			// if we have a valid base, return the appropriate byte
+			if (share->endianness() == ENDIANNESS_LITTLE)
+				result = base[BYTE8_XOR_LE(address) & lowmask];
+			else
+				result = base[BYTE8_XOR_BE(address) & lowmask];
+		}
+	}
+	return result;
+}
+
+
 //-------------------------------------------------
 //  set_memory_value - write 1,2,4 or 8 bytes at
 //  the given offset in the given address space
@@ -831,6 +885,11 @@ void symbol_table::set_memory_value(const char *name, expression_space spacenum,
 			write_memory_region(name, address, size, data);
 		break;
 
+	case EXPSPACE_SHARE:
+		if (name)
+			write_memory_share(name, address, size, data);
+		break;
+
 	default:
 		break;
 	}
@@ -953,6 +1012,65 @@ void symbol_table::write_memory_region(const char *rgntag, offs_t address, int s
 }
 
 
+//-------------------------------------------------
+//  write_memory_share - write memory to a
+//  memory share
+//-------------------------------------------------
+
+void symbol_table::write_memory_share(const char *shatag, offs_t address, int size, u64 data)
+{
+	auto search = get_device_search(m_machine, m_memintf, shatag);
+	memory_share *const share = search.first.memshare(search.second);
+
+	// make sure we get a valid base before proceeding
+	if (share)
+	{
+		// call ourself recursively until we are byte-sized
+		if (size > 1)
+		{
+			int halfsize = size / 2;
+
+			// break apart based on the target endianness
+			u64 halfmask = ~u64(0) >> (64 - 8 * halfsize);
+			u64 r0, r1;
+			if (share->endianness() == ENDIANNESS_LITTLE)
+			{
+				r0 = data & halfmask;
+				r1 = (data >> (8 * halfsize)) & halfmask;
+			}
+			else
+			{
+				r0 = (data >> (8 * halfsize)) & halfmask;
+				r1 = data & halfmask;
+			}
+
+			// write each half, from lower address to upper address
+			write_memory_share(shatag, address + 0, halfsize, r0);
+			write_memory_share(shatag, address + halfsize, halfsize, r1);
+		}
+
+		// only process if we're within range
+		else if (address < share->bytes())
+		{
+			// lowmask specified which address bits are within the databus width
+			u32 lowmask = share->bytewidth() - 1;
+			u8 *base = reinterpret_cast<u8 *>(share->ptr()) + (address & ~lowmask);
+
+			// if we have a valid base, set the appropriate byte
+			if (share->endianness() == ENDIANNESS_LITTLE)
+			{
+				base[BYTE8_XOR_LE(address) & lowmask] = data;
+			}
+			else
+			{
+				base[BYTE8_XOR_BE(address) & lowmask] = data;
+			}
+			notify_memory_modified();
+		}
+	}
+}
+
+
 //-------------------------------------------------
 //  memory_valid - return true if the given
 //  memory name/space/offset combination is valid
@@ -998,6 +1116,20 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres
 		}
 		break;
 
+	case EXPSPACE_SHARE:
+		if (!name)
+		{
+			return expression_error::MISSING_MEMORY_NAME;
+		}
+		else
+		{
+			auto search = get_device_search(m_machine, m_memintf, name);
+			memory_share *const share = search.first.memshare(search.second);
+			if (!share || !share->ptr())
+				return expression_error::INVALID_MEMORY_NAME;
+		}
+		break;
+
 	default:
 		return expression_error::NO_SUCH_MEMORY_SPACE;
 	}
@@ -1618,6 +1750,7 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st
 		case 'r':   memspace = EXPSPACE_PRGDIRECT;                                              break;
 		case 'o':   memspace = EXPSPACE_OPDIRECT;                                               break;
 		case 'm':   memspace = EXPSPACE_REGION;                                                 break;
+		case 's':   memspace = EXPSPACE_SHARE;                                                  break;
 		default:    throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
 	}
 
diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h
index 33ab9c3b472b9..f9e3983c053fc 100644
--- a/src/emu/debug/express.h
+++ b/src/emu/debug/express.h
@@ -41,7 +41,8 @@ enum expression_space
 	EXPSPACE_OPCODE_PHYSICAL,
 	EXPSPACE_PRGDIRECT,
 	EXPSPACE_OPDIRECT,
-	EXPSPACE_REGION
+	EXPSPACE_REGION,
+	EXPSPACE_SHARE
 };
 
 
@@ -215,8 +216,10 @@ class symbol_table
 	// memory helpers
 	u64 read_program_direct(address_space &space, int opcode, offs_t address, int size);
 	u64 read_memory_region(const char *rgntag, offs_t address, int size);
+	u64 read_memory_share(const char *shatag, offs_t address, int size);
 	void write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data);
 	void write_memory_region(const char *rgntag, offs_t address, int size, u64 data);
+	void write_memory_share(const char *shatag, offs_t address, int size, u64 data);
 	expression_error expression_get_space(const char *tag, int &spacenum, device_memory_interface *&memory);
 	void notify_memory_modified();
 

From 366a39ce83d5bdaaa77796f61659b87574611341 Mon Sep 17 00:00:00 2001
From: Andrei Holub <andrei.holub@gmail.com>
Date: Fri, 6 Jun 2025 12:03:09 -0400
Subject: [PATCH 3/5] implement load/save

---
 src/emu/debug/debugcmd.cpp | 207 +++++++++++++++++++++++++++----------
 src/emu/debug/debugcmd.h   |  12 +--
 src/emu/debug/debugcon.cpp |  34 +++++-
 src/emu/debug/debugcon.h   |   3 +
 4 files changed, 196 insertions(+), 60 deletions(-)

diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index d8807fe7299ed..04585fce3b1e8 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -2007,6 +2007,9 @@ void debugger_commands::execute_rewind(const std::vector<std::string_view> &para
 
 void debugger_commands::execute_save(int spacenum, const std::vector<std::string_view> &params)
 {
+	if (execute_save_try_memory(params))
+		return;
+
 	u64 offset, endoffset, length;
 	address_space *space;
 
@@ -2097,35 +2100,38 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string
     execute_savememory - execute the save command on memory
 -------------------------------------------------*/
 
-void debugger_commands::execute_savememory(const std::vector<std::string_view> &params)
+bool debugger_commands::execute_save_try_memory(const std::vector<std::string_view> &params)
 {
-}
-
+	u64 offset = u64(-1);
+	memory_region *region = nullptr;
+	memory_share *share = nullptr;
+	if (!m_console.validate_address_with_memory_parameter(params[1], offset, region, share))
+		return false; // not memory case
 
-/*-------------------------------------------------
-    execute_saveregion - execute the save command on region memory
--------------------------------------------------*/
-
-void debugger_commands::execute_saveregion(const std::vector<std::string_view> &params)
-{
-	u64 offset, length;
-	memory_region *region;
+	u64 length;
+	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
+		return true;
 
-	// validate parameters
-	if (!m_console.validate_number_parameter(params[1], offset))
-		return;
-	if (!m_console.validate_number_parameter(params[2], length))
-		return;
-	if (!m_console.validate_memory_region_parameter(params[3], region))
-		return;
+	u32 msize;
+	u8 *base;
+	if (region != nullptr)
+	{
+		msize = region->bytes();
+		base = region->base();
+	}
+	else // if (share != nullptr)
+	{
+		msize = share->bytes();
+		base = reinterpret_cast<u8 *>(share->ptr());
+	}
 
-	if (offset >= region->bytes())
+	if (offset >= msize)
 	{
 		m_console.printf("Invalid offset\n");
-		return;
+		return true;
 	}
-	if ((length <= 0) || ((length + offset) >= region->bytes()))
-		length = region->bytes() - offset;
+	if ((length <= 0) || ((length + offset) >= msize))
+		length = msize - offset;
 
 	/* open the file */
 	std::string const filename(params[0]);
@@ -2133,12 +2139,24 @@ void debugger_commands::execute_saveregion(const std::vector<std::string_view> &
 	if (!f)
 	{
 		m_console.printf("Error opening file '%s'\n", params[0]);
-		return;
+		return true;
 	}
-	fwrite(region->base() + offset, 1, length, f);
+	fwrite(base + offset, 1, length, f);
 
 	fclose(f);
 	m_console.printf("Data saved successfully\n");
+
+	return true;
+}
+
+
+/*-------------------------------------------------
+    execute_saveregion - execute the save command on region memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_saveregion(const std::vector<std::string_view> &params)
+{
+	execute_save(-1, std::vector<std::string_view>{ params[0], std::string(params[1]) + std::string(params[3]) + ".m", params[2] });
 }
 
 
@@ -2148,6 +2166,9 @@ void debugger_commands::execute_saveregion(const std::vector<std::string_view> &
 
 void debugger_commands::execute_load(int spacenum, const std::vector<std::string_view> &params)
 {
+	if (execute_load_try_memory(params))
+		return;
+
 	u64 offset, endoffset, length = 0;
 	address_space *space;
 
@@ -2259,35 +2280,39 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string
     execute_loadmemory - execute the load command on memory
 -------------------------------------------------*/
 
-void debugger_commands::execute_loadmemory(const std::vector<std::string_view> &params)
+bool debugger_commands::execute_load_try_memory(const std::vector<std::string_view> &params)
 {
-}
-
-
-/*-------------------------------------------------
-    execute_loadregion - execute the load command on region memory
--------------------------------------------------*/
-
-void debugger_commands::execute_loadregion(const std::vector<std::string_view> &params)
-{
-	u64 offset, length;
-	memory_region *region;
+	u64 offset = u64(-1);
+	memory_region *region = nullptr;
+	memory_share *share = nullptr;
+	if (!m_console.validate_address_with_memory_parameter(params[1], offset, region, share))
+		return false; // not memory case
 
+	u64 length;
 	// validate parameters
-	if (!m_console.validate_number_parameter(params[1], offset))
-		return;
-	if (!m_console.validate_number_parameter(params[2], length))
-		return;
-	if (!m_console.validate_memory_region_parameter(params[3], region))
-		return;
+	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
+		return true;
+
+	u32 msize;
+	u8 *base;
+	if (region != nullptr)
+	{
+		msize = region->bytes();
+		base = region->base();
+	}
+	else // if (share != nullptr)
+	{
+		msize = share->bytes();
+		base = reinterpret_cast<u8 *>(share->ptr());
+	}
 
-	if (offset >= region->bytes())
+	if (offset >= msize)
 	{
 		m_console.printf("Invalid offset\n");
-		return;
+		return true;
 	}
-	if ((length <= 0) || ((length + offset) >= region->bytes()))
-		length = region->bytes() - offset;
+	if ((length <= 0) || ((length + offset) >= msize))
+		length = msize - offset;
 
 	// open the file
 	std::string filename(params[0]);
@@ -2295,7 +2320,7 @@ void debugger_commands::execute_loadregion(const std::vector<std::string_view> &
 	if (!f)
 	{
 		m_console.printf("Error opening file '%s'\n", params[0]);
-		return;
+		return true;
 	}
 
 	fseek(f, 0L, SEEK_END);
@@ -2306,10 +2331,22 @@ void debugger_commands::execute_loadregion(const std::vector<std::string_view> &
 	if (length >= size)
 		length = size;
 
-	fread(region->base() + offset, 1, length, f);
+	fread(base + offset, 1, length, f);
 
 	fclose(f);
 	m_console.printf("Data loaded successfully to memory : 0x%X to 0x%X\n", offset, offset + length - 1);
+
+	return true;
+}
+
+
+/*-------------------------------------------------
+    execute_loadregion - execute the load command on region memory
+-------------------------------------------------*/
+
+void debugger_commands::execute_loadregion(const std::vector<std::string_view> &params)
+{
+	execute_load(-1, std::vector<std::string_view>{ params[0], std::string(params[1]) + std::string(params[3]) + ".m", params[2] });
 }
 
 
@@ -2319,7 +2356,10 @@ void debugger_commands::execute_loadregion(const std::vector<std::string_view> &
 
 void debugger_commands::execute_dump(int spacenum, const std::vector<std::string_view> &params)
 {
-	// validate parameters
+	if (execute_dump_try_memory(params))
+		return;
+
+		// validate parameters
 	address_space *space;
 	u64 offset;
 	if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset))
@@ -2480,8 +2520,21 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string
     execute_dumpmemory - execute the dump command on memory
 -------------------------------------------------*/
 
-void debugger_commands::execute_dumpmemory(const std::vector<std::string_view> &params)
+bool debugger_commands::execute_dump_try_memory(const std::vector<std::string_view> &params)
 {
+	u64 offset = u64(-1);
+	memory_region *region = nullptr;
+	memory_share *share = nullptr;
+	if (!m_console.validate_address_with_memory_parameter(params[1], offset, region, share))
+		return false;
+
+	u64 length;
+	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
+		return true; // not memory case
+
+	// ...
+
+	return true;
 }
 
 //-------------------------------------------------
@@ -2490,6 +2543,9 @@ void debugger_commands::execute_dumpmemory(const std::vector<std::string_view> &
 
 void debugger_commands::execute_strdump(int spacenum, const std::vector<std::string_view> &params)
 {
+	if (execute_strdump_try_memory(params))
+		return;
+
 	// validate parameters
 	u64 offset;
 	if (!m_console.validate_number_parameter(params[1], offset))
@@ -2663,8 +2719,21 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str
     execute_strdumpmemory - execute the strdump command on memory
 -------------------------------------------------*/
 
-void debugger_commands::execute_strdumpmemory(const std::vector<std::string_view> &params)
+bool debugger_commands::execute_strdump_try_memory(const std::vector<std::string_view> &params)
 {
+	u64 offset = u64(-1);
+	memory_region *region = nullptr;
+	memory_share *share = nullptr;
+	if (!m_console.validate_address_with_memory_parameter(params[1], offset, region, share))
+		return false; // not memory case
+
+	u64 length;
+	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
+		return true;
+
+	// ...
+
+	return true;
 }
 
 
@@ -3169,6 +3238,9 @@ void debugger_commands::execute_cheatundo(const std::vector<std::string_view> &p
 
 void debugger_commands::execute_find(int spacenum, const std::vector<std::string_view> &params)
 {
+	if (execute_find_try_memory(params))
+		return;
+
 	u64 offset, length;
 	address_space *space;
 
@@ -3296,8 +3368,21 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string
     execute_findmemory - execute the find command on memory
 -------------------------------------------------*/
 
-void debugger_commands::execute_findmemory(const std::vector<std::string_view> &params)
+bool debugger_commands::execute_find_try_memory(const std::vector<std::string_view> &params)
 {
+	u64 offset = u64(-1);
+	memory_region *region = nullptr;
+	memory_share *share = nullptr;
+	if (!m_console.validate_address_with_memory_parameter(params[0], offset, region, share))
+		return false; // not memory case
+
+	u64 length;
+	if (offset == u64(-1) || !m_console.validate_number_parameter(params[1], length) || (region == nullptr && share == nullptr))
+		return true;
+
+	// ...
+
+	return true;
 }
 
 
@@ -3307,6 +3392,9 @@ void debugger_commands::execute_findmemory(const std::vector<std::string_view> &
 
 void debugger_commands::execute_fill(int spacenum, const std::vector<std::string_view> &params)
 {
+	if (execute_fill_try_memory(params))
+		return;
+
 	u64 offset, length;
 	address_space *space;
 
@@ -3413,8 +3501,21 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string
     execute_fillmemory - execute the fill command on memory
 -------------------------------------------------*/
 
-void debugger_commands::execute_fillmemory(const std::vector<std::string_view> &params)
+bool debugger_commands::execute_fill_try_memory(const std::vector<std::string_view> &params)
 {
+	u64 offset = u64(-1);
+	memory_region *region = nullptr;
+	memory_share *share = nullptr;
+	if (!m_console.validate_address_with_memory_parameter(params[0], offset, region, share))
+		return false; // not memory case
+
+	u64 length;
+	if (offset == u64(-1) || !m_console.validate_number_parameter(params[1], length) || (region == nullptr && share == nullptr))
+		return true;
+
+	// ...
+
+	return true;
 }
 
 
diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h
index b9a5eaeda8862..0836790e404a3 100644
--- a/src/emu/debug/debugcmd.h
+++ b/src/emu/debug/debugcmd.h
@@ -127,24 +127,24 @@ class debugger_commands
 	void execute_stateload(const std::vector<std::string_view> &params);
 	void execute_rewind(const std::vector<std::string_view> &params);
 	void execute_save(int spacenum, const std::vector<std::string_view> &params);
-	void execute_savememory(const std::vector<std::string_view> &params);
+	bool execute_save_try_memory(const std::vector<std::string_view> &params);
 	void execute_saveregion(const std::vector<std::string_view> &params);
 	void execute_load(int spacenum, const std::vector<std::string_view> &params);
-	void execute_loadmemory(const std::vector<std::string_view> &params);
+	bool execute_load_try_memory(const std::vector<std::string_view> &params);
 	void execute_loadregion(const std::vector<std::string_view> &params);
 	void execute_dump(int spacenum, const std::vector<std::string_view> &params);
-	void execute_dumpmemory(const std::vector<std::string_view> &params);
+	bool execute_dump_try_memory(const std::vector<std::string_view> &params);
 	void execute_strdump(int spacenum, const std::vector<std::string_view> &params);
-	void execute_strdumpmemory(const std::vector<std::string_view> &params);
+	bool execute_strdump_try_memory(const std::vector<std::string_view> &params);
 	void execute_cheatrange(bool init, const std::vector<std::string_view> &params);
 	void execute_cheatnext(bool initial, const std::vector<std::string_view> &params);
 	void execute_cheatlist(const std::vector<std::string_view> &params);
 	void execute_cheatundo(const std::vector<std::string_view> &params);
 	void execute_dasm(const std::vector<std::string_view> &params);
 	void execute_find(int spacenum, const std::vector<std::string_view> &params);
-	void execute_findmemory(const std::vector<std::string_view> &params);
+	bool execute_find_try_memory(const std::vector<std::string_view> &params);
 	void execute_fill(int spacenum, const std::vector<std::string_view> &params);
-	void execute_fillmemory(const std::vector<std::string_view> &params);
+	bool execute_fill_try_memory(const std::vector<std::string_view> &params);
 	void execute_trace(const std::vector<std::string_view> &params, bool trace_over);
 	void execute_traceflush(const std::vector<std::string_view> &params);
 	void execute_history(const std::vector<std::string_view> &params);
diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp
index 1042766aa8721..245ed7b66f02a 100644
--- a/src/emu/debug/debugcon.cpp
+++ b/src/emu/debug/debugcon.cpp
@@ -24,6 +24,7 @@
 #include <cctype>
 #include <fstream>
 #include <iterator>
+#include <regex>
 
 
 /***************************************************************************
@@ -883,7 +884,7 @@ bool debugger_console::validate_device_space_parameter(std::string_view param, i
 /// optionally followed by a colon and a device identifier.  If the
 /// device identifier is not presnt, the current CPU with debugger focus
 /// is assumed.  See #validate_device_parameter for information on how
-/// device parametersare interpreted.
+/// device parameters are interpreted.
 /// \param [in] The parameter string.
 /// \param [in] spacenum The default address space index.  If negative,
 ///   the first address space exposed by the device (i.e. the address
@@ -916,6 +917,37 @@ bool debugger_console::validate_target_address_parameter(std::string_view param,
 }
 
 
+/// \brief Validate a parameter as a address with memory region or share name
+///
+/// Validates a parameter as a address with memory region or share tag and
+//  ... .
+/// \param [in] The parameter string.
+/// \param [out] addr The address on success, or unchanged on failure.
+/// \return true if the parameter refers to a memory region in the
+///   current system, or false otherwise.
+bool debugger_console::validate_address_with_memory_parameter(std::string_view param, u64 &addr, memory_region *&region, memory_share *&share)
+{
+	std::string str(param);
+	std::regex re("^([^:]+)(:.+)\\.([ms])$");
+	std::smatch m;
+	if (std::regex_match(str, m, re))
+	{
+		if ('m' == m[3])
+			validate_memory_region_parameter(m.str(2), region);
+		else if ('s' == m[3])
+			validate_memory_share_parameter(m.str(2), share);
+		else
+			return false;
+
+		validate_number_parameter(m.str(1), addr);
+
+		return true;
+	}
+
+	return false;
+}
+
+
 /// \brief Validate a parameter as a memory region
 ///
 /// Validates a parameter as a memory region tag and retrieves the
diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h
index 78ee1d9bb8dd2..09fea9fbfe781 100644
--- a/src/emu/debug/debugcon.h
+++ b/src/emu/debug/debugcon.h
@@ -130,6 +130,9 @@ class debugger_console
 	// validates a parameter as a target address and retrieves the given address space and address
 	bool validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr);
 
+	// validates a parameter as a address with memory region or share name and ...
+	bool validate_address_with_memory_parameter(std::string_view param, u64 &addr, memory_region *&region, memory_share *&share);
+
 	// validates a parameter as a memory region name and retrieves the given region
 	bool validate_memory_region_parameter(std::string_view param, memory_region *&result);
 

From 35f67f807d8e68787881fa1a1dbc0af1ed79725a Mon Sep 17 00:00:00 2001
From: Andrei Holub <andrei.holub@gmail.com>
Date: Sat, 7 Jun 2025 10:36:41 -0400
Subject: [PATCH 4/5] implement fill/find

---
 src/emu/debug/debugcmd.cpp | 235 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 231 insertions(+), 4 deletions(-)

diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 04585fce3b1e8..35b6cfe060c91 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -28,6 +28,7 @@
 #include "softlist.h"
 
 #include "corestr.h"
+#include "multibyte.h"
 
 #include <algorithm>
 #include <cctype>
@@ -2526,11 +2527,11 @@ bool debugger_commands::execute_dump_try_memory(const std::vector<std::string_vi
 	memory_region *region = nullptr;
 	memory_share *share = nullptr;
 	if (!m_console.validate_address_with_memory_parameter(params[1], offset, region, share))
-		return false;
+		return false; // not memory case
 
 	u64 length;
 	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
-		return true; // not memory case
+		return true;
 
 	// ...
 
@@ -2715,6 +2716,7 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str
 	fclose(f);
 	m_console.printf("Data dumped successfully\n");
 }
+
 /*-------------------------------------------------
     execute_strdumpmemory - execute the strdump command on memory
 -------------------------------------------------*/
@@ -3380,7 +3382,120 @@ bool debugger_commands::execute_find_try_memory(const std::vector<std::string_vi
 	if (offset == u64(-1) || !m_console.validate_number_parameter(params[1], length) || (region == nullptr && share == nullptr))
 		return true;
 
-	// ...
+	u32 msize;
+	u8 *base;
+	bool is_le;
+	if (region != nullptr)
+	{
+		msize = region->bytes();
+		base = region->base();
+		is_le = region->endianness() == ENDIANNESS_LITTLE;
+	}
+	else // if (share != nullptr)
+	{
+		msize = share->bytes();
+		base = reinterpret_cast<u8 *>(share->ptr());
+		is_le = share->endianness() == ENDIANNESS_LITTLE;
+	}
+
+	if (offset >= msize)
+	{
+		m_console.printf("Invalid offset\n");
+		return true;
+	}
+	if ((length <= 0) || ((length + offset) >= msize))
+		length = msize - offset;
+
+	// further validation
+	u64 const endoffset = offset + length - 1;
+	int cur_data_size = 1;
+
+	// parse the data parameters
+	u64 data_to_find[256];
+	u8 data_size[256];
+	int data_count = 0;
+	for (int i = 2; i < params.size(); i++)
+	{
+		std::string_view pdata = params[i];
+
+		if (!pdata.empty() && pdata.front() == '"' && pdata.back() == '"') // check for a string
+		{
+			auto const pdatalen = params[i].length() - 1;
+			for (int j = 1; j < pdatalen; j++)
+			{
+				data_to_find[data_count] = pdata[j];
+				data_size[data_count++] = 1;
+			}
+		}
+		else // otherwise, validate as a number
+		{
+			// check for a 'b','w','d',or 'q' prefix
+			data_size[data_count] = cur_data_size;
+			if (pdata.length() >= 2)
+			{
+				if (tolower(u8(pdata[0])) == 'b' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 1; pdata.remove_prefix(2); }
+				if (tolower(u8(pdata[0])) == 'w' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 2; pdata.remove_prefix(2); }
+				if (tolower(u8(pdata[0])) == 'd' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 4; pdata.remove_prefix(2); }
+				if (tolower(u8(pdata[0])) == 'q' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 8; pdata.remove_prefix(2); }
+			}
+
+			// look for a wildcard
+			if (pdata == "?")
+				data_size[data_count++] |= 0x10;
+
+			// otherwise, validate as a number
+			else if (!m_console.validate_number_parameter(pdata, data_to_find[data_count++]))
+				return true;
+		}
+	}
+
+	// now search
+	int found = 0;
+	for (u64 i = offset; i <= endoffset; i += data_size[0])
+	{
+		int suboffset = 0;
+		bool match = true;
+
+		// find the entire string
+		for (int j = 0; j < data_count && match; j++)
+		{
+			offs_t address = i + suboffset;
+			switch (data_size[j])
+			{
+			case 1:
+				match = u8(data_to_find[j]) == base[address];
+				break;
+
+			case 2:
+				match = u16(data_to_find[j]) == (is_le ? get_u16le(&base[address]) : get_u16be(&base[address]));
+				break;
+
+			case 4:
+				match = u32(data_to_find[j]) == (is_le ? get_u32le(&base[address]) : get_u32be(&base[address]));
+				break;
+
+			case 8:
+				match = u64(data_to_find[j]) == (is_le ? get_u64le(&base[address]) : get_u64be(&base[address]));
+				break;
+
+			default:
+				// all other cases are wildcards
+				break;
+			}
+			suboffset += data_size[j] & 0x0f;
+		}
+
+		// did we find it?
+		if (match)
+		{
+			found++;
+			m_console.printf("Found at %04X\n", i);
+		}
+	}
+
+	// print something if not found
+	if (found == 0)
+		m_console.printf("Not found\n");
 
 	return true;
 }
@@ -3513,7 +3628,119 @@ bool debugger_commands::execute_fill_try_memory(const std::vector<std::string_vi
 	if (offset == u64(-1) || !m_console.validate_number_parameter(params[1], length) || (region == nullptr && share == nullptr))
 		return true;
 
-	// ...
+	u32 msize;
+	u8 *base;
+	bool is_le;
+	if (region != nullptr)
+	{
+		msize = region->bytes();
+		base = region->base();
+		is_le = region->endianness() == ENDIANNESS_LITTLE;
+	}
+	else // if (share != nullptr)
+	{
+		msize = share->bytes();
+		base = reinterpret_cast<u8 *>(share->ptr());
+		is_le = share->endianness() == ENDIANNESS_LITTLE;
+	}
+
+	if (offset >= msize)
+	{
+		m_console.printf("Invalid offset\n");
+		return true;
+	}
+	if ((length <= 0) || ((length + offset) >= msize))
+		length = msize - offset;
+
+	// further validation
+	int cur_data_size = 1;
+
+	// parse the data parameters
+	u64 fill_data[256];
+	u8 fill_data_size[256];
+	int data_count = 0;
+	for (int i = 2; i < params.size(); i++)
+	{
+		std::string_view pdata = params[i];
+
+		// check for a string
+		if (!pdata.empty() && pdata.front() == '"' && pdata.back() == '"')
+		{
+			auto const pdatalen = pdata.length() - 1;
+			for (int j = 1; j < pdatalen; j++)
+			{
+				fill_data[data_count] = pdata[j];
+				fill_data_size[data_count++] = 1;
+			}
+		}
+
+		// otherwise, validate as a number
+		else
+		{
+			// check for a 'b','w','d',or 'q' prefix
+			fill_data_size[data_count] = cur_data_size;
+			if (pdata.length() >= 2)
+			{
+				if (tolower(u8(pdata[0])) == 'b' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 1; pdata.remove_prefix(2); }
+				if (tolower(u8(pdata[0])) == 'w' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 2; pdata.remove_prefix(2); }
+				if (tolower(u8(pdata[0])) == 'd' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 4; pdata.remove_prefix(2); }
+				if (tolower(u8(pdata[0])) == 'q' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 8; pdata.remove_prefix(2); }
+			}
+
+			// validate as a number
+			if (!m_console.validate_number_parameter(pdata, fill_data[data_count++]))
+				return true;
+		}
+	}
+	if (data_count == 0)
+		return true;
+
+	// now fill memory
+	u64 count = length;
+	while (count != 0)
+	{
+		// write the entire string
+		for (int j = 0; j < data_count; j++)
+		{
+			offs_t address = offset;
+			switch (fill_data_size[j])
+			{
+			case 1:
+				base[address] = u8(fill_data[j]);
+				break;
+
+			case 2:
+				if (is_le)
+					put_u16le(&base[address], u16(fill_data[j]));
+				else
+					put_u16be(&base[address], u16(fill_data[j]));
+				break;
+
+			case 4:
+				if (is_le)
+					put_u32le(&base[address], u32(fill_data[j]));
+				else
+					put_u32be(&base[address], u32(fill_data[j]));
+				break;
+
+			case 8:
+				if (is_le)
+					put_u64le(&base[address], u64(fill_data[j]));
+				else
+					put_u64be(&base[address], u64(fill_data[j]));
+				break;
+			}
+
+			offset += fill_data_size[j];
+			if (count <= fill_data_size[j])
+			{
+				count = 0;
+				break;
+			}
+			else
+				count -= fill_data_size[j];
+		}
+	}
 
 	return true;
 }

From 4b2232119c705ba450aa20937ba8d0e54c0b9e38 Mon Sep 17 00:00:00 2001
From: Andrei Holub <andrei.holub@gmail.com>
Date: Sat, 7 Jun 2025 21:30:48 -0400
Subject: [PATCH 5/5] implement dump/strdump

---
 src/emu/debug/debugcmd.cpp | 348 ++++++++++++++++++++++++++++++++++---
 src/emu/debug/debugcon.cpp |   7 +-
 src/emu/debug/debugcon.h   |   2 +-
 3 files changed, 333 insertions(+), 24 deletions(-)

diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 35b6cfe060c91..3e1a158d3920f 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -2360,7 +2360,7 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string
 	if (execute_dump_try_memory(params))
 		return;
 
-		// validate parameters
+	// validate parameters
 	address_space *space;
 	u64 offset;
 	if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset))
@@ -2533,7 +2533,153 @@ bool debugger_commands::execute_dump_try_memory(const std::vector<std::string_vi
 	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
 		return true;
 
-	// ...
+	u64 width = 0;
+	if (params.size() > 3 && !m_console.validate_number_parameter(params[3], width))
+		return true;
+
+	bool ascii = true;
+	if (params.size() > 4 && !m_console.validate_boolean_parameter(params[4], ascii))
+		return true;
+
+	u64 rowsize = 16;
+	if (params.size() > 5 && !m_console.validate_number_parameter(params[5], rowsize))
+		return true;
+
+	int shift = 0;
+	u64 granularity = shift >= 0 ? 1 : 1 << -shift;
+
+	u32 msize;
+	u8 *base;
+	bool be;
+	if (region != nullptr)
+	{
+		msize = region->bytes();
+		base = region->base();
+		be = region->endianness() == ENDIANNESS_BIG;
+		if (width == 0)
+			width = region->bytewidth();
+	}
+	else // if (share != nullptr)
+	{
+		msize = share->bytes();
+		base = reinterpret_cast<u8 *>(share->ptr());
+		be = share->endianness() == ENDIANNESS_BIG;
+		if (width == 0)
+			width = share->bytewidth();
+	}
+
+	if (offset >= msize)
+	{
+		m_console.printf("Invalid offset\n");
+		return true;
+	}
+	if ((length <= 0) || ((length + offset) >= msize))
+		length = msize - offset;
+
+	// further validation
+	if (width != 1 && width != 2 && width != 4 && width != 8)
+	{
+		m_console.printf("Invalid width! (must be 1,2,4 or 8)\n");
+		return true;
+	}
+	if (width < granularity)
+	{
+		m_console.printf("Invalid width! (must be at least %d)\n", granularity);
+		return true;
+	}
+	if (rowsize == 0 || (rowsize % width) != 0)
+	{
+		m_console.printf("Invalid row size! (must be a positive multiple of %d)\n", width);
+		return true;
+	}
+
+	u64 endoffset = offset + length - 1;
+
+	// open the file
+	std::string filename(params[0]);
+	FILE *const f = fopen(filename.c_str(), "w");
+	if (!f)
+	{
+		m_console.printf("Error opening file '%s'\n", params[0]);
+		return true;
+	}
+
+	// now write the data out
+	util::ovectorstream output;
+	output.reserve(200);
+
+	const unsigned delta = (shift >= 0) ? (width << shift) : (width >> -shift);
+
+	for (u64 i = offset; i <= endoffset; i += rowsize)
+	{
+		output.clear();
+		output.rdbuf()->clear();
+
+		// print the address
+		util::stream_format(output, "%0*X: ", 8, i);
+
+		// print the bytes
+		for (u64 j = 0; j < rowsize; j += delta)
+		{
+			if (i + j <= endoffset)
+			{
+				switch (width)
+				{
+				case 8:
+					util::stream_format(output, " %016X", get_u64be(&base[i+j]));
+					break;
+				case 4:
+					util::stream_format(output, " %08X", get_u32be(&base[i+j]));
+					break;
+				case 2:
+					util::stream_format(output, " %04X", get_u16be(&base[i+j]));
+					break;
+				case 1:
+					util::stream_format(output, " %02X", base[i+j]);
+					break;
+				}
+			}
+			else
+				util::stream_format(output, " %*s", width * 2, "");
+		}
+
+		// print the ASCII
+		if (ascii)
+		{
+			util::stream_format(output, "  ");
+			for (u64 j = 0; j < rowsize && (i + j) <= endoffset; j += delta)
+			{
+				u64 data = 0;
+				switch (width)
+				{
+				case 8:
+					data = get_u64be(&base[i+j]);
+					break;
+				case 4:
+					data = get_u32be(&base[i+j]);
+					break;
+				case 2:
+					data = get_u16be(&base[i+j]);
+					break;
+				case 1:
+					data = base[i+j];
+					break;
+				}
+				for (unsigned int b = 0; b != width; b++) {
+					u8 byte = data >> (8 * (be ? (width-1-b) : b));
+					util::stream_format(output, "%c", (byte >= 32 && byte < 127) ? byte : '.');
+				}
+			}
+		}
+
+		// output the result
+		auto const &text = output.vec();
+		fprintf(f, "%.*s\n", int(unsigned(text.size())), &text[0]);
+	}
+
+	// close the file
+	fclose(f);
+	m_console.printf("Data dumped successfully\n");
 
 	return true;
 }
@@ -2733,7 +2879,167 @@ bool debugger_commands::execute_strdump_try_memory(const std::vector<std::string
 	if (offset == u64(-1) || !m_console.validate_number_parameter(params[2], length) || (region == nullptr && share == nullptr))
 		return true;
 
-	// ...
+	u64 term = 0;
+	if (params.size() > 3 && !m_console.validate_number_parameter(params[3], term))
+		return true;
+
+	// further validation
+	if (term >= 0x100 && term != u64(-0x80))
+	{
+		m_console.printf("Invalid termination character\n");
+		return true;
+	}
+
+	// open the file
+	std::string filename(params[0]);
+	FILE *f = fopen(filename.c_str(), "w");
+	if (!f)
+	{
+		m_console.printf("Error opening file '%s'\n", params[0]);
+		return true;
+	}
+
+	u32 msize;
+	u8 *base;
+	bool be;
+	u64 width;
+	if (region != nullptr)
+	{
+		msize = region->bytes();
+		base = region->base();
+		be = region->endianness() == ENDIANNESS_BIG;
+		width = region->bytewidth();
+	}
+	else // if (share != nullptr)
+	{
+		msize = share->bytes();
+		base = reinterpret_cast<u8 *>(share->ptr());
+		be = share->endianness() == ENDIANNESS_BIG;
+		width = share->bytewidth();
+	}
+
+	if (offset >= msize)
+	{
+		m_console.printf("Invalid offset\n");
+		return true;
+	}
+	if ((length <= 0) || ((length + offset) >= msize))
+		length = msize - offset;
+
+	// now write the data out
+	util::ovectorstream output;
+	output.reserve(200);
+
+	bool terminated = true;
+	while (length-- != 0)
+	{
+		if (terminated)
+		{
+			terminated = false;
+			output.clear();
+			output.rdbuf()->clear();
+
+			// print the address
+			util::stream_format(output, "%0*X: \"", 8, offset);
+		}
+
+		// get the character data
+		u64 data = 0;
+		offs_t curaddr = offset;
+		switch (width)
+		{
+		case 1:
+			data = base[curaddr];
+			break;
+
+		case 2:
+			data = be ? get_u16be(&base[curaddr]) : get_u16le(&base[curaddr]);
+			break;
+
+		case 4:
+			data = be ? get_u32be(&base[curaddr]) : get_u32le(&base[curaddr]);
+			break;
+
+		case 8:
+			data = be ? get_u64be(&base[curaddr]) : get_u64le(&base[curaddr]);
+			break;
+		}
+
+		// print the characters
+		for (int n = 0; n < width; n++)
+		{
+			// check for termination within word
+			if (terminated)
+			{
+				terminated = false;
+
+				// output the result
+				auto const &text = output.vec();
+				fprintf(f, "%.*s\"\n", int(unsigned(text.size())), &text[0]);
+				output.clear();
+				output.rdbuf()->clear();
+
+				// print the address
+				util::stream_format(output, "%0*X.%d: \"", 8, offset, n);
+			}
+
+			u8 ch = data & 0xff;
+			data >>= 8;
+
+			// check for termination
+			if (term == u64(-0x80))
+			{
+				if (BIT(ch, 7))
+				{
+					terminated = true;
+					ch &= 0x7f;
+				}
+			}
+			else if (ch == term)
+			{
+				terminated = true;
+				continue;
+			}
+
+			// check for non-ASCII characters
+			if (ch < 0x20 || ch >= 0x7f)
+			{
+				// use special or octal escape
+				if (ch >= 0x07 && ch <= 0x0d)
+					util::stream_format(output, "\\%c", "abtnvfr"[ch - 0x07]);
+				else
+					util::stream_format(output, "\\%03o", ch);
+			}
+			else
+			{
+				if (ch == '"' || ch == '\\')
+					output << '\\';
+				output << char(ch);
+			}
+		}
+
+		if (terminated)
+		{
+			// output the result
+			auto const &text = output.vec();
+			fprintf(f, "%.*s\"\n", int(unsigned(text.size())), &text[0]);
+			output.clear();
+			output.rdbuf()->clear();
+		}
+
+		offset += width;
+	}
+
+	if (!terminated)
+	{
+		// output the result
+		auto const &text = output.vec();
+		fprintf(f, "%.*s\"\\\n", int(unsigned(text.size())), &text[0]);
+	}
+
+	// close the file
+	fclose(f);
+	m_console.printf("Data dumped successfully\n");
 
 	return true;
 }
@@ -3384,18 +3690,18 @@ bool debugger_commands::execute_find_try_memory(const std::vector<std::string_vi
 
 	u32 msize;
 	u8 *base;
-	bool is_le;
+	bool be;
 	if (region != nullptr)
 	{
 		msize = region->bytes();
 		base = region->base();
-		is_le = region->endianness() == ENDIANNESS_LITTLE;
+		be = region->endianness() == ENDIANNESS_BIG;
 	}
 	else // if (share != nullptr)
 	{
 		msize = share->bytes();
 		base = reinterpret_cast<u8 *>(share->ptr());
-		is_le = share->endianness() == ENDIANNESS_LITTLE;
+		be = share->endianness() == ENDIANNESS_BIG;
 	}
 
 	if (offset >= msize)
@@ -3467,15 +3773,15 @@ bool debugger_commands::execute_find_try_memory(const std::vector<std::string_vi
 				break;
 
 			case 2:
-				match = u16(data_to_find[j]) == (is_le ? get_u16le(&base[address]) : get_u16be(&base[address]));
+				match = u16(data_to_find[j]) == (be ? get_u16be(&base[address]) : get_u16le(&base[address]));
 				break;
 
 			case 4:
-				match = u32(data_to_find[j]) == (is_le ? get_u32le(&base[address]) : get_u32be(&base[address]));
+				match = u32(data_to_find[j]) == (be ? get_u32be(&base[address]) : get_u32le(&base[address]));
 				break;
 
 			case 8:
-				match = u64(data_to_find[j]) == (is_le ? get_u64le(&base[address]) : get_u64be(&base[address]));
+				match = u64(data_to_find[j]) == (be ? get_u64be(&base[address]) : get_u64le(&base[address]));
 				break;
 
 			default:
@@ -3630,18 +3936,18 @@ bool debugger_commands::execute_fill_try_memory(const std::vector<std::string_vi
 
 	u32 msize;
 	u8 *base;
-	bool is_le;
+	bool be;
 	if (region != nullptr)
 	{
 		msize = region->bytes();
 		base = region->base();
-		is_le = region->endianness() == ENDIANNESS_LITTLE;
+		be = region->endianness() == ENDIANNESS_BIG;
 	}
 	else // if (share != nullptr)
 	{
 		msize = share->bytes();
 		base = reinterpret_cast<u8 *>(share->ptr());
-		is_le = share->endianness() == ENDIANNESS_LITTLE;
+		be = share->endianness() == ENDIANNESS_BIG;
 	}
 
 	if (offset >= msize)
@@ -3710,24 +4016,24 @@ bool debugger_commands::execute_fill_try_memory(const std::vector<std::string_vi
 				break;
 
 			case 2:
-				if (is_le)
-					put_u16le(&base[address], u16(fill_data[j]));
-				else
+				if (be)
 					put_u16be(&base[address], u16(fill_data[j]));
+				else
+					put_u16le(&base[address], u16(fill_data[j]));
 				break;
 
 			case 4:
-				if (is_le)
-					put_u32le(&base[address], u32(fill_data[j]));
-				else
+				if (be)
 					put_u32be(&base[address], u32(fill_data[j]));
+				else
+					put_u32le(&base[address], u32(fill_data[j]));
 				break;
 
 			case 8:
-				if (is_le)
-					put_u64le(&base[address], u64(fill_data[j]));
-				else
+				if (be)
 					put_u64be(&base[address], u64(fill_data[j]));
+				else
+					put_u64le(&base[address], u64(fill_data[j]));
 				break;
 			}
 
diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp
index 245ed7b66f02a..f9076dda5235e 100644
--- a/src/emu/debug/debugcon.cpp
+++ b/src/emu/debug/debugcon.cpp
@@ -919,10 +919,13 @@ bool debugger_console::validate_target_address_parameter(std::string_view param,
 
 /// \brief Validate a parameter as a address with memory region or share name
 ///
-/// Validates a parameter as a address with memory region or share tag and
-//  ... .
+/// Validates a parameter as a address with memory region or share tag. addres
+/// parameters stays unchanged if invalid and requires additional validation on
+/// the caller side.
 /// \param [in] The parameter string.
 /// \param [out] addr The address on success, or unchanged on failure.
+/// \param [out] region The region on success, or unchanged on failure.
+/// \param [out] share The share on success, or unchanged on failure.
 /// \return true if the parameter refers to a memory region in the
 ///   current system, or false otherwise.
 bool debugger_console::validate_address_with_memory_parameter(std::string_view param, u64 &addr, memory_region *&region, memory_share *&share)
diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h
index 09fea9fbfe781..b1cef0f7c847d 100644
--- a/src/emu/debug/debugcon.h
+++ b/src/emu/debug/debugcon.h
@@ -130,7 +130,7 @@ class debugger_console
 	// validates a parameter as a target address and retrieves the given address space and address
 	bool validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr);
 
-	// validates a parameter as a address with memory region or share name and ...
+	// validates a parameter as a address with memory region or share name and retrieves the given address and region or share
 	bool validate_address_with_memory_parameter(std::string_view param, u64 &addr, memory_region *&region, memory_share *&share);
 
 	// validates a parameter as a memory region name and retrieves the given region