1 /*
2 * E-UAE - The portable Amiga Emulator
3 *
4 * Generate pixel output code.
5 *
6 * (c) 2006 Richard Drummond
7 * (c) 2013 Sven Eden
8 */
9
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13
14 /* Output for big-endian target if true, little-endian is false. */
15 int do_bigendian;
16
17 typedef int DEPTH_T;
18
19 #define DEPTH_8BPP 0
20 #define DEPTH_16BPP 1
21 #define DEPTH_32BPP 2
22 #define DEPTH_MAX DEPTH_32BPP
23
get_depth_str(DEPTH_T bpp)24 static const char *get_depth_str (DEPTH_T bpp)
25 {
26 if (bpp == DEPTH_8BPP)
27 return "8";
28 else if (bpp == DEPTH_16BPP)
29 return "16";
30 else
31 return "32";
32 }
33
get_depth_type_str(DEPTH_T bpp)34 static const char *get_depth_type_str (DEPTH_T bpp)
35 {
36 if (bpp == DEPTH_8BPP)
37 return "uae_u8";
38 else if (bpp == DEPTH_16BPP)
39 return "uae_u16";
40 else
41 return "uae_u32";
42 }
43
44 typedef int HMODE_T;
45
46 #define HMODE_NORMAL 0
47 #define HMODE_DOUBLE 1
48 #define HMODE_DOUBLE2X 2
49 #define HMODE_HALVE1 3
50 #define HMODE_HALVE1F 4
51 #define HMODE_HALVE2 5
52 #define HMODE_HALVE2F 6
53 #define HMODE_MAX HMODE_HALVE2F
54
get_hmode_str(HMODE_T hmode)55 static const char *get_hmode_str (HMODE_T hmode)
56 {
57 if (hmode == HMODE_DOUBLE)
58 return "_stretch1";
59 else if (hmode == HMODE_DOUBLE2X)
60 return "_stretch2";
61 else if (hmode == HMODE_HALVE1)
62 return "_shrink1";
63 else if (hmode == HMODE_HALVE1F)
64 return "_shrink1f";
65 else if (hmode == HMODE_HALVE2)
66 return "_shrink2";
67 else if (hmode == HMODE_HALVE2F)
68 return "_shrink2f";
69 else
70 return "";
71 }
72
73
74 typedef enum
75 {
76 CMODE_NORMAL,
77 CMODE_DUALPF,
78 CMODE_EXTRAHB,
79 CMODE_HAM
80 } CMODE_T;
81 #define CMODE_MAX CMODE_HAM
82
83
84 static FILE *outfile;
85 static unsigned int outfile_indent = 0;
86
set_outfile(FILE * f)87 void set_outfile (FILE *f)
88 {
89 outfile = f;
90 }
91
set_indent(int indent)92 int set_indent (int indent)
93 {
94 int old_indent = outfile_indent;
95 outfile_indent = indent;
96 return old_indent;
97 }
98
outln(const char * s)99 void outln (const char *s)
100 {
101 unsigned int i;
102 for (i = 0; i < outfile_indent; i++)
103 fputc (' ', outfile);
104 fprintf (outfile, "%s\n", s);
105 }
106
outlnf(const char * s,...)107 void outlnf (const char *s, ...)
108 {
109 va_list ap;
110 unsigned int i;
111 for (i = 0; i < outfile_indent; i++)
112 fputc (' ', outfile);
113 va_start (ap, s);
114 vfprintf (outfile, s, ap);
115 fputc ('\n', outfile);
116 }
117
out_linetoscr_decl(DEPTH_T bpp,HMODE_T hmode,int aga,int spr)118 static void out_linetoscr_decl (DEPTH_T bpp, HMODE_T hmode, int aga, int spr)
119 {
120 outlnf ("static int NOINLINE linetoscr_%s%s%s%s (int spix, int dpix, int dpix_end)",
121 get_depth_str (bpp),
122 get_hmode_str (hmode), aga ? "_aga" : "", spr ? "_spr" : "");
123 }
124
out_linetoscr_do_srcpix(DEPTH_T bpp,HMODE_T hmode,int aga,CMODE_T cmode,int spr)125 static void out_linetoscr_do_srcpix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr)
126 {
127 if (aga && cmode != CMODE_DUALPF) {
128 if (spr)
129 outln ( " sprpix_val = pixdata.apixels[spix];");
130 if (CMODE_HAM != cmode)
131 outln ( " spix_val = pixdata.apixels[spix] ^ xor_val;");
132 } else if (cmode != CMODE_HAM) {
133 outln ( " spix_val = pixdata.apixels[spix];");
134 if (spr) {
135 outln ( " sprpix_val = spix_val;");
136 }
137 }
138 }
139
out_linetoscr_do_dstpix(DEPTH_T bpp,HMODE_T hmode,int aga,CMODE_T cmode,int spr)140 static void out_linetoscr_do_dstpix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr)
141 {
142 if (aga && cmode == CMODE_HAM) {
143 outln ( " spix_val = ham_linebuf[spix];");
144 outln ( " dpix_val = CONVERT_RGB (spix_val);");
145 } else if (cmode == CMODE_HAM) {
146 outln ( " spix_val = ham_linebuf[spix];");
147 outln ( " dpix_val = xcolors[spix_val];");
148 if (spr)
149 outln ( " sprpix_val = pixdata.apixels[spix];");
150 } else if (aga && cmode == CMODE_DUALPF) {
151 outln ( " {");
152 outln ( " uae_u8 val = lookup[spix_val];");
153 outln ( " if (lookup_no[spix_val])");
154 outln ( " val += dblpfofs[bpldualpf2of];");
155 outln ( " val ^= xor_val;");
156 outln ( " dpix_val = colors_for_drawing.acolors[val];");
157 outln ( " }");
158 } else if (cmode == CMODE_DUALPF) {
159 outln ( " dpix_val = colors_for_drawing.acolors[lookup[spix_val]];");
160 } else if (aga && cmode == CMODE_EXTRAHB) {
161 outln ( " if (spix_val >= 32 && spix_val < 64) {");
162 outln ( " unsigned int c = (colors_for_drawing.color_regs_aga[spix_val - 32] >> 1) & 0x7F7F7F;");
163 outln ( " dpix_val = CONVERT_RGB (c);");
164 outln ( " } else");
165 outln ( " dpix_val = colors_for_drawing.acolors[spix_val];");
166 } else if (cmode == CMODE_EXTRAHB) {
167 outln ( " if (spix_val <= 31)");
168 outln ( " dpix_val = colors_for_drawing.acolors[spix_val];");
169 outln ( " else");
170 outln ( " dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777];");
171 } else
172 outln ( " dpix_val = colors_for_drawing.acolors[spix_val];");
173 }
174
out_linetoscr_do_incspix(DEPTH_T bpp,HMODE_T hmode,int aga,CMODE_T cmode,int spr)175 static void out_linetoscr_do_incspix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr)
176 {
177 if (hmode == HMODE_HALVE1F) {
178 outln ( " {");
179 outln ( " uae_u32 tmp_val = dpix_val;");
180 outln ( " spix++;");
181 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
182 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
183 outlnf ( " dpix_val = merge_2pixel%d (dpix_val, tmp_val);", bpp == 0 ? 8 : bpp == 1 ? 16 : 32);
184 outln ( " spix++;");
185 outln ( " }");
186 } else if (hmode == HMODE_HALVE2F) {
187 outln ( " {");
188 outln ( " uae_u32 tmp_val = dpix_val, tmp_val2, tmp_val3;");
189 outln ( " spix++;");
190 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
191 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
192 outln ( " spix++;");
193 outln ( " tmp_val2 = dpix_val;");
194 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
195 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
196 outln ( " spix++;");
197 outln ( " tmp_val3 = dpix_val;");
198 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
199 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
200 outlnf ( " tmp_val = merge_2pixel%d (tmp_val, tmp_val2);", bpp == 0 ? 8 : bpp == 1 ? 16 : 32);
201 outlnf ( " tmp_val2 = merge_2pixel%d (tmp_val3, dpix_val);", bpp == 0 ? 8 : bpp == 1 ? 16 : 32);
202 outlnf ( " dpix_val = merge_2pixel%d (tmp_val, tmp_val2);", bpp == 0 ? 8 : bpp == 1 ? 16 : 32);
203 outln ( " spix++;");
204 outln ( " }");
205 } else if (hmode == HMODE_HALVE1) {
206 outln ( " spix += 2;");
207 } else if (hmode == HMODE_HALVE2) {
208 outln ( " spix += 4;");
209 } else {
210 outln ( " spix++;");
211 }
212 }
213
214
put_dpix(const char * var)215 static void put_dpix (const char *var)
216 {
217 outlnf (" buf[dpix++] = %s;", var);
218 }
219
out_sprite(DEPTH_T bpp,HMODE_T hmode,CMODE_T cmode,int aga,int cnt)220 static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int cnt)
221 {
222 if (aga) {
223 if (cnt == 1) {
224 outlnf ( " if (spritepixels[dpix].data) {");
225 outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
226 outlnf ( " if (sprcol)");
227 outlnf ( " out_val = colors_for_drawing.acolors[sprcol];");
228 outlnf ( " }");
229 put_dpix ("out_val");
230 } else if (cnt == 2) {
231 outlnf ( " {");
232 outlnf ( " uae_u32 out_val1 = out_val;");
233 outlnf ( " uae_u32 out_val2 = out_val;");
234 outlnf ( " if (spritepixels[dpix + 0].data) {");
235 outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
236 outlnf ( " if (sprcol)");
237 outlnf ( " out_val1 = colors_for_drawing.acolors[sprcol];");
238 outlnf ( " }");
239 outlnf ( " if (spritepixels[dpix + 1].data) {");
240 outlnf ( " sprcol = render_sprites (dpix + 1, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
241 outlnf ( " if (sprcol)");
242 outlnf ( " out_val2 = colors_for_drawing.acolors[sprcol];");
243 outlnf ( " }");
244 put_dpix ("out_val1");
245 put_dpix ("out_val2");
246 outlnf ( " }");
247 } else if (cnt == 4) {
248 outlnf ( " {");
249 outlnf ( " uae_u32 out_val1 = out_val;");
250 outlnf ( " uae_u32 out_val2 = out_val;");
251 outlnf ( " uae_u32 out_val3 = out_val;");
252 outlnf ( " uae_u32 out_val4 = out_val;");
253 outlnf ( " if (spritepixels[dpix + 0].data) {");
254 outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
255 outlnf ( " if (sprcol)");
256 outlnf ( " out_val1 = colors_for_drawing.acolors[sprcol];");
257 outlnf ( " }");
258 outlnf ( " if (spritepixels[dpix + 1].data) {");
259 outlnf ( " sprcol = render_sprites (dpix + 1, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
260 outlnf ( " if (sprcol)");
261 outlnf ( " out_val2 = colors_for_drawing.acolors[sprcol];");
262 outlnf ( " }");
263 outlnf ( " if (spritepixels[dpix + 2].data) {");
264 outlnf ( " sprcol = render_sprites (dpix + 2, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
265 outlnf ( " if (sprcol)");
266 outlnf ( " out_val3 = colors_for_drawing.acolors[sprcol];");
267 outlnf ( " }");
268 outlnf ( " if (spritepixels[dpix + 3].data) {");
269 outlnf ( " sprcol = render_sprites (dpix + 3, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
270 outlnf ( " if (sprcol)");
271 outlnf ( " out_val4 = colors_for_drawing.acolors[sprcol];");
272 outlnf ( " }");
273 put_dpix ("out_val1");
274 put_dpix ("out_val2");
275 put_dpix ("out_val3");
276 put_dpix ("out_val4");
277 outlnf ( " }");
278 }
279 } else {
280 outlnf ( " if (spritepixels[dpix].data) {");
281 outlnf ( " sprcol = render_sprites (dpix, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
282 outlnf ( " if (sprcol) {");
283 outlnf ( " uae_u32 spcol = colors_for_drawing.acolors[sprcol];");
284 outlnf ( " out_val = spcol;");
285 outlnf ( " }");
286 outlnf ( " }");
287 while (cnt-- > 0)
288 put_dpix ("out_val");
289 }
290 }
291
292
out_linetoscr_mode(DEPTH_T bpp,HMODE_T hmode,int aga,int spr,CMODE_T cmode)293 static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CMODE_T cmode)
294 {
295 int old_indent = set_indent (8);
296
297 if (aga && cmode == CMODE_DUALPF) {
298 outln ( "int *lookup = bpldualpfpri ? dblpf_ind2_aga : dblpf_ind1_aga;");
299 outln ( "int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;");
300 } else if (cmode == CMODE_DUALPF)
301 outln ( "int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;");
302
303
304 /* TODO: add support for combining pixel writes in 8-bpp modes. */
305
306 if (bpp == DEPTH_16BPP && hmode != HMODE_DOUBLE && hmode != HMODE_DOUBLE2X && spr == 0) {
307 outln ( "int rem;");
308 outln ( "if (((long)&buf[dpix]) & 2) {");
309 //if (CMODE_HAM != cmode)
310 outln ( " uae_u32 spix_val;");
311 outln ( " uae_u32 dpix_val = 0;");
312
313 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
314 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
315 out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
316
317 put_dpix ("dpix_val");
318 outln ( "}");
319 outln ( "if (dpix >= dpix_end)");
320 outln ( " return spix;");
321 outln ( "rem = (((long)&buf[dpix_end]) & 2);");
322 outln ( "if (rem)");
323 outln ( " dpix_end--;");
324 }
325
326
327 outln ( "while (dpix < dpix_end) {");
328 if (spr)
329 outln ( " uae_u32 sprpix_val;");
330 //if (CMODE_HAM != cmode)
331 outln ( " uae_u32 spix_val;");
332 outln ( " uae_u32 dpix_val = 0;");
333 outln ( " uae_u32 out_val = 0;");
334 outln ( "");
335
336 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
337 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
338 out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
339
340 outln ( " out_val = dpix_val;");
341
342 if (hmode != HMODE_DOUBLE && hmode != HMODE_DOUBLE2X && bpp == DEPTH_16BPP && spr == 0) {
343 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
344 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
345 out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
346
347 if (do_bigendian)
348 outln ( " out_val = (out_val << 16) | (dpix_val & 0xFFFF);");
349 else
350 outln ( " out_val = (out_val & 0xFFFF) | (dpix_val << 16);");
351 }
352
353 if (hmode == HMODE_DOUBLE) {
354 if (bpp == DEPTH_8BPP) {
355 outln ( " *((uae_u16 *)&buf[dpix]) = (uae_u16) out_val;");
356 outln ( " dpix += 2;");
357 } else if (bpp == DEPTH_16BPP) {
358 if (spr) {
359 out_sprite (bpp, hmode, cmode, aga, 2);
360 } else {
361 outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
362 outln ( " dpix += 2;");
363 }
364 } else {
365 if (spr) {
366 out_sprite (bpp, hmode, cmode, aga, 2);
367 } else {
368 put_dpix ("out_val");
369 put_dpix ("out_val");
370 }
371 }
372 } else if (hmode == HMODE_DOUBLE2X) {
373 if (bpp == DEPTH_8BPP) {
374 outln ( " *((uae_u32 *)&buf[dpix]) = (uae_u32) out_val;");
375 outln ( " dpix += 4;");
376 } else if (bpp == DEPTH_16BPP) {
377 if (spr) {
378 out_sprite (bpp, hmode, cmode, aga, 4);
379 } else {
380 outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
381 outln ( " dpix += 2;");
382 outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
383 outln ( " dpix += 2;");
384 }
385 } else {
386 if (spr) {
387 out_sprite (bpp, hmode, cmode, aga, 4);
388 } else {
389 put_dpix ("out_val");
390 put_dpix ("out_val");
391 put_dpix ("out_val");
392 put_dpix ("out_val");
393 }
394 }
395 } else {
396 if (bpp == DEPTH_16BPP) {
397 if (spr) {
398 out_sprite (bpp, hmode, cmode, aga, 1);
399 } else {
400 outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
401 outln ( " dpix += 2;");
402 }
403 } else {
404 if (spr) {
405 out_sprite (bpp, hmode, cmode, aga, 1);
406 } else {
407 put_dpix ("out_val");
408 }
409 }
410 }
411
412 outln ( "}");
413
414
415 if (bpp == DEPTH_16BPP && hmode != HMODE_DOUBLE && hmode != HMODE_DOUBLE2X && spr == 0) {
416 outln ( "if (rem) {");
417 //if (CMODE_HAM != cmode)
418 outln ( " uae_u32 spix_val;");
419 outln ( " uae_u32 dpix_val = 0;");
420
421 out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
422 out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
423 out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
424
425 put_dpix ("dpix_val");
426 outln ( "}");
427 }
428
429 set_indent (old_indent);
430
431 return;
432 }
433
out_linetoscr(DEPTH_T bpp,HMODE_T hmode,int aga,int spr)434 static void out_linetoscr (DEPTH_T bpp, HMODE_T hmode, int aga, int spr)
435 {
436 if (aga)
437 outln ("#ifdef AGA");
438 else if ( (bpp > DEPTH_8BPP)
439 && ((HMODE_HALVE2 == hmode) || (HMODE_HALVE2F == hmode) )) {
440 /* Some combinations are unused, and some combinations
441 * have special versions in drawing.c if ECS_DENISE is
442 * defined. */
443 if (spr)
444 return;
445 else
446 outln("#ifndef ECS_DENISE // Has special version in drawing.c");
447 }
448
449 out_linetoscr_decl (bpp, hmode, aga, spr);
450 outln ( "{");
451
452 outlnf ( " %s *buf = (%s *) xlinebuffer;", get_depth_type_str (bpp), get_depth_type_str (bpp));
453 if (spr)
454 outln ( " uae_u8 sprcol;");
455 if (aga)
456 outln ( " uae_u8 xor_val = bplxor;");
457 outln ( "");
458
459 outln ( " if (dp_for_drawing->ham_seen) {");
460 out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_HAM);
461 outln ( " } else if (bpldualpf) {");
462 out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_DUALPF);
463 outln ( " } else if (bplehb) {");
464 out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_EXTRAHB);
465 outln ( " } else {");
466 out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_NORMAL);
467
468 outln ( " }\n");
469 outln ( " return spix;");
470 outln ( "}");
471
472 if (aga)
473 outln ( "#endif // AGA");
474 else if ( (bpp > DEPTH_8BPP)
475 && ((HMODE_HALVE2 == hmode) || (HMODE_HALVE2F == hmode) ))
476 outln ( "#endif // ECS_DENISE");
477
478 outln ( "");
479 }
480
main(int argc,char * argv[])481 int main (int argc, char *argv[])
482 {
483 DEPTH_T bpp;
484 int aga, spr;
485 HMODE_T hmode;
486 int i = 1;
487
488 do_bigendian = 0;
489
490 for ( ; i < argc; i++) {
491 if (argv[i][0] != '-')
492 continue;
493 if (argv[i][1] == 'b' && argv[i][2] == '\0')
494 do_bigendian = 1;
495 }
496
497 set_outfile (stdout);
498
499 outln ("/*");
500 outln (" * P-UAE - The portable Amiga emulator.");
501 outln (" *");
502 outln (" * This file was generated by genlinetoscr. Don't edit.");
503 outln (" */");
504 outln ("");
505
506 for (bpp = DEPTH_16BPP; bpp <= DEPTH_MAX; bpp++) {
507 for (aga = 0; aga <= 1 ; aga++) {
508 if (aga && bpp == DEPTH_8BPP)
509 continue;
510 for (spr = 0; spr <= 1; spr++) {
511 for (hmode = HMODE_NORMAL; hmode <= HMODE_MAX; hmode++)
512 out_linetoscr (bpp, hmode, aga, spr);
513 }
514 }
515 }
516 return 0;
517 }
518