trunk/src/osd/sdl/debugqtview.c
| r20288 | r20289 | |
| 3 | 3 | #include "debugqtview.h" |
| 4 | 4 | |
| 5 | 5 | |
| 6 | | DebuggerView::DebuggerView(const debug_view_type& type, |
| 7 | | running_machine* machine, |
| 8 | | QWidget* parent) : |
| 9 | | QAbstractScrollArea(parent), |
| 10 | | m_preferBottom(false), |
| 11 | | m_view(NULL), |
| 12 | | m_machine(machine) |
| 6 | DebuggerView::DebuggerView(const debug_view_type& type, |
| 7 | running_machine* machine, |
| 8 | QWidget* parent) : |
| 9 | QAbstractScrollArea(parent), |
| 10 | m_preferBottom(false), |
| 11 | m_view(NULL), |
| 12 | m_machine(machine) |
| 13 | 13 | { |
| 14 | | QFont viewFontRequest("Courier"); |
| 15 | | viewFontRequest.setFixedPitch(true); |
| 16 | | viewFontRequest.setPointSize(12); |
| 17 | | setFont(viewFontRequest); |
| 14 | // I like setting the font per-view since it doesn't override the menuing fonts. |
| 15 | QFont viewFontRequest("Courier New"); |
| 16 | viewFontRequest.setFixedPitch(true); |
| 17 | viewFontRequest.setPointSize(11); |
| 18 | setFont(viewFontRequest); |
| 18 | 19 | |
| 19 | | m_view = m_machine->debug_view().alloc_view(type, |
| 20 | | DebuggerView::debuggerViewUpdate, |
| 21 | | this); |
| 20 | m_view = m_machine->debug_view().alloc_view(type, |
| 21 | DebuggerView::debuggerViewUpdate, |
| 22 | this); |
| 23 | |
| 24 | connect(verticalScrollBar(), SIGNAL(valueChanged(int)), |
| 25 | this, SLOT(verticalScrollSlot(int))); |
| 26 | connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), |
| 27 | this, SLOT(horizontalScrollSlot(int))); |
| 22 | 28 | } |
| 23 | 29 | |
| 24 | 30 | |
| 25 | 31 | void DebuggerView::paintEvent(QPaintEvent* event) |
| 26 | 32 | { |
| 27 | | // Tell the MAME debug view how much real estate is available |
| 28 | | QFontMetrics actualFont = fontMetrics(); |
| 29 | | const int fontWidth = MAX(1, actualFont.maxWidth()); |
| 30 | | const int fontHeight = MAX(1, actualFont.height()); |
| 31 | | m_view->set_visible_size(debug_view_xy(width()/fontWidth, height()/fontHeight)); |
| 33 | // Tell the MAME debug view how much real estate is available |
| 34 | QFontMetrics actualFont = fontMetrics(); |
| 35 | const int fontWidth = MAX(1, actualFont.maxWidth()); |
| 36 | const int fontHeight = MAX(1, actualFont.height()); |
| 37 | m_view->set_visible_size(debug_view_xy(width()/fontWidth, height()/fontHeight)); |
| 32 | 38 | |
| 33 | 39 | |
| 34 | | // Handle the scroll bars |
| 35 | | const int verticalScrollCharDiff = m_view->total_size().y - m_view->visible_size().y; |
| 36 | | const int scrollSize = verticalScrollCharDiff < 0 ? 0 : verticalScrollCharDiff; |
| 37 | | bool atEnd = false; |
| 38 | | if (verticalScrollBar()->value() == verticalScrollBar()->maximum()) |
| 39 | | { |
| 40 | | atEnd = true; |
| 41 | | } |
| 42 | | verticalScrollBar()->setRange(0, scrollSize); |
| 43 | | if (m_preferBottom && atEnd) |
| 44 | | { |
| 45 | | verticalScrollBar()->setValue(scrollSize); |
| 46 | | } |
| 47 | | m_view->set_visible_position(debug_view_xy(0, verticalScrollBar()->value())); |
| 40 | // Handle the scroll bars |
| 41 | const int verticalScrollCharDiff = m_view->total_size().y - m_view->visible_size().y; |
| 42 | const int scrollSize = verticalScrollCharDiff < 0 ? 0 : verticalScrollCharDiff; |
| 43 | bool atEnd = false; |
| 44 | if (verticalScrollBar()->value() == verticalScrollBar()->maximum()) |
| 45 | { |
| 46 | atEnd = true; |
| 47 | } |
| 48 | verticalScrollBar()->setRange(0, scrollSize); |
| 49 | if (m_preferBottom && atEnd) |
| 50 | { |
| 51 | verticalScrollBar()->setValue(scrollSize); |
| 52 | } |
| 48 | 53 | |
| 49 | 54 | |
| 50 | | // Draw the viewport widget |
| 51 | | QPainter painter(viewport()); |
| 52 | | painter.fillRect(0, 0, width(), height(), QBrush(Qt::white)); |
| 53 | | painter.setBackgroundMode(Qt::OpaqueMode); |
| 54 | | painter.setBackground(QColor(255,255,255)); |
| 55 | // Draw the viewport widget |
| 56 | QPainter painter(viewport()); |
| 57 | painter.fillRect(0, 0, width(), height(), QBrush(Qt::white)); |
| 58 | painter.setBackgroundMode(Qt::OpaqueMode); |
| 59 | painter.setBackground(QColor(255,255,255)); |
| 55 | 60 | |
| 56 | | // Background control |
| 57 | | QBrush bgBrush; |
| 58 | | bgBrush.setStyle(Qt::SolidPattern); |
| 59 | | painter.setPen(QPen(QColor(0,0,0))); |
| 61 | // Background control |
| 62 | QBrush bgBrush; |
| 63 | bgBrush.setStyle(Qt::SolidPattern); |
| 64 | painter.setPen(QPen(QColor(0,0,0))); |
| 60 | 65 | |
| 61 | | size_t viewDataOffset = 0; |
| 62 | | const debug_view_xy& visibleCharDims = m_view->visible_size(); |
| 63 | | for (int y = 0; y < visibleCharDims.y; y++) |
| 64 | | { |
| 65 | | for (int x = 0; x < visibleCharDims.x; x++) |
| 66 | | { |
| 67 | | const unsigned char textAttr = m_view->viewdata()[viewDataOffset].attrib; |
| 66 | size_t viewDataOffset = 0; |
| 67 | const debug_view_xy& visibleCharDims = m_view->visible_size(); |
| 68 | for (int y = 0; y < visibleCharDims.y; y++) |
| 69 | { |
| 70 | for (int x = 0; x < visibleCharDims.x; x++) |
| 71 | { |
| 72 | const unsigned char textAttr = m_view->viewdata()[viewDataOffset].attrib; |
| 68 | 73 | |
| 69 | | if (x == 0 || textAttr != m_view->viewdata()[viewDataOffset-1].attrib) |
| 70 | | { |
| 71 | | // Text color handling |
| 72 | | QColor fgColor(0,0,0); |
| 73 | | QColor bgColor(255,255,255); |
| 74 | if (x == 0 || textAttr != m_view->viewdata()[viewDataOffset-1].attrib) |
| 75 | { |
| 76 | // Text color handling |
| 77 | QColor fgColor(0,0,0); |
| 78 | QColor bgColor(255,255,255); |
| 74 | 79 | |
| 75 | | if(textAttr & DCA_ANCILLARY) |
| 76 | | { |
| 77 | | bgColor.setRgb(0xe0, 0xe0, 0xe0); |
| 78 | | } |
| 79 | | if(textAttr & DCA_SELECTED) |
| 80 | | { |
| 81 | | bgColor.setRgb(0xff, 0x80, 0x80); |
| 82 | | } |
| 83 | | if(textAttr & DCA_CURRENT) |
| 84 | | { |
| 85 | | bgColor.setRgb(0xff, 0xff, 0x00); |
| 86 | | } |
| 87 | | if(textAttr & DCA_CHANGED) |
| 88 | | { |
| 89 | | fgColor.setRgb(0xff, 0x00, 0x00); |
| 90 | | } |
| 91 | | if(textAttr & DCA_INVALID) |
| 92 | | { |
| 93 | | fgColor.setRgb(0x00, 0x00, 0xff); |
| 94 | | } |
| 95 | | if(textAttr & DCA_DISABLED) |
| 96 | | { |
| 97 | | fgColor.setRgb((fgColor.red() + bgColor.red()) >> 1, |
| 98 | | (fgColor.green() + bgColor.green()) >> 1, |
| 99 | | (fgColor.blue() + bgColor.blue()) >> 1); |
| 100 | | } |
| 101 | | if(textAttr & DCA_COMMENT) |
| 102 | | { |
| 103 | | fgColor.setRgb(0x00, 0x80, 0x00); |
| 104 | | } |
| 80 | if(textAttr & DCA_ANCILLARY) |
| 81 | { |
| 82 | bgColor.setRgb(0xe0, 0xe0, 0xe0); |
| 83 | } |
| 84 | if(textAttr & DCA_SELECTED) |
| 85 | { |
| 86 | bgColor.setRgb(0xff, 0x80, 0x80); |
| 87 | } |
| 88 | if(textAttr & DCA_CURRENT) |
| 89 | { |
| 90 | bgColor.setRgb(0xff, 0xff, 0x00); |
| 91 | } |
| 92 | if(textAttr & DCA_CHANGED) |
| 93 | { |
| 94 | fgColor.setRgb(0xff, 0x00, 0x00); |
| 95 | } |
| 96 | if(textAttr & DCA_INVALID) |
| 97 | { |
| 98 | fgColor.setRgb(0x00, 0x00, 0xff); |
| 99 | } |
| 100 | if(textAttr & DCA_DISABLED) |
| 101 | { |
| 102 | fgColor.setRgb((fgColor.red() + bgColor.red()) >> 1, |
| 103 | (fgColor.green() + bgColor.green()) >> 1, |
| 104 | (fgColor.blue() + bgColor.blue()) >> 1); |
| 105 | } |
| 106 | if(textAttr & DCA_COMMENT) |
| 107 | { |
| 108 | fgColor.setRgb(0x00, 0x80, 0x00); |
| 109 | } |
| 105 | 110 | |
| 106 | | bgBrush.setColor(bgColor); |
| 107 | | painter.setBackground(bgBrush); |
| 108 | | painter.setPen(QPen(fgColor)); |
| 109 | | } |
| 111 | bgBrush.setColor(bgColor); |
| 112 | painter.setBackground(bgBrush); |
| 113 | painter.setPen(QPen(fgColor)); |
| 114 | } |
| 110 | 115 | |
| 111 | | // There is a touchy interplay between font height, drawing difference, visible position, etc |
| 112 | | // To test, set the bgcolor to something crazy and see where stuff gets drawn |
| 113 | | painter.drawText(x*fontWidth, |
| 114 | | y*fontHeight + fontHeight, |
| 115 | | QString(m_view->viewdata()[viewDataOffset].byte)); |
| 116 | | viewDataOffset++; |
| 117 | | } |
| 118 | | } |
| 116 | // Your character is not guaranteed to take up the entire fontWidth x fontHeight, so fill before. |
| 117 | painter.fillRect(x*fontWidth, y*fontHeight, fontWidth, fontHeight, bgBrush); |
| 118 | |
| 119 | // There is a touchy interplay between font height, drawing difference, visible position, etc |
| 120 | // Fonts don't get drawn "down and to the left" like boxes, so some wiggling is needed. |
| 121 | painter.drawText(x*fontWidth, |
| 122 | (y*fontHeight + (fontHeight*0.80)), |
| 123 | QString(m_view->viewdata()[viewDataOffset].byte)); |
| 124 | viewDataOffset++; |
| 125 | } |
| 126 | } |
| 119 | 127 | } |
| 120 | 128 | |
| 121 | 129 | |
| 122 | 130 | void DebuggerView::keyPressEvent(QKeyEvent* event) |
| 123 | 131 | { |
| 124 | | if (m_view == NULL) |
| 125 | | return QWidget::keyPressEvent(event); |
| 132 | if (m_view == NULL) |
| 133 | return QWidget::keyPressEvent(event); |
| 126 | 134 | |
| 127 | | Qt::KeyboardModifiers keyMods = QApplication::keyboardModifiers(); |
| 128 | | bool ctrlDown = keyMods.testFlag(Qt::ControlModifier); |
| 135 | Qt::KeyboardModifiers keyMods = QApplication::keyboardModifiers(); |
| 136 | const bool ctrlDown = keyMods.testFlag(Qt::ControlModifier); |
| 129 | 137 | |
| 130 | | int keyPress = -1; |
| 131 | | switch (event->key()) |
| 138 | int keyPress = -1; |
| 139 | switch (event->key()) |
| 140 | { |
| 141 | case Qt::Key_Up: |
| 142 | keyPress = DCH_UP; |
| 143 | break; |
| 144 | case Qt::Key_Down: |
| 145 | keyPress = DCH_DOWN; |
| 146 | break; |
| 147 | case Qt::Key_Left: |
| 148 | keyPress = DCH_LEFT; |
| 149 | if (ctrlDown) keyPress = DCH_CTRLLEFT; |
| 150 | break; |
| 151 | case Qt::Key_Right: |
| 152 | keyPress = DCH_RIGHT; |
| 153 | if (ctrlDown) keyPress = DCH_CTRLRIGHT; |
| 154 | break; |
| 155 | case Qt::Key_PageUp: |
| 156 | keyPress = DCH_PUP; |
| 157 | break; |
| 158 | case Qt::Key_PageDown: |
| 159 | keyPress = DCH_PDOWN; |
| 160 | break; |
| 161 | case Qt::Key_Home: |
| 162 | keyPress = DCH_HOME; |
| 163 | if (ctrlDown) keyPress = DCH_CTRLHOME; |
| 164 | break; |
| 165 | case Qt::Key_End: |
| 166 | keyPress = DCH_END; |
| 167 | if (ctrlDown) keyPress = DCH_CTRLEND; |
| 168 | break; |
| 169 | case Qt::Key_0: keyPress = '0'; break; |
| 170 | case Qt::Key_1: keyPress = '1'; break; |
| 171 | case Qt::Key_2: keyPress = '2'; break; |
| 172 | case Qt::Key_3: keyPress = '3'; break; |
| 173 | case Qt::Key_4: keyPress = '4'; break; |
| 174 | case Qt::Key_5: keyPress = '5'; break; |
| 175 | case Qt::Key_6: keyPress = '6'; break; |
| 176 | case Qt::Key_7: keyPress = '7'; break; |
| 177 | case Qt::Key_8: keyPress = '8'; break; |
| 178 | case Qt::Key_9: keyPress = '9'; break; |
| 179 | case Qt::Key_A: keyPress = 'a'; break; |
| 180 | case Qt::Key_B: keyPress = 'b'; break; |
| 181 | case Qt::Key_C: keyPress = 'c'; break; |
| 182 | case Qt::Key_D: keyPress = 'd'; break; |
| 183 | case Qt::Key_E: keyPress = 'e'; break; |
| 184 | case Qt::Key_F: keyPress = 'f'; break; |
| 185 | default: |
| 186 | return QWidget::keyPressEvent(event); |
| 187 | } |
| 188 | |
| 189 | m_view->set_cursor_visible(true); |
| 190 | m_view->process_char(keyPress); |
| 191 | |
| 192 | // Catch the view up with the cursor |
| 193 | verticalScrollBar()->setValue(m_view->visible_position().y); |
| 194 | |
| 195 | viewport()->update(); |
| 196 | update(); |
| 197 | } |
| 198 | |
| 199 | |
| 200 | void DebuggerView::mousePressEvent(QMouseEvent* event) |
| 201 | { |
| 202 | if (event->button() == Qt::LeftButton) |
| 132 | 203 | { |
| 133 | | case Qt::Key_Up: |
| 134 | | keyPress = DCH_UP; |
| 135 | | break; |
| 136 | | case Qt::Key_Down: |
| 137 | | keyPress = DCH_DOWN; |
| 138 | | break; |
| 139 | | case Qt::Key_Left: |
| 140 | | keyPress = DCH_LEFT; |
| 141 | | if (ctrlDown) keyPress = DCH_CTRLLEFT; |
| 142 | | break; |
| 143 | | case Qt::Key_Right: |
| 144 | | keyPress = DCH_RIGHT; |
| 145 | | if (ctrlDown) keyPress = DCH_CTRLRIGHT; |
| 146 | | break; |
| 147 | | case Qt::Key_PageUp: |
| 148 | | keyPress = DCH_PUP; |
| 149 | | break; |
| 150 | | case Qt::Key_PageDown: |
| 151 | | keyPress = DCH_PDOWN; |
| 152 | | break; |
| 153 | | case Qt::Key_Home: |
| 154 | | keyPress = DCH_HOME; |
| 155 | | if (ctrlDown) keyPress = DCH_CTRLHOME; |
| 156 | | break; |
| 157 | | case Qt::Key_End: |
| 158 | | keyPress = DCH_END; |
| 159 | | if (ctrlDown) keyPress = DCH_CTRLEND; |
| 160 | | break; |
| 161 | | case Qt::Key_0: keyPress = '0'; break; |
| 162 | | case Qt::Key_1: keyPress = '1'; break; |
| 163 | | case Qt::Key_2: keyPress = '2'; break; |
| 164 | | case Qt::Key_3: keyPress = '3'; break; |
| 165 | | case Qt::Key_4: keyPress = '4'; break; |
| 166 | | case Qt::Key_5: keyPress = '5'; break; |
| 167 | | case Qt::Key_6: keyPress = '6'; break; |
| 168 | | case Qt::Key_7: keyPress = '7'; break; |
| 169 | | case Qt::Key_8: keyPress = '8'; break; |
| 170 | | case Qt::Key_9: keyPress = '9'; break; |
| 171 | | case Qt::Key_A: keyPress = 'a'; break; |
| 172 | | case Qt::Key_B: keyPress = 'b'; break; |
| 173 | | case Qt::Key_C: keyPress = 'c'; break; |
| 174 | | case Qt::Key_D: keyPress = 'd'; break; |
| 175 | | case Qt::Key_E: keyPress = 'e'; break; |
| 176 | | case Qt::Key_F: keyPress = 'f'; break; |
| 177 | | default: |
| 178 | | return QWidget::keyPressEvent(event); |
| 204 | QFontMetrics actualFont = fontMetrics(); |
| 205 | const int fontWidth = MAX(1, actualFont.maxWidth()); |
| 206 | const int fontHeight = MAX(1, actualFont.height()); |
| 207 | |
| 208 | debug_view_xy topLeft = m_view->visible_position(); |
| 209 | debug_view_xy clickViewPosition; |
| 210 | clickViewPosition.x = topLeft.x + (event->x() / fontWidth); |
| 211 | clickViewPosition.y = topLeft.y + (event->y() / fontHeight); |
| 212 | m_view->process_click(DCK_LEFT_CLICK, clickViewPosition); |
| 213 | |
| 214 | viewport()->update(); |
| 215 | update(); |
| 179 | 216 | } |
| 217 | } |
| 180 | 218 | |
| 181 | | m_view->set_cursor_visible(true); |
| 182 | | m_view->process_char(keyPress); |
| 183 | 219 | |
| 184 | | // Catch the view up with the cursor |
| 185 | | verticalScrollBar()->setValue(m_view->visible_position().y); |
| 220 | void DebuggerView::verticalScrollSlot(int value) |
| 221 | { |
| 222 | m_view->set_visible_position(debug_view_xy(horizontalScrollBar()->value(), value)); |
| 223 | } |
| 186 | 224 | |
| 187 | | viewport()->update(); |
| 188 | | update(); |
| 225 | |
| 226 | void DebuggerView::horizontalScrollSlot(int value) |
| 227 | { |
| 228 | m_view->set_visible_position(debug_view_xy(value, verticalScrollBar()->value())); |
| 189 | 229 | } |
| 190 | 230 | |
| 191 | 231 | |
| 192 | 232 | void DebuggerView::debuggerViewUpdate(debug_view& debugView, void* osdPrivate) |
| 193 | 233 | { |
| 194 | | // Get a handle to the DebuggerView being updated & redraw |
| 195 | | DebuggerView* dView = (DebuggerView*)osdPrivate; |
| 196 | | dView->verticalScrollBar()->setValue(dView->view()->visible_position().y); |
| 197 | | dView->viewport()->update(); |
| 198 | | dView->update(); |
| 234 | // Get a handle to the DebuggerView being updated & redraw |
| 235 | DebuggerView* dView = (DebuggerView*)osdPrivate; |
| 236 | dView->verticalScrollBar()->setValue(dView->view()->visible_position().y); |
| 237 | dView->viewport()->update(); |
| 238 | dView->update(); |
| 199 | 239 | } |
| 240 | |
| 241 | |
trunk/src/osd/sdl/debugqtmainwindow.c
| r20288 | r20289 | |
| 4 | 4 | #include "debug/dvdisasm.h" |
| 5 | 5 | |
| 6 | 6 | |
| 7 | | MainWindow::MainWindow(device_t* processor, |
| 8 | | running_machine* machine, |
| 9 | | QWidget* parent) : |
| 10 | | WindowQt(machine, parent), |
| 11 | | m_historyIndex(0), |
| 12 | | m_inputHistory() |
| 7 | MainWindow::MainWindow(device_t* processor, |
| 8 | running_machine* machine, |
| 9 | QWidget* parent) : |
| 10 | WindowQt(machine, parent), |
| 11 | m_historyIndex(0), |
| 12 | m_inputHistory() |
| 13 | 13 | { |
| 14 | | setGeometry(300, 300, 1000, 600); |
| 14 | setGeometry(300, 300, 1000, 600); |
| 15 | 15 | |
| 16 | | // |
| 17 | | // The main frame and its input and log widgets |
| 18 | | // |
| 19 | | QFrame* mainWindowFrame = new QFrame(this); |
| 16 | // |
| 17 | // The main frame and its input and log widgets |
| 18 | // |
| 19 | QFrame* mainWindowFrame = new QFrame(this); |
| 20 | 20 | |
| 21 | | // The input line |
| 22 | | m_inputEdit = new QLineEdit(mainWindowFrame); |
| 23 | | connect(m_inputEdit, SIGNAL(returnPressed()), this, SLOT(executeCommand())); |
| 24 | | m_inputEdit->installEventFilter(this); |
| 21 | // The input line |
| 22 | m_inputEdit = new QLineEdit(mainWindowFrame); |
| 23 | connect(m_inputEdit, SIGNAL(returnPressed()), this, SLOT(executeCommand())); |
| 24 | m_inputEdit->installEventFilter(this); |
| 25 | 25 | |
| 26 | 26 | |
| 27 | | // The log view |
| 28 | | m_consoleView = new DebuggerView(DVT_CONSOLE, |
| 29 | | m_machine, |
| 30 | | mainWindowFrame); |
| 31 | | m_consoleView->setFocusPolicy(Qt::NoFocus); |
| 32 | | m_consoleView->setPreferBottom(true); |
| 27 | // The log view |
| 28 | m_consoleView = new DebuggerView(DVT_CONSOLE, |
| 29 | m_machine, |
| 30 | mainWindowFrame); |
| 31 | m_consoleView->setFocusPolicy(Qt::NoFocus); |
| 32 | m_consoleView->setPreferBottom(true); |
| 33 | 33 | |
| 34 | | QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); |
| 35 | | vLayout->addWidget(m_consoleView); |
| 36 | | vLayout->addWidget(m_inputEdit); |
| 37 | | vLayout->setSpacing(3); |
| 38 | | vLayout->setContentsMargins(4,0,4,2); |
| 34 | QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame); |
| 35 | vLayout->addWidget(m_consoleView); |
| 36 | vLayout->addWidget(m_inputEdit); |
| 37 | vLayout->setSpacing(3); |
| 38 | vLayout->setContentsMargins(4,0,4,2); |
| 39 | 39 | |
| 40 | | setCentralWidget(mainWindowFrame); |
| 40 | setCentralWidget(mainWindowFrame); |
| 41 | 41 | |
| 42 | | // |
| 43 | | // Menu bars |
| 44 | | // |
| 45 | | // Create two commands |
| 46 | | QAction* breakpointSetAct = new QAction("Toggle Breakpoint At Cursor", this); |
| 47 | | QAction* runToCursorAct = new QAction("Run To Cursor", this); |
| 48 | | breakpointSetAct->setShortcut(Qt::Key_F9); |
| 49 | | runToCursorAct->setShortcut(Qt::Key_F4); |
| 50 | | connect(breakpointSetAct, SIGNAL(triggered(bool)), this, SLOT(toggleBreakpointAtCursor(bool))); |
| 51 | | connect(runToCursorAct, SIGNAL(triggered(bool)), this, SLOT(runToCursor(bool))); |
| 42 | // |
| 43 | // Menu bars |
| 44 | // |
| 45 | // Create two commands |
| 46 | QAction* breakpointSetAct = new QAction("Toggle Breakpoint At Cursor", this); |
| 47 | QAction* runToCursorAct = new QAction("Run To Cursor", this); |
| 48 | breakpointSetAct->setShortcut(Qt::Key_F9); |
| 49 | runToCursorAct->setShortcut(Qt::Key_F4); |
| 50 | connect(breakpointSetAct, SIGNAL(triggered(bool)), this, SLOT(toggleBreakpointAtCursor(bool))); |
| 51 | connect(runToCursorAct, SIGNAL(triggered(bool)), this, SLOT(runToCursor(bool))); |
| 52 | 52 | |
| 53 | | // Right bar options |
| 54 | | QActionGroup* rightBarGroup = new QActionGroup(this); |
| 55 | | QAction* rightActRaw = new QAction("Raw Opcodes", this); |
| 56 | | QAction* rightActEncrypted = new QAction("Encrypted Opcodes", this); |
| 57 | | QAction* rightActComments = new QAction("Comments", this); |
| 58 | | rightActRaw->setCheckable(true); |
| 59 | | rightActEncrypted->setCheckable(true); |
| 60 | | rightActComments->setCheckable(true); |
| 61 | | rightActRaw->setActionGroup(rightBarGroup); |
| 62 | | rightActEncrypted->setActionGroup(rightBarGroup); |
| 63 | | rightActComments->setActionGroup(rightBarGroup); |
| 64 | | rightActRaw->setShortcut(QKeySequence("Ctrl+R")); |
| 65 | | rightActEncrypted->setShortcut(QKeySequence("Ctrl+E")); |
| 66 | | rightActComments->setShortcut(QKeySequence("Ctrl+C")); |
| 67 | | rightActRaw->setChecked(true); |
| 68 | | connect(rightBarGroup, SIGNAL(triggered(QAction*)), this, SLOT(rightBarChanged(QAction*))); |
| 53 | // Right bar options |
| 54 | QActionGroup* rightBarGroup = new QActionGroup(this); |
| 55 | QAction* rightActRaw = new QAction("Raw Opcodes", this); |
| 56 | QAction* rightActEncrypted = new QAction("Encrypted Opcodes", this); |
| 57 | QAction* rightActComments = new QAction("Comments", this); |
| 58 | rightActRaw->setCheckable(true); |
| 59 | rightActEncrypted->setCheckable(true); |
| 60 | rightActComments->setCheckable(true); |
| 61 | rightActRaw->setActionGroup(rightBarGroup); |
| 62 | rightActEncrypted->setActionGroup(rightBarGroup); |
| 63 | rightActComments->setActionGroup(rightBarGroup); |
| 64 | rightActRaw->setShortcut(QKeySequence("Ctrl+R")); |
| 65 | rightActEncrypted->setShortcut(QKeySequence("Ctrl+E")); |
| 66 | rightActComments->setShortcut(QKeySequence("Ctrl+C")); |
| 67 | rightActRaw->setChecked(true); |
| 68 | connect(rightBarGroup, SIGNAL(triggered(QAction*)), this, SLOT(rightBarChanged(QAction*))); |
| 69 | 69 | |
| 70 | | // Assemble the options menu |
| 71 | | QMenu* optionsMenu = menuBar()->addMenu("&Options"); |
| 72 | | optionsMenu->addAction(breakpointSetAct); |
| 73 | | optionsMenu->addAction(runToCursorAct); |
| 74 | | optionsMenu->addSeparator(); |
| 75 | | optionsMenu->addActions(rightBarGroup->actions()); |
| 70 | // Assemble the options menu |
| 71 | QMenu* optionsMenu = menuBar()->addMenu("&Options"); |
| 72 | optionsMenu->addAction(breakpointSetAct); |
| 73 | optionsMenu->addAction(runToCursorAct); |
| 74 | optionsMenu->addSeparator(); |
| 75 | optionsMenu->addActions(rightBarGroup->actions()); |
| 76 | 76 | |
| 77 | 77 | |
| 78 | | // |
| 79 | | // Dock windows |
| 80 | | // |
| 81 | | QMenu* dockMenu = menuBar()->addMenu("Doc&ks"); |
| 78 | // |
| 79 | // Dock windows |
| 80 | // |
| 81 | QMenu* dockMenu = menuBar()->addMenu("Doc&ks"); |
| 82 | 82 | |
| 83 | | setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea); |
| 84 | | setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); |
| 83 | setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea); |
| 84 | setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); |
| 85 | 85 | |
| 86 | | // The processor dock |
| 87 | | QDockWidget* cpuDock = new QDockWidget("processor", this); |
| 88 | | cpuDock->setAllowedAreas(Qt::LeftDockWidgetArea); |
| 89 | | m_procFrame = new ProcessorDockWidget(m_machine, cpuDock); |
| 90 | | cpuDock->setWidget(dynamic_cast<QWidget*>(m_procFrame)); |
| 86 | // The processor dock |
| 87 | QDockWidget* cpuDock = new QDockWidget("processor", this); |
| 88 | cpuDock->setAllowedAreas(Qt::LeftDockWidgetArea); |
| 89 | m_procFrame = new ProcessorDockWidget(m_machine, cpuDock); |
| 90 | cpuDock->setWidget(dynamic_cast<QWidget*>(m_procFrame)); |
| 91 | 91 | |
| 92 | | addDockWidget(Qt::LeftDockWidgetArea, cpuDock); |
| 93 | | dockMenu->addAction(cpuDock->toggleViewAction()); |
| 92 | addDockWidget(Qt::LeftDockWidgetArea, cpuDock); |
| 93 | dockMenu->addAction(cpuDock->toggleViewAction()); |
| 94 | 94 | |
| 95 | | // The disassembly dock |
| 96 | | QDockWidget* dasmDock = new QDockWidget("dasm", this); |
| 97 | | dasmDock->setAllowedAreas(Qt::TopDockWidgetArea); |
| 98 | | m_dasmFrame = new DasmDockWidget(m_machine, dasmDock); |
| 99 | | dasmDock->setWidget(m_dasmFrame); |
| 95 | // The disassembly dock |
| 96 | QDockWidget* dasmDock = new QDockWidget("dasm", this); |
| 97 | dasmDock->setAllowedAreas(Qt::TopDockWidgetArea); |
| 98 | m_dasmFrame = new DasmDockWidget(m_machine, dasmDock); |
| 99 | dasmDock->setWidget(m_dasmFrame); |
| 100 | 100 | |
| 101 | | addDockWidget(Qt::TopDockWidgetArea, dasmDock); |
| 102 | | dockMenu->addAction(dasmDock->toggleViewAction()); |
| 101 | addDockWidget(Qt::TopDockWidgetArea, dasmDock); |
| 102 | dockMenu->addAction(dasmDock->toggleViewAction()); |
| 103 | 103 | |
| 104 | | // Window title |
| 105 | | astring title; |
| 106 | | title.printf("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag()); |
| 107 | | setWindowTitle(title.cstr()); |
| 104 | // Window title |
| 105 | astring title; |
| 106 | title.printf("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag()); |
| 107 | setWindowTitle(title.cstr()); |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | |
| 111 | 111 | void MainWindow::setProcessor(device_t* processor) |
| 112 | 112 | { |
| 113 | | // Cpu swap |
| 114 | | m_procFrame->view()->view()->set_source(*m_procFrame->view()->view()->source_list().match_device(processor)); |
| 115 | | m_dasmFrame->view()->view()->set_source(*m_dasmFrame->view()->view()->source_list().match_device(processor)); |
| 113 | // Cpu swap |
| 114 | m_procFrame->view()->view()->set_source(*m_procFrame->view()->view()->source_list().match_device(processor)); |
| 115 | m_dasmFrame->view()->view()->set_source(*m_dasmFrame->view()->view()->source_list().match_device(processor)); |
| 116 | 116 | |
| 117 | | // Scrollbar refresh - seems I should be able to do in the DebuggerView |
| 118 | | m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y); |
| 119 | | m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y); |
| 117 | // Scrollbar refresh - seems I should be able to do in the DebuggerView |
| 118 | m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y); |
| 119 | m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y); |
| 120 | 120 | |
| 121 | | // Window title |
| 122 | | astring title; |
| 123 | | title.printf("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag()); |
| 124 | | setWindowTitle(title.cstr()); |
| 121 | // Window title |
| 122 | astring title; |
| 123 | title.printf("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag()); |
| 124 | setWindowTitle(title.cstr()); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | |
| 128 | 128 | // Used to intercept the user clicking 'X' in the upper corner |
| 129 | 129 | void MainWindow::closeEvent(QCloseEvent* event) |
| 130 | 130 | { |
| 131 | | debugActQuit(); |
| 131 | debugActQuit(); |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | |
| 135 | 135 | // Used to intercept the user hitting the up arrow in the input widget |
| 136 | 136 | bool MainWindow::eventFilter(QObject* obj, QEvent* event) |
| 137 | 137 | { |
| 138 | | // Only filter keypresses |
| 139 | | QKeyEvent* keyEvent = NULL; |
| 140 | | if (event->type() == QEvent::KeyPress) |
| 141 | | { |
| 142 | | keyEvent = static_cast<QKeyEvent*>(event); |
| 143 | | } |
| 144 | | else |
| 145 | | { |
| 146 | | return QObject::eventFilter(obj, event); |
| 147 | | } |
| 138 | // Only filter keypresses |
| 139 | QKeyEvent* keyEvent = NULL; |
| 140 | if (event->type() == QEvent::KeyPress) |
| 141 | { |
| 142 | keyEvent = static_cast<QKeyEvent*>(event); |
| 143 | } |
| 144 | else |
| 145 | { |
| 146 | return QObject::eventFilter(obj, event); |
| 147 | } |
| 148 | 148 | |
| 149 | | // Catch up & down keys |
| 150 | | if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) |
| 151 | | { |
| 152 | | if (keyEvent->key() == Qt::Key_Up) |
| 153 | | { |
| 154 | | if (m_historyIndex > 0) |
| 155 | | m_historyIndex--; |
| 156 | | } |
| 157 | | else if (keyEvent->key() == Qt::Key_Down) |
| 158 | | { |
| 159 | | if (m_historyIndex < m_inputHistory.size()) |
| 160 | | m_historyIndex++; |
| 161 | | } |
| 149 | // Catch up & down keys |
| 150 | if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) |
| 151 | { |
| 152 | if (keyEvent->key() == Qt::Key_Up) |
| 153 | { |
| 154 | if (m_historyIndex > 0) |
| 155 | m_historyIndex--; |
| 156 | } |
| 157 | else if (keyEvent->key() == Qt::Key_Down) |
| 158 | { |
| 159 | if (m_historyIndex < m_inputHistory.size()) |
| 160 | m_historyIndex++; |
| 161 | } |
| 162 | 162 | |
| 163 | | // Populate the input edit or clear it if you're at the end |
| 164 | | if (m_historyIndex == m_inputHistory.size()) |
| 165 | | { |
| 166 | | m_inputEdit->setText(""); |
| 167 | | } |
| 168 | | else |
| 169 | | { |
| 170 | | m_inputEdit->setText(m_inputHistory[m_historyIndex]); |
| 171 | | } |
| 172 | | } |
| 173 | | else if (keyEvent->key() == Qt::Key_Enter) |
| 174 | | { |
| 175 | | executeCommand(false); |
| 176 | | } |
| 177 | | else |
| 178 | | { |
| 179 | | return QObject::eventFilter(obj, event); |
| 180 | | } |
| 181 | | |
| 182 | | return true; |
| 163 | // Populate the input edit or clear it if you're at the end |
| 164 | if (m_historyIndex == m_inputHistory.size()) |
| 165 | { |
| 166 | m_inputEdit->setText(""); |
| 167 | } |
| 168 | else |
| 169 | { |
| 170 | m_inputEdit->setText(m_inputHistory[m_historyIndex]); |
| 171 | } |
| 172 | } |
| 173 | else if (keyEvent->key() == Qt::Key_Enter) |
| 174 | { |
| 175 | executeCommand(false); |
| 176 | } |
| 177 | else |
| 178 | { |
| 179 | return QObject::eventFilter(obj, event); |
| 180 | } |
| 181 | |
| 182 | return true; |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | 185 | |
| 186 | 186 | void MainWindow::toggleBreakpointAtCursor(bool changedTo) |
| 187 | 187 | { |
| 188 | | debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); |
| 189 | | if (dasmView->cursor_visible()) |
| 190 | | { |
| 191 | | if (debug_cpu_get_visible_cpu(*m_machine) == dasmView->source()->device()) |
| 192 | | { |
| 193 | | offs_t address = downcast<debug_view_disasm *>(dasmView)->selected_address(); |
| 194 | | device_debug *cpuinfo = dasmView->source()->device()->debug(); |
| 188 | debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); |
| 189 | if (dasmView->cursor_visible()) |
| 190 | { |
| 191 | if (debug_cpu_get_visible_cpu(*m_machine) == dasmView->source()->device()) |
| 192 | { |
| 193 | offs_t address = downcast<debug_view_disasm *>(dasmView)->selected_address(); |
| 194 | device_debug *cpuinfo = dasmView->source()->device()->debug(); |
| 195 | 195 | |
| 196 | | // Find an existing breakpoint at this address |
| 197 | | INT32 bpindex = -1; |
| 198 | | for (device_debug::breakpoint* bp = cpuinfo->breakpoint_first(); |
| 199 | | bp != NULL; |
| 200 | | bp = bp->next()) |
| 201 | | { |
| 202 | | if (address == bp->address()) |
| 203 | | { |
| 204 | | bpindex = bp->index(); |
| 205 | | break; |
| 206 | | } |
| 207 | | } |
| 196 | // Find an existing breakpoint at this address |
| 197 | INT32 bpindex = -1; |
| 198 | for (device_debug::breakpoint* bp = cpuinfo->breakpoint_first(); |
| 199 | bp != NULL; |
| 200 | bp = bp->next()) |
| 201 | { |
| 202 | if (address == bp->address()) |
| 203 | { |
| 204 | bpindex = bp->index(); |
| 205 | break; |
| 206 | } |
| 207 | } |
| 208 | 208 | |
| 209 | | // If none exists, add a new one |
| 210 | | astring command; |
| 211 | | if (bpindex == -1) |
| 212 | | { |
| 213 | | command.printf("bpset 0x%X", address); |
| 214 | | } |
| 215 | | else |
| 216 | | { |
| 217 | | command.printf("bpclear 0x%X", bpindex); |
| 218 | | } |
| 219 | | debug_console_execute_command(*m_machine, command, 1); |
| 220 | | } |
| 221 | | } |
| 209 | // If none exists, add a new one |
| 210 | astring command; |
| 211 | if (bpindex == -1) |
| 212 | { |
| 213 | command.printf("bpset 0x%X", address); |
| 214 | } |
| 215 | else |
| 216 | { |
| 217 | command.printf("bpclear 0x%X", bpindex); |
| 218 | } |
| 219 | debug_console_execute_command(*m_machine, command, 1); |
| 220 | } |
| 221 | } |
| 222 | 222 | |
| 223 | | refreshAll(); |
| 223 | refreshAll(); |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | 226 | |
| 227 | 227 | void MainWindow::runToCursor(bool changedTo) |
| 228 | 228 | { |
| 229 | | debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); |
| 230 | | if (dasmView->cursor_visible()) |
| 231 | | { |
| 232 | | if (debug_cpu_get_visible_cpu(*m_machine) == dasmView->source()->device()) |
| 233 | | { |
| 234 | | offs_t address = downcast<debug_view_disasm*>(dasmView)->selected_address(); |
| 235 | | astring command; |
| 236 | | command.printf("go 0x%X", address); |
| 237 | | debug_console_execute_command(*m_machine, command, 1); |
| 238 | | } |
| 239 | | } |
| 229 | debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); |
| 230 | if (dasmView->cursor_visible()) |
| 231 | { |
| 232 | if (debug_cpu_get_visible_cpu(*m_machine) == dasmView->source()->device()) |
| 233 | { |
| 234 | offs_t address = downcast<debug_view_disasm*>(dasmView)->selected_address(); |
| 235 | astring command; |
| 236 | command.printf("go 0x%X", address); |
| 237 | debug_console_execute_command(*m_machine, command, 1); |
| 238 | } |
| 239 | } |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | |
| 243 | 243 | void MainWindow::rightBarChanged(QAction* changedTo) |
| 244 | 244 | { |
| 245 | | debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); |
| 246 | | if (changedTo->text() == "Raw Opcodes") |
| 247 | | { |
| 248 | | dasmView->set_right_column(DASM_RIGHTCOL_RAW); |
| 249 | | } |
| 250 | | else if (changedTo->text() == "Encrypted Opcodes") |
| 251 | | { |
| 252 | | dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED); |
| 253 | | } |
| 254 | | else if (changedTo->text() == "Comments") |
| 255 | | { |
| 256 | | dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS); |
| 257 | | } |
| 258 | | m_dasmFrame->view()->viewport()->update(); |
| 245 | debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view()); |
| 246 | if (changedTo->text() == "Raw Opcodes") |
| 247 | { |
| 248 | dasmView->set_right_column(DASM_RIGHTCOL_RAW); |
| 249 | } |
| 250 | else if (changedTo->text() == "Encrypted Opcodes") |
| 251 | { |
| 252 | dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED); |
| 253 | } |
| 254 | else if (changedTo->text() == "Comments") |
| 255 | { |
| 256 | dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS); |
| 257 | } |
| 258 | m_dasmFrame->view()->viewport()->update(); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | 261 | |
| 262 | 262 | void MainWindow::executeCommand(bool withClear) |
| 263 | 263 | { |
| 264 | | debug_console_execute_command(*m_machine, |
| 265 | | m_inputEdit->text().toLocal8Bit().data(), |
| 266 | | true); |
| 264 | if (m_inputEdit->text() == "") |
| 265 | { |
| 266 | debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step(); |
| 267 | return; |
| 268 | } |
| 269 | |
| 270 | debug_console_execute_command(*m_machine, |
| 271 | m_inputEdit->text().toLocal8Bit().data(), |
| 272 | true); |
| 267 | 273 | |
| 268 | | // Add history & set the index to be the top of the stack |
| 269 | | addToHistory(m_inputEdit->text()); |
| 274 | // Add history & set the index to be the top of the stack |
| 275 | addToHistory(m_inputEdit->text()); |
| 270 | 276 | |
| 271 | | // Clear out the text and reset the history pointer only if asked |
| 272 | | if (withClear) |
| 273 | | { |
| 274 | | m_inputEdit->clear(); |
| 275 | | m_historyIndex = m_inputHistory.size(); |
| 276 | | } |
| 277 | // Clear out the text and reset the history pointer only if asked |
| 278 | if (withClear) |
| 279 | { |
| 280 | m_inputEdit->clear(); |
| 281 | m_historyIndex = m_inputHistory.size(); |
| 282 | } |
| 277 | 283 | |
| 278 | | // Refresh |
| 279 | | m_consoleView->viewport()->update(); |
| 280 | | m_procFrame->view()->update(); |
| 281 | | m_dasmFrame->view()->update(); |
| 284 | // Refresh |
| 285 | m_consoleView->viewport()->update(); |
| 286 | m_procFrame->view()->update(); |
| 287 | m_dasmFrame->view()->update(); |
| 282 | 288 | } |
| 283 | 289 | |
| 284 | 290 | |
| 285 | 291 | void MainWindow::addToHistory(const QString& command) |
| 286 | 292 | { |
| 287 | | if (command == "") |
| 288 | | return; |
| 293 | if (command == "") |
| 294 | return; |
| 295 | |
| 296 | // Always push back when there is no previous history |
| 297 | if (m_inputHistory.size() == 0) |
| 298 | { |
| 299 | m_inputHistory.push_back(m_inputEdit->text()); |
| 300 | return; |
| 301 | } |
| 289 | 302 | |
| 290 | | // Always push back when there is no previous history |
| 291 | | if (m_inputHistory.size() == 0) |
| 292 | | { |
| 293 | | m_inputHistory.push_back(m_inputEdit->text()); |
| 294 | | return; |
| 295 | | } |
| 296 | | |
| 297 | | // If there is previous history, make sure it's not what you just executed |
| 298 | | if (m_inputHistory.back() != m_inputEdit->text()) |
| 299 | | { |
| 300 | | m_inputHistory.push_back(m_inputEdit->text()); |
| 301 | | } |
| 303 | // If there is previous history, make sure it's not what you just executed |
| 304 | if (m_inputHistory.back() != m_inputEdit->text()) |
| 305 | { |
| 306 | m_inputHistory.push_back(m_inputEdit->text()); |
| 307 | } |
| 302 | 308 | } |
trunk/src/emu/debug/debugvw.h
| r20288 | r20289 | |
| 72 | 72 | |
| 73 | 73 | |
| 74 | 74 | // attribute bits for debug_view_char.attrib |
| 75 | | const UINT8 DCA_NORMAL = 0x00; // in Windows: black on white |
| 76 | | const UINT8 DCA_CHANGED = 0x01; // in Windows: red foreground |
| 77 | | const UINT8 DCA_SELECTED = 0x02; // in Windows: light red background |
| 78 | | const UINT8 DCA_INVALID = 0x04; // in Windows: dark blue foreground |
| 79 | | const UINT8 DCA_DISABLED = 0x08; // in Windows: darker foreground |
| 80 | | const UINT8 DCA_ANCILLARY = 0x10; // in Windows: grey background |
| 81 | | const UINT8 DCA_CURRENT = 0x20; // in Windows: yellow background |
| 82 | | const UINT8 DCA_COMMENT = 0x40; // in Windows: green foreground |
| 75 | const UINT8 DCA_NORMAL = 0x00; // in Windows: black on white |
| 76 | const UINT8 DCA_CHANGED = 0x01; // in Windows: red foreground |
| 77 | const UINT8 DCA_SELECTED = 0x02; // in Windows: light red background |
| 78 | const UINT8 DCA_INVALID = 0x04; // in Windows: dark blue foreground |
| 79 | const UINT8 DCA_DISABLED = 0x08; // in Windows: darker foreground |
| 80 | const UINT8 DCA_ANCILLARY = 0x10; // in Windows: grey background |
| 81 | const UINT8 DCA_CURRENT = 0x20; // in Windows: yellow background |
| 82 | const UINT8 DCA_COMMENT = 0x40; // in Windows: green foreground |
| 83 | 83 | |
| 84 | 84 | |
| 85 | 85 | // special characters that can be passed to process_char() |
| 86 | | const int DCH_UP = 1; // up arrow |
| 87 | | const int DCH_DOWN = 2; // down arrow |
| 88 | | const int DCH_LEFT = 3; // left arrow |
| 89 | | const int DCH_RIGHT = 4; // right arrow |
| 90 | | const int DCH_PUP = 5; // page up |
| 91 | | const int DCH_PDOWN = 6; // page down |
| 92 | | const int DCH_HOME = 7; // home |
| 93 | | const int DCH_CTRLHOME = 8; // ctrl+home |
| 94 | | const int DCH_END = 9; // end |
| 95 | | const int DCH_CTRLEND = 10; // ctrl+end |
| 96 | | const int DCH_CTRLRIGHT = 11; // ctrl+right |
| 97 | | const int DCH_CTRLLEFT = 12; // ctrl+left |
| 86 | const int DCH_UP = 1; // up arrow |
| 87 | const int DCH_DOWN = 2; // down arrow |
| 88 | const int DCH_LEFT = 3; // left arrow |
| 89 | const int DCH_RIGHT = 4; // right arrow |
| 90 | const int DCH_PUP = 5; // page up |
| 91 | const int DCH_PDOWN = 6; // page down |
| 92 | const int DCH_HOME = 7; // home |
| 93 | const int DCH_CTRLHOME = 8; // ctrl+home |
| 94 | const int DCH_END = 9; // end |
| 95 | const int DCH_CTRLEND = 10; // ctrl+end |
| 96 | const int DCH_CTRLRIGHT = 11; // ctrl+right |
| 97 | const int DCH_CTRLLEFT = 12; // ctrl+left |
| 98 | 98 | |
| 99 | 99 | |
| 100 | // special characters that can be passed to process_click() |
| 101 | const int DCK_LEFT_CLICK = 1; // left instantaneous click |
| 102 | const int DCK_RIGHT_CLICK = 2; // right instantaneous click |
| 103 | const int DCK_MIDDLE_CLICK = 3; // middle instantaneous click |
| 100 | 104 | |
| 105 | |
| 101 | 106 | //************************************************************************** |
| 102 | 107 | // TYPE DEFINITIONS |
| 103 | 108 | //************************************************************************** |
| r20288 | r20289 | |
| 113 | 118 | // a single "character" in the debug view has an ASCII value and an attribute byte |
| 114 | 119 | struct debug_view_char |
| 115 | 120 | { |
| 116 | | UINT8 byte; |
| 117 | | UINT8 attrib; |
| 121 | UINT8 byte; |
| 122 | UINT8 attrib; |
| 118 | 123 | }; |
| 119 | 124 | |
| 120 | 125 | |
| r20288 | r20289 | |
| 124 | 129 | public: |
| 125 | 130 | debug_view_xy(int _x = 0, int _y = 0) : x(_x), y(_y) { } |
| 126 | 131 | |
| 127 | | INT32 x; |
| 128 | | INT32 y; |
| 132 | INT32 x; |
| 133 | INT32 y; |
| 129 | 134 | }; |
| 130 | 135 | |
| 131 | 136 | |
| r20288 | r20289 | |
| 149 | 154 | |
| 150 | 155 | private: |
| 151 | 156 | // internal state |
| 152 | | debug_view_source * m_next; // link to next item |
| 153 | | astring m_name; // name of the source item |
| 154 | | device_t * m_device; // associated device (if applicable) |
| 155 | | bool m_is_octal; // is view in octal or hex |
| 157 | debug_view_source * m_next; // link to next item |
| 158 | astring m_name; // name of the source item |
| 159 | device_t * m_device; // associated device (if applicable) |
| 160 | bool m_is_octal; // is view in octal or hex |
| 156 | 161 | }; |
| 157 | 162 | |
| 158 | 163 | |
| r20288 | r20289 | |
| 181 | 186 | |
| 182 | 187 | private: |
| 183 | 188 | // internal state |
| 184 | | running_machine & m_machine; // reference to our machine |
| 185 | | debug_view_source * m_head; // head of the list |
| 186 | | debug_view_source * m_tail; // end of the tail |
| 187 | | UINT32 m_count; // number of items in the list |
| 189 | running_machine & m_machine; // reference to our machine |
| 190 | debug_view_source * m_head; // head of the list |
| 191 | debug_view_source * m_tail; // end of the tail |
| 192 | UINT32 m_count; // number of items in the list |
| 188 | 193 | }; |
| 189 | 194 | |
| 190 | 195 | |
| r20288 | r20289 | |
| 221 | 226 | void set_cursor_visible(bool visible = true); |
| 222 | 227 | void set_source(const debug_view_source &source); |
| 223 | 228 | void process_char(int character) { view_char(character); } |
| 229 | void process_click(int button, debug_view_xy pos) { view_click(button, pos); } |
| 224 | 230 | |
| 225 | 231 | protected: |
| 226 | 232 | // internal updating helpers |
| r20288 | r20289 | |
| 238 | 244 | virtual void view_update() = 0; |
| 239 | 245 | virtual void view_notify(debug_view_notification type); |
| 240 | 246 | virtual void view_char(int chval); |
| 247 | virtual void view_click(const int button, const debug_view_xy& pos); |
| 241 | 248 | |
| 242 | 249 | protected: |
| 243 | 250 | // core view data |
| 244 | | debug_view * m_next; // link to the next view |
| 245 | | debug_view_type m_type; // type of view |
| 246 | | const debug_view_source *m_source; // currently selected data source |
| 247 | | debug_view_source_list m_source_list; // list of available data sources |
| 251 | debug_view * m_next; // link to the next view |
| 252 | debug_view_type m_type; // type of view |
| 253 | const debug_view_source *m_source; // currently selected data source |
| 254 | debug_view_source_list m_source_list; // list of available data sources |
| 248 | 255 | |
| 249 | 256 | // OSD data |
| 250 | | debug_view_osd_update_func m_osdupdate; // callback for the update |
| 251 | | void * m_osdprivate; // OSD-managed private data |
| 257 | debug_view_osd_update_func m_osdupdate; // callback for the update |
| 258 | void * m_osdprivate; // OSD-managed private data |
| 252 | 259 | |
| 253 | 260 | // visibility info |
| 254 | | debug_view_xy m_visible; // visible size (in rows and columns) |
| 255 | | debug_view_xy m_total; // total size (in rows and columns) |
| 256 | | debug_view_xy m_topleft; // top-left visible position (in rows and columns) |
| 257 | | debug_view_xy m_cursor; // cursor position |
| 258 | | bool m_supports_cursor; // does this view support a cursor? |
| 259 | | bool m_cursor_visible; // is the cursor visible? |
| 261 | debug_view_xy m_visible; // visible size (in rows and columns) |
| 262 | debug_view_xy m_total; // total size (in rows and columns) |
| 263 | debug_view_xy m_topleft; // top-left visible position (in rows and columns) |
| 264 | debug_view_xy m_cursor; // cursor position |
| 265 | bool m_supports_cursor; // does this view support a cursor? |
| 266 | bool m_cursor_visible; // is the cursor visible? |
| 260 | 267 | |
| 261 | 268 | // update info |
| 262 | | bool m_recompute; // does this view require a recomputation? |
| 263 | | UINT8 m_update_level; // update level; updates when this hits 0 |
| 264 | | bool m_update_pending; // true if there is a pending update |
| 265 | | bool m_osd_update_pending; // true if there is a pending update |
| 266 | | debug_view_char * m_viewdata; // current array of view data |
| 267 | | int m_viewdata_size; // number of elements of the viewdata array |
| 269 | bool m_recompute; // does this view require a recomputation? |
| 270 | UINT8 m_update_level; // update level; updates when this hits 0 |
| 271 | bool m_update_pending; // true if there is a pending update |
| 272 | bool m_osd_update_pending; // true if there is a pending update |
| 273 | debug_view_char * m_viewdata; // current array of view data |
| 274 | int m_viewdata_size; // number of elements of the viewdata array |
| 268 | 275 | |
| 269 | 276 | private: |
| 270 | | running_machine & m_machine; // machine associated with this view |
| 277 | running_machine & m_machine; // machine associated with this view |
| 271 | 278 | }; |
| 272 | 279 | |
| 273 | 280 | |
| r20288 | r20289 | |
| 295 | 302 | debug_view *append(debug_view *view); |
| 296 | 303 | |
| 297 | 304 | // internal state |
| 298 | | running_machine & m_machine; // reference to our machine |
| 299 | | debug_view * m_viewlist; // list of views |
| 305 | running_machine & m_machine; // reference to our machine |
| 306 | debug_view * m_viewlist; // list of views |
| 300 | 307 | }; |
| 301 | 308 | |
| 302 | 309 | |
| r20288 | r20289 | |
| 326 | 333 | bool recompute(); |
| 327 | 334 | |
| 328 | 335 | // internal state |
| 329 | | running_machine & m_machine; // reference to the machine |
| 330 | | bool m_dirty; // true if the expression needs to be re-evaluated |
| 331 | | UINT64 m_result; // last result from the expression |
| 332 | | parsed_expression m_parsed; // parsed expression data |
| 333 | | astring m_string; // copy of the expression string |
| 336 | running_machine & m_machine; // reference to the machine |
| 337 | bool m_dirty; // true if the expression needs to be re-evaluated |
| 338 | UINT64 m_result; // last result from the expression |
| 339 | parsed_expression m_parsed; // parsed expression data |
| 340 | astring m_string; // copy of the expression string |
| 334 | 341 | }; |
| 335 | 342 | |
| 336 | 343 | |
trunk/src/emu/debug/dvmemory.c
| r20288 | r20289 | |
| 74 | 74 | |
| 75 | 75 | debug_view_memory_source::debug_view_memory_source(const char *name, address_space &space) |
| 76 | 76 | : debug_view_source(name, &space.device()), |
| 77 | | m_space(&space), |
| 78 | | m_memintf(dynamic_cast<device_memory_interface *>(&space.device())), |
| 79 | | m_base(NULL), |
| 80 | | m_length(0), |
| 81 | | m_offsetxor(0), |
| 82 | | m_endianness(space.endianness()), |
| 83 | | m_prefsize(space.data_width() / 8) |
| 77 | m_space(&space), |
| 78 | m_memintf(dynamic_cast<device_memory_interface *>(&space.device())), |
| 79 | m_base(NULL), |
| 80 | m_length(0), |
| 81 | m_offsetxor(0), |
| 82 | m_endianness(space.endianness()), |
| 83 | m_prefsize(space.data_width() / 8) |
| 84 | 84 | { |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | debug_view_memory_source::debug_view_memory_source(const char *name, memory_region ®ion) |
| 88 | 88 | : debug_view_source(name), |
| 89 | | m_space(NULL), |
| 90 | | m_memintf(NULL), |
| 91 | | m_base(region), |
| 92 | | m_length(region.bytes()), |
| 93 | | m_offsetxor(NATIVE_ENDIAN_VALUE_LE_BE(region.width() - 1, 0)), |
| 94 | | m_endianness(region.endianness()), |
| 95 | | m_prefsize(MIN(region.width(), 8)) |
| 89 | m_space(NULL), |
| 90 | m_memintf(NULL), |
| 91 | m_base(region), |
| 92 | m_length(region.bytes()), |
| 93 | m_offsetxor(NATIVE_ENDIAN_VALUE_LE_BE(region.width() - 1, 0)), |
| 94 | m_endianness(region.endianness()), |
| 95 | m_prefsize(MIN(region.width(), 8)) |
| 96 | 96 | { |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | debug_view_memory_source::debug_view_memory_source(const char *name, void *base, int element_size, int num_elements) |
| 100 | 100 | : debug_view_source(name), |
| 101 | | m_space(NULL), |
| 102 | | m_memintf(NULL), |
| 103 | | m_base(base), |
| 104 | | m_length(element_size * num_elements), |
| 105 | | m_offsetxor(0), |
| 106 | | m_endianness(ENDIANNESS_NATIVE), |
| 107 | | m_prefsize(MIN(element_size, 8)) |
| 101 | m_space(NULL), |
| 102 | m_memintf(NULL), |
| 103 | m_base(base), |
| 104 | m_length(element_size * num_elements), |
| 105 | m_offsetxor(0), |
| 106 | m_endianness(ENDIANNESS_NATIVE), |
| 107 | m_prefsize(MIN(element_size, 8)) |
| 108 | 108 | { |
| 109 | 109 | } |
| 110 | 110 | |
| r20288 | r20289 | |
| 120 | 120 | |
| 121 | 121 | debug_view_memory::debug_view_memory(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate) |
| 122 | 122 | : debug_view(machine, DVT_MEMORY, osdupdate, osdprivate), |
| 123 | | m_expression(machine), |
| 124 | | m_chunks_per_row(16), |
| 125 | | m_bytes_per_chunk(1), |
| 126 | | m_reverse_view(false), |
| 127 | | m_ascii_view(true), |
| 128 | | m_no_translation(false), |
| 129 | | m_maxaddr(0), |
| 130 | | m_bytes_per_row(16), |
| 131 | | m_byte_offset(0) |
| 123 | m_expression(machine), |
| 124 | m_chunks_per_row(16), |
| 125 | m_bytes_per_chunk(1), |
| 126 | m_reverse_view(false), |
| 127 | m_ascii_view(true), |
| 128 | m_no_translation(false), |
| 129 | m_maxaddr(0), |
| 130 | m_bytes_per_row(16), |
| 131 | m_byte_offset(0) |
| 132 | 132 | { |
| 133 | 133 | // fail if no available sources |
| 134 | 134 | enumerate_sources(); |
| r20288 | r20289 | |
| 181 | 181 | break; |
| 182 | 182 | |
| 183 | 183 | // add pretty much anything that's not a timer (we may wish to cull other items later) |
| 184 | | // also, don't trim the front of the name, it's important to know which VIA6522 we're looking at, e.g. |
| 185 | | if (strncmp(itemname, "timer/", 6)) |
| 184 | // also, don't trim the front of the name, it's important to know which VIA6522 we're looking at, e.g. |
| 185 | if (strncmp(itemname, "timer/", 6)) |
| 186 | 186 | { |
| 187 | | name.cpy(itemname); |
| 187 | name.cpy(itemname); |
| 188 | 188 | m_source_list.append(*auto_alloc(machine(), debug_view_memory_source(name, base, valsize, valcount))); |
| 189 | 189 | } |
| 190 | 190 | } |
| r20288 | r20289 | |
| 426 | 426 | |
| 427 | 427 | |
| 428 | 428 | //------------------------------------------------- |
| 429 | // view_click - handle a mouse click within the |
| 430 | // current view |
| 431 | //------------------------------------------------- |
| 432 | |
| 433 | void debug_view_memory::view_click(const int button, const debug_view_xy& pos) |
| 434 | { |
| 435 | const debug_view_xy origcursor = m_cursor; |
| 436 | m_cursor = pos; |
| 437 | |
| 438 | /* cursor popup|toggle */ |
| 439 | bool cursorVisible = true; |
| 440 | if (m_cursor.y == origcursor.y) |
| 441 | { |
| 442 | cursorVisible = !m_cursor_visible; |
| 443 | } |
| 444 | |
| 445 | /* send a cursor changed notification */ |
| 446 | begin_update(); |
| 447 | m_cursor_visible = cursorVisible; |
| 448 | view_notify(VIEW_NOTIFY_CURSOR_CHANGED); |
| 449 | m_update_pending = true; |
| 450 | end_update(); |
| 451 | } |
| 452 | |
| 453 | |
| 454 | //------------------------------------------------- |
| 429 | 455 | // recompute - recompute the internal data and |
| 430 | 456 | // structure of the memory view |
| 431 | 457 | //------------------------------------------------- |
| r20288 | r20289 | |
| 627 | 653 | { |
| 628 | 654 | switch (size) |
| 629 | 655 | { |
| 630 | | case 1: data = debug_read_byte(*source.m_space, offs, !m_no_translation); break; |
| 631 | | case 2: data = debug_read_word(*source.m_space, offs, !m_no_translation); break; |
| 632 | | case 4: data = debug_read_dword(*source.m_space, offs, !m_no_translation); break; |
| 633 | | case 8: data = debug_read_qword(*source.m_space, offs, !m_no_translation); break; |
| 656 | case 1: data = debug_read_byte(*source.m_space, offs, !m_no_translation); break; |
| 657 | case 2: data = debug_read_word(*source.m_space, offs, !m_no_translation); break; |
| 658 | case 4: data = debug_read_dword(*source.m_space, offs, !m_no_translation); break; |
| 659 | case 8: data = debug_read_qword(*source.m_space, offs, !m_no_translation); break; |
| 634 | 660 | } |
| 635 | 661 | } |
| 636 | 662 | return ismapped; |
| r20288 | r20289 | |
| 674 | 700 | { |
| 675 | 701 | switch (size) |
| 676 | 702 | { |
| 677 | | case 1: debug_write_byte(*source.m_space, offs, data, !m_no_translation); break; |
| 678 | | case 2: debug_write_word(*source.m_space, offs, data, !m_no_translation); break; |
| 679 | | case 4: debug_write_dword(*source.m_space, offs, data, !m_no_translation); break; |
| 680 | | case 8: debug_write_qword(*source.m_space, offs, data, !m_no_translation); break; |
| 703 | case 1: debug_write_byte(*source.m_space, offs, data, !m_no_translation); break; |
| 704 | case 2: debug_write_word(*source.m_space, offs, data, !m_no_translation); break; |
| 705 | case 4: debug_write_dword(*source.m_space, offs, data, !m_no_translation); break; |
| 706 | case 8: debug_write_qword(*source.m_space, offs, data, !m_no_translation); break; |
| 681 | 707 | } |
| 682 | 708 | return; |
| 683 | 709 | } |