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
23constexpr float scaleFrom100(float x) { return (x/50.f) - 1.f; }
24constexpr uInt32 scaleTo100(float x) { return uInt32(50*(x+1.f)); }
25
26// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27NTSCFilter::NTSCFilter()
28 : mySetup(AtariNTSC::TV_Composite),
29 myPreset(Preset::OFF),
30 myCurrentAdjustable(0)
31{
32}
33
34// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
35string 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69string 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
83string 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97string 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
112string 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
130string 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
165void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
181void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
201void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
216void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
232AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite;
233
234// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
235const 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