+#define M68KR(a) m68k_get_reg(NULL, a)
+#define RGBF_D7 rgbf_to_rtg[M68KR(M68K_REG_D7)]
+#define CMD_PITCH be16toh(r->BytesPerRow)
+
+static struct P96RenderInfo *r;
+static struct P96BoardInfo *b;
+static struct P96Line *ln;
+static uint8_t cmd_mask;
+
+static void handle_irtg_command(uint32_t cmd) {
+ b = (struct P96BoardInfo *)get_mapped_data_pointer_by_address(cfg, M68KR(M68K_REG_A0));
+ r = (struct P96RenderInfo *)get_mapped_data_pointer_by_address(cfg, M68KR(M68K_REG_A1));
+
+ switch (cmd) {
+ case RTGCMD_SETPAN: {
+ // A0: struct BoardInfo *b, A1: UBYTE *addr, D0 UWORD width, D1: WORD x_offset, D2: WORD y_offset, D7: RGBFTYPE format
+#ifdef DEBUG_RTG
+ if (realtime_graphics_debug) {
+ printf("iSetPanning begin\n");
+ printf("IRTGCmd SetPanning\n");
+ printf("IRTGCmd x: %d y: %d w: %d (%d)\n", M68KR(M68K_REG_D1), M68KR(M68K_REG_D2), M68KR(M68K_REG_D0) << RGBF_D7, M68KR(M68K_REG_D0));
+ printf("BoardInfo: %.8X Addr: %.8X\n", M68KR(M68K_REG_A0), M68KR(M68K_REG_A1));
+ printf("BoardInfo Xoffs: %d Yoffs: %d\n", be16toh(b->XOffset), be16toh(b->YOffset));
+ }
+#endif
+ if (!b) break;
+
+ b->XOffset = (int16_t)htobe16(M68KR(M68K_REG_D1));
+ b->YOffset = (int16_t)htobe16(M68KR(M68K_REG_D2));
+
+ rtg_offset_x = M68KR(M68K_REG_D1);
+ rtg_offset_y = M68KR(M68K_REG_D2);
+ rtg_pitch = (M68KR(M68K_REG_D0) << RGBF_D7);
+ framebuffer_addr = M68KR(M68K_REG_A1) - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
+ framebuffer_addr_adj = framebuffer_addr + (rtg_offset_x << RGBF_D7) + (rtg_offset_y * rtg_pitch);
+
+#ifdef DEBUG_RTG
+ if (realtime_graphics_debug) {
+ printf("RTG OffsetX/Y: %d/%d\n", rtg_offset_x, rtg_offset_y);
+ printf("RTG Pitch: %d\n", rtg_pitch);
+ printf("RTG FBAddr/Adj: %.8X (%.8X)/%.8X\n", framebuffer_addr, M68KR(M68K_REG_A1), framebuffer_addr_adj);
+ printf("iSetPanning End\n");
+ }
+#endif
+
+ break;
+ }
+ case RTGCMD_DRAWLINE: {
+ // A0: struct BoardInfo *b, A1: RenderInfo *r A2: struct Line *l, D0: UBYTE mask, D7: RGBFTYPE format
+ gdebug("iDrawLine begin\n");
+ ln = (struct P96Line *)get_mapped_data_pointer_by_address(cfg, M68KR(M68K_REG_A2));
+
+ if (!ln || !r) break;
+
+ cmd_mask = (uint8_t)M68KR(M68K_REG_D0);
+ rtg_address_adj[0] = be32toh(r->_p_Memory) - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
+
+ if (cmd_mask == 0xFF && be16toh(ln->LinePtrn) == 0xFFFF) {
+ rtg_drawline_solid(be16toh(ln->X), be16toh(ln->Y), be16toh(ln->dX), be16toh(ln->dY),
+ be16toh(ln->Length), be32toh(ln->FgPen), CMD_PITCH, RGBF_D7);
+ } else {
+ rtg_drawline(be16toh(ln->X), be16toh(ln->Y), be16toh(ln->dX), be16toh(ln->dY),
+ be16toh(ln->Length), be16toh(ln->LinePtrn), be16toh(ln->PatternShift),
+ be32toh(ln->FgPen), be32toh(ln->BgPen), CMD_PITCH,
+ RGBF_D7, cmd_mask, ln->DrawMode);
+ }
+ gdebug("iDrawLine end\n");
+ break;
+ }
+ case RTGCMD_FILLRECT: {
+ // A0: BoardInfo *b, A1: RenderInfo *r
+ // D0 WORD x, D1: WORD y, D2: WORD w, D3: WORD h
+ // D4: ULONG color, D5: UBYTE mask, D7: RGBFTYPE format
+ gdebug("iFillRect begin\n");
+#ifdef DEBUG_RTG
+ if (realtime_graphics_debug) {
+ DEBUG("X1/X2: %d/%d-> X2/Y2: %d/%d\n", (int16_t)M68KR(M68K_REG_D0), (int16_t)M68KR(M68K_REG_D1), (int16_t)M68KR(M68K_REG_D2), (int16_t)M68KR(M68K_REG_D3));
+ DEBUG("R: %.8X B: %.8X\n", M68KR(M68K_REG_A0), M68KR(M68K_REG_A1));
+ }
+#endif
+
+ if (!b || !r) break;
+
+ cmd_mask = (uint8_t)M68KR(M68K_REG_D5);
+ rtg_address_adj[0] = be32toh(r->_p_Memory) - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
+
+ if (cmd_mask == 0xFF) {
+ rtg_fillrect_solid((int16_t)M68KR(M68K_REG_D0), (int16_t)M68KR(M68K_REG_D1), (int16_t)M68KR(M68K_REG_D2), (int16_t)M68KR(M68K_REG_D3),
+ M68KR(M68K_REG_D4), CMD_PITCH, RGBF_D7);
+ } else {
+ rtg_fillrect((int16_t)M68KR(M68K_REG_D0), (int16_t)M68KR(M68K_REG_D1), (int16_t)M68KR(M68K_REG_D2), (int16_t)M68KR(M68K_REG_D3),
+ M68KR(M68K_REG_D4), CMD_PITCH, RGBF_D7, cmd_mask);
+ }
+ gdebug("iFillRect end\n");
+ break;
+ }
+ case RTGCMD_INVERTRECT: {
+ // A0: BoardInfo *b, A1: RenderInfo *r
+ // D0 WORD x, D1: WORD y, D2: WORD w, D3: WORD h
+ // D4: UBYTE mask, D7: RGBFTYPE format
+ gdebug("iInvertRect begin\n");
+ if (!b || !r) break;
+
+ cmd_mask = (uint8_t)M68KR(M68K_REG_D4);
+ rtg_address_adj[0] = be32toh(r->_p_Memory) - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
+
+ rtg_invertrect((int16_t)M68KR(M68K_REG_D0), (int16_t)M68KR(M68K_REG_D1), (int16_t)M68KR(M68K_REG_D2), (int16_t)M68KR(M68K_REG_D3), CMD_PITCH, RGBF_D7, cmd_mask);
+ gdebug("iInvertRect end\n");
+ break;
+ }
+ case RTGCMD_BLITRECT: {
+ // A0: BoardInfo *b, A1: RenderInfo *r)
+ // D0: WORD x, D1: WORD y, D2: WORD dx, D3: WORD dy, D4: WORD w, D5: WORD h,
+ // D6: UBYTE mask, D7: RGBFTYPE format
+ gdebug("iBlitRect begin\n");
+
+ cmd_mask = (uint8_t)M68KR(M68K_REG_D6);
+ rtg_address_adj[0] = be32toh(r->_p_Memory) - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
+
+ if (cmd_mask == 0xFF) {
+ rtg_blitrect_solid(M68KR(M68K_REG_D0), M68KR(M68K_REG_D1), M68KR(M68K_REG_D2), M68KR(M68K_REG_D3), M68KR(M68K_REG_D4), M68KR(M68K_REG_D5), CMD_PITCH, RGBF_D7);
+ } else {
+ rtg_blitrect(M68KR(M68K_REG_D0), M68KR(M68K_REG_D1), M68KR(M68K_REG_D2), M68KR(M68K_REG_D3), M68KR(M68K_REG_D4), M68KR(M68K_REG_D5), CMD_PITCH, RGBF_D7, cmd_mask);
+ }
+
+ gdebug("iBlitRect end\n");
+ break;
+ }
+ case RTGCMD_BLITRECT_NOMASK_COMPLETE: {
+ // A0: BoardInfo *b, A1: RenderInfo *rs, A2: RenderInfo *rt,
+ // D0: WORD x, D1: WORD y, D2: WORD dx, D3: WORD dy, D4: WORD w, D5: WORD h,
+ // D6: UBYTE minterm, D7: RGBFTYPE format
+ gdebug("iBlitRectNoMaskComplete begin\n");
+
+ uint8_t minterm = (uint8_t)M68KR(M68K_REG_D6);
+ struct P96RenderInfo *rt = (struct P96RenderInfo *)get_mapped_data_pointer_by_address(cfg, M68KR(M68K_REG_A2));
+
+ uint32_t src_addr = be32toh(r->_p_Memory);
+ uint32_t dst_addr = be32toh(rt->_p_Memory);
+
+ rtg_blitrect_nomask_complete(M68KR(M68K_REG_D0), M68KR(M68K_REG_D1), M68KR(M68K_REG_D2), M68KR(M68K_REG_D3), M68KR(M68K_REG_D4), M68KR(M68K_REG_D5),
+ CMD_PITCH, be16toh(rt->BytesPerRow), src_addr, dst_addr, RGBF_D7, minterm);
+
+ gdebug("iBlitRectNoMaskComplete end\n");
+ break;
+ }
+ default:
+ printf("[!!!IRTG] Unnkonw/unhandled iRTG command %d.\n", cmd);
+ break;
+ }
+}