VDPRegViewer.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. #include "VDPRegViewer.h"
  2. #include "VDPDataStore.h"
  3. #include "InteractiveButton.h"
  4. #include "CommClient.h"
  5. static const int VDP_TMS99X8 = 1;
  6. static const int VDP_V9938 = 0;
  7. static const int VDP_V9958 = 4;
  8. // class buttonHighlightDispatcher
  9. buttonHighlightDispatcher::buttonHighlightDispatcher()
  10. : counter(0)
  11. {
  12. }
  13. void buttonHighlightDispatcher::receiveState(bool state)
  14. {
  15. if (state) {
  16. if (counter == 0) {
  17. emit dispatchState(true);
  18. }
  19. ++counter;
  20. } else {
  21. --counter;
  22. if (counter == 0) {
  23. emit dispatchState(false);
  24. }
  25. }
  26. }
  27. // class VDPRegViewer
  28. VDPRegViewer::VDPRegViewer(QWidget *parent)
  29. : QDialog(parent)
  30. {
  31. setupUi(this);
  32. regs = new unsigned char[64 + 16 + 2];
  33. vdpid = 99; // make sure that we parse the first time the status registers are read
  34. vdpid = VDP_V9958; //quick hack for now
  35. //now hook up some signals and slots
  36. connectHighLights();
  37. //get initiale data
  38. refresh();
  39. decodeStatusVDPRegs(); // part of the quick hack :-)
  40. }
  41. VDPRegViewer::~VDPRegViewer()
  42. {
  43. delete[] regs;
  44. }
  45. void VDPRegViewer::setRegisterVisible(int r, bool visible)
  46. {
  47. QString name1 = QString("label_R%1").arg(r);
  48. QLabel* l1 = findChild<QLabel*>(name1);
  49. l1->setVisible(visible);
  50. QString name2 = QString("label_val_%1").arg(r);
  51. QLabel* l2 = findChild<QLabel*>(name2);
  52. l2->setVisible(visible);
  53. for (int b = 7; b >= 0; --b) {
  54. QString name3 = QString("pushButton_%1_%2").arg(r).arg(b);
  55. InteractiveButton *i = findChild<InteractiveButton*>(name3);
  56. i->setVisible(visible);
  57. }
  58. // now hide/show the explications of the give register
  59. switch (r) {
  60. case 8:
  61. label_dec_tp->setVisible(visible);
  62. label_dec_spd->setVisible(visible);
  63. break;
  64. case 9:
  65. label_dec_nt->setVisible(visible);
  66. label_dec_nt2->setVisible(visible);
  67. label_dec_il->setVisible(visible);
  68. label_dec_eo->setVisible(visible);
  69. label_dec_ln->setVisible(visible);
  70. label_dec_ln2->setVisible(visible);
  71. break;
  72. case 12:
  73. label_t2->setVisible(visible);
  74. label_bc->setVisible(visible);
  75. label_dec_t2->setVisible(visible);
  76. label_dec_bc->setVisible(visible);
  77. break;
  78. case 13:
  79. label_on->setVisible(visible);
  80. label_off->setVisible(visible);
  81. label_dec_on->setVisible(visible);
  82. label_dec_off->setVisible(visible);
  83. break;
  84. }
  85. }
  86. void VDPRegViewer::decodeStatusVDPRegs()
  87. {
  88. //const unsigned char* statusregs = regs + 64;
  89. //int id = statusregs[1] & 62; // + (machine_has_TMS99x8 ? 1 : 0)
  90. // test MSX1 id = 1;
  91. //if (vdpid != id) {
  92. // vdpid = id;
  93. if (vdpid == VDP_TMS99X8) {
  94. // TMS9918 = MSX1 VDP
  95. groupBox_V9958->setVisible(false);
  96. groupBox_TableBase->setVisible(true);
  97. groupBox_Color->setVisible(true);
  98. groupBox_Display->setVisible(false);
  99. groupBox_Access->setVisible(false);
  100. groupBox_dec_V9958->setVisible(false);
  101. groupBox_dec_TableBase->setVisible(true);
  102. groupBox_dec_Color->setVisible(true);
  103. groupBox_dec_Display->setVisible(false);
  104. groupBox_dec_Access->setVisible(false);
  105. label_dec_416K->setVisible(true);
  106. label_dec_ie1->setVisible(false);
  107. label_dec_ie2->setVisible(false);
  108. label_dec_dg->setVisible(false);
  109. setRegisterVisible( 8, false);
  110. setRegisterVisible( 9, false);
  111. setRegisterVisible(10, false);
  112. setRegisterVisible(11, false);
  113. setRegisterVisible(12, false);
  114. setRegisterVisible(13, false);
  115. setRegisterVisible(20, false);
  116. setRegisterVisible(21, false);
  117. setRegisterVisible(22, false);
  118. pushButton_0_2->setText("0");
  119. pushButton_0_2->setToolTip("");
  120. pushButton_0_3->setText("0");
  121. pushButton_0_3->setToolTip("");
  122. pushButton_0_4->setText("0");
  123. pushButton_0_4->setToolTip("");
  124. pushButton_0_5->setText("0");
  125. pushButton_0_5->setToolTip("");
  126. pushButton_0_6->setText("0");
  127. pushButton_0_6->setToolTip("");
  128. pushButton_1_7->setText("4/16");
  129. pushButton_1_7->setToolTip(
  130. "4/16K selection\n"
  131. "0 selects 4027 RAM operation\n"
  132. "1 selects 4108/4116 RAM operation");
  133. // mask all A16 bits of regs < 7
  134. pushButton_2_6->setText("0");
  135. pushButton_4_5->setText("0");
  136. pushButton_6_5->setText("0");
  137. // mask all A15
  138. pushButton_2_5->setText("0");
  139. pushButton_4_4->setText("0");
  140. pushButton_6_4->setText("0");
  141. // mask all A14 bits of regs < 7
  142. pushButton_2_4->setText("0");
  143. pushButton_4_3->setText("0");
  144. pushButton_6_3->setText("0");
  145. disconnect(modeBitsDispat, 0, pushButton_0_2, 0);
  146. disconnect(modeBitsDispat, 0, pushButton_0_3, 0);
  147. disconnect(pushButton_0_2, 0, 0, 0);
  148. disconnect(pushButton_0_3, 0, 0, 0);
  149. disconnect(pushButton_0_4, 0, 0, 0);
  150. disconnect(pushButton_0_5, 0, 0, 0);
  151. disconnect(pushButton_0_6, 0, 0, 0);
  152. monoGroup(pushButton_1_7, label_dec_416K);
  153. } else {
  154. // V9938 = MSX2 VDP
  155. // or
  156. // V9958 = MSX2+ VDP
  157. groupBox_TableBase->setVisible(true);
  158. groupBox_Color->setVisible(true);
  159. groupBox_Display->setVisible(true);
  160. groupBox_Access->setVisible(true);
  161. groupBox_dec_TableBase->setVisible(true);
  162. groupBox_dec_Color->setVisible(true);
  163. groupBox_dec_Display->setVisible(true);
  164. groupBox_dec_Access->setVisible(true);
  165. label_dec_416K->setVisible(false);
  166. label_dec_ie1->setVisible(true);
  167. label_dec_dg->setVisible(true);
  168. setRegisterVisible( 8, true);
  169. setRegisterVisible( 9, true);
  170. setRegisterVisible(10, true);
  171. setRegisterVisible(11, true);
  172. setRegisterVisible(12, true);
  173. setRegisterVisible(13, true);
  174. setRegisterVisible(20, true);
  175. setRegisterVisible(21, true);
  176. setRegisterVisible(22, true);
  177. pushButton_0_2->setText("M4");
  178. pushButton_0_3->setText("M5");
  179. pushButton_0_4->setText("IE1");
  180. pushButton_0_6->setText("DG");
  181. pushButton_1_7->setText("0");
  182. pushButton_0_2->setToolTip("Used to change the display mode.");
  183. pushButton_0_3->setToolTip("Used to change the display mode.");
  184. pushButton_0_4->setToolTip("Enables interrupt from Horizontal scanning line by Interrupt Enable 1.");
  185. pushButton_0_6->setToolTip("Sets the color bus to input mode, and inputs data into the VRAM.");
  186. pushButton_1_7->setToolTip("");
  187. // all A16 bits of regs < 7
  188. pushButton_4_5->setText("A16");
  189. pushButton_6_5->setText("A16");
  190. // all A15
  191. pushButton_4_4->setText("A15");
  192. pushButton_6_4->setText("A15");
  193. // all A14
  194. pushButton_4_3->setText("A14");
  195. pushButton_6_3->setText("A14");
  196. ////pushButton_0_5->setText("IE2");
  197. ////disconnect(pushButton_0_7, 0, 0, 0);
  198. ////disconnect(label_dec_416K, 0, 0, 0);
  199. ////reGroup(pushButton_0_2, modeBitsDispat);
  200. ////reGroup(pushButton_0_3, modeBitsDispat);
  201. ////monoGroup(pushButton_0_4, label_dec_ie1);
  202. ////monoGroup(pushButton_0_5, label_dec_ie2);
  203. ////monoGroup(pushButton_0_6, label_dec_dg);
  204. //break;
  205. // V9958 = MSX2+ VDP
  206. ////groupBox_TableBase->setVisible(true);
  207. ////groupBox_Color->setVisible(true);
  208. ////groupBox_Display->setVisible(true);
  209. ////groupBox_Access->setVisible(true);
  210. ////groupBox_dec_TableBase->setVisible(true);
  211. ////groupBox_dec_Color->setVisible(true);
  212. ////groupBox_dec_Display->setVisible(true);
  213. ////groupBox_dec_Access->setVisible(true);
  214. ////label_dec_416K->setVisible(false);
  215. ////label_dec_ie1->setVisible(true);
  216. ////label_dec_dg->setVisible(true);
  217. ////setRegisterVisible( 8, true);
  218. ////setRegisterVisible( 9, true);
  219. ////setRegisterVisible(10, true);
  220. ////setRegisterVisible(11, true);
  221. ////setRegisterVisible(12, true);
  222. ////setRegisterVisible(13, true);
  223. ////setRegisterVisible(20, true);
  224. ////setRegisterVisible(21, true);
  225. ////setRegisterVisible(22, true);
  226. ////pushButton_0_2->setText("M4");
  227. ////pushButton_0_3->setText("M5");
  228. ////pushButton_0_4->setText("IE1");
  229. ////pushButton_0_6->setText("DG");
  230. ////pushButton_1_7->setText("0");
  231. ////pushButton_0_2->setToolTip("Used to change the display mode.");
  232. ////pushButton_0_3->setToolTip("Used to change the display mode.");
  233. ////pushButton_0_4->setToolTip("Enables interrupt from Horizontal scanning line by Interrupt Enable 1.");
  234. ////pushButton_0_6->setToolTip("Sets the color bus to input mode, and inputs data into the VRAM.");
  235. ////pushButton_1_7->setToolTip("");
  236. pushButton_1_7->setToolTip("");
  237. disconnect(pushButton_0_7, 0, 0, 0);
  238. disconnect(label_dec_416K, 0, 0, 0);
  239. reGroup(pushButton_0_2, modeBitsDispat);
  240. reGroup(pushButton_0_3, modeBitsDispat);
  241. monoGroup(pushButton_0_4, label_dec_ie1);
  242. monoGroup(pushButton_0_5, label_dec_ie2);
  243. monoGroup(pushButton_0_6, label_dec_dg);
  244. if (vdpid == VDP_V9938){
  245. groupBox_V9958->setVisible(false);
  246. groupBox_dec_V9958->setVisible(false);
  247. label_dec_ie2->setVisible(true);
  248. pushButton_0_5->setText("IE2");
  249. pushButton_0_5->setToolTip("Enables interrupt from Lightpen by Interrupt Enable 2.");
  250. pushButton_8_6->setText("LP");
  251. pushButton_8_6->setToolTip("");
  252. pushButton_8_7->setText("MS");
  253. pushButton_8_7->setToolTip("");
  254. } else {
  255. groupBox_V9958->setVisible(true);
  256. groupBox_dec_V9958->setVisible(true);
  257. label_dec_ie2->setVisible(false);
  258. pushButton_0_5->setText("0");
  259. pushButton_0_5->setToolTip("");
  260. pushButton_8_7->setText("0");
  261. pushButton_8_7->setToolTip("");
  262. pushButton_8_6->setText("0");
  263. pushButton_8_6->setToolTip("");
  264. /* Since mouse/lightpen are disabled this will affect
  265. * status reg1 bit 7 (LPS) and
  266. * status reg1 bit 6 (FL)
  267. */
  268. }
  269. //break;
  270. }
  271. //}
  272. }
  273. static QString dec2(int val)
  274. {
  275. return QString("%1").arg(val, 2, 10, QChar('0'));
  276. }
  277. static QString dec3(int val)
  278. {
  279. return QString("%1").arg(val, 3, 10, QChar('0'));
  280. }
  281. static QString hex2(int val)
  282. {
  283. return QString("%1").arg(val, 2, 16, QChar('0')).toUpper();
  284. }
  285. static QString hex5(int val)
  286. {
  287. return QString("%1").arg(val, 5, 16, QChar('0')).toUpper();
  288. }
  289. void VDPRegViewer::decodeVDPRegs()
  290. {
  291. // first update all hex values
  292. label_val_0->setText(hex2(regs[0]));
  293. label_val_1->setText(hex2(regs[1]));
  294. label_val_2->setText(hex2(regs[2]));
  295. label_val_3->setText(hex2(regs[3]));
  296. label_val_4->setText(hex2(regs[4]));
  297. label_val_5->setText(hex2(regs[5]));
  298. label_val_6->setText(hex2(regs[6]));
  299. label_val_7->setText(hex2(regs[7]));
  300. // Only on V9938 and V9958 this makes sence
  301. if (vdpid != VDP_TMS99X8) {
  302. label_val_8 ->setText(hex2(regs[ 8]));
  303. label_val_9 ->setText(hex2(regs[ 9]));
  304. label_val_10->setText(hex2(regs[10]));
  305. label_val_11->setText(hex2(regs[11]));
  306. label_val_12->setText(hex2(regs[12]));
  307. label_val_13->setText(hex2(regs[13]));
  308. label_val_14->setText(hex2(regs[14]));
  309. label_val_15->setText(hex2(regs[15]));
  310. label_val_16->setText(hex2(regs[16]));
  311. label_val_17->setText(hex2(regs[17]));
  312. label_val_18->setText(hex2(regs[18]));
  313. label_val_19->setText(hex2(regs[19]));
  314. label_val_20->setText(hex2(regs[20]));
  315. label_val_21->setText(hex2(regs[21]));
  316. label_val_22->setText(hex2(regs[22]));
  317. label_val_23->setText(hex2(regs[23]));
  318. }
  319. // Only on V9958 this makes sence
  320. if (vdpid == VDP_V9958) {
  321. label_val_25->setText(hex2(regs[25]));
  322. label_val_26->setText(hex2(regs[26]));
  323. label_val_27->setText(hex2(regs[27]));
  324. }
  325. // determine screenmode
  326. int m = ((regs[0] & 0x0E) << 1) | ((regs[1] & 0x18) >> 3);
  327. const char* const screen[32] = {
  328. "SCREEN 1", "SCREEN 3", "SCREEN 0",
  329. "let's find out 3", "SCREEN 2", "let's find out 5",
  330. "let's find out 6", "let's find out 7", "SCREEN 4",
  331. "let's find out 9", "SCREEN 0 width 80", "let's find out 11",
  332. "SCREEN 5", "let's find out 13", "let's find out 14",
  333. "let's find out 15", "SCREEN 6", "let's find out 17",
  334. "let's find out 18", "let's find out 19", "SCREEN 7",
  335. "let's find out 21", "let's find out 22", "let's find out 23",
  336. "let's find out 24", "let's find out 25", "let's find out 26",
  337. "let's find out 27", "SCREEN 8", "let's find out 29",
  338. "let's find out 30", "let's find out 31"
  339. };
  340. int basicscreen;
  341. switch (m){
  342. case 2: basicscreen=0;break;
  343. case 0: basicscreen=1;break;
  344. case 4: basicscreen=2;break;
  345. case 1: basicscreen=3;break;
  346. case 8: basicscreen=4;break;
  347. case 12: basicscreen=5;break;
  348. case 16: basicscreen=6;break;
  349. case 20: basicscreen=7;break;
  350. case 28: basicscreen=8;break;
  351. case 10: basicscreen=9;break; //screen 0 width 80
  352. default: basicscreen=10; //not a valid basic screen mode
  353. };
  354. // 2 vdps, 11 basic screenmodes, 12 registers
  355. static const int mustbeone[][11][12] = {
  356. { // TMS99x8 MSX1 VDP chip
  357. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 0;
  358. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 1;
  359. {0, 0, 0x00, 0x7f, 0x03, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 2;
  360. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 3;
  361. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 4;
  362. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 5;
  363. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 6;
  364. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 7;
  365. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 8;
  366. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 0 width 80;
  367. {0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0} // undefined basic screen;
  368. },
  369. { // V9938 and V9958 MSX2/2+ VDP chip
  370. // Note that there is a hardcoded check for reg5 bit 2 (A9) in spritemode 2
  371. // which deliberatly isn't set here in the table!
  372. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 0;
  373. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 1;
  374. {0, 0, 0x00, 0x7f, 0x03, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 2;
  375. {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 3;
  376. {0, 0, 0x00, 0x7f, 0x03, 0x03, 0x00, 0x00, 0,0,0,0}, // screen 4;
  377. {0, 0, 0x1f, 0x00, 0x00, 0x03, 0x00, 0x00, 0,0,0,0}, // screen 5;
  378. {0, 0, 0x1f, 0x00, 0x00, 0x03, 0x00, 0x00, 0,0,0,0}, // screen 6;
  379. {0, 0, 0x1f, 0x00, 0x00, 0x03, 0x00, 0x00, 0,0,0,0}, // screen 7;
  380. {0, 0, 0x1f, 0x00, 0x00, 0x03, 0x00, 0x00, 0,0,0,0}, // screen 8;
  381. {0, 0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 0 width 80;
  382. {0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} // undefined basic screen;
  383. }
  384. };
  385. static const int bitsused[][11][12] = {
  386. {// MSX1 = static const int VDP_TMS99X8 = 1
  387. {0,1, 0x0f, 0xff, 0x07, 0x7f, 0x07, 7,8,9, 0x00, 0x00}, // screen 0;
  388. {0,1, 0x0f, 0xff, 0x07, 0x7f, 0x07, 7,8,9, 0x00, 0x00}, // screen 1;
  389. {0,1, 0x0f, 0xff, 0x07, 0x7f, 0x07, 7,8,9, 0x00, 0x00}, // screen 2;
  390. {0,1, 0x0f, 0xff, 0x07, 0x7f, 0x07, 7,8,9, 0x00, 0x00}, // screen 3;
  391. {0,1, 0x00, 0x00, 0x00, 0x00, 0x00, 7,8,9, 0x00, 0x00}, // screen 4;
  392. {0,1, 0x00, 0x00, 0x00, 0x00, 0x00, 7,8,9, 0x00, 0x00}, // screen 5;
  393. {0,1, 0x00, 0x00, 0x00, 0x00, 0x00, 7,8,9, 0x00, 0x00}, // screen 6;
  394. {0,1, 0x00, 0x00, 0x00, 0x00, 0x00, 7,8,9, 0x00, 0x00}, // screen 7;
  395. {0,1, 0x00, 0x00, 0x00, 0x00, 0x00, 7,8,9, 0x00, 0x00}, // screen 8;
  396. {0,1, 0x00, 0x00, 0x00, 0x00, 0x00, 7,8,9, 0x00, 0x00}, // screen 0 width 80;
  397. {255,255,255,255,255,255,255,255,255,255,255,255} // undefined basic screen;
  398. },
  399. { // MSX2 = static const int VDP_V9938 = 0;
  400. {0,1, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 7,8,9, 0x07, 0x03}, // screen 0;
  401. {0,1, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 7,8,9, 0x07, 0x03}, // screen 1;
  402. {0,1, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 7,8,9, 0x07, 0x03}, // screen 2;
  403. {0,1, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 7,8,9, 0x07, 0x03}, // screen 3;
  404. {0,1, 0x7f, 0xff, 0x3f, 0xfc, 0x3f, 7,8,9, 0x07, 0x03}, // screen 4;
  405. {0,1, 0x7f, 0xff, 0x3f, 0xfc, 0x3f, 7,8,9, 0x07, 0x03}, // screen 5;
  406. {0,1, 0x7f, 0xff, 0x3f, 0xfc, 0x3f, 7,8,9, 0x07, 0x03}, // screen 6;
  407. {0,1, 0x7f, 0xff, 0x3f, 0xfc, 0x3f, 7,8,9, 0x07, 0x03}, // screen 7;
  408. {0,1, 0x7f, 0xff, 0x3f, 0xfc, 0x3f, 7,8,9, 0x07, 0x03}, // screen 8;
  409. {0,1, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 7,8,9, 0x07, 0x03}, // screen 0 width 80;
  410. {255,255,255,255,255,255,255,255,255,255,255,255} // undefined basic screen;
  411. }
  412. };
  413. // update all the individual bits
  414. int upper_r = (vdpid == VDP_TMS99X8) ? 7 : (vdpid == VDP_V9938) ? 23 : 27;
  415. for (int r = 0; r <= upper_r; ++r) {
  416. if (r == 24) continue;
  417. for (int b = 7; b >= 0; --b) {
  418. QString name = QString("pushButton_%1_%2").arg(r).arg(b);
  419. InteractiveButton* i = findChild<InteractiveButton*>(name);
  420. i->setChecked((regs[r] & (1 << b)) ? true : false);
  421. if (r<12){
  422. i->mustBeSet((mustbeone[ (vdpid == VDP_TMS99X8)?0:1 ][basicscreen][r] & (1 << b)) ? true : false);
  423. // if A8 of R5 is a 'mustbeone' then we indicate this for A9 also
  424. // This bit is cleared in the table since it isn't used in the Sprite
  425. // Attribute Table address calculation otherwise, but will only impact the
  426. // Sprite Color Table
  427. if (r==5 && b==2 && vdpid!=VDP_TMS99X8 && mustbeone[1][basicscreen][5] ){
  428. i->mustBeSet(true);
  429. }
  430. }
  431. }
  432. }
  433. // Start the interpretation
  434. label_dec_ie2->setText((regs[0] & 32)
  435. ? "Interrupt from lightpen enabled"
  436. : "Interrupt from lightpen disabled");
  437. label_dec_ie1->setText((regs[0] & 16)
  438. ? "Reg 19 scanline interrupt enabled"
  439. : "Reg 19 scanline interrupt disabled");
  440. if (vdpid != VDP_TMS99X8) {
  441. if (m == 20 || m == 28) {
  442. pushButton_2_6->setText("0");
  443. pushButton_2_5->setText("A16");
  444. pushButton_2_4->setText("A15");
  445. pushButton_2_3->setText("A14");
  446. pushButton_2_2->setText("A13");
  447. pushButton_2_1->setText("A12");
  448. pushButton_2_0->setText("A11");
  449. } else {
  450. pushButton_2_6->setText("A16");
  451. pushButton_2_5->setText("A15");
  452. pushButton_2_4->setText("A14");
  453. pushButton_2_3->setText("A13");
  454. pushButton_2_2->setText("A12");
  455. pushButton_2_1->setText("A11");
  456. pushButton_2_0->setText("A10");
  457. }
  458. }
  459. if (m == 28 && vdpid == VDP_V9958) {
  460. bool yjk = (regs[25] & 8);
  461. bool yae = (regs[25] & 16);
  462. int scr = yjk ? (yae ? 10 : 12) : 8;
  463. label_dec_m->setText(QString("M=%1%2%3 : SCREEN %4")
  464. .arg(m)
  465. .arg(yjk ? "+YJK" : "")
  466. .arg(yae ? "+YAE" : "")
  467. .arg(scr));
  468. } else {
  469. label_dec_m->setText(QString("M=%1 : %2")
  470. .arg(m)
  471. .arg(screen[m]));
  472. }
  473. label_dec_bl->setText((regs[1] & 64)
  474. ? "Display enabled"
  475. : "Display disabled");
  476. label_dec_ie0->setText((regs[1] & 32)
  477. ? "V-Blank interrupt enabled"
  478. : "V-Blank interrupt disabled");
  479. label_dec_si->setText((regs[1] & 2)
  480. ? "16x16 sprites"
  481. : "8x8 sprites");
  482. label_dec_mag->setText((regs[1] & 1)
  483. ? "magnified sprites"
  484. : "regular sized");
  485. // Now calculate the addresses of all tables
  486. // TODO : clean up code and get rid of all the mustbeset bits for regs>5 since there are never must bits.
  487. // some variables used for readability of the code below
  488. int row = vdpid==VDP_TMS99X8?0:1;
  489. QString regtexttext;
  490. int must,must2;
  491. // the pattern name table address
  492. must=mustbeone[row][basicscreen][2] ;
  493. long nameTable = ((255^must) & bitsused[row][basicscreen][2] & regs[2]) << 10;
  494. if ((m == 20 || m == 28) && vdpid != VDP_TMS99X8)
  495. nameTable = ((nameTable & 0xffff) << 1) | ((nameTable & 0x10000) >> 16);
  496. regtexttext = hex5(nameTable);
  497. if ((must & regs[2]) != must ) {
  498. label_dec_r2->setText("<font color=red>" + regtexttext +"</font>");
  499. label_dec_r2->setToolTip("Some of the obligatory 1 bits are reset!");
  500. } else {
  501. label_dec_r2->setText(regtexttext);
  502. label_dec_r2->setToolTip(NULL);
  503. }
  504. // the color table address
  505. must=mustbeone[row][basicscreen][3] ;
  506. must2=mustbeone[row][basicscreen][10] ;
  507. regtexttext=hex5(
  508. (
  509. ((255^must) & bitsused[row][basicscreen][ 3] & regs[ 3]) << 6
  510. ) | (
  511. ((255^must2) & bitsused[row][basicscreen][10] & regs[10]) << 14
  512. )
  513. );
  514. if (((must & regs[3]) != must ) || ((must2 & regs[10]) != must2 ) ){
  515. label_dec_r3->setText("<font color=red>" + regtexttext +"</font>");
  516. label_dec_r3->setToolTip("Some of the obligatory 1 bits are reset!");
  517. } else {
  518. label_dec_r3->setText(regtexttext);
  519. label_dec_r3->setToolTip(NULL);
  520. }
  521. // the pattern generator address
  522. must=mustbeone[row][basicscreen][4] ;
  523. regtexttext=hex5(
  524. (
  525. ( 255^must) & bitsused[row][basicscreen][4] & regs[4]) << 11
  526. );
  527. if ((must & regs[4]) != must ){
  528. label_dec_r4->setText("<font color=red>" + regtexttext +"</font>");
  529. label_dec_r4->setToolTip("Some of the obligatory 1 bits are reset!");
  530. } else {
  531. label_dec_r4->setText(regtexttext);
  532. label_dec_r4->setToolTip(NULL);
  533. }
  534. // the sprite attribute tabel address
  535. must=mustbeone[row][basicscreen][5] ;
  536. must2=mustbeone[row][basicscreen][11] ;
  537. regtexttext=hex5(
  538. (
  539. (((255^must) & bitsused[row][basicscreen][ 5] & regs[ 5]) << 7) |
  540. (((255^must2) & bitsused[row][basicscreen][11] & regs[11]) << 15))
  541. );
  542. if (((must & regs[5]) != must ) || ((must2 & regs[11]) != must2 ) ){
  543. label_dec_r5->setText("<font color=red>" + regtexttext +"</font>");
  544. label_dec_r5->setToolTip("Some of the obligatory 1 bits are reset!");
  545. } else {
  546. label_dec_r5->setText(regtexttext);
  547. label_dec_r5->setToolTip(NULL);
  548. };
  549. // special case for sprite mode 2
  550. if (must && !( 4 & regs[ 5])) { // only in mode2 there are some 'must'-bits :-)
  551. label_dec_r5->setText("<font color=red>" + regtexttext +"</font>");
  552. label_dec_r5->setToolTip("Bit A9 should be set, to obtain the Sprite Color Table address this bit is masked<br>With the current bit reset the Color Tabel will use the same address as the Sprite Atribute Tabel!");
  553. };
  554. // the sprite pattern generator address
  555. label_dec_r6->setText(hex5(
  556. ((255^mustbeone[row][basicscreen][6]) & bitsused[row][basicscreen][6] & regs[6]) << 11));
  557. // end of address calculations
  558. label_dec_tc->setText(dec2((regs[7] >> 4) & 15));
  559. label_dec_bd->setText(dec2((regs[7] >> 0) & 15));
  560. if (vdpid != VDP_TMS99X8) {
  561. label_dec_tp->setText((regs[8] & 32)
  562. ? "Color 0 uses the color registers"
  563. : "Color 0 is transparent (=shows border)");
  564. label_dec_spd->setText((regs[8] & 2)
  565. ? "Sprites disabled"
  566. : "Sprites enabled");
  567. label_dec_ln->setText((regs[9] & 128) ? "212" : "192");
  568. label_dec_il->setText((regs[9] & 8) ? "interlaced" : "non-interlaced");
  569. label_dec_eo->setText((regs[9] & 4) ? "alternate pages" : "same page");
  570. label_dec_nt->setText((regs[9] & 2) ? "PAL" : "NTSC");
  571. label_dec_t2 ->setText(dec2((regs[12] >> 4) & 15));
  572. label_dec_bc ->setText(dec2((regs[12] >> 0) & 15));
  573. label_dec_on ->setText(dec2((regs[13] >> 4) & 15));
  574. label_dec_off->setText(dec2((regs[13] >> 0) & 15));
  575. int x = ((regs[18] >> 0) & 15);
  576. int y = ((regs[18] >> 4) & 15);
  577. x = x > 7 ? 16 - x : -x;
  578. y = y > 7 ? 16 - y : -y;
  579. label_dec_r18->setText(QString("(%1,%2)").arg(x).arg(y));
  580. label_dec_r19->setText(dec3(regs[19]));
  581. label_dec_r23->setText(dec3(regs[23]));
  582. label_dec_r14->setText(hex5(((regs[14] & 7) << 14) | ((regs[81] & 63) << 8) | regs[80]));
  583. label_dec_r15->setText(dec2(regs[15] & 15));
  584. label_dec_r16->setText(dec2(regs[16] & 15));
  585. label_dec_r17->setText(dec3(regs[17] & 63).append((regs[17] & 128) ? ", auto incr" : ""));
  586. }
  587. //V9958 registers
  588. if (vdpid == VDP_V9958) {
  589. label_dec_r26->setText(QString("horizontal scroll %1")
  590. .arg((regs[26] & 63) * 8 - (7 & regs[27])));
  591. label_dec_sp2->setText((regs[25] & 1)
  592. ? "Scroll uses 2 pages"
  593. : "Scroll same page");
  594. label_dec_msk->setText((regs[25] & 2)
  595. ? "Hide 8 leftmost pixels"
  596. : "No masking");
  597. label_dec_wte->setText((regs[25] & 4)
  598. ? "Disabled CPU Waitstate"
  599. : "Enable CPU Waitstate");
  600. if (regs[25] & 8) {
  601. label_dec_yjk->setText("YJK System");
  602. label_dec_yae->setText((regs[25] & 16)
  603. ? "Attribute enabled (Y=4bits)"
  604. : "regular YJK (Y=5bits)");
  605. } else {
  606. label_dec_yjk->setText("Normal RGB");
  607. label_dec_yae->setText("Ignored (YJK disabled)");
  608. }
  609. label_dec_vds->setText((regs[25] & 32)
  610. ? "Pin8 is /VDS"
  611. : "Pin8 is CPUCLK");
  612. label_dec_cmd->setText((regs[25] & 64)
  613. ? "CMD engine in char modes"
  614. : "V9938 VDP CMD engine");
  615. }
  616. }
  617. void VDPRegViewer::doConnect(InteractiveButton* but, buttonHighlightDispatcher* dis)
  618. {
  619. connect(but, SIGNAL(mouseOver(bool)),
  620. dis, SLOT(receiveState(bool)));
  621. connect(dis, SIGNAL(dispatchState(bool)),
  622. but, SLOT(highlight(bool)));
  623. }
  624. void VDPRegViewer::monoGroup(InteractiveButton* but, InteractiveLabel* lab)
  625. {
  626. connect(lab, SIGNAL(mouseOver(bool)), but, SLOT(highlight(bool)));
  627. connect(but, SIGNAL(mouseOver(bool)), lab, SLOT(highlight(bool)));
  628. connect(lab, SIGNAL(mouseOver(bool)), lab, SLOT(highlight(bool)));
  629. connect(but, SIGNAL(mouseOver(bool)), but, SLOT(highlight(bool)));
  630. }
  631. void VDPRegViewer::reGroup(InteractiveButton* item, buttonHighlightDispatcher* dispat)
  632. {
  633. //button must rehighlight itself
  634. connect(item, SIGNAL(mouseOver(bool)), item, SLOT(highlight(bool)));
  635. // and then talk to dispatcher
  636. doConnect(item, dispat);
  637. }
  638. buttonHighlightDispatcher* VDPRegViewer::makeGroup(
  639. QList<InteractiveButton*> list, InteractiveLabel* explained)
  640. {
  641. // First "steal" the Tooltip of the explained widget.
  642. InteractiveButton* item;
  643. //foreach(item, list) {
  644. // item->setToolTip(explained->toolTip());
  645. //}
  646. // Create a dispatcher and connect all to them
  647. buttonHighlightDispatcher* dispat = new buttonHighlightDispatcher();
  648. connect(explained, SIGNAL(mouseOver(bool)),
  649. dispat, SLOT(receiveState(bool)));
  650. connect(dispat, SIGNAL(dispatchState(bool)),
  651. explained, SLOT(highlight(bool)));
  652. foreach(item, list){
  653. doConnect(item, dispat);
  654. }
  655. return dispat;
  656. }
  657. void VDPRegViewer::connectHighLights()
  658. {
  659. // Before connecting the highlights we connect the special
  660. // 'Toggled Bit' event
  661. // Warning: This function is not available with MSVC 6!! Not that it
  662. // matters to me on my Linux environment :-)
  663. QList<InteractiveButton*> list = findChildren<InteractiveButton*>();
  664. InteractiveButton* item;
  665. foreach(item, list) {
  666. connect(item, SIGNAL(newBitValue(int,int,bool)),
  667. this, SLOT(registerBitChanged(int,int,bool)));
  668. }
  669. // register 0 (+M1,M2)
  670. monoGroup(pushButton_0_5, label_dec_ie2);
  671. monoGroup(pushButton_0_4, label_dec_ie1);
  672. list.clear();
  673. list << pushButton_0_3 << pushButton_0_2 << pushButton_0_1;
  674. list << pushButton_1_4 << pushButton_1_3;
  675. modeBitsDispat = makeGroup(list, label_dec_m);
  676. // register 1
  677. monoGroup(pushButton_1_6, label_dec_bl);
  678. monoGroup(pushButton_1_5, label_dec_ie0);
  679. monoGroup(pushButton_1_1, label_dec_si);
  680. monoGroup(pushButton_1_0, label_dec_mag);
  681. // register 8
  682. //monoGroup(pushButton_8_7, label_dec_ms);
  683. //monoGroup(pushButton_8_6, label_dec_lp);
  684. monoGroup(pushButton_8_5, label_dec_tp);
  685. //monoGroup(pushButton_8_4, label_dec_cb);
  686. //monoGroup(pushButton_8_3, label_dec_vr);
  687. monoGroup(pushButton_8_1, label_dec_spd);
  688. //monoGroup(pushButton_8_0, label_dec_bw);
  689. // register 9
  690. monoGroup(pushButton_9_7, label_dec_ln);
  691. list.clear();
  692. list << pushButton_9_5 << pushButton_9_4;
  693. makeGroup(list, label_dec_m); //TODO fix label
  694. monoGroup(pushButton_9_3, label_dec_il);
  695. monoGroup(pushButton_9_2, label_dec_eo);
  696. monoGroup(pushButton_9_1, label_dec_nt);
  697. //monoGroup(pushButton_9_0, label_dec_dc);
  698. // register 2
  699. list.clear();
  700. list << pushButton_2_7 << pushButton_2_6 << pushButton_2_5;
  701. list << pushButton_2_4 << pushButton_2_3 << pushButton_2_2;
  702. list << pushButton_2_1 << pushButton_2_0;
  703. makeGroup(list, label_dec_r2);
  704. // register 3 + 10
  705. list.clear();
  706. list << pushButton_3_7 << pushButton_3_6 << pushButton_3_5;
  707. list << pushButton_3_4 << pushButton_3_3 << pushButton_3_2;
  708. list << pushButton_3_1 << pushButton_3_0;
  709. list << pushButton_10_7 << pushButton_10_6 << pushButton_10_5;
  710. list << pushButton_10_4 << pushButton_10_3 << pushButton_10_2;
  711. list << pushButton_10_1 << pushButton_10_0;
  712. makeGroup(list, label_dec_r3);
  713. // register 4
  714. list.clear();
  715. list << pushButton_4_7 << pushButton_4_6 << pushButton_4_5;
  716. list << pushButton_4_4 << pushButton_4_3 << pushButton_4_2;
  717. list << pushButton_4_1 << pushButton_4_0;
  718. makeGroup(list, label_dec_r4);
  719. // register 5 + 11
  720. list.clear();
  721. list << pushButton_5_7 << pushButton_5_6 << pushButton_5_5;
  722. list << pushButton_5_4 << pushButton_5_3 << pushButton_5_2;
  723. list << pushButton_5_1 << pushButton_5_0;
  724. list << pushButton_11_7 << pushButton_11_6 << pushButton_11_5;
  725. list << pushButton_11_4 << pushButton_11_3 << pushButton_11_2;
  726. list << pushButton_11_1 << pushButton_11_0;
  727. makeGroup(list, label_dec_r5);
  728. // register 6
  729. list.clear();
  730. list << pushButton_6_7 << pushButton_6_6 << pushButton_6_5;
  731. list << pushButton_6_4 << pushButton_6_3 << pushButton_6_2;
  732. list << pushButton_6_1 << pushButton_6_0;
  733. makeGroup(list, label_dec_r6);
  734. // register 7
  735. list.clear();
  736. list << pushButton_7_7 << pushButton_7_6;
  737. list << pushButton_7_5 << pushButton_7_4;
  738. makeGroup(list, label_dec_tc);
  739. list.clear();
  740. list << pushButton_7_3 << pushButton_7_2;
  741. list << pushButton_7_1 << pushButton_7_0;
  742. makeGroup(list, label_dec_bd);
  743. // register 12
  744. list.clear();
  745. list << pushButton_12_7 << pushButton_12_6;
  746. list << pushButton_12_5 << pushButton_12_4;
  747. makeGroup(list, label_dec_t2);
  748. list.clear();
  749. list << pushButton_12_3 << pushButton_12_2;
  750. list << pushButton_12_1 << pushButton_12_0;
  751. makeGroup(list, label_dec_bc);
  752. // register 13
  753. list.clear();
  754. list << pushButton_13_7 << pushButton_13_6;
  755. list << pushButton_13_5 << pushButton_13_4;
  756. makeGroup(list, label_dec_on);
  757. list.clear();
  758. list << pushButton_13_3 << pushButton_13_2;
  759. list << pushButton_13_1 << pushButton_13_0;
  760. makeGroup(list, label_dec_off);
  761. // register 14
  762. list.clear();
  763. list << pushButton_14_7 << pushButton_14_6 << pushButton_14_5;
  764. list << pushButton_14_4 << pushButton_14_3 << pushButton_14_2;
  765. list << pushButton_14_1 << pushButton_14_0;
  766. makeGroup(list, label_dec_r14);
  767. // register 15
  768. list.clear();
  769. list << pushButton_15_7 << pushButton_15_6 << pushButton_15_5;
  770. list << pushButton_15_4 << pushButton_15_3 << pushButton_15_2;
  771. list << pushButton_15_1 << pushButton_15_0;
  772. makeGroup(list, label_dec_r15);
  773. // register 16
  774. list.clear();
  775. list << pushButton_16_7 << pushButton_16_6 << pushButton_16_5;
  776. list << pushButton_16_4 << pushButton_16_3 << pushButton_16_2;
  777. list << pushButton_16_1 << pushButton_16_0;
  778. makeGroup(list, label_dec_r16);
  779. // register 17
  780. list.clear();
  781. list << pushButton_17_7 << pushButton_17_6 << pushButton_17_5;
  782. list << pushButton_17_4 << pushButton_17_3 << pushButton_17_2;
  783. list << pushButton_17_1 << pushButton_17_0;
  784. makeGroup(list, label_dec_r17);
  785. // register 18
  786. list.clear();
  787. list << pushButton_18_7 << pushButton_18_6 << pushButton_18_5;
  788. list << pushButton_18_4 << pushButton_18_3 << pushButton_18_2;
  789. list << pushButton_18_1 << pushButton_18_0;
  790. makeGroup(list, label_dec_r18);
  791. // register 19
  792. list.clear();
  793. list << pushButton_19_7 << pushButton_19_6 << pushButton_19_5;
  794. list << pushButton_19_4 << pushButton_19_3 << pushButton_19_2;
  795. list << pushButton_19_1 << pushButton_19_0;
  796. makeGroup(list, label_dec_r19);
  797. // register 23
  798. list.clear();
  799. list << pushButton_23_7 << pushButton_23_6 << pushButton_23_5;
  800. list << pushButton_23_4 << pushButton_23_3 << pushButton_23_2;
  801. list << pushButton_23_1 << pushButton_23_0;
  802. makeGroup(list, label_dec_r23);
  803. // register 25
  804. monoGroup(pushButton_25_0, label_dec_sp2);
  805. monoGroup(pushButton_25_1, label_dec_msk);
  806. monoGroup(pushButton_25_2, label_dec_wte);
  807. monoGroup(pushButton_25_3, label_dec_yjk);
  808. monoGroup(pushButton_25_4, label_dec_yae);
  809. monoGroup(pushButton_25_5, label_dec_vds);
  810. monoGroup(pushButton_25_6, label_dec_cmd);
  811. // register 26
  812. list.clear();
  813. list << pushButton_26_7 << pushButton_26_6 << pushButton_26_5;
  814. list << pushButton_26_4 << pushButton_26_3 << pushButton_26_2;
  815. list << pushButton_26_1 << pushButton_26_0;
  816. list << pushButton_27_7 << pushButton_27_6 << pushButton_27_5;
  817. list << pushButton_27_4 << pushButton_27_3 << pushButton_27_2;
  818. list << pushButton_27_1 << pushButton_27_0;
  819. makeGroup(list, label_dec_r26);
  820. }
  821. void VDPRegViewer::refresh()
  822. {
  823. //new SimpleHexRequest("{VDP regs}",0,64,regs, *this);
  824. //new SimpleHexRequest("{VDP status regs}",0,16,regs, *this);
  825. // now combined in one request:
  826. new SimpleHexRequest(
  827. "debug_bin2hex "
  828. "[ debug read_block {VDP regs} 0 64 ]"
  829. "[ debug read_block {VDP status regs} 0 16 ]"
  830. "[ debug read_block {VRAM pointer} 0 2 ]",
  831. 64 + 16 + 2, regs, *this);
  832. }
  833. void VDPRegViewer::DataHexRequestReceived()
  834. {
  835. decodeStatusVDPRegs();
  836. decodeVDPRegs();
  837. }
  838. void VDPRegViewer::registerBitChanged(int reg, int bit, bool state)
  839. {
  840. // maybe this call is the result of our own SetChecked (VDPDataStorte
  841. // update event)
  842. if ((state ? 1 : 0) == (regs[reg] & (1 << bit))) {
  843. return;
  844. }
  845. // state does not correspond to the current register setting so we send
  846. // an update command
  847. if (state) {
  848. regs[reg] |= (1 << bit);
  849. } else {
  850. regs[reg] &= ~(1 << bit);
  851. }
  852. CommClient::instance().sendCommand(
  853. new SimpleCommand(
  854. QString("debug write {VDP regs} %1 %2").arg(reg).arg(regs[reg])));
  855. // Update display without waiting for the VDPDataStore update
  856. decodeVDPRegs();
  857. // and then we could request an update nevertheless since some other
  858. // objects might want to see this change through the VDPDataStore also
  859. // :-)
  860. // VDPDataStore::instance().refresh();
  861. }
  862. void VDPRegViewer::on_VDPcomboBox_currentIndexChanged(int index)
  863. {
  864. switch (index) {
  865. case 0:
  866. vdpid = VDP_V9958;
  867. break;
  868. case 1:
  869. vdpid = VDP_V9938;
  870. break;
  871. case 2:
  872. vdpid = VDP_TMS99X8;
  873. break;
  874. }
  875. decodeStatusVDPRegs();
  876. decodeVDPRegs();
  877. }