summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-11-18 19:33:02 -0500
committer AJR <ajrhacker@users.noreply.github.com>2020-11-18 19:33:13 -0500
commit73a555358889524404fec4851058a3b72cc13de6 (patch)
tree5505d74a0d8afa9680cf79c0655b4b6a0142aca1 /src/emu/debug
parent3a4506bd3e9e41db89aeafd4400ba3a0b338e8b4 (diff)
Add strdump debugger command for dumping memory as ASCII strings
Diffstat (limited to 'src/emu/debug')
-rw-r--r--src/emu/debug/debugcmd.cpp180
-rw-r--r--src/emu/debug/debugcmd.h1
-rw-r--r--src/emu/debug/debughlp.cpp22
3 files changed, 203 insertions, 0 deletions
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 9b33eac7b45..a5856a9b794 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -251,6 +251,11 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
m_console.register_command("dumpi", CMDFLAG_NONE, AS_IO, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2));
m_console.register_command("dumpo", CMDFLAG_NONE, AS_OPCODES, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2));
+ m_console.register_command("strdump", CMDFLAG_NONE, AS_PROGRAM, 3, 5, std::bind(&debugger_commands::execute_strdump, this, _1, _2));
+ m_console.register_command("strdumpd", CMDFLAG_NONE, AS_DATA, 3, 5, std::bind(&debugger_commands::execute_strdump, this, _1, _2));
+ m_console.register_command("strdumpi", CMDFLAG_NONE, AS_IO, 3, 5, std::bind(&debugger_commands::execute_strdump, this, _1, _2));
+ m_console.register_command("strdumpo", CMDFLAG_NONE, AS_OPCODES, 3, 5, std::bind(&debugger_commands::execute_strdump, this, _1, _2));
+
m_console.register_command("cheatinit", CMDFLAG_NONE, 0, 0, 4, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2));
m_console.register_command("ci", CMDFLAG_NONE, 0, 0, 4, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2));
@@ -2391,6 +2396,181 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa
}
+//-------------------------------------------------
+// execute_strdump - execute the strdump command
+//-------------------------------------------------
+
+void debugger_commands::execute_strdump(int ref, const std::vector<std::string> &params)
+{
+ // validate parameters
+ u64 offset;
+ if (!validate_number_parameter(params[1], offset))
+ return;
+
+ u64 length;
+ if (!validate_number_parameter(params[2], length))
+ return;
+
+ u64 term = 0;
+ if (params.size() > 3 && !validate_number_parameter(params[3], term))
+ return;
+
+ address_space *space;
+ if (!validate_cpu_space_parameter((params.size() > 4) ? params[4].c_str() : nullptr, ref, space))
+ return;
+
+ // further validation
+ if (term >= 0x100 && term != u64(-0x80))
+ {
+ m_console.printf("Invalid termination character\n");
+ return;
+ }
+
+ // open the file
+ FILE *f = fopen(params[0].c_str(), "w");
+ if (!f)
+ {
+ m_console.printf("Error opening file '%s'\n", params[0].c_str());
+ return;
+ }
+
+ const int shift = space->addr_shift();
+ const unsigned delta = (shift >= 0) ? (1 << shift) : 1;
+ const unsigned width = (shift >= 0) ? 1 : (1 << -shift);
+ const bool be = space->endianness() == ENDIANNESS_BIG;
+
+ offset = offset & space->addrmask();
+ if (shift > 0)
+ length >>= shift;
+
+ // now write the data out
+ util::ovectorstream output;
+ output.reserve(200);
+
+ auto dis = space->device().machine().disable_side_effects();
+
+ bool terminated = true;
+ while (length-- != 0)
+ {
+ if (terminated)
+ {
+ terminated = false;
+ output.clear();
+ output.rdbuf()->clear();
+
+ // print the address
+ util::stream_format(output, "%0*X: \"", space->logaddrchars(), offset);
+ }
+
+ // get the character data
+ u64 data = 0;
+ offs_t curaddr = offset;
+ if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr))
+ {
+ switch (width)
+ {
+ case 1:
+ data = space->read_byte(curaddr);
+ break;
+
+ case 2:
+ data = space->read_word(curaddr);
+ if (be)
+ data = swapendian_int16(data);
+ break;
+
+ case 4:
+ data = space->read_dword(curaddr);
+ if (be)
+ data = swapendian_int32(data);
+ break;
+
+ case 8:
+ data = space->read_qword(curaddr);
+ if (be)
+ data = swapendian_int64(data);
+ 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: \"", space->logaddrchars(), 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 += delta;
+ }
+
+ 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");
+}
+
+
/*-------------------------------------------------
execute_cheatinit - initialize the cheat system
-------------------------------------------------*/
diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h
index e2ebec7e2fc..0fad46d7009 100644
--- a/src/emu/debug/debugcmd.h
+++ b/src/emu/debug/debugcmd.h
@@ -151,6 +151,7 @@ private:
void execute_load(int ref, const std::vector<std::string> &params);
void execute_loadregion(int ref, const std::vector<std::string> &params);
void execute_dump(int ref, const std::vector<std::string> &params);
+ void execute_strdump(int ref, const std::vector<std::string> &params);
void execute_cheatinit(int ref, const std::vector<std::string> &params);
void execute_cheatnext(int ref, const std::vector<std::string> &params);
void execute_cheatlist(int ref, const std::vector<std::string> &params);
diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp
index 55e3524f7ef..dc6c204f03f 100644
--- a/src/emu/debug/debughlp.cpp
+++ b/src/emu/debug/debughlp.cpp
@@ -112,10 +112,17 @@ static const help_item static_help_list[] =
" f[ind] <address>,<length>[,<data>[,...]] -- search program memory 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 program memory with data\n"
+ " filld <address>,<length>[,<data>[,...]] -- fill data memory with data\n"
+ " filli <address>,<length>[,<data>[,...][ -- fill I/O memory with data\n"
" dump <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump program memory as text\n"
" dumpd <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump data memory as text\n"
" dumpi <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump I/O memory as text\n"
" dumpo <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump opcodes memory as text\n"
+ " strdump <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from program memory\n"
+ " strdumpd <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from data memory\n"
+ " strdumpi <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from I/O memory\n"
+ " strdumpo <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from opcodes memory\n"
" save <filename>,<address>,<length>[,<CPU>] -- save binary program memory to the given file\n"
" saved <filename>,<address>,<length>[,<CPU>] -- save binary data memory to the given file\n"
" savei <filename>,<address>,<length>[,<CPU>] -- save binary I/O memory to the given file\n"
@@ -646,6 +653,21 @@ static const help_item static_help_list[] =
"to the file 'harddriv.dmp'.\n"
},
{
+ "strdump",
+ "\n"
+ " strdump[{d|i}] <filename>,<address>,<length>[,<term>[,<CPU>]]\n"
+ "\n"
+ "The strdump/strdumpd/strdumpi/strdumpo commands dump memory to the text file specified in the "
+ "<filename> parameter. 'strdump' will dump program space memory, while 'strdumpd' will dump data "
+ "space memory, 'strdumpi' will dump I/O space memory and 'strdumpo' will dump opcodes memory. "
+ "<address> indicates the address of the start of dumping, and <length> indicates how much memory "
+ "to dump. The range <address> through <address>+<length>-1 inclusive will be output to the file. "
+ "By default, the data will be interpreted as a series of null-terminated strings, and the dump "
+ "will have one string on each line and C-style escapes for non-ASCII characters. The optional "
+ "<term> parameter can be used to specify a different character as the string terminator. Finally, "
+ "you can dump memory from another CPU by specifying the <CPU> parameter.\n"
+ },
+ {
"save",
"\n"
" save[{d|i}] <filename>,<address>,<length>[,<CPU>]\n"