// Print disassembled instructions // Return value: number of words in the last instruction int PrintDisassemble(CProcessor* pProc, WORD address, BOOL okOneInstr, BOOL okShort) { BOOL okHaltMode = pProc->IsHaltMode(); const int nWindowSize = 30; WORD memory[nWindowSize + 2]; int addrtype; for (int i = 0; i < nWindowSize + 2; i++) memory[i] = g_pBoard->GetWordView(address + i * 2, okHaltMode, TRUE, &addrtype); TCHAR bufaddr[7]; TCHAR bufvalue[7]; TCHAR buffer[64]; int lastLength = 0; int length = 0; for (int index = 0; index < nWindowSize; index++) // –исуем строки { PrintOctalValue(bufaddr, address); WORD value = memory[index]; PrintOctalValue(bufvalue, value); if (length > 0) { if (!okShort) { wsprintf(buffer, _T(" %s %s\r\n"), bufaddr, bufvalue); ConsoleView_Print(buffer); } } else { if (okOneInstr && index > 0) break; TCHAR instr[8]; TCHAR args[32]; length = DisassembleInstruction(memory + index, address, instr, args); lastLength = length; if (index + length > nWindowSize) break; if (okShort) wsprintf(buffer, _T(" %s %-7s %s\r\n"), bufaddr, instr, args); else wsprintf(buffer, _T(" %s %s %-7s %s\r\n"), bufaddr, bufvalue, instr, args); ConsoleView_Print(buffer); } length--; address += 2; } return lastLength; }
// Print memory dump void PrintMemoryDump(CProcessor* pProc, WORD address, int lines) { address &= ~1; // Line up to even address BOOL okHaltMode = pProc->IsHaltMode(); for (int line = 0; line < lines; line++) { WORD dump[8]; for (int i = 0; i < 8; i++) dump[i] = g_pBoard->GetWord(address + i * 2, okHaltMode); TCHAR buffer[2 + 6 + 2 + 7 * 8 + 1 + 16 + 1 + 2]; TCHAR* pBuf = buffer; *pBuf = _T(' '); pBuf++; *pBuf = _T(' '); pBuf++; PrintOctalValue(pBuf, address); pBuf += 6; *pBuf = _T(' '); pBuf++; *pBuf = _T(' '); pBuf++; for (int i = 0; i < 8; i++) { PrintOctalValue(pBuf, dump[i]); pBuf += 6; *pBuf = _T(' '); pBuf++; } *pBuf = _T(' '); pBuf++; for (int i = 0; i < 8; i++) { WORD word = dump[i]; BYTE ch1 = LOBYTE(word); TCHAR wch1 = Translate_BK_Unicode(ch1); if (ch1 < 32) wch1 = _T('Ј'); *pBuf = wch1; pBuf++; BYTE ch2 = HIBYTE(word); TCHAR wch2 = Translate_BK_Unicode(ch2); if (ch2 < 32) wch2 = _T('Ј'); *pBuf = wch2; pBuf++; } *pBuf++ = _T('\r'); *pBuf++ = _T('\n'); *pBuf = 0; ConsoleView_Print(buffer); address += 16; } }
void PrintConsolePrompt() { CProcessor* pProc = ConsoleView_GetCurrentProcessor(); TCHAR bufferAddr[7]; PrintOctalValue(bufferAddr, pProc->GetPC()); TCHAR buffer[14]; wsprintf(buffer, _T("%s> "), bufferAddr); ::SetWindowText(m_hwndConsolePrompt, buffer); }
void Dialogs_DoLoadBinPrepare(HWND hDlg, LPCTSTR strFileName) { ::SetDlgItemText(hDlg, IDC_EDITFILE, NULL); // Open file for reading HANDLE hFile = CreateFile(strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { AlertWarning(_T("Failed to load binary file.")); return; } // Load BIN header BYTE bufHeader[20]; DWORD bytesRead; ::ReadFile(hFile, bufHeader, 4, &bytesRead, NULL); if (bytesRead != 4) { ::CloseHandle(hFile); AlertWarning(_T("Failed to load binary file.")); return; } WORD baseAddress = *((WORD*)bufHeader); WORD dataSize = *(((WORD*)bufHeader) + 1); //TCHAR bufName[17]; //::MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(bufHeader + 4), 16, bufName, 17); //bufName[16] = 0; // Set controls text TCHAR bufValue[8]; ::SetDlgItemText(hDlg, IDC_EDITFILE, strFileName); PrintOctalValue(bufValue, baseAddress); ::SetDlgItemText(hDlg, IDC_EDITADDR, bufValue); PrintOctalValue(bufValue, dataSize); ::SetDlgItemText(hDlg, IDC_EDITSIZE, bufValue); //::SetDlgItemText(hDlg, IDC_EDITNAME, bufName); ::CloseHandle(hFile); }
// Print register name, octal value and binary value void PrintRegister(LPCTSTR strName, WORD value) { TCHAR buffer[31]; TCHAR* p = buffer; *p++ = _T(' '); *p++ = _T(' '); lstrcpy(p, strName); p += 2; *p++ = _T(' '); PrintOctalValue(p, value); p += 6; *p++ = _T(' '); PrintBinaryValue(p, value); p += 16; *p++ = _T('\r'); *p++ = _T('\n'); *p++ = 0; ConsoleView_Print(buffer); }
int DisasmView_DrawDisassemble(HDC hdc, CProcessor* pProc, WORD base, WORD previous, int x, int y) { int result = -1; int cxChar, cyLine; GetFontWidthAndHeight(hdc, &cxChar, &cyLine); COLORREF colorText = GetSysColor(COLOR_WINDOWTEXT); const CMemoryController* pMemCtl = pProc->GetMemoryController(); WORD proccurrent = pProc->GetPC(); WORD current = base; // Draw current line background if (!m_okDisasmSubtitles) //NOTE: Subtitles can move lines down { HGDIOBJ oldBrush = SelectObject(hdc, CreateSolidBrush(COLOR_CURRENT)); int yCurrent = (proccurrent - (current - 5)) * cyLine; PatBlt(hdc, 0, yCurrent, 1000, cyLine, PATCOPY); SelectObject(hdc, oldBrush); } // Читаем из памяти процессора в буфер const int nWindowSize = 30; WORD memory[nWindowSize + 2]; for (int idx = 0; idx < nWindowSize; idx++) { BOOL okValidAddress; memory[idx] = pMemCtl->GetWordView( (WORD)(current + idx * 2 - 10), pProc->IsHaltMode(), TRUE, &okValidAddress); } WORD address = current - 10; WORD disasmfrom = current; if (previous >= address && previous < current) disasmfrom = previous; int length = 0; WORD wNextBaseAddr = 0; for (int index = 0; index < nWindowSize; index++) // Рисуем строки { if (m_okDisasmSubtitles) // Subtitles - комментарий к блоку { DisasmSubtitleItem* pSubItem = DisasmView_FindSubtitle(address, SUBTYPE_BLOCKCOMMENT); if (pSubItem != NULL && pSubItem->comment != NULL) { LPCTSTR strBlockSubtitle = pSubItem->comment; ::SetTextColor(hdc, COLOR_SUBTITLE); TextOut(hdc, x + 21 * cxChar, y, strBlockSubtitle, (int) _tcslen(strBlockSubtitle)); ::SetTextColor(hdc, colorText); y += cyLine; } } DrawOctalValue(hdc, x + 5 * cxChar, y, address); // Address // Value at the address WORD value = memory[index]; ::SetTextColor(hdc, COLOR_VALUE); DrawOctalValue(hdc, x + 13 * cxChar, y, value); ::SetTextColor(hdc, colorText); // Current position if (address == current) { TextOut(hdc, x + 1 * cxChar, y, _T(" >"), 3); result = y; // Remember line for the focus rect } if (address == proccurrent) TextOut(hdc, x + 1 * cxChar, y, _T("PC>>"), 4); else if (address == previous) { ::SetTextColor(hdc, COLOR_BLUE); TextOut(hdc, x + 1 * cxChar, y, _T(" > "), 4); } BOOL okData = FALSE; if (m_okDisasmSubtitles) // Show subtitle { DisasmSubtitleItem* pSubItem = DisasmView_FindSubtitle(address, SUBTYPE_COMMENT | SUBTYPE_DATA); if (pSubItem != NULL && (pSubItem->type & SUBTYPE_DATA) != 0) okData = TRUE; if (pSubItem != NULL && (pSubItem->type & SUBTYPE_COMMENT) != 0 && pSubItem->comment != NULL) { LPCTSTR strSubtitle = pSubItem->comment; ::SetTextColor(hdc, COLOR_SUBTITLE); TextOut(hdc, x + 52 * cxChar, y, strSubtitle, (int) _tcslen(strSubtitle)); ::SetTextColor(hdc, colorText); // Строку с субтитром мы можем использовать как опорную для дизассемблера if (disasmfrom > address) disasmfrom = address; } } if (address >= disasmfrom && length == 0) { TCHAR strInstr[8]; TCHAR strArg[32]; if (okData) // По этому адресу лежат данные -- нет смысла дизассемблировать { lstrcpy(strInstr, _T("data")); PrintOctalValue(strArg, *(memory + index)); length = 1; } else { length = DisassembleInstruction(memory + index, address, strInstr, strArg); int delta; if (!m_okDisasmSubtitles && //NOTE: Subtitles can move lines down DisasmView_CheckForJump(memory + index, address, &delta) && abs(delta) < 32) { DisasmView_DrawJump(hdc, y, delta, x + (30 + _tcslen(strArg)) * cxChar, cyLine); } } if (index + length <= nWindowSize) { TextOut(hdc, x + 21 * cxChar, y, strInstr, (int) _tcslen(strInstr)); TextOut(hdc, x + 29 * cxChar, y, strArg, (int) _tcslen(strArg)); } ::SetTextColor(hdc, colorText); if (wNextBaseAddr == 0) wNextBaseAddr = (WORD)(address + length * 2); } if (length > 0) length--; address += 2; y += cyLine; } m_wDisasmNextBaseAddr = wNextBaseAddr; return result; }
void DebugView_DrawChannels(HDC hdc, int x, int y) { int cxChar, cyLine; GetFontWidthAndHeight(hdc, &cxChar, &cyLine); //CProcessor* pCPU = g_pBoard->GetCPU(); //CProcessor* pPPU = g_pBoard->GetPPU(); //CMemoryController* pCPUMemCtl = pCPU->GetMemoryController(); //CMemoryController* pPPUMemCtl = pPPU->GetMemoryController(); TextOut(hdc, x, y, _T("Channels:"), 9); TCHAR bufData[7]; TCHAR buffer[32]; chan_stc tmpstc; tmpstc = g_pBoard->GetChannelStruct(0, 0, 0); PrintOctalValue(bufData, tmpstc.data); wsprintf(buffer, _T("PPU CH:0 RX D:%s RDY:%d IRQ:%d"), bufData + 3, tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 1 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(0, 1, 0); PrintOctalValue(bufData, tmpstc.data); wsprintf(buffer, _T("PPU CH:1 RX D:%s RDY:%d IRQ:%d"), bufData + 3, tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 2 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(0, 2, 0); PrintOctalValue(bufData, tmpstc.data); wsprintf(buffer, _T("PPU CH:2 RX D:%s RDY:%d IRQ:%d"), bufData + 3, tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 3 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(0, 0, 1); wsprintf(buffer, _T("PPU CH:0 TX RDY:%d IRQ:%d"), tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 4 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(0, 1, 1); wsprintf(buffer, _T("PPU CH:1 TX RDY:%d IRQ:%d"), tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 5 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(1, 0, 0); PrintOctalValue(bufData, tmpstc.data); wsprintf(buffer, _T("CPU CH:0 RX D:%s RDY:%d IRQ:%d"), bufData + 3, tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 6 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(1, 1, 0); PrintOctalValue(bufData, tmpstc.data); wsprintf(buffer, _T("CPU CH:1 RX D:%s RDY:%d IRQ:%d"), bufData + 3, tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 7 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(1, 0, 1); wsprintf(buffer, _T("CPU CH:0 TX RDY:%d IRQ:%d"), tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 8 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(1, 1, 1); wsprintf(buffer, _T("CPU CH:1 TX RDY:%d IRQ:%d"), tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 9 * cyLine, buffer, lstrlen(buffer)); tmpstc = g_pBoard->GetChannelStruct(1, 2, 1); wsprintf(buffer, _T("CPU CH:2 TX RDY:%d IRQ:%d"), tmpstc.ready, tmpstc.irq); TextOut(hdc, x, y + 10 * cyLine, buffer, lstrlen(buffer)); }
void QMemoryView::paintEvent(QPaintEvent * /*event*/) { if (g_pBoard == NULL) return; QPainter painter(this); painter.fillRect(0,0, this->width(), this->height(), Qt::white); QFont font = Common_GetMonospacedFont(); painter.setFont(font); QFontMetrics fontmetrics(font); int cxChar = fontmetrics.averageCharWidth(); int cyLine = fontmetrics.height(); CProcessor* pDebugPU = g_pBoard->GetCPU(); ASSERT(pDebugPU != NULL); QColor colorText = painter.pen().color(); m_cyLineMemory = cyLine; TCHAR buffer[7]; const TCHAR* ADDRESS_LINE = _T(" address 0 2 4 6 10 12 14 16"); painter.drawText(0, cyLine, ADDRESS_LINE); // Calculate m_nPageSize m_nPageSize = this->height() / cyLine - 1; quint16 address = m_wBaseAddress; int y = 2 * cyLine; for (;;) { // Draw lines DrawOctalValue(painter, 2 * cxChar, y, address); int x = 10 * cxChar; ushort wchars[16]; for (int j = 0; j < 8; j++) { // Draw words as octal value // Get word from memory quint16 word = 0; int addrtype; bool okHalt = false; quint16 wChanged = 0; okHalt = pDebugPU->IsHaltMode(); word = g_pBoard->GetWordView(address, okHalt, false, &addrtype); wChanged = Emulator_GetChangeRamStatus(address); if ((addrtype & (ADDRTYPE_IO | ADDRTYPE_DENY)) == 0) { painter.setPen(wChanged != 0 ? Qt::red : colorText); if (m_ByteMode) { PrintOctalValue(buffer, (word & 0xff)); painter.drawText(x, y, buffer + 3); PrintOctalValue(buffer, (word >> 8)); painter.drawText(x + 3 * cxChar + cxChar / 2, y, buffer + 3); } else DrawOctalValue(painter, x, y, word); } // Prepare characters to draw at right quint8 ch1 = (quint8)(word & 0xff); // LOBYTE ushort wch1 = Translate_BK_Unicode(ch1); if (ch1 < 32) wch1 = 0x00b7; wchars[j * 2] = wch1; quint8 ch2 = (quint8)((word >> 8) & 0xff); // HIBYTE ushort wch2 = Translate_BK_Unicode(ch2); if (ch2 < 32) wch2 = 0x00b7; wchars[j * 2 + 1] = wch2; address += 2; x += 7 * cxChar; }