]> git.sesse.net Git - pistorm/blob - platforms/amiga/rtg/rtg-gfx.c
Fix up P2C/P2D, fix 256th color missing in 8bpp modes
[pistorm] / platforms / amiga / rtg / rtg-gfx.c
1 // SPDX-License-Identifier: MIT
2
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "config_file/config_file.h"
8 #ifndef FAKESTORM
9 #include "gpio/ps_protocol.h"
10 #endif
11 #include "rtg.h"
12
13 extern uint32_t rtg_address[8];
14 extern uint32_t rtg_address_adj[8];
15 extern uint8_t *rtg_mem; // FIXME
16 extern uint16_t rtg_display_format;
17 extern uint16_t rtg_user[8];
18 extern uint16_t rtg_x[8], rtg_y[8];
19
20 extern uint8_t realtime_graphics_debug;
21
22 uint8_t cursor_data[256 * 256];
23
24 void rtg_fillrect_solid(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color, uint16_t pitch, uint16_t format) {
25     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)];
26     switch(format) {
27         case RTGFMT_8BIT: {
28             for (int xs = 0; xs < w; xs++) {
29                 dptr[xs] = color & 0xFF;
30             }
31             break;
32         }
33         case RTGFMT_RBG565: {
34             color = htobe16((color & 0xFFFF));
35             uint16_t *ptr = (uint16_t *)dptr;
36             for (int xs = 0; xs < w; xs++) {
37                 ptr[xs] = color;
38             }
39             break;
40         }
41         case RTGFMT_RGB32: {
42             color = htobe32(color);
43             uint32_t *ptr = (uint32_t *)dptr;
44             for (int xs = 0; xs < w; xs++) {
45                 ptr[xs] = color;
46             }
47             break;
48         }
49     }
50     for (int ys = 1; ys < h; ys++) {
51         dptr += pitch;
52         memcpy(dptr, (void *)(size_t)(dptr - pitch), (w << format));
53     }
54 }
55
56 void rtg_fillrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color, uint16_t pitch, uint16_t format, uint8_t mask) {
57     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)];
58
59     for (int ys = 0; ys < h; ys++) {
60         for (int xs = 0; xs < w; xs++) {
61             SET_RTG_PIXEL_MASK(&dptr[xs], (color & 0xFF), format);
62         }
63         dptr += pitch;
64     }
65 }
66
67 void rtg_invertrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t pitch, uint16_t format, uint8_t mask) {
68     if (mask) {}
69     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)];
70     for (int ys = 0; ys < h; ys++) {
71         switch(format) {
72             case RTGFMT_8BIT: {
73                 for (int xs = 0; xs < w; xs++) {
74                     dptr[xs] ^= mask;
75                 }
76                 break;
77             }
78             case RTGFMT_RBG565: {
79                 for (int xs = 0; xs < w; xs++) {
80                     ((uint16_t *)dptr)[xs] = ~((uint16_t *)dptr)[xs];
81                 }
82                 break;
83             }
84             case RTGFMT_RGB32: {
85                 for (int xs = 0; xs < w; xs++) {
86                     ((uint32_t *)dptr)[xs] = ~((uint32_t *)dptr)[xs];
87                 }
88                 break;
89             }
90         }
91         dptr += pitch;
92     }
93 }
94
95 void rtg_blitrect(uint16_t x, uint16_t y, uint16_t dx, uint16_t dy, uint16_t w, uint16_t h, uint16_t pitch, uint16_t format, uint8_t mask) {
96     if (mask) {}
97     uint8_t *sptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)];
98     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dx << format) + (dy * pitch)];
99
100     uint32_t xdir = 1, pitchstep = pitch;
101
102     if (y < dy) {
103         pitchstep = -pitch;
104         sptr += ((h - 1) * pitch);
105         dptr += ((h - 1) * pitch);
106     }
107     if (x < dx) {
108         xdir = 0;
109     }
110
111     for (int ys = 0; ys < h; ys++) {
112         if (xdir) {
113             for (int xs = 0; xs < w; xs++) {
114                 SET_RTG_PIXEL_MASK(&dptr[xs], sptr[xs], format);
115             }
116         }
117         else {
118             for (int xs = w - 1; xs >= x; xs--) {
119                 SET_RTG_PIXEL_MASK(&dptr[xs], sptr[xs], format);
120             }
121         }
122         sptr += pitchstep;
123         dptr += pitchstep;
124     }
125 }
126
127 void rtg_blitrect_solid(uint16_t x, uint16_t y, uint16_t dx, uint16_t dy, uint16_t w, uint16_t h, uint16_t pitch, uint16_t format) {
128     uint8_t *sptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)];
129     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dx << format) + (dy * pitch)];
130
131     uint32_t xdir = 1, pitchstep = pitch;
132
133     if (y < dy) {
134         pitchstep = -pitch;
135         sptr += ((h - 1) * pitch);
136         dptr += ((h - 1) * pitch);
137     }
138     if (x < dx) {
139         xdir = 0;
140     }
141
142     for (int ys = 0; ys < h; ys++) {
143         if (xdir)
144             memcpy(dptr, sptr, w << format);
145         else
146             memmove(dptr, sptr, w << format);
147         sptr += pitchstep;
148         dptr += pitchstep;
149     }
150 }
151
152 void rtg_blitrect_nomask_complete(uint16_t sx, uint16_t sy, uint16_t dx, uint16_t dy, uint16_t w, uint16_t h, uint16_t srcpitch, uint16_t dstpitch, uint32_t src_addr, uint32_t dst_addr, uint16_t format, uint8_t minterm) {
153     if (minterm) {}
154     uint8_t *sptr = &rtg_mem[src_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE) + (sx << format) + (sy * srcpitch)];
155     uint8_t *dptr = &rtg_mem[dst_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE) + (dx << format) + (dy * dstpitch)];
156
157     uint32_t xdir = 1, src_pitchstep = srcpitch, dst_pitchstep = dstpitch;
158     uint8_t draw_mode = minterm;
159     uint32_t mask = 0xFF;
160
161     if (src_addr == dst_addr) {
162         if (sy < dy) {
163             src_pitchstep = -srcpitch;
164             sptr += ((h - 1) * srcpitch);
165             dst_pitchstep = -dstpitch;
166             dptr += ((h - 1) * dstpitch);
167         }
168         if (sx < dx) {
169             xdir = 0;
170         }
171     }
172
173     if (format == RTGFMT_RBG565)
174         mask = 0xFFFF;
175     if (format == RTGFMT_RGB32)
176         mask = 0xFFFFFFFF;
177
178     if (minterm == MINTERM_SRC) {
179         for (int ys = 0; ys < h; ys++) {
180             if (xdir)
181                 memcpy(dptr, sptr, w << format);
182             else
183                 memmove(dptr, sptr, w << format);
184             sptr += src_pitchstep;
185             dptr += dst_pitchstep;
186         }
187     }
188     else {
189         for (int ys = 0; ys < h; ys++) {
190             if (xdir) {
191                 for (int xs = 0; xs < w; xs++) {
192                     switch (format) {
193                         case RTGFMT_8BIT:
194                             HANDLE_MINTERM_PIXEL(sptr[xs], dptr[xs], format);
195                             break;
196                         case RTGFMT_RBG565:
197                             HANDLE_MINTERM_PIXEL(((uint16_t *)sptr)[xs], ((uint16_t *)dptr)[xs], format);
198                             break;
199                         case RTGFMT_RGB32:
200                             HANDLE_MINTERM_PIXEL(((uint32_t *)sptr)[xs], ((uint32_t *)dptr)[xs], format);
201                             break;
202                     }
203                 }
204             }
205             else {
206                 for (int xs = w - 1; xs >= sx; xs--) {
207                     switch (format) {
208                         case RTGFMT_8BIT:
209                             HANDLE_MINTERM_PIXEL(sptr[xs], dptr[xs], format);
210                             break;
211                         case RTGFMT_RBG565:
212                             HANDLE_MINTERM_PIXEL(((uint16_t *)sptr)[xs], ((uint16_t *)dptr)[xs], format);
213                             break;
214                         case RTGFMT_RGB32:
215                             HANDLE_MINTERM_PIXEL(((uint32_t *)sptr)[xs], ((uint32_t *)dptr)[xs], format);
216                             break;
217                     }
218                 }
219             }
220             sptr += src_pitchstep;
221             dptr += src_pitchstep;
222         }
223     }
224 }
225
226 extern struct emulator_config *cfg;
227
228 void rtg_blittemplate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t src_addr, uint32_t fgcol, uint32_t bgcol, uint16_t pitch, uint16_t t_pitch, uint16_t format, uint16_t offset_x, uint8_t mask, uint8_t draw_mode) {
229     if (mask) {}
230
231     uint8_t *dptr = &rtg_mem[rtg_address_adj[1] + (x << format) + (y * pitch)];
232     uint8_t *sptr = NULL;
233     uint8_t cur_bit = 0, base_bit = 0, cur_byte = 0;
234     uint8_t invert = (draw_mode & DRAWMODE_INVERSVID);
235     uint16_t tmpl_x = 0;
236
237     draw_mode &= 0x03;
238
239         tmpl_x = offset_x / 8;
240     cur_bit = base_bit = (0x80 >> (offset_x % 8));
241
242     if (realtime_graphics_debug) {
243         printf("DEBUG: BlitTemplate - %d, %d (%dx%d)\n", x, y, w, h);
244         printf("Src: %.8X (%.8X)\n", src_addr, rtg_address_adj[0]);
245         printf("Dest: %.8X (%.8X)\n", rtg_address[1], rtg_address_adj[1]);
246         printf("pitch: %d t_pitch: %d format: %d\n", pitch, t_pitch, format);
247         printf("offset_x: %d mask: %.2X draw_mode: %d\n", offset_x, mask, draw_mode);
248     }
249
250     uint32_t fg_color[3] = {
251         (fgcol & 0xFF),
252         htobe16((fgcol & 0xFFFF)),
253         htobe32(fgcol),
254     };
255     uint32_t bg_color[3] = {
256         (bgcol & 0xFF),
257         htobe16((bgcol & 0xFFFF)),
258         htobe32(bgcol),
259     };
260
261     if (src_addr >= (PIGFX_RTG_BASE + PIGFX_REG_SIZE)) {
262         sptr = &rtg_mem[src_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE)];
263         if (realtime_graphics_debug) {
264             printf("Origin: %.8X\n", rtg_address[2]);
265             printf("Grabbing data from RTG memory.\nData:\n");
266             for (int i = 0; i < h; i++) {
267                 for (int j = 0; j < t_pitch; j++) {
268                     printf("%.2X", sptr[j + (i * t_pitch)]);
269                 }
270                 printf("\n");
271             }
272 #ifndef FAKESTORM
273             printf("Data available at origin:\n");
274             for (int i = 0; i < h; i++) {
275                 for (int j = 0; j < w; j++) {
276                     printf("%.2X", read8(rtg_address[2] + j + (i * t_pitch)));
277                 }
278                 printf("\n");
279             }
280 #endif
281         }
282     }
283     else {
284         int i = get_mapped_item_by_address(cfg, src_addr);
285         if (i != -1) {
286             sptr = &cfg->map_data[i][src_addr - cfg->map_offset[i]];
287             if (realtime_graphics_debug) {
288                 printf("Grabbing data from maping %d - offset %.8lX\nData:\n", i, src_addr - cfg->map_offset[i]);
289                 for (int i = 0; i < h; i++) {
290                     for (int j = 0; j < t_pitch; j++) {
291                         printf("%.2X", sptr[j + (i * t_pitch)]);
292                     }
293                     printf("\n");
294                 }
295             }
296         }
297         else {
298             printf("BlitTemplate: Failed to find mapped range for address %.8X\n", src_addr);
299             return;
300         }
301     }
302
303     switch (draw_mode) {
304         case DRAWMODE_JAM1:
305             for (uint16_t ys = 0; ys < h; ys++) {
306                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
307
308                 for (int xs = 0; xs < w; xs++) {
309                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
310                         if (mask == 0xFF || format != RTGFMT_8BIT) {
311                             SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format);
312                         }
313                         else {
314                             SET_RTG_PIXELS_MASK(&dptr[xs], fg_color[format], format);
315                         }
316                         xs += 7;
317                     }
318                     else {
319                         while (cur_bit > 0 && xs < w) {
320                             if (cur_byte & cur_bit) {
321                                 if (mask == 0xFF || format != RTGFMT_8BIT) {
322                                     SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format);
323                                 }
324                                 else {
325                                     SET_RTG_PIXEL_MASK(&dptr[xs], fg_color[format], format);
326                                 }
327                             }
328                             xs++;
329                             cur_bit >>= 1;
330                         }
331                         xs--;
332                         cur_bit = 0x80;
333                     }
334                     TEMPLATE_LOOPX;
335                 }
336                 TEMPLATE_LOOPY;
337             }
338             return;
339         case DRAWMODE_JAM2:
340             for (uint16_t ys = 0; ys < h; ys++) {
341                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
342
343                 for (int xs = 0; xs < w; xs++) {
344                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
345                         if (mask == 0xFF || format != RTGFMT_8BIT) {
346                             SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format);
347                         }
348                         else {
349                             SET_RTG_PIXELS2_COND_MASK(&dptr[xs << format], fg_color[format], bg_color[format], format);
350                         }
351
352                         xs += 7;
353                     }
354                     else {
355                         while (cur_bit > 0 && xs < w) {
356                             if (mask == 0xFF || format != RTGFMT_8BIT) {
357                                 SET_RTG_PIXEL(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
358                             }
359                             else {
360                                 SET_RTG_PIXEL_MASK(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
361                             }
362                             xs++;
363                             cur_bit >>= 1;
364                         }
365                         xs--;
366                         cur_bit = 0x80;
367                     }
368                     TEMPLATE_LOOPX;
369                 }
370                 TEMPLATE_LOOPY;
371             }
372             return;
373         case DRAWMODE_COMPLEMENT:
374             for (uint16_t ys = 0; ys < h; ys++) {
375                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
376
377                 for (int xs = 0; xs < w; xs++) {
378                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
379                         INVERT_RTG_PIXELS(&dptr[xs << format], format)
380                         xs += 7;
381                     }
382                     else {
383                         while (cur_bit > 0 && xs < w) {
384                             if (cur_byte & cur_bit) {
385                                 INVERT_RTG_PIXEL(&dptr[xs << format], format)
386                             }
387                             xs++;
388                             cur_bit >>= 1;
389                         }
390                         xs--;
391                         cur_bit = 0x80;
392                     }
393                     TEMPLATE_LOOPX;
394                 }
395                 TEMPLATE_LOOPY;
396             }
397             return;
398     }
399 }
400
401 void rtg_blitpattern(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t src_addr, uint32_t fgcol, uint32_t bgcol, uint16_t pitch, uint16_t format, uint16_t offset_x, uint16_t offset_y, uint8_t mask, uint8_t draw_mode, uint8_t loop_rows) {
402     if (mask) {}
403
404     uint8_t *dptr = &rtg_mem[rtg_address_adj[1] + (x << format) + (y * pitch)];
405     uint8_t *sptr = NULL, *sptr_base = NULL;
406     uint8_t cur_bit = 0, base_bit = 0, cur_byte = 0;
407     uint8_t invert = (draw_mode & DRAWMODE_INVERSVID);
408     uint16_t tmpl_x = 0;
409
410     draw_mode &= 0x03;
411
412         tmpl_x = (offset_x / 8) % 2;
413     cur_bit = base_bit = (0x80 >> (offset_x % 8));
414
415     uint32_t fg_color[3] = {
416         (fgcol & 0xFF),
417         htobe16((fgcol & 0xFFFF)),
418         htobe32(fgcol),
419     };
420     uint32_t bg_color[3] = {
421         (bgcol & 0xFF),
422         htobe16((bgcol & 0xFFFF)),
423         htobe32(bgcol),
424     };
425
426
427     if (src_addr >= (PIGFX_RTG_BASE + PIGFX_REG_SIZE))
428         sptr = &rtg_mem[src_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE)];
429     else {
430         int i = get_mapped_item_by_address(cfg, src_addr);
431         if (i != -1) {
432             sptr = &cfg->map_data[i][src_addr - cfg->map_offset[i]];
433         }
434         else {
435             printf("BlitPattern: Failed to find mapped range for address %.8X\n", src_addr);
436             return;
437         }
438     }
439
440     sptr_base = sptr;
441     sptr += (offset_y % loop_rows) * 2;
442
443     switch (draw_mode) {
444         case DRAWMODE_JAM1:
445             for (uint16_t ys = 0; ys < h; ys++) {
446                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
447
448                 for (int xs = 0; xs < w; xs++) {
449                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
450                         if (mask == 0xFF || format != RTGFMT_8BIT) {
451                             SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format);
452                         }
453                         else {
454                             SET_RTG_PIXELS_MASK(&dptr[xs], fg_color[format], format);
455                         }
456                         xs += 7;
457                     }
458                     else {
459                         while (cur_bit > 0 && xs < w) {
460                             if (cur_byte & cur_bit) {
461                                 if (mask == 0xFF || format != RTGFMT_8BIT) {
462                                     SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format);
463                                 }
464                                 else {
465                                     SET_RTG_PIXEL_MASK(&dptr[xs], fg_color[format], format);
466                                 }
467                             }
468                             xs++;
469                             cur_bit >>= 1;
470                         }
471                         xs--;
472                         cur_bit = 0x80;
473                     }
474                     PATTERN_LOOPX;
475                 }
476                 PATTERN_LOOPY;
477             }
478             return;
479         case DRAWMODE_JAM2:
480             for (uint16_t ys = 0; ys < h; ys++) {
481                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
482
483                 for (int xs = 0; xs < w; xs++) {
484                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
485                         if (mask == 0xFF || format != RTGFMT_8BIT) {
486                             SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format);
487                         }
488                         else {
489                             SET_RTG_PIXELS2_COND_MASK(&dptr[xs << format], fg_color[format], bg_color[format], format);
490                         }
491
492                         xs += 7;
493                     }
494                     else {
495                         while (cur_bit > 0 && xs < w) {
496                             if (mask == 0xFF || format != RTGFMT_8BIT) {
497                                 SET_RTG_PIXEL(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
498                             }
499                             else {
500                                 SET_RTG_PIXEL_MASK(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
501                             }
502                             xs++;
503                             cur_bit >>= 1;
504                         }
505                         xs--;
506                         cur_bit = 0x80;
507                     }
508                     PATTERN_LOOPX;
509                 }
510                 PATTERN_LOOPY;
511             }
512             return;
513         case DRAWMODE_COMPLEMENT:
514             for (uint16_t ys = 0; ys < h; ys++) {
515                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
516
517                 for (int xs = 0; xs < w; xs++) {
518                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
519                         INVERT_RTG_PIXELS(&dptr[xs << format], format)
520                         xs += 7;
521                     }
522                     else {
523                         while (cur_bit > 0 && xs < w) {
524                             if (cur_byte & cur_bit) {
525                                 INVERT_RTG_PIXEL(&dptr[xs << format], format)
526                             }
527                             xs++;
528                             cur_bit >>= 1;
529                         }
530                         xs--;
531                         cur_bit = 0x80;
532                     }
533                     PATTERN_LOOPX;
534                 }
535                 PATTERN_LOOPY;
536             }
537             return;
538     }
539 }
540
541 void rtg_drawline_solid(int16_t x1_, int16_t y1_, int16_t x2_, int16_t y2_, uint16_t len, uint32_t fgcol, uint16_t pitch, uint16_t format) {
542         int16_t x1 = x1_, y1 = y1_;
543         int16_t x2 = x1_ + x2_, y2 = y1 + y2_;
544
545     uint32_t fg_color[3] = {
546         (fgcol & 0xFF),
547         htobe16((fgcol & 0xFFFF)),
548         htobe32(fgcol),
549     };
550
551     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (y1 * pitch)];
552
553         int32_t line_step = pitch;
554         int8_t x_step = 1;
555
556         int16_t dx, dy, dx_abs, dy_abs, ix, iy, x = x1;
557
558         if (x2 < x1)
559                 x_step = -1;
560         if (y2 < y1)
561                 line_step = -pitch;
562
563         dx = x2 - x1;
564         dy = y2 - y1;
565         dx_abs = abs(dx);
566         dy_abs = abs(dy);
567         ix = dy_abs >> 1;
568         iy = dx_abs >> 1;
569
570     SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format);
571
572         if (dx_abs >= dy_abs) {
573                 if (!len) len = dx_abs;
574                 for (uint16_t i = 0; i < len; i++) {
575                         iy += dy_abs;
576                         if (iy >= dx_abs) {
577                                 iy -= dx_abs;
578                                 dptr += line_step;
579                         }
580                         x += x_step;
581
582             SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format);
583                 }
584         }
585         else {
586                 if (!len) len = dy_abs;
587                 for (uint16_t i = 0; i < len; i++) {
588                         ix += dx_abs;
589                         if (ix >= dy_abs) {
590                                 ix -= dy_abs;
591                                 x += x_step;
592                         }
593                         dptr += line_step;
594
595                         SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format);
596                 }
597         }
598 }
599
600 #define DRAW_LINE_PIXEL \
601     if (pattern & cur_bit) { \
602         if (invert) { INVERT_RTG_PIXEL(&dptr[x << format], format) } \
603         else { \
604             if (mask == 0xFF || format != RTGFMT_8BIT) { SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format); } \
605             else { SET_RTG_PIXEL_MASK(&dptr[x << format], fg_color[format], format); } \
606         } \
607     } \
608     else if (draw_mode == DRAWMODE_JAM2) { \
609         if (invert) { INVERT_RTG_PIXEL(&dptr[x << format], format) } \
610         else { \
611             if (mask == 0xFF || format != RTGFMT_8BIT) { SET_RTG_PIXEL(&dptr[x << format], bg_color[format], format); } \
612             else { SET_RTG_PIXEL_MASK(&dptr[x << format], bg_color[format], format); } \
613         } \
614     } \
615     if ((cur_bit >>= 1) == 0) \
616             cur_bit = 0x8000;
617
618 void rtg_drawline (int16_t x1_, int16_t y1_, int16_t x2_, int16_t y2_, uint16_t len, uint16_t pattern, uint16_t pattern_offset, uint32_t fgcol, uint32_t bgcol, uint16_t pitch, uint16_t format, uint8_t mask, uint8_t draw_mode) {
619     if (pattern_offset) {}
620
621         int16_t x1 = x1_, y1 = y1_;
622         int16_t x2 = x1_ + x2_, y2 = y1 + y2_;
623     uint16_t cur_bit = 0x8000;
624     //uint32_t color_mask = 0xFFFF0000;
625     uint8_t invert = 0;
626
627     uint32_t fg_color[3] = {
628         (fgcol & 0xFF),
629         htobe16((fgcol & 0xFFFF)),
630         htobe32(fgcol),
631     };
632     uint32_t bg_color[3] = {
633         (bgcol & 0xFF),
634         htobe16((bgcol & 0xFFFF)),
635         htobe32(bgcol),
636     };
637
638     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (y1 * pitch)];
639
640         int32_t line_step = pitch;
641         int8_t x_step = 1;
642
643         int16_t dx, dy, dx_abs, dy_abs, ix, iy, x = x1;
644
645         if (x2 < x1)
646                 x_step = -1;
647         if (y2 < y1)
648                 line_step = -pitch;
649
650         dx = x2 - x1;
651         dy = y2 - y1;
652         dx_abs = abs(dx);
653         dy_abs = abs(dy);
654         ix = dy_abs >> 1;
655         iy = dx_abs >> 1;
656
657     if (draw_mode & DRAWMODE_INVERSVID)
658         pattern = ~pattern;
659     if (draw_mode & DRAWMODE_COMPLEMENT) {
660         invert = 1;
661     }
662     draw_mode &= 0x01;
663
664     DRAW_LINE_PIXEL;
665
666         if (dx_abs >= dy_abs) {
667                 if (!len) len = dx_abs;
668                 for (uint16_t i = 0; i < len; i++) {
669                         iy += dy_abs;
670                         if (iy >= dx_abs) {
671                                 iy -= dx_abs;
672                                 dptr += line_step;
673                         }
674                         x += x_step;
675
676             DRAW_LINE_PIXEL;
677                 }
678         }
679         else {
680                 if (!len) len = dy_abs;
681                 for (uint16_t i = 0; i < len; i++) {
682                         ix += dx_abs;
683                         if (ix >= dy_abs) {
684                                 ix -= dy_abs;
685                                 x += x_step;
686                         }
687                         dptr += line_step;
688
689                         DRAW_LINE_PIXEL;
690                 }
691         }
692 }
693
694 void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t h, uint8_t draw_mode, uint8_t planes, uint8_t mask, uint8_t layer_mask, uint16_t src_line_pitch, uint8_t *bmp_data_src) {
695     uint16_t pitch = rtg_x[3];
696     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dy * pitch)];
697
698         uint8_t cur_bit, base_bit, base_byte;
699         uint16_t cur_byte = 0, u8_fg = 0;
700     //uint32_t color_mask = 0xFFFFFFFF;
701
702         uint32_t plane_size = src_line_pitch * h;
703         uint8_t *bmp_data = bmp_data_src;
704
705         cur_bit = base_bit = (0x80 >> (sx % 8));
706         cur_byte = base_byte = ((sx / 8) % src_line_pitch);
707
708     if (realtime_graphics_debug) {
709         printf("P2C: %d,%d - %d,%d (%dx%d) %d, %.2X\n", sx, sy, dx, dy, w, h, planes, layer_mask);
710         printf("Mask: %.2X Minterm: %.2X\n", mask, draw_mode);
711         printf("Pitch: %d Src Pitch: %d (!!!: %.4X)\n", pitch, src_line_pitch, rtg_user[0]);
712         printf("Curbyte: %d Curbit: %d\n", cur_byte, cur_bit);
713         printf("Plane size: %d Total size: %d (%X)\n", plane_size, plane_size * planes, plane_size * planes);
714         printf("Source: %.8X - %.8X\n", rtg_address[1], rtg_address_adj[1]);
715         printf("Target: %.8X - %.8X\n", rtg_address[0], rtg_address_adj[0]);
716         fflush(stdout);
717
718         printf("Grabbing data from RTG memory.\nData:\n");
719         for (int i = 0; i < h; i++) {
720             for (int k = 0; k < planes; k++) {
721                 for (int j = 0; j < src_line_pitch; j++) {
722                     printf("%.2X", bmp_data_src[j + (i * src_line_pitch) + (plane_size * k)]);
723                 }
724                 printf("  ");
725             }
726             printf("\n");
727         }
728     }
729
730         for (int16_t line_y = 0; line_y < h; line_y++) {
731                 for (int16_t x = dx; x < dx + w; x++) {
732                         u8_fg = 0;
733                         if (draw_mode & 0x01) {
734                                 DECODE_INVERTED_PLANAR_PIXEL(u8_fg)
735             }
736                         else {
737                                 DECODE_PLANAR_PIXEL(u8_fg)
738             }
739
740                         if (mask == 0xFF && (draw_mode == MINTERM_SRC || draw_mode == MINTERM_NOTSRC)) {
741                                 dptr[x] = u8_fg;
742                                 goto skip;
743                         }
744
745             HANDLE_MINTERM_PIXEL(u8_fg, dptr[x], rtg_display_format);
746
747                         skip:;
748                         if ((cur_bit >>= 1) == 0) {
749                                 cur_bit = 0x80;
750                                 cur_byte++;
751                                 cur_byte %= src_line_pitch;
752                         }
753                 }
754                 dptr += pitch;
755                 if ((line_y + sy + 1) % h)
756                         bmp_data += src_line_pitch;
757                 else
758                         bmp_data = bmp_data_src;
759                 cur_bit = base_bit;
760                 cur_byte = base_byte;
761         }
762 }
763
764 void rtg_p2d (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t h, uint8_t draw_mode, uint8_t planes, uint8_t mask, uint8_t layer_mask, uint16_t src_line_pitch, uint8_t *bmp_data_src) {
765     uint16_t pitch = rtg_x[3];
766     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dy * pitch)];
767
768         uint8_t cur_bit, base_bit, base_byte;
769         uint16_t cur_byte = 0, u8_fg = 0;
770     //uint32_t color_mask = 0xFFFFFFFF;
771
772         uint32_t plane_size = src_line_pitch * h;
773         uint8_t *bmp_data = bmp_data_src;
774
775         cur_bit = base_bit = (0x80 >> (sx % 8));
776         cur_byte = base_byte = ((sx / 8) % src_line_pitch);
777
778     if (realtime_graphics_debug) {
779         printf("P2D: %d,%d - %d,%d (%dx%d) %d, %.2X\n", sx, sy, dx, dy, w, h, planes, layer_mask);
780         printf("Mask: %.2X Minterm: %.2X\n", mask, draw_mode);
781         printf("Pitch: %d Src Pitch: %d (!!!: %.4X)\n", pitch, src_line_pitch, rtg_user[0]);
782         printf("Curbyte: %d Curbit: %d\n", cur_byte, cur_bit);
783         printf("Plane size: %d Total size: %d (%X)\n", plane_size, plane_size * planes, plane_size * planes);
784         printf("Source: %.8X - %.8X\n", rtg_address[1], rtg_address_adj[1]);
785         printf("Target: %.8X - %.8X\n", rtg_address[0], rtg_address_adj[0]);
786         fflush(stdout);
787
788         printf("Grabbing data from RTG memory.\nData:\n");
789         for (int i = 0; i < h; i++) {
790             for (int k = 0; k < planes; k++) {
791                 for (int j = 0; j < src_line_pitch; j++) {
792                     printf("%.2X", bmp_data_src[j + (i * src_line_pitch) + (plane_size * k)]);
793                 }
794                 printf("  ");
795             }
796             printf("\n");
797         }
798     }
799
800     uint32_t *clut = (uint32_t *)bmp_data_src;
801     bmp_data += (256 * 4);
802     bmp_data_src += (256 * 4);
803
804         for (int16_t line_y = 0; line_y < h; line_y++) {
805                 for (int16_t x = dx; x < dx + w; x++) {
806                         u8_fg = 0;
807                         if (draw_mode & 0x01) {
808                                 DECODE_INVERTED_PLANAR_PIXEL(u8_fg)
809             }
810                         else {
811                                 DECODE_PLANAR_PIXEL(u8_fg)
812             }
813
814             uint32_t fg_color = clut[u8_fg];
815
816                         if (mask == 0xFF && (draw_mode == MINTERM_SRC || draw_mode == MINTERM_NOTSRC)) {
817                                 switch (rtg_display_format) {
818                                         case RTGFMT_RBG565:
819                                                 ((uint16_t *)dptr)[x] = (fg_color >> 16);
820                                                 break;
821                                         case RTGFMT_RGB32:
822                                                 ((uint32_t *)dptr)[x] = fg_color;
823                                                 break;
824                                 }
825                                 goto skip;
826                         }
827
828                         skip:;
829                         if ((cur_bit >>= 1) == 0) {
830                                 cur_bit = 0x80;
831                                 cur_byte++;
832                                 cur_byte %= src_line_pitch;
833                         }
834                 }
835                 dptr += pitch;
836                 if ((line_y + sy + 1) % h)
837                         bmp_data += src_line_pitch;
838                 else
839                         bmp_data = bmp_data_src;
840                 cur_bit = base_bit;
841                 cur_byte = base_byte;
842         }
843 }