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#include "JitterEmulation.hxx"
19
20enum Metrics: uInt32 {
21 framesForStableHeight = 2,
22 framesUntilDestabilization = 10,
23 minDeltaForJitter = 3,
24 maxJitter = 50
25};
26
27// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28JitterEmulation::JitterEmulation()
29 : myJitterFactor(0),
30 myYStart(0)
31{
32 reset();
33}
34
35// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
36void JitterEmulation::reset()
37{
38 myLastFrameScanlines = 0;
39 myStableFrameFinalLines = -1;
40 myStableFrames = 0;
41 myStabilizationCounter = 0;
42 myDestabilizationCounter = 0;
43 myJitter = 0;
44}
45
46// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47void JitterEmulation::frameComplete(uInt32 scanlineCount)
48{
49 if (Int32(scanlineCount) != myStableFrameFinalLines) {
50 if (myDestabilizationCounter++ > Metrics::framesUntilDestabilization) myStableFrameFinalLines = -1;
51
52 if (scanlineCount == myLastFrameScanlines) {
53
54 if (++myStabilizationCounter >= Metrics::framesForStableHeight) {
55 if (myStableFrameFinalLines > 0) updateJitter(scanlineCount - myStableFrameFinalLines);
56
57 myStableFrameFinalLines = scanlineCount;
58 myDestabilizationCounter = 0;
59 }
60
61 }
62 else myStabilizationCounter = 0;
63 }
64 else myDestabilizationCounter = 0;
65
66 myLastFrameScanlines = scanlineCount;
67
68 if (myJitter > 0) myJitter = std::max(myJitter - myJitterFactor, 0);
69 if (myJitter < 0) myJitter = std::min(myJitter + myJitterFactor, 0);
70}
71
72// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
73void JitterEmulation::updateJitter(Int32 scanlineDifference)
74{
75 if (uInt32(abs(scanlineDifference)) < Metrics::minDeltaForJitter) return;
76
77 Int32 jitter = std::min<Int32>(scanlineDifference, Metrics::maxJitter);
78 jitter = std::max<Int32>(jitter, -myYStart);
79
80 if (jitter > 0) jitter += myJitterFactor;
81 if (jitter < 0) jitter -= myJitterFactor;
82
83 if (abs(jitter) > abs(myJitter)) myJitter = jitter;
84}
85
86// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
87bool JitterEmulation::save(Serializer& out) const
88{
89 try
90 {
91 out.putInt(myLastFrameScanlines);
92 out.putInt(myStableFrameFinalLines);
93 out.putInt(myStableFrames);
94 out.putInt(myStabilizationCounter);
95 out.putInt(myDestabilizationCounter);
96 out.putInt(myJitter);
97 out.putInt(myJitterFactor);
98 out.putInt(myYStart);
99 }
100 catch(...)
101 {
102 cerr << "ERROR: JitterEmulation::save" << std::endl;
103
104 return false;
105 }
106
107 return true;
108}
109
110// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111bool JitterEmulation::load(Serializer& in)
112{
113 try
114 {
115 myLastFrameScanlines = in.getInt();
116 myStableFrameFinalLines = in.getInt();
117 myStableFrames = in.getInt();
118 myStabilizationCounter = in.getInt();
119 myDestabilizationCounter = in.getInt();
120 myJitter = in.getInt();
121 myJitterFactor = in.getInt();
122 myYStart = in.getInt();
123 }
124 catch (...)
125 {
126 cerr << "ERROR: JitterEmulation::load" << std::endl;
127
128 return false;
129 }
130
131 return true;
132}
133