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 #ifndef NST_API_VIDEO_H
26 #define NST_API_VIDEO_H
27 
28 #include "NstApi.hpp"
29 
30 #ifdef NST_PRAGMA_ONCE
31 #pragma once
32 #endif
33 
34 #if NST_ICC >= 810
35 #pragma warning( push )
36 #pragma warning( disable : 304 444 )
37 #elif NST_MSVC >= 1200
38 #pragma warning( push )
39 #pragma warning( disable : 4512 )
40 #endif
41 
42 namespace Nes
43 {
44 	namespace Core
45 	{
46 		namespace Video
47 		{
48 			/**
49 			* Video output context.
50 			*/
51 			class Output
52 			{
53 				struct Locker;
54 				struct Unlocker;
55 
56 			public:
57 
58 				enum
59 				{
60 					WIDTH = 256,
61 					HEIGHT = 240,
62 					NTSC_WIDTH = 602
63 				};
64 
65 				/**
66 				* Pointer to surface memory to be written to. Size must be equal to
67 				* or greater than bitsPerPixel/8 * NES screen width * NES screen height.
68 				*/
69 				void* pixels;
70 
71 				/**
72 				* Distance in bytes for each line in the surface memory.
73 				* Must be equal to or greater than the actual NES screen width.
74 				* Value is allowed to be negative.
75 				*/
76 				long pitch;
77 
Output(void * v=0,long p=0)78 				Output(void* v=0,long p=0)
79 				: pixels(v), pitch(p) {}
80 
81 				/**
82 				* Surface lock callback prototype.
83 				*
84 				* Called right before the core is about to render to the surface.
85 				*
86 				* @param userData optional user data
87 				* @param output object to this class
88 				* @return true if surface is valid and can be written to
89 				*/
90 				typedef bool (NST_CALLBACK *LockCallback) (void* userData,Output& output);
91 
92 				/**
93 				* Surface unlock callback prototype.
94 				*
95 				* Called when the core has finished rendering to the surface and a previous locked was made.
96 				*
97 				* @param userData optional user data
98 				* @param output object to this class
99 				*/
100 				typedef void (NST_CALLBACK *UnlockCallback) (void* userData,Output& output);
101 
102 				/**
103 				* Surface lock callback manager.
104 				*
105 				* Static object used for adding the user defined callback.
106 				*/
107 				static Locker lockCallback;
108 
109 				/**
110 				* Surface unlock callback manager.
111 				*
112 				* Static object used for adding the user defined callback.
113 				*/
114 				static Unlocker unlockCallback;
115 			};
116 
117 			/**
118 			* Surface lock callback invoker.
119 			*
120 			* Used internally by the core.
121 			*/
122 			struct Output::Locker : UserCallback<Output::LockCallback>
123 			{
operator ()Nes::Core::Video::Output::Locker124 				bool operator () (Output& output) const
125 				{
126 					return (!function || function( userdata, output )) && output.pixels && output.pitch;
127 				}
128 			};
129 
130 			/**
131 			* Surface unlock callback invoker.
132 			*
133 			* Used internally by the core.
134 			*/
135 			struct Output::Unlocker : UserCallback<Output::UnlockCallback>
136 			{
operator ()Nes::Core::Video::Output::Unlocker137 				void operator () (Output& output) const
138 				{
139 					if (function)
140 						function( userdata, output );
141 				}
142 			};
143 		}
144 	}
145 
146 	namespace Api
147 	{
148 		/**
149 		* Video interface.
150 		*/
151 		class Video : public Base
152 		{
153 		public:
154 
155 			/**
156 			* Interface constructor.
157 			*
158 			* @param instance emulator instance
159 			*/
160 			template<typename T>
Video(T & instance)161 			Video(T& instance)
162 			: Base(instance) {}
163 
164 			/**
165 			* Video output context.
166 			*/
167 			typedef Core::Video::Output Output;
168 
169 			enum
170 			{
171 				MIN_BRIGHTNESS                  = -100,
172 				DEFAULT_BRIGHTNESS              =    0,
173 				MAX_BRIGHTNESS                  = +100,
174 				MIN_SATURATION                  = -100,
175 				DEFAULT_SATURATION              =    0,
176 				DEFAULT_SATURATION_COMP         =    0,
177 				DEFAULT_SATURATION_SVIDEO       =    0,
178 		                DEFAULT_SATURATION_RGB          =    0,
179 		                DEFAULT_SATURATION_MONO         =  -100,
180 				MAX_SATURATION                  = +100,
181 				MIN_CONTRAST                    = -100,
182 				DEFAULT_CONTRAST                =    0,
183 				MAX_CONTRAST                    = +100,
184 				MIN_SHARPNESS                   = -100,
185 				DEFAULT_SHARPNESS_COMP          =    0,
186 				DEFAULT_SHARPNESS_SVIDEO        =   20,
187 				DEFAULT_SHARPNESS_RGB           =   20,
188 				DEFAULT_SHARPNESS_MONO          =    0,
189 				MAX_SHARPNESS                   = +100,
190 				MIN_COLOR_RESOLUTION            = -100,
191 				DEFAULT_COLOR_RESOLUTION_COMP   =    0,
192 				DEFAULT_COLOR_RESOLUTION_SVIDEO =   20,
193 				DEFAULT_COLOR_RESOLUTION_RGB    =   70,
194 				DEFAULT_COLOR_RESOLUTION_MONO   =    0,
195 				MAX_COLOR_RESOLUTION            = +100,
196 				MIN_COLOR_BLEED                 = -100,
197 				DEFAULT_COLOR_BLEED_COMP        =    0,
198 				DEFAULT_COLOR_BLEED_SVIDEO      =    0,
199 				DEFAULT_COLOR_BLEED_RGB         = -100,
200 				DEFAULT_COLOR_BLEED_MONO        = 0,
201 				MAX_COLOR_BLEED                 = +100,
202 				MIN_COLOR_ARTIFACTS             = -100,
203 				DEFAULT_COLOR_ARTIFACTS_COMP    =    0,
204 				DEFAULT_COLOR_ARTIFACTS_SVIDEO  = -100,
205 				DEFAULT_COLOR_ARTIFACTS_RGB     = -100,
206 				DEFAULT_COLOR_ARTIFACTS_MONO    =   5,
207 				MAX_COLOR_ARTIFACTS             = +100,
208 				MIN_COLOR_FRINGING              = -100,
209 				DEFAULT_COLOR_FRINGING_COMP     =    0,
210 				DEFAULT_COLOR_FRINGING_SVIDEO   = -100,
211 				DEFAULT_COLOR_FRINGING_RGB      = -100,
212 				DEFAULT_COLOR_FRINGING_MONO     =   5,
213 				MAX_COLOR_FRINGING              = +100,
214 				MIN_HUE                         =  -45,
215 				DEFAULT_HUE                     =    0,
216 				MAX_HUE                         =  +45
217 			};
218 
219 			/**
220 			* Allows the PPU to render more than eight sprites per line.
221 			*
222 			* @param state true to allow it, default is false
223 			* @return result code
224 			*/
225 			Result EnableUnlimSprites(bool state) throw();
226 
227 			/**
228 			* Checks if the PPU sprite software extension is enabled.
229 			*
230 			* @return true if enabled
231 			*/
232 			bool AreUnlimSpritesEnabled() const throw();
233 
234 			/**
235 			* Returns the current brightness.
236 			*
237 			* @return brightness value in the range -100 to 100
238 			*/
239 			int GetBrightness() const throw();
240 
241 			/**
242 			* Returns the current saturation.
243 			*
244 			* @return saturation value in the range -100 to 100
245 			*/
246 			int GetSaturation() const throw();
247 
248 			/**
249 			* Returns the current contrast.
250 			*
251 			* @return contrast value in the range -100 to 100
252 			*/
253 			int GetContrast() const throw();
254 
255 			/**
256 			* Returns the current sharpness for the NTSC filter.
257 			*
258 			* @return sharpness value in the range -100 to 100
259 			*/
260 			int GetSharpness() const throw();
261 
262 			/**
263 			* Returns the current color resolution for the NTSC filter.
264 			*
265 			* @return color resolution value in the range -100 to 100
266 			*/
267 			int GetColorResolution() const throw();
268 
269 			/**
270 			* Returns the current color bleed for the NTSC filter.
271 			*
272 			* @return color bleed value in the range -100 to 100
273 			*/
274 			int GetColorBleed() const throw();
275 
276 			/**
277 			* Returns the current color artifacts for the NTSC filter.
278 			*
279 			* @return color artifacts value in the range -100 to 100
280 			*/
281 			int GetColorArtifacts() const throw();
282 
283 			/**
284 			* Returns the current color fringing for the NTSC filter.
285 			*
286 			* @return color fringing value in the range -100 to 100
287 			*/
288 			int GetColorFringing() const throw();
289 
290 			/**
291 			* Returns the current hue.
292 			*
293 			* @return hue value in the range -45 to 45
294 			*/
295 			int GetHue() const throw();
296 
297 			/**
298 			* Returns whenever the xbr filters blends pixels or not
299 			*/
300 			bool GetBlend() const throw();
301 
302 			/**
303 			* Returns how the xbr filters rounds corners
304 			*/
305 			int GetCornerRounding() const throw();
306 
307 			/**
308 			* Sets the brightness.
309 			*
310 			* @param value brightness in the range -100 to 100, default is 0
311 			* @return result code
312 			*/
313 			Result SetBrightness(int value) throw();
314 
315 			/**
316 			* Sets the saturation.
317 			*
318 			* @param value saturation in the range -100 to 100, default is 0
319 			* @return result code
320 			*/
321 			Result SetSaturation(int value) throw();
322 
323 			/**
324 			* Sets the contrast.
325 			*
326 			* @param value contrast in the range -100 to 100, default is 0
327 			* @return result code
328 			*/
329 			Result SetContrast(int value) throw();
330 
331 			/**
332 			* Sets the sharpness for the NTSC filter.
333 			*
334 			* @param value sharpness in the range -100 to 100, default is 0
335 			* @return result code
336 			*/
337 			Result SetSharpness(int value) throw();
338 
339 			/**
340 			* Sets the color resolution for the NTSC filter.
341 			*
342 			* @param value color resolution in the range -100 to 100, default is 0
343 			* @return result code
344 			*/
345 			Result SetColorResolution(int value) throw();
346 
347 			/**
348 			* Sets the color bleed for the NTSC filter.
349 			*
350 			* @param value color bleed in the range -100 to 100, default is 0
351 			* @return result code
352 			*/
353 			Result SetColorBleed(int value) throw();
354 
355 			/**
356 			* Sets the color artifacts for the NTSC filter.
357 			*
358 			* @param value color artifacts in the range -100 to 100, default is 0
359 			* @return result code
360 			*/
361 			Result SetColorArtifacts(int value) throw();
362 
363 			/**
364 			* Sets the color fringing for the NTSC filter.
365 			*
366 			* @param value fringing in the range -100 to 100, default is 0
367 			* @return result code
368 			*/
369 			Result SetColorFringing(int value) throw();
370 
371 			/**
372 			* Sets the hue.
373 			*
374 			* @param value hue in the range -45 to 45, default is 0
375 			* @return result code
376 			*/
377 			Result SetHue(int value) throw();
378 
379 			/**
380 			 * Sets whenever the xbr filters is to blend pixels or not.
381 			 */
382 			Result SetBlend(bool value) throw();
383 
384 			/**
385 			 * Sets whenever the xbr filters is to round corners or not.
386 			 */
387 			Result SetCornerRounding(int value) throw();
388 
389 			/**
390 			 * Quickfix for blank screen issue.
391 		     */
392 			void ClearFilterUpdateFlag() throw();
393 
394 			/**
395 			* Enables field merging for the NTSC filter.
396 			*
397 			* @param state true to enable
398 			*/
399 			void EnableFieldMerging(bool state) throw();
400 
401 			/**
402 			* Checks if NTSC filter field merging is enabled.
403 			*
404 			* @return true if enabled
405 			*/
406 			bool IsFieldMergingEnabled() const throw();
407 
408 			/**
409 			* Performs a manual blit to the video output object.
410 			*
411 			* The core calls this method internally for each frame.
412 			*
413 			* @param output video output object to blit to
414 			* @return result code
415 			*/
416 			Result Blit(Output& output) throw();
417 
418 			/**
419 			* YUV decoder presets.
420 			*/
421 			enum DecoderPreset
422 			{
423 				/**
424 				* Canonical (default)
425 				*/
426 				DECODER_CANONICAL,
427 				/**
428 				* Consumer
429 				*/
430 				DECODER_CONSUMER,
431 				/**
432 				* Alternative
433 				*/
434 				DECODER_ALTERNATIVE
435 			};
436 
437 			/**
438 			* YUV decoder context.
439 			*/
440 			struct Decoder
441 			{
442 				/**
443 				* Constructor.
444 				*
445 				* @param preset preset, canonical by default
446 				*/
447 				Decoder(DecoderPreset preset=DECODER_CANONICAL) throw();
448 
449 				/**
450 				* Tests for equality.
451 				*
452 				* @param decoder object to compare
453 				* @return true if equal
454 				*/
455 				bool operator == (const Decoder& decoder) const throw();
456 
457 				/**
458 				* Tests for non-equality.
459 				*
460 				* @param decoder object to compare
461 				* @return true if non-equal
462 				*/
463 				bool operator != (const Decoder& decoder) const throw();
464 
465 				enum
466 				{
467 					AXIS_RY,
468 					AXIS_GY,
469 					AXIS_BY,
470 					NUM_AXES
471 				};
472 
473 				struct
474 				{
475 					float gain;
476 					uint angle;
477 				}   axes[NUM_AXES];
478 
479 				bool boostYellow;
480 			};
481 
482 			/**
483 			* Sets the YUV decoder.
484 			*
485 			* @param decoder decoder
486 			* @return result code
487 			*/
488 			Result SetDecoder(const Decoder& decoder) throw();
489 
490 			/**
491 			* Returns the current YUV decoder.
492 			*
493 			* @return current decoder
494 			*/
495 			const Decoder& GetDecoder() const throw();
496 
497 			/**
498 			* Palette interface.
499 			*/
500 			class Palette
501 			{
502 				Core::Machine& emulator;
503 
504 			public:
505 
506 				/**
507 				* Interface constructor
508 				*
509 				* @param instance emulator instance
510 				*/
Palette(Core::Machine & instance)511 				Palette(Core::Machine& instance)
512 				: emulator(instance) {}
513 
514 				enum
515 				{
516 					NUM_ENTRIES = 64,
517 					NUM_ENTRIES_EXT = 512
518 				};
519 
520 				/**
521 				* Custom palette types.
522 				*/
523 				enum CustomType
524 				{
525 					/**
526 					* Standard palette. 64 colors.
527 					*/
528 					STD_PALETTE = NUM_ENTRIES,
529 					/**
530 					* Extended palette. 512 colors with emphasis included in it.
531 					*/
532 					EXT_PALETTE = NUM_ENTRIES_EXT
533 				};
534 
535 				/**
536 				* Palette modes
537 				*/
538 				enum Mode
539 				{
540 					/**
541 					* YUV (default)
542 					*/
543 					MODE_YUV,
544 					/**
545 					* RGB
546 					*/
547 					MODE_RGB,
548 					/**
549 					* Custom
550 					*/
551 					MODE_CUSTOM
552 				};
553 
554 				/**
555 				* RGB colors.
556 				*/
557 				typedef const uchar (*Colors)[3];
558 
559 				/**
560 				* Returns the current palette mode.
561 				*
562 				* @return current mode
563 				*/
564 				Mode GetMode() const throw();
565 
566 				/**
567 				* Returns the default palette mode.
568 				*
569 				* @return default palette mode
570 				*/
571 				Mode GetDefaultMode() const throw();
572 
573 				/**
574 				* Sets the custom palette.
575 				*
576 				* @param colors RGB color data
577 				* @param type custom palette type
578 				*/
579 				Result SetCustom(Colors colors,CustomType type=STD_PALETTE) throw();
580 
581 				/**
582 				* Returns the custom palette.
583 				*
584 				* @param colors RGB colors to be filled
585 				* @param type custom palette type
586 				* @return number of colors written
587 				*/
588 				uint GetCustom(uchar (*colors)[3],CustomType type) const throw();
589 
590 				/**
591 				* Resets the custom palette.
592 				*/
593 				void ResetCustom() throw();
594 
595 				/**
596 				* Returns the custom palette type.
597 				*
598 				* @return custom palette type
599 				*/
600 				CustomType GetCustomType() const throw();
601 
602 				/**
603 				* Return the current palette colors.
604 				*
605 				* @return palette colors
606 				*/
607 				Colors GetColors() const throw();
608 
609 				/**
610 				* Sets the palette mode.
611 				*
612 				* @param mode palette mode
613 				* @return result code
614 				*/
615 				Result SetMode(Mode mode) throw();
616 			};
617 
618 			/**
619 			* Returns the palette interface.
620 			*
621 			* @return palette interface
622 			*/
GetPalette()623 			Palette GetPalette()
624 			{
625 				return emulator;
626 			}
627 
628 			/**
629 			* Render state context.
630 			*/
631 			struct RenderState
632 			{
633 				RenderState() throw();
634 
635 				/**
636 				* Pixel context.
637 				*/
638 				struct Bits
639 				{
640 					/**
641 					* RGB bit mask.
642 					*/
643 					struct Mask
644 					{
645 						ulong r,g,b;
646 					};
647 
648 					/**
649 					* RGB bit mask.
650 					*/
651 					Mask mask;
652 
653 					/**
654 					* Bits per pixel.
655 					*/
656 					uint count;
657 				};
658 
659 				/**
660 				* Pixel context.
661 				*/
662 				Bits bits;
663 
664 				/**
665 				* Screen width.
666 				*/
667 				ushort width;
668 
669 				/**
670 				* Screen height.
671 				*/
672 				ushort height;
673 
674 				/**
675 				* Video Filter.
676 				*/
677 				enum Filter
678 				{
679 					/**
680 					* No filter (default).
681 					*/
682 					FILTER_NONE,
683 					/**
684 					* NTSC filter.
685 					*/
686 					FILTER_NTSC
687 				#ifndef NST_NO_SCALEX
688 					,
689 					/**
690 					* Scale2x filter.
691 					*/
692 					FILTER_SCALE2X,
693 					/**
694 					* Scale3x filter.
695 					*/
696 					FILTER_SCALE3X
697 				#endif
698 				#ifndef NST_NO_HQ2X
699 					,
700 					/**
701 					* Hq2x filter.
702 					*/
703 					FILTER_HQ2X,
704 					/**
705 					* Hq3x filter.
706 					*/
707 					FILTER_HQ3X,
708 					/**
709 					* Hq4x filter.
710 					*/
711 					FILTER_HQ4X
712 				#endif
713 				#ifndef NST_NO_2XSAI
714 					,
715 					/**
716 					* 2xSaI filter.
717 					*/
718 					FILTER_2XSAI
719 				#endif
720 				#ifndef NST_NO_XBR
721 					,
722 					FILTER_2XBR,
723 					FILTER_3XBR,
724 					FILTER_4XBR
725 				#endif
726 				};
727 
728 				/**
729 				* Scale factors.
730 				*/
731 				enum Scale
732 				{
733 					SCALE_NONE = 1
734 				#ifndef NST_NO_SCALEX
735 					,SCALE_SCALE2X = 2
736 					,SCALE_SCALE3X = 3
737 				#endif
738 				#ifndef NST_NO_HQ2X
739 					,SCALE_HQ2X = 2
740 					,SCALE_HQ3X = 3
741 				#endif
742 				#ifndef NST_NO_2XSAI
743 					,SCALE_2XSAI = 2
744 				#endif
745 				};
746 
747 				/**
748 				* Filter.
749 				*/
750 				Filter filter;
751 			};
752 
753 			/**
754 			* Sets the render state.
755 			*
756 			* @param state render state to be set
757 			* @return result code
758 			*/
759 			Result SetRenderState(const RenderState& state) throw();
760 
761 			/**
762 			* Returns the current render state.
763 			*
764 			* @param state object to be filled
765 			* @return result code
766 			*/
767 			Result GetRenderState(RenderState& state) const throw();
768 		};
769 	}
770 }
771 
772 #if NST_MSVC >= 1200 || NST_ICC >= 810
773 #pragma warning( pop )
774 #endif
775 
776 #endif
777