diff options
Diffstat (limited to 'src/mame/video/itech32.c')
-rw-r--r-- | src/mame/video/itech32.c | 1486 |
1 files changed, 1486 insertions, 0 deletions
diff --git a/src/mame/video/itech32.c b/src/mame/video/itech32.c new file mode 100644 index 00000000000..4e00bae7b32 --- /dev/null +++ b/src/mame/video/itech32.c @@ -0,0 +1,1486 @@ +/*************************************************************************** + + Incredible Technologies/Strata system + (32-bit blitter variant) + +***************************************************************************/ + +#include "driver.h" +#include "profiler.h" +#include "cpu/m68000/m68000.h" +#include "itech32.h" + + +/************************************* + * + * Debugging + * + *************************************/ + +#define BLIT_LOGGING 0 + + + +/************************************* + * + * Blitter constants + * + *************************************/ + +#define VIDEO_UNKNOWN00 itech32_video[0x00/2] /* $0087 at startup */ +#define VIDEO_STATUS itech32_video[0x00/2] +#define VIDEO_INTSTATE itech32_video[0x02/2] +#define VIDEO_INTACK itech32_video[0x02/2] +#define VIDEO_TRANSFER itech32_video[0x04/2] +#define VIDEO_TRANSFER_FLAGS itech32_video[0x06/2] /* $5080 at startup (kept at $1512) */ +#define VIDEO_COMMAND itech32_video[0x08/2] /* $0005 at startup */ +#define VIDEO_INTENABLE itech32_video[0x0a/2] /* $0144 at startup (kept at $1514) */ +#define VIDEO_TRANSFER_HEIGHT itech32_video[0x0c/2] +#define VIDEO_TRANSFER_WIDTH itech32_video[0x0e/2] +#define VIDEO_TRANSFER_ADDRLO itech32_video[0x10/2] +#define VIDEO_TRANSFER_X itech32_video[0x12/2] +#define VIDEO_TRANSFER_Y itech32_video[0x14/2] +#define VIDEO_SRC_YSTEP itech32_video[0x16/2] /* $0011 at startup */ +#define VIDEO_SRC_XSTEP itech32_video[0x18/2] +#define VIDEO_DST_XSTEP itech32_video[0x1a/2] +#define VIDEO_DST_YSTEP itech32_video[0x1c/2] +#define VIDEO_YSTEP_PER_X itech32_video[0x1e/2] +#define VIDEO_XSTEP_PER_Y itech32_video[0x20/2] +#define VIDEO_UNKNOWN22 itech32_video[0x22/2] /* $0033 at startup */ +#define VIDEO_LEFTCLIP itech32_video[0x24/2] +#define VIDEO_RIGHTCLIP itech32_video[0x26/2] +#define VIDEO_TOPCLIP itech32_video[0x28/2] +#define VIDEO_BOTTOMCLIP itech32_video[0x2a/2] +#define VIDEO_INTSCANLINE itech32_video[0x2c/2] /* $00ef at startup */ +#define VIDEO_TRANSFER_ADDRHI itech32_video[0x2e/2] /* $0000 at startup */ + +#define VIDEO_UNKNOWN30 itech32_video[0x30/2] /* $0040 at startup */ +#define VIDEO_VTOTAL itech32_video[0x32/2] /* $0106 at startup */ +#define VIDEO_VSYNC itech32_video[0x34/2] /* $0101 at startup */ +#define VIDEO_VBLANK_START itech32_video[0x36/2] /* $00f3 at startup */ +#define VIDEO_VBLANK_END itech32_video[0x38/2] /* $0003 at startup */ +#define VIDEO_HTOTAL itech32_video[0x3a/2] /* $01fc at startup */ +#define VIDEO_HSYNC itech32_video[0x3c/2] /* $01e4 at startup */ +#define VIDEO_HBLANK_START itech32_video[0x3e/2] /* $01b2 at startup */ +#define VIDEO_HBLANK_END itech32_video[0x40/2] /* $0032 at startup */ +#define VIDEO_UNKNOWN42 itech32_video[0x42/2] /* $0015 at startup */ +#define VIDEO_DISPLAY_YORIGIN1 itech32_video[0x44/2] /* $0000 at startup */ +#define VIDEO_DISPLAY_YORIGIN2 itech32_video[0x46/2] /* $0000 at startup */ +#define VIDEO_DISPLAY_YSCROLL2 itech32_video[0x48/2] /* $0000 at startup */ +#define VIDEO_UNKNOWN4a itech32_video[0x4a/2] /* $0000 at startup */ +#define VIDEO_DISPLAY_XORIGIN1 itech32_video[0x4c/2] /* $0000 at startup */ +#define VIDEO_DISPLAY_XORIGIN2 itech32_video[0x4e/2] /* $0000 at startup */ +#define VIDEO_DISPLAY_XSCROLL2 itech32_video[0x50/2] /* $0000 at startup */ +#define VIDEO_UNKNOWN52 itech32_video[0x52/2] /* $0000 at startup */ +#define VIDEO_UNKNOWN54 itech32_video[0x54/2] /* $0080 at startup */ +#define VIDEO_UNKNOWN56 itech32_video[0x56/2] /* $00c0 at startup */ +#define VIDEO_UNKNOWN58 itech32_video[0x58/2] /* $01c0 at startup */ +#define VIDEO_UNKNOWN5a itech32_video[0x5a/2] /* $01c0 at startup */ +#define VIDEO_UNKNOWN5c itech32_video[0x5c/2] /* $01cf at startup */ +#define VIDEO_UNKNOWN5e itech32_video[0x5e/2] /* $01cf at startup */ +#define VIDEO_UNKNOWN60 itech32_video[0x60/2] /* $01e3 at startup */ +#define VIDEO_UNKNOWN62 itech32_video[0x62/2] /* $01cf at startup */ +#define VIDEO_UNKNOWN64 itech32_video[0x64/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN66 itech32_video[0x66/2] /* $0183 at startup */ +#define VIDEO_UNKNOWN68 itech32_video[0x68/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN6a itech32_video[0x6a/2] /* $000f at startup */ +#define VIDEO_UNKNOWN6c itech32_video[0x6c/2] /* $018f at startup */ +#define VIDEO_UNKNOWN6e itech32_video[0x6e/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN70 itech32_video[0x70/2] /* $000f at startup */ +#define VIDEO_UNKNOWN72 itech32_video[0x72/2] /* $000f at startup */ +#define VIDEO_UNKNOWN74 itech32_video[0x74/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN76 itech32_video[0x76/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN78 itech32_video[0x78/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN7a itech32_video[0x7a/2] /* $01ff at startup */ +#define VIDEO_UNKNOWN7c itech32_video[0x7c/2] /* $0820 at startup */ +#define VIDEO_UNKNOWN7e itech32_video[0x7e/2] /* $0100 at startup */ + +#define VIDEO_STARTSTEP itech32_video[0x80/2] /* drivedge only? */ +#define VIDEO_LEFTSTEPLO itech32_video[0x82/2] /* drivedge only? */ +#define VIDEO_LEFTSTEPHI itech32_video[0x84/2] /* drivedge only? */ +#define VIDEO_RIGHTSTEPLO itech32_video[0x86/2] /* drivedge only? */ +#define VIDEO_RIGHTSTEPHI itech32_video[0x88/2] /* drivedge only? */ + +#define VIDEOINT_SCANLINE 0x0004 +#define VIDEOINT_BLITTER 0x0040 + +#define XFERFLAG_TRANSPARENT 0x0001 +#define XFERFLAG_XFLIP 0x0002 +#define XFERFLAG_YFLIP 0x0004 +#define XFERFLAG_DSTXSCALE 0x0008 +#define XFERFLAG_DYDXSIGN 0x0010 +#define XFERFLAG_DXDYSIGN 0x0020 +#define XFERFLAG_UNKNOWN8 0x0100 +#define XFERFLAG_CLIP 0x0400 +#define XFERFLAG_UNKNOWN15 0x8000 + +#define XFERFLAG_KNOWNFLAGS (XFERFLAG_TRANSPARENT | XFERFLAG_XFLIP | XFERFLAG_YFLIP | XFERFLAG_DSTXSCALE | XFERFLAG_DYDXSIGN | XFERFLAG_DXDYSIGN | XFERFLAG_CLIP) + +#define VRAM_WIDTH 512 + + + +/************************************* + * + * Global variables + * + *************************************/ + +UINT16 *itech32_video; +UINT32 *drivedge_zbuf_control; +UINT8 itech32_planes; +UINT16 itech32_vram_height; + +static UINT16 xfer_xcount, xfer_ycount; +static UINT16 xfer_xcur, xfer_ycur; + +static rectangle clip_rect, scaled_clip_rect; +static rectangle clip_save; + +static emu_timer *scanline_timer; + +static UINT8 *grom_base; +static UINT32 grom_size; +static UINT32 grom_bank; +static UINT32 grom_bank_mask; + +static UINT16 color_latch[2]; +static UINT8 enable_latch[2]; + +static UINT16 *videoplane[2]; +static UINT32 vram_mask; +static UINT32 vram_xmask, vram_ymask; + +static int is_drivedge; + +static TIMER_CALLBACK( scanline_interrupt ); + + + +/************************************* + * + * Macros and inlines + * + *************************************/ + +#define ADJUSTED_HEIGHT(x) ((((x) >> 1) & 0x100) | ((x) & 0xff)) + +INLINE offs_t compute_safe_address(int x, int y) +{ + return ((y & vram_ymask) * 512) + (x & vram_xmask); +} + +INLINE void disable_clipping(void) +{ + clip_save = clip_rect; + + clip_rect.min_x = clip_rect.min_y = 0; + clip_rect.max_x = clip_rect.max_y = 0xfff; + + scaled_clip_rect.min_x = scaled_clip_rect.min_y = 0; + scaled_clip_rect.max_x = scaled_clip_rect.max_y = 0xfff << 8; +} + +INLINE void enable_clipping(void) +{ + clip_rect = clip_save; + + scaled_clip_rect.min_x = clip_rect.min_x << 8; + scaled_clip_rect.max_x = clip_rect.max_x << 8; + scaled_clip_rect.min_y = clip_rect.min_y << 8; + scaled_clip_rect.max_y = clip_rect.max_y << 8; +} + + + +/************************************* + * + * Video start + * + *************************************/ + +VIDEO_START( itech32 ) +{ + int i; + + /* allocate memory */ + videoram16 = auto_malloc(VRAM_WIDTH * (itech32_vram_height + 16) * 2 * 2); + memset(videoram16, 0xff, VRAM_WIDTH * (itech32_vram_height + 16) * 2 * 2); + + /* videoplane[0] is the foreground; videoplane[1] is the background */ + videoplane[0] = &videoram16[0 * VRAM_WIDTH * (itech32_vram_height + 16) + 8 * VRAM_WIDTH]; + videoplane[1] = &videoram16[1 * VRAM_WIDTH * (itech32_vram_height + 16) + 8 * VRAM_WIDTH]; + + /* set the masks */ + vram_mask = VRAM_WIDTH * itech32_vram_height - 1; + vram_xmask = VRAM_WIDTH - 1; + vram_ymask = itech32_vram_height - 1; + + /* clear the planes initially */ + for (i = 0; i < VRAM_WIDTH * itech32_vram_height; i++) + videoplane[0][i] = videoplane[1][i] = 0xff; + + /* fetch the GROM base */ + grom_base = memory_region(REGION_GFX1); + grom_size = memory_region_length(REGION_GFX1); + grom_bank = 0; + grom_bank_mask = grom_size >> 24; + if (grom_bank_mask == 2) + grom_bank_mask = 3; + + /* reset statics */ + memset(itech32_video, 0, 0x80); + + scanline_timer = timer_alloc(scanline_interrupt); + enable_latch[0] = 1; + enable_latch[1] = (itech32_planes > 1) ? 1 : 0; + + is_drivedge = 0; +} + + + +/************************************* + * + * Latches + * + *************************************/ + +WRITE16_HANDLER( timekill_colora_w ) +{ + if (ACCESSING_LSB) + { + enable_latch[0] = (~data >> 5) & 1; + enable_latch[1] = (~data >> 7) & 1; + color_latch[0] = (data & 0x0f) << 8; + } +} + + +WRITE16_HANDLER( timekill_colorbc_w ) +{ + if (ACCESSING_LSB) + color_latch[1] = ((data & 0xf0) << 4) | 0x1000; +} + + +WRITE16_HANDLER( timekill_intensity_w ) +{ + if (ACCESSING_LSB) + { + double intensity = (double)(data & 0xff) / (double)0x60; + int i; + for (i = 0; i < 8192; i++) + palette_set_brightness(Machine, i, intensity); + } +} + + +WRITE16_HANDLER( bloodstm_color1_w ) +{ + if (ACCESSING_LSB) + color_latch[0] = (data & 0x7f) << 8; +} + + +WRITE16_HANDLER( bloodstm_color2_w ) +{ + if (ACCESSING_LSB) + color_latch[1] = (data & 0x7f) << 8; +} + + +WRITE16_HANDLER( bloodstm_plane_w ) +{ + if (ACCESSING_LSB) + { + enable_latch[0] = (~data >> 1) & 1; + enable_latch[1] = (~data >> 2) & 1; + } +} + + +WRITE32_HANDLER( drivedge_color0_w ) +{ + if (!(mem_mask & 0x00ff0000)) + color_latch[0] = ((data >> 16) & 0x7f) << 8; +} + + +WRITE32_HANDLER( itech020_color1_w ) +{ + if (ACCESSING_LSB32) + color_latch[1] = (data & 0x7f) << 8; +} + + +WRITE32_HANDLER( itech020_color2_w ) +{ + if (ACCESSING_LSB32) + color_latch[0] = (data & 0x7f) << 8; +} + + +WRITE32_HANDLER( itech020_plane_w ) +{ + if (!(mem_mask & 0x0000ff00)) + { + enable_latch[0] = (~data >> 9) & 1; + enable_latch[1] = (~data >> 10) & 1; + grom_bank = ((data >> 14) & grom_bank_mask) << 24; + } +} + + + +/************************************* + * + * Palette I/O + * + *************************************/ + +WRITE16_HANDLER( timekill_paletteram_w ) +{ + int r, g, b; + + COMBINE_DATA(&paletteram16[offset]); + + r = paletteram16[offset & ~1] & 0xff; + g = paletteram16[offset & ~1] >> 8; + b = paletteram16[offset | 1] >> 8; + + palette_set_color(Machine, offset / 2, MAKE_RGB(r, g, b)); +} + + +WRITE16_HANDLER( bloodstm_paletteram_w ) +{ + int r, g, b; + + /* in test mode, the LSB is used; in game mode, the MSB is used */ + if (!ACCESSING_LSB && (offset & 1)) + data >>= 8, mem_mask >>= 8; + COMBINE_DATA(&paletteram16[offset]); + + r = paletteram16[offset & ~1] & 0xff; + g = paletteram16[offset & ~1] >> 8; + b = paletteram16[offset | 1] & 0xff; + + palette_set_color(Machine, offset / 2, MAKE_RGB(r, g, b)); +} + + +WRITE32_HANDLER( drivedge_paletteram_w ) +{ + int r, g, b; + + COMBINE_DATA(&paletteram32[offset]); + + r = paletteram32[offset] & 0xff; + g = (paletteram32[offset] >> 8) & 0xff; + b = (paletteram32[offset] >> 16) & 0xff; + + palette_set_color(Machine, offset, MAKE_RGB(r, g, b)); +} + + +WRITE32_HANDLER( itech020_paletteram_w ) +{ + int r, g, b; + + COMBINE_DATA(&paletteram32[offset]); + + r = (paletteram32[offset] >> 16) & 0xff; + g = (paletteram32[offset] >> 8) & 0xff; + b = paletteram32[offset] & 0xff; + + palette_set_color(Machine, offset, MAKE_RGB(r, g, b)); +} + + + +/************************************* + * + * Debugging + * + *************************************/ + +static void logblit(const char *tag) +{ + if (!input_code_pressed(KEYCODE_L)) + return; + if (is_drivedge && VIDEO_TRANSFER_FLAGS == 0x5490) + { + /* polygon drawing */ + logerror("%s: e=%d%d f=%04x s=(%03x-%03x,%03x) w=%03x h=%03x b=%02x%04x c=%02x%02x ss=%04x,%04x ds=%04x,%04x ls=%04x%04x rs=%04x%04x u80=%04x", tag, + enable_latch[0], enable_latch[1], + VIDEO_TRANSFER_FLAGS, + VIDEO_TRANSFER_X, VIDEO_RIGHTCLIP, VIDEO_TRANSFER_Y, VIDEO_TRANSFER_WIDTH, VIDEO_TRANSFER_HEIGHT, + VIDEO_TRANSFER_ADDRHI, VIDEO_TRANSFER_ADDRLO, + color_latch[0] >> 8, color_latch[1] >> 8, + VIDEO_SRC_XSTEP, VIDEO_SRC_YSTEP, + VIDEO_DST_XSTEP, VIDEO_DST_YSTEP, + VIDEO_LEFTSTEPHI, VIDEO_LEFTSTEPLO, VIDEO_RIGHTSTEPHI, VIDEO_RIGHTSTEPLO, + VIDEO_STARTSTEP); + } + + else if (itech32_video[0x16/2] == 0x100 && itech32_video[0x18/2] == 0x100 && + itech32_video[0x1a/2] == 0x000 && itech32_video[0x1c/2] == 0x100 && + itech32_video[0x1e/2] == 0x000 && itech32_video[0x20/2] == 0x000) + { + logerror("%s: e=%d%d f=%04x c=%02x%02x %02x%04x -> (%03x,%03x) %3dx%3dc=(%03x,%03x)-(%03x,%03x)", tag, + enable_latch[0], enable_latch[1], + VIDEO_TRANSFER_FLAGS, + color_latch[0] >> 8, color_latch[1] >> 8, + VIDEO_TRANSFER_ADDRHI, VIDEO_TRANSFER_ADDRLO, + VIDEO_TRANSFER_X, VIDEO_TRANSFER_Y, + VIDEO_TRANSFER_WIDTH, ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT), + VIDEO_LEFTCLIP, VIDEO_TOPCLIP, VIDEO_RIGHTCLIP, VIDEO_BOTTOMCLIP); + } + else + { + logerror("%s: e=%d%d f=%04x c=%02x%02x %02x%04x -> (%03x,%03x) %3dx%3d c=(%03x,%03x)-(%03x,%03x) s=%04x %04x %04x %04x %04x %04x", tag, + enable_latch[0], enable_latch[1], + VIDEO_TRANSFER_FLAGS, + color_latch[0] >> 8, color_latch[1] >> 8, + VIDEO_TRANSFER_ADDRHI, VIDEO_TRANSFER_ADDRLO, + VIDEO_TRANSFER_X, VIDEO_TRANSFER_Y, + VIDEO_TRANSFER_WIDTH, ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT), + VIDEO_LEFTCLIP, VIDEO_TOPCLIP, VIDEO_RIGHTCLIP, VIDEO_BOTTOMCLIP, + itech32_video[0x16/2], itech32_video[0x18/2], itech32_video[0x1a/2], + itech32_video[0x1c/2], itech32_video[0x1e/2], itech32_video[0x20/2]); + } + if (is_drivedge) logerror(" v0=%08x v1=%08x v2=%08x v3=%08x", drivedge_zbuf_control[0], drivedge_zbuf_control[1], drivedge_zbuf_control[2], drivedge_zbuf_control[3]); + logerror("\n"); +} + + + +/************************************* + * + * Video interrupts + * + *************************************/ + +static void update_interrupts(int fast) +{ + int scanline_state = 0, blitter_state = 0; + + if (VIDEO_INTSTATE & VIDEO_INTENABLE & VIDEOINT_SCANLINE) + scanline_state = 1; + if (VIDEO_INTSTATE & VIDEO_INTENABLE & VIDEOINT_BLITTER) + blitter_state = 1; + + itech32_update_interrupts(-1, blitter_state, scanline_state); +} + + +static TIMER_CALLBACK( scanline_interrupt ) +{ + /* set timer for next frame */ + timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, VIDEO_INTSCANLINE, 0), 0, attotime_zero); + + /* set the interrupt bit in the status reg */ + logerror("-------------- (DISPLAY INT @ %d) ----------------\n", video_screen_get_vpos(0)); + VIDEO_INTSTATE |= VIDEOINT_SCANLINE; + + /* update the interrupt state */ + update_interrupts(0); +} + + + +/************************************* + * + * Uncompressed blitter functions + * + *************************************/ + +static void draw_raw(UINT16 *base, UINT16 color) +{ + UINT8 *src = &grom_base[(grom_bank | ((VIDEO_TRANSFER_ADDRHI & 0xff) << 16) | VIDEO_TRANSFER_ADDRLO) % grom_size]; + int transparent_pen = (VIDEO_TRANSFER_FLAGS & XFERFLAG_TRANSPARENT) ? 0xff : -1; + int width = VIDEO_TRANSFER_WIDTH << 8; + int height = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT) << 8; + int xsrcstep = VIDEO_SRC_XSTEP; + int ysrcstep = VIDEO_SRC_YSTEP; + int sx, sy = (VIDEO_TRANSFER_Y & 0xfff) << 8; + int startx = (VIDEO_TRANSFER_X & 0xfff) << 8; + int xdststep = 0x100; + int ydststep = VIDEO_DST_YSTEP; + int x, y; + + /* adjust for (lack of) clipping */ + if (!(VIDEO_TRANSFER_FLAGS & XFERFLAG_CLIP)) + disable_clipping(); + + /* adjust for scaling */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_DSTXSCALE) + xdststep = VIDEO_DST_XSTEP; + + /* adjust for flipping */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_XFLIP) + xdststep = -xdststep; + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_YFLIP) + ydststep = -ydststep; + + /* loop over Y in src pixels */ + for (y = 0; y < height; y += ysrcstep, sy += ydststep) + { + UINT8 *rowsrc = &src[(y >> 8) * (width >> 8)]; + + /* simpler case: VIDEO_YSTEP_PER_X is zero */ + if (VIDEO_YSTEP_PER_X == 0) + { + /* clip in the Y direction */ + if (sy >= scaled_clip_rect.min_y && sy < scaled_clip_rect.max_y) + { + UINT32 dstoffs; + + /* direction matters here */ + sx = startx; + if (xdststep > 0) + { + /* skip left pixels */ + for (x = 0; x < width && sx < scaled_clip_rect.min_x; x += xsrcstep, sx += xdststep) ; + + /* compute the address */ + dstoffs = compute_safe_address(sx >> 8, sy >> 8) - (sx >> 8); + + /* render middle pixels */ + for ( ; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen) + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + } + } + else + { + /* skip right pixels */ + for (x = 0; x < width && sx >= scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep) ; + + /* compute the address */ + dstoffs = compute_safe_address(sx >> 8, sy >> 8) - (sx >> 8); + + /* render middle pixels */ + for ( ; x < width && sx >= scaled_clip_rect.min_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen) + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + } + } + } + } + + /* slow case: VIDEO_YSTEP_PER_X is non-zero */ + else + { + int ystep = (VIDEO_TRANSFER_FLAGS & XFERFLAG_DYDXSIGN) ? -VIDEO_YSTEP_PER_X : VIDEO_YSTEP_PER_X; + int ty = sy; + + /* render all pixels */ + sx = startx; + for (x = 0; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep, ty += ystep) + if (ty >= scaled_clip_rect.min_y && ty < scaled_clip_rect.max_y && + sx >= scaled_clip_rect.min_x && sx < scaled_clip_rect.max_x) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen) + base[compute_safe_address(sx >> 8, ty >> 8)] = pixel | color; + } + } + + /* apply skew */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_DXDYSIGN) + startx += VIDEO_XSTEP_PER_Y; + else + startx -= VIDEO_XSTEP_PER_Y; + } + + /* restore cliprects */ + if (!(VIDEO_TRANSFER_FLAGS & XFERFLAG_CLIP)) + enable_clipping(); +} + + +static void draw_raw_drivedge(UINT16 *base, UINT16 *zbase, UINT16 color) +{ + UINT8 *src = &grom_base[(grom_bank | ((VIDEO_TRANSFER_ADDRHI & 0xff) << 16) | VIDEO_TRANSFER_ADDRLO) % grom_size]; + int transparent_pen = (VIDEO_TRANSFER_FLAGS & XFERFLAG_TRANSPARENT) ? 0xff : -1; + int width = VIDEO_TRANSFER_WIDTH << 8; + int height = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT) << 8; + int xsrcstep = VIDEO_SRC_XSTEP; + int ysrcstep = VIDEO_SRC_YSTEP; + int sx, sy = ((VIDEO_TRANSFER_Y & 0xfff) << 8) + 0x80; + int startx = ((VIDEO_TRANSFER_X & 0xfff) << 8) + 0x80; + int xdststep = 0x100; + int ydststep = VIDEO_DST_YSTEP; + INT32 z0 = drivedge_zbuf_control[2] & 0x7ff00; + INT32 zmatch = (drivedge_zbuf_control[2] & 0x1f) << 11; + INT32 srcdelta = 0; + int x, y; + + /* adjust for (lack of) clipping */ + if (!(VIDEO_TRANSFER_FLAGS & XFERFLAG_CLIP)) + disable_clipping(); + + /* adjust for scaling */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_DSTXSCALE) + xdststep = VIDEO_DST_XSTEP; + + /* adjust for flipping */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_XFLIP) + xdststep = -xdststep; + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_YFLIP) + ydststep = -ydststep; + + /* loop over Y in src pixels */ + for (y = 0; y < height; y += ysrcstep, sy += ydststep) + { + UINT8 *rowsrc = src + (srcdelta >> 8); + + /* in the polygon case, we don't factor in the Y */ + if (VIDEO_TRANSFER_FLAGS != 0x5490) + rowsrc += (y >> 8) * (width >> 8); + else + width = 1000 << 8; + + /* simpler case: VIDEO_YSTEP_PER_X is zero */ + if (VIDEO_YSTEP_PER_X == 0) + { + /* clip in the Y direction */ + if (sy >= scaled_clip_rect.min_y && sy < scaled_clip_rect.max_y) + { + UINT32 dstoffs, zbufoffs; + INT32 z = z0; + + /* direction matters here */ + sx = startx; + if (xdststep > 0) + { + /* skip left pixels */ + for (x = 0; x < width && sx < scaled_clip_rect.min_x; x += xsrcstep, sx += xdststep) + z += (INT32)drivedge_zbuf_control[0]; + + /* compute the address */ + dstoffs = compute_safe_address(sx >> 8, sy >> 8) - (sx >> 8); + zbufoffs = compute_safe_address(sx >> 8, sy >> 8) - (sx >> 8); + + /* render middle pixels */ + if (drivedge_zbuf_control[3] & 0x8000) + { + for ( ; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen) + { + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + zbase[(zbufoffs + (sx >> 8)) & vram_mask] = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + else if (drivedge_zbuf_control[3] & 0x4000) + { + for ( ; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen && zmatch == (zbase[(zbufoffs + (sx >> 8)) & vram_mask] & (0x1f << 11))) + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + z += (INT32)drivedge_zbuf_control[0]; + } + } + else + { + for ( ; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen && ((z >> 8) <= (zbase[(zbufoffs + (sx >> 8)) & vram_mask] & 0x7ff))) + { + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + zbase[(zbufoffs + (sx >> 8)) & vram_mask] = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + } + else + { + /* skip right pixels */ + for (x = 0; x < width && sx >= scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep) + z += (INT32)drivedge_zbuf_control[0]; + + /* compute the address */ + dstoffs = compute_safe_address(sx >> 8, sy >> 8) - (sx >> 8); + zbufoffs = compute_safe_address(sx >> 8, sy >> 8) - (sx >> 8); + + /* render middle pixels */ + if (drivedge_zbuf_control[3] & 0x8000) + { + for ( ; x < width && sx >= scaled_clip_rect.min_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen) + { + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + zbase[(zbufoffs + (sx >> 8)) & vram_mask] = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + else if (drivedge_zbuf_control[3] & 0x4000) + { + for ( ; x < width && sx >= scaled_clip_rect.min_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen && zmatch == (zbase[(zbufoffs + (sx >> 8)) & vram_mask] & (0x1f << 11))) + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + z += (INT32)drivedge_zbuf_control[0]; + } + } + else + { + for ( ; x < width && sx >= scaled_clip_rect.min_x; x += xsrcstep, sx += xdststep) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen && ((z >> 8) <= (zbase[(zbufoffs + (sx >> 8)) & vram_mask] & 0x7ff))) + { + base[(dstoffs + (sx >> 8)) & vram_mask] = pixel | color; + zbase[(zbufoffs + (sx >> 8)) & vram_mask] = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + } + } + } + + /* slow case: VIDEO_YSTEP_PER_X is non-zero */ + else + { + int ystep = (VIDEO_TRANSFER_FLAGS & XFERFLAG_DYDXSIGN) ? -VIDEO_YSTEP_PER_X : VIDEO_YSTEP_PER_X; + int ty = sy; + INT32 z = z0; + + /* render all pixels */ + sx = startx; + if (drivedge_zbuf_control[3] & 0x8000) + { + for (x = 0; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep, ty += ystep) + if (ty >= scaled_clip_rect.min_y && ty < scaled_clip_rect.max_y && + sx >= scaled_clip_rect.min_x && sx < scaled_clip_rect.max_x) + { + int pixel = rowsrc[x >> 8]; + if (pixel != transparent_pen) + { + base[compute_safe_address(sx >> 8, ty >> 8)] = pixel | color; + zbase[compute_safe_address(sx >> 8, ty >> 8)] = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + else if (drivedge_zbuf_control[3] & 0x4000) + { + for (x = 0; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep, ty += ystep) + if (ty >= scaled_clip_rect.min_y && ty < scaled_clip_rect.max_y && + sx >= scaled_clip_rect.min_x && sx < scaled_clip_rect.max_x) + { + int pixel = rowsrc[x >> 8]; + UINT16 *zbuf = &zbase[compute_safe_address(sx >> 8, ty >> 8)]; + if (pixel != transparent_pen && zmatch == (*zbuf & (0x1f << 11))) + { + base[compute_safe_address(sx >> 8, ty >> 8)] = pixel | color; + *zbuf = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + else + { + for (x = 0; x < width && sx < scaled_clip_rect.max_x; x += xsrcstep, sx += xdststep, ty += ystep) + if (ty >= scaled_clip_rect.min_y && ty < scaled_clip_rect.max_y && + sx >= scaled_clip_rect.min_x && sx < scaled_clip_rect.max_x) + { + int pixel = rowsrc[x >> 8]; + UINT16 *zbuf = &zbase[compute_safe_address(sx >> 8, ty >> 8)]; + if (pixel != transparent_pen && ((z >> 8) <= (*zbuf & 0x7ff))) + { + base[compute_safe_address(sx >> 8, ty >> 8)] = pixel | color; + *zbuf = (z >> 8) | zmatch; + } + z += (INT32)drivedge_zbuf_control[0]; + } + } + } + + /* apply skew */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_DXDYSIGN) + startx += VIDEO_XSTEP_PER_Y; + else + startx -= VIDEO_XSTEP_PER_Y; + + /* update the per-scanline parameters */ + if (VIDEO_TRANSFER_FLAGS == 0x5490) + { + startx += (INT32)((VIDEO_LEFTSTEPHI << 16) | VIDEO_LEFTSTEPLO); + scaled_clip_rect.max_x += (INT32)((VIDEO_RIGHTSTEPHI << 16) | VIDEO_RIGHTSTEPLO); + srcdelta += (INT16)VIDEO_STARTSTEP; + } + z0 += (INT32)drivedge_zbuf_control[1]; + } + + /* restore cliprects */ + if (!(VIDEO_TRANSFER_FLAGS & XFERFLAG_CLIP)) + enable_clipping(); + + /* reflect the final values into registers */ + VIDEO_TRANSFER_X = (VIDEO_TRANSFER_X & ~0xfff) | (startx >> 8); + VIDEO_RIGHTCLIP = (VIDEO_RIGHTCLIP & ~0xfff) | (scaled_clip_rect.max_x >> 8); + VIDEO_TRANSFER_Y = (VIDEO_TRANSFER_Y & ~0xfff) | ((VIDEO_TRANSFER_Y + (y >> 8)) & 0xfff); + VIDEO_TRANSFER_ADDRLO += srcdelta >> 8; + + drivedge_zbuf_control[2] = (drivedge_zbuf_control[2] & ~0x7ff00) | (z0 & 0x7ff00); +} + + + +/************************************* + * + * Compressed blitter macros + * + *************************************/ + +#define GET_NEXT_RUN(xleft, count, innercount, src) \ +do { \ + /* load next RLE chunk if needed */ \ + if (!count) \ + { \ + count = *src++; \ + val = (count & 0x80) ? -1 : *src++; \ + count &= 0x7f; \ + } \ + \ + /* determine how much to bite off */ \ + innercount = (xleft > count) ? count : xleft; \ + count -= innercount; \ + xleft -= innercount; \ +} while (0) + + +#define SKIP_RLE(skip, xleft, count, innercount, src)\ +do { \ + /* scan RLE until done */ \ + for (xleft = skip; xleft > 0; ) \ + { \ + /* load next RLE chunk if needed */ \ + GET_NEXT_RUN(xleft, count, innercount, src);\ + \ + /* skip past the data */ \ + if (val == -1) src += innercount; \ + } \ +} while (0) + + + +/************************************* + * + * Fast compressed blitter functions + * + *************************************/ + +INLINE void draw_rle_fast(UINT16 *base, UINT16 color) +{ + UINT8 *src = &grom_base[(grom_bank | ((VIDEO_TRANSFER_ADDRHI & 0xff) << 16) | VIDEO_TRANSFER_ADDRLO) % grom_size]; + int transparent_pen = (VIDEO_TRANSFER_FLAGS & XFERFLAG_TRANSPARENT) ? 0xff : -1; + int width = VIDEO_TRANSFER_WIDTH; + int height = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT); + int sx = VIDEO_TRANSFER_X & 0xfff; + int sy = (VIDEO_TRANSFER_Y & 0xfff) << 8; + int xleft, y, count = 0, val = 0, innercount; + int ydststep = VIDEO_DST_YSTEP; + int lclip, rclip; + + /* determine clipping */ + lclip = clip_rect.min_x - sx; + if (lclip < 0) lclip = 0; + rclip = sx + width - clip_rect.max_x; + if (rclip < 0) rclip = 0; + width -= lclip + rclip; + sx += lclip; + + /* adjust for flipping */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_YFLIP) + ydststep = -ydststep; + + /* loop over Y in src pixels */ + for (y = 0; y < height; y++, sy += ydststep) + { + UINT32 dstoffs; + + /* clip in the Y direction */ + if (sy < scaled_clip_rect.min_y || sy >= scaled_clip_rect.max_y) + { + SKIP_RLE(width + lclip + rclip, xleft, count, innercount, src); + continue; + } + + /* compute the address */ + dstoffs = compute_safe_address(sx, sy >> 8); + + /* left clip */ + SKIP_RLE(lclip, xleft, count, innercount, src); + + /* loop until gone */ + for (xleft = width; xleft > 0; ) + { + /* load next RLE chunk if needed */ + GET_NEXT_RUN(xleft, count, innercount, src); + + /* run of literals */ + if (val == -1) + while (innercount--) + { + int pixel = *src++; + if (pixel != transparent_pen) + base[dstoffs & vram_mask] = color | pixel; + dstoffs++; + } + + /* run of non-transparent repeats */ + else if (val != transparent_pen) + { + val |= color; + while (innercount--) + base[dstoffs++ & vram_mask] = val; + } + + /* run of transparent repeats */ + else + dstoffs += innercount; + } + + /* right clip */ + SKIP_RLE(rclip, xleft, count, innercount, src); + } +} + + +INLINE void draw_rle_fast_xflip(UINT16 *base, UINT16 color) +{ + UINT8 *src = &grom_base[(grom_bank | ((VIDEO_TRANSFER_ADDRHI & 0xff) << 16) | VIDEO_TRANSFER_ADDRLO) % grom_size]; + int transparent_pen = (VIDEO_TRANSFER_FLAGS & XFERFLAG_TRANSPARENT) ? 0xff : -1; + int width = VIDEO_TRANSFER_WIDTH; + int height = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT); + int sx = VIDEO_TRANSFER_X & 0xfff; + int sy = (VIDEO_TRANSFER_Y & 0xfff) << 8; + int xleft, y, count = 0, val = 0, innercount; + int ydststep = VIDEO_DST_YSTEP; + int lclip, rclip; + + /* determine clipping */ + lclip = sx - clip_rect.max_x; + if (lclip < 0) lclip = 0; + rclip = clip_rect.min_x - (sx - width); + if (rclip < 0) rclip = 0; + width -= lclip + rclip; + sx -= lclip; + + /* adjust for flipping */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_YFLIP) + ydststep = -ydststep; + + /* loop over Y in src pixels */ + for (y = 0; y < height; y++, sy += ydststep) + { + UINT32 dstoffs; + + /* clip in the Y direction */ + if (sy < scaled_clip_rect.min_y || sy >= scaled_clip_rect.max_y) + { + SKIP_RLE(width + lclip + rclip, xleft, count, innercount, src); + continue; + } + + /* compute the address */ + dstoffs = compute_safe_address(sx, sy >> 8); + + /* left clip */ + SKIP_RLE(lclip, xleft, count, innercount, src); + + /* loop until gone */ + for (xleft = width; xleft > 0; ) + { + /* load next RLE chunk if needed */ + GET_NEXT_RUN(xleft, count, innercount, src); + + /* run of literals */ + if (val == -1) + while (innercount--) + { + int pixel = *src++; + if (pixel != transparent_pen) + base[dstoffs & vram_mask] = color | pixel; + dstoffs--; + } + + /* run of non-transparent repeats */ + else if (val != transparent_pen) + { + val |= color; + while (innercount--) + base[dstoffs-- & vram_mask] = val; + } + + /* run of transparent repeats */ + else + dstoffs -= innercount; + } + + /* right clip */ + SKIP_RLE(rclip, xleft, count, innercount, src); + } +} + + + +/************************************* + * + * Slow compressed blitter functions + * + *************************************/ + +INLINE void draw_rle_slow(UINT16 *base, UINT16 color) +{ + UINT8 *src = &grom_base[(grom_bank | ((VIDEO_TRANSFER_ADDRHI & 0xff) << 16) | VIDEO_TRANSFER_ADDRLO) % grom_size]; + int transparent_pen = (VIDEO_TRANSFER_FLAGS & XFERFLAG_TRANSPARENT) ? 0xff : -1; + int width = VIDEO_TRANSFER_WIDTH; + int height = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT); + int sx, sy = (VIDEO_TRANSFER_Y & 0xfff) << 8; + int xleft, y, count = 0, val = 0, innercount; + int xdststep = 0x100; + int ydststep = VIDEO_DST_YSTEP; + int startx = (VIDEO_TRANSFER_X & 0xfff) << 8; + + /* adjust for scaling */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_DSTXSCALE) + xdststep = VIDEO_DST_XSTEP; + + /* adjust for flipping */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_XFLIP) + xdststep = -xdststep; + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_YFLIP) + ydststep = -ydststep; + + /* loop over Y in src pixels */ + for (y = 0; y < height; y++, sy += ydststep) + { + UINT32 dstoffs; + + /* clip in the Y direction */ + if (sy < scaled_clip_rect.min_y || sy >= scaled_clip_rect.max_y) + { + SKIP_RLE(width, xleft, count, innercount, src); + continue; + } + + /* compute the address */ + sx = startx; + dstoffs = compute_safe_address(clip_rect.min_x, sy >> 8) - clip_rect.min_x; + + /* loop until gone */ + for (xleft = width; xleft > 0; ) + { + /* load next RLE chunk if needed */ + GET_NEXT_RUN(xleft, count, innercount, src); + + /* run of literals */ + if (val == -1) + for ( ; innercount--; sx += xdststep) + { + int pixel = *src++; + if (pixel != transparent_pen) + if (sx >= scaled_clip_rect.min_x && sx < scaled_clip_rect.max_x) + base[(dstoffs + (sx >> 8)) & vram_mask] = color | pixel; + } + + /* run of non-transparent repeats */ + else if (val != transparent_pen) + { + val |= color; + for ( ; innercount--; sx += xdststep) + if (sx >= scaled_clip_rect.min_x && sx < scaled_clip_rect.max_x) + base[(dstoffs + (sx >> 8)) & vram_mask] = val; + } + + /* run of transparent repeats */ + else + sx += xdststep * innercount; + } + + /* apply skew */ + if (VIDEO_TRANSFER_FLAGS & XFERFLAG_DXDYSIGN) + startx += VIDEO_XSTEP_PER_Y; + else + startx -= VIDEO_XSTEP_PER_Y; + } +} + + + +static void draw_rle(UINT16 *base, UINT16 color) +{ + /* adjust for (lack of) clipping */ + if (!(VIDEO_TRANSFER_FLAGS & XFERFLAG_CLIP)) + disable_clipping(); + + /* if we have an X scale, draw it slow */ + if (((VIDEO_TRANSFER_FLAGS & XFERFLAG_DSTXSCALE) && VIDEO_DST_XSTEP != 0x100) || VIDEO_XSTEP_PER_Y) + draw_rle_slow(base, color); + + /* else draw it fast */ + else if (VIDEO_TRANSFER_FLAGS & XFERFLAG_XFLIP) + draw_rle_fast_xflip(base, color); + else + draw_rle_fast(base, color); + + /* restore cliprects */ + if (!(VIDEO_TRANSFER_FLAGS & XFERFLAG_CLIP)) + enable_clipping(); +} + + + +/************************************* + * + * Shift register manipulation + * + *************************************/ + +static void shiftreg_clear(UINT16 *base, UINT16 *zbase) +{ + int ydir = (VIDEO_TRANSFER_FLAGS & XFERFLAG_YFLIP) ? -1 : 1; + int height = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT); + int sx = VIDEO_TRANSFER_X & 0xfff; + int sy = VIDEO_TRANSFER_Y & 0xfff; + UINT16 *src; + int y; + + /* first line is the source */ + src = &base[compute_safe_address(sx, sy)]; + sy += ydir; + + /* loop over height */ + for (y = 1; y < height; y++) + { + memcpy(&base[compute_safe_address(sx, sy)], src, 512*2); + if (zbase) + { + UINT16 zval = ((drivedge_zbuf_control[2] >> 8) & 0x7ff) | ((drivedge_zbuf_control[2] & 0x1f) << 11); + UINT16 *dst = &zbase[compute_safe_address(sx, sy)]; + int x; + for (x = 0; x < 512; x++) + *dst++ = zval; + } + sy += ydir; + } +} + + + +/************************************* + * + * Video commands + * + *************************************/ + +static void handle_video_command(void) +{ + /* only 6 known commands */ + switch (VIDEO_COMMAND) + { + /* command 1: blit raw data */ + case 1: + profiler_mark(PROFILER_USER1); + if (BLIT_LOGGING) logblit("Blit Raw"); + + if (is_drivedge) + { + if (enable_latch[0]) draw_raw_drivedge(videoplane[0], videoplane[1], color_latch[0]); + } + else + { + if (enable_latch[0]) draw_raw(videoplane[0], color_latch[0]); + if (enable_latch[1]) draw_raw(videoplane[1], color_latch[1]); + } + + profiler_mark(PROFILER_END); + break; + + /* command 2: blit RLE-compressed data */ + case 2: + profiler_mark(PROFILER_USER2); + if (BLIT_LOGGING) logblit("Blit RLE"); + + if (enable_latch[0]) draw_rle(videoplane[0], color_latch[0]); + if (enable_latch[1]) draw_rle(videoplane[1], color_latch[1]); + + profiler_mark(PROFILER_END); + break; + + /* command 3: set up raw data transfer */ + case 3: + if (BLIT_LOGGING) logblit("Raw Xfer"); + xfer_xcount = VIDEO_TRANSFER_WIDTH; + xfer_ycount = ADJUSTED_HEIGHT(VIDEO_TRANSFER_HEIGHT); + xfer_xcur = VIDEO_TRANSFER_X & 0xfff; + xfer_ycur = VIDEO_TRANSFER_Y & 0xfff; + break; + + /* command 4: flush? */ + case 4: + break; + + /* command 5: reset? */ + case 5: + break; + + /* command 6: perform shift register copy */ + case 6: + profiler_mark(PROFILER_USER3); + if (BLIT_LOGGING) logblit("ShiftReg"); + + if (is_drivedge) + { + if (enable_latch[0]) shiftreg_clear(videoplane[0], videoplane[1]); + } + else + { + if (enable_latch[0]) shiftreg_clear(videoplane[0], NULL); + if (enable_latch[1]) shiftreg_clear(videoplane[1], NULL); + } + + profiler_mark(PROFILER_END); + break; + + default: + if (BLIT_LOGGING) logerror("Unknown blit command %d\n", VIDEO_COMMAND); + break; + } + + /* tell the processor we're done */ + VIDEO_INTSTATE |= VIDEOINT_BLITTER; + update_interrupts(1); +} + + + +/************************************* + * + * Video I/O + * + *************************************/ + +WRITE16_HANDLER( itech32_video_w ) +{ + rectangle visarea; + + int old = itech32_video[offset]; + COMBINE_DATA(&itech32_video[offset]); + + switch (offset) + { + case 0x02/2: /* VIDEO_INTACK */ + VIDEO_INTSTATE = old & ~data; + update_interrupts(1); + break; + + case 0x04/2: /* VIDEO_TRANSFER */ + if (VIDEO_COMMAND == 3 && xfer_ycount) + { + offs_t addr = compute_safe_address(xfer_xcur, xfer_ycur); + if (enable_latch[0]) + { + VIDEO_TRANSFER = videoplane[0][addr]; + videoplane[0][addr] = (data & 0xff) | color_latch[0]; + } + if (enable_latch[1]) + { + VIDEO_TRANSFER = videoplane[1][addr]; + videoplane[1][addr] = (data & 0xff) | color_latch[1]; + } + if (--xfer_xcount) + xfer_xcur++; + else if (--xfer_ycount) + xfer_xcur = VIDEO_TRANSFER_X, xfer_xcount = VIDEO_TRANSFER_WIDTH, xfer_ycur++; + } + break; + + case 0x08/2: /* VIDEO_COMMAND */ + handle_video_command(); + break; + + case 0x0a/2: /* VIDEO_INTENABLE */ + update_interrupts(1); + break; + + case 0x24/2: /* VIDEO_LEFTCLIP */ + clip_rect.min_x = VIDEO_LEFTCLIP; + scaled_clip_rect.min_x = VIDEO_LEFTCLIP << 8; + break; + + case 0x26/2: /* VIDEO_RIGHTCLIP */ + clip_rect.max_x = VIDEO_RIGHTCLIP; + scaled_clip_rect.max_x = VIDEO_RIGHTCLIP << 8; + break; + + case 0x28/2: /* VIDEO_TOPCLIP */ + clip_rect.min_y = VIDEO_TOPCLIP; + scaled_clip_rect.min_y = VIDEO_TOPCLIP << 8; + break; + + case 0x2a/2: /* VIDEO_BOTTOMCLIP */ + clip_rect.max_y = VIDEO_BOTTOMCLIP; + scaled_clip_rect.max_y = VIDEO_BOTTOMCLIP << 8; + break; + + case 0x2c/2: /* VIDEO_INTSCANLINE */ + timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, VIDEO_INTSCANLINE, 0), 0, attotime_zero); + break; + + case 0x32/2: /* VIDEO_VTOTAL */ + case 0x36/2: /* VIDEO_VBLANK_START */ + case 0x38/2: /* VIDEO_VBLANK_END */ + case 0x3a/2: /* VIDEO_HTOTAL */ + case 0x3e/2: /* VIDEO_HBLANK_START */ + case 0x40/2: /* VIDEO_HBLANK_END */ + /* do some sanity checks first */ + if ((VIDEO_HTOTAL > 0) && (VIDEO_VTOTAL > 0) && + (VIDEO_VBLANK_START != VIDEO_VBLANK_END) && + (VIDEO_HBLANK_START != VIDEO_HBLANK_END) && + (VIDEO_HBLANK_START < VIDEO_HTOTAL) && + (VIDEO_HBLANK_END < VIDEO_HTOTAL) && + (VIDEO_VBLANK_START < VIDEO_VTOTAL) && + (VIDEO_VBLANK_END < VIDEO_VTOTAL)) + { + visarea.min_x = visarea.min_y = 0; + + if (VIDEO_HBLANK_START > VIDEO_HBLANK_END) + visarea.max_x = VIDEO_HBLANK_START - VIDEO_HBLANK_END - 1; + else + visarea.max_x = VIDEO_HTOTAL - VIDEO_HBLANK_END + VIDEO_HBLANK_START - 1; + + if (VIDEO_VBLANK_START > VIDEO_VBLANK_END) + visarea.max_y = VIDEO_VBLANK_START - VIDEO_VBLANK_END - 1; + else + visarea.max_y = VIDEO_VTOTAL - VIDEO_VBLANK_END + VIDEO_VBLANK_START - 1; + + logerror("Configure Screen: HTOTAL: %x HBSTART: %x HBEND: %x VTOTAL: %x VBSTART: %x VBEND: %x\n", + VIDEO_HTOTAL, VIDEO_HBLANK_START, VIDEO_HBLANK_END, VIDEO_VTOTAL, VIDEO_VBLANK_START, VIDEO_VBLANK_END); + video_screen_configure(0, VIDEO_HTOTAL, VIDEO_VTOTAL, &visarea, Machine->screen[0].refresh); + } + break; + } +} + + +READ16_HANDLER( itech32_video_r ) +{ + if (offset == 0) + { + return (itech32_video[offset] & ~0x08) | 0x04 | 0x01; + } + else if (offset == 3) + { + return 0xef;/*video_screen_get_vpos(0) - 1;*/ + } + + return itech32_video[offset]; +} + + + +/************************************* + * + * Alternate video I/O + * + *************************************/ + +WRITE16_HANDLER( bloodstm_video_w ) +{ + itech32_video_w(offset / 2, data, mem_mask); +} + + +READ16_HANDLER( bloodstm_video_r ) +{ + return itech32_video_r(offset / 2,0); +} + + +WRITE32_HANDLER( itech020_video_w ) +{ + if (ACCESSING_MSW32) + itech32_video_w(offset, data >> 16, mem_mask >> 16); + else + itech32_video_w(offset, data, mem_mask); +} + + +WRITE32_HANDLER( drivedge_zbuf_control_w ) +{ + COMBINE_DATA(&drivedge_zbuf_control[offset]); + is_drivedge = 1; +} + + +READ32_HANDLER( itech020_video_r ) +{ + int result = itech32_video_r(offset,0); + return (result << 16) | result; +} + + + +/************************************* + * + * Main refresh + * + *************************************/ + +VIDEO_UPDATE( itech32 ) +{ + int y; + + /* loop over height */ + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + { + UINT16 *src1 = &videoplane[0][compute_safe_address(VIDEO_DISPLAY_XORIGIN1, VIDEO_DISPLAY_YORIGIN1 + y)]; + + /* handle multi-plane case */ + if (itech32_planes > 1) + { + UINT16 *src2 = &videoplane[1][compute_safe_address(VIDEO_DISPLAY_XORIGIN2 + VIDEO_DISPLAY_XSCROLL2, VIDEO_DISPLAY_YORIGIN2 + VIDEO_DISPLAY_YSCROLL2 + y)]; + UINT16 scanline[384]; + int x; + + /* blend the pixels in the scanline; color xxFF is transparent */ + for (x = cliprect->min_x; x <= cliprect->max_x; x++) + { + UINT16 pixel = src1[x]; + if ((pixel & 0xff) == 0xff) + pixel = src2[x]; + scanline[x] = pixel; + } + + /* draw from the buffer */ + draw_scanline16(bitmap, cliprect->min_x, y, cliprect->max_x - cliprect->min_x + 1, &scanline[cliprect->min_x], machine->pens, -1); + } + + /* otherwise, draw directly from VRAM */ + else + draw_scanline16(bitmap, cliprect->min_x, y, cliprect->max_x - cliprect->min_x + 1, &src1[cliprect->min_x], machine->pens, -1); + } + return 0; +} |