RetroArch
snes_ntsc.h
Go to the documentation of this file.
1 /* SNES NTSC video filter */
2 
3 /* snes_ntsc 0.2.2 */
4 #ifndef SNES_NTSC_H
5 #define SNES_NTSC_H
6 
7 #include "snes_ntsc_config.h"
8 
9 #ifdef __cplusplus
10  extern "C" {
11 #endif
12 
13 /* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
14 in parenthesis and should remain fairly stable in future versions. */
15 typedef struct snes_ntsc_setup_t
16 {
17  /* Basic parameters */
18  double hue; /* -1 = -180 degrees +1 = +180 degrees */
19  double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
20  double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
21  double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
22  double sharpness; /* edge contrast enhancement/blurring */
23 
24  /* Advanced parameters */
25  double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
26  double resolution; /* image resolution */
27  double artifacts; /* artifacts caused by color changes */
28  double fringing; /* color artifacts caused by brightness changes */
29  double bleed; /* color bleed (color resolution reduction) */
30  int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */
31  float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
32 
33  unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */
35 
36 /* Video format presets */
37 extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */
38 extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */
39 extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */
40 extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */
41 
42 /* Initializes and adjusts parameters. Can be called multiple times on the same
43 snes_ntsc_t object. Can pass NULL for either parameter. */
44 typedef struct snes_ntsc_t snes_ntsc_t;
46 
47 /* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT
48 and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB.
49 In_row_width is the number of pixels to get to the next input row. Out_pitch
50 is the number of *bytes* to get to the next output row. */
51 void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
52  long in_row_width, int burst_phase, int in_width, int in_height,
53  void* rgb_out, long out_pitch, int first, int last);
54 
55 void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
56  long in_row_width, int burst_phase, int in_width, int in_height,
57  void* rgb_out, long out_pitch, int first, int last);
58 
59 /* Number of output pixels written by low-res blitter for given input width. Width
60 might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded
61 value. Guaranteed not to round 256 down at all. */
62 #define SNES_NTSC_OUT_WIDTH( in_width ) \
63  ((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk)
64 
65 /* Number of low-res input pixels that will fit within given output width. Might be
66 rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded
67 value. */
68 #define SNES_NTSC_IN_WIDTH( out_width ) \
69  (((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1)
70 
71 
72 /* Interface for user-defined custom blitters */
73 
74 enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */
75 enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */
76 enum { snes_ntsc_black = 0 }; /* palette index for black */
77 enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */
78 
79 /* Begins outputting row and starts three pixels. First pixel will be cut off a bit.
80 Use snes_ntsc_black for unused pixels. Declares variables, so must be before first
81 statement in a block (unless you're using C++). */
82 #define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \
83  char const* ktable = \
84  (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\
85  SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable )
86 
87 /* Begins input pixel */
88 #define SNES_NTSC_COLOR_IN( index, color ) \
89  SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable )
90 
91 /* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0:
92 24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB)
93 16: RRRRRGGG GGGBBBBB (5-6-5 RGB)
94 15: RRRRRGG GGGBBBBB (5-5-5 RGB)
95 14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format)
96  0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */
97 #define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \
98  SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 )
99 
100 /* Hires equivalents */
101 #define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \
102  char const* ktable = \
103  (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\
104  unsigned const snes_ntsc_pixel1_ = (pixel1);\
105  snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\
106  unsigned const snes_ntsc_pixel2_ = (pixel2);\
107  snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\
108  unsigned const snes_ntsc_pixel3_ = (pixel3);\
109  snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\
110  unsigned const snes_ntsc_pixel4_ = (pixel4);\
111  snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\
112  unsigned const snes_ntsc_pixel5_ = (pixel5);\
113  snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\
114  snes_ntsc_rgb_t const* kernel0 = kernel1;\
115  snes_ntsc_rgb_t const* kernelx0;\
116  snes_ntsc_rgb_t const* kernelx1 = kernel1;\
117  snes_ntsc_rgb_t const* kernelx2 = kernel1;\
118  snes_ntsc_rgb_t const* kernelx3 = kernel1;\
119  snes_ntsc_rgb_t const* kernelx4 = kernel1;\
120  snes_ntsc_rgb_t const* kernelx5 = kernel1
121 
122 #define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\
123  snes_ntsc_rgb_t raw_ =\
124  kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\
125  kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\
126  kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\
127  kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\
128  SNES_NTSC_CLAMP_( raw_, 0 );\
129  SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\
130 }
131 
132 
133 /* private */
134 enum { snes_ntsc_entry_size = 128 };
135 enum { snes_ntsc_palette_size = 0x2000 };
136 typedef unsigned long snes_ntsc_rgb_t;
137 struct snes_ntsc_t {
139 };
141 
142 #define SNES_NTSC_RGB16( ktable, n ) \
143  (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \
144  (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t)))
145 
146 #define SNES_NTSC_BGR15( ktable, n ) \
147  (snes_ntsc_rgb_t const*) (ktable + ((n << 9 & 0x3C00) | (n & 0x03E0) | (n >> 10 & 0x001E)) * \
148  (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t)))
149 
150 /* common 3->7 ntsc macros */
151 #define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \
152  unsigned const snes_ntsc_pixel0_ = (pixel0);\
153  snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\
154  unsigned const snes_ntsc_pixel1_ = (pixel1);\
155  snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\
156  unsigned const snes_ntsc_pixel2_ = (pixel2);\
157  snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\
158  snes_ntsc_rgb_t const* kernelx0;\
159  snes_ntsc_rgb_t const* kernelx1 = kernel0;\
160  snes_ntsc_rgb_t const* kernelx2 = kernel0
161 
162 #define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\
163  snes_ntsc_rgb_t raw_ =\
164  kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\
165  kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\
166  SNES_NTSC_CLAMP_( raw_, shift );\
167  SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\
168 }
169 
170 /* common ntsc macros */
171 #define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1))
172 #define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2)
173 #define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101)
174 #define SNES_NTSC_CLAMP_( io, shift ) {\
175  snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\
176  snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\
177  io |= clamp;\
178  clamp -= sub;\
179  io &= clamp;\
180 }
181 
182 #define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\
183  unsigned color_;\
184  kernelx##index = kernel##index;\
185  kernel##index = (color_ = (color), ENTRY( table, color_ ));\
186 }
187 
188 /* x is always zero except in snes_ntsc library */
189 /* original routine */
190 #define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
191  if ( bits == 16 )\
192  rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
193  if ( bits == 24 || bits == 32 )\
194  rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\
195  if ( bits == 15 )\
196  rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\
197  if ( bits == 14 )\
198  rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\
199  if ( bits == 0 )\
200  rgb_out = raw_ << x;\
201 }
202 
203 #ifdef __cplusplus
204  }
205 #endif
206 
207 #endif
Definition: snes_ntsc.h:135
snes_ntsc_setup_t const snes_ntsc_composite
Definition: snes_ntsc.c:19
const GLint * first
Definition: glext.h:6478
unsigned long snes_ntsc_rgb_t
Definition: snes_ntsc.h:136
void snes_ntsc_blit_hires(snes_ntsc_t const *ntsc, SNES_NTSC_IN_T const *input, long in_row_width, int burst_phase, int in_width, int in_height, void *rgb_out, long out_pitch, int first, int last)
Definition: snes_ntsc.c:174
Definition: snes_ntsc.h:77
#define SNES_NTSC_IN_T
Definition: snes_ntsc_config.h:17
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:6296
double saturation
Definition: snes_ntsc.h:19
double artifacts
Definition: snes_ntsc.h:27
double gamma
Definition: snes_ntsc.h:25
snes_ntsc_setup_t const snes_ntsc_rgb
Definition: snes_ntsc.c:21
Definition: snes_ntsc.h:74
GLenum GLenum GLenum input
Definition: glext.h:9938
Definition: snes_ntsc.h:15
double hue
Definition: snes_ntsc.h:18
double resolution
Definition: snes_ntsc.h:26
snes_ntsc_setup_t const snes_ntsc_monochrome
Definition: snes_ntsc.c:18
Definition: snes_ntsc.h:134
void snes_ntsc_init(snes_ntsc_t *ntsc, snes_ntsc_setup_t const *setup)
Definition: snes_ntsc.c:80
double fringing
Definition: snes_ntsc.h:28
float const * decoder_matrix
Definition: snes_ntsc.h:31
Definition: snes_ntsc.h:75
void snes_ntsc_blit(snes_ntsc_t const *ntsc, SNES_NTSC_IN_T const *input, long in_row_width, int burst_phase, int in_width, int in_height, void *rgb_out, long out_pitch, int first, int last)
Definition: snes_ntsc.c:121
Definition: snes_ntsc.h:137
Definition: snes_ntsc.h:76
struct snes_ntsc_setup_t snes_ntsc_setup_t
double sharpness
Definition: snes_ntsc.h:22
double contrast
Definition: snes_ntsc.h:20
Definition: snes_ntsc.h:140
snes_ntsc_setup_t const snes_ntsc_svideo
Definition: snes_ntsc.c:20
unsigned long const * bsnes_colortbl
Definition: snes_ntsc.h:33
int merge_fields
Definition: snes_ntsc.h:30
double bleed
Definition: snes_ntsc.h:29
Definition: setup.py:1
double brightness
Definition: snes_ntsc.h:21