1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #include "../NstMachine.hpp"
26 #include "../NstVideoRenderer.hpp"
27 #include "NstApiVideo.hpp"
28 
29 namespace Nes
30 {
31 	namespace Core
32 	{
33 		namespace Video
34 		{
35 			Output::Locker Output::lockCallback;
36 			Output::Unlocker Output::unlockCallback;
37 		}
38 	}
39 
40 	namespace Api
41 	{
42 		#ifdef NST_MSVC_OPTIMIZE
43 		#pragma optimize("s", on)
44 		#endif
45 
EnableUnlimSprites(bool state)46 		Result Video::EnableUnlimSprites(bool state) throw()
47 		{
48 			if (emulator.tracker.IsLocked( true ))
49 				return RESULT_ERR_NOT_READY;
50 
51 			if (!emulator.ppu.HasSpriteLimit() != state)
52 			{
53 				emulator.ppu.EnableSpriteLimit( !state );
54 				emulator.tracker.Resync( true );
55 				return RESULT_OK;
56 			}
57 
58 			return RESULT_NOP;
59 		}
60 
AreUnlimSpritesEnabled() const61 		bool Video::AreUnlimSpritesEnabled() const throw()
62 		{
63 			return !emulator.ppu.HasSpriteLimit();
64 		}
65 
GetBrightness() const66 		int Video::GetBrightness() const throw()
67 		{
68 			return emulator.renderer.GetBrightness();
69 		}
70 
GetSaturation() const71 		int Video::GetSaturation() const throw()
72 		{
73 			return emulator.renderer.GetSaturation();
74 		}
75 
GetContrast() const76 		int Video::GetContrast() const throw()
77 		{
78 			return emulator.renderer.GetContrast();
79 		}
80 
GetSharpness() const81 		int Video::GetSharpness() const throw()
82 		{
83 			return emulator.renderer.GetSharpness();
84 		}
85 
GetColorResolution() const86 		int Video::GetColorResolution() const throw()
87 		{
88 			return emulator.renderer.GetColorResolution();
89 		}
90 
GetColorBleed() const91 		int Video::GetColorBleed() const throw()
92 		{
93 			return emulator.renderer.GetColorBleed();
94 		}
95 
GetColorArtifacts() const96 		int Video::GetColorArtifacts() const throw()
97 		{
98 			return emulator.renderer.GetColorArtifacts();
99 		}
100 
GetColorFringing() const101 		int Video::GetColorFringing() const throw()
102 		{
103 			return emulator.renderer.GetColorFringing();
104 		}
105 
GetHue() const106 		int Video::GetHue() const throw()
107 		{
108 			return emulator.renderer.GetHue();
109 		}
110 
GetBlend() const111 		bool Video::GetBlend() const throw()
112 		{
113 			return emulator.renderer.GetBlend() != 0;
114 		}
115 
GetCornerRounding() const116 		int Video::GetCornerRounding() const throw()
117 		{
118 			return emulator.renderer.GetCornerRounding();
119 		}
120 
SetBrightness(int value)121 		Result Video::SetBrightness(int value) throw()
122 		{
123 			return emulator.renderer.SetBrightness( value );
124 		}
125 
SetSaturation(int value)126 		Result Video::SetSaturation(int value) throw()
127 		{
128 			return emulator.renderer.SetSaturation( value );
129 		}
130 
SetContrast(int value)131 		Result Video::SetContrast(int value) throw()
132 		{
133 			return emulator.renderer.SetContrast( value );
134 		}
135 
SetSharpness(int value)136 		Result Video::SetSharpness(int value) throw()
137 		{
138 			return emulator.renderer.SetSharpness( value );
139 		}
140 
SetColorResolution(int value)141 		Result Video::SetColorResolution(int value) throw()
142 		{
143 			return emulator.renderer.SetColorResolution( value );
144 		}
145 
SetColorBleed(int value)146 		Result Video::SetColorBleed(int value) throw()
147 		{
148 			return emulator.renderer.SetColorBleed( value );
149 		}
150 
SetColorArtifacts(int value)151 		Result Video::SetColorArtifacts(int value) throw()
152 		{
153 			return emulator.renderer.SetColorArtifacts( value );
154 		}
155 
SetColorFringing(int value)156 		Result Video::SetColorFringing(int value) throw()
157 		{
158 			return emulator.renderer.SetColorFringing( value );
159 		}
160 
SetHue(int value)161 		Result Video::SetHue(int value) throw()
162 		{
163 			return emulator.renderer.SetHue( value );
164 		}
165 
SetBlend(bool value)166 		Result Video::SetBlend(bool value) throw()
167 		{
168 			return emulator.renderer.SetBlend(value);
169 		}
170 
SetCornerRounding(int value)171 		Result Video::SetCornerRounding(int value) throw()
172 		{
173 			return emulator.renderer.SetCornerRounding(value);
174 		}
175 
ClearFilterUpdateFlag()176 		void Video::ClearFilterUpdateFlag() throw()
177 		{
178 			emulator.renderer.ClearFilterUpdateFlag();
179 		}
180 
EnableFieldMerging(bool state)181 		void Video::EnableFieldMerging(bool state) throw()
182 		{
183 			emulator.renderer.EnableFieldMerging( state );
184 		}
185 
IsFieldMergingEnabled() const186 		bool Video::IsFieldMergingEnabled() const throw()
187 		{
188 			return emulator.renderer.IsFieldMergingEnabled();
189 		}
190 
SetRenderState(const RenderState & state)191 		Result Video::SetRenderState(const RenderState& state) throw()
192 		{
193 			const Result result = emulator.renderer.SetState( state );
194 
195 			if (NES_SUCCEEDED(result) && result != RESULT_NOP)
196 				emulator.UpdateColorMode();
197 
198 			return result;
199 		}
200 
GetRenderState(RenderState & state) const201 		Result Video::GetRenderState(RenderState& state) const throw()
202 		{
203 			return emulator.renderer.GetState( state );
204 		}
205 
Blit(Output & output)206 		Result Video::Blit(Output& output) throw()
207 		{
208 			if (emulator.renderer.IsReady())
209 			{
210 				emulator.renderer.Blit( output, emulator.ppu.GetScreen(), emulator.ppu.GetBurstPhase() );
211 				return RESULT_OK;
212 			}
213 
214 			return RESULT_ERR_NOT_READY;
215 		}
216 
RenderState()217 		Video::RenderState::RenderState() throw()
218 		:
219 		width  (0),
220 		height (0),
221 		filter (FILTER_NONE)
222 		{
223 			bits.count = 0;
224 			bits.mask.r = 0;
225 			bits.mask.g = 0;
226 			bits.mask.b = 0;
227 		}
228 
Decoder(DecoderPreset preset)229 		Video::Decoder::Decoder(DecoderPreset preset) throw()
230 		{
231 			switch (preset)
232 			{
233 				case DECODER_CONSUMER:
234 
235 					axes[0].angle = 105;
236 					axes[0].gain  = 0.78f;
237 					axes[1].angle = 236;
238 					axes[1].gain  = 0.33f;
239 					axes[2].angle = 0;
240 					axes[2].gain  = 1.0f;
241 					boostYellow   = false;
242 					break;
243 
244 				case DECODER_ALTERNATIVE:
245 
246 					axes[0].angle = 105;
247 					axes[0].gain  = 0.570f;
248 					axes[1].angle = 251;
249 					axes[1].gain  = 0.351f;
250 					axes[2].angle = 15;
251 					axes[2].gain  = 1.015f;
252 					boostYellow   = true;
253 					break;
254 
255 				default:
256 
257 					axes[0].angle = 105;
258 					axes[0].gain  = 0.570f;
259 					axes[1].angle = 251;
260 					axes[1].gain  = 0.351f;
261 					axes[2].angle = 15;
262 					axes[2].gain  = 1.015f;
263 					boostYellow   = false;
264 					break;
265 			}
266 		}
267 
operator ==(const Decoder & decoder) const268 		bool Video::Decoder::operator == (const Decoder& decoder) const throw()
269 		{
270 			for (uint i=0; i < NUM_AXES; ++i)
271 			{
272 				if (axes[i].angle != decoder.axes[i].angle || axes[i].gain != decoder.axes[i].gain)
273 					return false;
274 			}
275 
276 			if (boostYellow != decoder.boostYellow)
277 				return false;
278 
279 			return true;
280 		}
281 
operator !=(const Decoder & decoder) const282 		bool Video::Decoder::operator != (const Decoder& decoder) const throw()
283 		{
284 			return !(*this == decoder);
285 		}
286 
SetDecoder(const Decoder & decoder)287 		Result Video::SetDecoder(const Decoder& decoder) throw()
288 		{
289 			return emulator.renderer.SetDecoder( decoder );
290 		}
291 
GetDecoder() const292 		const Video::Decoder& Video::GetDecoder() const throw()
293 		{
294 			return emulator.renderer.GetDecoder();
295 		}
296 
SetMode(const Mode mode)297 		Result Video::Palette::SetMode(const Mode mode) throw()
298 		{
299 			return emulator.UpdateColorMode
300 			(
301 				mode == MODE_RGB    ? Core::Machine::COLORMODE_RGB :
302 				mode == MODE_CUSTOM ? Core::Machine::COLORMODE_CUSTOM :
303                                       Core::Machine::COLORMODE_YUV
304 			);
305 		}
306 
GetMode() const307 		Video::Palette::Mode Video::Palette::GetMode() const throw()
308 		{
309 			if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_YUV)
310 			{
311 				return MODE_YUV;
312 			}
313 			else if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_CUSTOM)
314 			{
315 				return MODE_CUSTOM;
316 			}
317 
318 			return MODE_RGB;
319 		}
320 
GetDefaultMode() const321 		Video::Palette::Mode Video::Palette::GetDefaultMode() const throw()
322 		{
323 			NST_COMPILE_ASSERT( Core::Video::Renderer::DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 );
324 
325 			return MODE_YUV;
326 		}
327 
SetCustom(Colors colors,CustomType type)328 		Result Video::Palette::SetCustom(Colors colors,CustomType type) throw()
329 		{
330 			return emulator.renderer.LoadCustomPalette( colors, type == EXT_PALETTE );
331 		}
332 
GetCustom(uchar (* colors)[3],CustomType type) const333 		uint Video::Palette::GetCustom(uchar (*colors)[3],CustomType type) const throw()
334 		{
335 			return emulator.renderer.SaveCustomPalette( colors, type == EXT_PALETTE );
336 		}
337 
ResetCustom()338 		void Video::Palette::ResetCustom() throw()
339 		{
340 			return emulator.renderer.ResetCustomPalette();
341 		}
342 
GetCustomType() const343 		Video::Palette::CustomType Video::Palette::GetCustomType() const throw()
344 		{
345 			return emulator.renderer.HasCustomPaletteEmphasis() ? EXT_PALETTE : STD_PALETTE;
346 		}
347 
GetColors() const348 		Video::Palette::Colors Video::Palette::GetColors() const throw()
349 		{
350 			return emulator.renderer.GetPalette();
351 		}
352 
353 		#ifdef NST_MSVC_OPTIMIZE
354 		#pragma optimize("", on)
355 		#endif
356 	}
357 }
358