13#include "imgui_internal.h"
30static const char* modeName(uint32_t v)
33 static constexpr std::array<const char*, 32> modeNames = {
34 "Graphic 1 (screen 1)",
35 "Multicolor (screen 3)",
36 "Text 1 (screen 0, width 40)",
39 "Graphic 2 (screen 2)",
44 "Graphic 3 (screen 4)",
46 "Text 2 (screen 0, width 80)",
49 "Graphic 4 (screen 5)",
54 "Graphic 5 (screen 6)",
59 "Graphic 6 (screen 7)",
69 "Graphic 7 (screen 8)",
78using Bits = std::array<const char*, 8>;
84static constexpr auto registerDescriptions = std::array{
85 RD{{
" 0 ",
"DG ",
"IE2",
"IE1",
"M5 ",
"M4 ",
"M3 ",
" 0 "},
"Mode register 0"},
86 RD{{
" 0 ",
"BL ",
"IE0",
"M1 ",
"M2 ",
" 0 ",
"SI ",
"MAG"},
"Mode register 1"},
87 RD{{
" 0 ",
"A16",
"A15",
"A14",
"A13",
"A12",
"A11",
"A10"},
"Pattern name table base address register"},
88 RD{{
"A13",
"A12",
"A11",
"A10",
"A9 ",
"A8 ",
"A7 ",
"A6 "},
"Color table base address register low"},
89 RD{{
" 0 ",
" 0 ",
"A16",
"A15",
"A14",
"A13",
"A12",
"A11"},
"Pattern generator table base address register"},
90 RD{{
"A14",
"A13",
"A12",
"A11",
"A10",
"A9 ",
"A8 ",
"A7 "},
"Sprite attribute table base address register low"},
91 RD{{
" 0 ",
" 0 ",
"A16",
"A15",
"A14",
"A13",
"A12",
"A11"},
"Sprite pattern generator table base address register"},
92 RD{{
"TC3",
"TC2",
"TC1",
"TC0",
"BD3",
"BD2",
"BD1",
"BD0"},
"Text color/Back drop color register"},
94 RD{{
"MS ",
"LP ",
"TP ",
"CB ",
"VR ",
" 0 ",
"SPD",
"BW "},
"Mode register 2"},
95 RD{{
"LN ",
" 0 ",
"S1 ",
"S2 ",
"IL ",
"EO ",
"*NT",
"DC "},
"Mode register 3"},
96 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"A16",
"A15",
"A14"},
"Color table base address register high"},
97 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"A16",
"A15"},
"Sprite attribute table base address register high"},
98 RD{{
"T23",
"T22",
"T21",
"T20",
"BC3",
"BC2",
"BC1",
"BC0"},
"Text color/Back color register"},
99 RD{{
"ON3",
"ON2",
"ON1",
"ON0",
"OF3",
"OF2",
"OF1",
"OF0"},
"Blinking period register"},
100 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"A16",
"A15",
"A14"},
"VRAM Access base address register"},
101 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"S3 ",
"S2 ",
"S1 ",
"S0 "},
"Status register pointer"},
103 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"C3 ",
"C2 ",
"C1 ",
"C0 "},
"Color palette address register"},
104 RD{{
"AII",
" 0 ",
"RS5",
"RS4",
"RS3",
"RS2",
"RS1",
"RS0"},
"Control register pointer"},
105 RD{{
"V3 ",
"V2 ",
"V1 ",
"V0 ",
"H3 ",
"H2 ",
"H1 ",
"H0 "},
"Display adjust register"},
106 RD{{
"IL7",
"IL6",
"IL5",
"IL4",
"IL3",
"IL2",
"IL1",
"IL0"},
"Interrupt line register"},
107 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 "},
"Color burst register 1"},
108 RD{{
" 0 ",
" 0 ",
" 1 ",
" 1 ",
" 1 ",
" 0 ",
" 1 ",
" 1 "},
"Color burst register 2"},
109 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 1 ",
" 0 ",
" 1 "},
"Color burst register 3"},
110 RD{{
"DO7",
"DO6",
"DO5",
"DO4",
"DO3",
"DO2",
"DO1",
"DO0"},
"Display offset register"},
112 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
113 RD{{
" 0 ",
"CMD",
"VDS",
"YAE",
"YJK",
"WTE",
"MSK",
"SP2"},
"V9958 control register"},
114 RD{{
" 0 ",
" 0 ",
"HO8",
"HO7",
"HO6",
"HO5",
"HO4",
"HO3"},
"Horizontal scroll register high"},
115 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"HO2",
"HO1",
"HO0"},
"Horizontal scroll register low"},
116 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
117 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
118 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
119 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
121 RD{{
"SX7",
"SX6",
"SX5",
"SX4",
"SX3",
"SX2",
"SX1",
"SX0"},
"Source X low register"},
122 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"SX8"},
"Source X high register"},
123 RD{{
"SY7",
"SY6",
"SY5",
"SY4",
"SY3",
"SY2",
"SY1",
"SY0"},
"Source Y low register"},
124 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"SY9",
"SY8"},
"Source Y high register"},
125 RD{{
"DX7",
"DX6",
"DX5",
"DX4",
"DX3",
"DX2",
"DX1",
"DX0"},
"Destination X low register"},
126 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"DX8"},
"Destination X high register"},
127 RD{{
"DY7",
"DY6",
"DY5",
"DY4",
"DY3",
"DY2",
"DY1",
"DY0"},
"Destination Y low register"},
128 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"DY9",
"DY8"},
"Destination Y high register"},
130 RD{{
"NX7",
"NX6",
"NX5",
"NX4",
"NX3",
"NX2",
"NX1",
"NX0"},
"Number of dots X low register"},
131 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"NX8"},
"Number of dots X high register"},
132 RD{{
"NY7",
"NY6",
"NY5",
"NY4",
"NY3",
"NY2",
"NY1",
"NY0"},
"Number of dots Y low register"},
133 RD{{
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
" 0 ",
"NY9",
"NY8"},
"Number of dots Y high register"},
134 RD{{
"CH3",
"CH2",
"CH1",
"CH0",
"CL3",
"CL2",
"CL1",
"CL0"},
"Color register"},
135 RD{{
" 0 ",
"MXC",
"MXD",
"MXS",
"DIY",
"DIX",
"EQ ",
"MAJ"},
"Argument register"},
136 RD{{
"CM3",
"CM2",
"CM1",
"CM0",
"LO3",
"LO2",
"LO1",
"LO0"},
"Command register"},
137 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
139 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
140 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
141 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
142 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
143 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
144 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
145 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
146 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
148 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
149 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
150 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
151 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
152 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
153 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
154 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
155 RD{{
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - ",
" - "},
""},
159 RD{{
" F ",
"5S ",
" C ",
"FS4",
"FS3",
"FS2",
"FS1",
"FS0"},
"Status register 0"},
160 RD{{
"FL ",
"LPS",
"ID4",
"ID3",
"ID2",
"ID1",
"ID0",
"FH "},
"Status register 1"},
161 RD{{
"TR ",
"VR ",
"HR ",
"BD ",
" 1 ",
" 1 ",
"EO ",
"CE "},
"Status register 2"},
162 RD{{
"X7 ",
"X6 ",
"X5 ",
"X4 ",
"X3 ",
"X2 ",
"X1 ",
"X0 "},
"Column register low"},
163 RD{{
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
"X8 "},
"Column register high"},
164 RD{{
"Y7 ",
"Y6 ",
"Y5 ",
"Y4 ",
"Y3 ",
"Y2 ",
"Y1 ",
"Y0 "},
"Row register low"},
165 RD{{
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
"EO ",
"Y8 "},
"Row register high"},
166 RD{{
"C7 ",
"C6 ",
"C5 ",
"C4 ",
"C3 ",
"C2 ",
"C1 ",
"C0 "},
"Color register"},
168 RD{{
"BX7",
"BX6",
"BX5",
"BX4",
"BX3",
"BX2",
"BX1",
"BX0"},
"Border X register low"},
169 RD{{
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
" 1 ",
"BX8"},
"Border X register high"},
173 uint8_t
reg = uint8_t(-1);
179 std::array<SubFunction, 2>
subs;
185using namespace std::literals;
189static const VDP* g_vdp;
190static std::array<uint8_t, 64 + 10> registerValues;
191static uint8_t getMode() {
return uint8_t(((registerValues[1] & 0x18) >> 3) | ((registerValues[0] & 0x0E) << 1)); }
192static bool isText2Mode() {
return getMode() == 0b01010; }
193static bool isGraph23Mode() {
return getMode() ==
one_of(0b00100, 0b01000); }
194static bool isSprite2Mode() {
return getMode() ==
one_of(0b01000, 0b01100, 0b10000, 0b10100, 0b11100); }
195static bool isBitmapMode() {
return getMode() >= 0x0C; }
196static bool isPlanarMode() {
return (getMode() & 0x14) == 0x14; }
198static constexpr auto regFunctions = std::array{
201 R{{
S{1, 0x40}},
"screen display enable/disable",
202 [](uint32_t v) {
return TemporaryString(v ?
"enabled" :
"disabled"); }},
204 R{{
S{1, 0x18}, {0, 0x0E}},
"display mode",
207 R{{
S{9, 0x02}},
"select PAL or NTSC",
208 [](uint32_t v) {
return TemporaryString(v ?
"PAL (50Hz)" :
"NTSC (60Hz)"); }},
211 R{{
S{9, 0x80}},
"select 192 or 212 lines",
212 [](uint32_t v) {
return TemporaryString(v ?
"212 lines" :
"192 lines"); }},
214 R{{
S{9, 0x08}},
"interlace enable/disable",
215 [](uint32_t v) {
return TemporaryString(v ?
"interlaced" :
"non-interlaced"); }},
217 R{{
S{9, 0x04}},
"alternate odd/even pages enable/disable",
218 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"do not",
" alternate odd/even pages\n"); }},
221 R{{
S{8, 0x02}},
"sprite enable/disable",
222 [](uint32_t v) {
return TemporaryString(v ?
"disabled" :
"enabled"); }},
224 R{{
S{1, 0x02}},
"sprite size, 8x8 or 16x16",
225 [](uint32_t v) {
return tmpStrCat(
"size=", v ?
"16x16" :
"8x8"); }},
227 R{{
S{1, 0x01}},
"sprite magnification enable/disable",
228 [](uint32_t v) {
return TemporaryString(v ?
"magnified\n" :
"not-magnified\n"); }},
230 R{{
S{8, 0x20}},
"color 0 transparent or not",
231 [](uint32_t v) {
return tmpStrCat(
"color 0 is ", v ?
"a regular color\n" :
"transparent\n"); }},
233 R{{
S{1, 0x20}},
"V-Blank interrupt enable/disable",
234 [](uint32_t v) {
return tmpStrCat(
"V-Blank-IRQ: ", v ?
"enabled" :
"disabled"); }},
236 R{{
S{0, 0x10}},
"line interrupt enable/disable",
237 [](uint32_t v) {
return tmpStrCat(
"line-IRQ: ", v ?
"enabled" :
"disabled",
'\n'); }},
239 R{{
S{0, 0x40}},
"digitize", &noExplanation},
240 R{{
S{0, 0x20}},
"light pen interrupt enable", &noExplanation},
241 R{{
S{1, 0x04}},
"fast blink mode", &noExplanation},
242 R{{
S{8, 0x80}},
"mouse", &noExplanation},
243 R{{
S{8, 0x40}},
"light pen", &noExplanation},
244 R{{
S{8, 0x10}},
"set color bus input/output", &noExplanation},
245 R{{
S{8, 0x08}},
"select VRAM type", &noExplanation},
246 R{{
S{8, 0x01}},
"select black&white output", &noExplanation},
247 R{{
S{9, 0x30}},
"simultaneous mode", &noExplanation},
248 R{{
S{9, 0x01}},
"set DLCLK input/output", &noExplanation},
249 R{{
S{0, 0}},
"", &spacing},
252 R{{
S{2, 0x7F}},
"name table address", [](uint32_t v) {
255 }
else if (isBitmapMode()) {
257 if (isPlanarMode()) {
261 return tmpStrCat(
"name table: 0x", hex_string<5>(v << 10),
'\n');
263 R{{
S{3, 0xFF},
S{10, 0x07}},
"color table address", [](uint32_t v) {
264 if (isText2Mode()) v &= ~0x07;
265 if (isGraph23Mode()) v &= ~0x7F;
266 return tmpStrCat(
"color table: 0x", hex_string<5>(v << 6),
'\n');
268 R{{
S{4, 0x3F}},
"pattern table address", [](uint32_t v) {
269 if (isGraph23Mode()) v &= ~0x03;
270 return tmpStrCat(
"pattern table: 0x", hex_string<5>(v << 11),
'\n');
272 R{{
S{5, 0xFF},
S{11, 0x03}},
"sprite attribute table address", [](uint32_t v) {
273 if (isSprite2Mode()) {
276 return tmpStrCat(
"sprite attribute table: 0x", hex_string<5>(v << 7),
'\n');
278 R{{
S{6, 0x3F}},
"sprite pattern table address", [](uint32_t v) {
279 return tmpStrCat(
"sprite pattern table: 0x", hex_string<5>(v << 11),
'\n');
281 R{{
S{2, 0}},
"", &spacing},
285 R{{
S{7, 0xF0}},
"text color",
286 [](uint32_t v) {
return tmpStrCat(
" foreground=", v); }},
287 R{{
S{7, 0x0F}},
"background color",
288 [](uint32_t v) {
return tmpStrCat(
" background=", v,
'\n'); }},
289 R{{
S{13, 0}},
"", [](uint32_t) {
return TemporaryString(
"text blink color:"); }},
290 R{{
S{12, 0xF0}},
"text blink color",
291 [](uint32_t v) {
return tmpStrCat(
" foreground=", v); }},
292 R{{
S{12, 0x0F}},
"background blink color",
293 [](uint32_t v) {
return tmpStrCat(
" background=", v,
'\n'); }},
295 R{{
S{13, 0xF0}},
"blink period on",
296 [](uint32_t v) {
return tmpStrCat(
" on=", 10 * v); }},
297 R{{
S{13, 0x0F}},
"blink period off",
298 [](uint32_t v) {
return tmpStrCat(
" off=", 10 * v); }},
300 R{{
S{7, 0}},
"", &spacing},
304 R{{
S{18, 0x0F}},
"horizontal set-adjust",
305 [](uint32_t v) {
return tmpStrCat(
" horizontal=",
int(v ^ 7) - 7); }},
306 R{{
S{18, 0xF0}},
"vertical set-adjust",
307 [](uint32_t v) {
return tmpStrCat(
" vertical=",
int(v ^ 7) - 7,
'\n'); }},
308 R{{
S{19, 0xFF}},
"line number for line-interrupt",
309 [](uint32_t v) {
return tmpStrCat(
"line interrupt=", v,
'\n'); }},
310 R{{
S{23, 0xFF}},
"vertical scroll (line number for 1st line)",
311 [](uint32_t v) {
return tmpStrCat(
"vertical scroll=", v,
'\n'); }},
312 R{{
S{18, 0}},
"", &spacing},
315 R{{
S{14, 0x07}},
"VRAM access base address",
316 [](uint32_t v) {
return tmpStrCat(
"VRAM access base address: ", hex_string<5>(v << 14)); }},
317 R{{
S{14, 0}},
"", [](uint32_t) {
319 return tmpStrCat(
", full address: ", hex_string<5>(addr),
'\n');
321 R{{
S{15, 0x0F}},
"select status register",
322 [](uint32_t v) {
return tmpStrCat(
"selected status register: ", v,
'\n'); }},
323 R{{
S{16, 0x0F}},
"select palette entry",
324 [](uint32_t v) {
return tmpStrCat(
"selected palette entry: ", v,
'\n'); }},
325 R{{
S{17, 0x3F}},
"indirect register access",
326 [](uint32_t v) {
return tmpStrCat(
"selected indirect register: ", v); }},
328 R{{
S{17, 0x80}},
"auto-increment",
329 [](uint32_t v) {
return tmpStrCat(v ?
"no " :
"",
"auto-increment\n"); }},
330 R{{
S{14, 0}},
"", &spacing},
333 R{{
S{27, 0x07},
S{26, 0x3F}},
"horizontal scroll", [](uint32_t v) {
334 auto s = (v & ~7) - (v & 7);
335 return tmpStrCat(
"horizontal scroll: ", s);
338 R{{
S{25, 0x01}},
"2-page scroll enable/disable",
339 [](uint32_t v) {
return tmpStrCat(v + 1,
"-page"); }},
341 R{{
S{25, 0x02}},
"mask 8 left dots",
342 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"not-",
"masked\n"); }},
343 R{{
S{25, 0x18}},
"YJK/YAE mode",
344 [](uint32_t v) {
return tmpStrCat((v & 1) ? ((v & 2) ?
"YJK+YAE" :
"YJK") :
"RGB",
"-mode\n"); }},
345 R{{
S{25, 0x40}},
"expand command mode",
346 [](uint32_t v) {
return tmpStrCat(
"commands ", (v ?
"work in all " :
"only work in bitmap-"),
"modes\n"); }},
347 R{{
S{25, 0x20}},
"output select between CPUCLK and /VDS", &noExplanation},
348 R{{
S{25, 0x04}},
"enable/disable WAIT (not used on MSX)", &noExplanation},
349 R{{
S{25, 0}},
"", &spacing},
352 R{{
S{46, 0xF0}},
"command code", [](uint32_t v) {
353 static constexpr std::array<zstring_view, 16> COMMANDS = {
354 " ABRT",
" ????",
" ????",
" ????",
"POINT",
" PSET",
" SRCH",
" LINE",
355 " LMMV",
" LMMM",
" LMCM",
" LMMC",
" HMMV",
" HMMM",
" YMMM",
" HMMC"
360 R{{
S{46, 0x0F}},
"command code", [](uint32_t v) {
361 static constexpr std::array<zstring_view, 16> OPS = {
362 "IMP ",
"AND ",
"OR ",
"XOR ",
"NOT ",
"NOP ",
"NOP ",
"NOP ",
363 "TIMP",
"TAND",
"TOR ",
"TXOR",
"TNOT",
"NOP ",
"NOP ",
"NOP "
368 R{{
S{32, 0xFF},
S{33, 0x01}},
"source X", [](uint32_t v) {
return tmpStrCat(v); }},
370 R{{
S{34, 0xFF},
S{35, 0x03}},
"source Y", [](uint32_t v) {
return tmpStrCat(v); }},
372 R{{
S{36, 0xFF},
S{37, 0x01}},
"destination X", [](uint32_t v) {
return tmpStrCat(v); }},
374 R{{
S{38, 0xFF},
S{39, 0x03}},
"destination Y", [](uint32_t v) {
return tmpStrCat(v); }},
376 R{{
S{44, 0xFF}},
"color", [](uint32_t v) {
return tmpStrCat(v); }},
378 R{{
S{45, 0x04}},
"direction X", [](uint32_t v) {
return TemporaryString(v ?
"-" :
"+"); }},
379 R{{
S{40, 0xFF},
S{41, 0x01}},
"number of dots X", [](uint32_t v) {
return tmpStrCat(v); }},
381 R{{
S{45, 0x08}},
"direction Y", [](uint32_t v) {
return TemporaryString(v ?
"-" :
"+"); }},
382 R{{
S{42, 0xFF},
S{43, 0x03}},
"number of dots Y", [](uint32_t v) {
return tmpStrCat(v); }},
385 R{{
S{45, 0x40}},
"expanded VRAM for CPU access", &noExplanation},
386 R{{
S{45, 0x20}},
"expanded VRAM for destination", &noExplanation},
387 R{{
S{45, 0x10}},
"expanded VRAM for source", &noExplanation},
388 R{{
S{45, 0x02}},
"select equal/not-equal for SRCH command", &noExplanation},
389 R{{
S{45, 0x01}},
"select major direction (X/Y) for LINE command", &noExplanation},
390 R{{
S{32, 0}},
"", &spacing},
393 R{{
S{64, 0x80}},
"VBLANK interrupt pending",
394 [](uint32_t v) {
return tmpStrCat(
"VBLANK-IRQ: ", v); }},
396 R{{
S{65, 0x01}},
"line interrupt pending",
397 [](uint32_t v) {
return tmpStrCat(
"line-IRQ: ", v); }},
400 R{{
S{64, 0x40}},
"5th/9th sprite detected",
401 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"no ",
"5th/9th sprite per line"); }},
402 R{{
S{64, 0x1F}},
"5th/9th sprite number",
403 [](uint32_t v) {
return tmpStrCat(
" (sprite number=", v,
")\n"); }},
405 R{{
S{64, 0x20}},
"sprite collision",
406 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"no ",
"sprite collision"); }},
408 R{{
S{67, 0xFF},
S{68, 0x01}},
"x-coordinate",
409 [](uint32_t v) {
return tmpStrCat(
"x=", v); }},
410 R{{
S{69, 0xFF},
S{70, 0x03}},
"y-coordinate",
411 [](uint32_t v) {
return tmpStrCat(
"y=", v); }},
416 R{{
S{66, 0x01}},
"command executing",
417 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"not ",
"running"); }},
419 R{{
S{66, 0x80}},
"transfer ready flag",
420 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"not ",
"ready to transfer\n"); }},
423 R{{
S{66, 0x20}},
"horizontal border",
424 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"not ",
"in horizontal border"); }},
426 R{{
S{66, 0x40}},
"vertical border",
427 [](uint32_t v) {
return tmpStrCat(v ?
"" :
"not ",
"in vertical border\n"); }},
429 R{{
S{65, 0x80}},
"light pen (not used on MSX)", &noExplanation},
430 R{{
S{65, 0x40}},
"light pen switch (not used on MSX)", &noExplanation},
431 R{{
S{65, 0x3E}},
"VDP identification (V9938 or V9958)", &noExplanation},
432 R{{
S{66, 0x10}},
"SRCH command detected border color", &noExplanation},
433 R{{
S{66, 0x02}},
"odd/even field", &noExplanation},
434 R{{
S{71, 0xFF}},
"result of POINT command", &noExplanation},
435 R{{
S{72, 0xFF},
S{73, 0x01}},
"result of SRCH command", &noExplanation},
438static int lookupFunction(uint8_t reg, uint8_t mask)
441 for (
const auto& f : regFunctions) {
442 for (
const auto& s : f.subs) {
443 if ((reg == s.reg) && (mask & s.mask)) {
452void ImGuiVdpRegs::drawSection(std::span<const uint8_t> showRegisters, std::span<const uint8_t> regValues,
453 VDP& vdp, EmuTime::param time)
456 HelpMarker(
"Click to toggle bits, or edit the hex-field.\n"
457 "Right-click to show/hide register explanation.");
465 auto mouse_pos = ImGui::GetMousePos();
466 const auto* table = ImGui::GetCurrentTable();
467 auto isCellHovered = [&]() {
468 return ImGui::TableGetCellBgRect(table, table->CurrentColumn).Contains(mouse_pos);
472 auto reg = showRegisters[i];
475 const auto& rd = registerDescriptions[reg];
476 if (ImGui::TableNextColumn()) {
477 auto name = tmpStrCat(reg < 64 ?
"R#" :
"S#", reg < 64 ? reg : reg - 64);
478 ImGui::AlignTextToFramePadding();
479 ImGui::TextUnformatted(static_cast<std::string_view>(name));
480 simpleToolTip(rd.name);
482 uint8_t value = regValues[reg];
483 bool writeReg =
false;
484 if (ImGui::TableNextColumn()) {
486 if (ImGui::InputScalar(
"##value", ImGuiDataType_U8, &value,
nullptr,
nullptr,
"%02X", ImGuiInputTextFlags_CharsHexadecimal)) {
490 ImGui::Text(
"%02X", value);
493 const auto& bits = rd.bits;
495 if (ImGui::TableNextColumn()) {
497 auto mask = narrow<uint8_t>(1 << bit);
498 int f = lookupFunction(reg, mask);
499 if (f != -1 && f == hoveredFunction) {
500 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,
504 if (ImGui::Button(bits[bit_], {40.0f, 0.0f})) {
509 if ((f != -1) && isCellHovered()) {
510 newHoveredFunction = f;
511 if (
auto tip = regFunctions[f].toolTip; !tip.empty()) {
517 if (writeReg && (reg < 64)) {
518 vdp.changeRegister(reg, value, time);
523 auto* drawList = ImGui::GetWindowDrawList();
524 gl::vec2 framePadding = ImGui::GetStyle().FramePadding;
526 const auto& func = regFunctions[f];
527 if (!(
contains(showRegisters, func.subs[0].reg) ||
528 contains(showRegisters, func.subs[1].reg))) {
533 for (
const auto& sub : func.subs) {
534 if (sub.reg == uint8_t(-1))
break;
535 auto tmp = ((regValues[sub.reg] & sub.mask) >> std::countr_zero(sub.mask));
536 value |= tmp << shift;
537 shift += std::popcount(sub.mask);
539 if (
auto s = func.displayFunc(value); !s.empty()) {
540 auto textColor =
getColor(imColor::TEXT);
541 bool canHover = func.subs[0].mask != 0;
542 if (canHover && (f == hoveredFunction)) {
544 gl::vec2 pos = ImGui::GetCursorScreenPos();
545 textColor =
getColor(imColor::BLACK);
546 drawList->AddRectFilled(pos - framePadding, pos + textSize + 2.0f * framePadding,
getColor(imColor::YELLOW));
552 if (ImGui::IsItemHovered()) {
553 newHoveredFunction = f;
556 if (
auto reg = func.subs[0].reg; reg < 64) {
557 if (ImGui::IsItemClicked()) {
558 auto mask = func.subs[0].mask;
559 vdp.changeRegister(reg, regValues[reg] ^ mask, time);
564 if (!s.ends_with(
'\n')) ImGui::SameLine();
572 if (!show || !motherBoard)
return;
574 ImGui::SetNextWindowSize(
gl::vec2{41, 29} * ImGui::GetFontSize(), ImGuiCond_FirstUseEver);
576 auto* vdp =
dynamic_cast<VDP*
>(motherBoard->
findDevice(
"VDP"));
579 const bool tms99x8 = vdp->isMSX1VDP();
580 const bool v9958 = vdp->hasYJK();
583 for (
auto reg :
xrange(64)) {
584 registerValues[reg] = vdp->peekRegister(reg);
586 for (
auto reg :
xrange(uint8_t(10))) {
587 registerValues[reg + 64] = vdp->peekStatusReg(reg, time);
590 newHoveredFunction = -1;
592 return std::span<const uint8_t, std::dynamic_extent>(std::span(array));
596 static constexpr auto modeRegs1 = std::to_array<uint8_t>({0, 1});
597 static constexpr auto modeRegs2 = std::to_array<uint8_t>({0, 1, 8, 9});
599 drawSection(modeRegs, registerValues, *vdp, time);
602 static constexpr auto tableRegs1 = std::to_array<uint8_t>({2, 3, 4, 5, 6});
603 static constexpr auto tableRegs2 = std::to_array<uint8_t>({2, 3, 10, 4, 5, 11, 6});
605 drawSection(tableRegs, registerValues, *vdp, time);
608 static constexpr auto colorRegs1 = std::to_array<uint8_t>({7});
609 static constexpr auto colorRegs2 = std::to_array<uint8_t>({7, 12, 13, 20, 21, 22});
611 drawSection(colorRegs, registerValues, *vdp, time);
615 static constexpr auto displayRegs = std::to_array<uint8_t>({18, 19, 23});
616 drawSection(displayRegs, registerValues, *vdp, time);
619 static constexpr auto accessRegs = std::to_array<uint8_t>({14, 15, 16, 17});
620 drawSection(accessRegs, registerValues, *vdp, time);
625 static constexpr auto v9958Regs = std::to_array<uint8_t>({25, 26, 27});
626 drawSection(v9958Regs, registerValues, *vdp, time);
632 static constexpr auto cmdRegs = std::to_array<uint8_t>({
633 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46
635 drawSection(cmdRegs, registerValues, *vdp, time);
639 static constexpr auto statusRegs1 = std::to_array<uint8_t>({64});
640 static constexpr auto statusRegs2 = std::to_array<uint8_t>({
641 64, 65, 66, 67, 68, 69, 70, 71, 72, 73
644 drawSection(statusRegs, registerValues, *vdp, time);
646 hoveredFunction = newHoveredFunction;
648 if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
649 ImGui::OpenPopup(
"context");
652 if (ImGui::Checkbox(
"Show explanation ", &explanation)) {
653 ImGui::CloseCurrentPopup();
void loadLine(std::string_view name, zstring_view value) override
void save(ImGuiTextBuffer &buf) override
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
MSXDevice * findDevice(std::string_view name)
Find a MSXDevice by name.
Unified implementation of MSX Video Display Processors (VDPs).
int getVramPointer() const
Get vram pointer (14-bit) (only for debugger)
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
auto CalcTextSize(std::string_view str)
void TextUnformatted(const std::string &str)
void Table(const char *str_id, int column, ImGuiTableFlags flags, const ImVec2 &outer_size, float inner_width, std::invocable<> auto next)
void Window(const char *name, bool *p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
bool TreeNode(const char *label, ImGuiTreeNodeFlags flags, std::invocable<> auto next)
void StyleColor(bool active, Args &&...args)
void Popup(const char *str_id, ImGuiWindowFlags flags, std::invocable<> auto next)
void ID_for_range(std::integral auto count, std::invocable< int > auto next)
This file implemented 3 utility functions:
bool loadOnePersistent(std::string_view name, zstring_view value, C &c, const std::tuple< Elements... > &tup)
void simpleToolTip(std::string_view desc)
void savePersistent(ImGuiTextBuffer &buf, C &c, const std::tuple< Elements... > &tup)
void HelpMarker(std::string_view desc)
ImU32 getColor(imColor col)
std::array< const char *, 8 > Bits
size_t size(std::string_view utf8)
constexpr To narrow(From from) noexcept
constexpr auto make_span(Range &&range)
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
TemporaryString tmpStrCat(Ts &&... ts)
std::array< SubFunction, 2 > subs
TemporaryString(* displayFunc)(uint32_t)
constexpr auto xrange(T e)