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-2019 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#ifndef TIA_TIA
19#define TIA_TIA
20
21#include <functional>
22
23#include "bspf.hxx"
24#include "ConsoleIO.hxx"
25#include "ConsoleTiming.hxx"
26#include "Settings.hxx"
27#include "Device.hxx"
28#include "Serializer.hxx"
29#include "TIAConstants.hxx"
30#include "DelayQueue.hxx"
31#include "DelayQueueIterator.hxx"
32#include "frame-manager/AbstractFrameManager.hxx"
33#include "FrameLayout.hxx"
34#include "Audio.hxx"
35#include "Background.hxx"
36#include "Playfield.hxx"
37#include "Missile.hxx"
38#include "Player.hxx"
39#include "Ball.hxx"
40#include "LatchedInput.hxx"
41#include "PaddleReader.hxx"
42#include "DelayQueueIterator.hxx"
43#include "Control.hxx"
44#include "System.hxx"
45
46class AudioQueue;
47class DispatchResult;
48
49/**
50 This class is a device that emulates the Television Interface Adaptor
51 found in the Atari 2600 and 7800 consoles. The Television Interface
52 Adaptor is an integrated circuit designed to interface between an
53 eight bit microprocessor and a television video modulator. It converts
54 eight bit parallel data into serial outputs for the color, luminosity,
55 and composite sync required by a video modulator.
56
57 This class outputs the serial data into a frame buffer which can then
58 be displayed on screen.
59
60 @author Christian Speckner (DirtyHairy) and Stephen Anthony
61*/
62class TIA : public Device
63{
64 public:
65 /**
66 * These dummy register addresses are used to represent the delayed
67 * old / new register swap on writing GRPx and ENABL in the DelayQueue (see below).
68 */
69 enum DummyRegisters: uInt8 {
70 shuffleP0 = 0xF0,
71 shuffleP1 = 0xF1,
72 shuffleBL = 0xF2
73 };
74
75 /**
76 * Possible palette entries for objects in "fixed debug color mode".
77 */
78 enum FixedColor {
79 NTSC_RED = 0x30,
80 NTSC_ORANGE = 0x38,
81 NTSC_YELLOW = 0x1c,
82 NTSC_GREEN = 0xc4,
83 NTSC_BLUE = 0x9c,
84 NTSC_PURPLE = 0x66,
85 NTSC_GREY = 0x04,
86
87 PAL_RED = 0x62,
88 PAL_ORANGE = 0x4a,
89 PAL_YELLOW = 0x2e,
90 PAL_GREEN = 0x34,
91 PAL_BLUE = 0xbc,
92 PAL_PURPLE = 0xa6,
93 PAL_GREY = 0x06,
94
95 SECAM_RED = 0x04,
96 SECAM_ORANGE = 0x06, // purple
97 SECAM_YELLOW = 0x0c,
98 SECAM_GREEN = 0x08,
99 SECAM_BLUE = 0x02,
100 SECAM_PURPLE = 0x0a, // cyan
101 SECAM_GREY = 0x00,
102
103 HBLANK_WHITE = 0x0e
104 };
105
106 using ConsoleTimingProvider = std::function<ConsoleTiming()>;
107
108 public:
109 friend class TIADebug;
110 friend class RiotDebug;
111
112 /**
113 Create a new TIA for the specified console
114
115 @param console The console the TIA is associated with
116 @param settings The settings object for this TIA device
117 */
118 TIA(ConsoleIO& console, ConsoleTimingProvider timingProvider, Settings& settings);
119
120 virtual ~TIA() = default;
121
122 public:
123 /**
124 Configure the frame manager.
125 */
126 void setFrameManager(AbstractFrameManager *frameManager);
127
128 /**
129 Set the audio queue. This needs to be dynamic as the queue is created after
130 the timing has been determined.
131 */
132 void setAudioQueue(shared_ptr<AudioQueue> audioQueue);
133
134 /**
135 Clear the configured frame manager and deteach the lifecycle callbacks.
136 */
137 void clearFrameManager();
138
139 /**
140 Reset device to its power-on state.
141 */
142 void reset() override;
143
144 /**
145 Install TIA in the specified system. Invoked by the system
146 when the TIA is attached to it.
147
148 @param system The system the device should install itself in
149 */
150 void install(System& system) override;
151
152 /**
153 Get the byte at the specified address.
154
155 @return The byte at the specified address
156 */
157 uInt8 peek(uInt16 address) override;
158
159 /**
160 Change the byte at the specified address to the given value.
161
162 @param address The address where the value should be stored
163 @param value The value to be stored at the address
164
165 @return True if the poke changed the device address space, else false
166 */
167 bool poke(uInt16 address, uInt8 value) override;
168
169 /**
170 Install TIA in the specified system and device. Invoked by
171 the system when the TIA is attached to it. All devices
172 which invoke this method take responsibility for chaining
173 requests back to *this* device.
174
175 @param system The system the device should install itself in
176 @param device The device responsible for this address space
177 */
178 void installDelegate(System& system, Device& device);
179
180 /**
181 Bind to controllers.
182 */
183 void bindToControllers();
184
185 /**
186 The following are very similar to save() and load(), except they
187 do a 'deeper' save of the display data itself.
188
189 Normally, the internal framebuffer doesn't need to be saved to
190 a state file, since the file already contains all the information
191 needed to re-create it, starting from scanline 0. In effect, when a
192 state is loaded, the framebuffer is empty, and the next call to
193 update() generates valid framebuffer data.
194
195 However, state files saved from the debugger need more information,
196 such as the exact state of the internal framebuffer itself *before*
197 we call update(), including if the display was in partial frame mode.
198
199 Essentially, a normal state save has 'frame resolution', whereas
200 the debugger state save has 'cycle resolution', and hence needs
201 more information. The methods below save/load this extra info,
202 and eliminate having to save approx. 50K to normal state files.
203 */
204 bool saveDisplay(Serializer& out) const;
205 bool loadDisplay(Serializer& in);
206
207 /**
208 This method should be called at an interval corresponding to the
209 desired frame rate to update the TIA. Invoking this method will update
210 the graphics buffer and generate the corresponding audio samples.
211 */
212 void update(DispatchResult& result, uInt64 maxCycles = 50000);
213
214 void update(uInt64 maxCycles = 50000);
215
216 /**
217 Did we generate a new frame?
218 */
219 bool newFramePending() { return myFramesSinceLastRender > 0; }
220
221 /**
222 * Clear any pending frames.
223 */
224 void clearPendingFrame() { myFramesSinceLastRender = 0; }
225
226 /**
227 The number of frames since we did last render to the front buffer.
228 */
229 uInt32 framesSinceLastRender() { return myFramesSinceLastRender; }
230
231 /**
232 Render the pending frame to the framebuffer and clear the flag.
233 */
234 void renderToFrameBuffer();
235
236 /**
237 Return the buffer that holds the currently drawing TIA frame
238 (the TIA output widget needs this).
239 */
240 uInt8* outputBuffer() { return myBackBuffer.data(); }
241
242 /**
243 Returns a pointer to the internal frame buffer.
244 */
245 uInt8* frameBuffer() { return myFramebuffer.data(); }
246
247 /**
248 Answers dimensional info about the framebuffer.
249 */
250 uInt32 width() const { return TIAConstants::H_PIXEL; }
251 uInt32 height() const { return myFrameManager->height(); }
252 uInt32 ystart() const { return myFrameManager->ystart(); }
253
254 /**
255 Changes the current YStart property.
256 */
257 void setYStart(uInt32 ystart) { myFrameManager->setYstart(ystart); }
258
259 void setLayout(FrameLayout layout) { myFrameManager->setLayout(layout); }
260 FrameLayout frameLayout() const { return myFrameManager->layout(); }
261
262 /**
263 Enables/disables color-loss for PAL modes only.
264
265 @param enabled Whether to enable or disable PAL color-loss mode
266 */
267 bool enableColorLoss(bool enabled);
268
269 /**
270 Answers whether color-loss is enabled.
271
272 @return Colour-loss is enabled
273 */
274 bool colorLossEnabled() const { return myColorLossEnabled; }
275
276 /**
277 Answers whether colour-loss is applicable for the current frame.
278
279 @return Colour-loss is active for this frame
280 */
281 bool colorLossActive() const { return myColorLossActive; }
282
283 /**
284 Answers the current color clock we've gotten to on this scanline.
285
286 @return The current color clock
287 */
288 uInt32 clocksThisLine() const { return myHctr - myHctrDelta; }
289
290 /**
291 Answers the total number of scanlines the TIA generated in producing
292 the current frame buffer. For partial frames, this will be the
293 current scanline.
294
295 @return The total number of scanlines generated
296 */
297 uInt32 scanlines() const { return myFrameManager->scanlines(); }
298
299 /**
300 Answers the total number of scanlines the TIA generated in the
301 previous frame.
302
303 @return The total number of scanlines generated in the last frame.
304 */
305 uInt32 scanlinesLastFrame() const { return myFrameManager->scanlinesLastFrame(); }
306
307 /**
308 The same, but for the frame in the frame buffer.
309 */
310 uInt32 frameBufferScanlinesLastFrame() const { return myFrameBufferScanlines; }
311
312 /**
313 Answers the total system cycles from the start of the emulation.
314 */
315 uInt64 cycles() const { return uInt64(mySystem->cycles()); }
316
317 /**
318 Answers the frame count from the start of the emulation.
319 */
320 uInt32 frameCount() const { return myFrameManager->frameCount(); }
321
322 /**
323 Answers the system cycles from the start of the current frame.
324 */
325 uInt32 frameCycles() const {
326 return uInt32(mySystem->cycles() - myCyclesAtFrameStart);
327 }
328
329 /**
330 Answers whether the TIA is currently in being rendered
331 (we're in between the start and end of drawing a frame).
332
333 @return If the frame is in rendering mode
334 */
335 bool isRendering() const { return myFrameManager->isRendering(); }
336
337 /**
338 Answers the current position of the virtual 'electron beam' used
339 when drawing the TIA image in debugger mode.
340
341 @return The x/y coordinates of the scanline electron beam, and whether
342 it is in the visible/viewable area of the screen
343 */
344 bool electronBeamPos(uInt32& x, uInt32& y) const;
345
346 /**
347 Enables/disable/toggle the specified (or all) TIA bit(s). Note that
348 disabling a graphical object also disables its collisions.
349
350 @param mode 1/0 indicates on/off, and values greater than 1 mean
351 flip the bit from its current state
352
353 @return Whether the bit was enabled or disabled
354 */
355 bool toggleBit(TIABit b, uInt8 mode = 2);
356 bool toggleBits();
357
358 /**
359 Enables/disable/toggle the specified (or all) TIA bit collision(s).
360
361 @param mode 1/0 indicates on/off, and values greater than 1 mean
362 flip the collision from its current state
363
364 @return Whether the collision was enabled or disabled
365 */
366 bool toggleCollision(TIABit b, uInt8 mode = 2);
367 bool toggleCollisions();
368
369 /**
370 Enables/disable/toggle/query 'fixed debug colors' mode.
371
372 @param enable Whether to enable fixed debug colors mode
373
374 @return Whether the mode was enabled or disabled
375 */
376 bool enableFixedColors(bool enable);
377 bool toggleFixedColors() { return enableFixedColors(!usingFixedColors()); }
378 bool usingFixedColors() const { return myColorHBlank != 0x00; }
379
380 /**
381 Sets the color of each object in 'fixed debug colors' mode.
382 Note that this doesn't enable/disable fixed colors; it simply
383 updates the palette that is used.
384
385 @param colors Each character in the 6-char string represents the
386 first letter of the color to use for
387 P0/M0/P1/M1/PF/BL, respectively.
388
389 @return True if colors were changed successfully, else false
390 */
391 bool setFixedColorPalette(const string& colors);
392
393 /**
394 Enable/disable/query state of 'undriven/floating TIA pins'.
395
396 @param mode 1/0 indicates on/off, otherwise return the current state
397
398 @return Whether the mode was enabled or disabled
399 */
400 bool driveUnusedPinsRandom(uInt8 mode = 2);
401
402 /**
403 Enables/disable/toggle 'scanline jittering' mode, and set the
404 recovery 'factor'.
405
406 @param mode 1/0 indicates on/off, otherwise flip from
407 its current state
408
409 @return Whether the mode was enabled or disabled
410 */
411 bool toggleJitter(uInt8 mode = 2);
412 void setJitterRecoveryFactor(Int32 factor);
413
414 /**
415 Enables/disables delayed playfield bits values.
416
417 @param delayed Wether to enable delayed playfield delays
418 */
419 void setPFBitsDelay(bool delayed);
420
421 /**
422 Enables/disables delayed playfield colors.
423
424 @param delayed Wether to enable delayed playfield colors
425 */
426 void setPFColorDelay(bool delayed);
427
428 /**
429 Enables/disables delayed player swapping.
430
431 @param delayed Wether to enable delayed player swapping
432 */
433 void setPlSwapDelay(bool delayed);
434
435 /**
436 Enables/disables delayed ball swapping.
437
438 @param delayed Wether to enable delayed ball swapping
439 */
440 void setBlSwapDelay(bool delayed);
441
442 /**
443 Enables/disables inverted HMOVE phase clock for players.
444
445 @param enable Wether to enable inverted HMOVE phase clock for players
446 */
447 void setPlInvertedPhaseClock(bool enable);
448
449 /**
450 Enables/disables inverted HMOVE phase clock for missiles.
451
452 @param enable Wether to enable inverted HMOVE phase clock for missiles
453 */
454 void setMsInvertedPhaseClock(bool enable);
455
456 /**
457 Enables/disables inverted HMOVE phase clock for ball.
458
459 @param enable Wether to enable inverted HMOVE phase clock for ball
460 */
461 void setBlInvertedPhaseClock(bool enable);
462
463 /**
464 This method should be called to update the TIA with a new scanline.
465 */
466 TIA& updateScanline();
467
468 /**
469 This method should be called to update the TIA with a new partial
470 scanline by stepping one CPU instruction.
471 */
472 TIA& updateScanlineByStep();
473
474 /**
475 Retrieve the last value written to a certain register.
476 */
477 uInt8 registerValue(uInt8 reg) const;
478
479 /**
480 Get the current x value.
481 */
482 uInt8 getPosition() const {
483 uInt8 realHctr = myHctr - myHctrDelta;
484
485 return (realHctr < TIAConstants::H_BLANK_CLOCKS) ? 0 : (realHctr - TIAConstants::H_BLANK_CLOCKS);
486 }
487
488 /**
489 Flush the line cache after an externally triggered state change
490 (e.g. a register write).
491 */
492 void flushLineCache();
493
494 /**
495 Schedule a collision update
496 */
497 void scheduleCollisionUpdate();
498
499 /**
500 Create a new delayQueueIterator for the debugger.
501 */
502 shared_ptr<DelayQueueIterator> delayQueueIterator() const;
503
504 /**
505 Save the current state of this device to the given Serializer.
506
507 @param out The Serializer object to use
508 @return False on any errors, else true
509 */
510 bool save(Serializer& out) const override;
511
512 /**
513 Load the current state of this device from the given Serializer.
514
515 @param in The Serializer object to use
516 @return False on any errors, else true
517 */
518 bool load(Serializer& in) override;
519
520 /**
521 * Run and forward TIA emulation to the current system clock.
522 */
523 void updateEmulation();
524
525 private:
526 /**
527 * During each line, the TIA cycles through these two states.
528 */
529 enum class HState {blank, frame};
530
531 /**
532 * The three different modes of the priority encoder. Check TIA::renderPixel
533 * for a precise definition.
534 */
535 enum class Priority {pfp, score, normal};
536
537 /**
538 * Palette and indices for fixed debug colors.
539 */
540 enum FixedObject { P0, M0, P1, M1, PF, BL, BK };
541 FixedColor myFixedColorPalette[3][7];
542 string myFixedColorNames[7];
543
544 private:
545 /**
546 * This callback is invoked by FrameManager when a new frame starts.
547 */
548 void onFrameStart();
549
550 /**
551 * This callback is invoked by FrameManager when the current frame completes.
552 */
553 void onFrameComplete();
554
555 /**
556 * Called when the CPU enters halt state (RDY pulled low). Execution continues
557 * immediatelly afterwards, so we have to adjust the system clock to account
558 * for the cycles the 6502 spent in halt state.
559 */
560 void onHalt();
561
562 /**
563 * Execute colorClocks cycles of TIA simulation.
564 */
565 void cycle(uInt32 colorClocks);
566
567 /**
568 * Advance the movement logic by a single clock.
569 */
570 void tickMovement();
571
572 /**
573 * Advance a single clock during hblank.
574 */
575 void tickHblank();
576
577 /**
578 * Advance a single clock duing the visible part of the scanline.
579 */
580 void tickHframe();
581
582 /**
583 * Update the collision bitfield.
584 */
585 void updateCollision();
586
587 /**
588 * Execute a RSYNC.
589 */
590 void applyRsync();
591
592 /**
593 * Render the current pixel into the framebuffer.
594 */
595 void renderPixel(uInt32 x, uInt32 y);
596
597 /**
598 * Clear the first 8 pixels of a scanline with black if we are in hblank
599 * (called during HMOVE).
600 */
601 void clearHmoveComb();
602
603 /**
604 * Advance a line and update our state accordingly.
605 */
606 void nextLine();
607
608 /**
609 * Clone the last line. Called in nextLine if TIA state was unchanged.
610 */
611 void cloneLastLine();
612
613 /**
614 * Execute a delayed write. Called when the DelayQueue is pumped.
615 */
616 void delayedWrite(uInt8 address, uInt8 value);
617
618 /**
619 * Update all paddle readout circuits to the current controller state.
620 */
621 void updatePaddle(uInt8 idx);
622
623 /**
624 * Get the target counter value during a RESx. This essentially depends on
625 * the position in the current scanline.
626 */
627 uInt8 resxCounter();
628
629 /**
630 * Get the result of the specified collision register.
631 */
632 uInt8 collCXM0P() const;
633 uInt8 collCXM1P() const;
634 uInt8 collCXP0FB() const;
635 uInt8 collCXP1FB() const;
636 uInt8 collCXM0FB() const;
637 uInt8 collCXM1FB() const;
638 uInt8 collCXPPMM() const;
639 uInt8 collCXBLPF() const;
640
641 /**
642 * Toggle the specified collision bits
643 */
644 void toggleCollP0PF();
645 void toggleCollP0BL();
646 void toggleCollP0M1();
647 void toggleCollP0M0();
648 void toggleCollP0P1();
649 void toggleCollP1PF();
650 void toggleCollP1BL();
651 void toggleCollP1M1();
652 void toggleCollP1M0();
653 void toggleCollM0PF();
654 void toggleCollM0BL();
655 void toggleCollM0M1();
656 void toggleCollM1PF();
657 void toggleCollM1BL();
658 void toggleCollBLPF();
659
660 /**
661 * Re-apply developer settings from the settings object.
662 * This should be done each time the device is reset, or after
663 * a state load occurs.
664 */
665 void applyDeveloperSettings();
666
667 #ifdef DEBUGGER_SUPPORT
668 void createAccessBase();
669
670 /**
671 * Query the given address type for the associated disassembly flags.
672 *
673 * @param address The address to query
674 */
675 uInt8 getAccessFlags(uInt16 address) const override;
676 /**
677 * Change the given address to use the given disassembly flags.
678 *
679 * @param address The address to modify
680 * @param flags A bitfield of DisasmType directives for the given address
681 */
682 void setAccessFlags(uInt16 address, uInt8 flags) override;
683 #endif // DEBUGGER_SUPPORT
684
685 private:
686 ConsoleIO& myConsole;
687 ConsoleTimingProvider myTimingProvider;
688 Settings& mySettings;
689
690 /**
691 * The length of the delay queue (maximum number of clocks delay)
692 */
693 static constexpr unsigned delayQueueLength = 16;
694
695 /**
696 * The size of the delay queue (maximum number of writes scheduled in a single slot).
697 */
698 static constexpr unsigned delayQueueSize = 16;
699
700 /**
701 * A list of delayed writes that are queued up for future execution. Delayed
702 * writes can be both actual writes whose effect is delayed by one or more clocks
703 * on real hardware and delayed side effects of certain operations (GRPx!).
704 */
705 DelayQueue<delayQueueLength, delayQueueSize> myDelayQueue;
706
707 /**
708 Variable delay values for TIA writes.
709 */
710 uInt8 myPFBitsDelay;
711 uInt8 myPFColorDelay;
712 uInt8 myPlSwapDelay;
713 uInt8 myBlSwapDelay;
714
715 /**
716 * The frame manager is responsible for detecting frame boundaries and the visible
717 * region of each frame.
718 */
719 AbstractFrameManager* myFrameManager;
720
721 /**
722 * The various TIA objects.
723 */
724 Background myBackground;
725 Playfield myPlayfield;
726 Missile myMissile0;
727 Missile myMissile1;
728 Player myPlayer0;
729 Player myPlayer1;
730 Ball myBall;
731
732 Audio myAudio;
733
734 /**
735 * The paddle readout circuits.
736 */
737 std::array<PaddleReader, 4> myPaddleReaders;
738
739 /**
740 * Circuits for the "latched inputs".
741 */
742 LatchedInput myInput0;
743 LatchedInput myInput1;
744
745 // Pointer to the internal color-index-based frame buffer
746 std::array<uInt8, TIAConstants::H_PIXEL * TIAConstants::frameBufferHeight> myFramebuffer;
747
748 // The frame is rendered to the backbuffer and only copied to the framebuffer
749 // upon completion
750 std::array<uInt8, TIAConstants::H_PIXEL * TIAConstants::frameBufferHeight> myBackBuffer;
751 std::array<uInt8, TIAConstants::H_PIXEL * TIAConstants::frameBufferHeight> myFrontBuffer;
752
753 // We snapshot frame statistics when the back buffer is copied to the front buffer
754 // and when the front buffer is copied to the frame buffer
755 uInt32 myFrontBufferScanlines, myFrameBufferScanlines;
756
757 // Frames since the last time a frame was rendered to the render buffer
758 uInt32 myFramesSinceLastRender;
759
760 /**
761 * Setting this to true injects random values into undefined reads.
762 */
763 bool myTIAPinsDriven;
764
765 /**
766 * The current "line state" --- either hblank or frame.
767 */
768 HState myHstate;
769
770 /**
771 * Master line counter
772 */
773 uInt8 myHctr;
774
775 /**
776 * Delta between master line counter and actual color clock. Nonzero after
777 * RSYNC (before the scanline terminates)
778 */
779 Int32 myHctrDelta;
780
781 /**
782 * Electron beam x at rendering start (used for blanking out any pixels from
783 * the last frame that are not overwritten)
784 */
785 uInt8 myXAtRenderingStart;
786
787 /**
788 * Do we need to update the collision mask this clock?
789 */
790 bool myCollisionUpdateRequired;
791
792 /**
793 * Force schedule a collision update
794 */
795 bool myCollisionUpdateScheduled;
796
797 /**
798 * The collision latches are represented by 15 bits in a bitfield.
799 */
800 uInt32 myCollisionMask;
801
802 /**
803 * The movement clock counts the extra ticks sent to the objects during
804 * movement.
805 */
806 uInt32 myMovementClock;
807
808 /**
809 * Movement mode --- are we sending movement clocks?
810 */
811 bool myMovementInProgress;
812
813 /**
814 * Do we have an extended hblank this line? Get set by strobing HMOVE and
815 * cleared when the line wraps.
816 */
817 bool myExtendedHblank;
818
819 /**
820 * Counts the number of line wraps since the last external TIA state change.
821 * If at least two line breaks have passed, the TIA will suspend simulation
822 * and just reuse the last line instead.
823 */
824 uInt32 myLinesSinceChange;
825
826 /**
827 * The current mode of the priority encoder.
828 */
829 Priority myPriority;
830
831 /**
832 * The index of the last CPU cycle that was included in the simulation.
833 */
834 uInt64 myLastCycle;
835
836 /**
837 * Keeps track of a possible fractional number of clocks that still need
838 * to be simulated.
839 */
840 uInt8 mySubClock;
841
842 /**
843 * Bitmasks that track which sprites / collisions are enabled / disabled.
844 */
845 uInt8 mySpriteEnabledBits;
846 uInt8 myCollisionsEnabledBits;
847
848 /**
849 * The color used to highlight HMOVE blanks (if enabled).
850 */
851 uInt8 myColorHBlank;
852
853 /**
854 * The total number of color clocks since emulation started.
855 */
856 uInt64 myTimestamp;
857
858 /**
859 * The "shadow registers" track the last written register value for the
860 * debugger.
861 */
862 std::array<uInt8, 64> myShadowRegisters;
863
864 /**
865 * Indicates if color loss should be enabled or disabled. Color loss
866 * occurs on PAL-like systems when the previous frame contains an odd
867 * number of scanlines.
868 */
869 bool myColorLossEnabled;
870 bool myColorLossActive;
871
872 /**
873 * System cycles at the end of the previous frame / beginning of next frame.
874 */
875 uInt64 myCyclesAtFrameStart;
876
877 /**
878 * The frame manager can change during our lifetime, so we buffer those two.
879 */
880 bool myEnableJitter;
881 uInt8 myJitterFactor;
882
883 static constexpr uInt16
884 TIA_SIZE = 0x40, TIA_MASK = TIA_SIZE - 1, TIA_READ_MASK = 0x0f, TIA_BIT = 0x080, TIA_DELAY = 2;
885
886 #ifdef DEBUGGER_SUPPORT
887 // The arrays containing information about every byte of TIA
888 // indicating whether and how (RW) it is used.
889 std::array<uInt8, TIA_SIZE> myAccessBase;
890
891 // The array used to skip the first two TIA access trackings
892 std::array<uInt8, TIA_SIZE> myAccessDelay;
893 #endif // DEBUGGER_SUPPORT
894
895 private:
896 TIA() = delete;
897 TIA(const TIA&) = delete;
898 TIA(TIA&&) = delete;
899 TIA& operator=(const TIA&) = delete;
900 TIA& operator=(TIA&&) = delete;
901};
902
903#endif // TIA_TIA
904