-
Notifications
You must be signed in to change notification settings - Fork 0
/
sms_ntsc.c
145 lines (117 loc) · 5 KB
/
sms_ntsc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* sms_ntsc 0.2.3. http://www.slack.net/~ant/ */
#include "sms_ntsc.h"
/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
sms_ntsc_setup_t const sms_ntsc_monochrome = { 0,-1, 0, 0,.2, 0, .2,-.2,-.2,-1, 0, 0 };
sms_ntsc_setup_t const sms_ntsc_composite = { 0, 0, 0, 0, 0, 0,.25, 0, 0, 0, 0, 0 };
sms_ntsc_setup_t const sms_ntsc_svideo = { 0, 0, 0, 0, 0, 0,.25, -1, -1, 0, 0, 0 };
sms_ntsc_setup_t const sms_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.70, -1, -1,-1, 0, 0 };
#define alignment_count 3
#define burst_count 1
#define rescale_in 8
#define rescale_out 7
#define artifacts_mid 0.4f
#define artifacts_max 1.2f
#define fringing_mid 0.8f
#define std_decoder_hue 0
#define gamma_size 16
#include "sms_ntsc_impl.h"
/* 3 input pixels -> 8 composite samples */
pixel_info_t const sms_ntsc_pixels [alignment_count] = {
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } },
{ PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } },
{ PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } },
};
static void correct_errors( sms_ntsc_rgb_t color, sms_ntsc_rgb_t* out )
{
unsigned i;
for ( i = 0; i < rgb_kernel_size / 2; i++ )
{
sms_ntsc_rgb_t error = color -
out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] -
out [i + 7] - out [i + 5 +14] - out [i + 3 +28];
CORRECT_ERROR( i + 3 + 28 );
}
}
void sms_ntsc_init( sms_ntsc_t* ntsc, sms_ntsc_setup_t const* setup )
{
int entry;
init_t impl;
if ( !setup )
setup = &sms_ntsc_composite;
init( &impl, setup );
for ( entry = 0; entry < sms_ntsc_palette_size; entry++ )
{
float bb = impl.to_float [entry >> 8 & 0x0F];
float gg = impl.to_float [entry >> 4 & 0x0F];
float rr = impl.to_float [entry & 0x0F];
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
sms_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
if ( setup->palette_out )
RGB_PALETTE_OUT( rgb, &setup->palette_out [entry * 3] );
if ( ntsc )
{
gen_kernel( &impl, y, i, q, ntsc->table [entry] );
correct_errors( rgb, ntsc->table [entry] );
}
}
}
#ifndef SMS_NTSC_NO_BLITTERS
void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* input, long in_row_width,
int in_width, int in_height, void* rgb_out, long out_pitch )
{
int const chunk_count = in_width / sms_ntsc_in_chunk;
/* handle extra 0, 1, or 2 pixels by placing them at beginning of row */
int const in_extra = in_width - chunk_count * sms_ntsc_in_chunk;
unsigned const extra2 = (unsigned) -(in_extra >> 1 & 1); /* (unsigned) -1 = ~0 */
unsigned const extra1 = (unsigned) -(in_extra & 1) | extra2;
for ( ; in_height; --in_height )
{
SMS_NTSC_IN_T const* line_in = input;
SMS_NTSC_BEGIN_ROW( ntsc, sms_ntsc_black,
(SMS_NTSC_ADJ_IN( line_in [0] )) & extra2,
(SMS_NTSC_ADJ_IN( line_in [extra2 & 1] )) & extra1 );
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*) rgb_out;
int n;
line_in += in_extra;
for ( n = chunk_count; n; --n )
{
/* order of input and output pixels must not be altered */
SMS_NTSC_COLOR_IN( 0, ntsc, SMS_NTSC_ADJ_IN( line_in [0] ) );
SMS_NTSC_RGB_OUT( 0, line_out [0], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 1, line_out [1], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_COLOR_IN( 1, ntsc, SMS_NTSC_ADJ_IN( line_in [1] ) );
SMS_NTSC_RGB_OUT( 2, line_out [2], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 3, line_out [3], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_COLOR_IN( 2, ntsc, SMS_NTSC_ADJ_IN( line_in [2] ) );
SMS_NTSC_RGB_OUT( 4, line_out [4], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 5, line_out [5], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 6, line_out [6], SMS_NTSC_OUT_DEPTH );
line_in += 3;
line_out += 7;
}
/* finish final pixels */
SMS_NTSC_COLOR_IN( 0, ntsc, sms_ntsc_black );
SMS_NTSC_RGB_OUT( 0, line_out [0], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 1, line_out [1], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_COLOR_IN( 1, ntsc, sms_ntsc_black );
SMS_NTSC_RGB_OUT( 2, line_out [2], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 3, line_out [3], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_COLOR_IN( 2, ntsc, sms_ntsc_black );
SMS_NTSC_RGB_OUT( 4, line_out [4], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 5, line_out [5], SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 6, line_out [6], SMS_NTSC_OUT_DEPTH );
input += in_row_width;
rgb_out = (char*) rgb_out + out_pitch;
}
}
#endif