1 /*
2 * render1x1ntsc.c - 1x1 NTSC renderers
3 *
4 * Written by
5 * groepaz <groepaz@gmx.net> based on the pal renderers written by
6 * John Selck <graham@cruise.de>
7 *
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #include "vice.h"
29
30 #include "render1x1ntsc.h"
31 #include "types.h"
32 #include "video-color.h"
33
34 /*
35 right now this is basically the PAL renderer without delay line emulation
36 */
37
38 /*
39 YIQ->RGB (Sony CXA2025AS US decoder matrix)
40
41 R = Y + (1.630 * I + 0.317 * Q)
42 G = Y - (0.378 * I + 0.466 * Q)
43 B = Y - (1.089 * I - 1.677 * Q)
44 */
45 static inline
yuv_to_rgb(int32_t y,int32_t u,int32_t v,int32_t * red,int32_t * grn,int32_t * blu)46 void yuv_to_rgb(int32_t y, int32_t u, int32_t v,
47 int32_t *red, int32_t *grn, int32_t *blu)
48 {
49 *red = (y + ((209 * u + 41 * v) >> 7)) >> 15;
50 *grn = (y - (( 48 * u + 69 * v) >> 7)) >> 15;
51 *blu = (y - ((139 * u - 215 * v) >> 7)) >> 15;
52 }
53
54 static inline
store_pixel_2(uint8_t * trg,int32_t y1,int32_t u1,int32_t v1,int32_t y2,int32_t u2,int32_t v2)55 void store_pixel_2(uint8_t *trg, int32_t y1, int32_t u1, int32_t v1, int32_t y2, int32_t u2, int32_t v2)
56 {
57 uint16_t *tmp;
58 int32_t red;
59 int32_t grn;
60 int32_t blu;
61
62 yuv_to_rgb(y1, u1, v1, &red, &grn, &blu);
63 tmp = (uint16_t *) trg;
64 tmp[0] = (uint16_t) (gamma_red[256 + red] | gamma_grn[256 + grn] | gamma_blu[256 + blu]);
65
66 yuv_to_rgb(y2, u2, v2, &red, &grn, &blu);
67 tmp[1] = (uint16_t) (gamma_red[256 + red] | gamma_grn[256 + grn] | gamma_blu[256 + blu]);
68 }
69
70 static inline
store_pixel_3(uint8_t * trg,int32_t y1,int32_t u1,int32_t v1,int32_t y2,int32_t u2,int32_t v2)71 void store_pixel_3(uint8_t *trg, int32_t y1, int32_t u1, int32_t v1, int32_t y2, int32_t u2, int32_t v2)
72 {
73 uint32_t tmp;
74 int32_t red;
75 int32_t grn;
76 int32_t blu;
77
78 yuv_to_rgb(y1, u1, v1, &red, &grn, &blu);
79 tmp = gamma_red[256 + red] | gamma_grn[256 + grn] | gamma_blu[256 + blu];
80 trg[0] = (uint8_t) tmp;
81 tmp >>= 8;
82 trg[1] = (uint8_t) tmp;
83 tmp >>= 8;
84 trg[2] = (uint8_t) tmp;
85
86 yuv_to_rgb(y2, u2, v2, &red, &grn, &blu);
87 tmp = gamma_red[256 + red] | gamma_grn[256 + grn] | gamma_blu[256 + blu];
88 trg[3] = (uint8_t) tmp;
89 tmp >>= 8;
90 trg[4] = (uint8_t) tmp;
91 tmp >>= 8;
92 trg[5] = (uint8_t) tmp;
93 }
94
95 static inline
store_pixel_4(uint8_t * trg,int32_t y1,int32_t u1,int32_t v1,int32_t y2,int32_t u2,int32_t v2)96 void store_pixel_4(uint8_t *trg, int32_t y1, int32_t u1, int32_t v1, int32_t y2, int32_t u2, int32_t v2)
97 {
98 uint32_t *tmp;
99 int32_t red;
100 int32_t grn;
101 int32_t blu;
102
103 yuv_to_rgb(y1, u1, v1, &red, &grn, &blu);
104 tmp = (uint32_t *) trg;
105 tmp[0] = gamma_red[256 + red] | gamma_grn[256 + grn] | gamma_blu[256 + blu] | alpha;
106
107 yuv_to_rgb(y2, u2, v2, &red, &grn, &blu);
108 tmp[1] = gamma_red[256 + red] | gamma_grn[256 + grn] | gamma_blu[256 + blu] | alpha;
109 }
110
111 static inline
store_pixel_UYVY(uint8_t * trg,int32_t y1_,int32_t u1,int32_t v1,int32_t y2_,int32_t u2,int32_t v2)112 void store_pixel_UYVY(uint8_t *trg, int32_t y1_, int32_t u1, int32_t v1, int32_t y2_, int32_t u2, int32_t v2)
113 {
114 uint8_t y1 = (uint8_t)((y1_ >> 16) & 0xFFu);
115 uint8_t y2 = (uint8_t)((y2_ >> 16) & 0xFFu);
116
117 u1 = (u1 + u2) >> 17;
118 v1 = (v1 + v2) >> 17;
119
120 trg[0] = (uint8_t)(u1 + 128);
121 trg[1] = y1;
122 trg[2] = (uint8_t)(v1 + 128);
123 trg[3] = y2;
124 }
125
126 static inline
store_pixel_YUY2(uint8_t * trg,int32_t y1_,int32_t u1,int32_t v1,int32_t y2_,int32_t u2,int32_t v2)127 void store_pixel_YUY2(uint8_t *trg, int32_t y1_, int32_t u1, int32_t v1, int32_t y2_, int32_t u2, int32_t v2)
128 {
129 uint8_t y1 = (uint8_t)((y1_ >> 16) & 0xFFu);
130 uint8_t y2 = (uint8_t)((y2_ >> 16) & 0xFFu);
131
132 u1 = (u1 + u2) >> 17;
133 v1 = (v1 + v2) >> 17;
134
135 trg[0] = y1;
136 trg[1] = (uint8_t)(u1 + 128);
137 trg[2] = y2;
138 trg[3] = (uint8_t)(v1 + 128);
139 }
140
141 static inline
store_pixel_YVYU(uint8_t * trg,int32_t y1_,int32_t u1,int32_t v1,int32_t y2_,int32_t u2,int32_t v2)142 void store_pixel_YVYU(uint8_t *trg, int32_t y1_, int32_t u1, int32_t v1, int32_t y2_, int32_t u2, int32_t v2)
143 {
144 uint8_t y1 = (uint8_t)((y1_ >> 16) & 0xFFu);
145 uint8_t y2 = (uint8_t)((y2_ >> 16) & 0xFFu);
146
147 u1 = (u1 + u2) >> 17;
148 v1 = (v1 + v2) >> 17;
149
150 trg[0] = y1;
151 trg[1] = (uint8_t)(v1 + 128);
152 trg[2] = y2;
153 trg[3] = (uint8_t)(u1 + 128);
154 }
155
156 /* NTSC 1x1 renderers */
157 static inline void
render_generic_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,unsigned int width,const unsigned int height,unsigned int xs,const unsigned int ys,unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht,const unsigned int pixelstride,void (* store_func)(uint8_t * trg,int32_t y1,int32_t u1,int32_t v1,int32_t y2,int32_t u2,int32_t v2),int yuvtarget)158 render_generic_1x1_ntsc(video_render_color_tables_t *color_tab, const uint8_t *src, uint8_t *trg,
159 unsigned int width, const unsigned int height,
160 unsigned int xs, const unsigned int ys,
161 unsigned int xt, const unsigned int yt,
162 const unsigned int pitchs, const unsigned int pitcht,
163 const unsigned int pixelstride,
164 void (*store_func)(uint8_t *trg,
165 int32_t y1, int32_t u1, int32_t v1,
166 int32_t y2, int32_t u2, int32_t v2),
167 int yuvtarget)
168 {
169 const int32_t *cbtable = color_tab->cbtable;
170 const int32_t *crtable = color_tab->crtable;
171 const int32_t *ytablel = color_tab->ytablel;
172 const int32_t *ytableh = color_tab->ytableh;
173 const uint8_t *tmpsrc;
174 uint8_t *tmptrg;
175 unsigned int x, y;
176 int32_t l1, l2, u1, u2, v1, v2, unew, vnew;
177 uint8_t cl0, cl1, cl2, cl3;
178 int off_flip;
179
180 /* ensure starting on even coords */
181 if ((xt & 1) && xs > 0) {
182 xs--;
183 xt--;
184 width++;
185 }
186
187 src = src + pitchs * ys + xs - 2;
188 trg = trg + pitcht * yt + (xt >> 1) * pixelstride;
189
190 width >>= 1;
191
192 off_flip = 1 << 6;
193
194 for (y = ys; y < height + ys; y++) {
195 tmpsrc = src;
196 tmptrg = trg;
197
198 cbtable = yuvtarget ? color_tab->cutable : color_tab->cbtable;
199 crtable = yuvtarget ? color_tab->cvtable : color_tab->crtable;
200
201 /* one scanline */
202 for (x = 0; x < width; x++) {
203 cl0 = tmpsrc[0];
204 cl1 = tmpsrc[1];
205 cl2 = tmpsrc[2];
206 cl3 = tmpsrc[3];
207 tmpsrc += 1;
208 l1 = ytablel[cl1] + ytableh[cl2] + ytablel[cl3];
209 unew = cbtable[cl0] + cbtable[cl1] + cbtable[cl2] + cbtable[cl3];
210 vnew = crtable[cl0] + crtable[cl1] + crtable[cl2] + crtable[cl3];
211 u1 = (unew) * off_flip;
212 v1 = (vnew) * off_flip;
213
214 cl0 = tmpsrc[0];
215 cl1 = tmpsrc[1];
216 cl2 = tmpsrc[2];
217 cl3 = tmpsrc[3];
218 tmpsrc += 1;
219 l2 = ytablel[cl1] + ytableh[cl2] + ytablel[cl3];
220 unew = cbtable[cl0] + cbtable[cl1] + cbtable[cl2] + cbtable[cl3];
221 vnew = crtable[cl0] + crtable[cl1] + crtable[cl2] + crtable[cl3];
222 u2 = (unew) * off_flip;
223 v2 = (vnew) * off_flip;
224
225 store_func(tmptrg, l1, u1, v1, l2, u2, v2);
226 tmptrg += pixelstride;
227 }
228
229 src += pitchs;
230 trg += pitcht;
231 }
232 }
233
234 void
render_UYVY_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,const unsigned int width,const unsigned int height,const unsigned int xs,const unsigned int ys,const unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht)235 render_UYVY_1x1_ntsc(video_render_color_tables_t *color_tab,
236 const uint8_t *src, uint8_t *trg,
237 const unsigned int width, const unsigned int height,
238 const unsigned int xs, const unsigned int ys,
239 const unsigned int xt, const unsigned int yt,
240 const unsigned int pitchs, const unsigned int pitcht)
241 {
242 render_generic_1x1_ntsc(color_tab, src, trg, width, height, xs, ys, xt, yt,
243 pitchs, pitcht,
244 4, store_pixel_UYVY, 1);
245 }
246
247 void
render_YUY2_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,const unsigned int width,const unsigned int height,const unsigned int xs,const unsigned int ys,const unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht)248 render_YUY2_1x1_ntsc(video_render_color_tables_t *color_tab,
249 const uint8_t *src, uint8_t *trg,
250 const unsigned int width, const unsigned int height,
251 const unsigned int xs, const unsigned int ys,
252 const unsigned int xt, const unsigned int yt,
253 const unsigned int pitchs, const unsigned int pitcht)
254 {
255 render_generic_1x1_ntsc(color_tab, src, trg, width, height, xs, ys, xt, yt,
256 pitchs, pitcht,
257 4, store_pixel_YUY2, 1);
258 }
259
260 void
render_YVYU_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,const unsigned int width,const unsigned int height,const unsigned int xs,const unsigned int ys,const unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht)261 render_YVYU_1x1_ntsc(video_render_color_tables_t *color_tab,
262 const uint8_t *src, uint8_t *trg,
263 const unsigned int width, const unsigned int height,
264 const unsigned int xs, const unsigned int ys,
265 const unsigned int xt, const unsigned int yt,
266 const unsigned int pitchs, const unsigned int pitcht)
267 {
268 render_generic_1x1_ntsc(color_tab, src, trg, width, height, xs, ys, xt, yt,
269 pitchs, pitcht,
270 4, store_pixel_YVYU, 1);
271 }
272
273 void
render_16_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,const unsigned int width,const unsigned int height,const unsigned int xs,const unsigned int ys,const unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht)274 render_16_1x1_ntsc(video_render_color_tables_t *color_tab,
275 const uint8_t *src, uint8_t *trg,
276 const unsigned int width, const unsigned int height,
277 const unsigned int xs, const unsigned int ys,
278 const unsigned int xt, const unsigned int yt,
279 const unsigned int pitchs, const unsigned int pitcht)
280 {
281 render_generic_1x1_ntsc(color_tab, src, trg, width, height, xs, ys, xt, yt,
282 pitchs, pitcht,
283 4, store_pixel_2, 0);
284 }
285
286 void
render_24_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,const unsigned int width,const unsigned int height,const unsigned int xs,const unsigned int ys,const unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht)287 render_24_1x1_ntsc(video_render_color_tables_t *color_tab,
288 const uint8_t *src, uint8_t *trg,
289 const unsigned int width, const unsigned int height,
290 const unsigned int xs, const unsigned int ys,
291 const unsigned int xt, const unsigned int yt,
292 const unsigned int pitchs, const unsigned int pitcht)
293 {
294 render_generic_1x1_ntsc(color_tab, src, trg, width, height, xs, ys, xt, yt,
295 pitchs, pitcht,
296 6, store_pixel_3, 0);
297 }
298
299 void
render_32_1x1_ntsc(video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,const unsigned int width,const unsigned int height,const unsigned int xs,const unsigned int ys,const unsigned int xt,const unsigned int yt,const unsigned int pitchs,const unsigned int pitcht)300 render_32_1x1_ntsc(video_render_color_tables_t *color_tab,
301 const uint8_t *src, uint8_t *trg,
302 const unsigned int width, const unsigned int height,
303 const unsigned int xs, const unsigned int ys,
304 const unsigned int xt, const unsigned int yt,
305 const unsigned int pitchs, const unsigned int pitcht)
306 {
307 render_generic_1x1_ntsc(color_tab, src, trg, width, height, xs, ys, xt, yt,
308 pitchs, pitcht,
309 8, store_pixel_4, 0);
310 }
311