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