1 /*
2  * render2x4.c - 2x4 renderers
3  *
4  * Written by
5  *  groepaz <groepaz@gmx.net> based on the 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 "render2x4.h"
31 #include "types.h"
32 #include <string.h>
33 
34 /* 16 color 2x2 renderers */
35 
render_08_2x4_04(const video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,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,const unsigned int doublescan,video_render_config_t * config)36 void render_08_2x4_04(const video_render_color_tables_t *color_tab,
37                       const uint8_t *src, uint8_t *trg,
38                       unsigned int width, const unsigned int height,
39                       const unsigned int xs, const unsigned int ys,
40                       const unsigned int xt, const unsigned int yt,
41                       const unsigned int pitchs, const unsigned int pitcht,
42                       const unsigned int doublescan, video_render_config_t *config)
43 {
44     const uint32_t *colortab = color_tab->physical_colors;
45     const uint8_t *tmpsrc;
46     uint16_t *tmptrg;
47     unsigned int x, y, wfirst, wstart, wfast, wend, wlast, yys;
48     int readable = config->readable;
49 
50     src = src + pitchs * ys + xs;
51     trg = trg + pitcht * yt + xt;
52     yys = (ys << 1) | (yt & 1);
53     wfirst = xt & 1;
54     width -= wfirst;
55     wlast = width & 1;
56     width >>= 1;
57     if (width < 8) {
58         wstart = width;
59         wfast = 0;
60         wend = 0;
61     } else {
62         /* alignment: 8 pixels*/
63         wstart = (unsigned int)(8 - (vice_ptr_to_uint(trg) & 7));
64         wfast = (width - wstart) >> 3; /* fast loop for 8 pixel segments*/
65         wend = (width - wstart) & 0x07; /* do not forget the rest*/
66     }
67     for (y = yys; y < (yys + height); y++) {
68         tmpsrc = src;
69         tmptrg = (uint16_t *)trg;
70         if (!(y & 2) || doublescan) {
71             if ((y & 3) && readable && y > yys) { /* copy previous line */
72                 memcpy(trg, trg - pitcht, (width << 1) + wfirst + wlast);
73             } else {
74                 if (wfirst) {
75                     *((uint8_t *)tmptrg) = (uint8_t)colortab[*tmpsrc++];
76                     tmptrg = (uint16_t *)(((uint8_t *)tmptrg) + 1);
77                 }
78                 for (x = 0; x < wstart; x++) {
79                     *tmptrg++ = (uint16_t)colortab[*tmpsrc++];
80                 }
81                 for (x = 0; x < wfast; x++) {
82                     tmptrg[0] = (uint16_t)colortab[tmpsrc[0]];
83                     tmptrg[1] = (uint16_t)colortab[tmpsrc[1]];
84                     tmptrg[2] = (uint16_t)colortab[tmpsrc[2]];
85                     tmptrg[3] = (uint16_t)colortab[tmpsrc[3]];
86                     tmptrg[4] = (uint16_t)colortab[tmpsrc[4]];
87                     tmptrg[5] = (uint16_t)colortab[tmpsrc[5]];
88                     tmptrg[6] = (uint16_t)colortab[tmpsrc[6]];
89                     tmptrg[7] = (uint16_t)colortab[tmpsrc[7]];
90                     tmpsrc += 8;
91                     tmptrg += 8;
92                 }
93                 for (x = 0; x < wend; x++) {
94                     *tmptrg++ = (uint16_t)colortab[*tmpsrc++];
95                 }
96                 if (wlast) {
97                     *((uint8_t *)tmptrg) = (uint8_t)colortab[*tmpsrc];
98                     tmptrg = (uint16_t *)(((uint8_t *)tmptrg) + 1);
99                 }
100             }
101         } else {
102             memset(trg, (uint8_t)colortab[0], (width << 1) + wfirst + wlast);
103         }
104         if ((y & 3) == 3) {
105             src += pitchs;
106         }
107         trg += pitcht;
108     }
109 }
110 
render_16_2x4_04(const video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,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,const unsigned int doublescan,video_render_config_t * config)111 void render_16_2x4_04(const video_render_color_tables_t *color_tab,
112                       const uint8_t *src, uint8_t *trg,
113                       unsigned int width, const unsigned int height,
114                       const unsigned int xs, const unsigned int ys,
115                       const unsigned int xt, const unsigned int yt,
116                       const unsigned int pitchs, const unsigned int pitcht,
117                       const unsigned int doublescan, video_render_config_t *config)
118 {
119     const uint32_t *colortab = color_tab->physical_colors;
120     const uint8_t *tmpsrc;
121     uint32_t *tmptrg;
122     unsigned int x, y, wfirst, wstart, wfast, wend, wlast, yys;
123     uint32_t color;
124     int readable = config->readable;
125 
126     src = src + pitchs * ys + xs;
127     trg = trg + pitcht * yt + (xt << 1);
128     yys = (ys << 1) | (yt & 1);
129     wfirst = xt & 1;
130     width -= wfirst;
131     wlast = width & 1;
132     width >>= 1;
133     if (width < 8) {
134         wstart = width;
135         wfast = 0;
136         wend = 0;
137     } else {
138         /* alignment: 8 pixels*/
139         wstart = (unsigned int)(8 - (vice_ptr_to_int(trg) & 7));
140         wfast = (width - wstart) >> 3; /* fast loop for 8 pixel segments*/
141         wend = (width - wstart) & 0x07; /* do not forget the rest*/
142     }
143     for (y = yys; y < (yys + height); y++) {
144         tmpsrc = src;
145         tmptrg = (uint32_t *)trg;
146         if (!(y & 2) || doublescan) {
147             if ((y & 3) && readable && y > yys) { /* copy previous line */
148                 memcpy(trg, trg - pitcht, ((width << 1) + wfirst + wlast) << 1);
149             } else {
150                 if (wfirst) {
151                     *((uint16_t *)tmptrg) = (uint16_t)colortab[*tmpsrc++];
152                     tmptrg = (uint32_t *)(((uint16_t *)tmptrg) + 1);
153                 }
154                 for (x = 0; x < wstart; x++) {
155                     *tmptrg++ = colortab[*tmpsrc++];
156                 }
157                 for (x = 0; x < wfast; x++) {
158                     tmptrg[0] = colortab[tmpsrc[0]];
159                     tmptrg[1] = colortab[tmpsrc[1]];
160                     tmptrg[2] = colortab[tmpsrc[2]];
161                     tmptrg[3] = colortab[tmpsrc[3]];
162                     tmptrg[4] = colortab[tmpsrc[4]];
163                     tmptrg[5] = colortab[tmpsrc[5]];
164                     tmptrg[6] = colortab[tmpsrc[6]];
165                     tmptrg[7] = colortab[tmpsrc[7]];
166                     tmpsrc += 8;
167                     tmptrg += 8;
168                 }
169                 for (x = 0; x < wend; x++) {
170                     *tmptrg++ = colortab[*tmpsrc++];
171                 }
172                 if (wlast) {
173                     *((uint16_t *)tmptrg) = (uint16_t)colortab[*tmpsrc];
174                 }
175             }
176         } else {
177             if (readable && y > yys + 3) { /* copy 4 lines before */
178                 memcpy(trg, trg - pitcht * 4, ((width << 1) + wfirst + wlast) << 1);
179             } else {
180                 color = colortab[0];
181                 if (wfirst) {
182                     *((uint16_t *)tmptrg) = (uint16_t)color;
183                     tmptrg = (uint32_t *)(((uint16_t *)tmptrg) + 1);
184                 }
185                 for (x = 0; x < wstart; x++) {
186                     *tmptrg++ = color;
187                 }
188                 for (x = 0; x < wfast; x++) {
189                     tmptrg[0] = color;
190                     tmptrg[1] = color;
191                     tmptrg[2] = color;
192                     tmptrg[3] = color;
193                     tmptrg[4] = color;
194                     tmptrg[5] = color;
195                     tmptrg[6] = color;
196                     tmptrg[7] = color;
197                     tmptrg += 8;
198                 }
199                 for (x = 0; x < wend; x++) {
200                     *tmptrg++ = color;
201                 }
202                 if (wlast) {
203                     *((uint16_t *)tmptrg) = (uint16_t)color;
204                 }
205             }
206         }
207         if ((y & 3) == 3) {
208             src += pitchs;
209         }
210         trg += pitcht;
211     }
212 }
213 
render_24_2x4_04(const video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,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,const unsigned int doublescan,video_render_config_t * config)214 void render_24_2x4_04(const video_render_color_tables_t *color_tab,
215                       const uint8_t *src, uint8_t *trg,
216                       unsigned int width, const unsigned int height,
217                       const unsigned int xs, const unsigned int ys,
218                       const unsigned int xt, const unsigned int yt,
219                       const unsigned int pitchs, const unsigned int pitcht,
220                       const unsigned int doublescan, video_render_config_t *config)
221 {
222     const uint32_t *colortab = color_tab->physical_colors;
223     const uint8_t *tmpsrc;
224     uint8_t *tmptrg;
225     unsigned int x, y, wlast, yys;
226     register uint32_t color;
227     register uint32_t tcolor;
228     int readable = config->readable;
229 
230     src = src + pitchs * ys + xs;
231     trg = trg + pitcht * yt + (xt * 3);
232     yys = (ys << 1) | (yt & 1);
233     wlast = width & 1;
234     width >>= 1;
235     for (y = yys; y < (yys + height); y++) {
236         tmpsrc = src;
237         tmptrg = trg;
238         if (!(y & 2) || doublescan) {
239             if ((y & 3) && readable && y > yys) { /* copy previous line */
240                 memcpy(trg, trg - pitcht, ((width << 1) + wlast) * 3);
241             } else {
242                 for (x = 0; x < width; x++) {
243                     color = colortab[*tmpsrc++];
244                     tcolor = color;
245                     tmptrg[3] = tmptrg[0] = (uint8_t)color;
246                     color >>= 8;
247                     tmptrg[4] = tmptrg[1] = (uint8_t)color;
248                     color >>= 8;
249                     tmptrg[5] = tmptrg[2] = (uint8_t)color;
250                     tmptrg += 6;
251                 }
252                 if (wlast) {
253                     color = colortab[*tmpsrc];
254                     tmptrg[0] = (uint8_t)color;
255                     color >>= 8;
256                     tmptrg[1] = (uint8_t)color;
257                     color >>= 8;
258                     tmptrg[2] = (uint8_t)color;
259                 }
260             }
261         } else {
262             if (readable && y > yys + 3) { /* copy 4 lines before */
263                 memcpy(trg, trg - pitcht * 4, ((width << 1) + wlast) * 3);
264             } else {
265                 color = colortab[0];
266                 for (x = 0; x < width; x++) {
267                     tcolor = color;
268                     tmptrg[3] = tmptrg[0] = (uint8_t)tcolor;
269                     tcolor >>= 8;
270                     tmptrg[4] = tmptrg[1] = (uint8_t)tcolor;
271                     tcolor >>= 8;
272                     tmptrg[5] = tmptrg[2] = (uint8_t)tcolor;
273                     tmptrg += 6;
274                 }
275                 if (wlast) {
276                     tmptrg[0] = (uint8_t)color;
277                     color >>= 8;
278                     tmptrg[1] = (uint8_t)color;
279                     color >>= 8;
280                     tmptrg[2] = (uint8_t)color;
281                 }
282             }
283         }
284         if ((y & 3) == 3) {
285             src += pitchs;
286         }
287         trg += pitcht;
288     }
289 }
290 
render_32_2x4_04(const video_render_color_tables_t * color_tab,const uint8_t * src,uint8_t * trg,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,const unsigned int doublescan,video_render_config_t * config)291 void render_32_2x4_04(const video_render_color_tables_t *color_tab,
292                       const uint8_t *src, uint8_t *trg,
293                       unsigned int width, const unsigned int height,
294                       const unsigned int xs, const unsigned int ys,
295                       const unsigned int xt, const unsigned int yt,
296                       const unsigned int pitchs, const unsigned int pitcht,
297                       const unsigned int doublescan, video_render_config_t *config)
298 {
299     const uint32_t *colortab = color_tab->physical_colors;
300     const uint8_t *tmpsrc;
301     uint32_t *tmptrg;
302     unsigned int x, y, wfirst, wstart, wfast, wend, wlast, yys;
303     register uint32_t color;
304     int readable = config->readable;
305 
306     src = src + pitchs * ys + xs;
307     trg = trg + pitcht * yt + (xt << 2);
308     yys = (ys << 1) | (yt & 1);
309     wfirst = xt & 1;
310     width -= wfirst;
311     wlast = width & 1;
312     width >>= 1;
313     if (width < 8) {
314         wstart = width;
315         wfast = 0;
316         wend = 0;
317     } else {
318         /* alignment: 8 pixels*/
319         wstart = (unsigned int)(8 - (vice_ptr_to_uint(trg) & 7));
320         wfast = (width - wstart) >> 3; /* fast loop for 8 pixel segments*/
321         wend = (width - wstart) & 0x07; /* do not forget the rest*/
322     }
323     for (y = yys; y < (yys + height); y++) {
324         tmpsrc = src;
325         tmptrg = (uint32_t *)trg;
326         if (!(y & 2) || doublescan) {
327             if ((y & 3) && readable && y > yys) { /* copy previous line */
328                 memcpy(trg, trg - pitcht, ((width << 1) + wfirst + wlast) << 2);
329             } else {
330                 if (wfirst) {
331                     *tmptrg++ = colortab[*tmpsrc++];
332                 }
333                 for (x = 0; x < wstart; x++) {
334                     color = colortab[*tmpsrc++];
335                     *tmptrg++ = color;
336                     *tmptrg++ = color;
337                 }
338                 for (x = 0; x < wfast; x++) {
339                     color = colortab[tmpsrc[0]];
340                     tmptrg[0] = color;
341                     tmptrg[1] = color;
342                     color = colortab[tmpsrc[1]];
343                     tmptrg[2] = color;
344                     tmptrg[3] = color;
345                     color = colortab[tmpsrc[2]];
346                     tmptrg[4] = color;
347                     tmptrg[5] = color;
348                     color = colortab[tmpsrc[3]];
349                     tmptrg[6] = color;
350                     tmptrg[7] = color;
351                     color = colortab[tmpsrc[4]];
352                     tmptrg[8] = color;
353                     tmptrg[9] = color;
354                     color = colortab[tmpsrc[5]];
355                     tmptrg[10] = color;
356                     tmptrg[11] = color;
357                     color = colortab[tmpsrc[6]];
358                     tmptrg[12] = color;
359                     tmptrg[13] = color;
360                     color = colortab[tmpsrc[7]];
361                     tmptrg[14] = color;
362                     tmptrg[15] = color;
363                     tmpsrc += 8;
364                     tmptrg += 16;
365                 }
366                 for (x = 0; x < wend; x++) {
367                     color = colortab[*tmpsrc++];
368                     *tmptrg++ = color;
369                     *tmptrg++ = color;
370                 }
371                 if (wlast) {
372                     *tmptrg = colortab[*tmpsrc];
373                 }
374             }
375         } else {
376             if (readable && y > yys + 3) { /* copy 4 lines before */
377                 memcpy(trg, trg - pitcht * 4, ((width << 1) + wfirst + wlast) << 2);
378             } else {
379                 color = colortab[0];
380                 if (wfirst) {
381                     *tmptrg++ = color;
382                 }
383                 for (x = 0; x < wstart; x++) {
384                     *tmptrg++ = color;
385                     *tmptrg++ = color;
386                 }
387                 for (x = 0; x < wfast; x++) {
388                     tmptrg[0] = color;
389                     tmptrg[1] = color;
390                     tmptrg[2] = color;
391                     tmptrg[3] = color;
392                     tmptrg[4] = color;
393                     tmptrg[5] = color;
394                     tmptrg[6] = color;
395                     tmptrg[7] = color;
396                     tmptrg[8] = color;
397                     tmptrg[9] = color;
398                     tmptrg[10] = color;
399                     tmptrg[11] = color;
400                     tmptrg[12] = color;
401                     tmptrg[13] = color;
402                     tmptrg[14] = color;
403                     tmptrg[15] = color;
404                     tmptrg += 16;
405                 }
406                 for (x = 0; x < wend; x++) {
407                     *tmptrg++ = color;
408                     *tmptrg++ = color;
409                 }
410                 if (wlast) {
411                     *tmptrg = color;
412                 }
413             }
414         }
415         if ((y & 3) == 3) {
416             src += pitchs;
417         }
418         trg += pitcht;
419     }
420 }
421