bool debug_view_disasm::recompute(offs_t pc, int startline, int lines) { bool changed = false; const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); int char_num = source.is_octal() ? 3 : 2; // determine how many characters we need for an address and set the divider m_divider1 = 1 + (source.m_space.logaddrchars()/2*char_num) + 1; // assume a fixed number of characters for the disassembly m_divider2 = m_divider1 + 1 + m_dasm_width + 1; // determine how many bytes we might need to display int minbytes = source.m_disasmintf->min_opcode_bytes(); int maxbytes = source.m_disasmintf->max_opcode_bytes(); // ensure that the PC is aligned to the minimum opcode size pc &= ~source.m_space.byte_to_address_end(minbytes - 1); // set the width of the third column according to display mode if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) { int maxbytes_clamped = MIN(maxbytes, DASM_MAX_BYTES); m_total.x = m_divider2 + 1 + char_num * maxbytes_clamped + (maxbytes_clamped / minbytes - 1) + 1; } else if (m_right_column == DASM_RIGHTCOL_COMMENTS) m_total.x = m_divider2 + 1 + 50; // DEBUG_COMMENT_MAX_LINE_LENGTH else m_total.x = m_divider2 + 1; // allocate address array m_byteaddress.resize(m_total.y); // allocate disassembly buffer m_dasm.resize(m_total.x * m_total.y); // iterate over lines int row_width = m_total.x; for (int line = 0; line < lines; line++) { // convert PC to a byte offset offs_t pcbyte = source.m_space.address_to_byte(pc) & source.m_space.logbytemask(); // save a copy of the previous line as a backup if we're only doing one line int instr = startline + line; char *destbuf = &m_dasm[instr * row_width]; char oldbuf[100]; if (lines == 1) strncpy(oldbuf, destbuf, MIN(sizeof(oldbuf), row_width)); // convert back and set the address of this instruction m_byteaddress[instr] = pcbyte; sprintf(&destbuf[0], " %s ", core_i64_format(source.m_space.byte_to_address(pcbyte), source.m_space.logaddrchars()/2*char_num, source.is_octal())); // make sure we can translate the address, and then disassemble the result char buffer[100]; int numbytes = 0; offs_t physpcbyte = pcbyte; if (debug_cpu_translate(source.m_space, TRANSLATE_FETCH_DEBUG, &physpcbyte)) { UINT8 opbuf[64], argbuf[64]; // fetch the bytes up to the maximum for (numbytes = 0; numbytes < maxbytes; numbytes++) { opbuf[numbytes] = debug_read_opcode(source.m_decrypted_space, pcbyte + numbytes, 1); argbuf[numbytes] = debug_read_opcode(source.m_space, pcbyte + numbytes, 1); } // disassemble the result pc += numbytes = source.m_device.debug()->disassemble(buffer, pc & source.m_space.logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK; } else strcpy(buffer, "<unmapped>"); // append the disassembly to the buffer sprintf(&destbuf[m_divider1 + 1], "%-*s ", m_dasm_width, buffer); // output the right column if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) { // get the bytes numbytes = source.m_space.address_to_byte(numbytes) & source.m_space.logbytemask(); generate_bytes(pcbyte, numbytes, minbytes, &destbuf[m_divider2], row_width - m_divider2, m_right_column == DASM_RIGHTCOL_ENCRYPTED); } else if (m_right_column == DASM_RIGHTCOL_COMMENTS) { // get and add the comment, if present offs_t comment_address = source.m_space.byte_to_address(m_byteaddress[instr]); const char *text = source.m_device.debug()->comment_text(comment_address); if (text != NULL) sprintf(&destbuf[m_divider2], "// %.*s", row_width - m_divider2 - 4, text); } // see if the line changed at all if (lines == 1 && strncmp(oldbuf, destbuf, MIN(sizeof(oldbuf), row_width)) != 0) changed = true; } // update opcode base information m_last_direct_decrypted = source.m_decrypted_space.direct().ptr(); m_last_direct_raw = source.m_space.direct().ptr(); m_last_change_count = source.m_device.debug()->comment_change_count(); // no longer need to recompute m_recompute = false; return changed; }
bool debug_view_disasm::recompute(offs_t pc, int startline, int lines) { bool changed = false; const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); const int char_num = source.m_space.is_octal() ? 3 : 2; // determine how many characters we need for an address and set the divider m_divider1 = 1 + (source.m_space.logaddrchars()/2*char_num) + 1; // assume a fixed number of characters for the disassembly m_divider2 = m_divider1 + 1 + m_dasm_width + 1; // determine how many bytes we might need to display const int minbytes = source.m_disasmintf->min_opcode_bytes(); const int maxbytes = source.m_disasmintf->max_opcode_bytes(); // ensure that the PC is aligned to the minimum opcode size pc &= ~source.m_space.byte_to_address_end(minbytes - 1); // set the width of the third column according to display mode if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) { int const maxbytes_clamped = (std::min)(maxbytes, DASM_MAX_BYTES); m_total.x = m_divider2 + 1 + char_num * maxbytes_clamped + (maxbytes_clamped / minbytes - 1) + 1; } else if (m_right_column == DASM_RIGHTCOL_COMMENTS) m_total.x = m_divider2 + 1 + 50; // DEBUG_COMMENT_MAX_LINE_LENGTH else m_total.x = m_divider2 + 1; // allocate address array m_byteaddress.resize(m_total.y); // allocate disassembly buffer const auto total_bytes = m_total.x * m_total.y; m_dasm.clear(); m_dasm.reserve(total_bytes).seekp(total_bytes); // iterate over lines for (int line = 0; line < lines; line++) { // convert PC to a byte offset const offs_t pcbyte = source.m_space.address_to_byte(pc) & source.m_space.logbytemask(); // save a copy of the previous line as a backup if we're only doing one line const auto instr = startline + line; const auto base = instr * m_total.x; char oldbuf[100]; if (lines == 1) std::memcpy(oldbuf, &m_dasm.vec()[base], (std::min<std::size_t>)(sizeof(oldbuf), m_total.x)); // convert back and set the address of this instruction m_byteaddress[instr] = pcbyte; m_dasm.clear(); util::stream_format(m_dasm.seekp(base), source.m_space.is_octal() ? " %0*o " : " %0*X ", source.m_space.logaddrchars()/2*char_num, source.m_space.byte_to_address(pcbyte)); // make sure we can translate the address, and then disassemble the result char buffer[100]; int numbytes = 0; offs_t physpcbyte = pcbyte; if (source.m_space.device().memory().translate(source.m_space.spacenum(), TRANSLATE_FETCH_DEBUG, physpcbyte)) { UINT8 opbuf[64], argbuf[64]; // fetch the bytes up to the maximum for (numbytes = 0; numbytes < maxbytes; numbytes++) { opbuf[numbytes] = machine().debugger().cpu().read_opcode(source.m_decrypted_space, pcbyte + numbytes, 1); argbuf[numbytes] = machine().debugger().cpu().read_opcode(source.m_space, pcbyte + numbytes, 1); } // disassemble the result pc += numbytes = source.m_disasmintf->disassemble(buffer, pc & source.m_space.logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK; } else strcpy(buffer, "<unmapped>"); // append the disassembly to the buffer util::stream_format(m_dasm.seekp(base + m_divider1 + 1), "%2$-*1$.*1$s ", m_dasm_width, buffer); // output the right column if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) { // get the bytes numbytes = source.m_space.address_to_byte(numbytes) & source.m_space.logbytemask(); m_dasm.seekp(base + m_divider2); generate_bytes(pcbyte, numbytes, minbytes, m_total.x - m_divider2, m_right_column == DASM_RIGHTCOL_ENCRYPTED); } else if (m_right_column == DASM_RIGHTCOL_COMMENTS) { // get and add the comment, if present const offs_t comment_address = source.m_space.byte_to_address(m_byteaddress[instr]); const char *const text = source.device()->debug()->comment_text(comment_address); if (text != nullptr) util::stream_format(m_dasm.seekp(base + m_divider2), "// %.*s", m_total.x - m_divider2 - 4, text); } m_dasm.put('\0'); // see if the line changed at all if (lines == 1 && strncmp(oldbuf, &m_dasm.vec()[base], (std::min<std::size_t>)(sizeof(oldbuf), m_total.x)) != 0) changed = true; } // update opcode base information m_last_direct_decrypted = source.m_decrypted_space.direct().ptr(); m_last_direct_raw = source.m_space.direct().ptr(); m_last_change_count = source.device()->debug()->comment_change_count(); // no longer need to recompute m_recompute = false; return changed; }