X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fcd%2Fgfx.c;h=e3434e11705b27821eee4df52cefa595641a6495;hb=93f9619ed819dee07948416c98ca2f1c70a22666;hp=00a5d49d87fe40ed0583fab9bab9253dc881c992;hpb=e53f0499fe2337c5efea7443d6e2322887cae593;p=picodrive.git diff --git a/pico/cd/gfx.c b/pico/cd/gfx.c index 00a5d49..e3434e1 100644 --- a/pico/cd/gfx.c +++ b/pico/cd/gfx.c @@ -35,12 +35,13 @@ * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************************/ -#include "genplus_types.h" +#include "../pico_int.h" +#include "genplus_macros.h" typedef struct { - uint32 cycles; /* current cycles count for graphics operation */ - uint32 cyclesPerLine; /* current graphics operation timings */ + //uint32 cycles; /* current cycles count for graphics operation */ + //uint32 cyclesPerLine; /* current graphics operation timings */ uint32 dotMask; /* stamp map size mask */ uint16 *tracePtr; /* trace vector pointer */ uint16 *mapPtr; /* stamp map table base address */ @@ -48,13 +49,16 @@ typedef struct uint8 mapShift; /* stamp map table shift value (related to stamp map size) */ uint16 bufferOffset; /* image buffer column offset */ uint32 bufferStart; /* image buffer start index */ - uint8 lut_prio[4][0x100][0x100]; /* WORD-RAM data writes priority lookup table */ + uint32 y_step; /* pico: render line step */ + uint8 lut_prio[4][0x10][0x10]; /* WORD-RAM data writes priority lookup table */ uint8 lut_pixel[0x200]; /* Graphics operation dot offset lookup table */ uint8 lut_cell[0x100]; /* Graphics operation stamp offset lookup table */ } gfx_t; static gfx_t gfx; +static void gfx_schedule(void); + /***************************************************************/ /* Rotation / Scaling operation (2M Mode) */ /***************************************************************/ @@ -62,22 +66,21 @@ static gfx_t gfx; void gfx_init(void) { int i, j; - uint16 offset; uint8 mask, row, col, temp; memset(&gfx, 0, sizeof(gfx)); /* Initialize priority modes lookup table */ - for (i=0; i<0x100; i++) + for (i = 0; i < 0x10; i++) { - for (j=0; j<0x100; j++) + for (j = 0; j < 0x10; j++) { /* normal */ gfx.lut_prio[0][i][j] = j; /* underwrite */ - gfx.lut_prio[1][i][j] = ((i & 0x0f) ? (i & 0x0f) : (j & 0x0f)) | ((i & 0xf0) ? (i & 0xf0) : (j & 0xf0)); + gfx.lut_prio[1][i][j] = i ? i : j; /* overwrite */ - gfx.lut_prio[2][i][j] = ((j & 0x0f) ? (j & 0x0f) : (i & 0x0f)) | ((j & 0xf0) ? (j & 0xf0) : (i & 0xf0)); + gfx.lut_prio[2][i][j] = j ? j : i; /* invalid */ gfx.lut_prio[3][i][j] = i; } @@ -124,41 +127,37 @@ void gfx_init(void) } } -void gfx_reset(void) -{ - /* Reset cycle counter */ - gfx.cycles = 0; -} - int gfx_context_save(uint8 *state) { uint32 tmp32; int bufferptr = 0; - save_param(&gfx.cycles, sizeof(gfx.cycles)); - save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); + //save_param(&gfx.cycles, sizeof(gfx.cycles)); + //save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); save_param(&gfx.dotMask, sizeof(gfx.dotMask)); save_param(&gfx.stampShift, sizeof(gfx.stampShift)); save_param(&gfx.mapShift, sizeof(gfx.mapShift)); save_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset)); save_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); - tmp32 = (uint8 *)(gfx.tracePtr) - scd.word_ram_2M; + tmp32 = (uint8 *)(gfx.tracePtr) - Pico_mcd->word_ram2M; save_param(&tmp32, 4); - tmp32 = (uint8 *)(gfx.mapPtr) - scd.word_ram_2M; + tmp32 = (uint8 *)(gfx.mapPtr) - Pico_mcd->word_ram2M; save_param(&tmp32, 4); + save_param(&gfx.y_step, sizeof(gfx.y_step)); + return bufferptr; } -int gfx_context_load(uint8 *state) +int gfx_context_load(const uint8 *state) { uint32 tmp32; int bufferptr = 0; - load_param(&gfx.cycles, sizeof(gfx.cycles)); - load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); + //load_param(&gfx.cycles, sizeof(gfx.cycles)); + //load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); load_param(&gfx.dotMask, sizeof(gfx.dotMask)); load_param(&gfx.stampShift, sizeof(gfx.stampShift)); load_param(&gfx.mapShift, sizeof(gfx.mapShift)); @@ -166,19 +165,22 @@ int gfx_context_load(uint8 *state) load_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); load_param(&tmp32, 4); - gfx.tracePtr = (uint16 *)(scd.word_ram_2M + tmp32); + gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32); load_param(&tmp32, 4); - gfx.mapPtr = (uint16 *)(scd.word_ram_2M + tmp32); + gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32); + + load_param(&gfx.y_step, sizeof(gfx.y_step)); return bufferptr; } -INLINE void gfx_render(uint32 bufferIndex, uint32 width) +static void gfx_render(uint32 bufferIndex, uint32 width) { uint8 pixel_in, pixel_out; uint16 stamp_data; uint32 stamp_index; + uint32 priority; /* pixel map start position for current line (13.3 format converted to 13.11) */ uint32 xpos = *gfx.tracePtr++ << 8; @@ -188,11 +190,14 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) uint32 xoffset = (int16) *gfx.tracePtr++; uint32 yoffset = (int16) *gfx.tracePtr++; + priority = (Pico_mcd->s68k_regs[2] << 8) | Pico_mcd->s68k_regs[3]; + priority = (priority >> 3) & 0x03; + /* process all dots */ while (width--) { /* check if stamp map is repeated */ - if (scd.regs[0x58>>1].byte.l & 0x01) + if (Pico_mcd->s68k_regs[0x58+1] & 0x01) { /* stamp map range */ xpos &= gfx.dotMask; @@ -235,7 +240,9 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) /* xx = cell column (0-3) = (xpos >> (11 + 3)) & 3 */ /* s = stamp size (0=16x16, 1=32x32) */ /* hrr = HFLIP & ROTATION bits */ - stamp_index |= gfx.lut_cell[stamp_data | ((scd.regs[0x58>>1].byte.l & 0x02) << 2 ) | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6; + stamp_index |= gfx.lut_cell[ + stamp_data | ((Pico_mcd->s68k_regs[0x58+1] & 0x02) << 2 ) + | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6; /* pixel offset (0-63) */ /* table entry = yyyxxxhrr (9 bits) */ @@ -245,7 +252,7 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) stamp_index |= gfx.lut_pixel[stamp_data | ((xpos >> 8) & 0x38) | ((ypos >> 5) & 0x1c0)]; /* read pixel pair (2 pixels/byte) */ - pixel_out = READ_BYTE(scd.word_ram_2M, stamp_index >> 1); + pixel_out = READ_BYTE(Pico_mcd->word_ram2M, stamp_index >> 1); /* extract left or rigth pixel */ if (stamp_index & 1) @@ -265,23 +272,26 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) } /* read out paired pixel data */ - pixel_in = READ_BYTE(scd.word_ram_2M, bufferIndex >> 1); + pixel_in = READ_BYTE(Pico_mcd->word_ram2M, bufferIndex >> 1); /* update left or rigth pixel */ if (bufferIndex & 1) { + /* priority mode write */ + pixel_out = gfx.lut_prio[priority][pixel_in & 0x0f][pixel_out]; + pixel_out |= (pixel_in & 0xf0); } else { + /* priority mode write */ + pixel_out = gfx.lut_prio[priority][pixel_in >> 4][pixel_out]; + pixel_out = (pixel_out << 4) | (pixel_in & 0x0f); } - /* priority mode write */ - pixel_out = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][pixel_in][pixel_out]; - /* write data to image buffer */ - WRITE_BYTE(scd.word_ram_2M, bufferIndex >> 1, pixel_out); + WRITE_BYTE(Pico_mcd->word_ram2M, bufferIndex >> 1, pixel_out); /* check current pixel position */ if ((bufferIndex & 7) != 7) @@ -301,18 +311,19 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) } } -void gfx_start(unsigned int base, int cycles) +void gfx_start(unsigned int base) { /* make sure 2M mode is enabled */ - if (!(scd.regs[0x02>>1].byte.l & 0x04)) + if (!(Pico_mcd->s68k_regs[3] & 0x04)) { - uint32 mask; + uint32 mask = 0; + uint32 reg; /* trace vector pointer */ - gfx.tracePtr = (uint16 *)(scd.word_ram_2M + ((base << 2) & 0x3fff8)); + gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + ((base << 2) & 0x3fff8)); /* stamps & stamp map size */ - switch ((scd.regs[0x58>>1].byte.l >> 1) & 0x03) + switch ((Pico_mcd->s68k_regs[0x58+1] >> 1) & 0x03) { case 0: gfx.dotMask = 0x07ffff; /* 256x256 dots/map */ @@ -344,78 +355,97 @@ void gfx_start(unsigned int base, int cycles) } /* stamp map table base address */ - gfx.mapPtr = (uint16 *)(scd.word_ram_2M + ((scd.regs[0x5a>>1].w << 2) & mask)); + reg = (Pico_mcd->s68k_regs[0x5a] << 8) | Pico_mcd->s68k_regs[0x5b]; + gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + ((reg << 2) & mask)); /* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */ - gfx.bufferOffset = (((scd.regs[0x5c>>1].byte.l & 0x1f) + 1) << 6) - 7; + gfx.bufferOffset = (((Pico_mcd->s68k_regs[0x5c+1] & 0x1f) + 1) << 6) - 7; /* image buffer start index in dot units (2 pixels/byte) */ - gfx.bufferStart = (scd.regs[0x5e>>1].w << 3) & 0x7ffc0; + reg = (Pico_mcd->s68k_regs[0x5e] << 8) | Pico_mcd->s68k_regs[0x5f]; + gfx.bufferStart = (reg << 3) & 0x7ffc0; /* add image buffer horizontal dot offset */ - gfx.bufferStart += (scd.regs[0x60>>1].byte.l & 0x3f); + gfx.bufferStart += (Pico_mcd->s68k_regs[0x60+1] & 0x3f); /* reset GFX chip cycle counter */ - gfx.cycles = cycles; + //gfx.cycles = cycles; /* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike) */ - gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w; + //gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w; /* start graphics operation */ - scd.regs[0x58>>1].byte.h = 0x80; + Pico_mcd->s68k_regs[0x58] = 0x80; + + gfx_schedule(); } } -void gfx_update(int cycles) +/* PicoDrive specific */ +#define UPDATE_CYCLES 20000 + +static void gfx_schedule(void) { - /* synchronize GFX chip with SUB-CPU */ - cycles -= gfx.cycles; + int w, h, cycles; + int y_step; - /* make sure SUB-CPU is ahead */ - if (cycles > 0) - { - /* number of lines to process */ - unsigned int lines = (cycles + gfx.cyclesPerLine - 1) / gfx.cyclesPerLine; + w = (Pico_mcd->s68k_regs[0x62] << 8) | Pico_mcd->s68k_regs[0x63]; + h = (Pico_mcd->s68k_regs[0x64] << 8) | Pico_mcd->s68k_regs[0x65]; - /* check against remaining lines */ - if (lines < scd.regs[0x64>>1].byte.l) - { - /* update Vdot remaining size */ - scd.regs[0x64>>1].byte.l -= lines; + cycles = 5 * w * h; + if (cycles > UPDATE_CYCLES) + y_step = (UPDATE_CYCLES + 5 * w - 1) / (5 * w); + else + y_step = h; - /* increment cycle counter */ - gfx.cycles += lines * gfx.cyclesPerLine; - } - else - { - /* process remaining lines */ - lines = scd.regs[0x64>>1].byte.l; + gfx.y_step = y_step; + pcd_event_schedule_s68k(PCD_EVENT_GFX, 5 * w * y_step); +} - /* clear Vdot remaining size */ - scd.regs[0x64>>1].byte.l = 0; +void gfx_update(unsigned int cycles) +{ + int lines, lines_reg; + int w; - /* end of graphics operation */ - scd.regs[0x58>>1].byte.h = 0; - - /* level 1 interrupt enabled ? */ - if (scd.regs[0x32>>1].byte.l & 0x02) - { - /* trigger level 1 interrupt */ - scd.pending |= (1 << 1); + if (!(Pico_mcd->s68k_regs[0x58] & 0x80)) + return; - /* update IRQ level */ - s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1); - } + w = (Pico_mcd->s68k_regs[0x62] << 8) | Pico_mcd->s68k_regs[0x63]; + lines = (Pico_mcd->s68k_regs[0x64] << 8) | Pico_mcd->s68k_regs[0x65]; + lines_reg = lines - gfx.y_step; + + if (lines_reg <= 0) { + Pico_mcd->s68k_regs[0x58] = 0; + Pico_mcd->s68k_regs[0x64] = + Pico_mcd->s68k_regs[0x65] = 0; + + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) { + elprintf(EL_INTS|EL_CD, "s68k: gfx_cd irq 1"); + SekInterruptS68k(1); } + } + else { + Pico_mcd->s68k_regs[0x64] = lines_reg >> 8; + Pico_mcd->s68k_regs[0x65] = lines_reg; + if (lines > gfx.y_step) + lines = gfx.y_step; + + pcd_event_schedule(cycles, PCD_EVENT_GFX, 5 * w * lines); + } + + if (PicoIn.opt & POPT_EN_MCD_GFX) + { /* render lines */ while (lines--) { /* process dots to image buffer */ - gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w); + gfx_render(gfx.bufferStart, w); /* increment image buffer start index for next line (8 pixels/line) */ gfx.bufferStart += 8; } } } + +// vim:shiftwidth=2:ts=2:expandtab