summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/dvmemory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/debug/dvmemory.cpp')
-rw-r--r--src/emu/debug/dvmemory.cpp655
1 files changed, 390 insertions, 265 deletions
diff --git a/src/emu/debug/dvmemory.cpp b/src/emu/debug/dvmemory.cpp
index 947c387800b..7c10407822b 100644
--- a/src/emu/debug/dvmemory.cpp
+++ b/src/emu/debug/dvmemory.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/*********************************************************************
- dvmemory.c
+ dvmemory.cpp
Memory debugger view.
@@ -12,35 +12,51 @@
#include "dvmemory.h"
#include "debugcpu.h"
-#include "debugger.h"
#include <algorithm>
-#include <ctype.h>
+#include <cctype>
#include <tuple>
//**************************************************************************
+// HELPER FUNCTIONS
+//**************************************************************************
+
+namespace {
+
+constexpr u8 sanitise_character(u8 ch)
+{
+ // assume ISO-8859-1 (low 256 Unicode codepoints) - tab, soft hyphen, C0 and C1 cause problems
+ return ('\t' == ch) ? ' ' : (0xadU == ch) ? '-' : ((' ' > ch) || (('~' < ch) && (0xa0U > ch))) ? '.' : ch;
+}
+
+} // anonymous namespace
+
+//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-const debug_view_memory::memory_view_pos debug_view_memory::s_memory_pos_table[12] =
+const debug_view_memory::memory_view_pos debug_view_memory::s_memory_pos_table[16] =
{
- /* 0 bytes per chunk: */ { 0, { 0 } },
- /* 1 byte per chunk: 00 11 22 33 44 55 66 77 */ { 3, { 0x04, 0x00, 0x80 } },
- /* 2 bytes per chunk: 0011 2233 4455 6677 */ { 6, { 0x8c, 0x0c, 0x08, 0x04, 0x00, 0x80 } },
- /* 3 bytes per chunk: */ { 0, { 0 } },
- /* 4 bytes per chunk: 00112233 44556677 */ { 12, { 0x9c, 0x9c, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80 } },
- /* 5 bytes per chunk: */ { 0, { 0 } },
- /* 6 bytes per chunk: */ { 0, { 0 } },
- /* 7 bytes per chunk: */ { 0, { 0 } },
- /* 8 bytes per chunk: 0011223344556677 */ { 24, { 0xbc, 0xbc, 0xbc, 0xbc, 0x3c, 0x38, 0x34, 0x30, 0x2c, 0x28, 0x24, 0x20, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80, 0x80, 0x80 } },
- /* 32 bit floating point: */ { 16, { 0 } },
- /* 64 bit floating point: */ { 32, { 0 } },
- /* 80 bit floating point: */ { 32, { 0 } },
+ /* 0 bytes per chunk: */ { 0, 0, { 0 } },
+ /* 1 byte per chunk: 00 11 22 33 44 55 66 77 */ { 1, 3, { 0x04, 0x00, 0x80 } },
+ /* 2 bytes per chunk: 0011 2233 4455 6677 */ { 2, 6, { 0x8c, 0x0c, 0x08, 0x04, 0x00, 0x80 } },
+ /* 3 bytes per chunk: */ { 0, 0, { 0 } },
+ /* 4 bytes per chunk: 00112233 44556677 */ { 4, 12, { 0x9c, 0x9c, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80 } },
+ /* 5 bytes per chunk: */ { 0, 0, { 0 } },
+ /* 6 bytes per chunk: */ { 0, 0, { 0 } },
+ /* 7 bytes per chunk: */ { 0, 0, { 0 } },
+ /* 8 bytes per chunk: 0011223344556677 */ { 8, 24, { 0xbc, 0xbc, 0xbc, 0xbc, 0x3c, 0x38, 0x34, 0x30, 0x2c, 0x28, 0x24, 0x20, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80, 0x80, 0x80 } },
+ /* 32 bit floating point: */ { 4, 16, { 0 } },
+ /* 64 bit floating point: */ { 8, 32, { 0 } },
+ /* 80 bit floating point: */ { 10, 32, { 0 } },
+ /* 8 bit octal: */ { 1, 4, { 0x06, 0x03, 0x00, 0x80 } },
+ /* 16 bit octal: */ { 2, 8, { 0x8f, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x00, 0x80 } },
+ /* 32 bit octal: */ { 4, 15, { 0x9e, 0x9e, 0x1e, 0x1b, 0x18, 0x15, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x00, 0x80, 0x80 } },
+ /* 64 bit octal: */ { 8, 28, { 0xbf, 0xbf, 0xbf, 0x3f, 0x3c, 0x39, 0x36, 0x33, 0x30, 0x2d, 0x2a, 0x27, 0x24, 0x21, 0x1e, 0x1b, 0x18, 0x15, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x00, 0x80, 0x80, 0x80 } },
};
-
//**************************************************************************
// DEBUG VIEW MEMORY SOURCE
//**************************************************************************
@@ -49,39 +65,45 @@ const debug_view_memory::memory_view_pos debug_view_memory::s_memory_pos_table[1
// debug_view_memory_source - constructors
//-------------------------------------------------
-debug_view_memory_source::debug_view_memory_source(const char *name, address_space &space)
- : debug_view_source(name, &space.device()),
- m_space(&space),
- m_memintf(dynamic_cast<device_memory_interface *>(&space.device())),
- m_base(nullptr),
- m_length(0),
- m_offsetxor(0),
- m_endianness(space.endianness()),
- m_prefsize(space.data_width() / 8)
+debug_view_memory_source::debug_view_memory_source(std::string &&name, address_space &space)
+ : debug_view_source(std::move(name), &space.device())
+ , m_space(&space)
+ , m_memintf(dynamic_cast<device_memory_interface *>(&space.device()))
+ , m_base(nullptr)
+ , m_blocklength(0)
+ , m_numblocks(0)
+ , m_blockstride(0)
+ , m_offsetxor(0)
+ , m_endianness(space.endianness())
+ , m_prefsize(space.data_width() / 8)
{
}
-debug_view_memory_source::debug_view_memory_source(const char *name, memory_region &region)
- : debug_view_source(name),
- m_space(nullptr),
- m_memintf(nullptr),
- m_base(region.base()),
- m_length(region.bytes()),
- m_offsetxor(ENDIAN_VALUE_NE_NNE(region.endianness(), 0, region.bytewidth() - 1)),
- m_endianness(region.endianness()),
- m_prefsize(std::min<u8>(region.bytewidth(), 8))
+debug_view_memory_source::debug_view_memory_source(std::string &&name, memory_region &region)
+ : debug_view_source(std::move(name))
+ , m_space(nullptr)
+ , m_memintf(nullptr)
+ , m_base(region.base())
+ , m_blocklength(region.bytes())
+ , m_numblocks(1)
+ , m_blockstride(0)
+ , m_offsetxor(region.endianness() == ENDIANNESS_NATIVE ? 0 : region.bytewidth() - 1)
+ , m_endianness(region.endianness())
+ , m_prefsize(std::min<u8>(region.bytewidth(), 8))
{
}
-debug_view_memory_source::debug_view_memory_source(const char *name, void *base, int element_size, int num_elements)
- : debug_view_source(name),
- m_space(nullptr),
- m_memintf(nullptr),
- m_base(base),
- m_length(element_size * num_elements),
- m_offsetxor(0),
- m_endianness(ENDIANNESS_NATIVE),
- m_prefsize(std::min(element_size, 8))
+debug_view_memory_source::debug_view_memory_source(std::string &&name, void *base, int element_size, int num_elements, int num_blocks, int block_stride)
+ : debug_view_source(std::move(name))
+ , m_space(nullptr)
+ , m_memintf(nullptr)
+ , m_base(base)
+ , m_blocklength(element_size * num_elements)
+ , m_numblocks(num_blocks)
+ , m_blockstride(block_stride)
+ , m_offsetxor(0)
+ , m_endianness(ENDIANNESS_NATIVE)
+ , m_prefsize(std::min(element_size, 8))
{
}
@@ -101,11 +123,13 @@ debug_view_memory::debug_view_memory(running_machine &machine, debug_view_osd_up
m_chunks_per_row(16),
m_bytes_per_chunk(1),
m_steps_per_chunk(1),
- m_data_format(1),
+ m_data_format(data_format::HEX_8BIT),
m_reverse_view(false),
m_ascii_view(true),
m_no_translation(false),
m_edit_enabled(true),
+ m_shift_bits(4),
+ m_address_radix(16),
m_maxaddr(0),
m_bytes_per_row(16),
m_byte_offset(0)
@@ -119,7 +143,7 @@ debug_view_memory::debug_view_memory(running_machine &machine, debug_view_osd_up
// fail if no available sources
enumerate_sources();
- if (m_source_list.count() == 0)
+ if (m_source_list.empty())
throw std::bad_alloc();
// configure the view
@@ -135,49 +159,56 @@ debug_view_memory::debug_view_memory(running_machine &machine, debug_view_osd_up
void debug_view_memory::enumerate_sources()
{
// start with an empty list
- m_source_list.reset();
- std::string name;
+ m_source_list.clear();
+ m_source_list.reserve(machine().save().registration_count());
// first add all the devices' address spaces
- for (device_memory_interface &memintf : memory_interface_iterator(machine().root_device()))
+ for (device_memory_interface &memintf : memory_interface_enumerator(machine().root_device()))
+ {
for (int spacenum = 0; spacenum < memintf.max_space_count(); ++spacenum)
+ {
if (memintf.has_space(spacenum))
{
- address_space &space = memintf.space(spacenum);
- name = string_format("%s '%s' %s space memory", memintf.device().name(), memintf.device().tag(), space.name());
- m_source_list.append(*global_alloc(debug_view_memory_source(name.c_str(), space)));
+ address_space &space(memintf.space(spacenum));
+ m_source_list.emplace_back(
+ std::make_unique<debug_view_memory_source>(
+ util::string_format("%s '%s' %s space memory", memintf.device().name(), memintf.device().tag(), space.name()),
+ space));
}
+ }
+ }
// then add all the memory regions
for (auto &region : machine().memory().regions())
{
- name = string_format("Region '%s'", region.second->name());
- m_source_list.append(*global_alloc(debug_view_memory_source(name.c_str(), *region.second.get())));
+ m_source_list.emplace_back(
+ std::make_unique<debug_view_memory_source>(
+ util::string_format("Region '%s'", region.second->name()),
+ *region.second.get()));
}
- // finally add all global array symbols in alphabetical order
- std::vector<std::tuple<std::string, void *, u32, u32> > itemnames;
- itemnames.reserve(machine().save().registration_count());
-
+ // finally add all global array symbols in ASCII order
+ std::string name;
+ std::size_t const firstsave = m_source_list.size();
for (int itemnum = 0; itemnum < machine().save().registration_count(); itemnum++)
{
- u32 valsize, valcount;
+ u32 valsize, valcount, blockcount, stride;
void *base;
- std::string name_string(machine().save().indexed_item(itemnum, base, valsize, valcount));
+ name = machine().save().indexed_item(itemnum, base, valsize, valcount, blockcount, stride);
// add pretty much anything that's not a timer (we may wish to cull other items later)
// also, don't trim the front of the name, it's important to know which VIA6522 we're looking at, e.g.
- if (strncmp(name_string.c_str(), "timer/", 6))
- itemnames.emplace_back(std::move(name_string), base, valsize, valcount);
+ if (strncmp(name.c_str(), "timer/", 6))
+ m_source_list.emplace_back(std::make_unique<debug_view_memory_source>(std::move(name), base, valsize, valcount, blockcount, stride));
}
-
- std::sort(itemnames.begin(), itemnames.end(), [] (auto const &x, auto const &y) { return std::get<0>(x) < std::get<0>(y); });
-
- for (auto const &item : itemnames)
- m_source_list.append(*global_alloc(debug_view_memory_source(std::get<0>(item).c_str(), std::get<1>(item), std::get<2>(item), std::get<3>(item))));
+ std::sort(
+ std::next(m_source_list.begin(), firstsave),
+ m_source_list.end(),
+ [] (auto const &x, auto const &y) { return 0 > std::strcmp(x->name(), y->name()); });
// reset the source to a known good entry
- set_source(*m_source_list.first());
+ if (!m_source_list.empty())
+ set_source(*m_source_list[0]);
}
@@ -201,12 +232,33 @@ void debug_view_memory::view_notify(debug_view_notification type)
m_bytes_per_chunk = source.m_prefsize;
if (m_bytes_per_chunk > 8)
m_bytes_per_chunk = 8;
- m_data_format = m_bytes_per_chunk;
+ bool octal = source.m_space != nullptr && source.m_space->is_octal();
+ switch (m_bytes_per_chunk)
+ {
+ case 1:
+ m_data_format = octal ? data_format::OCTAL_8BIT : data_format::HEX_8BIT;
+ break;
+
+ case 2:
+ m_data_format = octal ? data_format::OCTAL_16BIT : data_format::HEX_16BIT;
+ break;
+
+ case 4:
+ m_data_format = octal ? data_format::OCTAL_32BIT : data_format::HEX_32BIT;
+ break;
+
+ case 8:
+ m_data_format = octal ? data_format::OCTAL_64BIT : data_format::HEX_64BIT;
+ break;
+ }
+ m_shift_bits = octal ? 3 : 4;
m_steps_per_chunk = source.m_space ? source.m_space->byte_to_address(m_bytes_per_chunk) : m_bytes_per_chunk;
if (source.m_space != nullptr)
m_expression.set_context(&source.m_space->device().debug()->symtable());
else
m_expression.set_context(nullptr);
+ m_address_radix = octal ? 8 : 16;
+ m_expression.set_default_base(m_address_radix);
}
}
@@ -244,6 +296,122 @@ static inline float u64_to_double(u64 value)
}
//-------------------------------------------------
+// generate_row - read one row of data and make a
+// text representation of the chunks
+//-------------------------------------------------
+
+void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char *destmax, debug_view_char *destrow, offs_t address)
+{
+ // get positional data
+ const memory_view_pos &posdata = get_posdata(m_data_format);
+ int spacing = posdata.m_spacing;
+
+ // generate the address
+ char addrtext[20];
+ snprintf(addrtext, 20, m_addrformat.c_str(), address);
+ debug_view_char *dest = destrow + m_section[0].m_pos + 1;
+ for (int ch = 0; addrtext[ch] != 0 && ch < m_section[0].m_width - 1; ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ dest->byte = addrtext[ch];
+
+ // generate the data and the ASCII string
+ std::string chunkascii;
+ if (m_shift_bits != 0)
+ {
+ for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++)
+ {
+ u64 chunkdata;
+ bool ismapped = read_chunk(address, chunknum, chunkdata);
+
+ int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum;
+ dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing;
+ for (int ch = 0; ch < spacing; ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ {
+ u8 shift = posdata.m_shift[ch];
+ if (shift < 64)
+ dest->byte = ismapped ? "0123456789ABCDEF"[BIT(chunkdata, shift, m_shift_bits)] : '*';
+ }
+
+ for (int i = 0; i < m_bytes_per_chunk; i++)
+ {
+ u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1));
+ chunkascii += char(ismapped ? sanitise_character(chval) : '.');
+ }
+ }
+ }
+ else
+ {
+ for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++)
+ {
+ char valuetext[64];
+ u64 chunkdata = 0;
+ extFloat80_t chunkdata80 = { 0, 0 };
+ bool ismapped;
+
+ if (m_data_format != data_format::FLOAT_80BIT)
+ ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata);
+ else
+ ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata80);
+
+ if (ismapped)
+ switch (m_data_format)
+ {
+ case data_format::FLOAT_32BIT:
+ snprintf(valuetext, 64, "%.8g", u32_to_float(u32(chunkdata)));
+ break;
+ case data_format::FLOAT_64BIT:
+ snprintf(valuetext, 64, "%.24g", u64_to_double(chunkdata));
+ break;
+ case data_format::FLOAT_80BIT:
+ {
+ float64_t f64 = extF80M_to_f64(&chunkdata80);
+ snprintf(valuetext, 64, "%.24g", u64_to_double(f64.v));
+ break;
+ }
+ default:
+ break;
+ }
+ else
+ {
+ valuetext[0] = '*';
+ valuetext[1] = 0;
+ }
+
+ int ch;
+ int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum;
+ dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing;
+ // first copy the text
+ for (ch = 0; (ch < spacing) && (valuetext[ch] != 0); ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ dest->byte = valuetext[ch];
+ // then fill with spaces
+ for (; ch < spacing; ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ dest->byte = ' ';
+
+ for (int i = 0; i < m_bytes_per_chunk; i++)
+ {
+ u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1));
+ chunkascii += char(ismapped ? sanitise_character(chval) : '.');
+ }
+ }
+ }
+
+ // generate the ASCII data, but follow the chunks
+ if (m_section[2].m_width > 0)
+ {
+ dest = destrow + m_section[2].m_pos + 1;
+ for (size_t i = 0; i != chunkascii.size(); i++)
+ {
+ if (dest >= destmin && dest < destmax)
+ dest->byte = chunkascii[i];
+ dest++;
+ }
+ }
+}
+
+//-------------------------------------------------
// view_update - update the contents of the
// memory view
//-------------------------------------------------
@@ -256,9 +424,6 @@ void debug_view_memory::view_update()
if (needs_recompute())
recompute();
- // get positional data
- const memory_view_pos &posdata = s_memory_pos_table[m_data_format];
-
// loop over visible rows
for (u32 row = 0; row < m_visible.y; row++)
{
@@ -268,10 +433,9 @@ void debug_view_memory::view_update()
u32 effrow = m_topleft.y + row;
// reset the line of data; section 1 is normal, others are ancillary, cursor is selected
- debug_view_char *dest = destmin;
- for (int ch = 0; ch < m_visible.x; ch++, dest++)
+ u32 effcol = m_topleft.x;
+ for (debug_view_char *dest = destmin; dest != destmax; dest++, effcol++)
{
- u32 effcol = m_topleft.x + ch;
dest->byte = ' ';
dest->attrib = DCA_ANCILLARY;
if (m_section[1].contains(effcol))
@@ -287,96 +451,7 @@ void debug_view_memory::view_update()
{
offs_t addrbyte = m_byte_offset + effrow * m_bytes_per_row;
offs_t address = (source.m_space != nullptr) ? source.m_space->byte_to_address(addrbyte) : addrbyte;
- char addrtext[20];
-
- // generate the address
- sprintf(addrtext, m_addrformat.c_str(), address);
- dest = destrow + m_section[0].m_pos + 1;
- for (int ch = 0; addrtext[ch] != 0 && ch < m_section[0].m_width - 1; ch++, dest++)
- if (dest >= destmin && dest < destmax)
- dest->byte = addrtext[ch];
-
- // generate the data and the ascii string
- std::string chunkascii;
- for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++)
- {
- int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum;
- int spacing = posdata.m_spacing;
-
- if (m_data_format <= 8) {
- u64 chunkdata;
- bool ismapped = read_chunk(address, chunknum, chunkdata);
- dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing;
- for (int ch = 0; ch < posdata.m_spacing; ch++, dest++)
- if (dest >= destmin && dest < destmax)
- {
- u8 shift = posdata.m_shift[ch];
- if (shift < 64)
- dest->byte = ismapped ? "0123456789ABCDEF"[(chunkdata >> shift) & 0x0f] : '*';
- }
- for (int i=0; i < m_bytes_per_chunk; i++) {
- u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1));
- chunkascii += char((ismapped && isprint(chval)) ? chval : '.');
- }
- }
- else {
- int ch;
- char valuetext[64];
- u64 chunkdata = 0;
- floatx80 chunkdata80 = { 0, 0 };
- bool ismapped;
-
- if (m_data_format != 11)
- ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata);
- else
- ismapped = read(m_bytes_per_chunk, address + chunknum * m_steps_per_chunk, chunkdata80);
-
- if (ismapped)
- switch (m_data_format)
- {
- case 9:
- sprintf(valuetext, "%.8g", u32_to_float(u32(chunkdata)));
- break;
- case 10:
- sprintf(valuetext, "%.24g", u64_to_double(chunkdata));
- break;
- case 11:
- float64 f64 = floatx80_to_float64(chunkdata80);
- sprintf(valuetext, "%.24g", u64_to_double(f64));
- break;
- }
- else {
- valuetext[0] = '*';
- valuetext[1] = 0;
- }
-
- dest = destrow + m_section[1].m_pos + 1 + chunkindex * spacing;
- // first copy the text
- for (ch = 0; (ch < spacing) && (valuetext[ch] != 0); ch++, dest++)
- if (dest >= destmin && dest < destmax)
- dest->byte = valuetext[ch];
- // then fill with spaces
- for (; ch < spacing; ch++, dest++)
- if (dest >= destmin && dest < destmax)
- dest->byte = ' ';
-
- for (int i=0; i < m_bytes_per_chunk; i++) {
- u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1));
- chunkascii += char((ismapped && isprint(chval)) ? chval : '.');
- }
- }
- }
-
- // generate the ASCII data, but follow the chunks
- if (m_section[2].m_width > 0)
- {
- dest = destrow + m_section[2].m_pos + 1;
- for (size_t i = 0; i != chunkascii.size(); i++) {
- if (dest >= destmin && dest < destmax)
- dest->byte = chunkascii[i];
- dest++;
- }
- }
+ generate_row(destmin, destmax, destrow, address);
}
}
}
@@ -429,12 +504,12 @@ void debug_view_memory::view_char(int chval)
case DCH_HOME:
pos.m_address -= pos.m_address % m_bytes_per_row;
- pos.m_shift = (m_bytes_per_chunk * 8) - 4;
+ pos.m_shift = get_posdata(m_data_format).m_shift[0] & 0x7f;
break;
case DCH_CTRLHOME:
pos.m_address = m_byte_offset;
- pos.m_shift = (m_bytes_per_chunk * 8) - 4;
+ pos.m_shift = get_posdata(m_data_format).m_shift[0] & 0x7f;
break;
case DCH_END:
@@ -458,43 +533,35 @@ void debug_view_memory::view_char(int chval)
break;
default:
- {
- static const char hexvals[] = "0123456789abcdef";
- char *hexchar = (char *)strchr(hexvals, tolower(chval));
- if (hexchar == nullptr)
- break;
-
- const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
- offs_t address = (source.m_space != nullptr) ? source.m_space->byte_to_address(pos.m_address) : pos.m_address;
- u64 data;
- bool ismapped = read(m_bytes_per_chunk, address, data);
- if (!ismapped)
- break;
+ {
+ static const char hexvals[] = "0123456789abcdef";
+ char *hexchar = (char *)strchr(hexvals, tolower(chval));
+ if (hexchar == nullptr || (m_shift_bits == 3 && chval >= '8'))
+ break;
- data &= ~(u64(0x0f) << pos.m_shift);
- data |= u64(hexchar - hexvals) << pos.m_shift;
- write(m_bytes_per_chunk, address, data);
+ if (!write_digit(pos.m_address, pos.m_shift, hexchar - hexvals))
+ break; // TODO: alert OSD?
+ }
// fall through to the right-arrow press
- }
-
+ [[fallthrough]];
case DCH_RIGHT:
- if (pos.m_shift == 0 && pos.m_address != m_maxaddr)
+ if (pos.m_shift != 0)
+ pos.m_shift -= m_shift_bits;
+ else if (pos.m_address != m_maxaddr)
{
- pos.m_shift = m_bytes_per_chunk * 8 - 4;
+ pos.m_shift = get_posdata(m_data_format).m_shift[0] & 0x7f;
pos.m_address += m_bytes_per_chunk;
}
- else
- pos.m_shift -= 4;
break;
case DCH_LEFT:
- if (pos.m_shift == m_bytes_per_chunk * 8 - 4 && pos.m_address != m_byte_offset)
+ if (pos.m_shift != (get_posdata(m_data_format).m_shift[0] & 0x7f))
+ pos.m_shift += m_shift_bits;
+ else if (pos.m_address != m_byte_offset)
{
pos.m_shift = 0;
pos.m_address -= m_bytes_per_chunk;
}
- else
- pos.m_shift += 4;
break;
}
@@ -551,19 +618,42 @@ void debug_view_memory::recompute()
{
m_maxaddr = m_no_translation ? source.m_space->addrmask() : source.m_space->logaddrmask();
maxbyte = source.m_space->address_to_byte_end(m_maxaddr);
- addrchars = m_no_translation ? source.m_space->addrchars() : source.m_space->logaddrchars();
+ if (m_address_radix == 8)
+ addrchars = ((m_no_translation ? source.m_space->addr_width() : source.m_space->logaddr_width()) + 2) / 3;
+ else
+ addrchars = m_no_translation ? source.m_space->addrchars() : source.m_space->logaddrchars();
}
else
{
- maxbyte = m_maxaddr = source.m_length - 1;
- addrchars = string_format("%X", m_maxaddr).size();
+ maxbyte = m_maxaddr = (source.m_blocklength * source.m_numblocks) - 1;
+ if (m_address_radix == 8)
+ addrchars = string_format("%o", m_maxaddr).size();
+ else
+ addrchars = string_format("%X", m_maxaddr).size();
}
// generate an 8-byte aligned format for the address
- if (!m_reverse_view)
- m_addrformat = string_format("%*s%%0%dX", 8 - addrchars, "", addrchars);
- else
- m_addrformat = string_format("%%0%dX%*s", addrchars, 8 - addrchars, "");
+ switch (m_address_radix)
+ {
+ case 8:
+ if (!m_reverse_view)
+ m_addrformat = string_format("%*s%%0%do", 11 - addrchars, "", addrchars);
+ else
+ m_addrformat = string_format("%%0%do%*s", addrchars, 11 - addrchars, "");
+ break;
+
+ case 10:
+ // omit leading zeros for decimal addresses
+ m_addrformat = m_reverse_view ? "%-10d" : "%10d";
+ break;
+
+ case 16:
+ if (!m_reverse_view)
+ m_addrformat = string_format("%*s%%0%dX", 8 - addrchars, "", addrchars);
+ else
+ m_addrformat = string_format("%%0%dX%*s", addrchars, 8 - addrchars, "");
+ break;
+ }
// if we are viewing a space with a minimum chunk size, clamp the bytes per chunk
// BAD
@@ -588,14 +678,21 @@ void debug_view_memory::recompute()
m_byte_offset = val % m_bytes_per_row;
// compute the section widths
- m_section[0].m_width = 1 + 8 + 1;
- if (m_data_format <= 8)
- m_section[1].m_width = 1 + 3 * m_bytes_per_row + 1;
- else {
- const memory_view_pos &posdata = s_memory_pos_table[m_data_format];
+ switch (m_address_radix)
+ {
+ case 8:
+ m_section[0].m_width = 1 + 11 + 1;
+ break;
- m_section[1].m_width = 1 + posdata.m_spacing * m_chunks_per_row + 1;
+ case 10:
+ m_section[0].m_width = 1 + 10 + 1;
+ break;
+
+ case 16:
+ m_section[0].m_width = 1 + 8 + 1;
+ break;
}
+ m_section[1].m_width = 1 + get_posdata(m_data_format).m_spacing * m_chunks_per_row + 1;
m_section[2].m_width = m_ascii_view ? (1 + m_bytes_per_row + 1) : 0;
// compute the section positions
@@ -661,11 +758,11 @@ debug_view_memory::cursor_pos debug_view_memory::get_cursor_pos(const debug_view
{
// start with the base address for this row
cursor_pos pos;
- const memory_view_pos &posdata = s_memory_pos_table[m_data_format];
+ const memory_view_pos &posdata = get_posdata(m_data_format);
pos.m_address = m_byte_offset + cursor.y * m_bytes_per_chunk * m_chunks_per_row;
// determine the X position within the middle section, clamping as necessary
- if (m_data_format <= 8) {
+ if (posdata.m_shift[0] != 0) {
int xposition = cursor.x - m_section[1].m_pos - 1;
if (xposition < 0)
xposition = 0;
@@ -712,7 +809,7 @@ debug_view_memory::cursor_pos debug_view_memory::get_cursor_pos(const debug_view
void debug_view_memory::set_cursor_pos(cursor_pos pos)
{
- const memory_view_pos &posdata = s_memory_pos_table[m_data_format];
+ const memory_view_pos &posdata = get_posdata(m_data_format);
// offset the address by the byte offset
if (pos.m_address < m_byte_offset)
@@ -727,7 +824,7 @@ void debug_view_memory::set_cursor_pos(cursor_pos pos)
if (m_reverse_view)
chunknum = m_chunks_per_row - 1 - chunknum;
- if (m_data_format <= 8) {
+ if (posdata.m_shift[0] != 0) {
// scan within the chunk to find the shift
for (m_cursor.x = 0; m_cursor.x < posdata.m_spacing; m_cursor.x++)
if (posdata.m_shift[m_cursor.x] == pos.m_shift)
@@ -764,22 +861,17 @@ bool debug_view_memory::read(u8 size, offs_t offs, u64 &data)
auto dis = machine().disable_side_effects();
bool ismapped = offs <= m_maxaddr;
+ address_space *tspace;
if (ismapped && !m_no_translation)
{
offs_t dummyaddr = offs;
- ismapped = source.m_memintf->translate(source.m_space->spacenum(), TRANSLATE_READ_DEBUG, dummyaddr);
+ ismapped = source.m_memintf->translate(source.m_space->spacenum(), device_memory_interface::TR_READ, dummyaddr, tspace);
}
+ else
+ tspace = source.m_space;
data = ~u64(0);
if (ismapped)
- {
- switch (size)
- {
- case 1: data = machine().debugger().cpu().read_byte(*source.m_space, offs, !m_no_translation); break;
- case 2: data = machine().debugger().cpu().read_word(*source.m_space, offs, !m_no_translation); break;
- case 4: data = machine().debugger().cpu().read_dword(*source.m_space, offs, !m_no_translation); break;
- case 8: data = machine().debugger().cpu().read_qword(*source.m_space, offs, !m_no_translation); break;
- }
- }
+ data = m_expression.context().read_memory(*tspace, offs, size, !m_no_translation);
return ismapped;
}
@@ -801,9 +893,9 @@ bool debug_view_memory::read(u8 size, offs_t offs, u64 &data)
// all 0xff if out of bounds
offs ^= source.m_offsetxor;
- if (offs >= source.m_length)
+ if (offs >= (source.m_blocklength * source.m_numblocks))
return false;
- data = *((u8 *)source.m_base + offs);
+ data = *(reinterpret_cast<const u8 *>(source.m_base) + (offs / source.m_blocklength * source.m_blockstride) + (offs % source.m_blocklength));
return true;
}
@@ -812,21 +904,21 @@ bool debug_view_memory::read(u8 size, offs_t offs, u64 &data)
// read - read a 80 bit value
//-------------------------------------------------
-bool debug_view_memory::read(u8 size, offs_t offs, floatx80 &data)
+bool debug_view_memory::read(u8 size, offs_t offs, extFloat80_t &data)
{
u64 t;
bool mappedhi, mappedlo;
const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
if (source.m_endianness == ENDIANNESS_LITTLE) {
- mappedlo = read(8, offs, data.low);
+ mappedlo = read(8, offs, data.signif);
mappedhi = read(2, offs+8, t);
- data.high = (bits16)t;
+ data.signExp = u16(t);
}
else {
mappedhi = read(2, offs, t);
- data.high = (bits16)t;
- mappedlo = read(8, offs + 2, data.low);
+ data.signExp = u16(t);
+ mappedlo = read(8, offs + 2, data.signif);
}
return mappedhi && mappedlo;
@@ -870,14 +962,7 @@ void debug_view_memory::write(u8 size, offs_t offs, u64 data)
if (source.m_space)
{
auto dis = machine().disable_side_effects();
-
- switch (size)
- {
- case 1: machine().debugger().cpu().write_byte(*source.m_space, offs, data, !m_no_translation); break;
- case 2: machine().debugger().cpu().write_word(*source.m_space, offs, data, !m_no_translation); break;
- case 4: machine().debugger().cpu().write_dword(*source.m_space, offs, data, !m_no_translation); break;
- case 8: machine().debugger().cpu().write_qword(*source.m_space, offs, data, !m_no_translation); break;
- }
+ m_expression.context().write_memory(*source.m_space, offs, data, size, !m_no_translation);
return;
}
@@ -900,18 +985,44 @@ void debug_view_memory::write(u8 size, offs_t offs, u64 data)
// ignore if out of bounds
offs ^= source.m_offsetxor;
- if (offs >= source.m_length)
+ if (offs >= (source.m_blocklength * source.m_numblocks))
return;
- *((u8 *)source.m_base + offs) = data;
+ *(reinterpret_cast<u8 *>(source.m_base) + (offs / source.m_blocklength * source.m_blockstride) + (offs % source.m_blocklength)) = data;
+}
+
+
+//-------------------------------------------------
+// write_digit - write one hex or octal digit
+// at the given address and bit position
+//-------------------------------------------------
+
+bool debug_view_memory::write_digit(offs_t offs, u8 pos, u8 digit)
+{
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+ offs_t address = (source.m_space != nullptr) ? source.m_space->byte_to_address(offs) : offs;
+ u64 data;
+ bool ismapped = read(m_bytes_per_chunk, address, data);
+ if (!ismapped)
+ return false;
-// hack for FD1094 editing
-#ifdef FD1094_HACK
- if (source.m_base == machine().root_device().memregion("user2"))
+ // clamp to chunk size
+ if (m_bytes_per_chunk * 8 < pos + m_shift_bits)
{
- extern void fd1094_regenerate_key(running_machine &machine);
- fd1094_regenerate_key(machine());
+ assert(m_bytes_per_chunk * 8 > pos);
+ digit &= util::make_bitmask<u8>(m_bytes_per_chunk * 8 - pos);
}
-#endif
+
+ u64 write_data = (data & ~(util::make_bitmask<u64>(m_shift_bits) << pos)) | (u64(digit) << pos);
+ write(m_bytes_per_chunk, address, write_data);
+
+ // verify that data reads back as it was written
+ if (source.m_space != nullptr)
+ {
+ read(m_bytes_per_chunk, address, data);
+ return data == write_data;
+ }
+ else
+ return true;
}
@@ -948,15 +1059,15 @@ void debug_view_memory::set_chunks_per_row(u32 rowchunks)
//-------------------------------------------------
// set_data_format - specify what kind of values
-// are shown, 1-8 8-64 bits, 9 32bit floating point
+// are shown
//-------------------------------------------------
-void debug_view_memory::set_data_format(int format)
+void debug_view_memory::set_data_format(data_format format)
{
cursor_pos pos;
// should never be
- if ((format <= 0) || (format > 11))
+ if (!is_valid_format(format))
return;
// no need to change
if (format == m_data_format)
@@ -964,47 +1075,42 @@ void debug_view_memory::set_data_format(int format)
pos = begin_update_and_get_cursor_pos();
const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
- if ((format <= 8) && (m_data_format <= 8)) {
-
+ if (is_hex_format(format) && is_hex_format(m_data_format)) {
pos.m_address += (pos.m_shift / 8) ^ ((source.m_endianness == ENDIANNESS_LITTLE) ? 0 : (m_bytes_per_chunk - 1));
pos.m_shift %= 8;
- m_bytes_per_chunk = format;
+ m_bytes_per_chunk = get_posdata(format).m_bytes;
m_steps_per_chunk = source.m_space ? source.m_space->byte_to_address(m_bytes_per_chunk) : m_bytes_per_chunk;
- m_chunks_per_row = m_bytes_per_row / format;
+ m_chunks_per_row = m_bytes_per_row / m_bytes_per_chunk;
if (m_chunks_per_row < 1)
m_chunks_per_row = 1;
pos.m_shift += 8 * ((pos.m_address % m_bytes_per_chunk) ^ ((source.m_endianness == ENDIANNESS_LITTLE) ? 0 : (m_bytes_per_chunk - 1)));
pos.m_address -= pos.m_address % m_bytes_per_chunk;
} else {
- if (format <= 8) {
+ if (is_hex_format(format)) {
m_supports_cursor = true;
m_edit_enabled = true;
-
- m_bytes_per_chunk = format;
+ m_shift_bits = 4;
+ }
+ else if (is_octal_format(format)) {
+ m_supports_cursor = true;
+ m_edit_enabled = true;
+ m_shift_bits = 3;
}
else {
m_supports_cursor = false;
m_edit_enabled = false;
m_cursor_visible = false;
-
- switch (format)
- {
- case 9:
- m_bytes_per_chunk = 4;
- break;
- case 10:
- m_bytes_per_chunk = 8;
- break;
- case 11:
- m_bytes_per_chunk = 10;
- break;
- }
+ m_shift_bits = 0;
}
+
+ m_bytes_per_chunk = get_posdata(format).m_bytes;
m_chunks_per_row = m_bytes_per_row / m_bytes_per_chunk;
+ if (m_chunks_per_row < 1)
+ m_chunks_per_row = 1;
m_steps_per_chunk = source.m_space ? source.m_space->byte_to_address(m_bytes_per_chunk) : m_bytes_per_chunk;
- pos.m_shift = 0;
+ pos.m_shift = get_posdata(format).m_shift[0] & 0x7f;
pos.m_address -= pos.m_address % m_bytes_per_chunk;
}
m_recompute = m_update_pending = true;
@@ -1053,3 +1159,22 @@ void debug_view_memory::set_physical(bool physical)
m_recompute = m_update_pending = true;
end_update_and_set_cursor_pos(pos);
}
+
+
+//-------------------------------------------------
+// set_address_radix - specify whether the memory
+// view should display addresses in base 8, base
+// 10 or base 16
+//-------------------------------------------------
+
+void debug_view_memory::set_address_radix(int radix)
+{
+ if (radix != 8 && radix != 10 && radix != 16)
+ return;
+
+ cursor_pos pos = begin_update_and_get_cursor_pos();
+ m_address_radix = radix;
+ m_expression.set_default_base(radix);
+ m_recompute = m_update_pending = true;
+ end_update_and_set_cursor_pos(pos);
+}