1 //============================================================================
2 //
3 // SSSS tt lll lll
4 // SS SS tt ll ll
5 // SS tttttt eeee ll ll aaaa
6 // SSSS tt ee ee ll ll aa
7 // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8 // SS SS tt ee ll ll aa aa
9 // SSSS ttt eeeee llll llll aaaaa
10 //
11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //============================================================================
17
18 #include "Base.hxx"
19 #include "System.hxx"
20 #include "Debugger.hxx"
21 #include "TIA.hxx"
22 #include "DelayQueueIterator.hxx"
23 #include "RiotDebug.hxx"
24
25 #include "TIADebug.hxx"
26
27 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TIADebug(Debugger & dbg,Console & console)28 TIADebug::TIADebug(Debugger& dbg, Console& console)
29 : DebuggerSystem(dbg, console),
30 myTIA{console.tia()}
31 {
32 }
33
34 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getState()35 const DebuggerState& TIADebug::getState()
36 {
37 // Color registers
38 myState.coluRegs.clear();
39 myState.coluRegs.push_back(coluP0());
40 myState.coluRegs.push_back(coluP1());
41 myState.coluRegs.push_back(coluPF());
42 myState.coluRegs.push_back(coluBK());
43
44 // Debug Colors
45 int timing = myConsole.timing() == ConsoleTiming::ntsc ? 0
46 : myConsole.timing() == ConsoleTiming::pal ? 1 : 2;
47
48 myState.fixedCols.clear();
49 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::P0]);
50 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::P1]);
51 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::PF]);
52 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::BK]);
53 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::M0]);
54 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::M1]);
55 myState.fixedCols.push_back(myTIA.myFixedColorPalette[timing][TIA::BL]);
56 myState.fixedCols.push_back(TIA::FixedColor::HBLANK_WHITE);
57
58 // Collisions
59 myState.cx.clear();
60 myState.cx.push_back(collP0_PF());
61 myState.cx.push_back(collP0_BL());
62 myState.cx.push_back(collM1_P0());
63 myState.cx.push_back(collM0_P0());
64 myState.cx.push_back(collP0_P1());
65 myState.cx.push_back(collP1_PF());
66 myState.cx.push_back(collP1_BL());
67 myState.cx.push_back(collM1_P1());
68 myState.cx.push_back(collM0_P1());
69 myState.cx.push_back(collM0_PF());
70 myState.cx.push_back(collM0_BL());
71 myState.cx.push_back(collM0_M1());
72 myState.cx.push_back(collM1_PF());
73 myState.cx.push_back(collM1_BL());
74 myState.cx.push_back(collBL_PF());
75
76 // Player 0 & 1 and Ball graphics registers
77 myState.gr.clear();
78 myState.gr.push_back(myTIA.myPlayer0.getGRPNew());
79 myState.gr.push_back(myTIA.myPlayer1.getGRPNew());
80 myState.gr.push_back(myTIA.myPlayer0.getGRPOld());
81 myState.gr.push_back(myTIA.myPlayer1.getGRPOld());
82 myState.gr.push_back(myTIA.myBall.getENABLNew());
83 myState.gr.push_back(myTIA.myBall.getENABLOld());
84 myState.gr.push_back(enaM0());
85 myState.gr.push_back(enaM1());
86
87 // Player 0 & 1, Missile 0 & 1 and Ball graphics status registers
88 myState.ref.clear();
89 myState.ref.push_back(refP0());
90 myState.ref.push_back(refP1());
91 myState.vdel.clear();
92 myState.vdel.push_back(vdelP0());
93 myState.vdel.push_back(vdelP1());
94 myState.vdel.push_back(vdelBL());
95 myState.resm.clear();
96 myState.resm.push_back(resMP0());
97 myState.resm.push_back(resMP1());
98
99 // Position registers
100 myState.pos.clear();
101 myState.pos.push_back(posP0());
102 myState.pos.push_back(posP1());
103 myState.pos.push_back(posM0());
104 myState.pos.push_back(posM1());
105 myState.pos.push_back(posBL());
106
107 // Horizontal move registers
108 myState.hm.clear();
109 myState.hm.push_back(hmP0());
110 myState.hm.push_back(hmP1());
111 myState.hm.push_back(hmM0());
112 myState.hm.push_back(hmM1());
113 myState.hm.push_back(hmBL());
114
115 // Playfield registers
116 myState.pf.clear();
117 myState.pf.push_back(pf0());
118 myState.pf.push_back(pf1());
119 myState.pf.push_back(pf2());
120 myState.pf.push_back(refPF());
121 myState.pf.push_back(scorePF());
122 myState.pf.push_back(priorityPF());
123
124 // Size registers
125 myState.size.clear();
126 myState.size.push_back(nusizP0());
127 myState.size.push_back(nusizP1());
128 myState.size.push_back(nusizM0());
129 myState.size.push_back(nusizM1());
130 myState.size.push_back(sizeBL());
131
132 // VSync/VBlank registers
133 myState.vsb.clear();
134 myState.vsb.push_back(vsync());
135 myState.vsb.push_back(vblank());
136
137 // Audio registers
138 myState.aud.clear();
139 myState.aud.push_back(audF0());
140 myState.aud.push_back(audF1());
141 myState.aud.push_back(audC0());
142 myState.aud.push_back(audC1());
143 myState.aud.push_back(audV0());
144 myState.aud.push_back(audV1());
145
146 // internal TIA state
147 myState.info.clear();
148 myState.info.push_back(frameCount());
149 myState.info.push_back(frameCycles());
150 myState.info.push_back(cyclesLo());
151 myState.info.push_back(cyclesHi());
152 myState.info.push_back(scanlines());
153 myState.info.push_back(scanlinesLastFrame());
154 myState.info.push_back(clocksThisLine());
155 myState.info.push_back(frameWsyncCycles());
156
157 return myState;
158 }
159
160 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
saveOldState()161 void TIADebug::saveOldState()
162 {
163 // Color registers
164 myOldState.coluRegs.clear();
165 myOldState.coluRegs.push_back(coluP0());
166 myOldState.coluRegs.push_back(coluP1());
167 myOldState.coluRegs.push_back(coluPF());
168 myOldState.coluRegs.push_back(coluBK());
169
170 // Collisions
171 myOldState.cx.clear();
172 myOldState.cx.push_back(collP0_PF());
173 myOldState.cx.push_back(collP0_BL());
174 myOldState.cx.push_back(collM1_P0());
175 myOldState.cx.push_back(collM0_P0());
176 myOldState.cx.push_back(collP0_P1());
177 myOldState.cx.push_back(collP1_PF());
178 myOldState.cx.push_back(collP1_BL());
179 myOldState.cx.push_back(collM1_P1());
180 myOldState.cx.push_back(collM0_P1());
181 myOldState.cx.push_back(collM0_PF());
182 myOldState.cx.push_back(collM0_BL());
183 myOldState.cx.push_back(collM0_M1());
184 myOldState.cx.push_back(collM1_PF());
185 myOldState.cx.push_back(collM1_BL());
186 myOldState.cx.push_back(collBL_PF());
187
188 // Player 0 & 1 graphics registers
189 myOldState.gr.clear();
190 myOldState.gr.push_back(myTIA.myPlayer0.getGRPNew());
191 myOldState.gr.push_back(myTIA.myPlayer1.getGRPNew());
192 myOldState.gr.push_back(myTIA.myPlayer0.getGRPOld());
193 myOldState.gr.push_back(myTIA.myPlayer1.getGRPOld());
194 myOldState.gr.push_back(myTIA.myBall.getENABLNew());
195 myOldState.gr.push_back(myTIA.myBall.getENABLOld());
196 myOldState.gr.push_back(enaM0());
197 myOldState.gr.push_back(enaM1());
198
199 // Player 0 & 1, Missile 0 & 1 and Ball graphics status registers
200 myOldState.ref.clear();
201 myOldState.ref.push_back(refP0());
202 myOldState.ref.push_back(refP1());
203 myOldState.vdel.clear();
204 myOldState.vdel.push_back(vdelP0());
205 myOldState.vdel.push_back(vdelP1());
206 myOldState.vdel.push_back(vdelBL());
207 myOldState.resm.clear();
208 myOldState.resm.push_back(resMP0());
209 myOldState.resm.push_back(resMP1());
210
211 // Position registers
212 myOldState.pos.clear();
213 myOldState.pos.push_back(posP0());
214 myOldState.pos.push_back(posP1());
215 myOldState.pos.push_back(posM0());
216 myOldState.pos.push_back(posM1());
217 myOldState.pos.push_back(posBL());
218
219 // Horizontal move registers
220 myOldState.hm.clear();
221 myOldState.hm.push_back(hmP0());
222 myOldState.hm.push_back(hmP1());
223 myOldState.hm.push_back(hmM0());
224 myOldState.hm.push_back(hmM1());
225 myOldState.hm.push_back(hmBL());
226
227 // Playfield registers
228 myOldState.pf.clear();
229 myOldState.pf.push_back(pf0());
230 myOldState.pf.push_back(pf1());
231 myOldState.pf.push_back(pf2());
232 myOldState.pf.push_back(refPF());
233 myOldState.pf.push_back(scorePF());
234 myOldState.pf.push_back(priorityPF());
235
236 // Size registers
237 myOldState.size.clear();
238 myOldState.size.push_back(nusizP0());
239 myOldState.size.push_back(nusizP1());
240 myOldState.size.push_back(nusizM0());
241 myOldState.size.push_back(nusizM1());
242 myOldState.size.push_back(sizeBL());
243
244 // VSync/VBlank registers
245 myOldState.vsb.clear();
246 myOldState.vsb.push_back(vsync());
247 myOldState.vsb.push_back(vblank());
248
249 // Audio registers
250 myOldState.aud.clear();
251 myOldState.aud.push_back(audF0());
252 myOldState.aud.push_back(audF1());
253 myOldState.aud.push_back(audC0());
254 myOldState.aud.push_back(audC1());
255 myOldState.aud.push_back(audV0());
256 myOldState.aud.push_back(audV1());
257
258 // internal TIA state
259 myOldState.info.clear();
260 myOldState.info.push_back(frameCount());
261 myOldState.info.push_back(frameCycles());
262 myOldState.info.push_back(cyclesLo());
263 myOldState.info.push_back(cyclesHi());
264 myOldState.info.push_back(scanlines());
265 myOldState.info.push_back(scanlinesLastFrame());
266 myOldState.info.push_back(clocksThisLine());
267 myOldState.info.push_back(frameWsyncCycles());
268 }
269
270 /* the set methods now use mySystem.poke(). This will save us the
271 trouble of masking the values here, since TIA::poke() will do it
272 for us.
273
274 This means that the GUI should *never* just display the value the
275 user entered: it should always read the return value of the set
276 method and display that.
277
278 An Example:
279
280 User enters "ff" in the AUDV0 field. GUI calls value = tiaDebug->audV0(0xff).
281 The AUDV0 register is only 4 bits wide, so "value" is 0x0f. That's what
282 should be displayed.
283
284 In a perfect world, the GUI would only allow one hex digit to be entered...
285 but we allow decimal or binary input in the GUI (with # or \ prefix). The
286 only way to make that work would be to validate the data entry after every
287 keystroke... which would be a pain for both us and the user. Using poke()
288 here is a compromise that allows the TIA to do the range-checking for us,
289 so the GUI and/or TIADebug don't have to duplicate logic from TIA::poke().
290 */
291
292 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vdelP0(int newVal)293 bool TIADebug::vdelP0(int newVal)
294 {
295 if(newVal > -1)
296 mySystem.poke(VDELP0, bool(newVal));
297
298 return myTIA.registerValue(VDELP0) & 0x01;
299 }
300
301 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vdelP1(int newVal)302 bool TIADebug::vdelP1(int newVal)
303 {
304 if(newVal > -1)
305 mySystem.poke(VDELP1, bool(newVal));
306
307 return myTIA.registerValue(VDELP1) & 0x01;
308 }
309
310 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vdelBL(int newVal)311 bool TIADebug::vdelBL(int newVal)
312 {
313 if(newVal > -1)
314 mySystem.poke(VDELBL, bool(newVal));
315
316 return myTIA.registerValue(VDELBL) & 0x01;
317 }
318
319 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
enaM0(int newVal)320 bool TIADebug::enaM0(int newVal)
321 {
322 if(newVal > -1)
323 mySystem.poke(ENAM0, bool(newVal) << 1);
324
325 return myTIA.registerValue(ENAM0) & 0x02;
326 }
327
328 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
enaM1(int newVal)329 bool TIADebug::enaM1(int newVal)
330 {
331 if(newVal > -1)
332 mySystem.poke(ENAM1, bool(newVal) << 1);
333
334 return myTIA.registerValue(ENAM1) & 0x02;
335 }
336
337 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
enaBL(int newVal)338 bool TIADebug::enaBL(int newVal)
339 {
340 if(newVal > -1)
341 mySystem.poke(ENABL, bool(newVal) << 1);
342
343 return myTIA.registerValue(ENABL) & 0x02;
344 }
345
346 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
resMP0(int newVal)347 bool TIADebug::resMP0(int newVal)
348 {
349 if(newVal > -1)
350 mySystem.poke(RESMP0, bool(newVal) << 1);
351
352 return myTIA.registerValue(RESMP0) & 0x02;
353 }
354
355 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
resMP1(int newVal)356 bool TIADebug::resMP1(int newVal)
357 {
358 if(newVal > -1)
359 mySystem.poke(RESMP1, bool(newVal) << 1);
360
361 return myTIA.registerValue(RESMP1) & 0x02;
362 }
363
364 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
refP0(int newVal)365 bool TIADebug::refP0(int newVal)
366 {
367 if(newVal > -1)
368 mySystem.poke(REFP0, bool(newVal) << 3);
369
370 return myTIA.registerValue(REFP0) & 0x08;
371 }
372
373 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
refP1(int newVal)374 bool TIADebug::refP1(int newVal)
375 {
376 if(newVal > -1)
377 mySystem.poke(REFP1, bool(newVal) << 3);
378
379 return myTIA.registerValue(REFP1) & 0x08;
380 }
381
382 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
refPF(int newVal)383 bool TIADebug::refPF(int newVal)
384 {
385 if(newVal > -1)
386 {
387 int tmp = myTIA.registerValue(CTRLPF);
388 if(newVal)
389 tmp |= 0x01;
390 else
391 tmp &= ~0x01;
392 mySystem.poke(CTRLPF, tmp);
393 }
394
395 return myTIA.registerValue(CTRLPF) & 0x01;
396 }
397
398 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scorePF(int newVal)399 bool TIADebug::scorePF(int newVal)
400 {
401 if(newVal > -1)
402 {
403 int tmp = myTIA.registerValue(CTRLPF);
404 if(newVal)
405 tmp |= 0x02;
406 else
407 tmp &= ~0x02;
408 mySystem.poke(CTRLPF, tmp);
409 }
410
411 return myTIA.registerValue(CTRLPF) & 0x02;
412 }
413
414 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
priorityPF(int newVal)415 bool TIADebug::priorityPF(int newVal)
416 {
417 if(newVal > -1)
418 {
419 int tmp = myTIA.registerValue(CTRLPF);
420 if(newVal)
421 tmp |= 0x04;
422 else
423 tmp &= ~0x04;
424 mySystem.poke(CTRLPF, tmp);
425 }
426
427 return myTIA.registerValue(CTRLPF) & 0x04;
428 }
429
430 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
collision(CollisionBit id,bool toggle) const431 bool TIADebug::collision(CollisionBit id, bool toggle) const
432 {
433 switch(id)
434 {
435 case CollisionBit::M0P1:
436 if(toggle)
437 myTIA.toggleCollP1M0();
438 return myTIA.collCXM0P() & 0x80;
439
440 case CollisionBit::M0P0:
441 if(toggle)
442 myTIA.toggleCollP0M0();
443 return myTIA.collCXM0P() & 0x40;
444
445 case CollisionBit::M1P0:
446 if(toggle)
447 myTIA.toggleCollP0M1();
448 return myTIA.collCXM1P() & 0x80;
449
450 case CollisionBit::M1P1:
451 if(toggle)
452 myTIA.toggleCollP1M1();
453 return myTIA.collCXM1P() & 0x40;
454
455 case CollisionBit::P0PF:
456 if(toggle)
457 myTIA.toggleCollP0PF();
458 return myTIA.collCXP0FB() & 0x80;
459 case CollisionBit::P0BL:
460 if(toggle)
461 myTIA.toggleCollP0BL();
462 return myTIA.collCXP0FB() & 0x40;
463
464 case CollisionBit::P1PF:
465 if(toggle)
466 myTIA.toggleCollP1PF();
467 return myTIA.collCXP1FB() & 0x80;
468
469 case CollisionBit::P1BL:
470 if(toggle)
471 myTIA.toggleCollP1BL();
472 return myTIA.collCXP1FB() & 0x40;
473
474 case CollisionBit::M0PF:
475 if(toggle)
476 myTIA.toggleCollM0PF();
477 return myTIA.collCXM0FB() & 0x80;
478
479 case CollisionBit::M0BL:
480 if(toggle)
481 myTIA.toggleCollM0BL();
482 return myTIA.collCXM0FB() & 0x40;
483
484 case CollisionBit::M1PF:
485 if(toggle)
486 myTIA.toggleCollM1PF();
487 return myTIA.collCXM1FB() & 0x80;
488
489 case CollisionBit::M1BL:
490 if(toggle)
491 myTIA.toggleCollM1BL();
492 return myTIA.collCXM1FB() & 0x40;
493
494 case CollisionBit::BLPF:
495 if(toggle)
496 myTIA.toggleCollBLPF();
497 return myTIA.collCXBLPF() & 0x80;
498
499 case CollisionBit::P0P1:
500 if(toggle)
501 myTIA.toggleCollP0P1();
502 return myTIA.collCXPPMM() & 0x80;
503
504 case CollisionBit::M0M1:
505 if(toggle)
506 myTIA.toggleCollM0M1();
507 return myTIA.collCXPPMM() & 0x40;
508 }
509 return false; // make compiler happy
510 }
511
512 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
audC0(int newVal)513 uInt8 TIADebug::audC0(int newVal)
514 {
515 if(newVal > -1)
516 mySystem.poke(AUDC0, newVal);
517
518 return myTIA.registerValue(AUDC0) & 0x0f;
519 }
520
521 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
audC1(int newVal)522 uInt8 TIADebug::audC1(int newVal)
523 {
524 if(newVal > -1)
525 mySystem.poke(AUDC1, newVal);
526
527 return myTIA.registerValue(AUDC1) & 0x0f;
528 }
529
530 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
audV0(int newVal)531 uInt8 TIADebug::audV0(int newVal)
532 {
533 if(newVal > -1)
534 mySystem.poke(AUDV0, newVal);
535
536 return myTIA.registerValue(AUDV0) & 0x0f;
537 }
538
539 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
audV1(int newVal)540 uInt8 TIADebug::audV1(int newVal)
541 {
542 if(newVal > -1)
543 mySystem.poke(AUDV1, newVal);
544
545 return myTIA.registerValue(AUDV1) & 0x0f;
546 }
547
548 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
audF0(int newVal)549 uInt8 TIADebug::audF0(int newVal)
550 {
551 if(newVal > -1)
552 mySystem.poke(AUDF0, newVal);
553
554 return myTIA.registerValue(AUDF0) & 0x1f;
555 }
556
557 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
audF1(int newVal)558 uInt8 TIADebug::audF1(int newVal)
559 {
560 if(newVal > -1)
561 mySystem.poke(AUDF1, newVal);
562
563 return myTIA.registerValue(AUDF1) & 0x1f;
564 }
565
566 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pf0(int newVal)567 uInt8 TIADebug::pf0(int newVal)
568 {
569 if(newVal > -1)
570 mySystem.poke(PF0, newVal << 4);
571
572 return myTIA.registerValue(PF0) >> 4;
573 }
574
575 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pf1(int newVal)576 uInt8 TIADebug::pf1(int newVal)
577 {
578 if(newVal > -1)
579 mySystem.poke(PF1, newVal);
580
581 return myTIA.registerValue(PF1);
582 }
583
584 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pf2(int newVal)585 uInt8 TIADebug::pf2(int newVal)
586 {
587 if(newVal > -1)
588 mySystem.poke(PF2, newVal);
589
590 return myTIA.registerValue(PF2);
591 }
592
593 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
coluP0(int newVal)594 uInt8 TIADebug::coluP0(int newVal)
595 {
596 if(newVal > -1)
597 mySystem.poke(COLUP0, newVal);
598
599 return myTIA.registerValue(COLUP0);
600 }
601
602 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
coluP1(int newVal)603 uInt8 TIADebug::coluP1(int newVal)
604 {
605 if(newVal > -1)
606 mySystem.poke(COLUP1, newVal);
607
608 return myTIA.registerValue(COLUP1);
609 }
610
611 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
coluPF(int newVal)612 uInt8 TIADebug::coluPF(int newVal)
613 {
614 if(newVal > -1)
615 mySystem.poke(COLUPF, newVal);
616
617 return myTIA.registerValue(COLUPF);
618 }
619
620 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
coluBK(int newVal)621 uInt8 TIADebug::coluBK(int newVal)
622 {
623 if(newVal > -1)
624 mySystem.poke(COLUBK, newVal);
625
626 return myTIA.registerValue(COLUBK);
627 }
628
629 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nusiz0(int newVal)630 uInt8 TIADebug::nusiz0(int newVal)
631 {
632 if(newVal > -1)
633 mySystem.poke(NUSIZ0, newVal);
634
635 return myTIA.registerValue(NUSIZ0);
636 }
637
638 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nusiz1(int newVal)639 uInt8 TIADebug::nusiz1(int newVal)
640 {
641 if(newVal > -1)
642 mySystem.poke(NUSIZ1, newVal);
643
644 return myTIA.registerValue(NUSIZ1);
645 }
646
647 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nusizP0(int newVal)648 uInt8 TIADebug::nusizP0(int newVal)
649 {
650 if(newVal > -1)
651 {
652 uInt8 tmp = myTIA.registerValue(NUSIZ0) & ~0x07;
653 tmp |= (newVal & 0x07);
654 mySystem.poke(NUSIZ0, tmp);
655 }
656
657 return myTIA.registerValue(NUSIZ0) & 0x07;
658 }
659
660 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nusizP1(int newVal)661 uInt8 TIADebug::nusizP1(int newVal)
662 {
663 if(newVal > -1)
664 {
665 uInt8 tmp = myTIA.registerValue(NUSIZ1) & ~0x07;
666 tmp |= newVal & 0x07;
667 mySystem.poke(NUSIZ1, tmp);
668 }
669
670 return myTIA.registerValue(NUSIZ1) & 0x07;
671 }
672
673 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nusizM0(int newVal)674 uInt8 TIADebug::nusizM0(int newVal)
675 {
676 if(newVal > -1)
677 {
678 uInt8 tmp = myTIA.registerValue(NUSIZ0) & ~0x30;
679 tmp |= (newVal & 0x04) << 4;
680 mySystem.poke(NUSIZ0, tmp);
681 }
682
683 return (myTIA.registerValue(NUSIZ0) & 0x30) >> 4;
684 }
685
686 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nusizM1(int newVal)687 uInt8 TIADebug::nusizM1(int newVal)
688 {
689 if(newVal > -1)
690 {
691 uInt8 tmp = myTIA.registerValue(NUSIZ1) & ~0x30;
692 tmp |= (newVal & 0x04) << 4;
693 mySystem.poke(NUSIZ1, tmp);
694 }
695
696 return (myTIA.registerValue(NUSIZ1) & 0x30) >> 4;
697 }
698
699 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
grP0(int newVal)700 uInt8 TIADebug::grP0(int newVal)
701 {
702 if(newVal > -1)
703 mySystem.poke(GRP0, newVal);
704
705 return myTIA.registerValue(GRP0);
706 }
707
708 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
grP1(int newVal)709 uInt8 TIADebug::grP1(int newVal)
710 {
711 if(newVal > -1)
712 mySystem.poke(GRP1, newVal);
713
714 return myTIA.registerValue(GRP1);
715 }
716
717 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
posP0(int newVal)718 uInt8 TIADebug::posP0(int newVal)
719 {
720 if(newVal > -1)
721 myTIA.myPlayer0.setPosition(newVal);
722
723 return myTIA.myPlayer0.getPosition();
724 }
725
726 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
posP1(int newVal)727 uInt8 TIADebug::posP1(int newVal)
728 {
729 if(newVal > -1)
730 myTIA.myPlayer1.setPosition(newVal);
731
732 return myTIA.myPlayer1.getPosition();
733 }
734
735 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
posM0(int newVal)736 uInt8 TIADebug::posM0(int newVal)
737 {
738 if(newVal > -1)
739 myTIA.myMissile0.setPosition(newVal);
740
741 return myTIA.myMissile0.getPosition();
742 }
743
744 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
posM1(int newVal)745 uInt8 TIADebug::posM1(int newVal)
746 {
747 if(newVal > -1)
748 myTIA.myMissile1.setPosition(newVal);
749
750 return myTIA.myMissile1.getPosition();
751 }
752
753 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
posBL(int newVal)754 uInt8 TIADebug::posBL(int newVal)
755 {
756 if(newVal > -1)
757 myTIA.myBall.setPosition(newVal);
758
759 return myTIA.myBall.getPosition();
760 }
761
762 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ctrlPF(int newVal)763 uInt8 TIADebug::ctrlPF(int newVal)
764 {
765 if(newVal > -1)
766 mySystem.poke(CTRLPF, newVal);
767
768 return myTIA.registerValue(CTRLPF);
769 }
770
771 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sizeBL(int newVal)772 uInt8 TIADebug::sizeBL(int newVal)
773 {
774 if(newVal > -1)
775 {
776 uInt8 tmp = myTIA.registerValue(CTRLPF) & ~0x30;
777 tmp |= (newVal & 0x04) << 4;
778 mySystem.poke(CTRLPF, tmp);
779 }
780
781 return (myTIA.registerValue(CTRLPF) & 0x30) >> 4;
782 }
783
784 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hmP0(int newVal)785 uInt8 TIADebug::hmP0(int newVal)
786 {
787 if(newVal > -1)
788 mySystem.poke(HMP0, newVal << 4);
789
790 return myTIA.registerValue(HMP0) >> 4;
791 }
792
793 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hmP1(int newVal)794 uInt8 TIADebug::hmP1(int newVal)
795 {
796 if(newVal > -1)
797 mySystem.poke(HMP1, newVal << 4);
798
799 return myTIA.registerValue(HMP1) >> 4;
800 }
801
802 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hmM0(int newVal)803 uInt8 TIADebug::hmM0(int newVal)
804 {
805 if(newVal > -1)
806 mySystem.poke(HMM0, newVal << 4);
807
808 return myTIA.registerValue(HMM0) >> 4;
809 }
810
811 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hmM1(int newVal)812 uInt8 TIADebug::hmM1(int newVal)
813 {
814 if(newVal > -1)
815 mySystem.poke(HMM1, newVal << 4);
816
817 return myTIA.registerValue(HMM1) >> 4;
818 }
819
820 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hmBL(int newVal)821 uInt8 TIADebug::hmBL(int newVal)
822 {
823 if(newVal > -1)
824 mySystem.poke(HMBL, newVal << 4);
825
826 return myTIA.registerValue(HMBL) >> 4;
827 }
828
829 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setGRP0Old(uInt8 b)830 void TIADebug::setGRP0Old(uInt8 b)
831 {
832 myTIA.myPlayer0.setGRPOld(b);
833 }
834
835 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setGRP1Old(uInt8 b)836 void TIADebug::setGRP1Old(uInt8 b)
837 {
838 myTIA.myPlayer1.setGRPOld(b);
839 }
840
841 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setENABLOld(bool b)842 void TIADebug::setENABLOld(bool b)
843 {
844 myTIA.myBall.setENABLOld(b);
845 }
846
847 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeWsync()848 void TIADebug::strobeWsync()
849 {
850 mySystem.poke(WSYNC, 0);
851 }
852
853 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeRsync()854 void TIADebug::strobeRsync()
855 {
856 mySystem.poke(RSYNC, 0);
857 }
858
859 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeResP0()860 void TIADebug::strobeResP0()
861 {
862 mySystem.poke(RESP0, 0);
863 }
864
865 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeResP1()866 void TIADebug::strobeResP1()
867 {
868 mySystem.poke(RESP1, 0);
869 }
870
871 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeResM0()872 void TIADebug::strobeResM0()
873 {
874 mySystem.poke(RESM0, 0);
875 }
876
877 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeResM1()878 void TIADebug::strobeResM1()
879 {
880 mySystem.poke(RESM1, 0);
881 }
882
883 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeResBL()884 void TIADebug::strobeResBL()
885 {
886 mySystem.poke(RESBL, 0);
887 }
888
889 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeHmove()890 void TIADebug::strobeHmove()
891 {
892 mySystem.poke(HMOVE, 0);
893 }
894
895 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeHmclr()896 void TIADebug::strobeHmclr()
897 {
898 mySystem.poke(HMCLR, 0);
899 }
900
901 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
strobeCxclr()902 void TIADebug::strobeCxclr()
903 {
904 mySystem.poke(CXCLR, 0);
905 }
906
907 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
frameCount() const908 int TIADebug::frameCount() const
909 {
910 return myTIA.frameCount();
911 }
912
913 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
frameCycles() const914 int TIADebug::frameCycles() const
915 {
916 return myTIA.frameCycles();
917 }
918
919 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
frameWsyncCycles() const920 int TIADebug::frameWsyncCycles() const
921 {
922 return myTIA.frameWSyncCycles();
923 }
924
925 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclesLo() const926 int TIADebug::cyclesLo() const
927 {
928 return int(myTIA.cycles());
929 }
930
931 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclesHi() const932 int TIADebug::cyclesHi() const
933 {
934 return int(myTIA.cycles() >> 32);
935 }
936
937 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scanlines() const938 int TIADebug::scanlines() const
939 {
940 return myTIA.scanlines();
941 }
942
943 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scanlinesLastFrame() const944 int TIADebug::scanlinesLastFrame() const
945 {
946 return myTIA.scanlinesLastFrame();
947 }
948
949 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
clocksThisLine() const950 int TIADebug::clocksThisLine() const
951 {
952 return myTIA.clocksThisLine();
953 }
954
955 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclesThisLine() const956 int TIADebug::cyclesThisLine() const
957 {
958 return myTIA.clocksThisLine()/3;
959 }
960
961 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vsync(int newVal)962 bool TIADebug::vsync(int newVal)
963 {
964 if (newVal > -1)
965 mySystem.poke(VSYNC, newVal);
966
967 return myTIA.registerValue(VSYNC) & 0x02;
968 }
969
970 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vsync() const971 bool TIADebug::vsync() const
972 {
973 return myTIA.registerValue(VSYNC) & 0x02;
974 }
975
976 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vblank(int newVal)977 bool TIADebug::vblank(int newVal)
978 {
979 if (newVal > -1)
980 mySystem.poke(VBLANK, newVal);
981
982 return myTIA.registerValue(VBLANK) & 0x02;
983 }
984
985 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vblank() const986 bool TIADebug::vblank() const
987 {
988 return myTIA.registerValue(VBLANK) & 0x02;
989 }
990
991 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
delayQueueIterator() const992 shared_ptr<DelayQueueIterator> TIADebug::delayQueueIterator() const
993 {
994 return myTIA.delayQueueIterator();
995 }
996
997 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
colorSwatch(uInt8 c) const998 string TIADebug::colorSwatch(uInt8 c) const
999 {
1000 string ret;
1001
1002 ret += char((c >> 1) | 0x80);
1003 ret += "\177 ";
1004 ret += "\177\001 ";
1005
1006 return ret;
1007 }
1008
1009 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1010 // FIXME - how does this work; is this even needed ??
1011 // convert to stringstream, get rid of snprintf
audFreq(uInt8 div)1012 string TIADebug::audFreq(uInt8 div)
1013 {
1014 string ret;
1015 std::array<char, 10> buf;
1016
1017 double hz = 31400.0;
1018 if(div) hz /= div;
1019 std::snprintf(buf.data(), 9, "%5.1f", hz);
1020 ret += buf.data();
1021 ret += "Hz";
1022
1023 return ret;
1024 }
1025
1026 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
stringOnly(string value,bool changed)1027 string TIADebug::stringOnly(string value, bool changed)
1028 {
1029 ostringstream buf;
1030
1031 buf << value;
1032
1033 if(changed)
1034 return char(kDbgColorRed & 0xff) + buf.str() + char(kTextColor & 0xff);
1035 else
1036 return buf.str();
1037 }
1038
1039 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
decWithLabel(string label,uInt16 value,bool changed,uInt16 width)1040 string TIADebug::decWithLabel(string label, uInt16 value, bool changed, uInt16 width)
1041 {
1042 ostringstream buf;
1043
1044 buf << label;
1045 if(label != EmptyString)
1046 buf << "=";
1047 buf << "#" << std::setw(width) << std::dec << std::left << value;
1048
1049 if(changed)
1050 return char(kDbgColorRed & 0xff) + buf.str() + char(kTextColor & 0xff);
1051 else
1052 return buf.str();
1053 }
1054
1055 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hexWithLabel(string label,uInt16 value,bool changed,uInt16 width)1056 string TIADebug::hexWithLabel(string label, uInt16 value, bool changed, uInt16 width)
1057 {
1058 ostringstream buf;
1059
1060 buf << label;
1061 if(label != EmptyString)
1062 buf << "=";
1063 buf << "$" << (width == 1 ? Common::Base::HEX1 : Common::Base::HEX2) << value;
1064
1065 if(changed)
1066 return char(kDbgColorRed & 0xff) + buf.str() + char(kTextColor & 0xff);
1067 else
1068 return buf.str();
1069 }
1070
1071 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
binWithLabel(string label,uInt16 value,bool changed)1072 string TIADebug::binWithLabel(string label, uInt16 value, bool changed)
1073 {
1074 ostringstream buf;
1075
1076 buf << label;
1077 if(label != EmptyString)
1078 buf << "=";
1079 buf << "%" << Common::Base::toString(value, Common::Base::Fmt::_2_8);
1080
1081 if(changed)
1082 return char(kDbgColorRed & 0xff) + buf.str() + char(kTextColor & 0xff);
1083 else
1084 return buf.str();
1085 }
1086
1087 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
boolWithLabel(string label,bool value,bool changed)1088 string TIADebug::boolWithLabel(string label, bool value, bool changed)
1089 {
1090 ostringstream buf;
1091
1092 if(value)
1093 buf << "\177" << BSPF::toUpperCase(label) << "\177";
1094 //return "+" + BSPF::toUpperCase(label);
1095 else
1096 buf << label;
1097 //return "-" + BSPF::toLowerCase(label);
1098
1099 if(changed)
1100 return char(kDbgColorRed & 0xff) + buf.str() + char(kTextColor & 0xff);
1101 else
1102 return buf.str();
1103 }
1104
1105 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
debugColors() const1106 string TIADebug::debugColors() const
1107 {
1108 ostringstream buf;
1109
1110 int timing = myConsole.timing() == ConsoleTiming::ntsc ? 0
1111 : myConsole.timing() == ConsoleTiming::pal ? 1 : 2;
1112
1113 buf << " " << myTIA.myFixedColorNames[TIA::P0] << " " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::P0])
1114 << " Player 0\n"
1115 << " " << myTIA.myFixedColorNames[TIA::M0] << " " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::M0])
1116 << " Missile 0\n"
1117 << " " << myTIA.myFixedColorNames[TIA::P1] << " " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::P1])
1118 << " Player 1\n"
1119 << " " << myTIA.myFixedColorNames[TIA::M1] << " " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::M1])
1120 << " Missile 1\n"
1121 << " " << myTIA.myFixedColorNames[TIA::PF] << " " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::PF])
1122 << " Playfield\n"
1123 << " " << myTIA.myFixedColorNames[TIA::BL] << " " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::BL])
1124 << " Ball\n"
1125 << " Grey " << colorSwatch(myTIA.myFixedColorPalette[timing][TIA::BK])
1126 << " Background\n"
1127 << " White " << colorSwatch(TIA::FixedColor::HBLANK_WHITE)
1128 << " HMOVE\n";
1129
1130 return buf.str();
1131 }
1132
1133 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
palette() const1134 string TIADebug::palette() const
1135 {
1136 ostringstream buf;
1137
1138 buf << " 0 2 4 6 8 A C E\n";
1139 uInt8 c = 0;
1140 for(uInt16 row = 0; row < 16; ++row)
1141 {
1142 buf << " " << Common::Base::HEX1 << row << " ";
1143 for(uInt16 col = 0; col < 8; ++col, c += 2)
1144 buf << colorSwatch(c);
1145
1146 buf << endl;
1147 }
1148 return buf.str();
1149 }
1150
1151 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
toString()1152 string TIADebug::toString()
1153 {
1154 ostringstream buf;
1155
1156 // TODO: strobes? WSYNC RSYNC RESP0/1 RESM0/1 RESBL HMOVE HMCLR CXCLR
1157
1158 RiotDebug& riot = myDebugger.riotDebug();
1159 const RiotState& riotState = static_cast<const RiotState&>(riot.getState());
1160 const RiotState& oldRiotState = static_cast<const RiotState&>(riot.getOldState());
1161
1162 const TiaState& state = static_cast<const TiaState&>(getState());
1163 const TiaState& oldState = static_cast<const TiaState&>(getOldState());
1164
1165 // build up output, then return it.
1166 buf << std::setfill(' ') << std::left
1167 << decWithLabel("scanline", myTIA.scanlines(),
1168 static_cast<int>(myTIA.scanlines()) != oldState.info[4]) << " "
1169 << boolWithLabel("vsync", vsync(),
1170 state.vsb[0] != oldState.vsb[0]) << " "
1171 << boolWithLabel("vblank", vblank(),
1172 state.vsb[1] != oldState.vsb[1])
1173 << endl
1174 << "Collisions: "
1175 << boolWithLabel("p0_pf", collP0_PF(), state.cx[0] != oldState.cx[0]) << " "
1176 << boolWithLabel("p0_bl", collP0_BL(), state.cx[1] != oldState.cx[1]) << " "
1177 << boolWithLabel("m1_p0", collM1_P0(), state.cx[2] != oldState.cx[2]) << " "
1178 << boolWithLabel("m0_p0", collM0_P0(), state.cx[3] != oldState.cx[3]) << " "
1179 << boolWithLabel("p0_p1", collP0_P1(), state.cx[4] != oldState.cx[4]) << " "
1180 << boolWithLabel("p1_pf", collP1_PF(), state.cx[5] != oldState.cx[5]) << " "
1181 << boolWithLabel("p1_bl", collP1_BL(), state.cx[6] != oldState.cx[6]) << " "
1182 << boolWithLabel("m1_p1", collM1_P1(), state.cx[7] != oldState.cx[7])
1183 << endl << " "
1184 << boolWithLabel("m0_p1", collM0_P1(), state.cx[8] != oldState.cx[8]) << " "
1185 << boolWithLabel("m0_pf", collM0_PF(), state.cx[9] != oldState.cx[9]) << " "
1186 << boolWithLabel("m0_bl", collM0_BL(), state.cx[10] != oldState.cx[10]) << " "
1187 << boolWithLabel("m0_m1", collM0_M1(), state.cx[11] != oldState.cx[11]) << " "
1188 << boolWithLabel("m1_pf", collM1_PF(), state.cx[12] != oldState.cx[12]) << " "
1189 << boolWithLabel("m1_bl", collM1_BL(), state.cx[13] != oldState.cx[13]) << " "
1190 << boolWithLabel("bl_pf", collBL_PF(), state.cx[14] != oldState.cx[14])
1191 << endl
1192 << "COLUxx: "
1193 << hexWithLabel("P0", state.coluRegs[TiaState::P0],
1194 state.coluRegs[TiaState::P0] != oldState.coluRegs[TiaState::P0]) << "/"
1195 << colorSwatch(state.coluRegs[TiaState::P0])
1196 << hexWithLabel("P1", state.coluRegs[TiaState::P1],
1197 state.coluRegs[TiaState::P1] != oldState.coluRegs[TiaState::P1]) << "/"
1198 << colorSwatch(state.coluRegs[TiaState::P1])
1199 << hexWithLabel("PF", state.coluRegs[2],
1200 state.coluRegs[2] != oldState.coluRegs[2]) << "/"
1201 << colorSwatch(state.coluRegs[2])
1202 << hexWithLabel("BK", state.coluRegs[3],
1203 state.coluRegs[3] != oldState.coluRegs[3]) << "/"
1204 << colorSwatch(state.coluRegs[3])
1205 << endl
1206 << "P0: "
1207 << binWithLabel("GR", state.gr[TiaState::P0],
1208 state.gr[TiaState::P0] != oldState.gr[TiaState::P0]) << " "
1209 << decWithLabel("pos", state.pos[TiaState::P0],
1210 state.pos[TiaState::P0] != oldState.pos[TiaState::P0]) << " "
1211 << hexWithLabel("HM", state.hm[TiaState::P0],
1212 state.hm[TiaState::P0] != oldState.hm[TiaState::P0], 1) << " "
1213 << stringOnly(nusizP0String(),
1214 state.size[TiaState::P0] != oldState.size[TiaState::P0]) << " "
1215 << boolWithLabel("refl", refP0(),
1216 state.ref[TiaState::P0] != oldState.ref[TiaState::P0]) << " "
1217 << boolWithLabel("delay", vdelP0(),
1218 state.vdel[TiaState::P0] != oldState.vdel[TiaState::P0])
1219 << endl
1220 << "P1: "
1221 << binWithLabel("GR", state.gr[TiaState::P1],
1222 state.gr[TiaState::P1] != oldState.gr[TiaState::P1]) << " "
1223 << decWithLabel("pos", state.pos[TiaState::P1],
1224 state.pos[TiaState::P1] != oldState.pos[TiaState::P1]) << " "
1225 << hexWithLabel("HM", state.hm[TiaState::P1],
1226 state.hm[TiaState::P1] != oldState.hm[TiaState::P1], 1) << " "
1227 << stringOnly(nusizP1String(),
1228 state.size[TiaState::P1] != oldState.size[TiaState::P1]) << " "
1229 << boolWithLabel("refl", refP1(),
1230 state.ref[TiaState::P1] != oldState.ref[TiaState::P1]) << " "
1231 << boolWithLabel("delay", vdelP1(),
1232 state.vdel[TiaState::P1] != oldState.vdel[TiaState::P1])
1233 << endl
1234 << "M0: "
1235 << stringOnly(enaM0() ? "ENABLED " : "disabled",
1236 state.gr[6] != oldState.gr[6]) << " "
1237 << decWithLabel("pos", state.pos[TiaState::M0],
1238 state.pos[TiaState::M0] != oldState.pos[TiaState::M0]) << " "
1239 << hexWithLabel("HM", state.hm[TiaState::M0],
1240 state.hm[TiaState::M0] != oldState.hm[TiaState::M0], 1) << " "
1241 << decWithLabel("size", state.size[TiaState::M0],
1242 state.size[TiaState::M0] != oldState.size[TiaState::M0], 1) << " "
1243 << boolWithLabel("reset", resMP0(), state.resm[TiaState::P0] != oldState.resm[TiaState::P0])
1244 << endl
1245 << "M1: "
1246 << stringOnly(enaM1() ? "ENABLED " : "disabled",
1247 state.gr[7] != oldState.gr[7]) << " "
1248 << decWithLabel("pos", state.pos[TiaState::M1],
1249 state.pos[TiaState::M1] != oldState.pos[TiaState::M1]) << " "
1250 << hexWithLabel("HM", state.hm[TiaState::M1],
1251 state.hm[TiaState::M1] != oldState.hm[TiaState::M1], 1) << " "
1252 << decWithLabel("size", state.size[TiaState::M1],
1253 state.size[TiaState::M1] != oldState.size[TiaState::M1], 1) << " "
1254 << boolWithLabel("reset", resMP0(), state.resm[TiaState::P1] != oldState.resm[TiaState::P1])
1255 << endl
1256 << "BL: "
1257 << stringOnly(enaBL() ? "ENABLED " : "disabled",
1258 state.gr[4] != oldState.gr[4]) << " "
1259 << decWithLabel("pos", state.pos[TiaState::BL],
1260 state.pos[TiaState::BL] != oldState.pos[TiaState::BL]) << " "
1261 << hexWithLabel("HM", state.hm[TiaState::BL],
1262 state.hm[TiaState::BL] != oldState.hm[TiaState::BL], 1) << " "
1263 << decWithLabel("size", state.size[TiaState::BL],
1264 state.size[TiaState::BL] != oldState.size[TiaState::BL], 1) << " "
1265 << boolWithLabel("delay", vdelBL(), state.vdel[2] != oldState.vdel[2])
1266 << endl
1267 << "PF0: "
1268 << binWithLabel("", state.pf[0],
1269 state.pf[0] != oldState.pf[0]) << "/"
1270 << hexWithLabel("", state.pf[0],
1271 state.pf[0] != oldState.pf[0]) << " "
1272 << "PF1: "
1273 << binWithLabel("", state.pf[1],
1274 state.pf[1] != oldState.pf[1]) << "/"
1275 << hexWithLabel("", state.pf[1],
1276 state.pf[1] != oldState.pf[1]) << " "
1277 << "PF2: "
1278 << binWithLabel("", state.pf[2],
1279 state.pf[2] != oldState.pf[2]) << "/"
1280 << hexWithLabel("", state.pf[2],
1281 state.pf[2] != oldState.pf[2]) << " "
1282 << endl << " "
1283 << boolWithLabel("reflect", refPF(), state.pf[3] != oldState.pf[3]) << " "
1284 << boolWithLabel("score", scorePF(), state.pf[4] != oldState.pf[4]) << " "
1285 << boolWithLabel("priority", priorityPF(), state.pf[5] != oldState.pf[5])
1286 << endl
1287 << boolWithLabel("inpt0", myTIA.peek(0x08) & 0x80,
1288 (riotState.INPT0 & 0x80) != (oldRiotState.INPT0 & 0x80)) << " "
1289 << boolWithLabel("inpt1", myTIA.peek(0x09) & 0x80,
1290 (riotState.INPT1 & 0x80) != (oldRiotState.INPT1 & 0x80)) << " "
1291 << boolWithLabel("inpt2", myTIA.peek(0x0a) & 0x80,
1292 (riotState.INPT2 & 0x80) != (oldRiotState.INPT2 & 0x80)) << " "
1293 << boolWithLabel("inpt3", myTIA.peek(0x0b) & 0x80,
1294 (riotState.INPT3 & 0x80) != (oldRiotState.INPT3 & 0x80)) << " "
1295 << boolWithLabel("inpt4", myTIA.peek(0x0c) & 0x80,
1296 (riotState.INPT4 & 0x80) != (oldRiotState.INPT4 & 0x80)) << " "
1297 << boolWithLabel("inpt5", myTIA.peek(0x0d) & 0x80,
1298 (riotState.INPT5 & 0x80) != (oldRiotState.INPT5 & 0x80)) << " "
1299 << boolWithLabel("dump_gnd_0123", myTIA.myAnalogReadouts[0].vblankDumped(),
1300 riotState.INPTDump != oldRiotState.INPTDump)
1301 << endl
1302 << "AUDF0: "
1303 << hexWithLabel("", int(audF0()),
1304 state.aud[0] != oldState.aud[0]) << "/"
1305 << std::setw(11) << std::right << stringOnly(audFreq(audF0()),
1306 state.aud[0] != oldState.aud[0]) << " "
1307 << "AUDC0: "
1308 << hexWithLabel("", int(audC0()),
1309 state.aud[2] != oldState.aud[2], 1) << " "
1310 << "AUDV0: "
1311 << hexWithLabel("", int(audV0()),
1312 state.aud[4] != oldState.aud[4], 1)
1313 << endl
1314 << "AUDF1: "
1315 << hexWithLabel("", int(audF1()),
1316 state.aud[1] != oldState.aud[1]) << "/"
1317 << std::setw(11) << std::right << stringOnly(audFreq(audF1()),
1318 state.aud[1] != oldState.aud[1]) << " "
1319 << "AUDC1: "
1320 << hexWithLabel("", int(audC1()),
1321 state.aud[3] != oldState.aud[3], 1) << " "
1322 << "AUDV1: "
1323 << hexWithLabel("", int(audV1()),
1324 state.aud[5] != oldState.aud[5], 1);
1325 // note: last line should not contain \n, caller will add.
1326 return buf.str();
1327 }
1328
1329 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1330 const std::array<string, 8> TIADebug::nusizStrings = {
1331 "1 copy ",
1332 "2 copies - close (8)",
1333 "2 copies - med (24) ",
1334 "3 copies - close (8)",
1335 "2 copies - wide (56)",
1336 "2x (16) sized player",
1337 "3 copies - med (24) ",
1338 "4x (32) sized player"
1339 };
1340