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 "TIASurface.hxx" |
19 | #include "Settings.hxx" |
20 | |
21 | #include "NTSCFilter.hxx" |
22 | |
23 | constexpr float scaleFrom100(float x) { return (x/50.f) - 1.f; } |
24 | constexpr uInt32 scaleTo100(float x) { return uInt32(50*(x+1.f)); } |
25 | |
26 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
27 | NTSCFilter::NTSCFilter() |
28 | : mySetup(AtariNTSC::TV_Composite), |
29 | myPreset(Preset::OFF), |
30 | myCurrentAdjustable(0) |
31 | { |
32 | } |
33 | |
34 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
35 | string NTSCFilter::setPreset(Preset preset) |
36 | { |
37 | myPreset = preset; |
38 | string msg = "disabled" ; |
39 | switch(myPreset) |
40 | { |
41 | case Preset::COMPOSITE: |
42 | mySetup = AtariNTSC::TV_Composite; |
43 | msg = "COMPOSITE" ; |
44 | break; |
45 | case Preset::SVIDEO: |
46 | mySetup = AtariNTSC::TV_SVideo; |
47 | msg = "S-VIDEO" ; |
48 | break; |
49 | case Preset::RGB: |
50 | mySetup = AtariNTSC::TV_RGB; |
51 | msg = "RGB" ; |
52 | break; |
53 | case Preset::BAD: |
54 | mySetup = AtariNTSC::TV_Bad; |
55 | msg = "BAD ADJUST" ; |
56 | break; |
57 | case Preset::CUSTOM: |
58 | mySetup = myCustomSetup; |
59 | msg = "CUSTOM" ; |
60 | break; |
61 | default: |
62 | return msg; |
63 | } |
64 | myNTSC.initialize(mySetup, myTIAPalette); |
65 | return msg; |
66 | } |
67 | |
68 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
69 | string NTSCFilter::getPreset() const |
70 | { |
71 | switch(myPreset) |
72 | { |
73 | case Preset::COMPOSITE: return "COMPOSITE" ; |
74 | case Preset::SVIDEO: return "S-VIDEO" ; |
75 | case Preset::RGB: return "RGB" ; |
76 | case Preset::BAD: return "BAD ADJUST" ; |
77 | case Preset::CUSTOM: return "CUSTOM" ; |
78 | default: return "Disabled" ; |
79 | } |
80 | } |
81 | |
82 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
83 | string NTSCFilter::setNextAdjustable() |
84 | { |
85 | if(myPreset != Preset::CUSTOM) |
86 | return "'Custom' TV mode not selected" ; |
87 | |
88 | myCurrentAdjustable = (myCurrentAdjustable + 1) % 10; |
89 | ostringstream buf; |
90 | buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type |
91 | << "' selected" ; |
92 | |
93 | return buf.str(); |
94 | } |
95 | |
96 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
97 | string NTSCFilter::setPreviousAdjustable() |
98 | { |
99 | if(myPreset != Preset::CUSTOM) |
100 | return "'Custom' TV mode not selected" ; |
101 | |
102 | if(myCurrentAdjustable == 0) myCurrentAdjustable = 9; |
103 | else --myCurrentAdjustable; |
104 | ostringstream buf; |
105 | buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type |
106 | << "' selected" ; |
107 | |
108 | return buf.str(); |
109 | } |
110 | |
111 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
112 | string NTSCFilter::increaseAdjustable() |
113 | { |
114 | if(myPreset != Preset::CUSTOM) |
115 | return "'Custom' TV mode not selected" ; |
116 | |
117 | uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); |
118 | newval += 2; if(newval > 100) newval = 100; |
119 | *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval); |
120 | |
121 | ostringstream buf; |
122 | buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type |
123 | << "' set to " << newval; |
124 | |
125 | setPreset(myPreset); |
126 | return buf.str(); |
127 | } |
128 | |
129 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
130 | string NTSCFilter::decreaseAdjustable() |
131 | { |
132 | if(myPreset != Preset::CUSTOM) |
133 | return "'Custom' TV mode not selected" ; |
134 | |
135 | uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); |
136 | if(newval < 2) newval = 0; |
137 | else newval -= 2; |
138 | *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval); |
139 | |
140 | ostringstream buf; |
141 | buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type |
142 | << "' set to " << newval; |
143 | |
144 | setPreset(myPreset); |
145 | return buf.str(); |
146 | } |
147 | |
148 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
149 | void NTSCFilter::loadConfig(const Settings& settings) |
150 | { |
151 | // Load adjustables for custom mode |
152 | myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue" ), -1.0f, 1.0f); |
153 | myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation" ), -1.0f, 1.0f); |
154 | myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast" ), -1.0f, 1.0f); |
155 | myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness" ), -1.0f, 1.0f); |
156 | myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness" ), -1.0f, 1.0f); |
157 | myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma" ), -1.0f, 1.0f); |
158 | myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution" ), -1.0f, 1.0f); |
159 | myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts" ), -1.0f, 1.0f); |
160 | myCustomSetup.fringing = BSPF::clamp(settings.getFloat("tv.fringing" ), -1.0f, 1.0f); |
161 | myCustomSetup.bleed = BSPF::clamp(settings.getFloat("tv.bleed" ), -1.0f, 1.0f); |
162 | } |
163 | |
164 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
165 | void NTSCFilter::saveConfig(Settings& settings) const |
166 | { |
167 | // Save adjustables for custom mode |
168 | settings.setValue("tv.hue" , myCustomSetup.hue); |
169 | settings.setValue("tv.saturation" , myCustomSetup.saturation); |
170 | settings.setValue("tv.contrast" , myCustomSetup.contrast); |
171 | settings.setValue("tv.brightness" , myCustomSetup.brightness); |
172 | settings.setValue("tv.sharpness" , myCustomSetup.sharpness); |
173 | settings.setValue("tv.gamma" , myCustomSetup.gamma); |
174 | settings.setValue("tv.resolution" , myCustomSetup.resolution); |
175 | settings.setValue("tv.artifacts" , myCustomSetup.artifacts); |
176 | settings.setValue("tv.fringing" , myCustomSetup.fringing); |
177 | settings.setValue("tv.bleed" , myCustomSetup.bleed); |
178 | } |
179 | |
180 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
181 | void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const |
182 | { |
183 | switch(preset) |
184 | { |
185 | case Preset::COMPOSITE: |
186 | convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break; |
187 | case Preset::SVIDEO: |
188 | convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break; |
189 | case Preset::RGB: |
190 | convertToAdjustable(adjustable, AtariNTSC::TV_RGB); break; |
191 | case Preset::BAD: |
192 | convertToAdjustable(adjustable, AtariNTSC::TV_Bad); break; |
193 | case Preset::CUSTOM: |
194 | convertToAdjustable(adjustable, myCustomSetup); break; |
195 | default: |
196 | break; |
197 | } |
198 | } |
199 | |
200 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
201 | void NTSCFilter::setCustomAdjustables(Adjustable& adjustable) |
202 | { |
203 | myCustomSetup.hue = scaleFrom100(adjustable.hue); |
204 | myCustomSetup.saturation = scaleFrom100(adjustable.saturation); |
205 | myCustomSetup.contrast = scaleFrom100(adjustable.contrast); |
206 | myCustomSetup.brightness = scaleFrom100(adjustable.brightness); |
207 | myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness); |
208 | myCustomSetup.gamma = scaleFrom100(adjustable.gamma); |
209 | myCustomSetup.resolution = scaleFrom100(adjustable.resolution); |
210 | myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts); |
211 | myCustomSetup.fringing = scaleFrom100(adjustable.fringing); |
212 | myCustomSetup.bleed = scaleFrom100(adjustable.bleed); |
213 | } |
214 | |
215 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
216 | void NTSCFilter::convertToAdjustable(Adjustable& adjustable, |
217 | const AtariNTSC::Setup& setup) const |
218 | { |
219 | adjustable.hue = scaleTo100(setup.hue); |
220 | adjustable.saturation = scaleTo100(setup.saturation); |
221 | adjustable.contrast = scaleTo100(setup.contrast); |
222 | adjustable.brightness = scaleTo100(setup.brightness); |
223 | adjustable.sharpness = scaleTo100(setup.sharpness); |
224 | adjustable.gamma = scaleTo100(setup.gamma); |
225 | adjustable.resolution = scaleTo100(setup.resolution); |
226 | adjustable.artifacts = scaleTo100(setup.artifacts); |
227 | adjustable.fringing = scaleTo100(setup.fringing); |
228 | adjustable.bleed = scaleTo100(setup.bleed); |
229 | } |
230 | |
231 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
232 | AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite; |
233 | |
234 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
235 | const NTSCFilter::AdjustableTag NTSCFilter::ourCustomAdjustables[10] = { |
236 | { "contrast" , &myCustomSetup.contrast }, |
237 | { "brightness" , &myCustomSetup.brightness }, |
238 | { "hue" , &myCustomSetup.hue }, |
239 | { "saturation" , &myCustomSetup.saturation }, |
240 | { "gamma" , &myCustomSetup.gamma }, |
241 | { "sharpness" , &myCustomSetup.sharpness }, |
242 | { "resolution" , &myCustomSetup.resolution }, |
243 | { "artifacts" , &myCustomSetup.artifacts }, |
244 | { "fringing" , &myCustomSetup.fringing }, |
245 | { "bleeding" , &myCustomSetup.bleed } |
246 | }; |
247 | |