From c7df5946af60dfdf9135fa4c8977f41bc16bd5aa Mon Sep 17 00:00:00 2001 From: beeanyew Date: Sat, 9 Jan 2021 21:58:20 +0100 Subject: [PATCH] Add mask handling to all RTG ops, add real time disassembly output --- Makefile | 2 +- emulator.c | 30 +- m68k.h | 4 + platforms/amiga/rtg/rtg-gfx.c | 325 ++++++++---------- platforms/amiga/rtg/rtg.c | 12 +- platforms/amiga/rtg/rtg.h | 107 +++++- platforms/amiga/rtg/rtg_driver_amiga/pigfx.c | 29 +- .../amiga/rtg/rtg_driver_amiga/pigfx020.card | Bin 5556 -> 5028 bytes .../amiga/rtg/rtg_driver_amiga/pigfx030.card | Bin 5556 -> 5028 bytes 9 files changed, 279 insertions(+), 230 deletions(-) diff --git a/Makefile b/Makefile index 927a53e..00ac323 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ MAINFILES = emulator.c \ platforms/amiga/rtg/rtg-gfx.c \ platforms/shared/rtc.c -MUSASHIFILES = m68kcpu.c softfloat/softfloat.c +MUSASHIFILES = m68kcpu.c m68kdasm.c softfloat/softfloat.c MUSASHIGENCFILES = m68kops.c MUSASHIGENHFILES = m68kops.h MUSASHIGENERATOR = m68kmake diff --git a/emulator.c b/emulator.c index d12d623..03cf080 100644 --- a/emulator.c +++ b/emulator.c @@ -44,6 +44,9 @@ char mouse_buttons = 0; extern volatile unsigned int *gpio; extern volatile uint16_t srdata; extern uint8_t realtime_graphics_debug; +uint8_t realtime_disassembly; + +char disasm_buf[4096]; #define KICKBASE 0xF80000 #define KICKSIZE 0x7FFFF @@ -201,17 +204,13 @@ int main(int argc, char *argv[]) { // reset amiga and statemachine skip_everything:; - cpu_pulse_reset(); - ovl = 1; - m68k_write_memory_8(0xbfe201, 0x0001); // AMIGA OVL - m68k_write_memory_8(0xbfe001, 0x0001); // AMIGA OVL high (ROM@0x0) usleep(1500); m68k_init(); printf("Setting CPU type to %d.\n", cpu_type); m68k_set_cpu_type(cpu_type); - m68k_pulse_reset(); + cpu_pulse_reset(); if (maprom == 1) { m68k_set_reg(M68K_REG_PC, 0xF80002); @@ -239,10 +238,18 @@ int main(int argc, char *argv[]) { if (cpu_emulation_running) m68k_execute(loop_cycles); + +disasm_run:; + if (realtime_disassembly) { + m68k_execute(1); + m68k_disassemble(disasm_buf, m68k_get_reg(NULL, M68K_REG_PC), cpu_type); + printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf); + } if (irq) { unsigned int status = read_reg(); m68k_set_irq((status & 0xe000) >> 13); + //printf("There was an IRQ: %d\n", (status & 0xe000) >> 13); } else if (gayleirq) { write16(0xdff09c, 0x8000 | (1 << 3)); @@ -287,9 +294,16 @@ int main(int argc, char *argv[]) { printf("Quitting and exiting emulator.\n"); goto stop_cpu_emulation; } + if (c == 'd') { + realtime_disassembly ^= 1; + printf("Real time disassembly is now %s\n", realtime_disassembly ? "on" : "off"); + } } } + if (realtime_disassembly) + goto disasm_run; + //gpio_handle_irq(); //GPIO_HANDLE_IRQ; } @@ -310,6 +324,12 @@ void cpu_pulse_reset(void) { usleep(100000); write_reg(0x02); // printf("Status Reg%x\n",read_reg()); + + ovl = 1; + m68k_write_memory_8(0xbfe201, 0x0001); // AMIGA OVL + m68k_write_memory_8(0xbfe001, 0x0001); // AMIGA OVL high (ROM@0x0) + + m68k_pulse_reset(); } int cpu_irq_ack(int level) { diff --git a/m68k.h b/m68k.h index e005ca9..eb360b7 100644 --- a/m68k.h +++ b/m68k.h @@ -175,6 +175,10 @@ typedef enum * USER mode, but it is also slower. */ +#define m68k_read_disassembler_8 m68k_read_memory_8 +#define m68k_read_disassembler_16 m68k_read_memory_16 +#define m68k_read_disassembler_32 m68k_read_memory_32 + /* Read from anywhere */ unsigned int m68k_read_memory_8(unsigned int address); unsigned int m68k_read_memory_16(unsigned int address); diff --git a/platforms/amiga/rtg/rtg-gfx.c b/platforms/amiga/rtg/rtg-gfx.c index 058a8b1..558816b 100644 --- a/platforms/amiga/rtg/rtg-gfx.c +++ b/platforms/amiga/rtg/rtg-gfx.c @@ -17,8 +17,7 @@ extern uint16_t rtg_x[8], rtg_y[8]; extern uint8_t realtime_graphics_debug; -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) { - if (mask) {} +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) { uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)]; switch(format) { case RTGFMT_8BIT: { @@ -50,6 +49,16 @@ void rtg_fillrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color } } +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) { + uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)]; + + for (int ys = 1; ys < h; ys++) { + for (int xs = 0; xs < w; xs++) { + SET_RTG_PIXEL_MASK(&dptr[xs], (color & 0xFF), format); + } + } +} + void rtg_invertrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t pitch, uint16_t format, uint8_t mask) { if (mask) {} uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)]; @@ -57,7 +66,7 @@ void rtg_invertrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t pit switch(format) { case RTGFMT_8BIT: { for (int xs = 0; xs < w; xs++) { - dptr[xs] = ~dptr[xs]; + dptr[xs] ^= mask; } break; } @@ -94,6 +103,37 @@ void rtg_blitrect(uint16_t x, uint16_t y, uint16_t dx, uint16_t dy, uint16_t w, xdir = 0; } + for (int ys = 0; ys < h; ys++) { + if (xdir) { + for (int xs = 0; xs < w; xs++) { + SET_RTG_PIXEL_MASK(&dptr[xs], sptr[xs], format); + } + } + else { + for (int xs = w - 1; xs >= x; xs--) { + SET_RTG_PIXEL_MASK(&dptr[xs], sptr[xs], format); + } + } + sptr += pitchstep; + dptr += pitchstep; + } +} + +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) { + uint8_t *sptr = &rtg_mem[rtg_address_adj[0] + (x << format) + (y * pitch)]; + uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dx << format) + (dy * pitch)]; + + uint32_t xdir = 1, pitchstep = pitch; + + if (y < dy) { + pitchstep = -pitch; + sptr += ((h - 1) * pitch); + dptr += ((h - 1) * pitch); + } + if (x < dx) { + xdir = 0; + } + for (int ys = 0; ys < h; ys++) { if (xdir) memcpy(dptr, sptr, w << format); @@ -110,6 +150,8 @@ void rtg_blitrect_nomask_complete(uint16_t sx, uint16_t sy, uint16_t dx, uint16_ uint8_t *dptr = &rtg_mem[dst_addr - (PIGFX_RTG_BASE + PIGFX_REG_SIZE) + (dx << format) + (dy * dstpitch)]; uint32_t xdir = 1, src_pitchstep = srcpitch, dst_pitchstep = dstpitch; + uint8_t draw_mode = minterm; + uint32_t mask = 0xFF; if (src_addr == dst_addr) { if (sy < dy) { @@ -123,13 +165,56 @@ void rtg_blitrect_nomask_complete(uint16_t sx, uint16_t sy, uint16_t dx, uint16_ } } - for (int ys = 0; ys < h; ys++) { - if (xdir) - memcpy(dptr, sptr, w << format); - else - memmove(dptr, sptr, w << format); - sptr += src_pitchstep; - dptr += dst_pitchstep; + if (format == RTGFMT_RBG565) + mask = 0xFFFF; + if (format == RTGFMT_RGB32) + mask = 0xFFFFFFFF; + + if (minterm == MINTERM_SRC) { + for (int ys = 0; ys < h; ys++) { + if (xdir) + memcpy(dptr, sptr, w << format); + else + memmove(dptr, sptr, w << format); + sptr += src_pitchstep; + dptr += dst_pitchstep; + } + } + else { + for (int ys = 0; ys < h; ys++) { + if (xdir) { + for (int xs = 0; xs < w; xs++) { + switch (format) { + case RTGFMT_8BIT: + HANDLE_MINTERM_PIXEL(sptr[xs], dptr[xs], format); + break; + case RTGFMT_RBG565: + HANDLE_MINTERM_PIXEL(((uint16_t *)sptr)[xs], ((uint16_t *)dptr)[xs], format); + break; + case RTGFMT_RGB32: + HANDLE_MINTERM_PIXEL(((uint32_t *)sptr)[xs], ((uint32_t *)dptr)[xs], format); + break; + } + } + } + else { + for (int xs = w - 1; xs >= sx; xs--) { + switch (format) { + case RTGFMT_8BIT: + HANDLE_MINTERM_PIXEL(sptr[xs], dptr[xs], format); + break; + case RTGFMT_RBG565: + HANDLE_MINTERM_PIXEL(((uint16_t *)sptr)[xs], ((uint16_t *)dptr)[xs], format); + break; + case RTGFMT_RGB32: + HANDLE_MINTERM_PIXEL(((uint32_t *)sptr)[xs], ((uint32_t *)dptr)[xs], format); + break; + } + } + } + sptr += src_pitchstep; + dptr += src_pitchstep; + } } } @@ -217,13 +302,23 @@ void rtg_blittemplate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t s for (int xs = 0; xs < w; xs++) { if (w >= 8 && cur_bit == 0x80 && xs < w - 8) { - SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format); + } + else { + SET_RTG_PIXELS_MASK(&dptr[xs], fg_color[format], format); + } xs += 7; } else { while (cur_bit > 0 && xs < w) { if (cur_byte & cur_bit) { - SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format); + } + else { + SET_RTG_PIXEL_MASK(&dptr[xs], fg_color[format], format); + } } xs++; cur_bit >>= 1; @@ -242,16 +337,22 @@ void rtg_blittemplate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t s for (int xs = 0; xs < w; xs++) { if (w >= 8 && cur_bit == 0x80 && xs < w - 8) { - SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format); + } + else { + SET_RTG_PIXELS2_COND_MASK(&dptr[xs << format], fg_color[format], bg_color[format], format); + } + xs += 7; } else { while (cur_bit > 0 && xs < w) { - if (cur_byte & cur_bit) { - SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXEL(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format); } else { - SET_RTG_PIXEL(&dptr[xs << format], bg_color[format], format); + SET_RTG_PIXEL_MASK(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format); } xs++; cur_bit >>= 1; @@ -341,13 +442,23 @@ void rtg_blitpattern(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t sr for (int xs = 0; xs < w; xs++) { if (w >= 8 && cur_bit == 0x80 && xs < w - 8) { - SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXELS(&dptr[xs << format], fg_color[format], format); + } + else { + SET_RTG_PIXELS_MASK(&dptr[xs], fg_color[format], format); + } xs += 7; } else { while (cur_bit > 0 && xs < w) { if (cur_byte & cur_bit) { - SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format); + } + else { + SET_RTG_PIXEL_MASK(&dptr[xs], fg_color[format], format); + } } xs++; cur_bit >>= 1; @@ -366,16 +477,22 @@ void rtg_blitpattern(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t sr for (int xs = 0; xs < w; xs++) { if (w >= 8 && cur_bit == 0x80 && xs < w - 8) { - SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXELS2_COND(&dptr[xs << format], fg_color[format], bg_color[format], format); + } + else { + SET_RTG_PIXELS2_COND_MASK(&dptr[xs << format], fg_color[format], bg_color[format], format); + } + xs += 7; } else { while (cur_bit > 0 && xs < w) { - if (cur_byte & cur_bit) { - SET_RTG_PIXEL(&dptr[xs << format], fg_color[format], format); + if (mask == 0xFF || format != RTGFMT_8BIT) { + SET_RTG_PIXEL(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format); } else { - SET_RTG_PIXEL(&dptr[xs << format], bg_color[format], format); + SET_RTG_PIXEL_MASK(&dptr[xs << format], (cur_byte & cur_bit) ? fg_color[format] : bg_color[format], format); } xs++; cur_bit >>= 1; @@ -499,7 +616,7 @@ void rtg_drawline (int16_t x1_, int16_t y1_, int16_t x2_, int16_t y2_, uint16_t int16_t x1 = x1_, y1 = y1_; int16_t x2 = x1_ + x2_, y2 = y1 + y2_; uint16_t cur_bit = 0x8000; - uint32_t color_mask = 0xFFFF0000; + //uint32_t color_mask = 0xFFFF0000; uint8_t invert = 0; uint32_t fg_color[3] = { @@ -569,77 +686,13 @@ void rtg_drawline (int16_t x1_, int16_t y1_, int16_t x2_, int16_t y2_, uint16_t } } -#define HANDLE_MINTERM_PIXEL_8(s, d, f) \ - switch(draw_mode) {\ - case MINTERM_NOR: \ - s &= ~(d); \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_ONLYDST: \ - d = d & ~(s); break; \ - case MINTERM_NOTSRC: \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_ONLYSRC: \ - s &= (d ^ 0xFF); \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_INVERT: \ - d ^= 0xFF; break; \ - case MINTERM_EOR: \ - d ^= s; break; \ - case MINTERM_NAND: \ - s = ~(d & ~(s)) & mask; \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_AND: \ - s &= d; \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_NEOR: \ - d ^= (s & mask); break; \ - case MINTERM_DST: /* This one does nothing. */ \ - return; break; \ - case MINTERM_NOTONLYSRC: \ - d |= (s & mask); break; \ - case MINTERM_SRC: \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_NOTONLYDST: \ - s = ~(d & s) & mask; \ - SET_RTG_PIXEL_MASK(&d, s, f); break; \ - case MINTERM_OR: \ - d |= (s & mask); break; \ - } - - -#define DECODE_PLANAR_PIXEL(a) \ - switch (planes) { \ - case 8: if (layer_mask & 0x80 && bmp_data[(plane_size * 7) + cur_byte] & cur_bit) a |= 0x80; \ - case 7: if (layer_mask & 0x40 && bmp_data[(plane_size * 6) + cur_byte] & cur_bit) a |= 0x40; \ - case 6: if (layer_mask & 0x20 && bmp_data[(plane_size * 5) + cur_byte] & cur_bit) a |= 0x20; \ - case 5: if (layer_mask & 0x10 && bmp_data[(plane_size * 4) + cur_byte] & cur_bit) a |= 0x10; \ - case 4: if (layer_mask & 0x08 && bmp_data[(plane_size * 3) + cur_byte] & cur_bit) a |= 0x08; \ - case 3: if (layer_mask & 0x04 && bmp_data[(plane_size * 2) + cur_byte] & cur_bit) a |= 0x04; \ - case 2: if (layer_mask & 0x02 && bmp_data[plane_size + cur_byte] & cur_bit) a |= 0x02; \ - case 1: if (layer_mask & 0x01 && bmp_data[cur_byte] & cur_bit) a |= 0x01; \ - break; \ - } - -#define DECODE_INVERTED_PLANAR_PIXEL(a) \ - switch (planes) { \ - case 8: if (layer_mask & 0x80 && (bmp_data[(plane_size * 7) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x80; \ - case 7: if (layer_mask & 0x40 && (bmp_data[(plane_size * 6) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x40; \ - case 6: if (layer_mask & 0x20 && (bmp_data[(plane_size * 5) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x20; \ - case 5: if (layer_mask & 0x10 && (bmp_data[(plane_size * 4) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x10; \ - case 4: if (layer_mask & 0x08 && (bmp_data[(plane_size * 3) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x08; \ - case 3: if (layer_mask & 0x04 && (bmp_data[(plane_size * 2) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x04; \ - case 2: if (layer_mask & 0x02 && (bmp_data[plane_size + cur_byte] ^ 0xFF) & cur_bit) a |= 0x02; \ - case 1: if (layer_mask & 0x01 && (bmp_data[cur_byte] ^ 0xFF) & cur_bit) a |= 0x01; \ - break; \ - } - 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) { uint16_t pitch = rtg_x[3]; uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dy * pitch)]; uint8_t cur_bit, base_bit, base_byte; uint16_t cur_byte = 0, u8_fg = 0; - uint32_t color_mask = 0xFFFFFFFF; + //uint32_t color_mask = 0xFFFFFFFF; uint32_t plane_size = src_line_pitch * h; uint8_t *bmp_data = bmp_data_src; @@ -684,8 +737,7 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t goto skip; } - //HANDLE_MINTERM_PIXEL_8(u8_fg, ((uint8_t *)dptr)[x]); - HANDLE_MINTERM_PIXEL_8(u8_fg, dptr[x], rtg_display_format); + HANDLE_MINTERM_PIXEL(u8_fg, dptr[x], rtg_display_format); skip:; if ((cur_bit >>= 1) == 0) { @@ -704,96 +756,3 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t cur_byte = base_byte; } } - -//void rtg_p2c_broken(int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t h, uint16_t pitch, uint8_t mask, uint8_t minterm, uint8_t depth, uint16_t planemask_) { - /*uint8_t *planeptr_src = &rtg_mem[rtg_address_adj[1]]; - uint8_t *dptr = &rtg_mem[rtg_address_adj[0] + (dy * pitch)]; - - uint8_t cur_bit, base_bit, base_byte; - uint16_t cur_byte = 0;//, color = 0; - uint16_t srcpitch = rtg_user[1]; - uint32_t plane_size = srcpitch * rtg_y[3]; - uint32_t color_mask = 0x00FFFFFF; - uint8_t color = 0; - - uint8_t planemask = planemask_ & 0xFF; - uint8_t planemask_0 = (planemask_ >> 8); - - cur_bit = base_bit = (0x80 >> (sx % 8)); - cur_byte = base_byte = ((sx / 8) % srcpitch); - - planeptr_src += (srcpitch * sy); - - if (realtime_graphics_debug) { - uint8_t *sptr = NULL; - - printf("P2C: %d,%d - %d,%d (%dx%d) %d, %.4X\n", sx, sy, dx, dy, w, h, depth, planemask_); - printf("Mask: %.2X Minterm: %.2X\n", mask, minterm); - printf("Pitch: %d Src Pitch: %d (!!!: %d)\n", pitch, srcpitch, rtg_user[1]); - printf("Curbyte: %d Curbit: %d\n", cur_byte, cur_bit); - printf("Plane size: %d Total size: %d (%X)\n", plane_size, plane_size * depth, plane_size * depth); - printf("Source: %.8X - %.8X\n", rtg_address[1], rtg_address_adj[1]); - printf("Target: %.8X - %.8X\n", rtg_address[0], rtg_address_adj[0]); - fflush(stdout); - - printf("Origin: %.8X\n", rtg_address[2]); - printf("Grabbing data from RTG memory.\nData:\n"); - for (int i = 0; i < h; i++) { - for (int k = 0; k < depth; k++) { - for (int j = 0; j < srcpitch; j++) { - printf("%.2X", planeptr_src[j + (i * srcpitch) + (plane_size * k)]); - } - printf(" "); - } - printf("\n"); - } -#ifndef FAKESTORM - printf("Data available at origin:\n"); - for (int i = 0; i < h; i++) { - for (int k = 0; k < depth; k++) { - for (int j = 0; j < srcpitch; j++) { - printf("%.2X", read8(rtg_address[2] + j + (i * srcpitch) + (plane_size * k))); - } - printf(" "); - } - printf("\n"); - } -#endif - } - - for (int16_t line_y = 0; line_y < h; line_y++) { - for (int16_t xs = dx; xs < dx + w; xs++) { - color = 0; - if (minterm & 0x01) { - //printf("Decode inverted planar pixel.\n"); - DECODE_INVERTED_PLANAR_PIXEL(color, planeptr_src); - } - else { - //printf("Decode planar pixel.\n"); - DECODE_PLANAR_PIXEL(color, planeptr_src); - } - - if (mask == 0xFF && (minterm == MINTERM_SRC || minterm == MINTERM_NOTSRC)) { - dptr[xs << rtg_display_format] = color; - goto skip; - } - - //printf("Place pixel.\n"); - HANDLE_MINTERM_PIXEL_8(color, dptr[xs << rtg_display_format], rtg_display_format); - - skip:; - if ((cur_bit >>= 1) == 0) { - cur_bit = 0x80; - cur_byte++; - cur_byte %= srcpitch; - } - } - dptr += pitch; - //if (line_y + sy + 1 == rtg_y[3]) - //planeptr_src = &rtg_mem[rtg_address_adj[1]];// + (srcpitch * sy); - //else - planeptr_src += srcpitch; - cur_bit = base_bit; - cur_byte = base_byte; - }*/ -//} diff --git a/platforms/amiga/rtg/rtg.c b/platforms/amiga/rtg/rtg.c index 910ee9b..5f33722 100644 --- a/platforms/amiga/rtg/rtg.c +++ b/platforms/amiga/rtg/rtg.c @@ -233,15 +233,21 @@ static void handle_rtg_command(uint32_t cmd) { } break; case RTGCMD_FILLRECT: - rtg_fillrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_rgb[0], rtg_x[2], rtg_format, 0xFF); + if (rtg_u8[0] == 0xFF || rtg_format != RTGFMT_8BIT) + rtg_fillrect_solid(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_rgb[0], rtg_x[2], rtg_format); + else + rtg_fillrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_rgb[0], rtg_x[2], rtg_format, rtg_u8[0]); gdebug("FillRect\n"); break; case RTGCMD_INVERTRECT: - rtg_invertrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_x[2], rtg_format, 0xFF); + rtg_invertrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_x[2], rtg_format, rtg_u8[0]); gdebug("InvertRect\n"); break; case RTGCMD_BLITRECT: - rtg_blitrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_x[2], rtg_y[2], rtg_x[3], rtg_format, 0xFF); + if (rtg_u8[0] == 0xFF || rtg_format != RTGFMT_8BIT) + rtg_blitrect_solid(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_x[2], rtg_y[2], rtg_x[3], rtg_format); + else + rtg_blitrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_x[2], rtg_y[2], rtg_x[3], rtg_format, rtg_u8[0]); gdebug("BlitRect\n"); break; case RTGCMD_BLITRECT_NOMASK_COMPLETE: diff --git a/platforms/amiga/rtg/rtg.h b/platforms/amiga/rtg/rtg.h index ca63898..dda431c 100644 --- a/platforms/amiga/rtg/rtg.h +++ b/platforms/amiga/rtg/rtg.h @@ -16,8 +16,10 @@ void rtg_init_display(); void rtg_shutdown_display(); 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); +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); void rtg_invertrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t pitch, uint16_t format, uint8_t mask); 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); +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); 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); 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); 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); @@ -51,14 +53,14 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t #define INVERT_RTG_PIXELS(dest, format) \ switch (format) { \ case RTGFMT_8BIT: \ - if (cur_byte & 0x80) (dest)[0] = ~(dest)[0]; \ - if (cur_byte & 0x40) (dest)[1] = ~(dest)[1]; \ - if (cur_byte & 0x20) (dest)[2] = ~(dest)[2]; \ - if (cur_byte & 0x10) (dest)[3] = ~(dest)[3]; \ - if (cur_byte & 0x08) (dest)[4] = ~(dest)[4]; \ - if (cur_byte & 0x04) (dest)[5] = ~(dest)[5]; \ - if (cur_byte & 0x02) (dest)[6] = ~(dest)[6]; \ - if (cur_byte & 0x01) (dest)[7] = ~(dest)[7]; \ + if (cur_byte & 0x80) (dest)[0] ^= mask; \ + if (cur_byte & 0x40) (dest)[1] ^= mask; \ + if (cur_byte & 0x20) (dest)[2] ^= mask; \ + if (cur_byte & 0x10) (dest)[3] ^= mask; \ + if (cur_byte & 0x08) (dest)[4] ^= mask; \ + if (cur_byte & 0x04) (dest)[5] ^= mask; \ + if (cur_byte & 0x02) (dest)[6] ^= mask; \ + if (cur_byte & 0x01) (dest)[7] ^= mask; \ break; \ case RTGFMT_RBG565: \ if (cur_byte & 0x80) ((uint16_t *)dest)[0] = ~((uint16_t *)dest)[0]; \ @@ -82,6 +84,27 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t break; \ } +#define SET_RTG_PIXELS_MASK(dest, src, format) \ + if (cur_byte & 0x80) (dest)[0] = src ^ ((dest)[0] & ~mask); \ + if (cur_byte & 0x40) (dest)[1] = src ^ ((dest)[1] & ~mask); \ + if (cur_byte & 0x20) (dest)[2] = src ^ ((dest)[2] & ~mask); \ + if (cur_byte & 0x10) (dest)[3] = src ^ ((dest)[3] & ~mask); \ + if (cur_byte & 0x08) (dest)[4] = src ^ ((dest)[4] & ~mask); \ + if (cur_byte & 0x04) (dest)[5] = src ^ ((dest)[5] & ~mask); \ + if (cur_byte & 0x02) (dest)[6] = src ^ ((dest)[6] & ~mask); \ + if (cur_byte & 0x01) (dest)[7] = src ^ ((dest)[7] & ~mask); \ + +#define SET_RTG_PIXELS2_COND_MASK(dest, src, src2, format) \ + (dest)[0] = (cur_byte & 0x80) ? src : src2 ^ ((dest)[0] & ~mask); \ + (dest)[1] = (cur_byte & 0x40) ? src : src2 ^ ((dest)[1] & ~mask); \ + (dest)[2] = (cur_byte & 0x20) ? src : src2 ^ ((dest)[2] & ~mask); \ + (dest)[3] = (cur_byte & 0x10) ? src : src2 ^ ((dest)[3] & ~mask); \ + (dest)[4] = (cur_byte & 0x08) ? src : src2 ^ ((dest)[4] & ~mask); \ + (dest)[5] = (cur_byte & 0x04) ? src : src2 ^ ((dest)[5] & ~mask); \ + (dest)[6] = (cur_byte & 0x02) ? src : src2 ^ ((dest)[6] & ~mask); \ + (dest)[7] = (cur_byte & 0x01) ? src : src2 ^ ((dest)[7] & ~mask); \ + + #define SET_RTG_PIXELS(dest, src, format) \ switch (format) { \ case RTGFMT_8BIT: \ @@ -171,10 +194,10 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t *(dest) = src ^ (*(dest) & ~mask); \ break; \ case RTGFMT_RBG565: \ - *((uint16_t *)dest) = src ^ (*((uint16_t *)dest) & ~color_mask); \ + *((uint16_t *)dest) = src; \ break; \ case RTGFMT_RGB32: \ - *((uint32_t *)dest) = src ^ (*((uint32_t *)dest) & ~color_mask); \ + *((uint32_t *)dest) = src; \ break; \ } @@ -190,3 +213,67 @@ void rtg_p2c (int16_t sx, int16_t sy, int16_t dx, int16_t dy, int16_t w, int16_t *((uint32_t *)dest) = ~*((uint32_t *)dest); \ break; \ } + +#define HANDLE_MINTERM_PIXEL(s, d, f) \ + switch(draw_mode) {\ + case MINTERM_NOR: \ + s &= ~(d); \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_ONLYDST: \ + d = d & ~(s); break; \ + case MINTERM_NOTSRC: \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_ONLYSRC: \ + s &= (d ^ 0xFF); \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_INVERT: \ + d ^= 0xFF; break; \ + case MINTERM_EOR: \ + d ^= s; break; \ + case MINTERM_NAND: \ + s = ~(d & ~(s)) & mask; \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_AND: \ + s &= d; \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_NEOR: \ + d ^= (s & mask); break; \ + case MINTERM_DST: /* This one does nothing. */ \ + return; break; \ + case MINTERM_NOTONLYSRC: \ + d |= (s & mask); break; \ + case MINTERM_SRC: \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_NOTONLYDST: \ + s = ~(d & s) & mask; \ + SET_RTG_PIXEL_MASK(&d, s, f); break; \ + case MINTERM_OR: \ + d |= (s & mask); break; \ + } + + +#define DECODE_PLANAR_PIXEL(a) \ + switch (planes) { \ + case 8: if (layer_mask & 0x80 && bmp_data[(plane_size * 7) + cur_byte] & cur_bit) a |= 0x80; \ + case 7: if (layer_mask & 0x40 && bmp_data[(plane_size * 6) + cur_byte] & cur_bit) a |= 0x40; \ + case 6: if (layer_mask & 0x20 && bmp_data[(plane_size * 5) + cur_byte] & cur_bit) a |= 0x20; \ + case 5: if (layer_mask & 0x10 && bmp_data[(plane_size * 4) + cur_byte] & cur_bit) a |= 0x10; \ + case 4: if (layer_mask & 0x08 && bmp_data[(plane_size * 3) + cur_byte] & cur_bit) a |= 0x08; \ + case 3: if (layer_mask & 0x04 && bmp_data[(plane_size * 2) + cur_byte] & cur_bit) a |= 0x04; \ + case 2: if (layer_mask & 0x02 && bmp_data[plane_size + cur_byte] & cur_bit) a |= 0x02; \ + case 1: if (layer_mask & 0x01 && bmp_data[cur_byte] & cur_bit) a |= 0x01; \ + break; \ + } + +#define DECODE_INVERTED_PLANAR_PIXEL(a) \ + switch (planes) { \ + case 8: if (layer_mask & 0x80 && (bmp_data[(plane_size * 7) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x80; \ + case 7: if (layer_mask & 0x40 && (bmp_data[(plane_size * 6) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x40; \ + case 6: if (layer_mask & 0x20 && (bmp_data[(plane_size * 5) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x20; \ + case 5: if (layer_mask & 0x10 && (bmp_data[(plane_size * 4) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x10; \ + case 4: if (layer_mask & 0x08 && (bmp_data[(plane_size * 3) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x08; \ + case 3: if (layer_mask & 0x04 && (bmp_data[(plane_size * 2) + cur_byte] ^ 0xFF) & cur_bit) a |= 0x04; \ + case 2: if (layer_mask & 0x02 && (bmp_data[plane_size + cur_byte] ^ 0xFF) & cur_bit) a |= 0x02; \ + case 1: if (layer_mask & 0x01 && (bmp_data[cur_byte] ^ 0xFF) & cur_bit) a |= 0x01; \ + break; \ + } diff --git a/platforms/amiga/rtg/rtg_driver_amiga/pigfx.c b/platforms/amiga/rtg/rtg_driver_amiga/pigfx.c index 6b4cff9..c6111b4 100644 --- a/platforms/amiga/rtg/rtg_driver_amiga/pigfx.c +++ b/platforms/amiga/rtg/rtg_driver_amiga/pigfx.c @@ -308,7 +308,7 @@ int InitCard(__REGA0(struct BoardInfo* b)) { //b->ScrollPlanar = (void *)NULL; //b->UpdatePlanar = (void *)NULL; - b->BlitPlanar2Chunky = (void *)BlitPlanar2Chunky; + //b->BlitPlanar2Chunky = (void *)BlitPlanar2Chunky; //b->BlitPlanar2Direct = (void *)NULL; b->FillRect = (void *)FillRect; @@ -483,10 +483,6 @@ void WaitVerticalSync (__REGA0(struct BoardInfo *b), __REGD0(BOOL toggle)) { void FillRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __REGD0(WORD x), __REGD1(WORD y), __REGD2(WORD w), __REGD3(WORD h), __REGD4(ULONG color), __REGD5(UBYTE mask), __REGD7(RGBFTYPE format)) { if (!r) return; - if (mask != 0xFF) { - b->FillRectDefault(b, r, x, y, w, h, color, mask, format); - return; - } WRITELONG(RTG_ADDR1, (unsigned long)r->Memory); @@ -504,11 +500,6 @@ void FillRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __RE void InvertRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __REGD0(WORD x), __REGD1(WORD y), __REGD2(WORD w), __REGD3(WORD h), __REGD4(UBYTE mask), __REGD7(RGBFTYPE format)) { if (!r) return; - if (mask != 0xFF) { - b->InvertRectDefault(b, r, x, y, w, h, mask, format); - return; - } - WRITELONG(RTG_ADDR1, (unsigned long)r->Memory); WRITESHORT(RTG_FORMAT, rgbf_to_rtg[format]); @@ -524,10 +515,6 @@ void InvertRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __ void BlitRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __REGD0(WORD x), __REGD1(WORD y), __REGD2(WORD dx), __REGD3(WORD dy), __REGD4(WORD w), __REGD5(WORD h), __REGD6(UBYTE mask), __REGD7(RGBFTYPE format)) { if (!r) return; - if (mask != 0xFF) { - b->BlitRectDefault(b, r, x, y, dx, dy, w, h, mask, format); - return; - } WRITELONG(RTG_ADDR1, (unsigned long)r->Memory); @@ -546,10 +533,6 @@ void BlitRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __RE void BlitRectNoMaskComplete (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *rs), __REGA2(struct RenderInfo *rt), __REGD0(WORD x), __REGD1(WORD y), __REGD2(WORD dx), __REGD3(WORD dy), __REGD4(WORD w), __REGD5(WORD h), __REGD6(UBYTE minterm), __REGD7(RGBFTYPE format)) { if (!rs || !rt) return; - if (minterm != MINTERM_SRC) { - b->BlitRectNoMaskCompleteDefault(b, rs, rt, x, y, dx, dy, w, h, minterm, format); - return; - } WRITESHORT(RTG_FORMAT, rgbf_to_rtg[format]); WRITELONG(RTG_ADDR1, (unsigned long)rs->Memory); @@ -570,11 +553,6 @@ void BlitTemplate (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), if (!r || !t) return; if (w < 1 || h < 1) return; - if (mask != 0xFF) { - b->BlitTemplateDefault(b, r, t, x, y, w, h, mask, format); - return; - } - WRITELONG(RTG_ADDR2, (unsigned long)r->Memory); WRITESHORT(RTG_FORMAT, rgbf_to_rtg[format]); @@ -610,11 +588,6 @@ void BlitPattern (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), _ if (!r || !p) return; if (w < 1 || h < 1) return; - if (mask != 0xFF) { - b->BlitPatternDefault(b, r, p, x, y, w, h, mask, format); - return; - } - WRITELONG(RTG_ADDR2, (unsigned long)r->Memory); WRITESHORT(RTG_FORMAT, rgbf_to_rtg[format]); diff --git a/platforms/amiga/rtg/rtg_driver_amiga/pigfx020.card b/platforms/amiga/rtg/rtg_driver_amiga/pigfx020.card index c58bd890acfa5a71122450ed25624e0a2f9b4804..0907cbeb70dbdbf764cd716b7ea35eeef48a0306 100644 GIT binary patch delta 1761 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 NIJ-P3 diff --git a/platforms/amiga/rtg/rtg_driver_amiga/pigfx030.card b/platforms/amiga/rtg/rtg_driver_amiga/pigfx030.card index c58bd890acfa5a71122450ed25624e0a2f9b4804..0907cbeb70dbdbf764cd716b7ea35eeef48a0306 100644 GIT binary patch delta 1761 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 NIJ-P3 -- 2.39.2