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 
EnableOverclocking(bool state)61 		Result Video::EnableOverclocking(bool state) throw()
62 		{
63 			if (emulator.tracker.IsLocked( true ))
64 				return RESULT_ERR_NOT_READY;
65 
66 			if (emulator.ppu.GetOverclockState() != state)
67 			{
68 				emulator.ppu.SetOverclockState( state );
69 				return RESULT_OK;
70 			}
71 
72 			return RESULT_NOP;
73 		}
74 
AreUnlimSpritesEnabled() const75 		bool Video::AreUnlimSpritesEnabled() const throw()
76 		{
77 			return !emulator.ppu.HasSpriteLimit();
78 		}
79 
GetBrightness() const80 		int Video::GetBrightness() const throw()
81 		{
82 			return emulator.renderer.GetBrightness();
83 		}
84 
GetSaturation() const85 		int Video::GetSaturation() const throw()
86 		{
87 			return emulator.renderer.GetSaturation();
88 		}
89 
GetContrast() const90 		int Video::GetContrast() const throw()
91 		{
92 			return emulator.renderer.GetContrast();
93 		}
94 
GetSharpness() const95 		int Video::GetSharpness() const throw()
96 		{
97 			return emulator.renderer.GetSharpness();
98 		}
99 
GetColorResolution() const100 		int Video::GetColorResolution() const throw()
101 		{
102 			return emulator.renderer.GetColorResolution();
103 		}
104 
GetColorBleed() const105 		int Video::GetColorBleed() const throw()
106 		{
107 			return emulator.renderer.GetColorBleed();
108 		}
109 
GetColorArtifacts() const110 		int Video::GetColorArtifacts() const throw()
111 		{
112 			return emulator.renderer.GetColorArtifacts();
113 		}
114 
GetColorFringing() const115 		int Video::GetColorFringing() const throw()
116 		{
117 			return emulator.renderer.GetColorFringing();
118 		}
119 
GetHue() const120 		int Video::GetHue() const throw()
121 		{
122 			return emulator.renderer.GetHue();
123 		}
124 
GetBlend() const125 		bool Video::GetBlend() const throw()
126 		{
127 			return emulator.renderer.GetBlend() != 0;
128 		}
129 
GetCornerRounding() const130 		int Video::GetCornerRounding() const throw()
131 		{
132 			return emulator.renderer.GetCornerRounding();
133 		}
134 
SetBrightness(int value)135 		Result Video::SetBrightness(int value) throw()
136 		{
137 			return emulator.renderer.SetBrightness( value );
138 		}
139 
SetSaturation(int value)140 		Result Video::SetSaturation(int value) throw()
141 		{
142 			return emulator.renderer.SetSaturation( value );
143 		}
144 
SetContrast(int value)145 		Result Video::SetContrast(int value) throw()
146 		{
147 			return emulator.renderer.SetContrast( value );
148 		}
149 
SetSharpness(int value)150 		Result Video::SetSharpness(int value) throw()
151 		{
152 			return emulator.renderer.SetSharpness( value );
153 		}
154 
SetColorResolution(int value)155 		Result Video::SetColorResolution(int value) throw()
156 		{
157 			return emulator.renderer.SetColorResolution( value );
158 		}
159 
SetColorBleed(int value)160 		Result Video::SetColorBleed(int value) throw()
161 		{
162 			return emulator.renderer.SetColorBleed( value );
163 		}
164 
SetColorArtifacts(int value)165 		Result Video::SetColorArtifacts(int value) throw()
166 		{
167 			return emulator.renderer.SetColorArtifacts( value );
168 		}
169 
SetColorFringing(int value)170 		Result Video::SetColorFringing(int value) throw()
171 		{
172 			return emulator.renderer.SetColorFringing( value );
173 		}
174 
SetHue(int value)175 		Result Video::SetHue(int value) throw()
176 		{
177 			return emulator.renderer.SetHue( value );
178 		}
179 
SetBlend(bool value)180 		Result Video::SetBlend(bool value) throw()
181 		{
182 			return emulator.renderer.SetBlend(value);
183 		}
184 
SetCornerRounding(int value)185 		Result Video::SetCornerRounding(int value) throw()
186 		{
187 			return emulator.renderer.SetCornerRounding(value);
188 		}
189 
ClearFilterUpdateFlag()190 		void Video::ClearFilterUpdateFlag() throw()
191 		{
192 			emulator.renderer.ClearFilterUpdateFlag();
193 		}
194 
EnableFieldMerging(bool state)195 		void Video::EnableFieldMerging(bool state) throw()
196 		{
197 			emulator.renderer.EnableFieldMerging( state );
198 		}
199 
IsFieldMergingEnabled() const200 		bool Video::IsFieldMergingEnabled() const throw()
201 		{
202 			return emulator.renderer.IsFieldMergingEnabled();
203 		}
204 
SetRenderState(const RenderState & state)205 		Result Video::SetRenderState(const RenderState& state) throw()
206 		{
207 			const Result result = emulator.renderer.SetState( state );
208 
209 			if (NES_SUCCEEDED(result) && result != RESULT_NOP)
210 				emulator.UpdateColorMode();
211 
212 			return result;
213 		}
214 
GetRenderState(RenderState & state) const215 		Result Video::GetRenderState(RenderState& state) const throw()
216 		{
217 			return emulator.renderer.GetState( state );
218 		}
219 
Blit(Output & output)220 		Result Video::Blit(Output& output) throw()
221 		{
222 			if (emulator.renderer.IsReady())
223 			{
224 				emulator.renderer.Blit( output, emulator.ppu.GetScreen(), emulator.ppu.GetBurstPhase() );
225 				return RESULT_OK;
226 			}
227 
228 			return RESULT_ERR_NOT_READY;
229 		}
230 
RenderState()231 		Video::RenderState::RenderState() throw()
232 		:
233 		width  (0),
234 		height (0),
235 		filter (FILTER_NONE)
236 		{
237 			bits.count = 0;
238 			bits.mask.r = 0;
239 			bits.mask.g = 0;
240 			bits.mask.b = 0;
241 		}
242 
Decoder(DecoderPreset preset)243 		Video::Decoder::Decoder(DecoderPreset preset) throw()
244 		{
245 			switch (preset)
246 			{
247 				case DECODER_CONSUMER:
248 
249 					axes[0].angle = 105;
250 					axes[0].gain  = 0.78f;
251 					axes[1].angle = 236;
252 					axes[1].gain  = 0.33f;
253 					axes[2].angle = 0;
254 					axes[2].gain  = 1.0f;
255 					boostYellow   = false;
256 					break;
257 
258 				case DECODER_ALTERNATIVE:
259 
260 					axes[0].angle = 105;
261 					axes[0].gain  = 0.570f;
262 					axes[1].angle = 251;
263 					axes[1].gain  = 0.351f;
264 					axes[2].angle = 15;
265 					axes[2].gain  = 1.015f;
266 					boostYellow   = true;
267 					break;
268 
269 				default:
270 
271 					axes[0].angle = 105;
272 					axes[0].gain  = 0.570f;
273 					axes[1].angle = 251;
274 					axes[1].gain  = 0.351f;
275 					axes[2].angle = 15;
276 					axes[2].gain  = 1.015f;
277 					boostYellow   = false;
278 					break;
279 			}
280 		}
281 
operator ==(const Decoder & decoder) const282 		bool Video::Decoder::operator == (const Decoder& decoder) const throw()
283 		{
284 			for (uint i=0; i < NUM_AXES; ++i)
285 			{
286 				if (axes[i].angle != decoder.axes[i].angle || axes[i].gain != decoder.axes[i].gain)
287 					return false;
288 			}
289 
290 			if (boostYellow != decoder.boostYellow)
291 				return false;
292 
293 			return true;
294 		}
295 
operator !=(const Decoder & decoder) const296 		bool Video::Decoder::operator != (const Decoder& decoder) const throw()
297 		{
298 			return !(*this == decoder);
299 		}
300 
SetDecoder(const Decoder & decoder)301 		Result Video::SetDecoder(const Decoder& decoder) throw()
302 		{
303 			return emulator.renderer.SetDecoder( decoder );
304 		}
305 
GetDecoder() const306 		const Video::Decoder& Video::GetDecoder() const throw()
307 		{
308 			return emulator.renderer.GetDecoder();
309 		}
310 
SetMode(const Mode mode)311 		Result Video::Palette::SetMode(const Mode mode) throw()
312 		{
313 			return emulator.UpdateColorMode
314 			(
315 				mode == MODE_RGB    ? Core::Machine::COLORMODE_RGB :
316 				mode == MODE_CUSTOM ? Core::Machine::COLORMODE_CUSTOM :
317                                       Core::Machine::COLORMODE_YUV
318 			);
319 		}
320 
GetMode() const321 		Video::Palette::Mode Video::Palette::GetMode() const throw()
322 		{
323 			if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_YUV)
324 			{
325 				return MODE_YUV;
326 			}
327 			else if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_CUSTOM)
328 			{
329 				return MODE_CUSTOM;
330 			}
331 
332 			return MODE_RGB;
333 		}
334 
GetDefaultMode() const335 		Video::Palette::Mode Video::Palette::GetDefaultMode() const throw()
336 		{
337 			NST_COMPILE_ASSERT( Core::Video::Renderer::DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 );
338 
339 			return MODE_YUV;
340 		}
341 
SetCustom(Colors colors,CustomType type)342 		Result Video::Palette::SetCustom(Colors colors,CustomType type) throw()
343 		{
344 			return emulator.renderer.LoadCustomPalette( colors, type == EXT_PALETTE );
345 		}
346 
GetCustom(uchar (* colors)[3],CustomType type) const347 		uint Video::Palette::GetCustom(uchar (*colors)[3],CustomType type) const throw()
348 		{
349 			return emulator.renderer.SaveCustomPalette( colors, type == EXT_PALETTE );
350 		}
351 
ResetCustom()352 		void Video::Palette::ResetCustom() throw()
353 		{
354 			return emulator.renderer.ResetCustomPalette();
355 		}
356 
GetCustomType() const357 		Video::Palette::CustomType Video::Palette::GetCustomType() const throw()
358 		{
359 			return emulator.renderer.HasCustomPaletteEmphasis() ? EXT_PALETTE : STD_PALETTE;
360 		}
361 
GetColors() const362 		Video::Palette::Colors Video::Palette::GetColors() const throw()
363 		{
364 			return emulator.renderer.GetPalette();
365 		}
366 
367 		#ifdef NST_MSVC_OPTIMIZE
368 		#pragma optimize("", on)
369 		#endif
370 	}
371 }
372