]> git.sesse.net Git - pistorm/blob - platforms/amiga/rtg/rtg-gfx.c
iRTG initial implementation
[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     if (mask) {}
231
232     uint8_t *dptr = &rtg_mem[rtg_address_adj[1] + (x << format) + (y * pitch)];
233     uint8_t *sptr = NULL;
234     uint8_t cur_bit = 0, base_bit = 0, cur_byte = 0;
235     uint8_t invert = (draw_mode & DRAWMODE_INVERSVID);
236     uint16_t tmpl_x = 0;
237
238     draw_mode &= 0x03;
239
240         tmpl_x = offset_x / 8;
241     cur_bit = base_bit = (0x80 >> (offset_x % 8));
242
243     if (realtime_graphics_debug) {
244         printf("DEBUG: BlitTemplate - %d, %d (%dx%d)\n", x, y, w, h);
245         printf("Src: %.8X (%.8X)\n", src_addr, rtg_address_adj[0]);
246         printf("Dest: %.8X (%.8X)\n", rtg_address[1], rtg_address_adj[1]);
247         printf("pitch: %d t_pitch: %d format: %d\n", pitch, t_pitch, format);
248         printf("offset_x: %d mask: %.2X draw_mode: %d\n", offset_x, mask, draw_mode);
249     }
250
251     uint32_t fg_color[3] = {
252         (fgcol & 0xFF),
253         htobe16((fgcol & 0xFFFF)),
254         htobe32(fgcol),
255     };
256     uint32_t bg_color[3] = {
257         (bgcol & 0xFF),
258         htobe16((bgcol & 0xFFFF)),
259         htobe32(bgcol),
260     };
261
262     if (src_addr >= (PIGFX_RTG_BASE + PIGFX_REG_SIZE)) {
263         sptr = &rtg_mem[src_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE)];
264         if (realtime_graphics_debug) {
265             printf("Origin: %.8X\n", rtg_address[2]);
266             printf("Grabbing data from RTG memory.\nData:\n");
267             for (int i = 0; i < h; i++) {
268                 for (int j = 0; j < t_pitch; j++) {
269                     printf("%.2X", sptr[j + (i * t_pitch)]);
270                 }
271                 printf("\n");
272             }
273 #ifndef FAKESTORM
274             printf("Data available at origin:\n");
275             for (int i = 0; i < h; i++) {
276                 for (int j = 0; j < w; j++) {
277                     printf("%.2X", read8(rtg_address[2] + j + (i * t_pitch)));
278                 }
279                 printf("\n");
280             }
281 #endif
282         }
283     }
284     else {
285         int i = get_mapped_item_by_address(cfg, src_addr);
286         if (i != -1) {
287             sptr = &cfg->map_data[i][src_addr - cfg->map_offset[i]];
288             if (realtime_graphics_debug) {
289                 printf("Grabbing data from maping %d - offset %.8lX\nData:\n", i, src_addr - cfg->map_offset[i]);
290                 for (int i = 0; i < h; i++) {
291                     for (int j = 0; j < t_pitch; j++) {
292                         printf("%.2X", sptr[j + (i * t_pitch)]);
293                     }
294                     printf("\n");
295                 }
296             }
297         }
298         else {
299             printf("BlitTemplate: Failed to find mapped range for address %.8X\n", src_addr);
300             return;
301         }
302     }
303
304     switch (draw_mode) {
305         case DRAWMODE_JAM1:
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                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
311                         if (mask == 0xFF || format != RTGFMT_8BIT) {
312                             SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format);
313                         }
314                         else {
315                             SET_RTG_PIXELS_MASK(&dptr[xs], fg_color[format], format);
316                         }
317                         xs += 7;
318                     }
319                     else {
320                         while (cur_bit > 0 && xs < w) {
321                             if (cur_byte & cur_bit) {
322                                 if (mask == 0xFF || format != RTGFMT_8BIT) {
323                                     SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format);
324                                 }
325                                 else {
326                                     SET_RTG_PIXEL_MASK(&dptr[xs], fg_color[format], format);
327                                 }
328                             }
329                             xs++;
330                             cur_bit >>= 1;
331                         }
332                         xs--;
333                         cur_bit = 0x80;
334                     }
335                     TEMPLATE_LOOPX;
336                 }
337                 TEMPLATE_LOOPY;
338             }
339             return;
340         case DRAWMODE_JAM2:
341             for (uint16_t ys = 0; ys < h; ys++) {
342                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
343
344                 for (int xs = 0; xs < w; xs++) {
345                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
346                         if (mask == 0xFF || format != RTGFMT_8BIT) {
347                             SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format);
348                         }
349                         else {
350                             SET_RTG_PIXELS2_COND_MASK(&dptr[xs << format], fg_color[format], bg_color[format], format);
351                         }
352
353                         xs += 7;
354                     }
355                     else {
356                         while (cur_bit > 0 && xs < w) {
357                             if (mask == 0xFF || format != RTGFMT_8BIT) {
358                                 SET_RTG_PIXEL(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
359                             }
360                             else {
361                                 SET_RTG_PIXEL_MASK(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
362                             }
363                             xs++;
364                             cur_bit >>= 1;
365                         }
366                         xs--;
367                         cur_bit = 0x80;
368                     }
369                     TEMPLATE_LOOPX;
370                 }
371                 TEMPLATE_LOOPY;
372             }
373             return;
374         case DRAWMODE_COMPLEMENT:
375             for (uint16_t ys = 0; ys < h; ys++) {
376                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
377
378                 for (int xs = 0; xs < w; xs++) {
379                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
380                         INVERT_RTG_PIXELS(&dptr[xs << format], format)
381                         xs += 7;
382                     }
383                     else {
384                         while (cur_bit > 0 && xs < w) {
385                             if (cur_byte & cur_bit) {
386                                 INVERT_RTG_PIXEL(&dptr[xs << format], format)
387                             }
388                             xs++;
389                             cur_bit >>= 1;
390                         }
391                         xs--;
392                         cur_bit = 0x80;
393                     }
394                     TEMPLATE_LOOPX;
395                 }
396                 TEMPLATE_LOOPY;
397             }
398             return;
399     }
400 }
401
402 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) {
403     if (mask) {}
404
405     uint8_t *dptr = &rtg_mem[rtg_address_adj[1] + (x << format) + (y * pitch)];
406     uint8_t *sptr = NULL, *sptr_base = NULL;
407     uint8_t cur_bit = 0, base_bit = 0, cur_byte = 0;
408     uint8_t invert = (draw_mode & DRAWMODE_INVERSVID);
409     uint16_t tmpl_x = 0;
410
411     draw_mode &= 0x03;
412
413         tmpl_x = (offset_x / 8) % 2;
414     cur_bit = base_bit = (0x80 >> (offset_x % 8));
415
416     uint32_t fg_color[3] = {
417         (fgcol & 0xFF),
418         htobe16((fgcol & 0xFFFF)),
419         htobe32(fgcol),
420     };
421     uint32_t bg_color[3] = {
422         (bgcol & 0xFF),
423         htobe16((bgcol & 0xFFFF)),
424         htobe32(bgcol),
425     };
426
427
428     if (src_addr >= (PIGFX_RTG_BASE + PIGFX_REG_SIZE))
429         sptr = &rtg_mem[src_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE)];
430     else {
431         int i = get_mapped_item_by_address(cfg, src_addr);
432         if (i != -1) {
433             sptr = &cfg->map_data[i][src_addr - cfg->map_offset[i]];
434         }
435         else {
436             printf("BlitPattern: Failed to find mapped range for address %.8X\n", src_addr);
437             return;
438         }
439     }
440
441     sptr_base = sptr;
442     sptr += (offset_y % loop_rows) * 2;
443
444     switch (draw_mode) {
445         case DRAWMODE_JAM1:
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_PIXELS(&dptr[xs << format], fg_color[format], format);
453                         }
454                         else {
455                             SET_RTG_PIXELS_MASK(&dptr[xs], fg_color[format], format);
456                         }
457                         xs += 7;
458                     }
459                     else {
460                         while (cur_bit > 0 && xs < w) {
461                             if (cur_byte & cur_bit) {
462                                 if (mask == 0xFF || format != RTGFMT_8BIT) {
463                                     SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format);
464                                 }
465                                 else {
466                                     SET_RTG_PIXEL_MASK(&dptr[xs], fg_color[format], format);
467                                 }
468                             }
469                             xs++;
470                             cur_bit >>= 1;
471                         }
472                         xs--;
473                         cur_bit = 0x80;
474                     }
475                     PATTERN_LOOPX;
476                 }
477                 PATTERN_LOOPY;
478             }
479             return;
480         case DRAWMODE_JAM2:
481             for (uint16_t ys = 0; ys < h; ys++) {
482                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
483
484                 for (int xs = 0; xs < w; xs++) {
485                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
486                         if (mask == 0xFF || format != RTGFMT_8BIT) {
487                             SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format);
488                         }
489                         else {
490                             SET_RTG_PIXELS2_COND_MASK(&dptr[xs << format], fg_color[format], bg_color[format], format);
491                         }
492
493                         xs += 7;
494                     }
495                     else {
496                         while (cur_bit > 0 && xs < w) {
497                             if (mask == 0xFF || format != RTGFMT_8BIT) {
498                                 SET_RTG_PIXEL(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
499                             }
500                             else {
501                                 SET_RTG_PIXEL_MASK(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format);
502                             }
503                             xs++;
504                             cur_bit >>= 1;
505                         }
506                         xs--;
507                         cur_bit = 0x80;
508                     }
509                     PATTERN_LOOPX;
510                 }
511                 PATTERN_LOOPY;
512             }
513             return;
514         case DRAWMODE_COMPLEMENT:
515             for (uint16_t ys = 0; ys < h; ys++) {
516                 cur_byte = (invert) ? sptr[tmpl_x] ^ 0xFF : sptr[tmpl_x];
517
518                 for (int xs = 0; xs < w; xs++) {
519                     if (w >= 8 && cur_bit == 0x80 && xs < w - 8) {
520                         INVERT_RTG_PIXELS(&dptr[xs << format], format)
521                         xs += 7;
522                     }
523                     else {
524                         while (cur_bit > 0 && xs < w) {
525                             if (cur_byte & cur_bit) {
526                                 INVERT_RTG_PIXEL(&dptr[xs << format], format)
527                             }
528                             xs++;
529                             cur_bit >>= 1;
530                         }
531                         xs--;
532                         cur_bit = 0x80;
533                     }
534                     PATTERN_LOOPX;
535                 }
536                 PATTERN_LOOPY;
537             }
538             return;
539     }
540 }
541
542 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) {
543         int16_t x1 = x1_, y1 = y1_;
544         int16_t x2 = x1_ + x2_, y2 = y1 + y2_;
545
546     uint32_t fg_color[3] = {
547         (fgcol & 0xFF),
548         htobe16((fgcol & 0xFFFF)),
549         htobe32(fgcol),
550     };
551
552     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (y1 * pitch)];
553
554         int32_t line_step = pitch;
555         int8_t x_step = 1;
556
557         int16_t dx, dy, dx_abs, dy_abs, ix, iy, x = x1;
558
559         if (x2 < x1)
560                 x_step = -1;
561         if (y2 < y1)
562                 line_step = -pitch;
563
564         dx = x2 - x1;
565         dy = y2 - y1;
566         dx_abs = abs(dx);
567         dy_abs = abs(dy);
568         ix = dy_abs >> 1;
569         iy = dx_abs >> 1;
570
571     SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format);
572
573         if (dx_abs >= dy_abs) {
574                 if (!len) len = dx_abs;
575                 for (uint16_t i = 0; i < len; i++) {
576                         iy += dy_abs;
577                         if (iy >= dx_abs) {
578                                 iy -= dx_abs;
579                                 dptr += line_step;
580                         }
581                         x += x_step;
582
583             SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format);
584                 }
585         }
586         else {
587                 if (!len) len = dy_abs;
588                 for (uint16_t i = 0; i < len; i++) {
589                         ix += dx_abs;
590                         if (ix >= dy_abs) {
591                                 ix -= dy_abs;
592                                 x += x_step;
593                         }
594                         dptr += line_step;
595
596                         SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format);
597                 }
598         }
599 }
600
601 #define DRAW_LINE_PIXEL \
602     if (pattern & cur_bit) { \
603         if (invert) { INVERT_RTG_PIXEL(&dptr[x << format], format) } \
604         else { \
605             if (mask == 0xFF || format != RTGFMT_8BIT) { SET_RTG_PIXEL(&dptr[x << format], fg_color[format], format); } \
606             else { SET_RTG_PIXEL_MASK(&dptr[x << format], fg_color[format], format); } \
607         } \
608     } \
609     else if (draw_mode == DRAWMODE_JAM2) { \
610         if (invert) { INVERT_RTG_PIXEL(&dptr[x << format], format) } \
611         else { \
612             if (mask == 0xFF || format != RTGFMT_8BIT) { SET_RTG_PIXEL(&dptr[x << format], bg_color[format], format); } \
613             else { SET_RTG_PIXEL_MASK(&dptr[x << format], bg_color[format], format); } \
614         } \
615     } \
616     if ((cur_bit >>= 1) == 0) \
617             cur_bit = 0x8000;
618
619 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) {
620     if (pattern_offset) {}
621
622         int16_t x1 = x1_, y1 = y1_;
623         int16_t x2 = x1_ + x2_, y2 = y1 + y2_;
624     uint16_t cur_bit = 0x8000;
625     //uint32_t color_mask = 0xFFFF0000;
626     uint8_t invert = 0;
627
628     uint32_t fg_color[3] = {
629         (fgcol & 0xFF),
630         htobe16((fgcol & 0xFFFF)),
631         htobe32(fgcol),
632     };
633     uint32_t bg_color[3] = {
634         (bgcol & 0xFF),
635         htobe16((bgcol & 0xFFFF)),
636         htobe32(bgcol),
637     };
638
639     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (y1 * pitch)];
640
641         int32_t line_step = pitch;
642         int8_t x_step = 1;
643
644         int16_t dx, dy, dx_abs, dy_abs, ix, iy, x = x1;
645
646         if (x2 < x1)
647                 x_step = -1;
648         if (y2 < y1)
649                 line_step = -pitch;
650
651         dx = x2 - x1;
652         dy = y2 - y1;
653         dx_abs = abs(dx);
654         dy_abs = abs(dy);
655         ix = dy_abs >> 1;
656         iy = dx_abs >> 1;
657
658     if (draw_mode & DRAWMODE_INVERSVID)
659         pattern = ~pattern;
660     if (draw_mode & DRAWMODE_COMPLEMENT) {
661         invert = 1;
662     }
663     draw_mode &= 0x01;
664
665     DRAW_LINE_PIXEL;
666
667         if (dx_abs >= dy_abs) {
668                 if (!len) len = dx_abs;
669                 for (uint16_t i = 0; i < len; i++) {
670                         iy += dy_abs;
671                         if (iy >= dx_abs) {
672                                 iy -= dx_abs;
673                                 dptr += line_step;
674                         }
675                         x += x_step;
676
677             DRAW_LINE_PIXEL;
678                 }
679         }
680         else {
681                 if (!len) len = dy_abs;
682                 for (uint16_t i = 0; i < len; i++) {
683                         ix += dx_abs;
684                         if (ix >= dy_abs) {
685                                 ix -= dy_abs;
686                                 x += x_step;
687                         }
688                         dptr += line_step;
689
690                         DRAW_LINE_PIXEL;
691                 }
692         }
693 }
694
695 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) {
696     uint16_t pitch = rtg_x[3];
697     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dy * pitch)];
698
699         uint8_t cur_bit, base_bit, base_byte;
700         uint16_t cur_byte = 0, u8_fg = 0;
701     //uint32_t color_mask = 0xFFFFFFFF;
702
703         uint32_t plane_size = src_line_pitch * h;
704         uint8_t *bmp_data = bmp_data_src;
705
706         cur_bit = base_bit = (0x80 >> (sx % 8));
707         cur_byte = base_byte = ((sx / 8) % src_line_pitch);
708
709     if (realtime_graphics_debug) {
710         printf("P2C: %d,%d - %d,%d (%dx%d) %d, %.2X\n", sx, sy, dx, dy, w, h, planes, layer_mask);
711         printf("Mask: %.2X Minterm: %.2X\n", mask, draw_mode);
712         printf("Pitch: %d Src Pitch: %d (!!!: %.4X)\n", pitch, src_line_pitch, rtg_user[0]);
713         printf("Curbyte: %d Curbit: %d\n", cur_byte, cur_bit);
714         printf("Plane size: %d Total size: %d (%X)\n", plane_size, plane_size * planes, plane_size * planes);
715         printf("Source: %.8X - %.8X\n", rtg_address[1], rtg_address_adj[1]);
716         printf("Target: %.8X - %.8X\n", rtg_address[0], rtg_address_adj[0]);
717         fflush(stdout);
718
719         printf("Grabbing data from RTG memory.\nData:\n");
720         for (int i = 0; i < h; i++) {
721             for (int k = 0; k < planes; k++) {
722                 for (int j = 0; j < src_line_pitch; j++) {
723                     printf("%.2X", bmp_data_src[j + (i * src_line_pitch) + (plane_size * k)]);
724                 }
725                 printf("  ");
726             }
727             printf("\n");
728         }
729     }
730
731         for (int16_t line_y = 0; line_y < h; line_y++) {
732                 for (int16_t x = dx; x < dx + w; x++) {
733                         u8_fg = 0;
734                         if (draw_mode & 0x01) {
735                                 DECODE_INVERTED_PLANAR_PIXEL(u8_fg)
736             }
737                         else {
738                                 DECODE_PLANAR_PIXEL(u8_fg)
739             }
740
741                         if (mask == 0xFF && (draw_mode == MINTERM_SRC || draw_mode == MINTERM_NOTSRC)) {
742                                 dptr[x] = u8_fg;
743                                 goto skip;
744                         }
745
746             HANDLE_MINTERM_PIXEL(u8_fg, dptr[x], rtg_display_format);
747
748                         skip:;
749                         if ((cur_bit >>= 1) == 0) {
750                                 cur_bit = 0x80;
751                                 cur_byte++;
752                                 cur_byte %= src_line_pitch;
753                         }
754                 }
755                 dptr += pitch;
756                 if ((line_y + sy + 1) % h)
757                         bmp_data += src_line_pitch;
758                 else
759                         bmp_data = bmp_data_src;
760                 cur_bit = base_bit;
761                 cur_byte = base_byte;
762         }
763 }
764
765 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) {
766     uint16_t pitch = rtg_x[3];
767     uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dy * pitch)];
768
769         uint8_t cur_bit, base_bit, base_byte;
770         uint16_t cur_byte = 0, u8_fg = 0;
771     //uint32_t color_mask = 0xFFFFFFFF;
772
773         uint32_t plane_size = src_line_pitch * h;
774         uint8_t *bmp_data = bmp_data_src;
775
776         cur_bit = base_bit = (0x80 >> (sx % 8));
777         cur_byte = base_byte = ((sx / 8) % src_line_pitch);
778
779     if (realtime_graphics_debug) {
780         printf("P2D: %d,%d - %d,%d (%dx%d) %d, %.2X\n", sx, sy, dx, dy, w, h, planes, layer_mask);
781         printf("Mask: %.2X Minterm: %.2X\n", mask, draw_mode);
782         printf("Pitch: %d Src Pitch: %d (!!!: %.4X)\n", pitch, src_line_pitch, rtg_user[0]);
783         printf("Curbyte: %d Curbit: %d\n", cur_byte, cur_bit);
784         printf("Plane size: %d Total size: %d (%X)\n", plane_size, plane_size * planes, plane_size * planes);
785         printf("Source: %.8X - %.8X\n", rtg_address[1], rtg_address_adj[1]);
786         printf("Target: %.8X - %.8X\n", rtg_address[0], rtg_address_adj[0]);
787         fflush(stdout);
788
789         printf("Grabbing data from RTG memory.\nData:\n");
790         for (int i = 0; i < h; i++) {
791             for (int k = 0; k < planes; k++) {
792                 for (int j = 0; j < src_line_pitch; j++) {
793                     printf("%.2X", bmp_data_src[j + (i * src_line_pitch) + (plane_size * k)]);
794                 }
795                 printf("  ");
796             }
797             printf("\n");
798         }
799     }
800
801     uint32_t *clut = (uint32_t *)bmp_data_src;
802     bmp_data += (256 * 4);
803     bmp_data_src += (256 * 4);
804
805         for (int16_t line_y = 0; line_y < h; line_y++) {
806                 for (int16_t x = dx; x < dx + w; x++) {
807                         u8_fg = 0;
808                         if (draw_mode & 0x01) {
809                                 DECODE_INVERTED_PLANAR_PIXEL(u8_fg)
810             }
811                         else {
812                                 DECODE_PLANAR_PIXEL(u8_fg)
813             }
814
815             uint32_t fg_color = clut[u8_fg];
816
817                         if (mask == 0xFF && (draw_mode == MINTERM_SRC || draw_mode == MINTERM_NOTSRC)) {
818                                 switch (rtg_display_format) {
819                                         case RTGFMT_RBG565:
820                                                 ((uint16_t *)dptr)[x] = (fg_color >> 16);
821                                                 break;
822                                         case RTGFMT_RGB32:
823                                                 ((uint32_t *)dptr)[x] = fg_color;
824                                                 break;
825                                 }
826                                 goto skip;
827                         }
828
829                         skip:;
830                         if ((cur_bit >>= 1) == 0) {
831                                 cur_bit = 0x80;
832                                 cur_byte++;
833                                 cur_byte %= src_line_pitch;
834                         }
835                 }
836                 dptr += pitch;
837                 if ((line_y + sy + 1) % h)
838                         bmp_data += src_line_pitch;
839                 else
840                         bmp_data = bmp_data_src;
841                 cur_bit = base_bit;
842                 cur_byte = base_byte;
843         }
844 }