SlotViewer.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "SlotViewer.h"
  2. #include "DebuggerData.h"
  3. #include "OpenMSXConnection.h"
  4. #include "CommClient.h"
  5. #include <QPainter>
  6. #include <QPaintEvent>
  7. #include <QStyleOptionHeader>
  8. class DebugMemMapperHandler : public SimpleCommand
  9. {
  10. public:
  11. DebugMemMapperHandler(SlotViewer& viewer_)
  12. : SimpleCommand("debug_memmapper")
  13. , viewer(viewer_)
  14. {
  15. }
  16. virtual void replyOk(const QString& message)
  17. {
  18. viewer.slotsUpdated(message);
  19. delete this;
  20. }
  21. private:
  22. SlotViewer& viewer;
  23. };
  24. SlotViewer::SlotViewer(QWidget* parent)
  25. : QFrame(parent)
  26. {
  27. setFrameStyle(WinPanel | Sunken);
  28. setFocusPolicy(Qt::StrongFocus);
  29. setBackgroundRole(QPalette::Base);
  30. setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
  31. memLayout = NULL;
  32. for (int p = 0; p < 4; ++p) {
  33. slotsChanged[p] = false;
  34. segmentsChanged[p] = false;
  35. }
  36. frameR = frameL = frameT = frameB = frameWidth();
  37. headerSize1 = 8 + fontMetrics().width("Page");
  38. headerSize2 = 8 + fontMetrics().width("Address");
  39. headerSize3 = 8 + fontMetrics().width("Slot");
  40. headerSize4 = 8 + fontMetrics().width("Segment");
  41. headerHeight = 8 + fontMetrics().height();
  42. }
  43. void SlotViewer::resizeEvent(QResizeEvent* e)
  44. {
  45. QFrame::resizeEvent(e);
  46. }
  47. void SlotViewer::paintEvent(QPaintEvent* e)
  48. {
  49. // call parent for drawing the actual frame
  50. QFrame::paintEvent(e);
  51. QPainter p(this);
  52. // calc and set drawing bounds
  53. QRect r(e->rect());
  54. if (r.left() < frameL) r.setLeft(frameL);
  55. if (r.top() < frameT) r.setTop (frameT);
  56. if (r.right() > width() - frameR - 1) r.setRight (width() - frameR - 1);
  57. if (r.bottom() > height() - frameB - 1) r.setBottom(height() - frameB - 1);
  58. p.setClipRect(r);
  59. // redraw background
  60. p.fillRect(r, palette().color(QPalette::Base));
  61. QStyleOptionHeader so;
  62. so.init(this);
  63. so.state |= QStyle::State_Raised;
  64. so.orientation = Qt::Horizontal;
  65. so.position = QStyleOptionHeader::Beginning;
  66. so.sortIndicator = QStyleOptionHeader::None;
  67. so.textAlignment = Qt::AlignHCenter;
  68. so.rect.setTop(frameT);
  69. so.rect.setHeight(headerHeight);
  70. so.rect.setLeft(frameL);
  71. so.rect.setWidth(headerSize1);
  72. so.section = 0;
  73. so.text = "Page";
  74. style()->drawControl(QStyle::CE_Header, &so, &p, this);
  75. so.rect.setLeft(so.rect.left() + headerSize1);
  76. so.rect.setWidth(headerSize2);
  77. so.section = 1;
  78. so.text = "Address";
  79. style()->drawControl(QStyle::CE_Header, &so, &p, this);
  80. so.rect.setLeft(so.rect.left() + headerSize2);
  81. so.rect.setWidth(headerSize3);
  82. so.section = 2;
  83. so.text = "Slot";
  84. style()->drawControl(QStyle::CE_Header, &so, &p, this);
  85. so.rect.setLeft(so.rect.left() + headerSize3);
  86. so.rect.setWidth(headerSize4);
  87. so.section = 3;
  88. so.text = "Segment";
  89. style()->drawControl(QStyle::CE_Header, &so, &p, this);
  90. int mid1 = frameL + headerSize1 / 2;
  91. int mid2 = frameL + headerSize1 + headerSize2 / 2;
  92. int mid3 = frameL + headerSize1 + headerSize2 + headerSize3 / 2;
  93. int mid4 = frameL + headerSize1 + headerSize2 + headerSize3 + headerSize4 / 2;
  94. int dy = (height() - frameT - frameB - headerHeight) / 4;
  95. int y = frameT + headerHeight + dy / 2 + fontMetrics().height() / 2 -
  96. fontMetrics().descent();
  97. int isOn = isEnabled() && memLayout != NULL;
  98. for (int i = 0; i < 4; ++i) {
  99. QString str;
  100. p.setPen(palette().color(QPalette::Text));
  101. // print page nr
  102. str.sprintf("%i", i);
  103. p.drawText(mid1 - fontMetrics().width(str) / 2, y, str);
  104. // print address
  105. str.sprintf("$%04X", i * 0x4000);
  106. p.drawText(mid2 - fontMetrics().width(str) / 2, y, str);
  107. // print slot
  108. if (isOn) {
  109. if (memLayout->isSubslotted[memLayout->primarySlot[i]]) {
  110. str.sprintf("%i-%i", memLayout->primarySlot[i],
  111. memLayout->secondarySlot[i]);
  112. } else {
  113. str = QString::number(memLayout->primarySlot[i]);
  114. }
  115. } else {
  116. str = "-";
  117. }
  118. // set pen colour to red if slot was recently changed
  119. if (slotsChanged[i] && isOn) {
  120. p.setPen(Qt::red);
  121. } else {
  122. p.setPen(palette().color(QPalette::Text));
  123. }
  124. p.drawText(mid3 - fontMetrics().width(str) / 2, y, str);
  125. // print segment
  126. if (isOn) {
  127. int ms;
  128. if (memLayout->isSubslotted[memLayout->primarySlot[i] & 3]) {
  129. ms = memLayout->mapperSize[memLayout->primarySlot[i] & 3]
  130. [memLayout->secondarySlot[i] & 3];
  131. } else {
  132. ms = memLayout->mapperSize[memLayout->primarySlot[i] & 3][0];
  133. }
  134. if (ms > 0) {
  135. str.sprintf("%i", memLayout->mapperSegment[i]);
  136. } else if(memLayout->romBlock[2*i] >= 0) {
  137. if (memLayout->romBlock[2*i] == memLayout->romBlock[2*i+1]) {
  138. str.sprintf("R%i", memLayout->romBlock[2*i]);
  139. } else {
  140. str.sprintf("R%i/%i", memLayout->romBlock[2*i], memLayout->romBlock[2*i+1]);
  141. }
  142. } else {
  143. str = "-";
  144. }
  145. } else {
  146. str = "-";
  147. }
  148. // set pen colour to red if slot was recently changed
  149. if (segmentsChanged[i] && isOn) {
  150. p.setPen(Qt::red);
  151. } else {
  152. p.setPen(palette().color(QPalette::Text));
  153. }
  154. p.drawText(mid4 - fontMetrics().width(str) / 2, y, str);
  155. y += dy;
  156. }
  157. }
  158. QSize SlotViewer::sizeHint() const
  159. {
  160. return QSize(headerSize1 + headerSize2 + headerSize3 + headerSize4 + frameL + frameR,
  161. headerHeight + 4*fontMetrics().height());
  162. }
  163. void SlotViewer::refresh()
  164. {
  165. CommClient::instance().sendCommand(new DebugMemMapperHandler(*this));
  166. }
  167. void SlotViewer::setMemoryLayout(MemoryLayout* ml)
  168. {
  169. memLayout = ml;
  170. }
  171. void SlotViewer::slotsUpdated(const QString& message)
  172. {
  173. QStringList lines = message.split('\n');
  174. // parse page slots and segments
  175. for (int p = 0; p < 4; ++p) {
  176. slotsChanged[p] = (memLayout->primarySlot [p] != lines[p * 2][0].toLatin1()-'0') ||
  177. (memLayout->secondarySlot[p] != lines[p * 2][1].toLatin1()-'0' && memLayout->isSubslotted[p]);
  178. memLayout->primarySlot [p] = lines[p * 2][0].toLatin1()-'0';
  179. memLayout->secondarySlot[p] = lines[p * 2][1].toLatin1()-'0';
  180. segmentsChanged[p] = memLayout->mapperSegment[p] !=
  181. lines[p * 2 + 1].toInt();
  182. memLayout->mapperSegment[p] = lines[p * 2 + 1].toInt();
  183. }
  184. // parse slot layout
  185. int l = 8;
  186. for (int ps = 0; ps < 4; ++ps) {
  187. memLayout->isSubslotted[ps] = lines[l++][0] == '1';
  188. if (memLayout->isSubslotted[ps]) {
  189. for (int ss = 0; ss < 4; ++ss) {
  190. memLayout->mapperSize[ps][ss] = lines[l++].toUShort();
  191. }
  192. } else {
  193. memLayout->mapperSize[ps][0] = lines[l++].toUShort();
  194. }
  195. }
  196. // parse rom blocks
  197. for (int i = 0; i < 8; ++i, ++l) {
  198. if (lines[l][0] == 'X')
  199. memLayout->romBlock[i] = -1;
  200. else
  201. memLayout->romBlock[i] = lines[l].toInt();
  202. }
  203. update();
  204. }