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