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_ABSTRACT_FRAME_MANAGER
19#define TIA_ABSTRACT_FRAME_MANAGER
20
21#include <functional>
22
23#include "Serializable.hxx"
24#include "FrameLayout.hxx"
25
26class AbstractFrameManager : public Serializable
27{
28 public:
29
30 using callback = std::function<void()>;
31
32 public:
33
34 AbstractFrameManager();
35
36 public:
37
38 /**
39 * Configure the various handler callbacks.
40 */
41 void setHandlers(
42 callback frameStartCallback,
43 callback frameCompletionCallback
44 );
45
46 /**
47 * Clear the configured handler callbacks.
48 */
49 void clearHandlers();
50
51 /**
52 * Reset.
53 */
54 void reset();
55
56 /**
57 * Called by TIA to notify the start of the next scanline.
58 */
59 void nextLine();
60
61 /**
62 * Called by TIA on VBLANK writes.
63 */
64 void setVblank(bool vblank);
65
66 /**
67 * Called by TIA on VSYNC writes.
68 */
69 void setVsync(bool vsync);
70
71 /**
72 * Should the TIA render its frame? This is buffered in a flag for
73 * performance reasons; descendants must update the flag.
74 */
75 bool isRendering() const { return myIsRendering; }
76
77 /**
78 * Is vsync on?
79 */
80 bool vsync() const { return myVsync; }
81
82 /**
83 * Is vblank on?
84 */
85 bool vblank() const { return myVblank; }
86
87 /**
88 * The number of scanlines in the last finished frame.
89 */
90 uInt32 scanlinesLastFrame() const { return myCurrentFrameFinalLines; }
91
92 /**
93 * Did the number of scanlines switch between even / odd (used for color loss
94 * emulation).
95 */
96 bool scanlineParityChanged() const {
97 return (myPreviousFrameFinalLines & 0x1) != (myCurrentFrameFinalLines & 0x1);
98 }
99
100 /**
101 * The total number of frames. 32 bit should be good for > 2 years :)
102 */
103 uInt32 frameCount() const { return myTotalFrames; }
104
105 /**
106 * The configured (our autodetected) frame layout (PAL / NTSC).
107 */
108 FrameLayout layout() const { return myLayout; }
109
110 /**
111 * Save state.
112 */
113 bool save(Serializer& out) const override;
114
115 /**
116 * Restore state.
117 */
118 bool load(Serializer& in) override;
119
120 public:
121 // The following methods are implement as noops and should be overriden as
122 // required. All of these are irrelevant if nothing is displayed (during
123 // autodetect).
124
125 /**
126 * The jitter factor determines the time jitter simulation takes to recover.
127 */
128 virtual void setJitterFactor(uInt8 factor) {}
129
130 /**
131 * Is jitter simulation enabled?
132 */
133 virtual bool jitterEnabled() const { return false; }
134
135 /**
136 * Enable jitter simulation
137 */
138 virtual void enableJitter(bool enabled) {}
139
140 /**
141 * The scanline difference between the last two frames. Used in the TIA to
142 * clear any scanlines that were not repainted.
143 */
144 virtual Int32 missingScanlines() const { return 0; }
145
146 /**
147 * Frame height.
148 */
149 virtual uInt32 height() const { return 0; }
150
151 /**
152 * The current y coordinate (valid only during rendering).
153 */
154 virtual uInt32 getY() const { return 0; }
155
156 /**
157 * The current number of scanlines in the current frame (including invisible
158 * lines).
159 */
160 virtual uInt32 scanlines() const { return 0; }
161
162 /**
163 * Configure the ystart value.
164 */
165 virtual void setYstart(uInt32 ystart) {}
166
167 /**
168 * The configured ystart value.
169 */
170 virtual uInt32 ystart() const { return 0; }
171
172 /**
173 * Set the frame layout. This may be a noop (on the autodetection manager).
174 */
175 virtual void setLayout(FrameLayout mode) {}
176
177 protected:
178 // The following are template methods that can be implemented to hook into
179 // the frame logic.
180
181 /**
182 * Called if vblank changes.
183 */
184 virtual void onSetVblank() {}
185
186 /**
187 * Called if vsync changes.
188 */
189 virtual void onSetVsync() {}
190
191 /**
192 * Called if the next line is signalled, after the internal bookkeeping has
193 * been updated.
194 */
195 virtual void onNextLine() {}
196
197 /**
198 * Called on reset (after the base class has reset).
199 */
200 virtual void onReset() {}
201
202 /**
203 * Called after a frame layout change.
204 */
205 virtual void onLayoutChange() {}
206
207 /**
208 * Called during state save (after the base class has serialized its state).
209 */
210 virtual bool onSave(Serializer& out) const { throw runtime_error("cannot be serialized"); }
211
212 /**
213 * Called during state restore (after the base class has restored its state).
214 */
215 virtual bool onLoad(Serializer& in) { throw runtime_error("cannot be serialized"); }
216
217 protected:
218 // These need to be called in order to drive the frame lifecycle of the
219 // emulation.
220
221 /**
222 * Signal frame start.
223 */
224 void notifyFrameStart();
225
226 /**
227 * Signal frame stop.
228 */
229 void notifyFrameComplete();
230
231 /**
232 * The internal setter to update the frame layout.
233 */
234 void layout(FrameLayout layout);
235
236 protected:
237
238 /**
239 * Rendering flag.
240 */
241 bool myIsRendering;
242
243 /**
244 * Vsync flag.
245 */
246 bool myVsync;
247
248 /**
249 * Vblank flag.
250 */
251 bool myVblank;
252
253 /**
254 * Current scanline count in the current frame.
255 */
256 uInt32 myCurrentFrameTotalLines;
257
258 /**
259 * Total number of scanlines in the last complete frame.
260 */
261 uInt32 myCurrentFrameFinalLines;
262
263 /**
264 * Total number of scanlines in the second last complete frame.
265 */
266 uInt32 myPreviousFrameFinalLines;
267
268 /**
269 * Total frame count.
270 */
271 uInt32 myTotalFrames;
272
273 private:
274
275 /**
276 * Current frame layout.
277 */
278 FrameLayout myLayout;
279
280 /**
281 * The various lifecycle callbacks.
282 */
283 callback myOnFrameStart;
284 callback myOnFrameComplete;
285
286 private:
287
288 AbstractFrameManager(const AbstractFrameManager&) = delete;
289 AbstractFrameManager(AbstractFrameManager&&) = delete;
290 AbstractFrameManager& operator=(const AbstractFrameManager&);
291 AbstractFrameManager& operator=(AbstractFrameManager&&);
292
293};
294
295#endif // TIA_ABSTRACT_FRAME_MANAGER
296