void debug_view::set_source(const debug_view_source &source) { if (&source != m_source) { begin_update(); m_source = &source; m_update_pending = true; view_notify(VIEW_NOTIFY_SOURCE_CHANGED); end_update(); } }
void debug_view::set_cursor_visible(bool visible) { if (visible != m_cursor_visible) { begin_update(); m_cursor_visible = visible; m_update_pending = true; view_notify(VIEW_NOTIFY_CURSOR_CHANGED); end_update(); } }
void debug_view::set_cursor_position(debug_view_xy pos) { if (pos.x != m_cursor.x || pos.y != m_cursor.y) { begin_update(); m_cursor = pos; m_update_pending = true; view_notify(VIEW_NOTIFY_CURSOR_CHANGED); end_update(); } }
void debug_view::set_visible_position(debug_view_xy pos) { if (pos.x != m_topleft.x || pos.y != m_topleft.y) { begin_update(); m_topleft = pos; m_update_pending = true; view_notify(VIEW_NOTIFY_VISIBLE_CHANGED); end_update(); } }
void debug_view::set_visible_size(debug_view_xy size) { if (size.x != m_visible.x || size.y != m_visible.y) { begin_update(); m_visible = size; m_update_pending = true; view_notify(VIEW_NOTIFY_VISIBLE_CHANGED); end_update(); } }
void debug_view_disasm::view_click(const int button, const debug_view_xy& pos) { const debug_view_xy origcursor = m_cursor; m_cursor = pos; /* cursor popup|toggle */ bool cursorVisible = true; if (m_cursor.y == origcursor.y) { cursorVisible = !m_cursor_visible; } /* send a cursor changed notification */ begin_update(); m_cursor_visible = cursorVisible; view_notify(VIEW_NOTIFY_CURSOR_CHANGED); m_update_pending = true; end_update(); }
void debug_view_disasm::view_update() { const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); offs_t pc = source.m_device.safe_pc(); offs_t pcbyte = source.m_space.address_to_byte(pc) & source.m_space.logbytemask(); // update our context; if the expression is dirty, recompute if (m_expression.dirty()) m_recompute = true; // if we're tracking a value, make sure it is visible UINT64 previous = m_expression.last_value(); UINT64 result = m_expression.value(); if (result != previous) { offs_t resultbyte = source.m_space.address_to_byte(result) & source.m_space.logbytemask(); // see if the new result is an address we already have UINT32 row; for (row = 0; row < m_byteaddress.size(); row++) if (m_byteaddress[row] == resultbyte) break; // if we didn't find it, or if it's really close to the bottom, recompute if (row == m_byteaddress.size() || row >= m_total.y - m_visible.y) m_recompute = true; // otherwise, if it's not visible, adjust the view so it is else if (row < m_topleft.y || row >= m_topleft.y + m_visible.y - 2) m_topleft.y = (row > 3) ? row - 3 : 0; } // if the opcode base has changed, rework things if (source.m_decrypted_space.direct().ptr() != m_last_direct_decrypted || source.m_space.direct().ptr() != m_last_direct_raw) m_recompute = true; // if the comments have changed, redo it if (m_last_change_count != source.m_device.debug()->comment_change_count()) m_recompute = true; // if we need to recompute, do it bool recomputed_this_time = false; recompute: if (m_recompute) { // recompute the view if (!m_byteaddress.empty() && m_last_change_count != source.m_device.debug()->comment_change_count()) { // smoosh us against the left column, but not the top row m_topleft.x = 0; // recompute from where we last recomputed! recompute(source.m_space.byte_to_address(m_byteaddress[0]), 0, m_total.y); } else { // determine the addresses of what we will display offs_t backpc = find_pc_backwards((UINT32)m_expression.value(), m_backwards_steps); // put ourselves back in the top left m_topleft.y = 0; m_topleft.x = 0; recompute(backpc, 0, m_total.y); } recomputed_this_time = true; } // figure out the row where the PC is and recompute the disassembly if (pcbyte != m_last_pcbyte) { // find the row with the PC on it for (UINT32 row = 0; row < m_visible.y; row++) { UINT32 effrow = m_topleft.y + row; if (effrow >= m_byteaddress.size()) break; if (pcbyte == m_byteaddress[effrow]) { // see if we changed bool changed = recompute(pc, effrow, 1); if (changed && !recomputed_this_time) { m_recompute = true; goto recompute; } // set the effective row and PC m_cursor.y = effrow; view_notify(VIEW_NOTIFY_CURSOR_CHANGED); } } m_last_pcbyte = pcbyte; } // loop over visible rows debug_view_char *dest = &m_viewdata[0]; int row_width = m_dasm.size() / m_byteaddress.size(); for (UINT32 row = 0; row < m_visible.y; row++) { UINT32 effrow = m_topleft.y + row; UINT32 col = 0; // if this visible row is valid, add it to the buffer UINT8 attrib = DCA_NORMAL; if (effrow < m_byteaddress.size()) { // if we're on the line with the PC, recompute and hilight it if (pcbyte == m_byteaddress[effrow]) attrib = DCA_CURRENT; // if we're on a line with a breakpoint, tag it changed else { for (device_debug::breakpoint *bp = source.m_device.debug()->breakpoint_first(); bp != NULL; bp = bp->next()) if (m_byteaddress[effrow] == (source.m_space.address_to_byte(bp->address()) & source.m_space.logbytemask())) attrib = DCA_CHANGED; } // if we're on the active column and everything is couth, highlight it if (m_cursor_visible && effrow == m_cursor.y) attrib |= DCA_SELECTED; // if we've visited this pc, mark it as such if (source.m_device.debug()->track_pc_visited(m_byteaddress[effrow])) attrib |= DCA_VISITED; // get the effective string const char *data = &m_dasm[effrow * row_width]; UINT32 len = (UINT32)strlen(data); // copy data UINT32 effcol = m_topleft.x; while (col < m_visible.x && effcol < len) { dest->byte = data[effcol++]; dest->attrib = (effcol <= m_divider1 || effcol >= m_divider2) ? (attrib | DCA_ANCILLARY) : attrib; // comments are just green for now - maybe they shouldn't even be this? if (effcol >= m_divider2 && m_right_column == DASM_RIGHTCOL_COMMENTS) attrib |= DCA_COMMENT; dest++; col++; } } // fill the rest with blanks while (col < m_visible.x) { dest->byte = ' '; dest->attrib = (effrow < m_total.y) ? (attrib | DCA_ANCILLARY) : attrib; dest++; col++; } } }
void debug_view_disasm::view_char(int chval) { debug_view_xy origcursor = m_cursor; UINT8 end_buffer = 3; INT32 temp; switch (chval) { case DCH_UP: if (m_cursor.y > 0) m_cursor.y--; break; case DCH_DOWN: if (m_cursor.y < m_total.y - 1) m_cursor.y++; break; case DCH_PUP: temp = m_cursor.y - (m_visible.y - end_buffer); if (temp < 0) m_cursor.y = 0; else m_cursor.y = temp; break; case DCH_PDOWN: temp = m_cursor.y + (m_visible.y - end_buffer); if (temp > m_total.y - 1) m_cursor.y = m_total.y - 1; else m_cursor.y = temp; break; case DCH_HOME: // set the active column to the PC { const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); offs_t pc = source.m_space.address_to_byte(source.m_device.safe_pc()) & source.m_space.logbytemask(); // figure out which row the pc is on for (unsigned int curline = 0; curline < m_byteaddress.size(); curline++) if (m_byteaddress[curline] == pc) m_cursor.y = curline; break; } case DCH_CTRLHOME: m_cursor.y = 0; break; case DCH_CTRLEND: m_cursor.y = m_total.y - 1; break; } /* send a cursor changed notification */ if (m_cursor.y != origcursor.y) { begin_update(); view_notify(VIEW_NOTIFY_CURSOR_CHANGED); m_update_pending = true; end_update(); } }