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_YSTART_DETECTOR |
19 | #define TIA_YSTART_DETECTOR |
20 | |
21 | #include "AbstractFrameManager.hxx" |
22 | |
23 | /** |
24 | * This frame manager detects ystart from the first line with vblank = off. |
25 | */ |
26 | |
27 | class YStartDetector: public AbstractFrameManager { |
28 | |
29 | public: |
30 | |
31 | YStartDetector(); |
32 | |
33 | public: |
34 | |
35 | /** |
36 | * Getter for the detected ystart value |
37 | */ |
38 | uInt32 detectedYStart() const; |
39 | |
40 | /** |
41 | * We require frame layout to be set from outside. |
42 | */ |
43 | void setLayout(FrameLayout layout) override { this->layout(layout); } |
44 | |
45 | protected: |
46 | |
47 | /** |
48 | * We need to track vsync changes. |
49 | */ |
50 | void onSetVsync() override; |
51 | |
52 | /** |
53 | * Reset hook. |
54 | */ |
55 | void onReset() override; |
56 | |
57 | /** |
58 | * The workhorse. |
59 | */ |
60 | void onNextLine() override; |
61 | |
62 | private: |
63 | |
64 | /** |
65 | * Our various states. |
66 | */ |
67 | enum class State { |
68 | // Wait for vsync on |
69 | waitForVsyncStart, |
70 | |
71 | // Wait for vsync off |
72 | waitForVsyncEnd, |
73 | |
74 | // Wait for the visible frame to start |
75 | waitForFrameStart |
76 | }; |
77 | |
78 | /** |
79 | * Have we settled on a frame start? |
80 | */ |
81 | enum class VblankMode { |
82 | // We have settled on a frame start and have some hysteresis before we return to floating |
83 | locked, |
84 | |
85 | // We are actively looking for the frame to start |
86 | floating |
87 | }; |
88 | |
89 | private: |
90 | |
91 | /** |
92 | * Side effects for state transitions. |
93 | */ |
94 | void setState(State state); |
95 | |
96 | /** |
97 | * Perform detection and decide whether the frame starts now. |
98 | */ |
99 | bool shouldTransitionToFrame(); |
100 | |
101 | private: |
102 | |
103 | /** |
104 | * State. |
105 | */ |
106 | State myState; |
107 | |
108 | /** |
109 | * locked / floating |
110 | */ |
111 | VblankMode myVblankMode; |
112 | |
113 | /** |
114 | * Counts the scanlines that we wait for vsync to start. |
115 | */ |
116 | uInt32 myLinesWaitingForVsyncToStart; |
117 | |
118 | /** |
119 | * The number of lines we are currently waiting for the frame to start (and vblank to end). |
120 | */ |
121 | uInt32 myCurrentVblankLines; |
122 | |
123 | /** |
124 | * The number of vblank lines on the last frame. |
125 | */ |
126 | uInt32 myLastVblankLines; |
127 | |
128 | /** |
129 | * Count "vblank violations" in fixed mode (the number of consecutive frames where ystart |
130 | * differs from the previously detected value). Once a trip point is reached, we transition |
131 | * back to floating mode. |
132 | */ |
133 | uInt32 myVblankViolations; |
134 | |
135 | /** |
136 | * The number of frames in floating mode with stable ystart. Once a trip point is reacted, |
137 | * we transition to fixed mode |
138 | */ |
139 | uInt32 myStableVblankFrames; |
140 | |
141 | /** |
142 | * Tracks deviations from the determined ystart value during a fixed mode frame in order to |
143 | * avoid double counting. |
144 | */ |
145 | bool myVblankViolated; |
146 | |
147 | private: |
148 | |
149 | YStartDetector(const YStartDetector&) = delete; |
150 | YStartDetector(YStartDetector&&) = delete; |
151 | YStartDetector& operator=(const YStartDetector&) = delete; |
152 | YStartDetector& operator=(YStartDetector&&) = delete; |
153 | }; |
154 | |
155 | #endif // TIA_YSTART_DETECTOR |
156 | |