From 0863066da55f49fc5363dd5d6939ceee2dd63f79 Mon Sep 17 00:00:00 2001 From: Robbbert Date: Wed, 1 Dec 2021 22:36:51 +1100 Subject: stv: moved video into video/saturn.cpp to remove possible circular dependency. (#8915) --- scripts/src/video.lua | 15 - scripts/target/mame/arcade.lua | 2 +- scripts/target/mame/mess.lua | 2 +- src/devices/video/stvvdp1.cpp | 2206 ---------- src/devices/video/stvvdp1.h | 2 - src/devices/video/stvvdp2.cpp | 7156 ------------------------------ src/devices/video/stvvdp2.h | 2 - src/mame/video/saturn.cpp | 9365 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 9367 insertions(+), 9383 deletions(-) delete mode 100644 src/devices/video/stvvdp1.cpp delete mode 100644 src/devices/video/stvvdp1.h delete mode 100644 src/devices/video/stvvdp2.cpp delete mode 100644 src/devices/video/stvvdp2.h create mode 100644 src/mame/video/saturn.cpp diff --git a/scripts/src/video.lua b/scripts/src/video.lua index b61b5ffb0f7..12f4f55b2a8 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -952,21 +952,6 @@ if (VIDEOS["SNES_PPU"]~=null) then } end --------------------------------------------------- --- ---@src/devices/video/stvvdp1.h,VIDEOS["STVVDP"] = true ---@src/devices/video/stvvdp2.h,VIDEOS["STVVDP"] = true --------------------------------------------------- - -if (VIDEOS["STVVDP"]~=null) then - files { - MAME_DIR .. "src/devices/video/stvvdp1.cpp", - MAME_DIR .. "src/devices/video/stvvdp1.h", - MAME_DIR .. "src/devices/video/stvvdp2.cpp", - MAME_DIR .. "src/devices/video/stvvdp2.h", - } -end - -------------------------------------------------- -- --@src/devices/video/t6963c.h,VIDEOS["T6963C"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index d92e9fd22bf..28bd9aca6b9 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -377,7 +377,6 @@ VIDEOS["PWM_DISPLAY"] = true --VIDEOS["SED1500"] = true --VIDEOS["SED1520"] = true VIDEOS["SNES_PPU"] = true -VIDEOS["STVVDP"] = true --VIDEOS["T6963C"] = true --VIDEOS["T6A04"] = true VIDEOS["TLC34076"] = true @@ -3633,6 +3632,7 @@ files { MAME_DIR .. "src/mame/includes/saturn.h", MAME_DIR .. "src/mame/drivers/saturn.cpp", MAME_DIR .. "src/mame/machine/saturn.cpp", + MAME_DIR .. "src/mame/video/saturn.cpp", MAME_DIR .. "src/mame/machine/saturn_cdb.cpp", MAME_DIR .. "src/mame/machine/saturn_cdb.h", MAME_DIR .. "src/mame/includes/stv.h", diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 45b82a5353e..7aac8e84c98 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -410,7 +410,6 @@ VIDEOS["SED1356"] = true VIDEOS["SED1500"] = true VIDEOS["SED1520"] = true VIDEOS["SNES_PPU"] = true -VIDEOS["STVVDP"] = true VIDEOS["T6963C"] = true VIDEOS["T6A04"] = true VIDEOS["TEA1002"] = true @@ -1626,6 +1625,7 @@ files { MAME_DIR .. "src/mame/includes/saturn.h", MAME_DIR .. "src/mame/drivers/saturn.cpp", MAME_DIR .. "src/mame/machine/saturn.cpp", + MAME_DIR .. "src/mame/drivers/saturn.cpp", MAME_DIR .. "src/mame/machine/saturn_cdb.cpp", MAME_DIR .. "src/mame/machine/saturn_cdb.h", } diff --git a/src/devices/video/stvvdp1.cpp b/src/devices/video/stvvdp1.cpp deleted file mode 100644 index d26b65309be..00000000000 --- a/src/devices/video/stvvdp1.cpp +++ /dev/null @@ -1,2206 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:David Haywood, Angelo Salese, Olivier Galibert, Mariusz Wojcieszek, R. Belmont -/* - -STV - VDP1 - -the vdp1 draws to the FRAMEBUFFER which is mapped in memory - --------------------------- WARNING WARNING WARNING -------------------------- -This is a legacy core, all game based notes are for a future device rewrite. -Please don't remove them if for no reason you truly want to mess with this. --------------------------- WARNING WARNING WARNING -------------------------- - -Framebuffer todo: -- finish manual erase -- add proper framebuffer erase -- 8 bpp support - now we always draw as 16 bpp, but this is not a problem since - VDP2 interprets framebuffer as 8 bpp in these cases - -*/ - - -#include "emu.h" -#include "includes/saturn.h" // FIXME: this is a dependency from devices on MAME - - -#define VDP1_LOG 0 - - -enum { FRAC_SHIFT = 16 }; - -struct spoint { - int32_t x, y; - int32_t u, v; -}; - -struct shaded_point -{ - int32_t x,y; - int32_t r,g,b; -}; - -#define RGB_R(_color) (_color & 0x1f) -#define RGB_G(_color) ((_color >> 5) & 0x1f) -#define RGB_B(_color) ((_color >> 10) & 0x1f) - -#define SWAP_INT32(_a,_b) \ - { \ - int32_t t; \ - t = _a; \ - _a = _b; \ - _b = t; \ - } - -#define SWAP_INT32PTR(_p1, _p2) \ - { \ - int32_t *p; \ - p = _p1; \ - _p1 = _p2; \ - _p2 = p; \ - } - -/*TV Mode Selection Register */ -/* - xxxx xxxx xxxx ---- | UNUSED - ---- ---- ---- x--- | VBlank Erase/Write (VBE) - ---- ---- ---- -xxx | TV Mode (TVM) - TV-Mode: - This sets the Frame Buffer size,the rotation of the Frame Buffer & the bit width. - bit 2 HDTV disable(0)/enable(1) - bit 1 non-rotation/rotation(1) - bit 0 16(0)/8(1) bits per pixel - Size of the Frame Buffer: - 7 invalid - 6 invalid - 5 invalid - 4 512x256 - 3 512x512 - 2 512x256 - 1 1024x256 - 0 512x256 -*/ - -/*Frame Buffer Change Mode Register*/ -/* - xxxx xxxx xxx- ---- | UNUSED - ---- ---- ---x ---- | Even/Odd Coordinate Select Bit (EOS) - ---- ---- ---- x--- | Double Interlace Mode (DIE) - ---- ---- ---- -x-- | Double Interlace Draw Line (DIL) - ---- ---- ---- --x- | Frame Buffer Change Trigger (FCM) - ---- ---- ---- ---x | Frame Buffer Change Mode (FCT) -*/ -#define STV_VDP1_FBCR ((m_vdp1_regs[0x002/2] >> 0)&0xffff) -#define STV_VDP1_EOS ((STV_VDP1_FBCR & 0x0010) >> 4) -#define STV_VDP1_DIE ((STV_VDP1_FBCR & 0x0008) >> 3) -#define STV_VDP1_DIL ((STV_VDP1_FBCR & 0x0004) >> 2) -#define STV_VDP1_FCM ((STV_VDP1_FBCR & 0x0002) >> 1) -#define STV_VDP1_FCT ((STV_VDP1_FBCR & 0x0001) >> 0) - -/*Plot Trigger Register*/ -/* - xxxx xxxx xxxx xx-- | UNUSED - ---- ---- ---- --xx | Plot Trigger Mode (PTM) - - Plot Trigger Mode: - 3 Invalid - 2 Automatic draw - 1 VDP1 draw by request - 0 VDP1 Idle (no access) -*/ -#define STV_VDP1_PTMR ((m_vdp1_regs[0x004/2])&0xffff) -#define STV_VDP1_PTM ((STV_VDP1_PTMR & 0x0003) >> 0) -#define PTM_0 m_vdp1_regs[0x004/2]&=~0x0001 - -/* - Erase/Write Data Register - 16 bpp = data - 8 bpp = erase/write data for even/odd X coordinates -*/ -#define STV_VDP1_EWDR ((m_vdp1_regs[0x006/2])&0xffff) - -/*Erase/Write Upper-Left register*/ -/* - x--- ---- ---- ---- | UNUSED - -xxx xxx- ---- ---- | X1 register - ---- ---x xxxx xxxx | Y1 register - -*/ -#define STV_VDP1_EWLR ((m_vdp1_regs[0x008/2])&0xffff) -#define STV_VDP1_EWLR_X1 ((STV_VDP1_EWLR & 0x7e00) >> 9) -#define STV_VDP1_EWLR_Y1 ((STV_VDP1_EWLR & 0x01ff) >> 0) -/*Erase/Write Lower-Right register*/ -/* - xxxx xxx- ---- ---- | X3 register - ---- ---x xxxx xxxx | Y3 register - -*/ -#define STV_VDP1_EWRR ((m_vdp1_regs[0x00a/2])&0xffff) -#define STV_VDP1_EWRR_X3 ((STV_VDP1_EWRR & 0xfe00) >> 9) -#define STV_VDP1_EWRR_Y3 ((STV_VDP1_EWRR & 0x01ff) >> 0) -/*Transfer End Status Register*/ -/* - xxxx xxxx xxxx xx-- | UNUSED - ---- ---- ---- --x- | CEF - ---- ---- ---- ---x | BEF - -*/ -#define STV_VDP1_EDSR ((m_vdp1_regs[0x010/2])&0xffff) -#define STV_VDP1_CEF (STV_VDP1_EDSR & 2) -#define STV_VDP1_BEF (STV_VDP1_EDSR & 1) -/**/ - - - -uint16_t saturn_state::saturn_vdp1_regs_r(offs_t offset) -{ - //logerror ("%s VDP1: Read from Registers, Offset %04x\n", machine().describe_context(), offset); - - switch(offset) - { - case 0x02/2: - return 0; - case 0x10/2: - break; - case 0x12/2: return m_vdp1.lopr; - case 0x14/2: return m_vdp1.copr; - /* MODR register, read register for the other VDP1 regs - (Shienryu SS version abuses of this during intro) */ - case 0x16/2: - uint16_t modr; - - modr = 0x1000; //vdp1 VER - modr |= (STV_VDP1_PTM >> 1) << 8; // PTM1 - modr |= STV_VDP1_EOS << 7; // EOS - modr |= STV_VDP1_DIE << 6; // DIE - modr |= STV_VDP1_DIL << 5; // DIL - modr |= STV_VDP1_FCM << 4; //FCM - modr |= STV_VDP1_VBE << 3; //VBE - modr |= STV_VDP1_TVM & 7; //TVM - - return modr; - default: - if(!machine().side_effects_disabled()) - logerror("%s VDP1: Read from Registers, Offset %04x\n", machine().describe_context(), offset*2); - break; - } - - return m_vdp1_regs[offset]; //TODO: write-only regs should return open bus or zero -} - -/* TODO: TVM & 1 is just a kludgy work-around, the VDP1 actually needs to be rewritten from scratch. */ -/* Daisenryaku Strong Style (daisenss) uses it */ -void saturn_state::stv_clear_framebuffer( int which_framebuffer ) -{ - int start_x, end_x, start_y, end_y; - - start_x = STV_VDP1_EWLR_X1 * ((STV_VDP1_TVM & 1) ? 16 : 8); - start_y = STV_VDP1_EWLR_Y1 * (m_vdp1.framebuffer_double_interlace+1); - end_x = STV_VDP1_EWRR_X3 * ((STV_VDP1_TVM & 1) ? 16 : 8); - end_y = (STV_VDP1_EWRR_Y3+1) * (m_vdp1.framebuffer_double_interlace+1); -// popmessage("%d %d %d %d %d",STV_VDP1_EWLR_X1,STV_VDP1_EWLR_Y1,STV_VDP1_EWRR_X3,STV_VDP1_EWRR_Y3,m_vdp1.framebuffer_double_interlace); - - if(STV_VDP1_TVM & 1) - { - for(int y=start_y;y 0xdf) && ((offset * 4) < 0x140)) -// { -// logerror("%s: VRAM dword write to %08X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask); -// } - - data = m_vdp1_vram[offset]; - /* put in gfx region for easy decoding */ - vdp1[offset*4+0] = (data & 0xff000000) >> 24; - vdp1[offset*4+1] = (data & 0x00ff0000) >> 16; - vdp1[offset*4+2] = (data & 0x0000ff00) >> 8; - vdp1[offset*4+3] = (data & 0x000000ff) >> 0; -} - -void saturn_state::saturn_vdp1_framebuffer0_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - //popmessage ("STV VDP1 Framebuffer 0 WRITE offset %08x data %08x",offset, data); - if ( STV_VDP1_TVM & 1 ) - { - /* 8-bit mode */ - //printf("VDP1 8-bit mode %08x %02x\n",offset,data); - if ( ACCESSING_BITS_24_31 ) - { - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0x00ff; - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0xff00; - } - if ( ACCESSING_BITS_16_23 ) - { - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0xff00; - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0x00ff; - } - if ( ACCESSING_BITS_8_15 ) - { - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0x00ff; - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0xff00; - } - if ( ACCESSING_BITS_0_7 ) - { - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0xff00; - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0x00ff; - } - } - else - { - /* 16-bit mode */ - if ( ACCESSING_BITS_16_31 ) - { - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] = (data >> 16) & 0xffff; - } - if ( ACCESSING_BITS_0_15 ) - { - m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] = data & 0xffff; - } - } -} - -uint32_t saturn_state::saturn_vdp1_framebuffer0_r(offs_t offset, uint32_t mem_mask) -{ - uint32_t result = 0; - //popmessage ("STV VDP1 Framebuffer 0 READ offset %08x",offset); - if ( STV_VDP1_TVM & 1 ) - { - /* 8-bit mode */ - //printf("VDP1 8-bit mode %08x\n",offset); - if ( ACCESSING_BITS_24_31 ) - result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0xff00) << 16); - if ( ACCESSING_BITS_16_23 ) - result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0x00ff) << 16); - if ( ACCESSING_BITS_8_15 ) - result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0xff00)); - if ( ACCESSING_BITS_0_7 ) - result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0x00ff)); - } - else - { - /* 16-bit mode */ - if ( ACCESSING_BITS_16_31 ) - { - result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] << 16); - } - if ( ACCESSING_BITS_0_15 ) - { - result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1]); - } - - } - - return result; -} - - -/* - -there is a command every 0x20 bytes -the first word is the control word -the rest are data used by it - ---- -00 CMDCTRL - e--- ---- ---- ---- | end bit (15) - -jjj ---- ---- ---- | jump select bits (12-14) - ---- zzzz ---- ---- | zoom point / hotspot (8-11) - ---- ---- 00-- ---- | UNUSED - ---- ---- --dd ---- | character read direction (4,5) - ---- ---- ---- cccc | command bits (0-3) - -02 CMDLINK - llll llll llll ll-- | link - ---- ---- ---- --00 | UNUSED - -04 CMDPMOD - m--- ---- ---- ---- | MON (looks at MSB and apply shadows etc.) - -00- ---- ---- ---- | UNUSED - ---h ---- ---- ---- | HSS (High Speed Shrink) - ---- p--- ---- ---- | PCLIP (Pre Clipping Disable) - ---- -c-- ---- ---- | CLIP (Clipping Mode Bit) - ---- --m- ---- ---- | CMOD (User Clipping Enable Bit) - ---- ---M ---- ---- | MESH (Mesh Enable Bit) - ---- ---- e--- ---- | ECD (End Code Disable) - ---- ---- -S-- ---- | SPD (Transparent Pixel Disable) - ---- ---- --cc c--- | Colour Mode - ---- ---- ---- -CCC | Colour Calculation bits - ---- ---- ---- -1-- | Gouraud shading enable - ---- ---- ---- --1- | 1/2 original GFX enable - ---- ---- ---- ---1 | 1/2 background enable - -06 CMDCOLR - mmmm mmmm mmmm mmmm | Colour Bank, Colour Lookup /8 - -08 CMDSRCA (Character Address) - aaaa aaaa aaaa aa-- | Character Address - ---- ---- ---- --00 | UNUSED - -0a CMDSIZE (Character Size) - 00-- ---- ---- ---- | UNUSED - --xx xxxx ---- ---- | Character Size (X) - ---- ---- yyyy yyyy | Character Size (Y) - -0c CMDXA (used for normal sprite) - eeee ee-- ---- ---- | extension bits - ---- --xx xxxx xxxx | x position - -0e CMDYA (used for normal sprite) - eeee ee-- ---- ---- | extension bits - ---- --yy yyyy yyyy | y position - -10 CMDXB -12 CMDYB -14 CMDXC -16 CMDYC -18 CMDXD -1a CMDYD -1c CMDGRDA (Gouraud Shading Table) -1e UNUSED ---- - - -*/ - -void saturn_state::stv_clear_gouraud_shading(void) -{ - memset( &stv_gouraud_shading, 0, sizeof( stv_gouraud_shading ) ); -} - -uint8_t saturn_state::stv_read_gouraud_table( void ) -{ - int gaddr; - - if ( stv2_current_sprite.CMDPMOD & 0x4 ) - { - gaddr = stv2_current_sprite.CMDGRDA * 8; - stv_gouraud_shading.GA = (m_vdp1_vram[gaddr/4] >> 16) & 0xffff; - stv_gouraud_shading.GB = (m_vdp1_vram[gaddr/4] >> 0) & 0xffff; - stv_gouraud_shading.GC = (m_vdp1_vram[gaddr/4 + 1] >> 16) & 0xffff; - stv_gouraud_shading.GD = (m_vdp1_vram[gaddr/4 + 1] >> 0) & 0xffff; - return 1; - } - else - { - return 0; - } -} - -static inline int32_t _shading( int32_t color, int32_t correction ) -{ - correction = (correction >> 16) & 0x1f; - color += (correction - 16); - - if ( color < 0 ) color = 0; - if ( color > 0x1f ) color = 0x1f; - - return color; -} - -uint16_t saturn_state::stv_vdp1_apply_gouraud_shading( int x, int y, uint16_t pix ) -{ - int32_t r,g,b, msb; - - msb = pix & 0x8000; - -#ifdef MAME_DEBUG - if ( (stv_vdp1_shading_data->scanline[y].x[0] >> 16) != x ) - { - logerror( "ERROR in computing x coordinates (line %d, x = %x, %d, xc = %x, %d)\n", y, x, x, stv_vdp1_shading_data->scanline[y].x[0], stv_vdp1_shading_data->scanline[y].x[0] >> 16 ); - }; -#endif - - b = RGB_B(pix); - g = RGB_G(pix); - r = RGB_R(pix); - - b = _shading( b, stv_vdp1_shading_data->scanline[y].b[0] ); - g = _shading( g, stv_vdp1_shading_data->scanline[y].g[0] ); - r = _shading( r, stv_vdp1_shading_data->scanline[y].r[0] ); - - stv_vdp1_shading_data->scanline[y].b[0] += stv_vdp1_shading_data->scanline[y].db; - stv_vdp1_shading_data->scanline[y].g[0] += stv_vdp1_shading_data->scanline[y].dg; - stv_vdp1_shading_data->scanline[y].r[0] += stv_vdp1_shading_data->scanline[y].dr; - - stv_vdp1_shading_data->scanline[y].x[0] += 1 << FRAC_SHIFT; - - return msb | b << 10 | g << 5 | r; -} - -void saturn_state::stv_vdp1_setup_shading_for_line(int32_t y, int32_t x1, int32_t x2, - int32_t r1, int32_t g1, int32_t b1, - int32_t r2, int32_t g2, int32_t b2) -{ - int xx1 = x1>>FRAC_SHIFT; - int xx2 = x2>>FRAC_SHIFT; - - - if ( xx1 > xx2 ) - { - SWAP_INT32(xx1, xx2); - SWAP_INT32(r1, r2); - SWAP_INT32(g1, g2); - SWAP_INT32(b1, b2); - } - - if ( (y >= 0) && (y < 512) ) - { - int32_t dx; - int32_t gbd, ggd, grd; - - dx = xx2 - xx1; - - if ( dx == 0 ) - { - gbd = ggd = grd = 0; - } - else - { - gbd = abs(b2 - b1) / dx; - if (b2 < b1) gbd = -gbd; - ggd = abs(g2 - g1) / dx; - if (g2 < g1) ggd = -ggd; - grd = abs(r2 - r1) / dx; - if (r2 < r1) grd = -grd; - } - - stv_vdp1_shading_data->scanline[y].x[0] = x1; - stv_vdp1_shading_data->scanline[y].x[1] = x2; - - stv_vdp1_shading_data->scanline[y].b[0] = b1; - stv_vdp1_shading_data->scanline[y].g[0] = g1; - stv_vdp1_shading_data->scanline[y].r[0] = r1; - stv_vdp1_shading_data->scanline[y].b[1] = b2; - stv_vdp1_shading_data->scanline[y].g[1] = g2; - stv_vdp1_shading_data->scanline[y].r[1] = r2; - - stv_vdp1_shading_data->scanline[y].db = gbd; - stv_vdp1_shading_data->scanline[y].dg = ggd; - stv_vdp1_shading_data->scanline[y].dr = grd; - - } -} - -void saturn_state::stv_vdp1_setup_shading_for_slope( - int32_t x1, int32_t x2, int32_t sl1, int32_t sl2, int32_t *nx1, int32_t *nx2, - int32_t r1, int32_t r2, int32_t slr1, int32_t slr2, int32_t *nr1, int32_t *nr2, - int32_t g1, int32_t g2, int32_t slg1, int32_t slg2, int32_t *ng1, int32_t *ng2, - int32_t b1, int32_t b2, int32_t slb1, int32_t slb2, int32_t *nb1, int32_t *nb2, - int32_t _y1, int32_t y2) -{ - if(x1 > x2 || (x1==x2 && sl1 > sl2)) { - SWAP_INT32(x1,x2); - SWAP_INT32(sl1,sl2); - SWAP_INT32PTR(nx1, nx2); - SWAP_INT32(r1,r2); - SWAP_INT32(slr1, slr2); - SWAP_INT32PTR(nr1, nr2); - SWAP_INT32(g1, g2); - SWAP_INT32(slg1, slg2); - SWAP_INT32PTR(ng1, ng2); - SWAP_INT32(b1, b2); - SWAP_INT32(slb1, slb2); - SWAP_INT32PTR(nb1, nb2); - } - - while(_y1 < y2) - { - stv_vdp1_setup_shading_for_line(_y1, x1, x2, r1, g1, b1, r2, g2, b2); - x1 += sl1; - r1 += slr1; - g1 += slg1; - b1 += slb1; - - x2 += sl2; - r2 += slr2; - g2 += slg2; - b2 += slb2; - _y1++; - } - *nx1 = x1; - *nr1 = r1; - *ng1 = g1; - *nb1 = b1; - - *nx2 = x2; - *nr2 = r2; - *nb2 = b2; - *ng2 = g2; -} - -void saturn_state::stv_vdp1_setup_shading(const struct spoint* q, const rectangle &cliprect) -{ - int32_t x1, x2, delta, cury, limy; - int32_t r1, g1, b1, r2, g2, b2; - int32_t sl1, slg1, slb1, slr1; - int32_t sl2, slg2, slb2, slr2; - int pmin, pmax, i, ps1, ps2; - struct shaded_point p[8]; - uint16_t gd[4]; - - if ( stv_read_gouraud_table() == 0 ) return; - - gd[0] = stv_gouraud_shading.GA; - gd[1] = stv_gouraud_shading.GB; - gd[2] = stv_gouraud_shading.GC; - gd[3] = stv_gouraud_shading.GD; - - for(i=0; i<4; i++) { - p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT; - p[i].y = p[i+4].y = q[i].y; - p[i].r = p[i+4].r = RGB_R(gd[i]) << FRAC_SHIFT; - p[i].g = p[i+4].g = RGB_G(gd[i]) << FRAC_SHIFT; - p[i].b = p[i+4].b = RGB_B(gd[i]) << FRAC_SHIFT; - } - - pmin = pmax = 0; - for(i=1; i<4; i++) { - if(p[i].y < p[pmin].y) - pmin = i; - if(p[i].y > p[pmax].y) - pmax = i; - } - - cury = p[pmin].y; - limy = p[pmax].y; - - stv_vdp1_shading_data->sy = cury; - stv_vdp1_shading_data->ey = limy; - - if(cury == limy) { - x1 = x2 = p[0].x; - ps1 = ps2 = 0; - for(i=1; i<4; i++) { - if(p[i].x < x1) { - x1 = p[i].x; - ps1 = i; - } - if(p[i].x > x2) { - x2 = p[i].x; - ps2 = i; - } - } - stv_vdp1_setup_shading_for_line(cury, x1, x2, p[ps1].r, p[ps1].g, p[ps1].b, p[ps2].r, p[ps2].g, p[ps2].b); - goto finish; - } - - ps1 = pmin+4; - ps2 = pmin; - - goto startup; - - for(;;) { - if(p[ps1-1].y == p[ps2+1].y) { - stv_vdp1_setup_shading_for_slope( - x1, x2, sl1, sl2, &x1, &x2, - r1, r2, slr1, slr2, &r1, &r2, - g1, g2, slg1, slg2, &g1, &g2, - b1, b2, slb1, slb2, &b1, &b2, - cury, p[ps1-1].y); - cury = p[ps1-1].y; - if(cury >= limy) - break; - ps1--; - ps2++; - - startup: - while(p[ps1-1].y == cury) - ps1--; - while(p[ps2+1].y == cury) - ps2++; - x1 = p[ps1].x; - r1 = p[ps1].r; - g1 = p[ps1].g; - b1 = p[ps1].b; - x2 = p[ps2].x; - r2 = p[ps2].r; - g2 = p[ps2].g; - b2 = p[ps2].b; - - delta = cury-p[ps1-1].y; - sl1 = (x1-p[ps1-1].x)/delta; - slr1 = (r1-p[ps1-1].r)/delta; - slg1 = (g1-p[ps1-1].g)/delta; - slb1 = (b1-p[ps1-1].b)/delta; - - delta = cury-p[ps2+1].y; - sl2 = (x2-p[ps2+1].x)/delta; - slr2 = (r2-p[ps2+1].r)/delta; - slg2 = (g2-p[ps2+1].g)/delta; - slb2 = (b2-p[ps2+1].b)/delta; - } else if(p[ps1-1].y < p[ps2+1].y) { - stv_vdp1_setup_shading_for_slope( - x1, x2, sl1, sl2, &x1, &x2, - r1, r2, slr1, slr2, &r1, &r2, - g1, g2, slg1, slg2, &g1, &g2, - b1, b2, slb1, slb2, &b1, &b2, - cury, p[ps1-1].y); - cury = p[ps1-1].y; - if(cury >= limy) - break; - ps1--; - while(p[ps1-1].y == cury) - ps1--; - x1 = p[ps1].x; - r1 = p[ps1].r; - g1 = p[ps1].g; - b1 = p[ps1].b; - - delta = cury-p[ps1-1].y; - sl1 = (x1-p[ps1-1].x)/delta; - slr1 = (r1-p[ps1-1].r)/delta; - slg1 = (g1-p[ps1-1].g)/delta; - slb1 = (b1-p[ps1-1].b)/delta; - } else { - stv_vdp1_setup_shading_for_slope( - x1, x2, sl1, sl2, &x1, &x2, - r1, r2, slr1, slr2, &r1, &r2, - g1, g2, slg1, slg2, &g1, &g2, - b1, b2, slb1, slb2, &b1, &b2, - cury, p[ps2+1].y); - cury = p[ps2+1].y; - if(cury >= limy) - break; - ps2++; - while(p[ps2+1].y == cury) - ps2++; - x2 = p[ps2].x; - r2 = p[ps2].r; - g2 = p[ps2].g; - b2 = p[ps2].b; - - delta = cury-p[ps2+1].y; - sl2 = (x2-p[ps2+1].x)/delta; - slr2 = (r2-p[ps2+1].r)/delta; - slg2 = (g2-p[ps2+1].g)/delta; - slb2 = (b2-p[ps2+1].b)/delta; - } - } - if(cury == limy) - stv_vdp1_setup_shading_for_line(cury, x1, x2, r1, g1, b1, r2, g2, b2 ); - -finish: - - if ( stv_vdp1_shading_data->sy < 0 ) stv_vdp1_shading_data->sy = 0; - if ( stv_vdp1_shading_data->sy >= 512 ) return; - if ( stv_vdp1_shading_data->ey < 0 ) return; - if ( stv_vdp1_shading_data->ey >= 512 ) stv_vdp1_shading_data->ey = 511; - - for ( cury = stv_vdp1_shading_data->sy; cury <= stv_vdp1_shading_data->ey; cury++ ) - { - while( (stv_vdp1_shading_data->scanline[cury].x[0] >> 16) < cliprect.min_x ) - { - stv_vdp1_shading_data->scanline[cury].x[0] += (1 << FRAC_SHIFT); - stv_vdp1_shading_data->scanline[cury].b[0] += stv_vdp1_shading_data->scanline[cury].db; - stv_vdp1_shading_data->scanline[cury].g[0] += stv_vdp1_shading_data->scanline[cury].dg; - stv_vdp1_shading_data->scanline[cury].r[0] += stv_vdp1_shading_data->scanline[cury].dr; - } - } - -} - -/* note that if we're drawing -to the framebuffer we CAN'T frameskip the vdp1 drawing as the hardware can READ the framebuffer -and if we skip the drawing the content could be incorrect when it reads it, although i have no idea -why they would want to */ - - - -void saturn_state::drawpixel_poly(int x, int y, int patterndata, int offsetcnt) -{ - /* Capcom Collection Dai 4 uses a dummy polygon to clear VDP1 framebuffer that goes over our current max size ... */ - if(x >= 1024 || y >= 512) - return; - - m_vdp1.framebuffer_draw_lines[y][x] = stv2_current_sprite.CMDCOLR; -} - -void saturn_state::drawpixel_8bpp_trans(int x, int y, int patterndata, int offsetcnt) -{ - uint16_t pix; - - pix = m_vdp1.gfx_decode[patterndata+offsetcnt] & 0xff; - if ( pix != 0 ) - { - m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank; - } -} - -void saturn_state::drawpixel_4bpp_notrans(int x, int y, int patterndata, int offsetcnt) -{ - uint16_t pix; - - pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2]; - pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4); - m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank; -} - -void saturn_state::drawpixel_4bpp_trans(int x, int y, int patterndata, int offsetcnt) -{ - uint16_t pix; - - pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2]; - pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4); - if ( pix != 0 ) - m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank; -} - -void saturn_state::drawpixel_generic(int x, int y, int patterndata, int offsetcnt) -{ - int pix,transpen, spd = stv2_current_sprite.CMDPMOD & 0x40; -// int mode; - int mesh = stv2_current_sprite.CMDPMOD & 0x100; - int raw,endcode; - - if ( mesh && !((x ^ y) & 1) ) - { - return; - } - - if(x >= 1024 || y >= 512) - return; - - if ( stv2_current_sprite.ispoly ) - { - raw = pix = stv2_current_sprite.CMDCOLR&0xffff; - - transpen = 0; - endcode = 0xffff; - #if 0 - if ( pix & 0x8000 ) - { - mode = 5; - } - else - { - mode = 1; - } - #endif - } - else - { - switch (stv2_current_sprite.CMDPMOD&0x0038) - { - case 0x0000: // mode 0 16 colour bank mode (4bits) (hanagumi blocks) - // most of the shienryu sprites use this mode - raw = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff]; - raw = offsetcnt&1 ? (raw & 0x0f) : ((raw & 0xf0)>>4); - pix = raw+((stv2_current_sprite.CMDCOLR&0xfff0)); - //mode = 0; - transpen = 0; - endcode = 0xf; - break; - case 0x0008: // mode 1 16 colour lookup table mode (4bits) - // shienryu explosions (and some enemies) use this mode - raw = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff]; - raw = offsetcnt&1 ? (raw & 0x0f) : ((raw & 0xf0)>>4); - pix = raw&1 ? - ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((raw&0xfffe)/2)])) & 0x0000ffff) >> 0): - ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((raw&0xfffe)/2)])) & 0xffff0000) >> 16); - //mode = 5; - transpen = 0; - endcode = 0xf; - break; - case 0x0010: // mode 2 64 colour bank mode (8bits) (character select portraits on hanagumi) - raw = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff; - //mode = 2; - pix = raw+(stv2_current_sprite.CMDCOLR&0xffc0); - transpen = 0; - endcode = 0xff; - // Notes of interest: - // Scud: the disposable assassin wants transparent pen on 0 - // sasissu: racing stage background clouds - break; - case 0x0018: // mode 3 128 colour bank mode (8bits) (little characters on hanagumi use this mode) - raw = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff; - pix = raw+(stv2_current_sprite.CMDCOLR&0xff80); - transpen = 0; - endcode = 0xff; - //mode = 3; - break; - case 0x0020: // mode 4 256 colour bank mode (8bits) (hanagumi title) - raw = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff; - pix = raw+(stv2_current_sprite.CMDCOLR&0xff00); - transpen = 0; - endcode = 0xff; - //mode = 4; - break; - case 0x0028: // mode 5 32,768 colour RGB mode (16bits) - raw = m_vdp1.gfx_decode[(patterndata+offsetcnt*2+1) & 0xfffff] | (m_vdp1.gfx_decode[(patterndata+offsetcnt*2) & 0xfffff]<<8); - //mode = 5; - // TODO: 0x1-0x7ffe reserved (color bank) - pix = raw; - transpen = 0; - endcode = 0x7fff; - break; - case 0x0038: // invalid - // game tengoku uses this on hi score screen (tate mode) - // according to Charles, reads from VRAM address 0 - raw = pix = m_vdp1.gfx_decode[1] | (m_vdp1.gfx_decode[0]<<8) ; - // TODO: check transpen - transpen = 0; - endcode = -1; - break; - default: // other settings illegal - pix = machine().rand(); - raw = pix & 0xff; // just mimic old driver behavior - //mode = 0; - transpen = 0; - endcode = 0xff; - popmessage("Illegal Sprite Mode %02x, contact MAMEdev",stv2_current_sprite.CMDPMOD&0x0038); - } - - - // preliminary end code disable support - if ( ((stv2_current_sprite.CMDPMOD & 0x80) == 0) && - (raw == endcode) ) - { - return; - } - } - - /* MSBON */ - // TODO: does this always applies to the frame buffer regardless of the mode? - pix |= stv2_current_sprite.CMDPMOD & 0x8000; - /* - TODO: from docs: - "Except for the color calculation of replace and shadow, color calculation can only be performed when the color code of the original picture is RGB code. - Color calculation can be executed when the color code is color bank code, but the results are not guaranteed." - Currently no idea about the "result not guaranteed" part, let's disable this branch for the time being ... - */ - #if 0 - if ( mode != 5 ) - { - if ( (raw != transpen) || spd ) - { - m_vdp1.framebuffer_draw_lines[y][x] = pix; - } - } - else - #endif - { - if ( (raw != transpen) || spd ) - { - if ( stv2_current_sprite.CMDPMOD & 0x4 ) /* Gouraud shading */ - pix = stv_vdp1_apply_gouraud_shading( x, y, pix ); - - switch( stv2_current_sprite.CMDPMOD & 0x3 ) - { - case 0: /* replace */ - m_vdp1.framebuffer_draw_lines[y][x] = pix; - break; - case 1: /* shadow */ - if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 ) - { - m_vdp1.framebuffer_draw_lines[y][x] = ((m_vdp1.framebuffer_draw_lines[y][x] & ~0x8421) >> 1) | 0x8000; - } - break; - case 2: /* half luminance */ - m_vdp1.framebuffer_draw_lines[y][x] = ((pix & ~0x8421) >> 1) | 0x8000; - break; - case 3: /* half transparent */ - if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 ) - { - m_vdp1.framebuffer_draw_lines[y][x] = alpha_blend_r16( m_vdp1.framebuffer_draw_lines[y][x], pix, 0x80 ) | 0x8000; - } - else - { - m_vdp1.framebuffer_draw_lines[y][x] = pix; - } - break; - //case 4: /* Gouraud shading */ - // TODO: Pro Yakyuu Team mo Tsukurou (during team creation, on PR girl select) - //case 6: - // break; - //case 7: /* Gouraud-shading + half-transparent */ - // Lupin the 3rd Pyramid no Kenja enemy shadows - // Death Crimson lives indicators - // TODO: latter looks really bad. - default: - // TODO: mode 5: prohibited, mode 6: gouraud shading + half-luminance, mode 7: gouraud-shading + half-transparent - popmessage("VDP1 PMOD = %02x, contact MAMEdev",stv2_current_sprite.CMDPMOD & 0x7); - m_vdp1.framebuffer_draw_lines[y][x] = pix; - break; - } - } - } -} - - -void saturn_state::stv_vdp1_set_drawpixel( void ) -{ - int sprite_type = stv2_current_sprite.CMDCTRL & 0x000f; - int sprite_mode = stv2_current_sprite.CMDPMOD&0x0038; - int spd = stv2_current_sprite.CMDPMOD & 0x40; - int mesh = stv2_current_sprite.CMDPMOD & 0x100; - int ecd = stv2_current_sprite.CMDPMOD & 0x80; - - if ( mesh || !ecd || ((stv2_current_sprite.CMDPMOD & 0x7) != 0) ) - { - drawpixel = &saturn_state::drawpixel_generic; - return; - } - - if(stv2_current_sprite.CMDPMOD & 0x8000) - { - drawpixel = &saturn_state::drawpixel_generic; - return; - } - - // polygon / polyline / line with replace case - if (sprite_type & 4 && ((stv2_current_sprite.CMDPMOD & 0x7) == 0)) - { - drawpixel = &saturn_state::drawpixel_poly; - } - else if ( (sprite_mode == 0x20) && !spd ) - { - m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xff00); - drawpixel = &saturn_state::drawpixel_8bpp_trans; - } - else if ((sprite_mode == 0x00) && spd) - { - m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0); - drawpixel = &saturn_state::drawpixel_4bpp_notrans; - } - else if (sprite_mode == 0x00 && !spd ) - { - m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0); - drawpixel = &saturn_state::drawpixel_4bpp_trans; - } - else - { - drawpixel = &saturn_state::drawpixel_generic; - } -} - - -void saturn_state::vdp1_fill_slope(const rectangle &cliprect, int patterndata, int xsize, - int32_t x1, int32_t x2, int32_t sl1, int32_t sl2, int32_t *nx1, int32_t *nx2, - int32_t u1, int32_t u2, int32_t slu1, int32_t slu2, int32_t *nu1, int32_t *nu2, - int32_t v1, int32_t v2, int32_t slv1, int32_t slv2, int32_t *nv1, int32_t *nv2, - int32_t _y1, int32_t y2) -{ - if(_y1 > cliprect.max_y) - return; - - if(y2 <= cliprect.min_y) { - int delta = y2-_y1; - *nx1 = x1+delta*sl1; - *nu1 = u1+delta*slu1; - *nv1 = v1+delta*slv1; - *nx2 = x2+delta*sl2; - *nu2 = u2+delta*slu2; - *nv2 = v2+delta*slv2; - return; - } - - if(y2 > cliprect.max_y) - y2 = cliprect.max_y+1; - - if(_y1 < cliprect.min_y) { - int delta = cliprect.min_y - _y1; - x1 += delta*sl1; - u1 += delta*slu1; - v1 += delta*slv1; - x2 += delta*sl2; - u2 += delta*slu2; - v2 += delta*slv2; - _y1 = cliprect.min_y; - } - - if(x1 > x2 || (x1==x2 && sl1 > sl2)) { - int32_t t, *tp; - t = x1; - x1 = x2; - x2 = t; - t = sl1; - sl1 = sl2; - sl2 = t; - tp = nx1; - nx1 = nx2; - nx2 = tp; - - t = u1; - u1 = u2; - u2 = t; - t = slu1; - slu1 = slu2; - slu2 = t; - tp = nu1; - nu1 = nu2; - nu2 = tp; - - t = v1; - v1 = v2; - v2 = t; - t = slv1; - slv1 = slv2; - slv2 = t; - tp = nv1; - nv1 = nv2; - nv2 = tp; - } - - while(_y1 < y2) { - if(_y1 >= cliprect.min_y) { - int32_t slux = 0, slvx = 0; - int xx1 = x1>>FRAC_SHIFT; - int xx2 = x2>>FRAC_SHIFT; - int32_t u = u1; - int32_t v = v1; - if(xx1 != xx2) { - int delta = xx2-xx1; - slux = (u2-u1)/delta; - slvx = (v2-v1)/delta; - } - if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) { - if(xx1 < cliprect.min_x) { - int delta = cliprect.min_x-xx1; - u += slux*delta; - v += slvx*delta; - xx1 = cliprect.min_x; - } - if(xx2 > cliprect.max_x) - xx2 = cliprect.max_x; - - while(xx1 <= xx2) { - (this->*drawpixel)(xx1,_y1, patterndata, (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT)); - xx1++; - u += slux; - v += slvx; - } - } - } - - x1 += sl1; - u1 += slu1; - v1 += slv1; - x2 += sl2; - u2 += slu2; - v2 += slv2; - _y1++; - } - *nx1 = x1; - *nu1 = u1; - *nv1 = v1; - *nx2 = x2; - *nu2 = u2; - *nv2 = v2; -} - -void saturn_state::vdp1_fill_line(const rectangle &cliprect, int patterndata, int xsize, int32_t y, - int32_t x1, int32_t x2, int32_t u1, int32_t u2, int32_t v1, int32_t v2) -{ - int xx1 = x1>>FRAC_SHIFT; - int xx2 = x2>>FRAC_SHIFT; - - if(y > cliprect.max_y || y < cliprect.min_y) - return; - - if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) { - int32_t slux = 0, slvx = 0; - int32_t u = u1; - int32_t v = v1; - if(xx1 != xx2) { - int delta = xx2-xx1; - slux = (u2-u1)/delta; - slvx = (v2-v1)/delta; - } - if(xx1 < cliprect.min_x) { - int delta = cliprect.min_x-xx1; - u += slux*delta; - v += slvx*delta; - xx1 = cliprect.min_x; - } - if(xx2 > cliprect.max_x) - xx2 = cliprect.max_x; - - while(xx1 <= xx2) { - (this->*drawpixel)(xx1,y,patterndata,(v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT)); - xx1++; - u += slux; - v += slvx; - } - } -} - -void saturn_state::vdp1_fill_quad(const rectangle &cliprect, int patterndata, int xsize, const struct spoint *q) -{ - int32_t sl1, sl2, slu1, slu2, slv1, slv2, cury, limy, x1, x2, u1, u2, v1, v2, delta; - int pmin, pmax, i, ps1, ps2; - struct spoint p[8]; - - for(i=0; i<4; i++) { - p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT; - p[i].y = p[i+4].y = q[i].y; - p[i].u = p[i+4].u = q[i].u << FRAC_SHIFT; - p[i].v = p[i+4].v = q[i].v << FRAC_SHIFT; - } - - pmin = pmax = 0; - for(i=1; i<4; i++) { - if(p[i].y < p[pmin].y) - pmin = i; - if(p[i].y > p[pmax].y) - pmax = i; - } - - cury = p[pmin].y; - limy = p[pmax].y; - - if(cury == limy) { - x1 = x2 = p[0].x; - u1 = u2 = p[0].u; - v1 = v2 = p[0].v; - for(i=1; i<4; i++) { - if(p[i].x < x1) { - x1 = p[i].x; - u1 = p[i].u; - v1 = p[i].v; - } - if(p[i].x > x2) { - x2 = p[i].x; - u2 = p[i].u; - v2 = p[i].v; - } - } - vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2); - return; - } - - if(cury > cliprect.max_y) - return; - if(limy <= cliprect.min_y) - return; - - if(limy > cliprect.max_y) - limy = cliprect.max_y; - - ps1 = pmin+4; - ps2 = pmin; - - goto startup; - - for(;;) { - if(p[ps1-1].y == p[ps2+1].y) { - vdp1_fill_slope(cliprect, patterndata, xsize, - x1, x2, sl1, sl2, &x1, &x2, - u1, u2, slu1, slu2, &u1, &u2, - v1, v2, slv1, slv2, &v1, &v2, - cury, p[ps1-1].y); - cury = p[ps1-1].y; - if(cury >= limy) - break; - ps1--; - ps2++; - - startup: - while(p[ps1-1].y == cury) - ps1--; - while(p[ps2+1].y == cury) - ps2++; - x1 = p[ps1].x; - u1 = p[ps1].u; - v1 = p[ps1].v; - x2 = p[ps2].x; - u2 = p[ps2].u; - v2 = p[ps2].v; - - delta = cury-p[ps1-1].y; - sl1 = (x1-p[ps1-1].x)/delta; - slu1 = (u1-p[ps1-1].u)/delta; - slv1 = (v1-p[ps1-1].v)/delta; - - delta = cury-p[ps2+1].y; - sl2 = (x2-p[ps2+1].x)/delta; - slu2 = (u2-p[ps2+1].u)/delta; - slv2 = (v2-p[ps2+1].v)/delta; - } else if(p[ps1-1].y < p[ps2+1].y) { - vdp1_fill_slope(cliprect, patterndata, xsize, - x1, x2, sl1, sl2, &x1, &x2, - u1, u2, slu1, slu2, &u1, &u2, - v1, v2, slv1, slv2, &v1, &v2, - cury, p[ps1-1].y); - cury = p[ps1-1].y; - if(cury >= limy) - break; - ps1--; - while(p[ps1-1].y == cury) - ps1--; - x1 = p[ps1].x; - u1 = p[ps1].u; - v1 = p[ps1].v; - - delta = cury-p[ps1-1].y; - sl1 = (x1-p[ps1-1].x)/delta; - slu1 = (u1-p[ps1-1].u)/delta; - slv1 = (v1-p[ps1-1].v)/delta; - } else { - vdp1_fill_slope(cliprect, patterndata, xsize, - x1, x2, sl1, sl2, &x1, &x2, - u1, u2, slu1, slu2, &u1, &u2, - v1, v2, slv1, slv2, &v1, &v2, - cury, p[ps2+1].y); - cury = p[ps2+1].y; - if(cury >= limy) - break; - ps2++; - while(p[ps2+1].y == cury) - ps2++; - x2 = p[ps2].x; - u2 = p[ps2].u; - v2 = p[ps2].v; - - delta = cury-p[ps2+1].y; - sl2 = (x2-p[ps2+1].x)/delta; - slu2 = (u2-p[ps2+1].u)/delta; - slv2 = (v2-p[ps2+1].v)/delta; - } - } - if(cury == limy) - vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2); -} - -int saturn_state::x2s(int v) -{ - return (int32_t)(int16_t)v + m_vdp1.local_x; -} - -int saturn_state::y2s(int v) -{ - return (int32_t)(int16_t)v + m_vdp1.local_y; -} - -void saturn_state::stv_vdp1_draw_line(const rectangle &cliprect) -{ - struct spoint q[4]; - - q[0].x = x2s(stv2_current_sprite.CMDXA); - q[0].y = y2s(stv2_current_sprite.CMDYA); - q[1].x = x2s(stv2_current_sprite.CMDXB); - q[1].y = y2s(stv2_current_sprite.CMDYB); - q[2].x = x2s(stv2_current_sprite.CMDXA); - q[2].y = y2s(stv2_current_sprite.CMDYA); - q[3].x = x2s(stv2_current_sprite.CMDXB); - q[3].y = y2s(stv2_current_sprite.CMDYB); - - q[0].u = q[3].u = q[1].u = q[2].u = 0; - q[0].v = q[1].v = q[2].v = q[3].v = 0; - - vdp1_fill_quad(cliprect, 0, 1, q); -} - -void saturn_state::stv_vdp1_draw_poly_line(const rectangle &cliprect) -{ - struct spoint q[4]; - - q[0].x = x2s(stv2_current_sprite.CMDXA); - q[0].y = y2s(stv2_current_sprite.CMDYA); - q[1].x = x2s(stv2_current_sprite.CMDXB); - q[1].y = y2s(stv2_current_sprite.CMDYB); - q[2].x = x2s(stv2_current_sprite.CMDXA); - q[2].y = y2s(stv2_current_sprite.CMDYA); - q[3].x = x2s(stv2_current_sprite.CMDXB); - q[3].y = y2s(stv2_current_sprite.CMDYB); - - q[0].u = q[3].u = q[1].u = q[2].u = 0; - q[0].v = q[1].v = q[2].v = q[3].v = 0; - - vdp1_fill_quad(cliprect, 0, 1, q); - - q[0].x = x2s(stv2_current_sprite.CMDXB); - q[0].y = y2s(stv2_current_sprite.CMDYB); - q[1].x = x2s(stv2_current_sprite.CMDXC); - q[1].y = y2s(stv2_current_sprite.CMDYC); - q[2].x = x2s(stv2_current_sprite.CMDXB); - q[2].y = y2s(stv2_current_sprite.CMDYB); - q[3].x = x2s(stv2_current_sprite.CMDXC); - q[3].y = y2s(stv2_current_sprite.CMDYC); - - q[0].u = q[3].u = q[1].u = q[2].u = 0; - q[0].v = q[1].v = q[2].v = q[3].v = 0; - - vdp1_fill_quad(cliprect, 0, 1, q); - - q[0].x = x2s(stv2_current_sprite.CMDXC); - q[0].y = y2s(stv2_current_sprite.CMDYC); - q[1].x = x2s(stv2_current_sprite.CMDXD); - q[1].y = y2s(stv2_current_sprite.CMDYD); - q[2].x = x2s(stv2_current_sprite.CMDXC); - q[2].y = y2s(stv2_current_sprite.CMDYC); - q[3].x = x2s(stv2_current_sprite.CMDXD); - q[3].y = y2s(stv2_current_sprite.CMDYD); - - q[0].u = q[3].u = q[1].u = q[2].u = 0; - q[0].v = q[1].v = q[2].v = q[3].v = 0; - - vdp1_fill_quad(cliprect, 0, 1, q); - - q[0].x = x2s(stv2_current_sprite.CMDXD); - q[0].y = y2s(stv2_current_sprite.CMDYD); - q[1].x = x2s(stv2_current_sprite.CMDXA); - q[1].y = y2s(stv2_current_sprite.CMDYA); - q[2].x = x2s(stv2_current_sprite.CMDXD); - q[2].y = y2s(stv2_current_sprite.CMDYD); - q[3].x = x2s(stv2_current_sprite.CMDXA); - q[3].y = y2s(stv2_current_sprite.CMDYA); - - q[0].u = q[3].u = q[1].u = q[2].u = 0; - q[0].v = q[1].v = q[2].v = q[3].v = 0; - - stv_vdp1_setup_shading(q, cliprect); - vdp1_fill_quad(cliprect, 0, 1, q); - -} - -void saturn_state::stv_vdp1_draw_distorted_sprite(const rectangle &cliprect) -{ - struct spoint q[4]; - - int xsize, ysize; - int direction; - int patterndata; - - direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4; - - if ( stv2_current_sprite.ispoly ) - { - xsize = ysize = 1; - patterndata = 0; - } - else - { - xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8; - xsize = xsize * 8; - if (xsize == 0) return; /* setting prohibited */ - - ysize = (stv2_current_sprite.CMDSIZE & 0x00ff); - if (ysize == 0) return; /* setting prohibited */ - - patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff; - patterndata = patterndata * 0x8; - - } - - - q[0].x = x2s(stv2_current_sprite.CMDXA); - q[0].y = y2s(stv2_current_sprite.CMDYA); - q[1].x = x2s(stv2_current_sprite.CMDXB); - q[1].y = y2s(stv2_current_sprite.CMDYB); - q[2].x = x2s(stv2_current_sprite.CMDXC); - q[2].y = y2s(stv2_current_sprite.CMDYC); - q[3].x = x2s(stv2_current_sprite.CMDXD); - q[3].y = y2s(stv2_current_sprite.CMDYD); - - if(direction & 1) { // xflip - q[0].u = q[3].u = xsize-1; - q[1].u = q[2].u = 0; - } else { - q[0].u = q[3].u = 0; - q[1].u = q[2].u = xsize-1; - } - if(direction & 2) { // yflip - q[0].v = q[1].v = ysize-1; - q[2].v = q[3].v = 0; - } else { - q[0].v = q[1].v = 0; - q[2].v = q[3].v = ysize-1; - } - - stv_vdp1_setup_shading(q, cliprect); - vdp1_fill_quad(cliprect, patterndata, xsize, q); -} - -void saturn_state::stv_vdp1_draw_scaled_sprite(const rectangle &cliprect) -{ - struct spoint q[4]; - - int xsize, ysize; - int direction; - int patterndata; - int zoompoint; - int x,y; - int x2,y2; - int screen_width,screen_height,screen_height_negative = 0; - - direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4; - - xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8; - xsize = xsize * 8; - - ysize = (stv2_current_sprite.CMDSIZE & 0x00ff); - - patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff; - patterndata = patterndata * 0x8; - - zoompoint = (stv2_current_sprite.CMDCTRL & 0x0f00)>>8; - - x = stv2_current_sprite.CMDXA; - y = stv2_current_sprite.CMDYA; - - screen_width = (int16_t)stv2_current_sprite.CMDXB; - if ( (screen_width < 0) && zoompoint) - { - screen_width = -screen_width; - direction |= 1; - } - - screen_height = (int16_t)stv2_current_sprite.CMDYB; - if ( (screen_height < 0) && zoompoint ) - { - screen_height_negative = 1; - screen_height = -screen_height; - direction |= 2; - } - - x2 = stv2_current_sprite.CMDXC; // second co-ordinate set x - y2 = stv2_current_sprite.CMDYC; // second co-ordinate set y - - switch (zoompoint) - { - case 0x0: // specified co-ordinates - break; - case 0x5: // up left - break; - case 0x6: // up center - x -= screen_width/2 ; - break; - case 0x7: // up right - x -= screen_width; - break; - - case 0x9: // center left - y -= screen_height/2 ; - break; - case 0xa: // center center - y -= screen_height/2 ; - x -= screen_width/2 ; - - break; - - case 0xb: // center right - y -= screen_height/2 ; - x -= screen_width; - break; - - case 0xd: // center left - y -= screen_height; - break; - - case 0xe: // center center - y -= screen_height; - x -= screen_width/2 ; - break; - - case 0xf: // center right - y -= screen_height; - x -= screen_width; - break; - - default: // illegal - break; - - } - - /* 0----1 - | | - | | - 3----2 */ - - if (zoompoint) - { - q[0].x = x2s(x); - q[0].y = y2s(y); - q[1].x = x2s(x)+screen_width; - q[1].y = y2s(y); - q[2].x = x2s(x)+screen_width; - q[2].y = y2s(y)+screen_height; - q[3].x = x2s(x); - q[3].y = y2s(y)+screen_height; - - if ( screen_height_negative ) - { - q[0].y += screen_height; - q[1].y += screen_height; - q[2].y += screen_height; - q[3].y += screen_height; - } - } - else - { - q[0].x = x2s(x); - q[0].y = y2s(y); - q[1].x = x2s(x2); - q[1].y = y2s(y); - q[2].x = x2s(x2); - q[2].y = y2s(y2); - q[3].x = x2s(x); - q[3].y = y2s(y2); - } - - - if(direction & 1) { // xflip - q[0].u = q[3].u = xsize-1; - q[1].u = q[2].u = 0; - } else { - q[0].u = q[3].u = 0; - q[1].u = q[2].u = xsize-1; - } - if(direction & 2) { // yflip - q[0].v = q[1].v = ysize-1; - q[2].v = q[3].v = 0; - } else { - q[0].v = q[1].v = 0; - q[2].v = q[3].v = ysize-1; - } - - stv_vdp1_setup_shading(q, cliprect); - vdp1_fill_quad(cliprect, patterndata, xsize, q); -} - - - - -void saturn_state::stv_vdp1_draw_normal_sprite(const rectangle &cliprect, int sprite_type) -{ - int y, ysize, drawypos; - int x, xsize, drawxpos; - int direction; - int patterndata; - uint8_t shading; - int su, u, dux, duy; - int maxdrawypos, maxdrawxpos; - - x = x2s(stv2_current_sprite.CMDXA); - y = y2s(stv2_current_sprite.CMDYA); - - direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4; - - xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8; - xsize = xsize * 8; - - ysize = (stv2_current_sprite.CMDSIZE & 0x00ff); - - patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff; - patterndata = patterndata * 0x8; - - if (VDP1_LOG) logerror ("Drawing Normal Sprite x %04x y %04x xsize %04x ysize %04x patterndata %06x\n",x,y,xsize,ysize,patterndata); - - if ( x > cliprect.max_x ) return; - if ( y > cliprect.max_y ) return; - - shading = stv_read_gouraud_table(); - if ( shading ) - { - struct spoint q[4]; - q[0].x = x; q[0].y = y; - q[1].x = x + xsize; q[1].y = y; - q[2].x = x + xsize; q[2].y = y + ysize; - q[3].x = x; q[3].y = y + ysize; - - stv_vdp1_setup_shading( q, cliprect ); - } - - u = 0; - dux = 1; - duy = xsize; - if ( direction & 0x1 ) //xflip - { - dux = -1; - u = xsize - 1; - } - if ( direction & 0x2 ) //yflip - { - duy = -xsize; - u += xsize*(ysize-1); - } - if ( y < cliprect.min_y ) //clip y - { - u += xsize*(cliprect.min_y - y); - ysize -= (cliprect.min_y - y); - y = cliprect.min_y; - } - if ( x < cliprect.min_x ) //clip x - { - u += dux*(cliprect.min_x - x); - xsize -= (cliprect.min_x - x); - x = cliprect.min_x; - } - maxdrawypos = std::min(y+ysize-1,cliprect.max_y); - maxdrawxpos = std::min(x+xsize-1,cliprect.max_x); - for (drawypos = y; drawypos <= maxdrawypos; drawypos++ ) - { - //destline = m_vdp1.framebuffer_draw_lines[drawypos]; - su = u; - for (drawxpos = x; drawxpos <= maxdrawxpos; drawxpos++ ) - { - (this->*drawpixel)( drawxpos, drawypos, patterndata, u ); - u += dux; - } - u = su + duy; - } -} - -TIMER_CALLBACK_MEMBER(saturn_state::vdp1_draw_end ) -{ - /* set CEF to 1*/ - CEF_1; - - // TODO: temporary for Batman Forever, presumably anonymous timer not behaving well. - #if 0 - if(!(m_scu.ism & IRQ_VDP1_END)) - { - m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d); // SH2 - scu_do_transfer(6); - } - else - m_scu.ist |= (IRQ_VDP1_END); - #endif -} - - -void saturn_state::stv_vdp1_process_list( void ) -{ - int position; - int spritecount; - int vdp1_nest; - rectangle *cliprect; - - spritecount = 0; - position = 0; - - if (VDP1_LOG) logerror ("Sprite List Process START\n"); - - vdp1_nest = -1; - - stv_clear_gouraud_shading(); - - /*Set CEF bit to 0*/ - CEF_0; - - // TODO: is there an actual limit for this? - while (spritecount<16383) // max 16383 with texture or max 16384 without texture - vitrually unlimited - { - int draw_this_sprite; - - draw_this_sprite = 1; - - // if (position >= ((0x80000/0x20)/4)) // safety check - // { - // if (VDP1_LOG) logerror ("Sprite List Position Too High!\n"); - // position = 0; - // } - - spritecount++; - - stv2_current_sprite.CMDCTRL = (m_vdp1_vram[position * (0x20/4)+0] & 0xffff0000) >> 16; - - if (stv2_current_sprite.CMDCTRL == 0x8000) - { - if (VDP1_LOG) logerror ("List Terminator (0x8000) Encountered, Sprite List Process END\n"); - goto end; // end of list - } - - stv2_current_sprite.CMDLINK = (m_vdp1_vram[position * (0x20/4)+0] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDPMOD = (m_vdp1_vram[position * (0x20/4)+1] & 0xffff0000) >> 16; - stv2_current_sprite.CMDCOLR = (m_vdp1_vram[position * (0x20/4)+1] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDSRCA = (m_vdp1_vram[position * (0x20/4)+2] & 0xffff0000) >> 16; - stv2_current_sprite.CMDSIZE = (m_vdp1_vram[position * (0x20/4)+2] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDXA = (m_vdp1_vram[position * (0x20/4)+3] & 0xffff0000) >> 16; - stv2_current_sprite.CMDYA = (m_vdp1_vram[position * (0x20/4)+3] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDXB = (m_vdp1_vram[position * (0x20/4)+4] & 0xffff0000) >> 16; - stv2_current_sprite.CMDYB = (m_vdp1_vram[position * (0x20/4)+4] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDXC = (m_vdp1_vram[position * (0x20/4)+5] & 0xffff0000) >> 16; - stv2_current_sprite.CMDYC = (m_vdp1_vram[position * (0x20/4)+5] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDXD = (m_vdp1_vram[position * (0x20/4)+6] & 0xffff0000) >> 16; - stv2_current_sprite.CMDYD = (m_vdp1_vram[position * (0x20/4)+6] & 0x0000ffff) >> 0; - stv2_current_sprite.CMDGRDA = (m_vdp1_vram[position * (0x20/4)+7] & 0xffff0000) >> 16; -// stv2_current_sprite.UNUSED = (m_vdp1_vram[position * (0x20/4)+7] & 0x0000ffff) >> 0; - - /* proecess jump / skip commands, set position for next sprite */ - switch (stv2_current_sprite.CMDCTRL & 0x7000) - { - case 0x0000: // jump next - if (VDP1_LOG) logerror ("Sprite List Process + Next (Normal)\n"); - position++; - break; - case 0x1000: // jump assign - if (VDP1_LOG) logerror ("Sprite List Process + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2)); - position= (stv2_current_sprite.CMDLINK>>2); - break; - case 0x2000: // jump call - if (vdp1_nest == -1) - { - if (VDP1_LOG) logerror ("Sprite List Process + Call Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2)); - vdp1_nest = position+1; - position = (stv2_current_sprite.CMDLINK>>2); - } - else - { - if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n"); - position++; - } - break; - case 0x3000: - if (vdp1_nest != -1) - { - if (VDP1_LOG) logerror ("Sprite List Process + Return\n"); - position = vdp1_nest; - vdp1_nest = -1; - } - else - { - if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n"); - position++; - goto end; // end of list - } - break; - case 0x4000: - draw_this_sprite = 0; - position++; - break; - case 0x5000: - if (VDP1_LOG) logerror ("Sprite List Skip + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2)); - draw_this_sprite = 0; - position= (stv2_current_sprite.CMDLINK>>2); - - break; - case 0x6000: - draw_this_sprite = 0; - if (vdp1_nest == -1) - { - if (VDP1_LOG) logerror ("Sprite List Skip + Call To Subroutine Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2)); - - vdp1_nest = position+1; - position = (stv2_current_sprite.CMDLINK>>2); - } - else - { - if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n"); - position++; - } - break; - case 0x7000: - draw_this_sprite = 0; - if (vdp1_nest != -1) - { - if (VDP1_LOG) logerror ("Sprite List Skip + Return from Subroutine\n"); - - position = vdp1_nest; - vdp1_nest = -1; - } - else - { - if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n"); - position++; - goto end; // end of list - } - break; - } - - /* continue to draw this sprite only if the command wasn't to skip it */ - if (draw_this_sprite ==1) - { - if ( stv2_current_sprite.CMDPMOD & 0x0400 ) - { - //if(stv2_current_sprite.CMDPMOD & 0x0200) /* TODO: Bio Hazard inventory screen uses outside cliprect */ - // cliprect = &m_vdp1.system_cliprect; - //else - cliprect = &m_vdp1.user_cliprect; - } - else - { - cliprect = &m_vdp1.system_cliprect; - } - - stv_vdp1_set_drawpixel(); - - switch (stv2_current_sprite.CMDCTRL & 0x000f) - { - case 0x0000: - if (VDP1_LOG) logerror ("Sprite List Normal Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA); - stv2_current_sprite.ispoly = 0; - stv_vdp1_draw_normal_sprite(*cliprect, 0); - break; - - case 0x0001: - if (VDP1_LOG) logerror ("Sprite List Scaled Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA); - stv2_current_sprite.ispoly = 0; - stv_vdp1_draw_scaled_sprite(*cliprect); - break; - - case 0x0002: - case 0x0003: // used by Hardcore 4x4 - if (VDP1_LOG) logerror ("Sprite List Distorted Sprite\n"); - if (VDP1_LOG) logerror ("(A: %d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA); - if (VDP1_LOG) logerror ("(B: %d %d)\n",stv2_current_sprite.CMDXB,stv2_current_sprite.CMDYB); - if (VDP1_LOG) logerror ("(C: %d %d)\n",stv2_current_sprite.CMDXC,stv2_current_sprite.CMDYC); - if (VDP1_LOG) logerror ("(D: %d %d)\n",stv2_current_sprite.CMDXD,stv2_current_sprite.CMDYD); - if (VDP1_LOG) logerror ("CMDPMOD = %04x\n",stv2_current_sprite.CMDPMOD); - - stv2_current_sprite.ispoly = 0; - stv_vdp1_draw_distorted_sprite(*cliprect); - break; - - case 0x0004: - if (VDP1_LOG) logerror ("Sprite List Polygon\n"); - stv2_current_sprite.ispoly = 1; - stv_vdp1_draw_distorted_sprite(*cliprect); - break; - - case 0x0005: -// case 0x0007: // mirror? Baroque uses it, crashes for whatever reason - if (VDP1_LOG) logerror ("Sprite List Polyline\n"); - stv2_current_sprite.ispoly = 1; - stv_vdp1_draw_poly_line(*cliprect); - break; - - case 0x0006: - if (VDP1_LOG) logerror ("Sprite List Line\n"); - stv2_current_sprite.ispoly = 1; - stv_vdp1_draw_line(*cliprect); - break; - - case 0x0008: -// case 0x000b: // mirror? Bug 2 - if (VDP1_LOG) logerror ("Sprite List Set Command for User Clipping (%d,%d),(%d,%d)\n", stv2_current_sprite.CMDXA, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC); - m_vdp1.user_cliprect.set(stv2_current_sprite.CMDXA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDYC); - break; - - case 0x0009: - if (VDP1_LOG) logerror ("Sprite List Set Command for System Clipping (0,0),(%d,%d)\n", stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC); - m_vdp1.system_cliprect.set(0, stv2_current_sprite.CMDXC, 0, stv2_current_sprite.CMDYC); - break; - - case 0x000a: - if (VDP1_LOG) logerror ("Sprite List Local Co-Ordinate Set (%d %d)\n",(int16_t)stv2_current_sprite.CMDXA,(int16_t)stv2_current_sprite.CMDYA); - m_vdp1.local_x = (int16_t)stv2_current_sprite.CMDXA; - m_vdp1.local_y = (int16_t)stv2_current_sprite.CMDYA; - break; - - default: - popmessage ("VDP1: Sprite List Illegal %02x (%d), contact MAMEdev",stv2_current_sprite.CMDCTRL & 0xf,spritecount); - m_vdp1.lopr = (position * 0x20) >> 3; - //m_vdp1.copr = (position * 0x20) >> 3; - // prematurely kill the VDP1 process if an illegal opcode is executed - // Sexy Parodius calls multiple illegals and expects VDP1 irq to be fired anyway! - goto end; - } - } - - } - - - end: - m_vdp1.copr = (position * 0x20) >> 3; - - - /* TODO: what's the exact formula? Guess it should be a mix between number of pixels written and actual command data fetched. */ - // if spritecount = 10000 don't send a vdp1 draw end -// if(spritecount < 10000) - machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(spritecount*16), timer_expired_delegate(FUNC(saturn_state::vdp1_draw_end),this)); - - if (VDP1_LOG) logerror ("End of list processing!\n"); -} - -void saturn_state::video_update_vdp1( void ) -{ - int framebuffer_changed = 0; - -// int enable; -// if (machine.input().code_pressed (KEYCODE_R)) VDP1_LOG = 1; -// if (machine.input().code_pressed (KEYCODE_T)) VDP1_LOG = 0; - -// if (machine.input().code_pressed (KEYCODE_Y)) VDP1_LOG = 0; -// { -// FILE *fp; -// -// fp=fopen("vdp1_ram.dmp", "w+b"); -// if (fp) -// { -// fwrite(stv_vdp1, 0x00100000, 1, fp); -// fclose(fp); -// } -// } - if (VDP1_LOG) logerror("video_update_vdp1 called\n"); - if (VDP1_LOG) logerror( "FBCR = %0x, accessed = %d\n", STV_VDP1_FBCR, m_vdp1.fbcr_accessed ); - - if(STV_VDP1_CEF) - BEF_1; - else - BEF_0; - - if ( m_vdp1.framebuffer_clear_on_next_frame ) - { - if ( ((STV_VDP1_FBCR & 0x3) == 3) && - m_vdp1.fbcr_accessed ) - { - stv_clear_framebuffer(m_vdp1.framebuffer_current_display); - m_vdp1.framebuffer_clear_on_next_frame = 0; - } - } - - switch( STV_VDP1_FBCR & 0x3 ) - { - case 0: /* Automatic mode */ - stv_vdp1_change_framebuffers(); - stv_clear_framebuffer(m_vdp1.framebuffer_current_draw); - framebuffer_changed = 1; - break; - case 1: /* Setting prohibited */ - break; - case 2: /* Manual mode - erase */ - if ( m_vdp1.fbcr_accessed ) - { - m_vdp1.framebuffer_clear_on_next_frame = 1; - } - break; - case 3: /* Manual mode - change */ - if ( m_vdp1.fbcr_accessed ) - { - stv_vdp1_change_framebuffers(); - if ( STV_VDP1_VBE ) - { - stv_clear_framebuffer(m_vdp1.framebuffer_current_draw); - } - /* TODO: Slam n Jam 96 & Cross Romance doesn't like this, investigate. */ - framebuffer_changed = 1; - } - // framebuffer_changed = 1; - break; - } - m_vdp1.fbcr_accessed = 0; - - if (VDP1_LOG) logerror( "PTM = %0x, TVM = %x\n", STV_VDP1_PTM, STV_VDP1_TVM ); - /*Set CEF bit to 0*/ - //CEF_0; - switch(STV_VDP1_PTM & 3) - { - case 0:/*Idle Mode*/ - /*Set CEF bit to 0*/ - //CEF_0; - break; - case 1:/*Draw by request*/ - /*Set CEF bit to 0*/ - //CEF_0; - break; - case 2:/*Automatic Draw*/ - if ( framebuffer_changed || VDP1_LOG ) - { - /*set CEF to 1*/ - stv_vdp1_process_list(); - } - break; - case 3: /**/ - logerror("Warning: Invalid PTM mode set for VDP1!\n"); - break; - } - //popmessage("%04x %04x",STV_VDP1_EWRR_X3,STV_VDP1_EWRR_Y3); -} - -void saturn_state::stv_vdp1_state_save_postload( void ) -{ - uint8_t *vdp1 = m_vdp1.gfx_decode.get(); - int offset; - uint32_t data; - - m_vdp1.framebuffer_mode = -1; - m_vdp1.framebuffer_double_interlace = -1; - - stv_set_framebuffer_config(); - - for (offset = 0; offset < 0x80000/4; offset++ ) - { - data = m_vdp1_vram[offset]; - /* put in gfx region for easy decoding */ - vdp1[offset*4+0] = (data & 0xff000000) >> 24; - vdp1[offset*4+1] = (data & 0x00ff0000) >> 16; - vdp1[offset*4+2] = (data & 0x0000ff00) >> 8; - vdp1[offset*4+3] = (data & 0x000000ff) >> 0; - } -} - -int saturn_state::stv_vdp1_start ( void ) -{ - m_vdp1_regs = make_unique_clear(0x020/2 ); - m_vdp1_vram = make_unique_clear(0x100000/4 ); - m_vdp1.gfx_decode = std::make_unique(0x100000 ); - - stv_vdp1_shading_data = std::make_unique(); - - m_vdp1.framebuffer[0] = std::make_unique(1024 * 256 * 2 ); /* *2 is for double interlace */ - m_vdp1.framebuffer[1] = std::make_unique(1024 * 256 * 2 ); - - m_vdp1.framebuffer_display_lines = std::make_unique(512); - m_vdp1.framebuffer_draw_lines = std::make_unique(512); - - m_vdp1.framebuffer_width = m_vdp1.framebuffer_height = 0; - m_vdp1.framebuffer_mode = -1; - m_vdp1.framebuffer_double_interlace = -1; - m_vdp1.fbcr_accessed = 0; - m_vdp1.framebuffer_current_display = 0; - m_vdp1.framebuffer_current_draw = 1; - stv_clear_framebuffer(m_vdp1.framebuffer_current_draw); - m_vdp1.framebuffer_clear_on_next_frame = 0; - - m_vdp1.system_cliprect.set(0, 0, 0, 0); - /* Kidou Senshi Z Gundam - Zenpen Zeta no Kodou loves to use the user cliprect vars in an undefined state ... */ - m_vdp1.user_cliprect.set(0, 512, 0, 256); - - // save state - save_pointer(NAME(m_vdp1_regs), 0x020/2); - save_pointer(NAME(m_vdp1_vram), 0x100000/4); - save_item(NAME(m_vdp1.fbcr_accessed)); - save_item(NAME(m_vdp1.framebuffer_current_display)); - save_item(NAME(m_vdp1.framebuffer_current_draw)); - save_item(NAME(m_vdp1.framebuffer_clear_on_next_frame)); - save_item(NAME(m_vdp1.local_x)); - save_item(NAME(m_vdp1.local_y)); - machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp1_state_save_postload), this)); - return 0; -} diff --git a/src/devices/video/stvvdp1.h b/src/devices/video/stvvdp1.h deleted file mode 100644 index 6acafefe66a..00000000000 --- a/src/devices/video/stvvdp1.h +++ /dev/null @@ -1,2 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:David Haywood, Angelo Salese, Olivier Galibert, Mariusz Wojcieszek, R. Belmont diff --git a/src/devices/video/stvvdp2.cpp b/src/devices/video/stvvdp2.cpp deleted file mode 100644 index 66cfb7c2ec0..00000000000 --- a/src/devices/video/stvvdp2.cpp +++ /dev/null @@ -1,7156 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:David Haywood, Angelo Salese, Olivier Galibert, Mariusz Wojcieszek, R. Belmont -/* Sega Saturn VDP2 */ - -/* - --------------------------- WARNING WARNING WARNING -------------------------- -This is a legacy core, all game based notes are for a future device rewrite. -Please don't remove them if for no reason you truly want to mess with this. --------------------------- WARNING WARNING WARNING -------------------------- - -the dirty marking stuff and tile decoding will probably be removed in the end anyway as we'll need custom -rendering code since mame's drawgfx / tilesytem don't offer everything st-v needs - -this system seems far too complex to use Mame's tilemap system - -4 'scroll' planes (scroll screens) - -the scroll planes have slightly different capabilities - -NBG0 -NBG1 -NBG2 -NBG3 - -2 'rotate' planes - -RBG0 -RBG1 - --- other crap -EXBG (external) - ------------------------------------------------------------------------------------------------------------ - -Video emulation TODO: --all games: - \-priorities (check myfairld,thunt) - \-complete windows effects - \-mosaic effect - \-ODD bit/H/V Counter not yet emulated properly - \-Reduction enable bits (zooming limiters) - \-Check if there are any remaining video registers that are yet to be macroized & added to the rumble. --batmanfr: - \-If you reset the game after the character selection screen,when you get again to it there's garbage - floating behind Batman. --elandore: - \-(BTANB) priorities at the VS. screen apparently is wrong,but it's like this on the Saturn version too. --hanagumi: - \-ending screens have corrupt graphics. (*untested*) --kiwames: - \-(fixed) incorrect color emulation for the alpha blended flames on the title screen,it's caused by a schizoid - linescroll emulation quirk. - \-the VDP1 sprites refresh is too slow,causing the "Draw by request" mode to - flicker. Moved back to default ATM. --pblbeach: - \-Sprites are offset, because it doesn't clear vdp1 local coordinates set by bios, - I guess that they are cleared when some vdp1 register is written (kludged for now) --prikura: - \-Attract mode presentation has corrupted graphics in various places,probably caused by incomplete - framebuffer data delete. --seabass: - \-(fixed) Player sprite is corrupt/missing during movements,caused by incomplete framebuffer switching. --shienryu: - \-level 2 background colors on statues, caused by special color calculation usage (per dot); -(Saturn games) -- scud the disposable assassin: - \- when zooming on melee attack background gets pink, color calculation issue? -- virtual hydlide: - \- transparent pens usage on most vdp1 items should be black instead. - \- likewise "press start button" is the other way around, i.e. black pen where it should be transparent instead. - -Notes of Interest & Unclear features: - --the test mode / bios is drawn with layer NBG3; --hanagumi puts a 'RED' dragon logo in tileram (base 0x64000, 4bpp, 8x8 tiles) but -its not displayed because its priority value is 0.Left-over? - --scrolling is screen display wise,meaning that a scrolling value is masked with the -screen resolution size values; - --H-Blank bit is INDIPENDENT of the V-Blank bit...trying to fix enable/disable it during V-Blank period - causes wrong gameplay speed in Golden Axe:The Duel. - --Bitmaps uses transparency pens,examples are: -\-elandore's energy bars; -\-mausuke's foreground(the one used on the playfield) -\-shanhigw's tile-based sprites; -The transparency pen table is like this: - -|------------------|---------------------| -| Character count | Transparency code | -|------------------|---------------------| -| 16 colors |=0x0 (4 bits) | -| 256 colors |=0x00 (8 bits) | -| 2048 colors |=0x000 (11 bits) | -| 32,768 colors |MSB=0 (bit 15) | -| 16,770,000 colors|MSB=0 (bit 31) | -|------------------|---------------------| -In other words,the first three types uses the offset and not the color allocated. - --double density interlace setting (LSMD == 3) apparently does a lot of fancy stuff in the graphics sizes. - --Debug key list(only if you enable the debug mode on top of this file): - \-T: NBG3 layer toggle - \-Y: NBG2 layer toggle - \-U: NBG1 layer toggle - \-I: NBG0 layer toggle - \-O: SPRITE toggle - \-K: RBG0 layer toggle - \-W Decodes the graphics for F4 menu. - \-M Stores VDP1 ram contents from a file. - \-N Stores VDP1 ram contents into a file. -*/ - -#include "emu.h" -#include "includes/saturn.h" // FIXME: this is a dependency from devices on MAME - - -#define DEBUG_MODE 0 -#define TEST_FUNCTIONS 0 -#define POPMESSAGE_DEBUG 0 - - -enum -{ - STV_TRANSPARENCY_PEN = 0x0, - STV_TRANSPARENCY_NONE = 0x1, - STV_TRANSPARENCY_ADD_BLEND = 0x2, - STV_TRANSPARENCY_ALPHA = 0x4 -}; - -#if DEBUG_MODE -#define LOG_VDP2 1 -#define LOG_ROZ 0 -#else -#define LOG_VDP2 0 -#define LOG_ROZ 0 -#endif - -/* - --------------------------------------------------|-----------------------------|------------------------------ -| Function | Normal Scroll Screen | Rotation Scroll Screen | -| |-----------------------------|-----------------------------|------------------------------ -| | NBG0 | NBG1 | NBG2 | NBG3 | RBG0 | RBG1 | --------------------------------------------------|-----------------------------|------------------------------ -| Character Colour | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours | -| Count | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " | -| | 2048 " " | 2048 " " | | | 2048 " " | 2048 " " | -| | 32768 " " | 32768 " " | | | 32768 " " | 32768 " " | -| | 16770000 " " | | | | 16770000 " " | 16770000 " " | --------------------------------------------------|-----------------------------|------------------------------ -| Character Size | 1x1 Cells , 2x2 Cells | --------------------------------------------------|-----------------------------|------------------------------ -| Pattern Name | 1 word , 2 words | -| Data Size | | --------------------------------------------------|-----------------------------|------------------------------ -| Plane Size | 1 H x 1 V 1 Pages ; 2 H x 1 V 1 Pages ; 2 H x 2 V Pages | --------------------------------------------------|-----------------------------|------------------------------ -| Plane Count | 4 | 16 | --------------------------------------------------|-----------------------------|------------------------------ -| Bitmap Possible | Yes | No | Yes | No | --------------------------------------------------|-----------------------------|------------------------------ -| Bitmap Size | 512 x 256 | N/A | 512x256 | N/A | -| | 512 x 512 | | 512x512 | | -| | 1024 x 256 | | | | -| | 1024 x 512 | | | | --------------------------------------------------|-----------------------------|------------------------------ -| Scale | 0.25 x - 256 x | None | Any ? | --------------------------------------------------|-----------------------------|------------------------------ -| Rotation | No | Yes | --------------------------------------------------|-----------------------------|-----------------------------| -| Linescroll | Yes | No | --------------------------------------------------|-----------------------------|------------------------------ -| Column Scroll | Yes | No | --------------------------------------------------|-----------------------------|------------------------------ -| Mosaic | Yes | Horizontal Only | --------------------------------------------------|-----------------------------|------------------------------ - -*/ - -/* 180000 - r/w - TVMD - TV Screen Mode - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | DISP | -- | -- | -- | -- | -- | -- | BDCLMD | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | LSMD1 | LSMD0 | VRESO1 | VRESO0 | -- | HRESO2 | HRESO1 | HRESO0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_TVMD (m_vdp2_regs[0x000/2]) - - #define STV_VDP2_DISP ((STV_VDP2_TVMD & 0x8000) >> 15) - #define STV_VDP2_BDCLMD ((STV_VDP2_TVMD & 0x0100) >> 8) - #define STV_VDP2_LSMD ((STV_VDP2_TVMD & 0x00c0) >> 6) - #define STV_VDP2_VRES ((STV_VDP2_TVMD & 0x0030) >> 4) - #define STV_VDP2_HRES ((STV_VDP2_TVMD & 0x0007) >> 0) - -/* 180002 - r/w - EXTEN - External Signal Enable Register - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | EXLTEN | EXSYEN | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | DASEL | EXBGEN | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_EXTEN (m_vdp2_regs[0x002/2]) - - #define STV_VDP2_EXLTEN ((STV_VDP2_EXTEN & 0x0200) >> 9) - -/* 180004 - r/o - TVSTAT - Screen Status - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | EXLTFG | EXSYFG | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | VBLANK | HBLANK | ODD | PAL | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - -/* 180006 - r/w - VRSIZE - VRAM Size - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VRAMSZ | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | VER3 | VER2 | VER1 | VER0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_VRSIZE (m_vdp2_regs[0x006/2]) - - #define STV_VDP2_VRAMSZ ((STV_VDP2_VRSIZE & 0x8000) >> 15) - -/* 180008 - r/o - HCNT - H-Counter - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | HCT9 | HCT8 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | HCT7 | HCT6 | HCT5 | HCT4 | HCT3 | HCT2 | HCT1 | HCT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_HCNT (m_vdp2_regs[0x008/2]) - -/* 18000A - r/o - VCNT - V-Counter - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | VCT9 | VCT8 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCT7 | VCT6 | VCT5 | VCT4 | VCT3 | VCT2 | VCT1 | VCT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_VCNT (m_vdp2_regs[0x00a/2]) - -/* 18000C - RESERVED - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - -/* 18000E - r/w - RAMCTL - RAM Control - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | CRKTE | -- | CRMD1 | CRMD0 | -- | -- | VRBMD | VRAMD | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | RDBSB11 | RDBSB10 | RDBSB01 | RDBSB00 | RDBSA11 | RDBSA10 | RDBSA01 | RDBSA00 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_RAMCTL (m_vdp2_regs[0x00e/2]) - - #define STV_VDP2_CRKTE ((STV_VDP2_RAMCTL & 0x8000) >> 15) - #define STV_VDP2_CRMD ((STV_VDP2_RAMCTL & 0x3000) >> 12) - #define STV_VDP2_RDBSB1 ((STV_VDP2_RAMCTL & 0x00c0) >> 6) - #define STV_VDP2_RDBSB0 ((STV_VDP2_RAMCTL & 0x0030) >> 4) - #define STV_VDP2_RDBSA1 ((STV_VDP2_RAMCTL & 0x000c) >> 2) - #define STV_VDP2_RDBSA0 ((STV_VDP2_RAMCTL & 0x0003) >> 0) - - -/* 180010 - r/w - -CYCA0L - VRAM CYCLE PATTERN (BANK A0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP0A03 | VCP0A02 | VCP0A01 | VCP0A00 | VCP1A03 | VCP1A02 | VCP1A01 | VCP1A00 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP2A03 | VCP2A02 | VCP2A01 | VCP2A00 | VCP3A03 | VCP3A02 | VCP3A01 | VCP3A00 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA0L (m_vdp2_regs[0x010/2]) - -/* 180012 - r/w - -CYCA0U - VRAM CYCLE PATTERN (BANK A0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP4A03 | VCP4A02 | VCP4A01 | VCP4A00 | VCP5A03 | VCP5A02 | VCP5A01 | VCP5A00 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP6A03 | VCP6A02 | VCP6A01 | VCP6A00 | VCP7A03 | VCP7A02 | VCP7A01 | VCP7A00 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA0U (m_vdp2_regs[0x012/2]) - -/* 180014 - r/w - -CYCA1L - VRAM CYCLE PATTERN (BANK A1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP0A13 | VCP0A12 | VCP0A11 | VCP0A10 | VCP1A13 | VCP1A12 | VCP1A11 | VCP1A10 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP2A13 | VCP2A12 | VCP2A11 | VCP2A10 | VCP3A13 | VCP3A12 | VCP3A11 | VCP3A10 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA1L (m_vdp2_regs[0x014/2]) - -/* 180016 - r/w - -CYCA1U - VRAM CYCLE PATTERN (BANK A1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP4A13 | VCP4A12 | VCP4A11 | VCP4A10 | VCP5A13 | VCP5A12 | VCP5A11 | VCP5A10 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP6A13 | VCP6A12 | VCP6A11 | VCP6A10 | VCP7A13 | VCP7A12 | VCP7A11 | VCP7A10 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA1U (m_vdp2_regs[0x016/2]) - -/* 180018 - r/w - -CYCB0L - VRAM CYCLE PATTERN (BANK B0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP0B03 | VCP0B02 | VCP0B01 | VCP0B00 | VCP1B03 | VCP1B02 | VCP1B01 | VCP1B00 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP2B03 | VCP2B02 | VCP2B01 | VCP2B00 | VCP3B03 | VCP3B02 | VCP3B01 | VCP3B00 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA2L (m_vdp2_regs[0x018/2]) - -/* 18001A - r/w - -CYCB0U - VRAM CYCLE PATTERN (BANK B0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP4B03 | VCP4B02 | VCP4B01 | VCP4B00 | VCP5B03 | VCP5B02 | VCP5B01 | VCP5B00 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP6B03 | VCP6B02 | VCP6B01 | VCP6B00 | VCP7B03 | VCP7B02 | VCP7B01 | VCP7B00 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA2U (m_vdp2_regs[0x01a/2]) - -/* 18001C - r/w - -CYCB1L - VRAM CYCLE PATTERN (BANK B1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP0B13 | VCP0B12 | VCP0B11 | VCP0B10 | VCP1B13 | VCP1B12 | VCP1B11 | VCP1B10 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP2B13 | VCP2B12 | VCP2B11 | VCP2B10 | VCP3B13 | VCP3B12 | VCP3B11 | VCP3B10 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA3L (m_vdp2_regs[0x01c/2]) - -/* 18001E - r/w - -CYCB1U - VRAM CYCLE PATTERN (BANK B1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | VCP4B13 | VCP4B12 | VCP4B11 | VCP4B10 | VCP5B13 | VCP5B12 | VCP5B11 | VCP5B10 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | VCP6B13 | VCP6B12 | VCP6B11 | VCP6B10 | VCP7B13 | VCP7B12 | VCP7B11 | VCP7B10 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CYCA3U (m_vdp2_regs[0x01e/2]) - -/* 180020 - r/w - BGON - SCREEN DISPLAY ENABLE - - this register allows each tilemap to be enabled or disabled and also which layers are solid - - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | R0TPON | N3TPON | N2TPON | N1TPON | N0TPON | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | R1ON | R0ON | N3ON | N2ON | N1ON | N0ON | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_BGON (m_vdp2_regs[0x020/2]) - - // NxOn - Layer Enable Register - #define STV_VDP2_xxON ((STV_VDP2_BGON & 0x001f) >> 0) /* to see if anything is enabled */ - - #define STV_VDP2_N0ON ((STV_VDP2_BGON & 0x0001) >> 0) /* N0On = NBG0 Enable */ - #define STV_VDP2_N1ON ((STV_VDP2_BGON & 0x0002) >> 1) /* N1On = NBG1 Enable */ - #define STV_VDP2_N2ON ((STV_VDP2_BGON & 0x0004) >> 2) /* N2On = NBG2 Enable */ - #define STV_VDP2_N3ON ((STV_VDP2_BGON & 0x0008) >> 3) /* N3On = NBG3 Enable */ - #define STV_VDP2_R0ON ((STV_VDP2_BGON & 0x0010) >> 4) /* R0On = RBG0 Enable */ - #define STV_VDP2_R1ON ((STV_VDP2_BGON & 0x0020) >> 5) /* R1On = RBG1 Enable */ - - // NxTPON - Transparency Pen Enable Registers - #define STV_VDP2_N0TPON ((STV_VDP2_BGON & 0x0100) >> 8) /* N0TPON = NBG0 Draw Transparent Pen (as solid) /or/ RBG1 Draw Transparent Pen */ - #define STV_VDP2_N1TPON ((STV_VDP2_BGON & 0x0200) >> 9) /* N1TPON = NBG1 Draw Transparent Pen (as solid) /or/ EXBG Draw Transparent Pen */ - #define STV_VDP2_N2TPON ((STV_VDP2_BGON & 0x0400) >> 10)/* N2TPON = NBG2 Draw Transparent Pen (as solid) */ - #define STV_VDP2_N3TPON ((STV_VDP2_BGON & 0x0800) >> 11)/* N3TPON = NBG3 Draw Transparent Pen (as solid) */ - #define STV_VDP2_R0TPON ((STV_VDP2_BGON & 0x1000) >> 12)/* R0TPON = RBG0 Draw Transparent Pen (as solid) */ - -/* -180022 - MZCTL - Mosaic Control -bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MZCTL (m_vdp2_regs[0x022/2]) - - #define STV_VDP2_MZSZV ((STV_VDP2_MZCTL & 0xf000) >> 12) - #define STV_VDP2_MZSZH ((STV_VDP2_MZCTL & 0x0f00) >> 8) - #define STV_VDP2_R0MZE ((STV_VDP2_MZCTL & 0x0010) >> 4) - #define STV_VDP2_N3MZE ((STV_VDP2_MZCTL & 0x0008) >> 3) - #define STV_VDP2_N2MZE ((STV_VDP2_MZCTL & 0x0004) >> 2) - #define STV_VDP2_N1MZE ((STV_VDP2_MZCTL & 0x0002) >> 1) - #define STV_VDP2_N0MZE ((STV_VDP2_MZCTL & 0x0001) >> 0) - -/*180024 - Special Function Code Select - -*/ - - #define STV_VDP2_SFSEL (m_vdp2_regs[0x024/2]) - -/*180026 - Special Function Code - -*/ - - #define STV_VDP2_SFCODE (m_vdp2_regs[0x026/2]) - - -/* -180028 - CHCTLA - Character Control (NBG0, NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | N1CHCN1 | N1CHCN0 | N1BMSZ1 | N1BMSZ0 | N1BMEN | N1CHSZ | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | N0CHCN2 | N0CHCN1 | N0CHCN0 | N0BMSZ1 | N0BMSZ0 | N0BMEN | N0CHSZ | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CHCTLA (m_vdp2_regs[0x028/2]) - -/* -------------------------- NBG0 Character Control Registers -------------------------- */ - -/* N0CHCNx NBG0 (or RGB1) Colour Depth - 000 - 16 Colours - 001 - 256 Colours - 010 - 2048 Colours - 011 - 32768 Colours (RGB5) - 100 - 16770000 Colours (RGB8) - 101 - invalid - 110 - invalid - 111 - invalid */ - #define STV_VDP2_N0CHCN ((STV_VDP2_CHCTLA & 0x0070) >> 4) - -/* N0BMSZx - NBG0 Bitmap Size *guessed* - 00 - 512 x 256 - 01 - 512 x 512 - 10 - 1024 x 256 - 11 - 1024 x 512 */ - #define STV_VDP2_N0BMSZ ((STV_VDP2_CHCTLA & 0x000c) >> 2) - -/* N0BMEN - NBG0 Bitmap Enable - 0 - use cell mode - 1 - use bitmap mode */ - #define STV_VDP2_N0BMEN ((STV_VDP2_CHCTLA & 0x0002) >> 1) - -/* N0CHSZ - NBG0 Character (Tile) Size - 0 - 1 cell x 1 cell (8x8) - 1 - 2 cells x 2 cells (16x16) */ - #define STV_VDP2_N0CHSZ ((STV_VDP2_CHCTLA & 0x0001) >> 0) - -/* -------------------------- NBG1 Character Control Registers -------------------------- */ - -/* N1CHCNx - NBG1 (or EXB1) Colour Depth - 00 - 16 Colours - 01 - 256 Colours - 10 - 2048 Colours - 11 - 32768 Colours (RGB5) */ - #define STV_VDP2_N1CHCN ((STV_VDP2_CHCTLA & 0x3000) >> 12) - -/* N1BMSZx - NBG1 Bitmap Size *guessed* - 00 - 512 x 256 - 01 - 512 x 512 - 10 - 1024 x 256 - 11 - 1024 x 512 */ - #define STV_VDP2_N1BMSZ ((STV_VDP2_CHCTLA & 0x0c00) >> 10) - -/* N1BMEN - NBG1 Bitmap Enable - 0 - use cell mode - 1 - use bitmap mode */ - #define STV_VDP2_N1BMEN ((STV_VDP2_CHCTLA & 0x0200) >> 9) - -/* N1CHSZ - NBG1 Character (Tile) Size - 0 - 1 cell x 1 cell (8x8) - 1 - 2 cells x 2 cells (16x16) */ - #define STV_VDP2_N1CHSZ ((STV_VDP2_CHCTLA & 0x0100) >> 8) - -/* -18002A - CHCTLB - Character Control (NBG2, NBG1, RBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | R0CHCN2 | R0CHCN1 | R0CHCN0 | -- | R0BMSZ | R0BMEN | R0CHSZ | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | N3CHCN | N3CHSZ | -- | -- | N2CHCN | N2CHSZ | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CHCTLB (m_vdp2_regs[0x02a/2]) - -/* -------------------------- RBG0 Character Control Registers -------------------------- */ - - -/* R0CHCNx RBG0 Colour Depth - 000 - 16 Colours - 001 - 256 Colours - 010 - 2048 Colours - 011 - 32768 Colours (RGB5) - 100 - 16770000 Colours (RGB8) - 101 - invalid - 110 - invalid - 111 - invalid */ - #define STV_VDP2_R0CHCN ((STV_VDP2_CHCTLB & 0x7000) >> 12) - -/* R0BMSZx - RBG0 Bitmap Size *guessed* - 00 - 512 x 256 - 01 - 512 x 512 */ - #define STV_VDP2_R0BMSZ ((STV_VDP2_CHCTLB & 0x0400) >> 10) - -/* R0BMEN - RBG0 Bitmap Enable - 0 - use cell mode - 1 - use bitmap mode */ - #define STV_VDP2_R0BMEN ((STV_VDP2_CHCTLB & 0x0200) >> 9) - -/* R0CHSZ - RBG0 Character (Tile) Size - 0 - 1 cell x 1 cell (8x8) - 1 - 2 cells x 2 cells (16x16) */ - #define STV_VDP2_R0CHSZ ((STV_VDP2_CHCTLB & 0x0100) >> 8) - - #define STV_VDP2_N3CHCN ((STV_VDP2_CHCTLB & 0x0020) >> 5) - #define STV_VDP2_N3CHSZ ((STV_VDP2_CHCTLB & 0x0010) >> 4) - #define STV_VDP2_N2CHCN ((STV_VDP2_CHCTLB & 0x0002) >> 1) - #define STV_VDP2_N2CHSZ ((STV_VDP2_CHCTLB & 0x0001) >> 0) - - -/* -18002C - BMPNA - Bitmap Palette Number (NBG0, NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_BMPNA (m_vdp2_regs[0x02c/2]) - - #define STV_VDP2_N1BMP ((STV_VDP2_BMPNA & 0x0700) >> 8) - #define STV_VDP2_N0BMP ((STV_VDP2_BMPNA & 0x0007) >> 0) - -/* 18002E - Bitmap Palette Number (RBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_BMPNB (m_vdp2_regs[0x02e/2]) - - #define STV_VDP2_R0BMP ((STV_VDP2_BMPNB & 0x0007) >> 0) - -/* 180030 - PNCN0 - Pattern Name Control (NBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | N0PNB | N0CNSM | -- | -- | -- | -- | N0SPR | N0SCC | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | N0SPLT6 | N0SPLT5 | N0SPLT4 | N0SPCN4 | N0SPCN3 | N0SPCN2 | N0SPCN1 | N0SPCN0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PNCN0 (m_vdp2_regs[0x030/2]) - -/* Pattern Data Size - 0 = 2 bytes - 1 = 1 byte */ - #define STV_VDP2_N0PNB ((STV_VDP2_PNCN0 & 0x8000) >> 15) - -/* Character Number Supplement (in 1 byte mode) - 0 = Character Number = 10bits + 2bits for flip - 1 = Character Number = 12 bits, no flip */ - #define STV_VDP2_N0CNSM ((STV_VDP2_PNCN0 & 0x4000) >> 14) - -/* NBG0 Special Priority Register (in 1 byte mode) */ - #define STV_VDP2_N0SPR ((STV_VDP2_PNCN0 & 0x0200) >> 9) - -/* NBG0 Special Colour Control Register (in 1 byte mode) */ - #define STV_VDP2_N0SCC ((STV_VDP2_PNCN0 & 0x0100) >> 8) - -/* Supplementary Palette Bits (in 1 byte mode) */ - #define STV_VDP2_N0SPLT ((STV_VDP2_PNCN0 & 0x00e0) >> 5) - -/* Supplementary Character Bits (in 1 byte mode) */ - #define STV_VDP2_N0SPCN ((STV_VDP2_PNCN0 & 0x001f) >> 0) - -/* 180032 - Pattern Name Control (NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PNCN1 (m_vdp2_regs[0x032/2]) - -/* Pattern Data Size - 0 = 2 bytes - 1 = 1 byte */ - #define STV_VDP2_N1PNB ((STV_VDP2_PNCN1 & 0x8000) >> 15) - -/* Character Number Supplement (in 1 byte mode) - 0 = Character Number = 10bits + 2bits for flip - 1 = Character Number = 12 bits, no flip */ - #define STV_VDP2_N1CNSM ((STV_VDP2_PNCN1 & 0x4000) >> 14) - -/* NBG0 Special Priority Register (in 1 byte mode) */ - #define STV_VDP2_N1SPR ((STV_VDP2_PNCN1 & 0x0200) >> 9) - -/* NBG0 Special Colour Control Register (in 1 byte mode) */ - #define STV_VDP2_N1SCC ((STV_VDP2_PNCN1 & 0x0100) >> 8) - -/* Supplementary Palette Bits (in 1 byte mode) */ - #define STV_VDP2_N1SPLT ((STV_VDP2_PNCN1 & 0x00e0) >> 5) - -/* Supplementary Character Bits (in 1 byte mode) */ - #define STV_VDP2_N1SPCN ((STV_VDP2_PNCN1 & 0x001f) >> 0) - - -/* 180034 - Pattern Name Control (NBG2) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PNCN2 (m_vdp2_regs[0x034/2]) - -/* Pattern Data Size - 0 = 2 bytes - 1 = 1 byte */ - #define STV_VDP2_N2PNB ((STV_VDP2_PNCN2 & 0x8000) >> 15) - -/* Character Number Supplement (in 1 byte mode) - 0 = Character Number = 10bits + 2bits for flip - 1 = Character Number = 12 bits, no flip */ - #define STV_VDP2_N2CNSM ((STV_VDP2_PNCN2 & 0x4000) >> 14) - -/* NBG0 Special Priority Register (in 1 byte mode) */ - #define STV_VDP2_N2SPR ((STV_VDP2_PNCN2 & 0x0200) >> 9) - -/* NBG0 Special Colour Control Register (in 1 byte mode) */ - #define STV_VDP2_N2SCC ((STV_VDP2_PNCN2 & 0x0100) >> 8) - -/* Supplementary Palette Bits (in 1 byte mode) */ - #define STV_VDP2_N2SPLT ((STV_VDP2_PNCN2 & 0x00e0) >> 5) - -/* Supplementary Character Bits (in 1 byte mode) */ - #define STV_VDP2_N2SPCN ((STV_VDP2_PNCN2 & 0x001f) >> 0) - - -/* 180036 - Pattern Name Control (NBG3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | N3PNB | N3CNSM | -- | -- | -- | -- | N3SPR | N3SCC | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | N3SPLT6 | N3SPLT5 | N3SPLT4 | N3SPCN4 | N3SPCN3 | N3SPCN2 | N3SPCN1 | N3SPCN0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PNCN3 (m_vdp2_regs[0x036/2]) - -/* Pattern Data Size - 0 = 2 bytes - 1 = 1 byte */ - #define STV_VDP2_N3PNB ((STV_VDP2_PNCN3 & 0x8000) >> 15) - -/* Character Number Supplement (in 1 byte mode) - 0 = Character Number = 10bits + 2bits for flip - 1 = Character Number = 12 bits, no flip */ - #define STV_VDP2_N3CNSM ((STV_VDP2_PNCN3 & 0x4000) >> 14) - -/* NBG0 Special Priority Register (in 1 byte mode) */ - #define STV_VDP2_N3SPR ((STV_VDP2_PNCN3 & 0x0200) >> 9) - -/* NBG0 Special Colour Control Register (in 1 byte mode) */ - #define STV_VDP2_N3SCC ((STV_VDP2_PNCN3 & 0x0100) >> 8) - -/* Supplementary Palette Bits (in 1 byte mode) */ - #define STV_VDP2_N3SPLT ((STV_VDP2_PNCN3 & 0x00e0) >> 5) - -/* Supplementary Character Bits (in 1 byte mode) */ - #define STV_VDP2_N3SPCN ((STV_VDP2_PNCN3 & 0x001f) >> 0) - - -/* 180038 - Pattern Name Control (RBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PNCR (m_vdp2_regs[0x038/2]) - -/* Pattern Data Size - 0 = 2 bytes - 1 = 1 byte */ - #define STV_VDP2_R0PNB ((STV_VDP2_PNCR & 0x8000) >> 15) - -/* Character Number Supplement (in 1 byte mode) - 0 = Character Number = 10bits + 2bits for flip - 1 = Character Number = 12 bits, no flip */ - #define STV_VDP2_R0CNSM ((STV_VDP2_PNCR & 0x4000) >> 14) - -/* NBG0 Special Priority Register (in 1 byte mode) */ - #define STV_VDP2_R0SPR ((STV_VDP2_PNCR & 0x0200) >> 9) - -/* NBG0 Special Colour Control Register (in 1 byte mode) */ - #define STV_VDP2_R0SCC ((STV_VDP2_PNCR & 0x0100) >> 8) - -/* Supplementary Palette Bits (in 1 byte mode) */ - #define STV_VDP2_R0SPLT ((STV_VDP2_PNCR & 0x00e0) >> 5) - -/* Supplementary Character Bits (in 1 byte mode) */ - #define STV_VDP2_R0SPCN ((STV_VDP2_PNCR & 0x001f) >> 0) - -/* 18003A - PLSZ - Plane Size - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | N3PLSZ1 | N3PLSZ0 | -- | -- | N1PLSZ1 | N1PLSZ0 | N0PLSZ1 | N0PLSZ0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PLSZ (m_vdp2_regs[0x03a/2]) - - /* NBG0 Plane Size - 00 1H Page x 1V Page - 01 2H Pages x 1V Page - 10 invalid - 11 2H Pages x 2V Pages */ - #define STV_VDP2_RBOVR ((STV_VDP2_PLSZ & 0xc000) >> 14) - #define STV_VDP2_RBPLSZ ((STV_VDP2_PLSZ & 0x3000) >> 12) - #define STV_VDP2_RAOVR ((STV_VDP2_PLSZ & 0x0c00) >> 10) - #define STV_VDP2_RAPLSZ ((STV_VDP2_PLSZ & 0x0300) >> 8) - #define STV_VDP2_N3PLSZ ((STV_VDP2_PLSZ & 0x00c0) >> 6) - #define STV_VDP2_N2PLSZ ((STV_VDP2_PLSZ & 0x0030) >> 4) - #define STV_VDP2_N1PLSZ ((STV_VDP2_PLSZ & 0x000c) >> 2) - #define STV_VDP2_N0PLSZ ((STV_VDP2_PLSZ & 0x0003) >> 0) - -/* 18003C - MPOFN - Map Offset (NBG0, NBG1, NBG2, NBG3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | N3MP8 | N3MP7 | N3MP6 | -- | N2MP8 | N2MP7 | N2MP6 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | N1MP8 | N1MP7 | N1MP6 | -- | N0MP8 | N0MP7 | N0MP6 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPOFN_ (m_vdp2_regs[0x03c/2]) - - /* Higher 3 bits of the map offset for each layer */ - #define STV_VDP2_N3MP_ ((STV_VDP2_MPOFN_ & 0x3000) >> 12) - #define STV_VDP2_N2MP_ ((STV_VDP2_MPOFN_ & 0x0300) >> 8) - #define STV_VDP2_N1MP_ ((STV_VDP2_MPOFN_ & 0x0030) >> 4) - #define STV_VDP2_N0MP_ ((STV_VDP2_MPOFN_ & 0x0003) >> 0) - - - - -/* 18003E - Map Offset (Rotation Parameter A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPOFR_ (m_vdp2_regs[0x03e/2]) - - #define STV_VDP2_RBMP_ ((STV_VDP2_MPOFR_ & 0x0030) >> 4) - #define STV_VDP2_RAMP_ ((STV_VDP2_MPOFR_ & 0x0003) >> 0) - -/* 180040 - MPABN0 - Map (NBG0, Plane A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | N0MPB5 | N0MPB4 | N0MPB3 | N0MPB2 | N0MPB1 | N0MPB0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | N0MPA5 | N0MPA4 | N0MPA3 | N0MPA2 | N0MPA1 | N0MPA0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPABN0 (m_vdp2_regs[0x040/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */ - #define STV_VDP2_N0MPB ((STV_VDP2_MPABN0 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */ - #define STV_VDP2_N0MPA ((STV_VDP2_MPABN0 & 0x003f) >> 0) - - -/* 180042 - MPCDN0 - (NBG0, Plane C,D) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | N0MPD5 | N0MPD4 | N0MPD3 | N0MPD2 | N0MPD1 | N0MPD0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | N0MPC5 | N0MPC4 | N0MPC3 | N0MPC2 | N0MPC1 | N0MPC0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPCDN0 (m_vdp2_regs[0x042/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */ - #define STV_VDP2_N0MPD ((STV_VDP2_MPCDN0 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */ - #define STV_VDP2_N0MPC ((STV_VDP2_MPCDN0 & 0x003f) >> 0) - - -/* 180044 - Map (NBG1, Plane A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPABN1 (m_vdp2_regs[0x044/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */ - #define STV_VDP2_N1MPB ((STV_VDP2_MPABN1 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */ - #define STV_VDP2_N1MPA ((STV_VDP2_MPABN1 & 0x003f) >> 0) - -/* 180046 - Map (NBG1, Plane C,D) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPCDN1 (m_vdp2_regs[0x046/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */ - #define STV_VDP2_N1MPD ((STV_VDP2_MPCDN1 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */ - #define STV_VDP2_N1MPC ((STV_VDP2_MPCDN1 & 0x003f) >> 0) - - -/* 180048 - Map (NBG2, Plane A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPABN2 (m_vdp2_regs[0x048/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG2 */ - #define STV_VDP2_N2MPB ((STV_VDP2_MPABN2 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG2 */ - #define STV_VDP2_N2MPA ((STV_VDP2_MPABN2 & 0x003f) >> 0) - -/* 18004a - Map (NBG2, Plane C,D) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPCDN2 (m_vdp2_regs[0x04a/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG2 */ - #define STV_VDP2_N2MPD ((STV_VDP2_MPCDN2 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG2 */ - #define STV_VDP2_N2MPC ((STV_VDP2_MPCDN2 & 0x003f) >> 0) - -/* 18004c - Map (NBG3, Plane A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPABN3 (m_vdp2_regs[0x04c/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */ - #define STV_VDP2_N3MPB ((STV_VDP2_MPABN3 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */ - #define STV_VDP2_N3MPA ((STV_VDP2_MPABN3 & 0x003f) >> 0) - - -/* 18004e - Map (NBG3, Plane C,D) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPCDN3 (m_vdp2_regs[0x04e/2]) - - /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */ - #define STV_VDP2_N3MPD ((STV_VDP2_MPCDN3 & 0x3f00) >> 8) - - /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */ - #define STV_VDP2_N3MPC ((STV_VDP2_MPCDN3 & 0x003f) >> 0) - -/* 180050 - Map (Rotation Parameter A, Plane A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPABRA (m_vdp2_regs[0x050/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */ - #define STV_VDP2_RAMPB ((STV_VDP2_MPABRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */ - #define STV_VDP2_RAMPA ((STV_VDP2_MPABRA & 0x003f) >> 0) - - - -/* 180052 - Map (Rotation Parameter A, Plane C,D) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPCDRA (m_vdp2_regs[0x052/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */ - #define STV_VDP2_RAMPD ((STV_VDP2_MPCDRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */ - #define STV_VDP2_RAMPC ((STV_VDP2_MPCDRA & 0x003f) >> 0) - -/* 180054 - Map (Rotation Parameter A, Plane E,F) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPEFRA (m_vdp2_regs[0x054/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */ - #define STV_VDP2_RAMPF ((STV_VDP2_MPEFRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */ - #define STV_VDP2_RAMPE ((STV_VDP2_MPEFRA & 0x003f) >> 0) - -/* 180056 - Map (Rotation Parameter A, Plane G,H) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPGHRA (m_vdp2_regs[0x056/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */ - #define STV_VDP2_RAMPH ((STV_VDP2_MPGHRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */ - #define STV_VDP2_RAMPG ((STV_VDP2_MPGHRA & 0x003f) >> 0) - -/* 180058 - Map (Rotation Parameter A, Plane I,J) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPIJRA (m_vdp2_regs[0x058/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */ - #define STV_VDP2_RAMPJ ((STV_VDP2_MPIJRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane I of Tilemap RBG0 */ - #define STV_VDP2_RAMPI ((STV_VDP2_MPIJRA & 0x003f) >> 0) - -/* 18005a - Map (Rotation Parameter A, Plane K,L) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPKLRA (m_vdp2_regs[0x05a/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */ - #define STV_VDP2_RAMPL ((STV_VDP2_MPKLRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */ - #define STV_VDP2_RAMPK ((STV_VDP2_MPKLRA & 0x003f) >> 0) - -/* 18005c - Map (Rotation Parameter A, Plane M,N) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPMNRA (m_vdp2_regs[0x05c/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */ - #define STV_VDP2_RAMPN ((STV_VDP2_MPMNRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */ - #define STV_VDP2_RAMPM ((STV_VDP2_MPMNRA & 0x003f) >> 0) - -/* 18005e - Map (Rotation Parameter A, Plane O,P) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_MPOPRA (m_vdp2_regs[0x05e/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */ - #define STV_VDP2_RAMPP ((STV_VDP2_MPOPRA & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */ - #define STV_VDP2_RAMPO ((STV_VDP2_MPOPRA & 0x003f) >> 0) - -/* 180060 - Map (Rotation Parameter B, Plane A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPABRB (m_vdp2_regs[0x060/2]) - - /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */ - #define STV_VDP2_RBMPB ((STV_VDP2_MPABRB & 0x3f00) >> 8) - - /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */ - #define STV_VDP2_RBMPA ((STV_VDP2_MPABRB & 0x003f) >> 0) - - -/* 180062 - Map (Rotation Parameter B, Plane C,D) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPCDRB (m_vdp2_regs[0x062/2]) - - /* R0MPD5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */ - #define STV_VDP2_RBMPD ((STV_VDP2_MPCDRB & 0x3f00) >> 8) - - /* R0MPc5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */ - #define STV_VDP2_RBMPC ((STV_VDP2_MPCDRB & 0x003f) >> 0) - -/* 180064 - Map (Rotation Parameter B, Plane E,F) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPEFRB (m_vdp2_regs[0x064/2]) - - /* R0MPF5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */ - #define STV_VDP2_RBMPF ((STV_VDP2_MPEFRB & 0x3f00) >> 8) - - /* R0MPE5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */ - #define STV_VDP2_RBMPE ((STV_VDP2_MPEFRB & 0x003f) >> 0) - -/* 180066 - Map (Rotation Parameter B, Plane G,H) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPGHRB (m_vdp2_regs[0x066/2]) - - /* R0MPH5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */ - #define STV_VDP2_RBMPH ((STV_VDP2_MPGHRB & 0x3f00) >> 8) - - /* R0MPG5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */ - #define STV_VDP2_RBMPG ((STV_VDP2_MPGHRB & 0x003f) >> 0) - -/* 180068 - Map (Rotation Parameter B, Plane I,J) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPIJRB (m_vdp2_regs[0x068/2]) - - /* R0MPJ5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */ - #define STV_VDP2_RBMPJ ((STV_VDP2_MPIJRB & 0x3f00) >> 8) - - /* R0MPI5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */ - #define STV_VDP2_RBMPI ((STV_VDP2_MPIJRB & 0x003f) >> 0) - -/* 18006a - Map (Rotation Parameter B, Plane K,L) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPKLRB (m_vdp2_regs[0x06a/2]) - - /* R0MPL5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */ - #define STV_VDP2_RBMPL ((STV_VDP2_MPKLRB & 0x3f00) >> 8) - - /* R0MPK5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */ - #define STV_VDP2_RBMPK ((STV_VDP2_MPKLRB & 0x003f) >> 0) - -/* 18006c - Map (Rotation Parameter B, Plane M,N) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPMNRB (m_vdp2_regs[0x06c/2]) - - /* R0MPN5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */ - #define STV_VDP2_RBMPN ((STV_VDP2_MPMNRB & 0x3f00) >> 8) - - /* R0MPM5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */ - #define STV_VDP2_RBMPM ((STV_VDP2_MPMNRB & 0x003f) >> 0) - -/* 18006e - Map (Rotation Parameter B, Plane O,P) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_MPOPRB (m_vdp2_regs[0x06e/2]) - - /* R0MPP5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */ - #define STV_VDP2_RBMPP ((STV_VDP2_MPOPRB & 0x3f00) >> 8) - - /* R0MPO5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */ - #define STV_VDP2_RBMPO ((STV_VDP2_MPOPRB & 0x003f) >> 0) - -/* 180070 - SCXIN0 - Screen Scroll (NBG0, Horizontal Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCXIN0 (m_vdp2_regs[0x070/2]) - - -/* 180072 - Screen Scroll (NBG0, Horizontal Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCXDN0 (m_vdp2_regs[0x072/2]) - -/* 180074 - SCYIN0 - Screen Scroll (NBG0, Vertical Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_SCYIN0 (m_vdp2_regs[0x074/2]) - - -/* 180076 - Screen Scroll (NBG0, Vertical Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCYDN0 (m_vdp2_regs[0x076/2]) - -/* 180078 - Coordinate Inc (NBG0, Horizontal Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMXIN0 (m_vdp2_regs[0x078/2]) - - #define STV_VDP2_N0ZMXI ((STV_VDP2_ZMXIN0 & 0x0007) >> 0) - -/* 18007a - Coordinate Inc (NBG0, Horizontal Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMXDN0 (m_vdp2_regs[0x07a/2]) - - #define STV_VDP2_N0ZMXD ((STV_VDP2_ZMXDN0 >> 8)& 0xff) - #define STV_VDP2_ZMXN0 (((STV_VDP2_N0ZMXI<<16) | (STV_VDP2_N0ZMXD<<8)) & 0x0007ff00) - - -/* 18007c - Coordinate Inc (NBG0, Vertical Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMYIN0 (m_vdp2_regs[0x07c/2]) - - #define STV_VDP2_N0ZMYI ((STV_VDP2_ZMYIN0 & 0x0007) >> 0) - -/* 18007e - Coordinate Inc (NBG0, Vertical Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMYDN0 (m_vdp2_regs[0x07e/2]) - - #define STV_VDP2_N0ZMYD ((STV_VDP2_ZMYDN0 >> 8)& 0xff) - #define STV_VDP2_ZMYN0 (((STV_VDP2_N0ZMYI<<16) | (STV_VDP2_N0ZMYD<<8)) & 0x0007ff00) - -/* 180080 - SCXIN1 - Screen Scroll (NBG1, Horizontal Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCXIN1 (m_vdp2_regs[0x080/2]) - -/* 180082 - Screen Scroll (NBG1, Horizontal Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCXDN1 (m_vdp2_regs[0x082/2]) - -/* 180084 - SCYIN1 - Screen Scroll (NBG1, Vertical Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCYIN1 (m_vdp2_regs[0x084/2]) - -/* 180086 - Screen Scroll (NBG1, Vertical Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCYDN1 (m_vdp2_regs[0x086/2]) - -/* 180088 - Coordinate Inc (NBG1, Horizontal Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMXIN1 (m_vdp2_regs[0x088/2]) - - #define STV_VDP2_N1ZMXI ((STV_VDP2_ZMXIN1 & 0x0007) >> 0) - -/* 18008a - Coordinate Inc (NBG1, Horizontal Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMXDN1 (m_vdp2_regs[0x08a/2]) - - #define STV_VDP2_N1ZMXD ((STV_VDP2_ZMXDN1 >> 8)& 0xff) - #define STV_VDP2_ZMXN1 (((STV_VDP2_N1ZMXI<<16) | (STV_VDP2_N1ZMXD<<8)) & 0x0007ff00) - -/* 18008c - Coordinate Inc (NBG1, Vertical Integer Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMYIN1 (m_vdp2_regs[0x08c/2]) - - #define STV_VDP2_N1ZMYI ((STV_VDP2_ZMYIN1 & 0x0007) >> 0) - -/* 18008e - Coordinate Inc (NBG1, Vertical Fractional Part) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMYDN1 (m_vdp2_regs[0x08e/2]) - - #define STV_VDP2_N1ZMYD ((STV_VDP2_ZMYDN1 >> 8)& 0xff) - #define STV_VDP2_ZMYN1 (((STV_VDP2_N1ZMYI<<16) | (STV_VDP2_N1ZMYD<<8)) & 0x007ff00) - -/* 180090 - SCXN2 - Screen Scroll (NBG2, Horizontal) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCXN2 (m_vdp2_regs[0x090/2]) - -/* 180092 - SCYN2 - Screen Scroll (NBG2, Vertical) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCYN2 (m_vdp2_regs[0x092/2]) - -/* 180094 - SCXN3 - Screen Scroll (NBG3, Horizontal) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCXN3 (m_vdp2_regs[0x094/2]) - -/* 180096 - SCYN3 - Screen Scroll (NBG3, Vertical) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCYN3 (m_vdp2_regs[0x096/2]) - -/* 180098 - Reduction Enable - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | N1ZMQT | N1ZMHF | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | N0ZMQT | N0ZMHF | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_ZMCTL (m_vdp2_regs[0x098/2]) - - #define STV_VDP2_N1ZMQT ((STV_VDP2_ZMCTL & 0x0200) >> 9) - #define STV_VDP2_N1ZMHF ((STV_VDP2_ZMCTL & 0x0100) >> 8) - #define STV_VDP2_N0ZMQT ((STV_VDP2_ZMCTL & 0x0002) >> 1) - #define STV_VDP2_N0ZMHF ((STV_VDP2_ZMCTL & 0x0001) >> 0) - -/* 18009a - Line and Vertical Cell Scroll Control (NBG0, NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SCRCTL (m_vdp2_regs[0x09a/2]) - - #define STV_VDP2_N1LSS ((STV_VDP2_SCRCTL & 0x3000) >> 12) - #define STV_VDP2_N1LZMX ((STV_VDP2_SCRCTL & 0x0800) >> 11) - #define STV_VDP2_N1LSCY ((STV_VDP2_SCRCTL & 0x0400) >> 10) - #define STV_VDP2_N1LSCX ((STV_VDP2_SCRCTL & 0x0200) >> 9) - #define STV_VDP2_N1VCSC ((STV_VDP2_SCRCTL & 0x0100) >> 8) - #define STV_VDP2_N0LSS ((STV_VDP2_SCRCTL & 0x0030) >> 4) - #define STV_VDP2_N0LZMX ((STV_VDP2_SCRCTL & 0x0008) >> 3) - #define STV_VDP2_N0LSCY ((STV_VDP2_SCRCTL & 0x0004) >> 2) - #define STV_VDP2_N0LSCX ((STV_VDP2_SCRCTL & 0x0002) >> 1) - #define STV_VDP2_N0VCSC ((STV_VDP2_SCRCTL & 0x0001) >> 0) - -/* 18009c - Vertical Cell Table Address (NBG0, NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_VCSTAU (m_vdp2_regs[0x09c/2] & 7) - - -/* 18009e - Vertical Cell Table Address (NBG0, NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_VCSTAL (m_vdp2_regs[0x09e/2]) - -/* 1800a0 - LSTA0U - Line Scroll Table Address (NBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - /*bit 2 unused when VRAM = 4 Mbits*/ - #define STV_VDP2_LSTA0U (m_vdp2_regs[0x0a0/2] & 7) - -/* 1800a2 - LSTA0L - Line Scroll Table Address (NBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LSTA0L (m_vdp2_regs[0x0a2/2]) - -/* 1800a4 - LSTA1U - Line Scroll Table Address (NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - /*bit 2 unused when VRAM = 4 Mbits*/ - #define STV_VDP2_LSTA1U (m_vdp2_regs[0x0a4/2] & 7) - -/* 1800a6 - LSTA1L - Line Scroll Table Address (NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LSTA1L (m_vdp2_regs[0x0a6/2]) - -/* 1800a8 - LCTAU - Line Colour Screen Table Address - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LCTAU (m_vdp2_regs[0x0a8/2]) - #define STV_VDP2_LCCLMD ((STV_VDP2_LCTAU & 0x8000) >> 15) - -/* 1800aa - LCTAL - Line Colour Screen Table Address - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_LCTAL (m_vdp2_regs[0x0aa/2]) - - #define STV_VDP2_LCTA (((STV_VDP2_LCTAU & 0x0007) << 16) | (STV_VDP2_LCTAL & 0xffff)) - -/* 1800ac - Back Screen Table Address - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | BKCLMD | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | BKTA18 | BKTA17 | BKTA16 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_BKTAU (m_vdp2_regs[0x0ac/2]) - - #define STV_VDP2_BKCLMD ((STV_VDP2_BKTAU & 0x8000) >> 15) - - -/* 1800ae - Back Screen Table Address - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | BKTA15 | BKTA14 | BKTA13 | BKTA12 | BKTA11 | BKTA10 | BKTA9 | BKTA8 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | BKTA7 | BKTA7 | BKTA6 | BKTA5 | BKTA4 | BKTA3 | BKTA2 | BKTA0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_BKTAL (m_vdp2_regs[0x0ae/2]) - - #define STV_VDP2_BKTA (((STV_VDP2_BKTAU & 0x0007) << 16) | (STV_VDP2_BKTAL & 0xffff)) - -/* 1800b0 - RPMD - Rotation Parameter Mode - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_RPMD ((m_vdp2_regs[0x0b0/2]) & 0x0003) - -/* 1800b2 - RPRCTL - Rotation Parameter Read Control - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | RBKASTRE | RBYSTRE | RBXSTRE | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | RAKASTRE | RAYSTRE | RBXSTRE | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_RPRCTL (m_vdp2_regs[0x0b2/2]) - #define STV_VDP2_RBKASTRE ((STV_VDP2_RPRCTL & 0x0400) >> 10) - #define STV_VDP2_RBYSTRE ((STV_VDP2_RPRCTL & 0x0200) >> 9) - #define STV_VDP2_RBXSTRE ((STV_VDP2_RPRCTL & 0x0100) >> 8) - #define STV_VDP2_RAKASTRE ((STV_VDP2_RPRCTL & 0x0004) >> 2) - #define STV_VDP2_RAYSTRE ((STV_VDP2_RPRCTL & 0x0002) >> 1) - #define STV_VDP2_RAXSTRE ((STV_VDP2_RPRCTL & 0x0001) >> 0) - -/* 1800b4 - KTCTL - Coefficient Table Control - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | RBKLCE | RBKMD1 | RBKMD0 | RBKDBS | RBKTE | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | RAKLCE | RAKMD1 | RAKMD0 | RAKDBS | RAKTE | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_KTCTL (m_vdp2_regs[0x0b4/2]) - #define STV_VDP2_RBUNK ((STV_VDP2_KTCTL & 0x6000) >> 13) - #define STV_VDP2_RBKLCE ((STV_VDP2_KTCTL & 0x1000) >> 12) - #define STV_VDP2_RBKMD ((STV_VDP2_KTCTL & 0x0c00) >> 10) - #define STV_VDP2_RBKDBS ((STV_VDP2_KTCTL & 0x0200) >> 9) - #define STV_VDP2_RBKTE ((STV_VDP2_KTCTL & 0x0100) >> 8) - #define STV_VDP2_RAUNK ((STV_VDP2_KTCTL & 0x0060) >> 5) - #define STV_VDP2_RAKLCE ((STV_VDP2_KTCTL & 0x0010) >> 4) - #define STV_VDP2_RAKMD ((STV_VDP2_KTCTL & 0x000c) >> 2) - #define STV_VDP2_RAKDBS ((STV_VDP2_KTCTL & 0x0002) >> 1) - #define STV_VDP2_RAKTE ((STV_VDP2_KTCTL & 0x0001) >> 0) - -/* 1800b6 - KTAOF - Coefficient Table Address Offset (Rotation Parameter A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | RBKTAOS2 | RBKTAOS1 | RBKTAOS0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | RAKTAOS2 | RAKTAOS1 | RAKTAOS0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_KTAOF (m_vdp2_regs[0x0b6/2]) - #define STV_VDP2_RBKTAOS ((STV_VDP2_KTAOF & 0x0700) >> 8) - #define STV_VDP2_RAKTAOS ((STV_VDP2_KTAOF & 0x0007) >> 0) - -/* 1800b8 - OVPNRA - Screen Over Pattern Name (Rotation Parameter A) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_OVPNRA (m_vdp2_regs[0x0b8/2]) - -/* 1800ba - Screen Over Pattern Name (Rotation Parameter B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_OVPNRB (m_vdp2_regs[0x0ba/2]) - -/* 1800bc - RPTAU - Rotation Parameter Table Address (Rotation Parameter A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | RPTA18 | RPTA17 | RPTA16 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_RPTAU (m_vdp2_regs[0x0bc/2] & 7) - -/* 1800be - RPTAL - Rotation Parameter Table Address (Rotation Parameter A,B) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | RPTA15 | RPTA14 | RPTA13 | RPTA12 | RPTA11 | RPTA10 | RPTA9 | RPTA8 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | RPTA7 | RPTA6 | RPTA5 | RPTA4 | RPTA3 | RPTA2 | RPTA1 | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_RPTAL (m_vdp2_regs[0x0be/2] & 0x0000ffff) - -/* 1800c0 - Window Position (W0, Horizontal Start Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPSX0 (m_vdp2_regs[0x0c0/2]) - - #define STV_VDP2_W0SX ((STV_VDP2_WPSX0 & 0x03ff) >> 0) - -/* 1800c2 - Window Position (W0, Vertical Start Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPSY0 (m_vdp2_regs[0x0c2/2]) - - #define STV_VDP2_W0SY ((STV_VDP2_WPSY0 & 0x07ff) >> 0) - -/* 1800c4 - Window Position (W0, Horizontal End Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPEX0 (m_vdp2_regs[0x0c4/2]) - - #define STV_VDP2_W0EX ((STV_VDP2_WPEX0 & 0x03ff) >> 0) - -/* 1800c6 - Window Position (W0, Vertical End Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPEY0 (m_vdp2_regs[0x0c6/2]) - - #define STV_VDP2_W0EY ((STV_VDP2_WPEY0 & 0x07ff) >> 0) - -/* 1800c8 - Window Position (W1, Horizontal Start Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPSX1 (m_vdp2_regs[0x0c8/2]) - - #define STV_VDP2_W1SX ((STV_VDP2_WPSX1 & 0x03ff) >> 0) - -/* 1800ca - Window Position (W1, Vertical Start Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPSY1 (m_vdp2_regs[0x0ca/2]) - - #define STV_VDP2_W1SY ((STV_VDP2_WPSY1 & 0x07ff) >> 0) - -/* 1800cc - Window Position (W1, Horizontal End Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPEX1 (m_vdp2_regs[0x0cc/2]) - - #define STV_VDP2_W1EX ((STV_VDP2_WPEX1 & 0x03ff) >> 0) - -/* 1800ce - Window Position (W1, Vertical End Point) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WPEY1 (m_vdp2_regs[0x0ce/2]) - - #define STV_VDP2_W1EY ((STV_VDP2_WPEY1 & 0x07ff) >> 0) - -/* 1800d0 - Window Control (NBG0, NBG1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WCTLA (m_vdp2_regs[0x0d0/2]) - #define STV_VDP2_N1LOG ((STV_VDP2_WCTLA & 0x8000) >> 15) - #define STV_VDP2_N1SWE ((STV_VDP2_WCTLA & 0x2000) >> 13) - #define STV_VDP2_N1SWA ((STV_VDP2_WCTLA & 0x1000) >> 12) - #define STV_VDP2_N1W1E ((STV_VDP2_WCTLA & 0x0800) >> 11) - #define STV_VDP2_N1W1A ((STV_VDP2_WCTLA & 0x0400) >> 10) - #define STV_VDP2_N1W0E ((STV_VDP2_WCTLA & 0x0200) >> 9) - #define STV_VDP2_N1W0A ((STV_VDP2_WCTLA & 0x0100) >> 8) - #define STV_VDP2_N0LOG ((STV_VDP2_WCTLA & 0x0080) >> 7) - #define STV_VDP2_N0SWE ((STV_VDP2_WCTLA & 0x0020) >> 5) - #define STV_VDP2_N0SWA ((STV_VDP2_WCTLA & 0x0010) >> 4) - #define STV_VDP2_N0W1E ((STV_VDP2_WCTLA & 0x0008) >> 3) - #define STV_VDP2_N0W1A ((STV_VDP2_WCTLA & 0x0004) >> 2) - #define STV_VDP2_N0W0E ((STV_VDP2_WCTLA & 0x0002) >> 1) - #define STV_VDP2_N0W0A ((STV_VDP2_WCTLA & 0x0001) >> 0) - -/* 1800d2 - Window Control (NBG2, NBG3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WCTLB (m_vdp2_regs[0x0d2/2]) - #define STV_VDP2_N3LOG ((STV_VDP2_WCTLB & 0x8000) >> 15) - #define STV_VDP2_N3SWE ((STV_VDP2_WCTLB & 0x2000) >> 13) - #define STV_VDP2_N3SWA ((STV_VDP2_WCTLB & 0x1000) >> 12) - #define STV_VDP2_N3W1E ((STV_VDP2_WCTLB & 0x0800) >> 11) - #define STV_VDP2_N3W1A ((STV_VDP2_WCTLB & 0x0400) >> 10) - #define STV_VDP2_N3W0E ((STV_VDP2_WCTLB & 0x0200) >> 9) - #define STV_VDP2_N3W0A ((STV_VDP2_WCTLB & 0x0100) >> 8) - #define STV_VDP2_N2LOG ((STV_VDP2_WCTLB & 0x0080) >> 7) - #define STV_VDP2_N2SWE ((STV_VDP2_WCTLB & 0x0020) >> 5) - #define STV_VDP2_N2SWA ((STV_VDP2_WCTLB & 0x0010) >> 4) - #define STV_VDP2_N2W1E ((STV_VDP2_WCTLB & 0x0008) >> 3) - #define STV_VDP2_N2W1A ((STV_VDP2_WCTLB & 0x0004) >> 2) - #define STV_VDP2_N2W0E ((STV_VDP2_WCTLB & 0x0002) >> 1) - #define STV_VDP2_N2W0A ((STV_VDP2_WCTLB & 0x0001) >> 0) - -/* 1800d4 - Window Control (RBG0, Sprite) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WCTLC (m_vdp2_regs[0x0d4/2]) - #define STV_VDP2_SPLOG ((STV_VDP2_WCTLC & 0x8000) >> 15) - #define STV_VDP2_SPSWE ((STV_VDP2_WCTLC & 0x2000) >> 13) - #define STV_VDP2_SPSWA ((STV_VDP2_WCTLC & 0x1000) >> 12) - #define STV_VDP2_SPW1E ((STV_VDP2_WCTLC & 0x0800) >> 11) - #define STV_VDP2_SPW1A ((STV_VDP2_WCTLC & 0x0400) >> 10) - #define STV_VDP2_SPW0E ((STV_VDP2_WCTLC & 0x0200) >> 9) - #define STV_VDP2_SPW0A ((STV_VDP2_WCTLC & 0x0100) >> 8) - #define STV_VDP2_R0LOG ((STV_VDP2_WCTLC & 0x0080) >> 7) - #define STV_VDP2_R0SWE ((STV_VDP2_WCTLC & 0x0020) >> 5) - #define STV_VDP2_R0SWA ((STV_VDP2_WCTLC & 0x0010) >> 4) - #define STV_VDP2_R0W1E ((STV_VDP2_WCTLC & 0x0008) >> 3) - #define STV_VDP2_R0W1A ((STV_VDP2_WCTLC & 0x0004) >> 2) - #define STV_VDP2_R0W0E ((STV_VDP2_WCTLC & 0x0002) >> 1) - #define STV_VDP2_R0W0A ((STV_VDP2_WCTLC & 0x0001) >> 0) - -/* 1800d6 - Window Control (Parameter Window, Colour Calc. Window) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_WCTLD (m_vdp2_regs[0x0d6/2]) - #define STV_VDP2_CCLOG ((STV_VDP2_WCTLD & 0x8000) >> 15) - #define STV_VDP2_CCSWE ((STV_VDP2_WCTLD & 0x2000) >> 13) - #define STV_VDP2_CCSWA ((STV_VDP2_WCTLD & 0x1000) >> 12) - #define STV_VDP2_CCW1E ((STV_VDP2_WCTLD & 0x0800) >> 11) - #define STV_VDP2_CCW1A ((STV_VDP2_WCTLD & 0x0400) >> 10) - #define STV_VDP2_CCW0E ((STV_VDP2_WCTLD & 0x0200) >> 9) - #define STV_VDP2_CCW0A ((STV_VDP2_WCTLD & 0x0100) >> 8) - #define STV_VDP2_RPLOG ((STV_VDP2_WCTLD & 0x0080) >> 7) - #define STV_VDP2_RPW1E ((STV_VDP2_WCTLD & 0x0008) >> 3) - #define STV_VDP2_RPW1A ((STV_VDP2_WCTLD & 0x0004) >> 2) - #define STV_VDP2_RPW0E ((STV_VDP2_WCTLD & 0x0002) >> 1) - #define STV_VDP2_RPW0A ((STV_VDP2_WCTLD & 0x0001) >> 0) - -/* 1800d8 - Line Window Table Address (W0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LWTA0U (m_vdp2_regs[0x0d8/2]) - - #define STV_VDP2_W0LWE ((STV_VDP2_LWTA0U & 0x8000) >> 15) - -/* 1800da - Line Window Table Address (W0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LWTA0L (m_vdp2_regs[0x0da/2]) - - /* bit 19 isn't used when VRAM = 4 Mbit */ - #define STV_VDP2_W0LWTA (((STV_VDP2_LWTA0U & 0x0007) << 16) | (STV_VDP2_LWTA0L & 0xfffe)) - - -/* 1800dc - Line Window Table Address (W1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LWTA1U (m_vdp2_regs[0x0dc/2]) - - #define STV_VDP2_W1LWE ((STV_VDP2_LWTA1U & 0x8000) >> 15) - - -/* 1800de - Line Window Table Address (W1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LWTA1L (m_vdp2_regs[0x0de/2]) - - /* bit 19 isn't used when VRAM = 4 Mbit */ - #define STV_VDP2_W1LWTA (((STV_VDP2_LWTA1U & 0x0007) << 16) | (STV_VDP2_LWTA1L & 0xfffe)) - - -/* 1800e0 - Sprite Control - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | SPCCCS1 | SPCCCS0 | -- | SPCCN2 | SPCCN1 | SPCCN0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | SPCLMD | SPWINEN | SPTYPE3 | SPTYPE2 | SPTYPE1 | SPTYPE0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SPCTL (m_vdp2_regs[0x0e0/2]) - #define STV_VDP2_SPCCCS ((STV_VDP2_SPCTL & 0x3000) >> 12) - #define STV_VDP2_SPCCN ((STV_VDP2_SPCTL & 0x700) >> 8) - #define STV_VDP2_SPCLMD ((STV_VDP2_SPCTL & 0x20) >> 5) - #define STV_VDP2_SPWINEN ((STV_VDP2_SPCTL & 0x10) >> 4) - #define STV_VDP2_SPTYPE (STV_VDP2_SPCTL & 0xf) - -/* 1800e2 - Shadow Control - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SDCTL (m_vdp2_regs[0x0e2/2]) - -/* 1800e4 - CRAOFA - Colour Ram Address Offset (NBG0 - NBG3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | N0CAOS2 | N3CAOS1 | N3CAOS0 | -- | N2CAOS2 | N2CAOS1 | N2CAOS0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | N1CAOS2 | N1CAOS1 | N1CAOS0 | -- | N0CAOS2 | N0CAOS1 | N0CAOS0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CRAOFA (m_vdp2_regs[0x0e4/2]) - - /* NxCAOS = */ - #define STV_VDP2_N0CAOS ((STV_VDP2_CRAOFA & 0x0007) >> 0) - #define STV_VDP2_N1CAOS ((STV_VDP2_CRAOFA & 0x0070) >> 4) - #define STV_VDP2_N2CAOS ((STV_VDP2_CRAOFA & 0x0700) >> 8) - #define STV_VDP2_N3CAOS ((STV_VDP2_CRAOFA & 0x7000) >> 12) - - -/* 1800e6 - Colour Ram Address Offset (RBG0, SPRITE) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_CRAOFB (m_vdp2_regs[0x0e6/2]) - #define STV_VDP2_R0CAOS ((STV_VDP2_CRAOFB & 0x0007) >> 0) - #define STV_VDP2_SPCAOS ((STV_VDP2_CRAOFB & 0x0070) >> 4) - -/* 1800e8 - LNCLEN - Line Colour Screen Enable - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | SPLCEN | R0LCEN | N3LCEN | N2LCEN | N1LCEN | N0LCEN | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_LNCLEN (m_vdp2_regs[0x0e8/2]) - #define STV_VDP2_SPLCEN ((STV_VDP2_LNCLEN & 0x0020) >> 5) - #define STV_VDP2_R0LCEN ((STV_VDP2_LNCLEN & 0x0010) >> 4) - #define STV_VDP2_N3LCEN ((STV_VDP2_LNCLEN & 0x0008) >> 3) - #define STV_VDP2_N2LCEN ((STV_VDP2_LNCLEN & 0x0004) >> 2) - #define STV_VDP2_N1LCEN ((STV_VDP2_LNCLEN & 0x0002) >> 1) - #define STV_VDP2_N0LCEN ((STV_VDP2_LNCLEN & 0x0001) >> 0) - -/* 1800ea - Special Priority Mode - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SFPRMD (m_vdp2_regs[0x0ea/2]) - - -/* 1800ec - Colour Calculation Control - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | BOKEN | BOKN2 | BOKN1 | BOKN0 | -- | EXCCEN | CCRTMD | CCMD | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | SPCCEN | LCCCEN | R0CCEN | N3CCEN | N2CCEN | N1CCEN | N0CCEN | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCCR (m_vdp2_regs[0x0ec/2]) - #define STV_VDP2_CCMD ((STV_VDP2_CCCR & 0x100) >> 8) - #define STV_VDP2_SPCCEN ((STV_VDP2_CCCR & 0x40) >> 6) - #define STV_VDP2_LCCCEN ((STV_VDP2_CCCR & 0x20) >> 5) - #define STV_VDP2_R0CCEN ((STV_VDP2_CCCR & 0x10) >> 4) - #define STV_VDP2_N3CCEN ((STV_VDP2_CCCR & 0x8) >> 3) - #define STV_VDP2_N2CCEN ((STV_VDP2_CCCR & 0x4) >> 2) - #define STV_VDP2_N1CCEN ((STV_VDP2_CCCR & 0x2) >> 1) - #define STV_VDP2_N0CCEN ((STV_VDP2_CCCR & 0x1) >> 0) - - -/* 1800ee - Special Colour Calculation Mode - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_SFCCMD (m_vdp2_regs[0x0ee/2]) - -/* 1800f0 - Priority Number (Sprite 0,1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | S1PRIN2 | S1PRIN1 | S1PRIN0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | S0PRIN2 | S0PRIN1 | S0PRIN0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PRISA (m_vdp2_regs[0x0f0/2]) - #define STV_VDP2_S1PRIN ((STV_VDP2_PRISA & 0x0700) >> 8) - #define STV_VDP2_S0PRIN ((STV_VDP2_PRISA & 0x0007) >> 0) - -/* 1800f2 - Priority Number (Sprite 2,3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | S3PRIN2 | S3PRIN1 | S3PRIN0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | S2PRIN2 | S2PRIN1 | S2PRIN0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PRISB (m_vdp2_regs[0x0f2/2]) - #define STV_VDP2_S3PRIN ((STV_VDP2_PRISB & 0x0700) >> 8) - #define STV_VDP2_S2PRIN ((STV_VDP2_PRISB & 0x0007) >> 0) - -/* 1800f4 - Priority Number (Sprite 4,5) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | S5PRIN2 | S5PRIN1 | S5PRIN0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | S4PRIN2 | S4PRIN1 | S4PRIN0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PRISC (m_vdp2_regs[0x0f4/2]) - #define STV_VDP2_S5PRIN ((STV_VDP2_PRISC & 0x0700) >> 8) - #define STV_VDP2_S4PRIN ((STV_VDP2_PRISC & 0x0007) >> 0) - -/* 1800f6 - Priority Number (Sprite 6,7) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | S7PRIN2 | S7PRIN1 | S7PRIN0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | S6PRIN2 | S6PRIN1 | S6PRIN0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PRISD (m_vdp2_regs[0x0f6/2]) - #define STV_VDP2_S7PRIN ((STV_VDP2_PRISD & 0x0700) >> 8) - #define STV_VDP2_S6PRIN ((STV_VDP2_PRISD & 0x0007) >> 0) - - -/* 1800f8 - PRINA - Priority Number (NBG 0,1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PRINA (m_vdp2_regs[0x0f8/2]) - - #define STV_VDP2_N1PRIN ((STV_VDP2_PRINA & 0x0700) >> 8) - #define STV_VDP2_N0PRIN ((STV_VDP2_PRINA & 0x0007) >> 0) - -/* 1800fa - PRINB - Priority Number (NBG 2,3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_PRINB (m_vdp2_regs[0x0fa/2]) - - #define STV_VDP2_N3PRIN ((STV_VDP2_PRINB & 0x0700) >> 8) - #define STV_VDP2_N2PRIN ((STV_VDP2_PRINB & 0x0007) >> 0) - -/* 1800fc - Priority Number (RBG0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_PRIR (m_vdp2_regs[0x0fc/2]) - - #define STV_VDP2_R0PRIN ((STV_VDP2_PRIR & 0x0007) >> 0) - -/* 1800fe - Reserved - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - -/* 180100 - Colour Calculation Ratio (Sprite 0,1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | S1CCRT4 | S1CCRT3 | S1CCRT2 | S1CCRT1 | S1CCRT0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | S0CCRT4 | S0CCRT3 | S0CCRT2 | S0CCRT1 | S0CCRT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRSA (m_vdp2_regs[0x100/2]) - #define STV_VDP2_S1CCRT ((STV_VDP2_CCRSA & 0x1f00) >> 8) - #define STV_VDP2_S0CCRT ((STV_VDP2_CCRSA & 0x001f) >> 0) - -/* 180102 - Colour Calculation Ratio (Sprite 2,3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | S3CCRT4 | S3CCRT3 | S3CCRT2 | S3CCRT1 | S3CCRT0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | S2CCRT4 | S2CCRT3 | S2CCRT2 | S2CCRT1 | S2CCRT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRSB (m_vdp2_regs[0x102/2]) - #define STV_VDP2_S3CCRT ((STV_VDP2_CCRSB & 0x1f00) >> 8) - #define STV_VDP2_S2CCRT ((STV_VDP2_CCRSB & 0x001f) >> 0) - -/* 180104 - Colour Calculation Ratio (Sprite 4,5) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | S5CCRT4 | S5CCRT3 | S5CCRT2 | S5CCRT1 | S5CCRT0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | S4CCRT4 | S4CCRT3 | S4CCRT2 | S4CCRT1 | S4CCRT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRSC (m_vdp2_regs[0x104/2]) - #define STV_VDP2_S5CCRT ((STV_VDP2_CCRSC & 0x1f00) >> 8) - #define STV_VDP2_S4CCRT ((STV_VDP2_CCRSC & 0x001f) >> 0) - -/* 180106 - Colour Calculation Ratio (Sprite 6,7) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | S7CCRT4 | S7CCRT3 | S7CCRT2 | S7CCRT1 | S7CCRT0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | S6CCRT4 | S6CCRT3 | S6CCRT2 | S6CCRT1 | S6CCRT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRSD (m_vdp2_regs[0x106/2]) - #define STV_VDP2_S7CCRT ((STV_VDP2_CCRSD & 0x1f00) >> 8) - #define STV_VDP2_S6CCRT ((STV_VDP2_CCRSD & 0x001f) >> 0) - -/* 180108 - Colour Calculation Ratio (NBG 0,1) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | N1CCRT4 | N1CCRT3 | N1CCRT2 | N1CCRT1 | N1CCRT0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | N0CCRT4 | N0CCRT3 | N0CCRT2 | N0CCRT1 | N0CCRT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRNA (m_vdp2_regs[0x108/2]) - #define STV_VDP2_N1CCRT ((STV_VDP2_CCRNA & 0x1f00) >> 8) - #define STV_VDP2_N0CCRT (STV_VDP2_CCRNA & 0x1f) - -/* 18010a - Colour Calculation Ratio (NBG 2,3) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | N3CCRT4 | N3CCRT3 | N3CCRT2 | N3CCRT1 | N3CCRT0 | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | N2CCRT4 | N2CCRT3 | N2CCRT2 | N2CCRT1 | N2CCRT0 | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRNB (m_vdp2_regs[0x10a/2]) - #define STV_VDP2_N3CCRT ((STV_VDP2_CCRNB & 0x1f00) >> 8) - #define STV_VDP2_N2CCRT (STV_VDP2_CCRNB & 0x1f) - -/* 18010c - Colour Calculation Ratio (RBG 0) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRR (m_vdp2_regs[0x10c/2]) - #define STV_VDP2_R0CCRT (STV_VDP2_CCRR & 0x1f) - -/* 18010e - Colour Calculation Ratio (Line Colour Screen, Back Colour Screen) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CCRLB (m_vdp2_regs[0x10e/2]) - - -/* 180110 - Colour Offset Enable - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CLOFEN (m_vdp2_regs[0x110/2]) - #define STV_VDP2_N0COEN ((STV_VDP2_CLOFEN & 0x01) >> 0) - #define STV_VDP2_N1COEN ((STV_VDP2_CLOFEN & 0x02) >> 1) - #define STV_VDP2_N2COEN ((STV_VDP2_CLOFEN & 0x04) >> 2) - #define STV_VDP2_N3COEN ((STV_VDP2_CLOFEN & 0x08) >> 3) - #define STV_VDP2_R0COEN ((STV_VDP2_CLOFEN & 0x10) >> 4) - #define STV_VDP2_BKCOEN ((STV_VDP2_CLOFEN & 0x20) >> 5) - #define STV_VDP2_SPCOEN ((STV_VDP2_CLOFEN & 0x40) >> 6) - -/* 180112 - Colour Offset Select - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_CLOFSL (m_vdp2_regs[0x112/2]) - #define STV_VDP2_N0COSL ((STV_VDP2_CLOFSL & 0x01) >> 0) - #define STV_VDP2_N1COSL ((STV_VDP2_CLOFSL & 0x02) >> 1) - #define STV_VDP2_N2COSL ((STV_VDP2_CLOFSL & 0x04) >> 2) - #define STV_VDP2_N3COSL ((STV_VDP2_CLOFSL & 0x08) >> 3) - #define STV_VDP2_R0COSL ((STV_VDP2_CLOFSL & 0x10) >> 4) - #define STV_VDP2_BKCOSL ((STV_VDP2_CLOFSL & 0x20) >> 5) - #define STV_VDP2_SPCOSL ((STV_VDP2_CLOFSL & 0x40) >> 6) - -/* 180114 - Colour Offset A (Red) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_COAR (m_vdp2_regs[0x114/2]) - -/* 180116 - Colour Offset A (Green) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_COAG (m_vdp2_regs[0x116/2]) - -/* 180118 - Colour Offset A (Blue) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - - #define STV_VDP2_COAB (m_vdp2_regs[0x118/2]) - -/* 18011a - Colour Offset B (Red) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_COBR (m_vdp2_regs[0x11a/2]) - -/* 18011c - Colour Offset B (Green) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_COBG (m_vdp2_regs[0x11c/2]) - -/* 18011e - Colour Offset B (Blue) - bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ - | -- | -- | -- | -- | -- | -- | -- | -- | - |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| - | -- | -- | -- | -- | -- | -- | -- | -- | - \----------|----------|----------|----------|----------|----------|----------|---------*/ - #define STV_VDP2_COBB (m_vdp2_regs[0x11e/2]) - - -#define STV_VDP2_RBG_ROTATION_PARAMETER_A 1 -#define STV_VDP2_RBG_ROTATION_PARAMETER_B 2 - - -#define mul_fixed32( a, b ) mul_32x32_shift( a, b, 16 ) - -void saturn_state::stv_vdp2_fill_rotation_parameter_table( uint8_t rot_parameter ) -{ - uint32_t address; - - address = (((STV_VDP2_RPTAU << 16) | STV_VDP2_RPTAL) << 1); - if ( rot_parameter == 1 ) - { - address &= ~0x00000080; - } - else if ( rot_parameter == 2 ) - { - address |= 0x00000080; - } - - stv_current_rotation_parameter_table.xst = (m_vdp2_vram[address/4] & 0x1fffffc0) | ((m_vdp2_vram[address/4] & 0x10000000) ? 0xe0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.yst = (m_vdp2_vram[address/4 + 1] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 1] & 0x10000000) ? 0xe0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.zst = (m_vdp2_vram[address/4 + 2] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 2] & 0x10000000) ? 0xe0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.dxst = (m_vdp2_vram[address/4 + 3] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 3] & 0x00040000) ? 0xfff80000 : 0x00000000 ); - stv_current_rotation_parameter_table.dyst = (m_vdp2_vram[address/4 + 4] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 4] & 0x00040000) ? 0xfff80000 : 0x00000000 ); - stv_current_rotation_parameter_table.dx = (m_vdp2_vram[address/4 + 5] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 5] & 0x00040000) ? 0xfff80000 : 0x00000000 ); - stv_current_rotation_parameter_table.dy = (m_vdp2_vram[address/4 + 6] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 6] & 0x00040000) ? 0xfff80000 : 0x00000000 ); - stv_current_rotation_parameter_table.A = (m_vdp2_vram[address/4 + 7] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 7] & 0x00080000) ? 0xfff00000 : 0x00000000 ); - stv_current_rotation_parameter_table.B = (m_vdp2_vram[address/4 + 8] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 8] & 0x00080000) ? 0xfff00000 : 0x00000000 ); - stv_current_rotation_parameter_table.C = (m_vdp2_vram[address/4 + 9] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 9] & 0x00080000) ? 0xfff00000 : 0x00000000 ); - stv_current_rotation_parameter_table.D = (m_vdp2_vram[address/4 + 10] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 10] & 0x00080000) ? 0xfff00000 : 0x00000000 ); - stv_current_rotation_parameter_table.E = (m_vdp2_vram[address/4 + 11] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 11] & 0x00080000) ? 0xfff00000 : 0x00000000 ); - stv_current_rotation_parameter_table.F = (m_vdp2_vram[address/4 + 12] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 12] & 0x00080000) ? 0xfff00000 : 0x00000000 ); - stv_current_rotation_parameter_table.px = (m_vdp2_vram[address/4 + 13] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 13] & 0x30000000) ? 0xc0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.py = (m_vdp2_vram[address/4 + 13] & 0x00003fff) << 16; - if ( stv_current_rotation_parameter_table.py & 0x20000000 ) stv_current_rotation_parameter_table.py |= 0xc0000000; - stv_current_rotation_parameter_table.pz = (m_vdp2_vram[address/4 + 14] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 14] & 0x20000000) ? 0xc0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.cx = (m_vdp2_vram[address/4 + 15] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 15] & 0x20000000) ? 0xc0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.cy = (m_vdp2_vram[address/4 + 15] & 0x00003fff) << 16; - if ( stv_current_rotation_parameter_table.cy & 0x20000000 ) stv_current_rotation_parameter_table.cy |= 0xc0000000; - stv_current_rotation_parameter_table.cz = (m_vdp2_vram[address/4 + 16] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 16] & 0x20000000) ? 0xc0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.mx = (m_vdp2_vram[address/4 + 17] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 17] & 0x20000000) ? 0xc0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.my = (m_vdp2_vram[address/4 + 18] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 18] & 0x20000000) ? 0xc0000000 : 0x00000000 ); - stv_current_rotation_parameter_table.kx = (m_vdp2_vram[address/4 + 19] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 19] & 0x00800000) ? 0xff000000 : 0x00000000 ); - stv_current_rotation_parameter_table.ky = (m_vdp2_vram[address/4 + 20] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 20] & 0x00800000) ? 0xff000000 : 0x00000000 ); - stv_current_rotation_parameter_table.kast = (m_vdp2_vram[address/4 + 21] & 0xffffffc0); - stv_current_rotation_parameter_table.dkast= (m_vdp2_vram[address/4 + 22] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 22] & 0x02000000) ? 0xfc000000 : 0x00000000 ); - stv_current_rotation_parameter_table.dkax = (m_vdp2_vram[address/4 + 23] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 23] & 0x02000000) ? 0xfc000000 : 0x00000000 ); - - // check rotation parameter read control, override if specific bits are disabled - // (Batman Forever The Riddler stage relies on this) - switch(rot_parameter) - { - case 1: - // TODO: disable read control if these undocumented bits are on (Radiant Silvergun Xiga final boss) - if(!STV_VDP2_RAUNK) - { - if(!STV_VDP2_RAXSTRE) - stv_current_rotation_parameter_table.xst = 0; - - if(!STV_VDP2_RAYSTRE) - stv_current_rotation_parameter_table.yst = 0; - - if(!STV_VDP2_RAKASTRE) - stv_current_rotation_parameter_table.dkax = 0; - } - break; - case 2: - // same as above - if(!STV_VDP2_RBUNK) - { - if(!STV_VDP2_RBXSTRE) - stv_current_rotation_parameter_table.xst = 0; - - if(!STV_VDP2_RBYSTRE) - stv_current_rotation_parameter_table.yst = 0; - - if(!STV_VDP2_RBKASTRE) - stv_current_rotation_parameter_table.dkax = 0; - } - break; - } - -#define RP stv_current_rotation_parameter_table - - if(LOG_ROZ == 1) logerror( "Rotation parameter table (%d)\n", rot_parameter ); - if(LOG_ROZ == 1) logerror( "xst = %x, yst = %x, zst = %x\n", RP.xst, RP.yst, RP.zst ); - if(LOG_ROZ == 1) logerror( "dxst = %x, dyst = %x\n", RP.dxst, RP.dyst ); - if(LOG_ROZ == 1) logerror( "dx = %x, dy = %x\n", RP.dx, RP.dy ); - if(LOG_ROZ == 1) logerror( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x\n", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); - if(LOG_ROZ == 1) logerror( "px = %x, py = %x, pz = %x\n", RP.px, RP.py, RP.pz ); - if(LOG_ROZ == 1) logerror( "cx = %x, cy = %x, cz = %x\n", RP.cx, RP.cy, RP.cz ); - if(LOG_ROZ == 1) logerror( "mx = %x, my = %x\n", RP.mx, RP.my ); - if(LOG_ROZ == 1) logerror( "kx = %x, ky = %x\n", RP.kx, RP.ky ); - if(LOG_ROZ == 1) logerror( "kast = %x, dkast = %x, dkax = %x\n", RP.kast, RP.dkast, RP.dkax ); - - /*Attempt to show on screen the rotation table*/ - #if 0 - if(LOG_ROZ == 2) - { - if(machine().input().code_pressed_once(JOYCODE_Y_UP_SWITCH)) - m_vdpdebug_roz++; - - if(machine().input().code_pressed_once(JOYCODE_Y_DOWN_SWITCH)) - m_vdpdebug_roz--; - - if(m_vdpdebug_roz > 10) - m_vdpdebug_roz = 10; - - switch(m_vdpdebug_roz) - { - case 0: popmessage( "Rotation parameter Table (%d)", rot_parameter ); break; - case 1: popmessage( "xst = %x, yst = %x, zst = %x", RP.xst, RP.yst, RP.zst ); break; - case 2: popmessage( "dxst = %x, dyst = %x", RP.dxst, RP.dyst ); break; - case 3: popmessage( "dx = %x, dy = %x", RP.dx, RP.dy ); break; - case 4: popmessage( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); break; - case 5: popmessage( "px = %x, py = %x, pz = %x", RP.px, RP.py, RP.pz ); break; - case 6: popmessage( "cx = %x, cy = %x, cz = %x", RP.cx, RP.cy, RP.cz ); break; - case 7: popmessage( "mx = %x, my = %x", RP.mx, RP.my ); break; - case 8: popmessage( "kx = %x, ky = %x", RP.kx, RP.ky ); break; - case 9: popmessage( "kast = %x, dkast = %x, dkax = %x", RP.kast, RP.dkast, RP.dkax ); break; - case 10: break; - } - } - #endif -} - -/* check if RGB layer has rotation applied */ -uint8_t saturn_state::stv_vdp2_is_rotation_applied(void) -{ -#define _FIXED_1 (0x00010000) -#define _FIXED_0 (0x00000000) - - if ( RP.A == _FIXED_1 && - RP.B == _FIXED_0 && - RP.C == _FIXED_0 && - RP.D == _FIXED_0 && - RP.E == _FIXED_1 && - RP.F == _FIXED_0 && - RP.dxst == _FIXED_0 && - RP.dyst == _FIXED_1 && - RP.dx == _FIXED_1 && - RP.dy == _FIXED_0 && - RP.kx == _FIXED_1 && - RP.ky == _FIXED_1 && - STV_VDP2_RPMD < 2) // disable optimizations if roz mode is 2 or 3 - { - return 0; - } - else - { - return 1; - } -} - -uint8_t saturn_state::stv_vdp2_are_map_registers_equal(void) -{ - int i; - - for ( i = 1; i < stv2_current_tilemap.map_count; i++ ) - { - if ( stv2_current_tilemap.map_offset[i] != stv2_current_tilemap.map_offset[0] ) - { - return 0; - } - } - return 1; -} - -void saturn_state::stv_vdp2_check_fade_control_for_layer( void ) -{ - if ( stv2_current_tilemap.fade_control & 1 ) - { - if ( stv2_current_tilemap.fade_control & 2 ) - { - if ((STV_VDP2_COBR & 0x1ff) == 0 && - (STV_VDP2_COBG & 0x1ff) == 0 && - (STV_VDP2_COBB & 0x1ff) == 0 ) - { - stv2_current_tilemap.fade_control = 0; - } - } - else - { - if ((STV_VDP2_COAR & 0x1ff) == 0 && - (STV_VDP2_COAG & 0x1ff) == 0 && - (STV_VDP2_COAB & 0x1ff) == 0 ) - { - stv2_current_tilemap.fade_control = 0; - } - } - } -} - -#define STV_VDP2_CP_NBG0_PNMDR 0x0 -#define STV_VDP2_CP_NBG1_PNMDR 0x1 -#define STV_VDP2_CP_NBG2_PNMDR 0x2 -#define STV_VDP2_CP_NBG3_PNMDR 0x3 -#define STV_VDP2_CP_NBG0_CPDR 0x4 -#define STV_VDP2_CP_NBG1_CPDR 0x5 -#define STV_VDP2_CP_NBG2_CPDR 0x6 -#define STV_VDP2_CP_NBG3_CPDR 0x7 - -uint8_t saturn_state::stv_vdp2_check_vram_cycle_pattern_registers( uint8_t access_command_pnmdr, uint8_t access_command_cpdr, uint8_t bitmap_enable ) -{ - int i; - uint8_t access_command_ok = 0; - uint16_t cp_regs[8]; - cp_regs[0] = STV_VDP2_CYCA0L; - cp_regs[1] = STV_VDP2_CYCA0U; - cp_regs[2] = STV_VDP2_CYCA1L; - cp_regs[3] = STV_VDP2_CYCA1U; - cp_regs[4] = STV_VDP2_CYCA2L; - cp_regs[5] = STV_VDP2_CYCA2U; - cp_regs[6] = STV_VDP2_CYCA3L; - cp_regs[7] = STV_VDP2_CYCA3U; - - if ( bitmap_enable ) access_command_ok = 1; - - for ( i = 0; i < 8; i++ ) - { - if ( ((cp_regs[i] >> 12) & 0xf) == access_command_pnmdr ) - { - access_command_ok |= 1; - } - if ( ((cp_regs[i] >> 12) & 0xf) == access_command_cpdr ) - { - access_command_ok |= 2; - } - if ( ((cp_regs[i] >> 8) & 0xf) == access_command_pnmdr ) - { - access_command_ok |= 1; - } - if ( ((cp_regs[i] >> 8) & 0xf) == access_command_cpdr ) - { - access_command_ok |= 2; - } - if ( ((cp_regs[i] >> 4) & 0xf) == access_command_pnmdr ) - { - access_command_ok |= 1; - } - if ( ((cp_regs[i] >> 4) & 0xf) == access_command_cpdr ) - { - access_command_ok |= 2; - } - if ( ((cp_regs[i] >> 0) & 0xf) == access_command_pnmdr ) - { - access_command_ok |= 1; - } - if ( ((cp_regs[i] >> 0) & 0xf) == access_command_cpdr ) - { - access_command_ok |= 2; - } - } - return access_command_ok == 3 ? 1 : 0; -} - - -void saturn_state::stv_vdp2_compute_color_offset( int *r, int *g, int *b, int cor ) -{ - if ( cor == 0 ) - { - *r = (STV_VDP2_COAR & 0x100) ? (*r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + *r); - *g = (STV_VDP2_COAG & 0x100) ? (*g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + *g); - *b = (STV_VDP2_COAB & 0x100) ? (*b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + *b); - } - else - { - *r = (STV_VDP2_COBR & 0x100) ? (*r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + *r); - *g = (STV_VDP2_COBG & 0x100) ? (*g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + *g); - *b = (STV_VDP2_COBB & 0x100) ? (*b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + *b); - } - if(*r < 0) { *r = 0; } - if(*r > 0xff) { *r = 0xff; } - if(*g < 0) { *g = 0; } - if(*g > 0xff) { *g = 0xff; } - if(*b < 0) { *b = 0; } - if(*b > 0xff) { *b = 0xff; } -} - -void saturn_state::stv_vdp2_compute_color_offset_UINT32(rgb_t *rgb, int cor) -{ - int _r = rgb->r(); - int _g = rgb->g(); - int _b = rgb->b(); - if ( cor == 0 ) - { - _r = (STV_VDP2_COAR & 0x100) ? (_r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + _r); - _g = (STV_VDP2_COAG & 0x100) ? (_g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + _g); - _b = (STV_VDP2_COAB & 0x100) ? (_b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + _b); - } - else - { - _r = (STV_VDP2_COBR & 0x100) ? (_r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + _r); - _g = (STV_VDP2_COBG & 0x100) ? (_g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + _g); - _b = (STV_VDP2_COBB & 0x100) ? (_b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + _b); - } - if(_r < 0) { _r = 0; } - if(_r > 0xff) { _r = 0xff; } - if(_g < 0) { _g = 0; } - if(_g > 0xff) { _g = 0xff; } - if(_b < 0) { _b = 0; } - if(_b > 0xff) { _b = 0xff; } - - *rgb = rgb_t(_r, _g, _b); -} - -void saturn_state::stv_vdp2_drawgfxzoom( - bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, - uint32_t code,uint32_t color,int flipx,int flipy,int sx,int sy, - int transparency,int scalex, int scaley, - int sprite_screen_width, int sprite_screen_height, int alpha) -{ - rectangle myclip; - - if (!scalex || !scaley) return; - - if (gfx->has_pen_usage() && !(transparency & STV_TRANSPARENCY_NONE)) - { - int transmask; - - transmask = 1 << (0 & 0xff); - - if ((gfx->pen_usage(code) & ~transmask) == 0) - /* character is totally transparent, no need to draw */ - return; - else if ((gfx->pen_usage(code) & transmask) == 0) - /* character is totally opaque, can disable transparency */ - transparency |= STV_TRANSPARENCY_NONE; - } - - /* - scalex and scaley are 16.16 fixed point numbers - 1<<15 : shrink to 50% - 1<<16 : uniform scale - 1<<17 : double to 200% - */ - - - /* KW 991012 -- Added code to force clip to bitmap boundary */ - myclip = clip; - myclip &= dest_bmp.cliprect(); - - if( gfx ) - { - const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); - const uint8_t *source_base = gfx->get_data(code % gfx->elements()); - - //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16; - //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16; - - if (sprite_screen_width && sprite_screen_height) - { - /* compute sprite increment per screen pixel */ - //int dx = (gfx->width()<<16)/sprite_screen_width; - //int dy = (gfx->height()<<16)/sprite_screen_height; - int dx = stv2_current_tilemap.incx; - int dy = stv2_current_tilemap.incy; - - int ex = sx+sprite_screen_width; - int ey = sy+sprite_screen_height; - - int x_index_base; - int y_index; - - if( flipx ) - { - x_index_base = (sprite_screen_width-1)*dx; - dx = -dx; - } - else - { - x_index_base = 0; - } - - if( flipy ) - { - y_index = (sprite_screen_height-1)*dy; - dy = -dy; - } - else - { - y_index = 0; - } - - if( sx < myclip.left()) - { /* clip left */ - int pixels = myclip.left()-sx; - sx += pixels; - x_index_base += pixels*dx; - } - if( sy < myclip.top() ) - { /* clip top */ - int pixels = myclip.top()-sy; - sy += pixels; - y_index += pixels*dy; - } - /* NS 980211 - fixed incorrect clipping */ - if( ex > myclip.right()+1 ) - { /* clip right */ - int pixels = ex-myclip.right()-1; - ex -= pixels; - } - if( ey > myclip.bottom()+1 ) - { /* clip bottom */ - int pixels = ey-myclip.bottom()-1; - ey -= pixels; - } - - if( ex>sx ) - { /* skip if inner loop doesn't draw anything */ - int y; - - /* case : STV_TRANSPARENCY_ALPHA */ - if (transparency & STV_TRANSPARENCY_ALPHA) - { - for( y=sy; y>16) * gfx->rowbytes(); - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16]; - if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) - dest[x] = alpha_blend_r32(dest[x], pal[c], alpha); - } - x_index += dx; - } - - y_index += dy; - } - } /* case : STV_TRANSPARENCY_ADD_BLEND */ - else if (transparency & STV_TRANSPARENCY_ADD_BLEND) - { - for( y=sy; y>16) * gfx->rowbytes(); - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16]; - if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) - dest[x] = add_blend_r32(dest[x],pal[c]); - } - x_index += dx; - } - - y_index += dy; - } - } /* case : STV_TRANSPARENCY_PEN */ - else - { - for( y=sy; y>16) * gfx->rowbytes(); - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16]; - if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) - dest[x] = pal[c]; - } - x_index += dx; - } - - y_index += dy; - } - } - } - } - } -} - -void saturn_state::stv_vdp2_drawgfxzoom_rgb555( - bitmap_rgb32 &dest_bmp,const rectangle &clip, - uint32_t code,uint32_t color,int flipx,int flipy,int sx,int sy, - int transparency,int scalex, int scaley, - int sprite_screen_width, int sprite_screen_height, int alpha) -{ - rectangle myclip; - uint8_t* gfxdata; - - gfxdata = m_vdp2.gfx_decode.get() + code * 0x20; - - if(stv2_current_tilemap.window_control.enabled[0] || - stv2_current_tilemap.window_control.enabled[1]) - popmessage("Window Enabled for RGB555 Zoom"); - - if (!scalex || !scaley) return; - - #if 0 - if (gfx->has_pen_usage() && !(transparency & STV_TRANSPARENCY_NONE)) - { - int transmask = 0; - - transmask = 1 << (0 & 0xff); - - if ((gfx->pen_usage(code) & ~transmask) == 0) - /* character is totally transparent, no need to draw */ - return; - else if ((gfx->pen_usage(code) & transmask) == 0) - /* character is totally opaque, can disable transparency */ - transparency |= STV_TRANSPARENCY_NONE; - } - #endif - - /* - scalex and scaley are 16.16 fixed point numbers - 1<<15 : shrink to 50% - 1<<16 : uniform scale - 1<<17 : double to 200% - */ - - - /* KW 991012 -- Added code to force clip to bitmap boundary */ - myclip = clip; - myclip &= dest_bmp.cliprect(); - -// if( gfx ) - { -// const uint8_t *source_base = gfx->get_data(code % gfx->elements()); - - //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16; - //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16; - - if (sprite_screen_width && sprite_screen_height) - { - /* compute sprite increment per screen pixel */ - //int dx = (gfx->width()<<16)/sprite_screen_width; - //int dy = (gfx->height()<<16)/sprite_screen_height; - int dx = stv2_current_tilemap.incx; - int dy = stv2_current_tilemap.incy; - - int ex = sx+sprite_screen_width; - int ey = sy+sprite_screen_height; - - int x_index_base; - int y_index; - - if( flipx ) - { - x_index_base = (sprite_screen_width-1)*dx; - dx = -dx; - } - else - { - x_index_base = 0; - } - - if( flipy ) - { - y_index = (sprite_screen_height-1)*dy; - dy = -dy; - } - else - { - y_index = 0; - } - - if( sx < myclip.left()) - { /* clip left */ - int pixels = myclip.left()-sx; - sx += pixels; - x_index_base += pixels*dx; - } - if( sy < myclip.top() ) - { /* clip top */ - int pixels = myclip.top()-sy; - sy += pixels; - y_index += pixels*dy; - } - /* NS 980211 - fixed incorrect clipping */ - if( ex > myclip.right()+1 ) - { /* clip right */ - int pixels = ex-myclip.right()-1; - ex -= pixels; - } - if( ey > myclip.bottom()+1 ) - { /* clip bottom */ - int pixels = ey-myclip.bottom()-1; - ey -= pixels; - } - - if( ex>sx ) - { /* skip if inner loop doesn't draw anything */ - int y; - - /* case : STV_TRANSPARENCY_ALPHA */ - if (transparency & STV_TRANSPARENCY_ALPHA) - { - for( y=sy; y>16)*16; - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16)*2] << 8) | source[(x_index>>16)*2+1]; - int b = pal5bit((data & 0x7c00) >> 10); - int g = pal5bit((data & 0x03e0) >> 5); - int r = pal5bit( data & 0x001f); - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000)) - dest[x] = alpha_blend_r32(dest[x], rgb_t(r, g, b), alpha); - - x_index += dx; - } - - y_index += dy; - } - } /* case : STV_TRANSPARENCY_ADD_BLEND */ - else if (transparency & STV_TRANSPARENCY_ADD_BLEND) - { - for( y=sy; y>16)*16; - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16]<<0)|(source[(x_index*2+1)>>16]<<8); - int b = pal5bit((data & 0x7c00) >> 10); - int g = pal5bit((data & 0x03e0) >> 5); - int r = pal5bit( data & 0x001f); - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000)) - dest[x] = add_blend_r32(dest[x], rgb_t(r, g, b)); - - x_index += dx; - } - - y_index += dy; - } - } /* case : STV_TRANSPARENCY_PEN */ - else - { - for( y=sy; y>16)*16; - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16)*2] << 8) | source[(x_index>>16)*2+1]; - int b = pal5bit((data & 0x7c00) >> 10); - int g = pal5bit((data & 0x03e0) >> 5); - int r = pal5bit( data & 0x001f); - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000)) - dest[x] = rgb_t(r, g, b); - - x_index += dx; - } - - y_index += dy; - } - } - } - } - } - -} - - -void saturn_state::stv_vdp2_drawgfx_rgb555( bitmap_rgb32 &dest_bmp, const rectangle &clip, uint32_t code, int flipx, int flipy, int sx, int sy, int transparency, int alpha) -{ - rectangle myclip; - uint8_t* gfxdata; - int sprite_screen_width, sprite_screen_height; - - gfxdata = m_vdp2.gfx_decode.get() + code * 0x20; - sprite_screen_width = sprite_screen_height = 8; - - if(stv2_current_tilemap.window_control.enabled[0] || - stv2_current_tilemap.window_control.enabled[1]) - popmessage("Window Enabled for RGB555 tiles"); - - /* KW 991012 -- Added code to force clip to bitmap boundary */ - myclip = clip; - myclip &= dest_bmp.cliprect(); - - { - int dx = stv2_current_tilemap.incx; - int dy = stv2_current_tilemap.incy; - - int ex = sx+sprite_screen_width; - int ey = sy+sprite_screen_height; - - int x_index_base; - int y_index; - - if( flipx ) - { - x_index_base = (sprite_screen_width-1)*dx; - dx = -dx; - } - else - { - x_index_base = 0; - } - - if( flipy ) - { - y_index = (sprite_screen_height-1)*dy; - dy = -dy; - } - else - { - y_index = 0; - } - - if( sx < myclip.left()) - { /* clip left */ - int pixels = myclip.left()-sx; - sx += pixels; - x_index_base += pixels*dx; - } - if( sy < myclip.top() ) - { /* clip top */ - int pixels = myclip.top()-sy; - sy += pixels; - y_index += pixels*dy; - } - /* NS 980211 - fixed incorrect clipping */ - if( ex > myclip.right()+1 ) - { /* clip right */ - int pixels = ex-myclip.right()-1; - ex -= pixels; - } - if( ey > myclip.bottom()+1 ) - { /* clip bottom */ - int pixels = ey-myclip.bottom()-1; - ey -= pixels; - } - - if( ex>sx ) - { /* skip if inner loop doesn't draw anything */ - int y; - - for( y=sy; y>16)*16; - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - for( int x=sx; x>16)*2] << 8) | source[(x_index>>16)*2+1]; - if ((data & 0x8000) || (transparency & STV_TRANSPARENCY_NONE)) - { - int b = pal5bit((data & 0x7c00) >> 10); - int g = pal5bit((data & 0x03e0) >> 5); - int r = pal5bit( data & 0x001f); - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if (transparency & STV_TRANSPARENCY_ALPHA) - dest[x] = alpha_blend_r32( dest[x], rgb_t(r, g, b), alpha ); - else - dest[x] = rgb_t(r, g, b); - } - x_index += dx; - } - - y_index += dy; - } - - } - - } - -} - - -void saturn_state::stv_vdp2_drawgfx_rgb888( bitmap_rgb32 &dest_bmp, const rectangle &clip, uint32_t code, int flipx, int flipy, - int sx, int sy, int transparency, int alpha) -{ - rectangle myclip; - uint8_t* gfxdata; - int sprite_screen_width, sprite_screen_height; - - gfxdata = m_vdp2.gfx_decode.get() + code * 0x20; - sprite_screen_width = sprite_screen_height = 8; - - if(stv2_current_tilemap.window_control.enabled[0] || - stv2_current_tilemap.window_control.enabled[1]) - popmessage("Window Enabled for RGB888 tiles"); - - /* KW 991012 -- Added code to force clip to bitmap boundary */ - myclip = clip; - myclip &= dest_bmp.cliprect(); - { - int dx = stv2_current_tilemap.incx; - int dy = stv2_current_tilemap.incy; - - int ex = sx+sprite_screen_width; - int ey = sy+sprite_screen_height; - - int x_index_base; - int y_index; - - if( flipx ) - { - x_index_base = (sprite_screen_width-1)*dx; - dx = -dx; - } - else - { - x_index_base = 0; - } - - if( flipy ) - { - y_index = (sprite_screen_height-1)*dy; - dy = -dy; - } - else - { - y_index = 0; - } - - if( sx < myclip.left()) - { /* clip left */ - int pixels = myclip.left()-sx; - sx += pixels; - x_index_base += pixels*dx; - } - if( sy < myclip.top() ) - { /* clip top */ - int pixels = myclip.top()-sy; - sy += pixels; - y_index += pixels*dy; - } - /* NS 980211 - fixed incorrect clipping */ - if( ex > myclip.right()+1 ) - { /* clip right */ - int pixels = ex-myclip.right()-1; - ex -= pixels; - } - if( ey > myclip.bottom()+1 ) - { /* clip bottom */ - int pixels = ey-myclip.bottom()-1; - ey -= pixels; - } - - if( ex>sx ) - { /* skip if inner loop doesn't draw anything */ - for( int y=sy; y>16)*32; - uint32_t *const dest = &dest_bmp.pix(y); - - int x_index = x_index_base; - - for( int x=sx; x>16)*4+0] << 24) | (source[(x_index>>16)*4+1] << 16) | (source[(x_index>>16)*4+2] << 8) | (source[(x_index>>16)*4+3] << 0); - if ((data & 0x80000000) || (transparency & STV_TRANSPARENCY_NONE)) - { - int b = (data & 0xff0000) >> 16; - int g = (data & 0x00ff00) >> 8; - int r = (data & 0x0000ff); - - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if (transparency & STV_TRANSPARENCY_ALPHA) - dest[x] = alpha_blend_r32( dest[x], rgb_t(r, g, b), alpha ); - else - dest[x] = rgb_t(r, g, b); - } - x_index += dx; - } - - y_index += dy; - } - - } - - } -} - -void saturn_state::stv_vdp2_drawgfx_alpha(bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, - uint32_t code,uint32_t color, int flipx,int flipy,int offsx,int offsy, - int transparency, int alpha) -{ - const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); - const uint8_t *source_base = gfx->get_data(code % gfx->elements()); - int x_index_base, y_index, sx, sy, ex, ey; - int xinc, yinc; - - xinc = flipx ? -1 : 1; - yinc = flipy ? -1 : 1; - - x_index_base = flipx ? gfx->width()-1 : 0; - y_index = flipy ? gfx->height()-1 : 0; - - /* start coordinates */ - sx = offsx; - sy = offsy; - - /* end coordinates */ - ex = sx + gfx->width(); - ey = sy + gfx->height(); - - /* clip left */ - if (sx < clip.left()) - { - int pixels = clip.left()-sx; - sx += pixels; - x_index_base += xinc*pixels; - } - - /* clip top */ - if (sy < clip.top()) - { int pixels = clip.top()-sy; - sy += pixels; - y_index += yinc*pixels; - } - - /* clip right */ - if (ex > clip.right()+1) - { - ex = clip.right()+1; - } - /* clip bottom */ - if (ey > clip.bottom()+1) - { - ey = clip.bottom()+1; - } - - /* skip if inner loop doesn't draw anything */ - if (ex > sx) - { - for (int y = sy; y < ey; y++) - { - uint8_t const *const source = source_base + y_index*gfx->rowbytes(); - uint32_t *const dest = &dest_bmp.pix(y); - int x_index = x_index_base; - for (int x = sx; x < ex; x++) - { - if(stv_vdp2_window_process(x,y)) - { - int c = (source[x_index]); - if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) - dest[x] = alpha_blend_r32( dest[x], pal[c], alpha ); - } - - x_index += xinc; - } - y_index += yinc; - } - } -} - -void saturn_state::stv_vdp2_drawgfx_transpen(bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, - uint32_t code,uint32_t color, int flipx,int flipy,int offsx,int offsy, - int transparency) -{ - const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); - const uint8_t *source_base = gfx->get_data(code % gfx->elements()); - int x_index_base, y_index, sx, sy, ex, ey; - int xinc, yinc; - - xinc = flipx ? -1 : 1; - yinc = flipy ? -1 : 1; - - x_index_base = flipx ? gfx->width()-1 : 0; - y_index = flipy ? gfx->height()-1 : 0; - - /* start coordinates */ - sx = offsx; - sy = offsy; - - /* end coordinates */ - ex = sx + gfx->width(); - ey = sy + gfx->height(); - - /* clip left */ - if (sx < clip.left()) - { - int pixels = clip.left()-sx; - sx += pixels; - x_index_base += xinc*pixels; - } - - /* clip top */ - if (sy < clip.top()) - { int pixels = clip.top()-sy; - sy += pixels; - y_index += yinc*pixels; - } - - /* clip right */ - if (ex > clip.right()+1) - { - ex = clip.right()+1; - } - /* clip bottom */ - if (ey > clip.bottom()+1) - { - ey = clip.bottom()+1; - } - - /* skip if inner loop doesn't draw anything */ - if (ex > sx) - { - for (int y = sy; y < ey; y++) - { - uint8_t const *const source = source_base + y_index*gfx->rowbytes(); - uint32_t *const dest = &dest_bmp.pix(y); - int x_index = x_index_base; - for (int x = sx; x < ex; x++) - { - if(stv_vdp2_window_process(x,y)) - { - int c = (source[x_index]); - if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) - dest[x] = pal[c]; - } - - x_index += xinc; - } - y_index += yinc; - } - } -} - -void saturn_state::draw_4bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int xsize, ysize, xsize_mask, ysize_mask; - int xsrc,ysrc,xdst,ydst; - int src_offs; - uint8_t* vram = m_vdp2.gfx_decode.get(); - uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; - int scrollx = stv2_current_tilemap.scrollx; - int scrolly = stv2_current_tilemap.scrolly; - uint16_t dot_data; - uint16_t pal_bank; - - xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; - ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; - - xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; - ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; - - pal_bank = stv2_current_tilemap.bitmap_palette_number; - pal_bank+= stv2_current_tilemap.colour_ram_address_offset; - pal_bank&= 7; - pal_bank<<=8; - if(stv2_current_tilemap.fade_control & 1) - pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048)); - - for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) - { - for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) - { - if(!stv_vdp2_window_process(xdst,ydst)) - continue; - - xsrc = (xdst + scrollx) & (xsize_mask-1); - ysrc = (ydst + scrolly) & (ysize_mask-1); - src_offs = (xsrc + (ysrc*xsize)); - src_offs/= 2; - src_offs += map_offset; - src_offs &= 0x7ffff; - - dot_data = vram[src_offs] >> ((xsrc & 1) ? 0 : 4); - dot_data&= 0xf; - - if ((dot_data != 0) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) - { - dot_data += pal_bank; - - if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) - bitmap.pix(ydst, xdst) = m_palette->pen(dot_data); - else - bitmap.pix(ydst, xdst) = alpha_blend_r32(bitmap.pix(ydst, xdst), m_palette->pen(dot_data), stv2_current_tilemap.alpha); - } - } - } -} - - -void saturn_state::draw_8bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int xsize, ysize, xsize_mask, ysize_mask; - int xsrc,ysrc,xdst,ydst; - int src_offs; - uint8_t* vram = m_vdp2.gfx_decode.get(); - uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; - int scrollx = stv2_current_tilemap.scrollx; - int scrolly = stv2_current_tilemap.scrolly; - uint16_t dot_data; - uint16_t pal_bank; - int xf, yf; - - xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; - ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; - - xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; - ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; - - pal_bank = stv2_current_tilemap.bitmap_palette_number; - pal_bank+= stv2_current_tilemap.colour_ram_address_offset; - pal_bank&= 7; - pal_bank<<=8; - if(stv2_current_tilemap.fade_control & 1) - pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048)); - - for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) - { - for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) - { - if(!stv_vdp2_window_process(xdst,ydst)) - continue; - - xf = stv2_current_tilemap.incx * xdst; - xf>>=16; - yf = stv2_current_tilemap.incy * ydst; - yf>>=16; - - xsrc = (xf + scrollx) & (xsize_mask-1); - ysrc = (yf + scrolly) & (ysize_mask-1); - src_offs = (xsrc + (ysrc*xsize)); - src_offs += map_offset; - src_offs &= 0x7ffff; - - dot_data = vram[src_offs]; - - if ((dot_data != 0) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) - { - dot_data += pal_bank; - - if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) - bitmap.pix(ydst, xdst) = m_palette->pen(dot_data); - else - bitmap.pix(ydst, xdst) = alpha_blend_r32(bitmap.pix(ydst, xdst), m_palette->pen(dot_data), stv2_current_tilemap.alpha); - } - } - } -} - -void saturn_state::draw_11bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int xsize, ysize, xsize_mask, ysize_mask; - int xsrc,ysrc,xdst,ydst; - int src_offs; - uint8_t* vram = m_vdp2.gfx_decode.get(); - uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; - int scrollx = stv2_current_tilemap.scrollx; - int scrolly = stv2_current_tilemap.scrolly; - uint16_t dot_data; - uint16_t pal_bank; - int xf, yf; - - xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; - ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; - - xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; - ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; - - pal_bank = 0; - if(stv2_current_tilemap.fade_control & 1) - pal_bank = ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048)); - - for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) - { - for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) - { - if(!stv_vdp2_window_process(xdst,ydst)) - continue; - - xf = stv2_current_tilemap.incx * xdst; - xf>>=16; - yf = stv2_current_tilemap.incy * ydst; - yf>>=16; - - xsrc = (xf + scrollx) & (xsize_mask-1); - ysrc = (yf + scrolly) & (ysize_mask-1); - src_offs = (xsrc + (ysrc*xsize)); - src_offs *= 2; - src_offs += map_offset; - src_offs &= 0x7ffff; - - dot_data = ((vram[src_offs]<<8)|(vram[src_offs+1]<<0)) & 0x7ff; - - if ((dot_data != 0) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) - { - dot_data += pal_bank; - - if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) - bitmap.pix(ydst, xdst) = m_palette->pen(dot_data); - else - bitmap.pix(ydst, xdst) = alpha_blend_r32(bitmap.pix(ydst, xdst), m_palette->pen(dot_data), stv2_current_tilemap.alpha); - } - } - } -} - - -void saturn_state::draw_rgb15_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int xsize, ysize, xsize_mask, ysize_mask; - int xsrc,ysrc,xdst,ydst; - int src_offs; - uint8_t* vram = m_vdp2.gfx_decode.get(); - uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; - int scrollx = stv2_current_tilemap.scrollx; - int scrolly = stv2_current_tilemap.scrolly; - int r,g,b; - uint16_t dot_data; - int xf, yf; - - xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; - ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; - - xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; - ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; - - for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) - { - for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) - { - if(!stv_vdp2_window_process(xdst,ydst)) - continue; - - xf = stv2_current_tilemap.incx * xdst; - xf>>=16; - yf = stv2_current_tilemap.incy * ydst; - yf>>=16; - - xsrc = (xf + scrollx) & (xsize_mask-1); - ysrc = (yf + scrolly) & (ysize_mask-1); - src_offs = (xsrc + (ysrc*xsize)); - src_offs *= 2; - src_offs += map_offset; - src_offs &= 0x7ffff; - - dot_data =(vram[src_offs]<<8)|(vram[src_offs+1]<<0); - - if ((dot_data & 0x8000) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) - { - b = pal5bit((dot_data & 0x7c00) >> 10); - g = pal5bit((dot_data & 0x03e0) >> 5); - r = pal5bit((dot_data & 0x001f) >> 0); - - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) - bitmap.pix(ydst, xdst) = rgb_t(r, g, b); - else - bitmap.pix(ydst, xdst) = alpha_blend_r32( bitmap.pix(ydst, xdst), rgb_t(r, g, b), stv2_current_tilemap.alpha ); - } - } - } -} - -void saturn_state::draw_rgb32_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int xsize, ysize, xsize_mask, ysize_mask; - int xsrc,ysrc,xdst,ydst; - int src_offs; - uint8_t* vram = m_vdp2.gfx_decode.get(); - uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; - int scrollx = stv2_current_tilemap.scrollx; - int scrolly = stv2_current_tilemap.scrolly; - int r,g,b; - uint32_t dot_data; - int xf, yf; - - xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; - ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; - - xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; - ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; - - for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) - { - for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) - { - if(!stv_vdp2_window_process(xdst,ydst)) - continue; - - xf = stv2_current_tilemap.incx * xdst; - xf>>=16; - yf = stv2_current_tilemap.incy * ydst; - yf>>=16; - - xsrc = (xf + scrollx) & (xsize_mask-1); - ysrc = (yf + scrolly) & (ysize_mask-1); - src_offs = (xsrc + (ysrc*xsize)); - src_offs *= 4; - src_offs += map_offset; - src_offs &= 0x7ffff; - - dot_data = (vram[src_offs+0]<<24)|(vram[src_offs+1]<<16)|(vram[src_offs+2]<<8)|(vram[src_offs+3]<<0); - - if ((dot_data & 0x80000000) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) - { - b = ((dot_data & 0x00ff0000) >> 16); - g = ((dot_data & 0x0000ff00) >> 8); - r = ((dot_data & 0x000000ff) >> 0); - - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); - - if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) - bitmap.pix(ydst, xdst) = rgb_t(r, g, b); - else - bitmap.pix(ydst, xdst) = alpha_blend_r32( bitmap.pix(ydst, xdst), rgb_t(r, g, b), stv2_current_tilemap.alpha ); - } - } - } -} - - -void saturn_state::stv_vdp2_draw_basic_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - if (!stv2_current_tilemap.enabled) return; - - /* new bitmap code, supposed to rewrite the old one. Not supposed to be clean, but EFFICIENT! */ - if(stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) - { - switch(stv2_current_tilemap.colour_depth) - { - case 0: draw_4bpp_bitmap(bitmap,cliprect); return; - case 1: draw_8bpp_bitmap(bitmap,cliprect); return; - case 2: draw_11bpp_bitmap(bitmap, cliprect); return; - case 3: draw_rgb15_bitmap(bitmap,cliprect); return; - case 4: draw_rgb32_bitmap(bitmap,cliprect); return; - } - - /* intentional fall-through*/ - popmessage("%d %s %s %s",stv2_current_tilemap.colour_depth, - stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE ? "no trans" : "trans", - stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc", - (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom"); - } - else - { - switch(stv2_current_tilemap.colour_depth) - { - // case 0: draw_4bpp_bitmap(bitmap,cliprect); return; - case 1: draw_8bpp_bitmap(bitmap,cliprect); return; - // case 2: draw_11bpp_bitmap(bitmap, cliprect); return; - case 3: draw_rgb15_bitmap(bitmap,cliprect); return; - case 4: draw_rgb32_bitmap(bitmap,cliprect); return; - } - - /* intentional fall-through*/ - popmessage("%d %s %s %s",stv2_current_tilemap.colour_depth, - stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE ? "no trans" : "trans", - stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc", - (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom"); - } -} - - /*--------------------------------------------------------------------------- - | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address | - ----------------------------------------------------------------------------| - | | | 1 H x 1 V | bits 6-0 * 0x02000 | - | | 1 word |-------------------------------------| - | | | 2 H x 2 V | bits 8-0 * 0x00800 | - | 1 H x 1 V ---------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-0 * 0x04000 | - | | 2 words |-------------------------------------| - | | | 2 H x 2 V | bits 7-0 * 0x01000 | - ----------------------------------------------------------------------------- - | | | 1 H x 1 V | bits 6-1 * 0x04000 | - | | 1 word |-------------------------------------| - | | | 2 H x 2 V | bits 8-1 * 0x01000 | - | 2 H x 1 V ---------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-1 * 0x08000 | - | | 2 words |-------------------------------------| - | | | 2 H x 2 V | bits 7-1 * 0x02000 | - ----------------------------------------------------------------------------- - | | | 1 H x 1 V | bits 6-2 * 0x08000 | - | | 1 word |-------------------------------------| - | | | 2 H x 2 V | bits 8-2 * 0x02000 | - | 2 H x 2 V ---------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-2 * 0x10000 | - | | 2 words |-------------------------------------| - | | | 2 H x 2 V | bits 7-2 * 0x04000 | - --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/ - - -/* -4.2 Sega's Cell / Character Pattern / Page / Plane / Map system, aka a rather annoying thing that makes optimizations hard - (this is only for the normal tilemaps at the moment, i haven't even thought about the ROZ ones) - -Tiles: - -Cells are 8x8 gfx stored in video ram, they can be of various colour depths - -Character Patterns can be 8x8 or 16x16 (1 hcell x 1 vcell or 2 hcell x 2 vcell) - (a 16x16 character pattern is 4 8x8 cells put together) - -A page is made up of 64x64 cells, thats 64x64 character patterns in 8x8 mode or 32x32 character patterns in 16x16 mode. - 64 * 8 = 512 (0x200) - 32 * 16 = 512 (0x200) -A page is _always_ 512 (0x200) pixels in each direction - -in 1 word mode a 32*16 x 32*16 page is 0x0800 bytes -in 1 word mode a 64*8 x 64*8 page is 0x2000 bytes -in 2 word mode a 32*16 x 32*16 page is 0x1000 bytes -in 2 word mode a 64*8 x 64*8 page is 0x4000 bytes - -either 1, 2 or 4 pages make each plane depending on the plane size register (per tilemap) - therefore each plane is either - 64 * 8 * 1 x 64 * 8 * 1 (512 x 512) - 64 * 8 * 2 x 64 * 8 * 1 (1024 x 512) - 64 * 8 * 2 x 64 * 8 * 2 (1024 x 1024) - - 32 * 16 * 1 x 32 * 16 * 1 (512 x 512) - 32 * 16 * 2 x 32 * 16 * 1 (1024 x 512) - 32 * 16 * 2 x 32 * 16 * 2 (1024 x 1024) - -map is always enabled? - map is a 2x2 arrangement of planes, all 4 of the planes can be the same. - -*/ - -void saturn_state::stv_vdp2_get_map_page( int x, int y, int *_map, int *_page ) -{ - int page = 0; - int map; - - if ( stv2_current_tilemap.map_count == 4 ) - { - if ( stv2_current_tilemap.tile_size == 0 ) - { - if ( stv2_current_tilemap.plane_size & 1 ) - { - page = ((x >> 6) & 1); - map = (x >> 7) & 1; - } - else - { - map = (x >> 6) & 1; - } - - if ( stv2_current_tilemap.plane_size & 2 ) - { - page |= ((y >> (6-1)) & 2); - map |= ((y >> (7-1)) & 2); - } - else - { - map |= ((y >> (6-1)) & 2); - } - } - else - { - if ( stv2_current_tilemap.plane_size & 1 ) - { - page = ((x >> 5) & 1); - map = (x >> 6) & 1; - } - else - { - map = (x >> 5) & 1; - } - - if ( stv2_current_tilemap.plane_size & 2 ) - { - page |= ((y >> (5 - 1)) & 2); - map |= ((y >> (6-1)) & 2); - } - else - { - map |= ((y >> (5-1)) & 2); - } - } - } - else //16 - { - if ( stv2_current_tilemap.tile_size == 0 ) - { - if ( stv2_current_tilemap.plane_size & 1 ) - { - page = ((x >> 6) & 1); - map = (x >> 7) & 3; - } - else - { - map = (x >> 6) & 3; - } - - if ( stv2_current_tilemap.plane_size & 2 ) - { - page |= ((y >> (6-1)) & 2); - map |= ((y >> (7-2)) & 12); - } - else - { - map |= ((y >> (6-2)) & 12); - } - } - else - { - if ( stv2_current_tilemap.plane_size & 1 ) - { - page = ((x >> 5) & 1); - map = (x >> 6) & 3; - } - else - { - map = (x >> 5) & 3; - } - - if ( stv2_current_tilemap.plane_size & 2 ) - { - page |= ((y >> (5 - 1)) & 2); - map |= ((y >> (6-2)) & 12); - } - else - { - map |= ((y >> (5-2)) & 12); - } - } - } - *_page = page; - *_map = map; -} - -void saturn_state::stv_vdp2_draw_basic_tilemap(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* hopefully this is easier to follow than it is efficient .. */ - - /* I call character patterns tiles .. even if they represent up to 4 tiles */ - - /* Page variables */ - int pgtiles_x, pgpixels_x; - int pgtiles_y, pgpixels_y; - int pgsize_bytes, pgsize_dwords; - - /* Plane Variables */ - int pltiles_x, plpixels_x; - int pltiles_y, plpixels_y; - int plsize_bytes/*, plsize_dwords*/; - - /* Map Variables */ - int mptiles_x, mppixels_x; - int mptiles_y, mppixels_y; - int mpsize_bytes, mpsize_dwords; - - /* work Variables */ - int i, x, y; - int base[16]; - - int scalex,scaley; - int tilesizex, tilesizey; - int drawypos, drawxpos; - - int tilecodemin = 0x10000000, tilecodemax = 0; - - if ( stv2_current_tilemap.incx == 0 || stv2_current_tilemap.incy == 0 ) return; - - if ( stv2_current_tilemap.colour_calculation_enabled == 1 ) - { - if ( STV_VDP2_CCMD ) - { - stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ADD_BLEND; - } - else - { - stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA; - } - } - - scalex = s32(s64(0x100000000U) / s64(stv2_current_tilemap.incx)); - scaley = s32(s64(0x100000000U) / s64(stv2_current_tilemap.incy)); - tilesizex = scalex * 8; - tilesizey = scaley * 8; - drawypos = drawxpos = 0; - - /* Calculate the Number of tiles for x / y directions of each page (actually these will be the same */ - /* (2-stv2_current_tilemap.tile_size) << 5) */ - pgtiles_x = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode) - pgtiles_y = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode) - - /* Calculate the Page Size in BYTES */ - /* 64 * 64 * (1 * 2) = 0x2000 bytes - 32 * 32 * (1 * 2) = 0x0800 bytes - 64 * 64 * (2 * 2) = 0x4000 bytes - 32 * 32 * (2 * 2) = 0x1000 bytes */ - - pgsize_bytes = (pgtiles_x * pgtiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2); - - /*--------------------------------------------------------------------------- - | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address | - ----------------------------------------------------------------------------| - | | | 1 H x 1 V | bits 6-0 * 0x02000 | - | | 1 word |-------------------------------------| - | | | 2 H x 2 V | bits 8-0 * 0x00800 | - | 1 H x 1 V ---------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-0 * 0x04000 | - | | 2 words |-------------------------------------| - | | | 2 H x 2 V | bits 7-0 * 0x01000 | - ---------------------------------------------------------------------------*/ - - - /* Page Dimensions are always 0x200 pixes (512x512) */ - pgpixels_x = 0x200; - pgpixels_y = 0x200; - - /* Work out the Plane Size in tiles and Plane Dimensions (pixels) */ - switch (stv2_current_tilemap.plane_size & 3) - { - case 0: // 1 page * 1 page - pltiles_x = pgtiles_x; - plpixels_x = pgpixels_x; - pltiles_y = pgtiles_y; - plpixels_y = pgpixels_y; - break; - - case 1: // 2 pages * 1 page - pltiles_x = pgtiles_x * 2; - plpixels_x = pgpixels_x * 2; - pltiles_y = pgtiles_y; - plpixels_y = pgpixels_y; - break; - - case 3: // 2 pages * 2 pages - pltiles_x = pgtiles_x * 2; - plpixels_x = pgpixels_x * 2; - pltiles_y = pgtiles_y * 2; - plpixels_y = pgpixels_y * 2; - break; - - default: - // illegal - pltiles_x = pgtiles_x; - plpixels_x = pgpixels_x; - pltiles_y = pgtiles_y * 2; - plpixels_y = pgpixels_y * 2; - break; - } - - /* Plane Size in BYTES */ - /* still the same as before - (64 * 1) * (64 * 1) * (1 * 2) = 0x02000 bytes - (32 * 1) * (32 * 1) * (1 * 2) = 0x00800 bytes - (64 * 1) * (64 * 1) * (2 * 2) = 0x04000 bytes - (32 * 1) * (32 * 1) * (2 * 2) = 0x01000 bytes - changed - (64 * 2) * (64 * 1) * (1 * 2) = 0x04000 bytes - (32 * 2) * (32 * 1) * (1 * 2) = 0x01000 bytes - (64 * 2) * (64 * 1) * (2 * 2) = 0x08000 bytes - (32 * 2) * (32 * 1) * (2 * 2) = 0x02000 bytes - changed - (64 * 2) * (64 * 1) * (1 * 2) = 0x08000 bytes - (32 * 2) * (32 * 1) * (1 * 2) = 0x02000 bytes - (64 * 2) * (64 * 1) * (2 * 2) = 0x10000 bytes - (32 * 2) * (32 * 1) * (2 * 2) = 0x04000 bytes - */ - - plsize_bytes = (pltiles_x * pltiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2); - - /*--------------------------------------------------------------------------- - | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address | - ----------------------------------------------------------------------------- - | 1 H x 1 V see above, nothing has changed | - ----------------------------------------------------------------------------- - | | | 1 H x 1 V | bits 6-1 * 0x04000 | - | | 1 word |-------------------------------------| - | | | 2 H x 2 V | bits 8-1 * 0x01000 | - | 2 H x 1 V ---------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-1 * 0x08000 | - | | 2 words |-------------------------------------| - | | | 2 H x 2 V | bits 7-1 * 0x02000 | - ----------------------------------------------------------------------------- - | | | 1 H x 1 V | bits 6-2 * 0x08000 | - | | 1 word |-------------------------------------| - | | | 2 H x 2 V | bits 8-2 * 0x02000 | - | 2 H x 2 V ---------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-2 * 0x10000 | - | | 2 words |-------------------------------------| - | | | 2 H x 2 V | bits 7-2 * 0x04000 | - --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/ - - - /* Work out the Map Sizes in tiles, Map Dimensions */ - /* maps are always enabled? */ - if ( stv2_current_tilemap.map_count == 4 ) - { - mptiles_x = pltiles_x * 2; - mptiles_y = pltiles_y * 2; - mppixels_x = plpixels_x * 2; - mppixels_y = plpixels_y * 2; - } - else - { - mptiles_x = pltiles_x * 4; - mptiles_y = pltiles_y * 4; - mppixels_x = plpixels_x * 4; - mppixels_y = plpixels_y * 4; - } - - /* Map Size in BYTES */ - mpsize_bytes = (mptiles_x * mptiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2); - - - /*----------------------------------------------------------------------------------------------------------- - | | | 1 H x 1 V | bits 6-1 (upper mask 0x07f) (0x1ff >> 2) * 0x04000 | - | | 1 word |---------------------------------------------------------------------| - | | | 2 H x 2 V | bits 8-1 (upper mask 0x1ff) (0x1ff >> 0) * 0x01000 | - | 2 H x 1 V -----------------------------------------------------------------------------------------------| - | | | 1 H x 1 V | bits 5-1 (upper mask 0x03f) (0x1ff >> 3) * 0x08000 | - | | 2 words |---------------------------------------------------------------------| - | | | 2 H x 2 V | bits 7-1 (upper mask 0x0ff) (0x1ff >> 1) * 0x02000 | - ------------------------------------------------------------------------------------------------------------- - lower mask = ~stv2_current_tilemap.plane_size - -----------------------------------------------------------------------------------------------------------*/ - - /* Precalculate bases from MAP registers */ - for (i = 0; i < stv2_current_tilemap.map_count; i++) - { - static const int shifttable[4] = {0,1,2,2}; - - int uppermask, uppermaskshift; - - uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1); - uppermask = 0x1ff >> uppermaskshift; - - base[i] = ((stv2_current_tilemap.map_offset[i] & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes; - - base[i] &= 0x7ffff; /* shienryu needs this for the text layer, is there a problem elsewhere or is it just right without the ram cart */ - - base[i] = base[i] / 4; // convert bytes to DWORDS - } - - /* other bits */ - //stv2_current_tilemap.trans_enabled = stv2_current_tilemap.trans_enabled ? STV_TRANSPARENCY_NONE : STV_TRANSPARENCY_PEN; - stv2_current_tilemap.scrollx &= mppixels_x-1; - stv2_current_tilemap.scrolly &= mppixels_y-1; - - pgsize_dwords = pgsize_bytes /4; - //plsize_dwords = plsize_bytes /4; - mpsize_dwords = mpsize_bytes /4; - -// if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit %08x", stv2_current_tilemap.map_offset[0]); -// if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit %08x %08x %08x %08x", stv2_current_tilemap.plane_size, pgtiles_x, pltiles_x, mptiles_x); - - if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... - - /* most things we need (or don't need) to work out are now worked out */ - - for (y = 0; y> 16) < cliprect.top() ) - { - drawypos += drawyposinc; - y++; - } - mptiles_y += y; - } - else - { - drawypos += tilesizey*(stv2_current_tilemap.tile_size ? 2 : 1); - } - if ((drawypos >> 16) > cliprect.bottom()) break; - - ypageoffs = y & (pgtiles_y-1); - - for (x = 0; x> 16) < cliprect.left() ) - { - drawxpos += drawxposinc; - x++; - } - mptiles_x += x; - } - else - { - drawxpos+=tilesizex*(stv2_current_tilemap.tile_size ? 2 : 1); - } - if ( (drawxpos >> 16) > cliprect.right() ) break; - - xpageoffs = x & (pgtiles_x-1); - - stv_vdp2_get_map_page(x,y,&map,&page); - - newbase = base[map] + page * pgsize_dwords; - offs = (ypageoffs * pgtiles_x) + xpageoffs; - -/* GET THE TILE INFO ... */ - /* 1 word per tile mode with supplement bits */ - if (stv2_current_tilemap.pattern_data_size ==1) - { - data = m_vdp2_vram[newbase + offs/2]; - data = (offs&1) ? (data & 0x0000ffff) : ((data & 0xffff0000) >> 16); - - /* Supplement Mode 12 bits, no flip */ - if (stv2_current_tilemap.character_number_supplement == 1) - { -/* no flip */ flipyx = 0; -/* 8x8 */ if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x0fff) + ( (stv2_current_tilemap.supplementary_character_bits&0x1c) << 10); -/* 16x16 */ else tilecode = ((data & 0x0fff) << 2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x10) << 10); - } - /* Supplement Mode 10 bits, with flip */ - else - { -/* flip bits */ flipyx = (data & 0x0c00) >> 10; -/* 8x8 */ if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x03ff) + ( (stv2_current_tilemap.supplementary_character_bits) << 10); -/* 16x16 */ else tilecode = ((data & 0x03ff) <<2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x1c) << 10); - } - -/*>16cols*/ if (stv2_current_tilemap.colour_depth != 0) pal = ((data & 0x7000)>>8); -/*16 cols*/ else pal = ((data & 0xf000)>>12) +( (stv2_current_tilemap.supplementary_palette_bits) << 4); - - } - /* 2 words per tile, no supplement bits */ - else - { - data = m_vdp2_vram[newbase + offs]; - tilecode = (data & 0x00007fff); - pal = (data & 0x007f0000)>>16; - // specialc = (data & 0x10000000)>>28; - flipyx = (data & 0xc0000000)>>30; - } -/* WE'VE GOT THE TILE INFO ... */ - - if ( tilecode < tilecodemin ) tilecodemin = tilecode; - if ( tilecode > tilecodemax ) tilecodemax = tilecode; - -/* DECODE ANY TILES WE NEED TO DECODE */ - - pal += stv2_current_tilemap.colour_ram_address_offset<< 4; // bios uses this .. - - /*Enable fading bit*/ - if(stv2_current_tilemap.fade_control & 1) - { - /*Select fading bit*/ - pal += ((stv2_current_tilemap.fade_control & 2) ? (0x100) : (0x80)); - } - - if (stv2_current_tilemap.colour_depth == 1) - { - gfx = 2; - pal = pal >>4; - tilecode &=0x7fff; - if (tilecode == 0x7fff) tilecode--; /* prevents crash but unsure what should happen; wrapping? */ - tilecodespacing = 2; - } - else if (stv2_current_tilemap.colour_depth == 0) - { - gfx = 0; - tilecode &=0x7fff; - tilecodespacing = 1; - } -/* TILES ARE NOW DECODED */ - - if(!STV_VDP2_VRAMSZ) - tilecode &= 0x3fff; - -/* DRAW! */ - if(stv2_current_tilemap.incx != 0x10000 || - stv2_current_tilemap.incy != 0x10000 || - stv2_current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND ) - { -#define SCR_TILESIZE_X (((drawxpos + tilesizex) >> 16) - (drawxpos >> 16)) -#define SCR_TILESIZE_X1(startx) (((drawxpos + (startx) + tilesizex) >> 16) - ((drawxpos + (startx))>>16)) -#define SCR_TILESIZE_Y (((drawypos + tilesizey) >> 16) - (drawypos >> 16)) -#define SCR_TILESIZE_Y1(starty) (((drawypos + (starty) + tilesizey) >> 16) - ((drawypos + (starty))>>16)) - if (stv2_current_tilemap.tile_size==1) - { - if ( stv2_current_tilemap.colour_depth == 4 ) - { - popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 1, contact MAMEdev"); - } - else if ( stv2_current_tilemap.colour_depth == 3 ) - { - /* RGB555 */ - stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha); - stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha); - stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); - stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); - } - else - { - /* normal */ - stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha); - stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha); - stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); - stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); - } - } - else - { - if ( stv2_current_tilemap.colour_depth == 4 ) - popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 0, contact MAMEdev"); - else if ( stv2_current_tilemap.colour_depth == 3) - { - stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha); - } - else - stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha); - } - } - else - { - int olddrawxpos, olddrawypos; - olddrawxpos = drawxpos; drawxpos >>= 16; - olddrawypos = drawypos; drawypos >>= 16; - if (stv2_current_tilemap.tile_size==1) - { - if ( stv2_current_tilemap.colour_depth == 4 ) - { - /* normal */ - stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - } - else if ( stv2_current_tilemap.colour_depth == 3 ) - { - /* normal */ - stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - } - else if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) - { - /* alpha */ - stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - } - else - { - /* normal */ - stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency); - stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency); - stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency); - stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency); - } - } - else - { - if ( stv2_current_tilemap.colour_depth == 4) - { - stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - } - else if ( stv2_current_tilemap.colour_depth == 3) - { - stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - } - else - { - if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) - stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); - else - stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,stv2_current_tilemap.transparency); - } - } - drawxpos = olddrawxpos; - drawypos = olddrawypos; - } -/* DRAWN?! */ - - } - } - if ( stv2_current_tilemap.layer_name & 0x80 ) - { - static const int shifttable[4] = {0,1,2,2}; - int uppermask, uppermaskshift; - int mapsize; - uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1); - uppermask = 0x1ff >> uppermaskshift; - - if ( LOG_VDP2 ) - { - logerror( "Layer RBG%d, size %d x %d\n", stv2_current_tilemap.layer_name & 0x7f, cliprect.right() + 1, cliprect.bottom() + 1 ); - logerror( "Tiles: min %08X, max %08X\n", tilecodemin, tilecodemax ); - logerror( "MAP size in dwords %08X\n", mpsize_dwords ); - for (i = 0; i < stv2_current_tilemap.map_count; i++) - { - logerror( "Map register %d: base %08X\n", stv2_current_tilemap.map_offset[i], base[i] ); - } - } - - // store map information - stv_vdp2_layer_data_placement.map_offset_min = 0x7fffffff; - stv_vdp2_layer_data_placement.map_offset_max = 0x00000000; - - for (i = 0; i < stv2_current_tilemap.map_count; i++) - { - uint32_t max_base; - - if ( base[i] < stv_vdp2_layer_data_placement.map_offset_min ) - stv_vdp2_layer_data_placement.map_offset_min = base[i]; - - // Head On in Sega Memorial Collection 1 cares (uses RBG0 with all map regs equal to 0x20) - max_base = (base[i] + plsize_bytes/4); - if ( max_base > stv_vdp2_layer_data_placement.map_offset_max ) - stv_vdp2_layer_data_placement.map_offset_max = max_base; - } - - - mapsize = ((1 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes - - ((0 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes; - mapsize /= 4; - - stv_vdp2_layer_data_placement.map_offset_max += mapsize; - - stv_vdp2_layer_data_placement.tile_offset_min = tilecodemin * 0x20 / 4; - stv_vdp2_layer_data_placement.tile_offset_max = (tilecodemax + 1) * 0x20 / 4; - } - -} - -#define STV_VDP2_READ_VERTICAL_LINESCROLL( _val, _address ) \ - { \ - _val = m_vdp2_vram[ _address ]; \ - _val &= 0x07ffff00; \ - if ( _val & 0x04000000 ) _val |= 0xf8000000; \ - } - - -void saturn_state::stv_vdp2_check_tilemap_with_linescroll(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - rectangle mycliprect; - int cur_line = cliprect.top(); - int address; - int active_functions = 0; - int32_t scroll_values[3], prev_scroll_values[3]; - int i; - int scroll_values_equal; - int lines; - int16_t main_scrollx, main_scrolly; -// int32_t incx; - int linescroll_enable, vertical_linescroll_enable, linezoom_enable; - int vertical_linescroll_index = -1; - - // read original scroll values - main_scrollx = stv2_current_tilemap.scrollx; - main_scrolly = stv2_current_tilemap.scrolly; -// incx = stv2_current_tilemap.incx; - - // prepare linescroll flags - linescroll_enable = stv2_current_tilemap.linescroll_enable; -// stv2_current_tilemap.linescroll_enable = 0; - vertical_linescroll_enable = stv2_current_tilemap.vertical_linescroll_enable; -// stv2_current_tilemap.vertical_linescroll_enable = 0; - linezoom_enable = stv2_current_tilemap.linezoom_enable; -// stv2_current_tilemap.linezoom_enable = 0; - - // prepare working clipping rectangle - memcpy( &mycliprect, &cliprect, sizeof(rectangle) ); - - // calculate the number of active functions - if ( linescroll_enable ) active_functions++; - if ( vertical_linescroll_enable ) - { - vertical_linescroll_index = active_functions; - active_functions++; - } - if ( linezoom_enable ) active_functions++; - - // address of data table - address = stv2_current_tilemap.linescroll_table_address + active_functions*4*cliprect.top(); - - // get the first scroll values - for ( i = 0; i < active_functions; i++ ) - { - if ( i == vertical_linescroll_index ) - { - STV_VDP2_READ_VERTICAL_LINESCROLL( prev_scroll_values[i], (address / 4) + i ); - prev_scroll_values[i] -= (cur_line * stv2_current_tilemap.incy); - } - else - { - prev_scroll_values[i] = m_vdp2_vram[ (address / 4) + i ]; - } - } - - while( cur_line <= cliprect.bottom() ) - { - lines = 0; - do - { - // update address - address += active_functions*4; - - // update lines count - lines += stv2_current_tilemap.linescroll_interval; - - // get scroll values - for ( i = 0; i < active_functions; i++ ) - { - if ( i == vertical_linescroll_index ) - { - STV_VDP2_READ_VERTICAL_LINESCROLL( scroll_values[i], (address/4) + i ); - scroll_values[i] -= (cur_line + lines) * stv2_current_tilemap.incy; - } - else - { - scroll_values[i] = m_vdp2_vram[ (address / 4) + i ]; - } - } - - // compare scroll values - scroll_values_equal = 1; - for ( i = 0; i < active_functions; i++ ) - { - scroll_values_equal &= (scroll_values[i] == prev_scroll_values[i]); - } - } while( scroll_values_equal && ((cur_line + lines) <= cliprect.bottom()) ); - - // determined how many lines can be drawn - // prepare clipping rectangle - mycliprect.sety(cur_line, cur_line + lines - 1); - - // prepare scroll values - i = 0; - // linescroll - if ( linescroll_enable ) - { - prev_scroll_values[i] &= 0x07ffff00; - if ( prev_scroll_values[i] & 0x04000000 ) prev_scroll_values[i] |= 0xf8000000; - stv2_current_tilemap.scrollx = main_scrollx + (prev_scroll_values[i] >> 16); - i++; - } - // vertical line scroll - if ( vertical_linescroll_enable ) - { - stv2_current_tilemap.scrolly = main_scrolly + (prev_scroll_values[i] >> 16); - i++; - } - - // linezooom - if ( linezoom_enable ) - { - prev_scroll_values[i] &= 0x0007ff00; - if ( prev_scroll_values[i] & 0x00040000 ) prev_scroll_values[i] |= 0xfff80000; - stv2_current_tilemap.incx = prev_scroll_values[i]; - i++; - } - -// if ( LOG_VDP2 ) logerror( "Linescroll: y < %d, %d >, scrollx = %d, scrolly = %d, incx = %f\n", mycliprect.top(), mycliprect.bottom(), stv2_current_tilemap.scrollx, stv2_current_tilemap.scrolly, (float)stv2_current_tilemap.incx/65536.0 ); - // render current tilemap portion - if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap - { - stv_vdp2_draw_basic_bitmap(bitmap, mycliprect); - } - else - { - //stv_vdp2_apply_window_on_layer(mycliprect); - stv_vdp2_draw_basic_tilemap(bitmap, mycliprect); - } - - // update parameters for next iteration - memcpy( prev_scroll_values, scroll_values, sizeof(scroll_values)); - cur_line += lines; - } -} - -void saturn_state::stv_vdp2_draw_line(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int x,y; - uint8_t* gfxdata = m_vdp2.gfx_decode.get(); - uint32_t base_offs,base_mask; - uint32_t pix; - uint8_t interlace; - - interlace = (STV_VDP2_LSMD == 3)+1; - - { - base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; - - for(y=cliprect.top();y<=cliprect.bottom();y++) - { - base_offs = (STV_VDP2_LCTA & base_mask) << 1; - - if(STV_VDP2_LCCLMD) - base_offs += (y / interlace) << 1; - - for(x=cliprect.left();x<=cliprect.right();x++) - { - uint16_t pen; - - pen = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1]; - pix = bitmap.pix(y, x); - - bitmap.pix(y, x) = add_blend_r32(m_palette->pen(pen & 0x7ff),pix); - } - } - } -} - -void saturn_state::stv_vdp2_draw_mosaic(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint8_t is_roz) -{ - uint8_t h_size = STV_VDP2_MZSZH+1; - uint8_t v_size = STV_VDP2_MZSZV+1; - - if(is_roz) - v_size = 1; - - if(h_size == 1 && v_size == 1) - return; // don't bother - - if(STV_VDP2_LSMD == 3) - v_size <<= 1; - - for(int y=cliprect.top();y<=cliprect.bottom();y+=v_size) - { - for(int x=cliprect.left();x<=cliprect.right();x+=h_size) - { - uint32_t pix = bitmap.pix(y, x); - - for(int yi=0;yi>= 2; - - base_offset = 0; - base_multiplier = 1; - // offset for both enabled - if(STV_VDP2_N0VCSC && STV_VDP2_N1VCSC) - { - // NBG1 - if(stv2_current_tilemap.layer_name & 1) - base_offset = 1; - - base_multiplier = 2; - } - - base_scrollx = stv2_current_tilemap.scrollx; - base_scrolly = stv2_current_tilemap.scrolly; - //base_incx = stv2_current_tilemap.incx; - //base_incy = stv2_current_tilemap.incy; - - while(cur_char <= cliprect.right()) - { - mycliprect.setx(cur_char, cur_char + 8 - 1); - - uint32_t cur_address; - int16_t char_scroll; - - cur_address = vcsc_address; - cur_address += ((cur_char >> 3) * base_multiplier) + base_offset; - - char_scroll = m_vdp2_vram[ cur_address ] >> 16; - char_scroll &= 0x07ff; - if ( char_scroll & 0x0400 ) char_scroll |= 0xf800; - stv2_current_tilemap.scrollx = base_scrollx; - stv2_current_tilemap.scrolly = base_scrolly + (char_scroll); - //stv2_current_tilemap.incx = base_incx; - //stv2_current_tilemap.incy = base_incy; - - stv_vdp2_check_tilemap_with_linescroll(bitmap, mycliprect); - - // TODO: + 16 for tilemap and char size = 16? - cur_char += 8; - - } - } - else - stv_vdp2_check_tilemap_with_linescroll(bitmap, cliprect); - - return; - } - - if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap - { - stv_vdp2_draw_basic_bitmap(bitmap, mycliprect); - } - else - { - //stv_vdp2_apply_window_on_layer(mycliprect); - stv_vdp2_draw_basic_tilemap(bitmap, mycliprect); - } - - /* post-processing functions */ - // (TODO: needs layer bitmaps to be individual planes to work correctly) - if(stv2_current_tilemap.line_screen_enabled && TEST_FUNCTIONS) - stv_vdp2_draw_line(bitmap,cliprect); - - if(stv2_current_tilemap.mosaic_screen_enabled && TEST_FUNCTIONS) - stv_vdp2_draw_mosaic(bitmap,cliprect,stv2_current_tilemap.layer_name & 0x80); - - - { - if(stv2_current_tilemap.colour_depth == 2 && !stv2_current_tilemap.bitmap_enable) - popmessage("2048 color mode used on a non-bitmap plane"); - -// if(STV_VDP2_SCXDN0 || STV_VDP2_SCXDN1 || STV_VDP2_SCYDN0 || STV_VDP2_SCYDN1) -// popmessage("Fractional part scrolling write, contact MAMEdev"); - - /* Pukunpa */ - //if(STV_VDP2_SPWINEN) - // popmessage("Sprite Window enabled"); - - /* Capcom Collection Dai 2 - Choh Makaimura (Duh!) */ - if(STV_VDP2_MZCTL & 0x1f && POPMESSAGE_DEBUG) - popmessage("Mosaic control enabled = %04x\n",STV_VDP2_MZCTL); - - /* Bio Hazard bit 1 */ - /* Airs Adventure 0x3e */ - /* Bakuretsu Hunter */ - if(STV_VDP2_LNCLEN & ~2 && POPMESSAGE_DEBUG) - popmessage("Line Colour screen enabled %04x %08x, contact MAMEdev",STV_VDP2_LNCLEN,STV_VDP2_LCTAU<<16|STV_VDP2_LCTAL); - - /* Bio Hazard 0x400 = extended color calculation enabled */ - /* Advanced World War 0x200 = color calculation ratio mode */ - /* Whizz = 0x8100 */ - /* Dark Saviour = 0x9051 on save select screen (the one with a Saturn in the background) */ - if(STV_VDP2_CCCR & 0x6000) - popmessage("Gradation enabled %04x, contact MAMEdev",STV_VDP2_CCCR); - - /* Advanced VG, Shining Force III */ - if(STV_VDP2_SFCCMD && POPMESSAGE_DEBUG) - popmessage("Special Color Calculation enable %04x, contact MAMEdev",STV_VDP2_SFCCMD); - - /* Cleopatra Fortune Transparent Shadow */ - /* Pretty Fighter X Back & Transparent Shadow*/ - //if(STV_VDP2_SDCTL & 0x0120) - // popmessage("%s shadow select bit enabled, contact MAMEdev",STV_VDP2_SDCTL & 0x100 ? "Transparent" : "Back"); - - /* Langrisser III bit 3 normal, bit 1 during battle field */ - /* Metal Slug bit 0 during gameplay */ - /* Bug! Sega Away Logo onward 0x470 */ - /* Command & Conquer 0x0004 0xc000 */ - if(STV_VDP2_SFSEL & ~0x47f) - popmessage("Special Function Code Select enable %04x %04x, contact MAMEdev",STV_VDP2_SFSEL,STV_VDP2_SFCODE); - - /* Albert Odyssey Gaiden 0x0001 */ - /* Asuka 120% 0x0101 */ - /* Slam n Jam 96 0x0003 */ - if(STV_VDP2_ZMCTL & 0x0200) - popmessage("Reduction enable %04x, contact MAMEdev",STV_VDP2_ZMCTL); - - /* Burning Rangers and friends FMV, J.League Pro Soccer Club Wo Tsukurou!! backgrounds */ - if(STV_VDP2_SCRCTL & 0x0101 && POPMESSAGE_DEBUG) - popmessage("Vertical cell scroll enable %04x, contact MAMEdev",STV_VDP2_SCRCTL); - - /* Magical Drop III 0x200 -> color calculation window */ - /* Ide Yousuke Meijin No Shin Jissen Mahjong 0x0303 */ - /* Decathlete 0x088 */ - /* Sexy Parodius 0x2300 */ -// if(STV_VDP2_WCTLD & 0x2000) -// popmessage("Special window enabled %04x, contact MAMEdev",STV_VDP2_WCTLD); - - /* Shining Force III, After Burner 2 (doesn't make a proper use tho?) */ - /* Layer Section */ - //if(STV_VDP2_W0LWE || STV_VDP2_W1LWE) - // popmessage("Line Window %s %08x enabled, contact MAMEdev",STV_VDP2_W0LWE ? "0" : "1",STV_VDP2_W0LWTA); - - /* Akumajou Dracula, bits 2-4 */ - /* Arcana Strikes bit 5 */ - /* Choh Makai Mura 0x0055 */ - /* Sega Rally 0x0155 */ - /* Find Love 0x4400 */ - /* Dragon Ball Z 0x3800 - 0x2c00 */ - /* Assault Suit Leynos 2 0x0200*/ - /* Bug! 0x8800 */ - /* Wonder 3 0x0018 */ - if(STV_VDP2_SFPRMD & ~0xff7f) - popmessage("Special Priority Mode enabled %04x, contact MAMEdev",STV_VDP2_SFPRMD); - } -} - - -void saturn_state::stv_vdp2_copy_roz_bitmap(bitmap_rgb32 &bitmap, - bitmap_rgb32 &roz_bitmap, - const rectangle &cliprect, - int iRP, - int planesizex, - int planesizey, - int planerenderedsizex, - int planerenderedsizey) -{ - int32_t xsp, ysp, xp, yp, dx, dy, x, y, xs, ys, dxs, dys; - int32_t vcnt, hcnt; - int32_t kx, ky; - int8_t use_coeff_table, coeff_table_mode, coeff_table_size, coeff_table_shift; - int8_t screen_over_process; - uint8_t vcnt_shift, hcnt_shift; - uint8_t coeff_msb; - uint32_t *coeff_table_base, coeff_table_offset; - int32_t coeff_table_val; - uint32_t address; - uint32_t *line; - rgb_t pix; - //uint32_t coeff_line_color_screen_data; - int32_t clipxmask = 0, clipymask = 0; - - - vcnt_shift = ((STV_VDP2_LSMD & 3) == 3); - hcnt_shift = ((STV_VDP2_HRES & 2) == 2); - - planesizex--; - planesizey--; - planerenderedsizex--; - planerenderedsizey--; - - kx = RP.kx; - ky = RP.ky; - - use_coeff_table = coeff_table_mode = coeff_table_size = coeff_table_shift = 0; - coeff_table_offset = 0; - coeff_table_val = 0; - coeff_table_base = nullptr; - - if ( LOG_ROZ == 1 ) logerror( "Rendering RBG with parameter %s\n", iRP == 1 ? "A" : "B" ); - if ( LOG_ROZ == 1 ) logerror( "RPMD (parameter mode) = %x\n", STV_VDP2_RPMD ); - if ( LOG_ROZ == 1 ) logerror( "RPRCTL (parameter read control) = %04x\n", STV_VDP2_RPRCTL ); - if ( LOG_ROZ == 1 ) logerror( "KTCTL (coefficient table control) = %04x\n", STV_VDP2_KTCTL ); - if ( LOG_ROZ == 1 ) logerror( "KTAOF (coefficient table address offset) = %04x\n", STV_VDP2_KTAOF ); - if ( LOG_ROZ == 1 ) logerror( "RAOVR (screen-over process) = %x\n", STV_VDP2_RAOVR ); - if ( iRP == 1 ) - { - use_coeff_table = STV_VDP2_RAKTE; - if ( use_coeff_table == 1 ) - { - coeff_table_mode = STV_VDP2_RAKMD; - coeff_table_size = STV_VDP2_RAKDBS; - coeff_table_offset = STV_VDP2_RAKTAOS; - } - screen_over_process = STV_VDP2_RAOVR; - } - else - { - use_coeff_table = STV_VDP2_RBKTE; - if ( use_coeff_table == 1 ) - { - coeff_table_mode = STV_VDP2_RBKMD; - coeff_table_size = STV_VDP2_RBKDBS; - coeff_table_offset = STV_VDP2_RBKTAOS; - } - screen_over_process = STV_VDP2_RBOVR; - } - if ( use_coeff_table ) - { - if ( STV_VDP2_CRKTE == 0 ) - { - coeff_table_base = m_vdp2_vram.get(); - } - else - { - coeff_table_base = m_vdp2_cram.get(); - } - if ( coeff_table_size == 0 ) - { - coeff_table_offset = (coeff_table_offset & 0x0003) * 0x40000; - coeff_table_shift = 2; - } - else - { - coeff_table_offset = (coeff_table_offset & 0x0007) * 0x20000; - coeff_table_shift = 1; - } - } - - if ( stv2_current_tilemap.colour_calculation_enabled == 1 ) - { - if ( STV_VDP2_CCMD ) - { - stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ADD_BLEND; - } - else - { - stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA; - } - } - - /* clipping */ - switch( screen_over_process ) - { - case 0: - /* repeated */ - clipxmask = clipymask = 0; - break; - case 1: - /* screen over pattern */ - // TODO: not supported, cfr. STV_VDP2_OVPNRA / STV_VDP2_OVPNRB - // D-Xhird uses this on practice stage - clipxmask = ~planesizex; - clipymask = ~planesizey; - break; - case 2: - /* outside display area, scroll screen is transparent */ - clipxmask = ~planesizex; - clipymask = ~planesizey; - break; - case 3: - /* display area is 512x512, outside is transparent */ - clipxmask = ~511; - clipymask = ~511; - break; - } - - //dx = (RP.A * RP.dx) + (RP.B * RP.dy); - //dy = (RP.D * RP.dx) + (RP.E * RP.dy); - dx = mul_fixed32( RP.A, RP.dx ) + mul_fixed32( RP.B, RP.dy ); - dy = mul_fixed32( RP.D, RP.dx ) + mul_fixed32( RP.E, RP.dy ); - - //xp = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx; - //yp = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my; - xp = mul_fixed32( RP.A, RP.px - RP.cx ) + mul_fixed32( RP.B, RP.py - RP.cy ) + mul_fixed32( RP.C, RP.pz - RP.cz ) + RP.cx + RP.mx; - yp = mul_fixed32( RP.D, RP.px - RP.cx ) + mul_fixed32( RP.E, RP.py - RP.cy ) + mul_fixed32( RP.F, RP.pz - RP.cz ) + RP.cy + RP.my; - - for (vcnt = cliprect.top(); vcnt <= cliprect.bottom(); vcnt++ ) - { - /*xsp = RP.A * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) + - RP.B * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) + - RP.C * ( RP.zst - RP.pz); - ysp = RP.D * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) + - RP.E * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) + - RP.F * ( RP.zst - RP.pz );*/ - xsp = mul_fixed32( RP.A, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) + - mul_fixed32( RP.B, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) + - mul_fixed32( RP.C, RP.zst - RP.pz ); - ysp = mul_fixed32( RP.D, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) + - mul_fixed32( RP.E, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) + - mul_fixed32( RP.F, RP.zst - RP.pz ); - //xp = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx; - //yp = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my; - //dx = (RP.A * RP.dx) + (RP.B * RP.dy); - //dy = (RP.D * RP.dx) + (RP.E * RP.dy); - - line = &bitmap.pix(vcnt); - - // TODO: nuke this spaghetti code - if ( !use_coeff_table || RP.dkax == 0 ) - { - if ( use_coeff_table ) - { - switch( coeff_table_size ) - { - case 0: - address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 4; - coeff_table_val = coeff_table_base[ address / 4 ]; - //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24; - coeff_msb = (coeff_table_val & 0x80000000) > 0; - if ( coeff_table_val & 0x00800000 ) - { - coeff_table_val |= 0xff000000; - } - else - { - coeff_table_val &= 0x007fffff; - } - break; - case 1: - address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 2; - coeff_table_val = coeff_table_base[ address / 4 ]; - if ( (address & 2) == 0 ) - { - coeff_table_val >>= 16; - } - coeff_table_val &= 0xffff; - //coeff_line_color_screen_data = 0; - coeff_msb = (coeff_table_val & 0x8000) > 0; - if ( coeff_table_val & 0x4000 ) - { - coeff_table_val |= 0xffff8000; - } - else - { - coeff_table_val &= 0x3fff; - } - coeff_table_val <<= 6; /* to form 16.16 fixed point val */ - break; - default: - coeff_msb = 1; - break; - } - if ( coeff_msb ) continue; - - switch( coeff_table_mode ) - { - case 0: - kx = ky = coeff_table_val; - break; - case 1: - kx = coeff_table_val; - break; - case 2: - ky = coeff_table_val; - break; - case 3: - xp = coeff_table_val; - break; - } - } - - //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp; - //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp; - xs = mul_fixed32( kx, xsp ) + xp; - ys = mul_fixed32( ky, ysp ) + yp; - dxs = mul_fixed32( kx, mul_fixed32( dx, 1 << (16-hcnt_shift))); - dys = mul_fixed32( ky, mul_fixed32( dy, 1 << (16-hcnt_shift))); - - for (hcnt = cliprect.left(); hcnt <= cliprect.right(); xs+=dxs, ys+=dys, hcnt++ ) - { - x = xs >> 16; - y = ys >> 16; - - if ( x & clipxmask || y & clipymask ) continue; - if ( stv_vdp2_roz_window(hcnt, vcnt) == false ) - continue; - - if ( stv2_current_tilemap.roz_mode3 == true ) - { - if( stv_vdp2_roz_mode3_window(hcnt, vcnt, iRP-1) == false ) - continue; - } - - pix = roz_bitmap.pix(y & planerenderedsizey, x & planerenderedsizex); - if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) - { - if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) - { - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); - - line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha ); - } - } - else if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND) - { - if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) - { - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); - - line[hcnt] = add_blend_r32( line[hcnt], pix ); - } - } - else - { - if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) - { - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); - - line[hcnt] = pix; - } - } - } - } - else - { - for (hcnt = cliprect.left(); hcnt <= cliprect.right(); hcnt++ ) - { - switch( coeff_table_size ) - { - case 0: - address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 4; - coeff_table_val = coeff_table_base[ address / 4 ]; - //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24; - coeff_msb = (coeff_table_val & 0x80000000) > 0; - if ( coeff_table_val & 0x00800000 ) - { - coeff_table_val |= 0xff000000; - } - else - { - coeff_table_val &= 0x007fffff; - } - break; - case 1: - address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 2; - coeff_table_val = coeff_table_base[ address / 4 ]; - if ( (address & 2) == 0 ) - { - coeff_table_val >>= 16; - } - coeff_table_val &= 0xffff; - //coeff_line_color_screen_data = 0; - coeff_msb = (coeff_table_val & 0x8000) > 0; - if ( coeff_table_val & 0x4000 ) - { - coeff_table_val |= 0xffff8000; - } - else - { - coeff_table_val &= 0x3fff; - } - coeff_table_val <<= 6; /* to form 16.16 fixed point val */ - break; - default: - coeff_msb = 1; - break; - } - if ( coeff_msb ) continue; - switch( coeff_table_mode ) - { - case 0: - kx = ky = coeff_table_val; - break; - case 1: - kx = coeff_table_val; - break; - case 2: - ky = coeff_table_val; - break; - case 3: - xp = coeff_table_val; - break; - } - - //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp; - //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp; - x = mul_fixed32( kx, xsp + mul_fixed32( dx, (hcnt>>hcnt_shift) << 16 ) ) + xp; - y = mul_fixed32( ky, ysp + mul_fixed32( dy, (hcnt>>hcnt_shift) << 16 ) ) + yp; - - x >>= 16; - y >>= 16; - - if ( x & clipxmask || y & clipymask ) continue; - - pix = roz_bitmap.pix(y & planerenderedsizey, x & planerenderedsizex); - if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) - { - if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) - { - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); - - line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha ); - } - } - else if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND) - { - if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) - { - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); - - line[hcnt] = add_blend_r32( line[hcnt], pix ); - } - } - else - { - if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) - { - if(stv2_current_tilemap.fade_control & 1) - stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); - - line[hcnt] = pix; - } - } - } - } - } -} - -inline bool saturn_state::stv_vdp2_roz_window(int x, int y) -{ - int s_x=0,e_x=0,s_y=0,e_y=0; - int w0_pix, w1_pix; - uint8_t logic = STV_VDP2_R0LOG; - uint8_t w0_enable = STV_VDP2_R0W0E; - uint8_t w1_enable = STV_VDP2_R0W1E; - uint8_t w0_area = STV_VDP2_R0W0A; - uint8_t w1_area = STV_VDP2_R0W1A; - - if (w0_enable == 0 && - w1_enable == 0) - return true; - - stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y); - w0_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w0_enable, w0_area); - - stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y); - w1_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w1_enable, w1_area); - - return (logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix)); -} - -inline bool saturn_state::stv_vdp2_roz_mode3_window(int x, int y, int rot_parameter) -{ - int s_x=0,e_x=0,s_y=0,e_y=0; - int w0_pix, w1_pix; - uint8_t logic = STV_VDP2_RPLOG; - uint8_t w0_enable = STV_VDP2_RPW0E; - uint8_t w1_enable = STV_VDP2_RPW1E; - uint8_t w0_area = STV_VDP2_RPW0A; - uint8_t w1_area = STV_VDP2_RPW1A; - - if (w0_enable == 0 && - w1_enable == 0) - return rot_parameter ^ 1; - - stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y); - w0_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w0_enable, w0_area); - - stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y); - w1_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w1_enable, w1_area); - - return (logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix)) ^ rot_parameter; -} - -inline int saturn_state::get_roz_window_pixel(int s_x,int e_x,int s_y,int e_y,int x, int y,uint8_t winenable, uint8_t winarea) -{ - int res; - - res = 1; - if(winenable) - { - if(winarea) - res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x); - else - res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x) ^ 1; - } - - return res; -} - - -void saturn_state::stv_vdp2_draw_NBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint32_t base_mask; - - base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; - - /* - Colours : 16, 256, 2048, 32768, 16770000 - Char Size : 1x1 cells, 2x2 cells - Pattern Data Size : 1 word, 2 words - Plane Layouts : 1 x 1, 2 x 1, 2 x 2 - Planes : 4 - Bitmap : Possible - Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512 - Scale : 0.25 x - 256 x - Rotation : No - Linescroll : Yes - Column Scroll : Yes - Mosaic : Yes - */ - - stv2_current_tilemap.enabled = STV_VDP2_N0ON | STV_VDP2_R1ON; - -// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... - - //stv2_current_tilemap.trans_enabled = STV_VDP2_N0TPON; - if ( STV_VDP2_N0CCEN ) - { - stv2_current_tilemap.colour_calculation_enabled = 1; - stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N0CCRT)*0xff)/0x1f; - } - else - { - stv2_current_tilemap.colour_calculation_enabled = 0; - } - if ( STV_VDP2_N0TPON == 0 ) - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; - } - else - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; - } - stv2_current_tilemap.colour_depth = STV_VDP2_N0CHCN; - stv2_current_tilemap.tile_size = STV_VDP2_N0CHSZ; - stv2_current_tilemap.bitmap_enable = STV_VDP2_N0BMEN; - stv2_current_tilemap.bitmap_size = STV_VDP2_N0BMSZ; - stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N0BMP; - stv2_current_tilemap.bitmap_map = STV_VDP2_N0MP_; - stv2_current_tilemap.map_offset[0] = STV_VDP2_N0MPA | (STV_VDP2_N0MP_ << 6); - stv2_current_tilemap.map_offset[1] = STV_VDP2_N0MPB | (STV_VDP2_N0MP_ << 6); - stv2_current_tilemap.map_offset[2] = STV_VDP2_N0MPC | (STV_VDP2_N0MP_ << 6); - stv2_current_tilemap.map_offset[3] = STV_VDP2_N0MPD | (STV_VDP2_N0MP_ << 6); - stv2_current_tilemap.map_count = 4; - - stv2_current_tilemap.pattern_data_size = STV_VDP2_N0PNB; - stv2_current_tilemap.character_number_supplement = STV_VDP2_N0CNSM; - stv2_current_tilemap.special_priority_register = STV_VDP2_N0SPR; - stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN0; - stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N0SPLT; - stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N0SPCN; - - stv2_current_tilemap.scrollx = STV_VDP2_SCXIN0; - stv2_current_tilemap.scrolly = STV_VDP2_SCYIN0; - stv2_current_tilemap.incx = STV_VDP2_ZMXN0; - stv2_current_tilemap.incy = STV_VDP2_ZMYN0; - - stv2_current_tilemap.linescroll_enable = STV_VDP2_N0LSCX; - stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N0LSS); - stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA0U << 16) | STV_VDP2_LSTA0L) & base_mask) * 2; - stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N0LSCY; - stv2_current_tilemap.linezoom_enable = STV_VDP2_N0LZMX; - stv2_current_tilemap.vertical_cell_scroll_enable = STV_VDP2_N0VCSC; - - stv2_current_tilemap.plane_size = (STV_VDP2_R1ON) ? STV_VDP2_RBPLSZ : STV_VDP2_N0PLSZ; - stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N0CAOS; - stv2_current_tilemap.fade_control = (STV_VDP2_N0COEN * 1) | (STV_VDP2_N0COSL * 2); - stv_vdp2_check_fade_control_for_layer(); - stv2_current_tilemap.window_control.logic = STV_VDP2_N0LOG; - stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N0W0E; - stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N0W1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_N0SWE; - stv2_current_tilemap.window_control.area[0] = STV_VDP2_N0W0A; - stv2_current_tilemap.window_control.area[1] = STV_VDP2_N0W1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_N0SWA; - - stv2_current_tilemap.line_screen_enabled = STV_VDP2_N0LCEN; - stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N0MZE; - - stv2_current_tilemap.layer_name=(STV_VDP2_R1ON) ? 0x81 : 0; - - if ( stv2_current_tilemap.enabled && (!(STV_VDP2_R1ON))) /* TODO: check cycle pattern for RBG1 */ - { - stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG0_PNMDR, STV_VDP2_CP_NBG0_CPDR, stv2_current_tilemap.bitmap_enable ); - } - - if(STV_VDP2_R1ON) - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); - else - stv_vdp2_check_tilemap(bitmap, cliprect); -} - -void saturn_state::stv_vdp2_draw_NBG1(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint32_t base_mask; - - base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; - - /* - Colours : 16, 256, 2048, 32768 - Char Size : 1x1 cells, 2x2 cells - Pattern Data Size : 1 word, 2 words - Plane Layouts : 1 x 1, 2 x 1, 2 x 2 - Planes : 4 - Bitmap : Possible - Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512 - Scale : 0.25 x - 256 x - Rotation : No - Linescroll : Yes - Column Scroll : Yes - Mosaic : Yes - */ - stv2_current_tilemap.enabled = STV_VDP2_N1ON; - -// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... - - //stv2_current_tilemap.trans_enabled = STV_VDP2_N1TPON; - if ( STV_VDP2_N1CCEN ) - { - stv2_current_tilemap.colour_calculation_enabled = 1; - stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N1CCRT)*0xff)/0x1f; - } - else - { - stv2_current_tilemap.colour_calculation_enabled = 0; - } - if ( STV_VDP2_N1TPON == 0 ) - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; - } - else - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; - } - stv2_current_tilemap.colour_depth = STV_VDP2_N1CHCN; - stv2_current_tilemap.tile_size = STV_VDP2_N1CHSZ; - stv2_current_tilemap.bitmap_enable = STV_VDP2_N1BMEN; - stv2_current_tilemap.bitmap_size = STV_VDP2_N1BMSZ; - stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N1BMP; - stv2_current_tilemap.bitmap_map = STV_VDP2_N1MP_; - stv2_current_tilemap.map_offset[0] = STV_VDP2_N1MPA | (STV_VDP2_N1MP_ << 6); - stv2_current_tilemap.map_offset[1] = STV_VDP2_N1MPB | (STV_VDP2_N1MP_ << 6); - stv2_current_tilemap.map_offset[2] = STV_VDP2_N1MPC | (STV_VDP2_N1MP_ << 6); - stv2_current_tilemap.map_offset[3] = STV_VDP2_N1MPD | (STV_VDP2_N1MP_ << 6); - stv2_current_tilemap.map_count = 4; - - stv2_current_tilemap.pattern_data_size = STV_VDP2_N1PNB; - stv2_current_tilemap.character_number_supplement = STV_VDP2_N1CNSM; - stv2_current_tilemap.special_priority_register = STV_VDP2_N1SPR; - stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN1; - stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N1SPLT; - stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N1SPCN; - - stv2_current_tilemap.scrollx = STV_VDP2_SCXIN1; - stv2_current_tilemap.scrolly = STV_VDP2_SCYIN1; - stv2_current_tilemap.incx = STV_VDP2_ZMXN1; - stv2_current_tilemap.incy = STV_VDP2_ZMYN1; - - stv2_current_tilemap.linescroll_enable = STV_VDP2_N1LSCX; - stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N1LSS); - stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA1U << 16) | STV_VDP2_LSTA1L) & base_mask) * 2; - stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N1LSCY; - stv2_current_tilemap.linezoom_enable = STV_VDP2_N1LZMX; - stv2_current_tilemap.vertical_cell_scroll_enable = STV_VDP2_N1VCSC; - - stv2_current_tilemap.plane_size = STV_VDP2_N1PLSZ; - stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N1CAOS; - stv2_current_tilemap.fade_control = (STV_VDP2_N1COEN * 1) | (STV_VDP2_N1COSL * 2); - stv_vdp2_check_fade_control_for_layer(); - stv2_current_tilemap.window_control.logic = STV_VDP2_N1LOG; - stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N1W0E; - stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N1W1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_N1SWE; - stv2_current_tilemap.window_control.area[0] = STV_VDP2_N1W0A; - stv2_current_tilemap.window_control.area[1] = STV_VDP2_N1W1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_N1SWA; - - stv2_current_tilemap.line_screen_enabled = STV_VDP2_N1LCEN; - stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N1MZE; - - stv2_current_tilemap.layer_name=1; - - if ( stv2_current_tilemap.enabled ) - { - stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG1_PNMDR, STV_VDP2_CP_NBG1_CPDR, stv2_current_tilemap.bitmap_enable ); - } - - stv_vdp2_check_tilemap(bitmap, cliprect); -} - -void saturn_state::stv_vdp2_draw_NBG2(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* - NBG2 is the first of the 2 more basic tilemaps, it has exactly the same capabilities as NBG3 - - Colours : 16, 256 - Char Size : 1x1 cells, 2x2 cells - Pattern Data Size : 1 word, 2 words - Plane Layouts : 1 x 1, 2 x 1, 2 x 2 - Planes : 4 - Bitmap : No - Bitmap Sizes : N/A - Scale : No - Rotation : No - Linescroll : No - Column Scroll : No - Mosaic : Yes - */ - - stv2_current_tilemap.enabled = STV_VDP2_N2ON; - - /* these modes for N0 disable this layer */ - if (STV_VDP2_N0CHCN == 0x03) stv2_current_tilemap.enabled = 0; - if (STV_VDP2_N0CHCN == 0x04) stv2_current_tilemap.enabled = 0; - -// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... - - //stv2_current_tilemap.trans_enabled = STV_VDP2_N2TPON; - if ( STV_VDP2_N2CCEN ) - { - stv2_current_tilemap.colour_calculation_enabled = 1; - stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N2CCRT)*0xff)/0x1f; - } - else - { - stv2_current_tilemap.colour_calculation_enabled = 0; - } - if ( STV_VDP2_N2TPON == 0 ) - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; - } - else - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; - } - stv2_current_tilemap.colour_depth = STV_VDP2_N2CHCN; - stv2_current_tilemap.tile_size = STV_VDP2_N2CHSZ; - /* this layer can't be a bitmap,so ignore these registers*/ - stv2_current_tilemap.bitmap_enable = 0; - stv2_current_tilemap.bitmap_size = 0; - stv2_current_tilemap.bitmap_palette_number = 0; - stv2_current_tilemap.bitmap_map = 0; - stv2_current_tilemap.map_offset[0] = STV_VDP2_N2MPA | (STV_VDP2_N2MP_ << 6); - stv2_current_tilemap.map_offset[1] = STV_VDP2_N2MPB | (STV_VDP2_N2MP_ << 6); - stv2_current_tilemap.map_offset[2] = STV_VDP2_N2MPC | (STV_VDP2_N2MP_ << 6); - stv2_current_tilemap.map_offset[3] = STV_VDP2_N2MPD | (STV_VDP2_N2MP_ << 6); - stv2_current_tilemap.map_count = 4; - - stv2_current_tilemap.pattern_data_size = STV_VDP2_N2PNB; - stv2_current_tilemap.character_number_supplement = STV_VDP2_N2CNSM; - stv2_current_tilemap.special_priority_register = STV_VDP2_N2SPR; - stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN2; - stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N2SPLT; - stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N2SPCN; - - stv2_current_tilemap.scrollx = STV_VDP2_SCXN2; - stv2_current_tilemap.scrolly = STV_VDP2_SCYN2; - /*This layer can't be scaled*/ - stv2_current_tilemap.incx = 0x10000; - stv2_current_tilemap.incy = 0x10000; - - stv2_current_tilemap.linescroll_enable = 0; - stv2_current_tilemap.linescroll_interval = 0; - stv2_current_tilemap.linescroll_table_address = 0; - stv2_current_tilemap.vertical_linescroll_enable = 0; - stv2_current_tilemap.linezoom_enable = 0; - stv2_current_tilemap.vertical_cell_scroll_enable = 0; - - stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N2CAOS; - stv2_current_tilemap.fade_control = (STV_VDP2_N2COEN * 1) | (STV_VDP2_N2COSL * 2); - stv_vdp2_check_fade_control_for_layer(); - stv2_current_tilemap.window_control.logic = STV_VDP2_N2LOG; - stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N2W0E; - stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N2W1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_N2SWE; - stv2_current_tilemap.window_control.area[0] = STV_VDP2_N2W0A; - stv2_current_tilemap.window_control.area[1] = STV_VDP2_N2W1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_N2SWA; - - stv2_current_tilemap.line_screen_enabled = STV_VDP2_N2LCEN; - stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N2MZE; - - stv2_current_tilemap.layer_name=2; - - stv2_current_tilemap.plane_size = STV_VDP2_N2PLSZ; - - if ( stv2_current_tilemap.enabled ) - { - stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG2_PNMDR, STV_VDP2_CP_NBG2_CPDR, stv2_current_tilemap.bitmap_enable ); - } - - stv_vdp2_check_tilemap(bitmap, cliprect); -} - -void saturn_state::stv_vdp2_draw_NBG3(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* - NBG3 is the second of the 2 more basic tilemaps, it has exactly the same capabilities as NBG2 - - Colours : 16, 256 - Char Size : 1x1 cells, 2x2 cells - Pattern Data Size : 1 word, 2 words - Plane Layouts : 1 x 1, 2 x 1, 2 x 2 - Planes : 4 - Bitmap : No - Bitmap Sizes : N/A - Scale : No - Rotation : No - Linescroll : No - Column Scroll : No - Mosaic : Yes - */ - - stv2_current_tilemap.enabled = STV_VDP2_N3ON; - -// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... - - /* these modes for N1 disable this layer */ - if (STV_VDP2_N1CHCN == 0x03) stv2_current_tilemap.enabled = 0; - if (STV_VDP2_N1CHCN == 0x04) stv2_current_tilemap.enabled = 0; - - //stv2_current_tilemap.trans_enabled = STV_VDP2_N3TPON; - if ( STV_VDP2_N3CCEN ) - { - stv2_current_tilemap.colour_calculation_enabled = 1; - stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N3CCRT)*0xff)/0x1f; - } - else - { - stv2_current_tilemap.colour_calculation_enabled = 0; - } - if ( STV_VDP2_N3TPON == 0 ) - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; - } - else - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; - } - stv2_current_tilemap.colour_depth = STV_VDP2_N3CHCN; - stv2_current_tilemap.tile_size = STV_VDP2_N3CHSZ; - /* this layer can't be a bitmap,so ignore these registers*/ - stv2_current_tilemap.bitmap_enable = 0; - stv2_current_tilemap.bitmap_size = 0; - stv2_current_tilemap.bitmap_palette_number = 0; - stv2_current_tilemap.bitmap_map = 0; - stv2_current_tilemap.map_offset[0] = STV_VDP2_N3MPA | (STV_VDP2_N3MP_ << 6); - stv2_current_tilemap.map_offset[1] = STV_VDP2_N3MPB | (STV_VDP2_N3MP_ << 6); - stv2_current_tilemap.map_offset[2] = STV_VDP2_N3MPC | (STV_VDP2_N3MP_ << 6); - stv2_current_tilemap.map_offset[3] = STV_VDP2_N3MPD | (STV_VDP2_N3MP_ << 6); - stv2_current_tilemap.map_count = 4; - - stv2_current_tilemap.pattern_data_size = STV_VDP2_N3PNB; - stv2_current_tilemap.character_number_supplement = STV_VDP2_N3CNSM; - stv2_current_tilemap.special_priority_register = STV_VDP2_N3SPR; - stv2_current_tilemap.special_colour_control_register = STV_VDP2_N3SCC; - stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N3SPLT; - stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N3SPCN; - - stv2_current_tilemap.scrollx = STV_VDP2_SCXN3; - stv2_current_tilemap.scrolly = STV_VDP2_SCYN3; - /*This layer can't be scaled*/ - stv2_current_tilemap.incx = 0x10000; - stv2_current_tilemap.incy = 0x10000; - - stv2_current_tilemap.linescroll_enable = 0; - stv2_current_tilemap.linescroll_interval = 0; - stv2_current_tilemap.linescroll_table_address = 0; - stv2_current_tilemap.vertical_linescroll_enable = 0; - stv2_current_tilemap.linezoom_enable = 0; - stv2_current_tilemap.vertical_cell_scroll_enable = 0; - - stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N3CAOS; - stv2_current_tilemap.fade_control = (STV_VDP2_N3COEN * 1) | (STV_VDP2_N3COSL * 2); - stv_vdp2_check_fade_control_for_layer(); - stv2_current_tilemap.window_control.logic = STV_VDP2_N3LOG; - stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N3W0E; - stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N3W1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_N3SWE; - stv2_current_tilemap.window_control.area[0] = STV_VDP2_N3W0A; - stv2_current_tilemap.window_control.area[1] = STV_VDP2_N3W1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_N3SWA; - - stv2_current_tilemap.line_screen_enabled = STV_VDP2_N3LCEN; - stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N3MZE; - - stv2_current_tilemap.layer_name=3; - - stv2_current_tilemap.plane_size = STV_VDP2_N3PLSZ; - - if ( stv2_current_tilemap.enabled ) - { - stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG3_PNMDR, STV_VDP2_CP_NBG3_CPDR, stv2_current_tilemap.bitmap_enable ); - } - - stv_vdp2_check_tilemap(bitmap, cliprect); -} - - -void saturn_state::stv_vdp2_draw_rotation_screen(bitmap_rgb32 &bitmap, const rectangle &cliprect, int iRP) -{ - rectangle roz_clip_rect; - int planesizex = 0, planesizey = 0; - int planerenderedsizex, planerenderedsizey; - uint8_t colour_calculation_enabled; - uint8_t fade_control; - - if ( iRP == 1) - { - stv2_current_tilemap.bitmap_map = STV_VDP2_RAMP_; - stv2_current_tilemap.map_offset[0] = STV_VDP2_RAMPA | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[1] = STV_VDP2_RAMPB | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[2] = STV_VDP2_RAMPC | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[3] = STV_VDP2_RAMPD | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[4] = STV_VDP2_RAMPE | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[5] = STV_VDP2_RAMPF | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[6] = STV_VDP2_RAMPG | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[7] = STV_VDP2_RAMPH | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[8] = STV_VDP2_RAMPI | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[9] = STV_VDP2_RAMPJ | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[10] = STV_VDP2_RAMPK | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[11] = STV_VDP2_RAMPL | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[12] = STV_VDP2_RAMPM | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[13] = STV_VDP2_RAMPN | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[14] = STV_VDP2_RAMPO | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_offset[15] = STV_VDP2_RAMPP | (STV_VDP2_RAMP_ << 6); - stv2_current_tilemap.map_count = 16; - } - else - { - stv2_current_tilemap.bitmap_map = STV_VDP2_RBMP_; - stv2_current_tilemap.map_offset[0] = STV_VDP2_RBMPA | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[1] = STV_VDP2_RBMPB | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[2] = STV_VDP2_RBMPC | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[3] = STV_VDP2_RBMPD | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[4] = STV_VDP2_RBMPE | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[5] = STV_VDP2_RBMPF | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[6] = STV_VDP2_RBMPG | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[7] = STV_VDP2_RBMPH | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[8] = STV_VDP2_RBMPI | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[9] = STV_VDP2_RBMPJ | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[10] = STV_VDP2_RBMPK | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[11] = STV_VDP2_RBMPL | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[12] = STV_VDP2_RBMPM | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[13] = STV_VDP2_RBMPN | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[14] = STV_VDP2_RBMPO | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_offset[15] = STV_VDP2_RBMPP | (STV_VDP2_RBMP_ << 6); - stv2_current_tilemap.map_count = 16; - } - - stv_vdp2_fill_rotation_parameter_table(iRP); - - if ( iRP == 1 ) - { - stv2_current_tilemap.plane_size = STV_VDP2_RAPLSZ; - } - else - { - stv2_current_tilemap.plane_size = STV_VDP2_RBPLSZ; - } - - if (stv2_current_tilemap.bitmap_enable) - { - switch (stv2_current_tilemap.bitmap_size) - { - case 0: planesizex=512; planesizey=256; break; - case 1: planesizex=512; planesizey=512; break; - case 2: planesizex=1024; planesizey=256; break; - case 3: planesizex=1024; planesizey=512; break; - } - } - else - { - switch( stv2_current_tilemap.plane_size ) - { - case 0: - planesizex = planesizey = 2048; - break; - case 1: - planesizex = 4096; - planesizey = 2048; - break; - case 2: - planesizex = 0; - planesizey = 0; - break; - case 3: - planesizex = planesizey = 4096; - break; - } - } - - if ( stv_vdp2_is_rotation_applied() == 0 ) - { - stv2_current_tilemap.scrollx = stv_current_rotation_parameter_table.mx >> 16; - stv2_current_tilemap.scrolly = stv_current_rotation_parameter_table.my >> 16; - - if(stv2_current_tilemap.roz_mode3 == true) - { - // TODO: Cotton 2 enables mode 3 without an actual RP window enabled - // Technically you could use split screen effect without rotation applied, - // which will be annoying to emulate with this video structure. - // Let's see if anything will do it ... - if(STV_VDP2_RPW0E || STV_VDP2_RPW1E) - popmessage("ROZ Mode 3 window enabled without zooming, contact MAMEdev!"); - - if(iRP == 2) - return; - } - - // TODO: legacy code, to be removed - stv2_current_tilemap.window_control.logic = STV_VDP2_R0LOG; - stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_R0W0E; - stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_R0W1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWE; - stv2_current_tilemap.window_control.area[0] = STV_VDP2_R0W0A; - stv2_current_tilemap.window_control.area[1] = STV_VDP2_R0W1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWA; - - rectangle mycliprect = cliprect; - - if ( stv2_current_tilemap.window_control.enabled[0] || stv2_current_tilemap.window_control.enabled[1] ) - { - //popmessage("Window control for RBG"); - stv_vdp2_apply_window_on_layer(mycliprect); - stv2_current_tilemap.window_control.enabled[0] = 0; - stv2_current_tilemap.window_control.enabled[1] = 0; - } - - stv_vdp2_check_tilemap(bitmap,mycliprect); - } - else - { - if ( !m_vdp2.roz_bitmap[iRP-1].valid() ) - m_vdp2.roz_bitmap[iRP-1].allocate(4096, 4096); - - roz_clip_rect.min_x = roz_clip_rect.min_y = 0; - if ( (iRP == 1 && STV_VDP2_RAOVR == 3) || - (iRP == 2 && STV_VDP2_RBOVR == 3) ) - { - roz_clip_rect.max_x = roz_clip_rect.max_y = 511; - planerenderedsizex = planerenderedsizey = 512; - } - else if (stv_vdp2_are_map_registers_equal() && - !stv2_current_tilemap.bitmap_enable) - { - roz_clip_rect.max_x = (planesizex / 4) - 1; - roz_clip_rect.max_y = (planesizey / 4) - 1; - planerenderedsizex = planesizex / 4; - planerenderedsizey = planesizey / 4; - } - else - { - roz_clip_rect.max_x = planesizex - 1; - roz_clip_rect.max_y = planesizey - 1; - planerenderedsizex = planesizex; - planerenderedsizey = planesizey; - } - - - colour_calculation_enabled = stv2_current_tilemap.colour_calculation_enabled; - stv2_current_tilemap.colour_calculation_enabled = 0; -// window_control = stv2_current_tilemap.window_control; -// stv2_current_tilemap.window_control = 0; - fade_control = stv2_current_tilemap.fade_control; - stv2_current_tilemap.fade_control = 0; - g_profiler.start(PROFILER_USER1); - if ( LOG_VDP2 ) logerror( "Checking for cached RBG bitmap, cache_dirty = %d, memcmp() = %d\n", stv_rbg_cache_data.is_cache_dirty, memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap))); - if ( (stv_rbg_cache_data.is_cache_dirty & iRP) || - memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap)) != 0 ) - { - m_vdp2.roz_bitmap[iRP-1].fill(m_palette->black_pen(), roz_clip_rect ); - stv_vdp2_check_tilemap(m_vdp2.roz_bitmap[iRP-1], roz_clip_rect); - // prepare cache data - stv_rbg_cache_data.watch_vdp2_vram_writes |= iRP; - stv_rbg_cache_data.is_cache_dirty &= ~iRP; - memcpy(&stv_rbg_cache_data.layer_data[iRP-1], &stv2_current_tilemap, sizeof(stv2_current_tilemap)); - stv_rbg_cache_data.map_offset_min[iRP-1] = stv_vdp2_layer_data_placement.map_offset_min; - stv_rbg_cache_data.map_offset_max[iRP-1] = stv_vdp2_layer_data_placement.map_offset_max; - stv_rbg_cache_data.tile_offset_min[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_min; - stv_rbg_cache_data.tile_offset_max[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_max; - if ( LOG_VDP2 ) logerror( "Cache watch: map = %06X - %06X, tile = %06X - %06X\n", stv_rbg_cache_data.map_offset_min[iRP-1], - stv_rbg_cache_data.map_offset_max[iRP-1], stv_rbg_cache_data.tile_offset_min[iRP-1], stv_rbg_cache_data.tile_offset_max[iRP-1] ); - } - - g_profiler.stop(); - - stv2_current_tilemap.colour_calculation_enabled = colour_calculation_enabled; - if ( colour_calculation_enabled ) - { - stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA; - } - -#if 0 - // old reference code - mycliprect = cliprect; - - if ( stv2_current_tilemap.window_control.enabled[0] || stv2_current_tilemap.window_control.enabled[1] ) - { - //popmessage("Window control for RBG"); - stv_vdp2_apply_window_on_layer(mycliprect); - stv2_current_tilemap.window_control.enabled[0] = 0; - stv2_current_tilemap.window_control.enabled[1] = 0; - } -#endif - - stv2_current_tilemap.fade_control = fade_control; - - g_profiler.start(PROFILER_USER2); - stv_vdp2_copy_roz_bitmap(bitmap, m_vdp2.roz_bitmap[iRP-1], cliprect, iRP, planesizex, planesizey, planerenderedsizex, planerenderedsizey ); - g_profiler.stop(); - } - -} - -void saturn_state::stv_vdp2_draw_RBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* - Colours : 16, 256, 2048, 32768, 16770000 - Char Size : 1x1 cells, 2x2 cells - Pattern Data Size : 1 word, 2 words - Plane Layouts : 1 x 1, 2 x 1, 2 x 2 - Planes : 4 - Bitmap : Possible - Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512 - Scale : 0.25 x - 256 x - Rotation : Yes - Linescroll : Yes - Column Scroll : Yes - Mosaic : Yes - */ - - stv2_current_tilemap.enabled = STV_VDP2_R0ON; - -// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... - - //stv2_current_tilemap.trans_enabled = STV_VDP2_R0TPON; - if ( STV_VDP2_R0CCEN ) - { - stv2_current_tilemap.colour_calculation_enabled = 1; - stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_R0CCRT)*0xff)/0x1f; - } - else - { - stv2_current_tilemap.colour_calculation_enabled = 0; - } - if ( STV_VDP2_R0TPON == 0 ) - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; - } - else - { - stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; - } - stv2_current_tilemap.colour_depth = STV_VDP2_R0CHCN; - stv2_current_tilemap.tile_size = STV_VDP2_R0CHSZ; - stv2_current_tilemap.bitmap_enable = STV_VDP2_R0BMEN; - stv2_current_tilemap.bitmap_size = STV_VDP2_R0BMSZ; - stv2_current_tilemap.bitmap_palette_number = STV_VDP2_R0BMP; - - stv2_current_tilemap.pattern_data_size = STV_VDP2_R0PNB; - stv2_current_tilemap.character_number_supplement = STV_VDP2_R0CNSM; - stv2_current_tilemap.special_priority_register = STV_VDP2_R0SPR; - stv2_current_tilemap.special_colour_control_register = STV_VDP2_R0SCC; - stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_R0SPLT; - stv2_current_tilemap.supplementary_character_bits = STV_VDP2_R0SPCN; - - stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_R0CAOS; - stv2_current_tilemap.fade_control = (STV_VDP2_R0COEN * 1) | (STV_VDP2_R0COSL * 2); - stv_vdp2_check_fade_control_for_layer(); - // disable these, we apply them in the roz routines (they were interfering with stv_vdp2_roz_window() ?) - stv2_current_tilemap.window_control.logic = 0; //STV_VDP2_R0LOG; - stv2_current_tilemap.window_control.enabled[0] = 0; //STV_VDP2_R0W0E; - stv2_current_tilemap.window_control.enabled[1] = 0; //STV_VDP2_R0W1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWE; - stv2_current_tilemap.window_control.area[0] = 0; //STV_VDP2_R0W0A; - stv2_current_tilemap.window_control.area[1] = 0; //STV_VDP2_R0W1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWA; - - stv2_current_tilemap.scrollx = 0; - stv2_current_tilemap.scrolly = 0; - stv2_current_tilemap.incx = 0x10000; - stv2_current_tilemap.incy = 0x10000; - - stv2_current_tilemap.linescroll_enable = 0; - stv2_current_tilemap.linescroll_interval = 0; - stv2_current_tilemap.linescroll_table_address = 0; - stv2_current_tilemap.vertical_linescroll_enable = 0; - stv2_current_tilemap.linezoom_enable = 0; - stv2_current_tilemap.vertical_cell_scroll_enable = 0; - - stv2_current_tilemap.line_screen_enabled = STV_VDP2_R0LCEN; - stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_R0MZE; - - /*Use 0x80 as a normal/rotate switch*/ - stv2_current_tilemap.layer_name=0x80; - - if ( !stv2_current_tilemap.enabled ) return; - - switch(STV_VDP2_RPMD) - { - case 0://Rotation Parameter A - stv2_current_tilemap.roz_mode3 = false; - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 ); - break; - case 1://Rotation Parameter B - //case 2: - stv2_current_tilemap.roz_mode3 = false; - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); - break; - case 2://Rotation Parameter A & B CKTE - stv2_current_tilemap.roz_mode3 = false; - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 ); - break; - case 3://Rotation Parameter A & B Window - stv2_current_tilemap.roz_mode3 = true; - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); - stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 ); - break; - } - -} - -void saturn_state::stv_vdp2_draw_back(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint8_t const *const gfxdata = m_vdp2.gfx_decode.get(); - - uint8_t interlace = (STV_VDP2_LSMD == 3)+1; - -// popmessage("Back screen %08x %08x %08x",STV_VDP2_BDCLMD,STV_VDP2_BKCLMD,STV_VDP2_BKTA); - - /* draw black if BDCLMD and DISP are cleared */ - if(!(STV_VDP2_BDCLMD) && !(STV_VDP2_DISP)) - bitmap.fill(m_palette->black_pen(), cliprect); - else - { - uint32_t base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; - - for(int y=cliprect.top();y<=cliprect.bottom();y++) - { - uint32_t base_offs = ((STV_VDP2_BKTA ) & base_mask) << 1; - if(STV_VDP2_BKCLMD) - base_offs += ((y / interlace) << 1); - - for(int x=cliprect.left();x<=cliprect.right();x++) - { - uint16_t dot = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1]; - int b = pal5bit((dot & 0x7c00) >> 10); - int g = pal5bit((dot & 0x03e0) >> 5); - int r = pal5bit( dot & 0x001f); - if(STV_VDP2_BKCOEN) - stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_BKCOSL ); - - bitmap.pix(y, x) = rgb_t(r, g, b); - } - } - } -} - -uint32_t saturn_state::saturn_vdp2_vram_r(offs_t offset) -{ - return m_vdp2_vram[offset]; -} - -void saturn_state::saturn_vdp2_vram_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - uint8_t* gfxdata = m_vdp2.gfx_decode.get(); - - COMBINE_DATA(&m_vdp2_vram[offset]); - - data = m_vdp2_vram[offset]; - /* put in gfx region for easy decoding */ - gfxdata[offset*4+0] = (data & 0xff000000) >> 24; - gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16; - gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8; - gfxdata[offset*4+3] = (data & 0x000000ff) >> 0; - - m_gfxdecode->gfx(0)->mark_dirty(offset/8); - m_gfxdecode->gfx(1)->mark_dirty(offset/8); - m_gfxdecode->gfx(2)->mark_dirty(offset/8); - m_gfxdecode->gfx(3)->mark_dirty(offset/8); - - /* 8-bit tiles overlap, so this affects the previous one as well */ - if (offset/8 != 0) - { - m_gfxdecode->gfx(2)->mark_dirty(offset/8 - 1); - m_gfxdecode->gfx(3)->mark_dirty(offset/8 - 1); - } - - if ( stv_rbg_cache_data.watch_vdp2_vram_writes ) - { - if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_A ) - { - if ( (offset >= stv_rbg_cache_data.map_offset_min[0] && - offset < stv_rbg_cache_data.map_offset_max[0]) || - (offset >= stv_rbg_cache_data.tile_offset_min[0] && - offset < stv_rbg_cache_data.tile_offset_max[0]) ) - { - if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 1, write at offset = %06X\n", offset ); - stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_A; - stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_A; - } - } - if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_B ) - { - if ( (offset >= stv_rbg_cache_data.map_offset_min[1] && - offset < stv_rbg_cache_data.map_offset_max[1]) || - (offset >= stv_rbg_cache_data.tile_offset_min[1] && - offset < stv_rbg_cache_data.tile_offset_max[1]) ) - { - if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 2, write at offset = %06X\n", offset ); - stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_B; - stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_B; - } - } - } -} - -uint16_t saturn_state::saturn_vdp2_regs_r(offs_t offset) -{ - switch(offset) - { - case 0x002/2: - { - /* latch h/v signals through HV latch*/ - if(!STV_VDP2_EXLTEN) - { - if(!machine().side_effects_disabled()) - { - m_vdp2.h_count = get_hcounter(); - m_vdp2.v_count = get_vcounter(); - /* latch flag */ - m_vdp2.exltfg |= 1; - } - } - - break; - } - case 0x004/2: - { - /*Screen Status Register*/ - /*VBLANK HBLANK ODD PAL */ - m_vdp2_regs[offset] = (m_vdp2.exltfg<<9) | - (m_vdp2.exsyfg<<8) | - (get_vblank() << 3) | - (get_hblank() << 2) | - (get_odd_bit() << 1) | - (m_vdp2.pal << 0); - - /* vblank bit is always 1 if DISP bit is disabled */ - if(!STV_VDP2_DISP) - m_vdp2_regs[offset] |= 1 << 3; - - /* HV latches clears if this register is read */ - if(!machine().side_effects_disabled()) - { - m_vdp2.exltfg &= ~1; - m_vdp2.exsyfg &= ~1; - } - break; - } - case 0x006/2: - { - m_vdp2_regs[offset] = (STV_VDP2_VRAMSZ << 15) | - ((0 << 0) & 0xf); // VDP2 version - - /* Games basically r/w the entire VDP2 register area when this is tripped. (example: Silhouette Mirage) - Disable log for the time being. */ - //if(!machine().side_effects_disabled()) - // printf("Warning: VDP2 version read\n"); - break; - } - - /* HCNT */ - case 0x008/2: - { - m_vdp2_regs[offset] = (m_vdp2.h_count); - break; - } - - /* VCNT */ - case 0x00a/2: - { - m_vdp2_regs[offset] = (m_vdp2.v_count); - break; - } - - default: - //if(!machine().side_effects_disabled()) - // printf("VDP2: read from register %08x %08x\n",offset*4,mem_mask); - break; - } - - return m_vdp2_regs[offset]; -} - -uint32_t saturn_state::saturn_vdp2_cram_r(offs_t offset) -{ - offset &= (0xfff) >> (2); - return m_vdp2_cram[offset]; -} - - - - -void saturn_state::saturn_vdp2_cram_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - int r,g,b; - uint8_t cmode0; - - cmode0 = (STV_VDP2_CRMD & 3) == 0; - - offset &= (0xfff) >> (2); - COMBINE_DATA(&m_vdp2_cram[offset]); - - switch( STV_VDP2_CRMD ) - { - /*Mode 2/3*/ - case 2: - case 3: - { - //offset &= (0xfff) >> 2; - - b = ((m_vdp2_cram[offset] & 0x00ff0000) >> 16); - g = ((m_vdp2_cram[offset] & 0x0000ff00) >> 8); - r = ((m_vdp2_cram[offset] & 0x000000ff) >> 0); - m_palette->set_pen_color(offset,rgb_t(r,g,b)); - m_palette->set_pen_color(offset^0x400,rgb_t(r,g,b)); - } - break; - /*Mode 0*/ - case 0: - case 1: - { - offset &= (0xfff) >> (cmode0+2); - - b = ((m_vdp2_cram[offset] & 0x00007c00) >> 10); - g = ((m_vdp2_cram[offset] & 0x000003e0) >> 5); - r = ((m_vdp2_cram[offset] & 0x0000001f) >> 0); - m_palette->set_pen_color((offset*2)+1,pal5bit(r),pal5bit(g),pal5bit(b)); - if(cmode0) - m_palette->set_pen_color(((offset*2)+1)^0x400,pal5bit(r),pal5bit(g),pal5bit(b)); - - b = ((m_vdp2_cram[offset] & 0x7c000000) >> 26); - g = ((m_vdp2_cram[offset] & 0x03e00000) >> 21); - r = ((m_vdp2_cram[offset] & 0x001f0000) >> 16); - m_palette->set_pen_color(offset*2,pal5bit(r),pal5bit(g),pal5bit(b)); - if(cmode0) - m_palette->set_pen_color((offset*2)^0x400,pal5bit(r),pal5bit(g),pal5bit(b)); - } - break; - } -} - -void saturn_state::refresh_palette_data( void ) -{ - int r,g,b; - int c_i; - uint8_t bank; - - switch( STV_VDP2_CRMD ) - { - case 2: - case 3: - { - for(c_i=0;c_i<0x400;c_i++) - { - b = ((m_vdp2_cram[c_i] & 0x00ff0000) >> 16); - g = ((m_vdp2_cram[c_i] & 0x0000ff00) >> 8); - r = ((m_vdp2_cram[c_i] & 0x000000ff) >> 0); - m_palette->set_pen_color(c_i,rgb_t(r,g,b)); - m_palette->set_pen_color(c_i+0x400,rgb_t(r,g,b)); - } - } - break; - case 0: - { - for(bank=0;bank<2;bank++) - { - for(c_i=0;c_i<0x400;c_i++) - { - b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10); - g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5); - r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0); - m_palette->set_pen_color((c_i*2)+1+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b)); - b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26); - g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21); - r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16); - m_palette->set_pen_color(c_i*2+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b)); - } - } - } - break; - case 1: - { - for(c_i=0;c_i<0x800;c_i++) - { - b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10); - g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5); - r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0); - m_palette->set_pen_color((c_i*2)+1,pal5bit(r),pal5bit(g),pal5bit(b)); - b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26); - g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21); - r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16); - m_palette->set_pen_color(c_i*2,pal5bit(r),pal5bit(g),pal5bit(b)); - } - } - break; - } -} - -void saturn_state::saturn_vdp2_regs_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&m_vdp2_regs[offset]); - - if(m_vdp2.old_crmd != STV_VDP2_CRMD) - { - m_vdp2.old_crmd = STV_VDP2_CRMD; - refresh_palette_data(); - } - if(m_vdp2.old_tvmd != STV_VDP2_TVMD) - { - m_vdp2.old_tvmd = STV_VDP2_TVMD; - stv_vdp2_dynamic_res_change(); - } - - if(STV_VDP2_VRAMSZ) - printf("VDP2 sets up 8 Mbit VRAM!\n"); -} - -int saturn_state::get_hblank_duration( void ) -{ - int res; - - res = (STV_VDP2_HRES & 1) ? 455 : 427; - - /* double pump horizontal max res */ - if(STV_VDP2_HRES & 2) - res<<=1; - - return res; -} - -/*some vblank lines measurements (according to Charles MacDonald)*/ -/* TODO: interlace mode "eats" one line, should be 262.5 */ -int saturn_state::get_vblank_duration( void ) -{ - int res; - - res = (m_vdp2.pal) ? 313 : 263; - - /* compensate for interlacing */ - if((STV_VDP2_LSMD & 3) == 3) - res<<=1; - - if(STV_VDP2_HRES & 4) - res = (STV_VDP2_HRES & 1) ? 561 : 525; //Hi-Vision / 31kHz Monitor - - return res; -} - -int saturn_state::get_pixel_clock( void ) -{ - int res,divider; - - res = (m_vdp2.dotsel ? MASTER_CLOCK_352 : MASTER_CLOCK_320).value(); - /* TODO: divider is ALWAYS 8, this thing is just to over-compensate for MAME framework faults ... */ - divider = 8; - - if(STV_VDP2_HRES & 2) - divider>>=1; - - if((STV_VDP2_LSMD & 3) == 3) - divider>>=1; - - if(STV_VDP2_HRES & 4) //TODO - divider>>=1; - - return res/divider; -} - -/* TODO: hblank position and hblank firing doesn't really match HW behaviour. */ -uint8_t saturn_state::get_hblank( void ) -{ - const rectangle &visarea = m_screen->visible_area(); - int cur_h = m_screen->hpos(); - - if (cur_h > visarea.right()) //TODO - return 1; - - return 0; -} - -uint8_t saturn_state::get_vblank( void ) -{ - int cur_v,vblank; - cur_v = m_screen->vpos(); - - vblank = get_vblank_start_position() * get_ystep_count(); - - if (cur_v >= vblank) - return 1; - - return 0; -} - -uint8_t saturn_state::get_odd_bit( void ) -{ - if(STV_VDP2_HRES & 4) //exclusive monitor mode makes this bit to be always 1 - return 1; - -// TODO: seabass explicitly wants this bit to be 0 when screen is disabled from bios to game transition. -// But the documentation claims that "non-interlaced" mode is always 1. -// grdforce tests this bit to be 1 from title screen to gameplay, ditto for finlarch/sasissu/magzun. -// Assume documentation is wrong and actually always flip this bit. - return m_vdp2.odd;//m_screen->frame_number() & 1; -} - -int saturn_state::get_vblank_start_position( void ) -{ - // TODO: test says that second setting happens at 241, might need further investigation ... - // also first one happens at 240, but needs mods in SMPC otherwise we get 2 credits at startup in shanhigw and sokyugrt - // (i.e. make a special screen device that handles this for us) - const int d_vres[4] = { 224, 240, 256, 256 }; - int vres_mask; - int vblank_line; - - vres_mask = (m_vdp2.pal << 1)|1; //PAL uses mask 3, NTSC uses mask 1 - vblank_line = d_vres[STV_VDP2_VRES & vres_mask]; - - return vblank_line; -} - -int saturn_state::get_ystep_count( void ) -{ - int max_y = m_screen->height(); - int y_step; - - y_step = 2; - - if((max_y == 263 && m_vdp2.pal == 0) || (max_y == 313 && m_vdp2.pal == 1)) - y_step = 1; - - return y_step; -} - -/* TODO: these needs to be checked via HW tests! */ -int saturn_state::get_hcounter( void ) -{ - int hcount; - - hcount = m_screen->hpos(); - - switch(STV_VDP2_HRES & 6) - { - /* Normal */ - case 0: - hcount &= 0x1ff; - hcount <<= 1; - break; - /* Hi-Res */ - case 2: - hcount &= 0x3ff; - break; - /* Exclusive Normal*/ - case 4: - hcount &= 0x1ff; - break; - /* Exclusive Hi-Res */ - case 6: - hcount >>= 1; - hcount &= 0x1ff; - break; - } - - return hcount; -} - -int saturn_state::get_vcounter( void ) -{ - int vcount; - - vcount = m_screen->vpos(); - - /* Exclusive Monitor */ - if(STV_VDP2_HRES & 4) - return vcount & 0x3ff; - - /* Double Density Interlace */ - if((STV_VDP2_LSMD & 3) == 3) - return (vcount & ~1) | (m_screen->frame_number() & 1); - - /* docs says << 1, but according to HW tests it's a typo. */ - assert((vcount & 0x1ff) < std::size(true_vcount)); - return (true_vcount[vcount & 0x1ff][STV_VDP2_VRES]); // Non-interlace -} - -void saturn_state::stv_vdp2_state_save_postload( void ) -{ - uint8_t *gfxdata = m_vdp2.gfx_decode.get(); - int offset; - uint32_t data; - - for ( offset = 0; offset < 0x100000/4; offset++ ) - { - data = m_vdp2_vram[offset]; - /* put in gfx region for easy decoding */ - gfxdata[offset*4+0] = (data & 0xff000000) >> 24; - gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16; - gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8; - gfxdata[offset*4+3] = (data & 0x000000ff) >> 0; - - m_gfxdecode->gfx(0)->mark_dirty(offset/8); - m_gfxdecode->gfx(1)->mark_dirty(offset/8); - m_gfxdecode->gfx(2)->mark_dirty(offset/8); - m_gfxdecode->gfx(3)->mark_dirty(offset/8); - - /* 8-bit tiles overlap, so this affects the previous one as well */ - if (offset/8 != 0) - { - m_gfxdecode->gfx(2)->mark_dirty(offset/8 - 1); - m_gfxdecode->gfx(3)->mark_dirty(offset/8 - 1); - } - - } - - memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data)); - stv_rbg_cache_data.is_cache_dirty = 3; - memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement)); - - refresh_palette_data(); -} - -void saturn_state::stv_vdp2_exit ( void ) -{ - m_vdp2.roz_bitmap[0].reset(); - m_vdp2.roz_bitmap[1].reset(); -} - -int saturn_state::stv_vdp2_start ( void ) -{ - machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&saturn_state::stv_vdp2_exit, this)); - - m_vdp2_regs = make_unique_clear(0x040000/2 ); - m_vdp2_vram = make_unique_clear(0x100000/4 ); - m_vdp2_cram = make_unique_clear(0x080000/4 ); - m_vdp2.gfx_decode = std::make_unique(0x100000 ); - -// m_gfxdecode->gfx(0)->granularity()=4; -// m_gfxdecode->gfx(1)->granularity()=4; - - memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data)); - stv_rbg_cache_data.is_cache_dirty = 3; - memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement)); - - save_pointer(NAME(m_vdp2_regs), 0x040000/2); - save_pointer(NAME(m_vdp2_vram), 0x100000/4); - save_pointer(NAME(m_vdp2_cram), 0x080000/4); - machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp2_state_save_postload), this)); - - return 0; -} - -/* maybe we should move this to video/stv.c */ -VIDEO_START_MEMBER(saturn_state,stv_vdp2) -{ - int i; - m_screen->register_screen_bitmap(m_tmpbitmap); - stv_vdp2_start(); - stv_vdp1_start(); - m_vdpdebug_roz = 0; - m_gfxdecode->gfx(0)->set_source(m_vdp2.gfx_decode.get()); - m_gfxdecode->gfx(1)->set_source(m_vdp2.gfx_decode.get()); - m_gfxdecode->gfx(2)->set_source(m_vdp2.gfx_decode.get()); - m_gfxdecode->gfx(3)->set_source(m_vdp2.gfx_decode.get()); - - /* calc V counter offsets */ - /* 224 mode */ - for(i=0;i<263;i++) - { - true_vcount[i][0] = i; - if(i>0xec) - true_vcount[i][0]+=0xf9; - } - - for(i=0;i<263;i++) - { - true_vcount[i][1] = i; - if(i>0xf5) - true_vcount[i][1]+=0xf9; - } - - /* 256 mode, todo */ - for(i=0;i<263;i++) - { - true_vcount[i][2] = i; - true_vcount[i][3] = i; - } -} - -void saturn_state::stv_vdp2_dynamic_res_change( void ) -{ - const int d_vres[4] = { 224, 240, 256, 256 }; - const int d_hres[4] = { 320, 352, 640, 704 }; - int horz_res,vert_res; - int vres_mask; - - // reset odd bit if a dynamic resolution change occurs, seabass ST-V cares! - m_vdp2.odd = 1; - vres_mask = (m_vdp2.pal << 1)|1; //PAL uses mask 3, NTSC uses mask 1 - vert_res = d_vres[STV_VDP2_VRES & vres_mask]; - - if((STV_VDP2_VRES & 3) == 3) - popmessage("Illegal VRES MODE, contact MAMEdev"); - - /*Double-density interlace mode,doubles the vertical res*/ - if((STV_VDP2_LSMD & 3) == 3) { vert_res*=2; } - - horz_res = d_hres[STV_VDP2_HRES & 3]; - /*Exclusive modes,they sets the Vertical Resolution without considering the - VRES register.*/ - if(STV_VDP2_HRES & 4) - vert_res = 480; - - { - int vblank_period,hblank_period; - attoseconds_t refresh; - rectangle visarea(0, horz_res-1, 0, vert_res-1); - - vblank_period = get_vblank_duration(); - hblank_period = get_hblank_duration(); - refresh = HZ_TO_ATTOSECONDS(get_pixel_clock()) * (hblank_period) * vblank_period; - //printf("%d %d %d %d\n",horz_res,vert_res,horz_res+hblank_period,vblank_period); - - m_screen->configure(hblank_period, vblank_period, visarea, refresh ); - } -// m_screen->set_visible_area(0*8, horz_res-1,0*8, vert_res-1); -} - -/*This is for calculating the rgb brightness*/ -/*TODO: Optimize this...*/ -void saturn_state::stv_vdp2_fade_effects( void ) -{ - /* - Note:We have to use temporary storages because palette_get_color must use - variables setted with unsigned int8 - */ - int16_t t_r,t_g,t_b; - uint8_t r,g,b; - rgb_t color; - int i; - //popmessage("%04x %04x",STV_VDP2_CLOFEN,STV_VDP2_CLOFSL); - for(i=0;i<2048;i++) - { - /*Fade A*/ - color = m_palette->pen_color(i); - t_r = (STV_VDP2_COAR & 0x100) ? (color.r() - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + color.r()); - t_g = (STV_VDP2_COAG & 0x100) ? (color.g() - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + color.g()); - t_b = (STV_VDP2_COAB & 0x100) ? (color.b() - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + color.b()); - if(t_r < 0) { t_r = 0; } - if(t_r > 0xff) { t_r = 0xff; } - if(t_g < 0) { t_g = 0; } - if(t_g > 0xff) { t_g = 0xff; } - if(t_b < 0) { t_b = 0; } - if(t_b > 0xff) { t_b = 0xff; } - r = t_r; - g = t_g; - b = t_b; - m_palette->set_pen_color(i+(2048*1),rgb_t(r,g,b)); - - /*Fade B*/ - color = m_palette->pen_color(i); - t_r = (STV_VDP2_COBR & 0x100) ? (color.r() - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + color.r()); - t_g = (STV_VDP2_COBG & 0x100) ? (color.g() - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + color.g()); - t_b = (STV_VDP2_COBB & 0x100) ? (color.b() - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + color.b()); - if(t_r < 0) { t_r = 0; } - if(t_r > 0xff) { t_r = 0xff; } - if(t_g < 0) { t_g = 0; } - if(t_g > 0xff) { t_g = 0xff; } - if(t_b < 0) { t_b = 0; } - if(t_b > 0xff) { t_b = 0xff; } - r = t_r; - g = t_g; - b = t_b; - m_palette->set_pen_color(i+(2048*2),rgb_t(r,g,b)); - } - //popmessage("%04x %04x %04x %04x %04x %04x",STV_VDP2_COAR,STV_VDP2_COAG,STV_VDP2_COAB,STV_VDP2_COBR,STV_VDP2_COBG,STV_VDP2_COBB); -} - -void saturn_state::stv_vdp2_get_window0_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y) -{ - /*W0*/ - switch(STV_VDP2_LSMD & 3) - { - case 0: - case 1: - case 2: - *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0); - *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0); - break; - case 3: - *s_y = ((STV_VDP2_W0SY & 0x7ff) >> 0); - *e_y = ((STV_VDP2_W0EY & 0x7ff) >> 0); - break; - } - // check if line window is enabled - if(STV_VDP2_W0LWE) - { - uint32_t base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; - uint32_t address = (STV_VDP2_W0LWTA & base_mask) * 2; - // double density makes the line window to fetch data every two lines - uint8_t interlace = (STV_VDP2_LSMD == 3); - uint32_t vram_data = m_vdp2_vram[(address >> 2)+(y >> interlace)]; - - *s_x = (vram_data >> 16) & 0x3ff; - *e_x = (vram_data & 0x3ff); - } - else - { - switch(STV_VDP2_HRES & 6) - { - /*Normal*/ - case 0: - *s_x = ((STV_VDP2_W0SX & 0x3fe) >> 1); - *e_x = ((STV_VDP2_W0EX & 0x3fe) >> 1); - break; - /*Hi-Res*/ - case 2: - *s_x = ((STV_VDP2_W0SX & 0x3ff) >> 0); - *e_x = ((STV_VDP2_W0EX & 0x3ff) >> 0); - break; - /*Exclusive Normal*/ - case 4: - *s_x = ((STV_VDP2_W0SX & 0x1ff) >> 0); - *e_x = ((STV_VDP2_W0EX & 0x1ff) >> 0); - *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0); - *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0); - break; - /*Exclusive Hi-Res*/ - case 6: - *s_x = ((STV_VDP2_W0SX & 0x1ff) << 1); - *e_x = ((STV_VDP2_W0EX & 0x1ff) << 1); - *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0); - *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0); - break; - } - } -} - -void saturn_state::stv_vdp2_get_window1_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y) -{ - /*W1*/ - switch(STV_VDP2_LSMD & 3) - { - case 0: - case 1: - case 2: - *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0); - *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0); - break; - case 3: - *s_y = ((STV_VDP2_W1SY & 0x7ff) >> 0); - *e_y = ((STV_VDP2_W1EY & 0x7ff) >> 0); - break; - } - // check if line window is enabled - if(STV_VDP2_W1LWE) - { - uint32_t base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; - uint32_t address = (STV_VDP2_W1LWTA & base_mask) * 2; - // double density makes the line window to fetch data every two lines - uint8_t interlace = (STV_VDP2_LSMD == 3); - uint32_t vram_data = m_vdp2_vram[(address >> 2)+(y >> interlace)]; - - *s_x = (vram_data >> 16) & 0x3ff; - *e_x = (vram_data & 0x3ff); - } - else - { - switch(STV_VDP2_HRES & 6) - { - /*Normal*/ - case 0: - *s_x = ((STV_VDP2_W1SX & 0x3fe) >> 1); - *e_x = ((STV_VDP2_W1EX & 0x3fe) >> 1); - break; - /*Hi-Res*/ - case 2: - *s_x = ((STV_VDP2_W1SX & 0x3ff) >> 0); - *e_x = ((STV_VDP2_W1EX & 0x3ff) >> 0); - break; - /*Exclusive Normal*/ - case 4: - *s_x = ((STV_VDP2_W1SX & 0x1ff) >> 0); - *e_x = ((STV_VDP2_W1EX & 0x1ff) >> 0); - *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0); - *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0); - break; - /*Exclusive Hi-Res*/ - case 6: - *s_x = ((STV_VDP2_W1SX & 0x1ff) << 1); - *e_x = ((STV_VDP2_W1EX & 0x1ff) << 1); - *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0); - *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0); - break; - } - } -} - -int saturn_state::get_window_pixel(int s_x,int e_x,int s_y,int e_y,int x, int y,uint8_t win_num) -{ - int res; - - res = 1; - if(stv2_current_tilemap.window_control.enabled[win_num]) - { - if(stv2_current_tilemap.window_control.area[win_num]) - res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x); - else - res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x) ^ 1; - } - - return res; -} - -inline int saturn_state::stv_vdp2_window_process(int x,int y) -{ - int s_x=0,e_x=0,s_y=0,e_y=0; - int w0_pix, w1_pix; - - if (stv2_current_tilemap.window_control.enabled[0] == 0 && - stv2_current_tilemap.window_control.enabled[1] == 0) - return 1; - - stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y); - w0_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,0); - - stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y); - w1_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,1); - - return stv2_current_tilemap.window_control.logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix); -} - -/* TODO: remove this crap. */ -int saturn_state::stv_vdp2_apply_window_on_layer(rectangle &cliprect) -{ - int s_x=0,e_x=0,s_y=0,e_y=0; - - if ( stv2_current_tilemap.window_control.enabled[0] && (!stv2_current_tilemap.window_control.area[0])) - { - /* w0, transparent outside supported */ - stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, 0); - - if ( s_x > cliprect.min_x ) cliprect.min_x = s_x; - if ( e_x < cliprect.max_x ) cliprect.max_x = e_x; - if ( s_y > cliprect.min_y ) cliprect.min_y = s_y; - if ( e_y < cliprect.max_y ) cliprect.max_y = e_y; - - return 1; - } - else if ( stv2_current_tilemap.window_control.enabled[1] && (!stv2_current_tilemap.window_control.area[1]) ) - { - /* w1, transparent outside supported */ - stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, 0); - - if ( s_x > cliprect.min_x ) cliprect.min_x = s_x; - if ( e_x < cliprect.max_x ) cliprect.max_x = e_x; - if ( s_y > cliprect.min_y ) cliprect.min_y = s_y; - if ( e_y < cliprect.max_y ) cliprect.max_y = e_y; - - return 1; - } - else - { - return 0; - } -} - -void saturn_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint8_t pri) -{ - int x,y,r,g,b; - int i; - uint16_t pix; - uint16_t *framebuffer_line; - uint32_t *bitmap_line, *bitmap_line2 = nullptr; - uint8_t interlace_framebuffer; - uint8_t double_x; - static const uint16_t sprite_colormask_table[] = { - 0x07ff, 0x07ff, 0x07ff, 0x07ff, 0x03ff, 0x07ff, 0x03ff, 0x01ff, - 0x007f, 0x003f, 0x003f, 0x003f, 0x00ff, 0x00ff, 0x00ff, 0x00ff - }; - static const uint16_t priority_shift_table[] = { 14, 13, 14, 13, 13, 12, 12, 12, 7, 7, 6, 0, 7, 7, 6, 0 }; - static const uint16_t priority_mask_table[] = { 3, 7, 1, 3, 3, 7, 7, 7, 1, 1, 3, 0, 1, 1, 3, 0 }; - static const uint16_t ccrr_shift_table[] = { 11, 11, 11, 11, 10, 11, 10, 9, 0, 6, 0, 6, 0, 6, 0, 6 }; - static const uint16_t ccrr_mask_table[] = { 7, 3, 7, 3, 7, 1, 3, 7, 0, 1, 0, 3, 0, 1, 0, 3 }; - static const uint16_t shadow_mask_table[] = { 0, 0, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0 }; - uint16_t alpha_enabled; - - int sprite_type; - int sprite_colormask; - int color_offset_pal; - int sprite_shadow; - uint16_t sprite_priority_shift, sprite_priority_mask, sprite_ccrr_shift, sprite_ccrr_mask; - uint8_t priority; - uint8_t ccr = 0; - uint8_t sprite_priorities[8]; - uint8_t sprite_ccr[8]; - int sprite_color_mode = STV_VDP2_SPCLMD; - - if ( (stv_sprite_priorities_usage_valid == 1) && (stv_sprite_priorities_used[pri] == 0) ) - return; - - sprite_priorities[0] = STV_VDP2_S0PRIN; - sprite_priorities[1] = STV_VDP2_S1PRIN; - sprite_priorities[2] = STV_VDP2_S2PRIN; - sprite_priorities[3] = STV_VDP2_S3PRIN; - sprite_priorities[4] = STV_VDP2_S4PRIN; - sprite_priorities[5] = STV_VDP2_S5PRIN; - sprite_priorities[6] = STV_VDP2_S6PRIN; - sprite_priorities[7] = STV_VDP2_S7PRIN; - - sprite_ccr[0] = STV_VDP2_S0CCRT; - sprite_ccr[1] = STV_VDP2_S1CCRT; - sprite_ccr[2] = STV_VDP2_S2CCRT; - sprite_ccr[3] = STV_VDP2_S3CCRT; - sprite_ccr[4] = STV_VDP2_S4CCRT; - sprite_ccr[5] = STV_VDP2_S5CCRT; - sprite_ccr[6] = STV_VDP2_S6CCRT; - sprite_ccr[7] = STV_VDP2_S7CCRT; - - sprite_type = STV_VDP2_SPTYPE; - sprite_colormask = sprite_colormask_table[sprite_type]; - sprite_priority_shift = priority_shift_table[sprite_type]; - sprite_priority_mask = priority_mask_table[sprite_type]; - sprite_ccrr_shift = ccrr_shift_table[sprite_type]; - sprite_ccrr_mask = ccrr_mask_table[sprite_type]; - sprite_shadow = shadow_mask_table[sprite_type]; - - for ( i = 0; i < (sprite_priority_mask+1); i++ ) if ( sprite_priorities[i] == pri ) break; - if ( i == (sprite_priority_mask+1) ) return; - - /* color offset (RGB brightness) */ - color_offset_pal = 0; - if ( STV_VDP2_SPCOEN ) - { - if ( STV_VDP2_SPCOSL == 0 ) - { color_offset_pal = 2048; } - else - { color_offset_pal = 2048*2; } - } - - /* color calculation (alpha blending)*/ - if ( STV_VDP2_SPCCEN ) - { - alpha_enabled = 0; - switch( STV_VDP2_SPCCCS ) - { - case 0x0: if ( pri <= STV_VDP2_SPCCN ) alpha_enabled = 1; break; - case 0x1: if ( pri == STV_VDP2_SPCCN ) alpha_enabled = 1; break; - case 0x2: if ( pri >= STV_VDP2_SPCCN ) alpha_enabled = 1; break; - case 0x3: alpha_enabled = 2; sprite_shadow = 0; break; - } - } - else - { - alpha_enabled = 0; - } - - /* framebuffer interlace */ - if ( (STV_VDP2_LSMD == 3) && m_vdp1.framebuffer_double_interlace == 0 ) - interlace_framebuffer = 1; - else - interlace_framebuffer = 0; - - /*Guess:Some games needs that the horizontal sprite size to be doubled - (TODO: understand the proper settings,it might not work like this)*/ - if(STV_VDP1_TVM == 0 && STV_VDP2_HRES & 2) // astrass & findlove - double_x = 1; - else - double_x = 0; - - /* window control */ - stv2_current_tilemap.window_control.logic = STV_VDP2_SPLOG; - stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_SPW0E; - stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_SPW1E; -// stv2_current_tilemap.window_control.? = STV_VDP2_SPSWE; - stv2_current_tilemap.window_control.area[0] = STV_VDP2_SPW0A; - stv2_current_tilemap.window_control.area[1] = STV_VDP2_SPW1A; -// stv2_current_tilemap.window_control.? = STV_VDP2_SPSWA; - -// stv_vdp2_apply_window_on_layer(mycliprect); - - if (interlace_framebuffer == 0 && double_x == 0 ) - { - if ( alpha_enabled == 0 ) - { - for ( y = cliprect.top(); y <= cliprect.bottom(); y++ ) - { - if ( stv_sprite_priorities_usage_valid ) - if (stv_sprite_priorities_in_fb_line[y][pri] == 0) - continue; - - framebuffer_line = m_vdp1.framebuffer_display_lines[y]; - bitmap_line = &bitmap.pix(y); - - for ( x = cliprect.left(); x <= cliprect.right(); x++ ) - { - if(!stv_vdp2_window_process(x,y)) - continue; - - pix = framebuffer_line[x]; - if ( (pix & 0x8000) && sprite_color_mode) - { - if ( sprite_priorities[0] != pri ) - { - stv_sprite_priorities_used[sprite_priorities[0]] = 1; - stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1; - continue; - }; - - if(STV_VDP2_SPWINEN && pix == 0x8000) /* Pukunpa */ - continue; - - b = pal5bit((pix & 0x7c00) >> 10); - g = pal5bit((pix & 0x03e0) >> 5); - r = pal5bit( pix & 0x001f); - if ( color_offset_pal ) - { - stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL ); - } - - bitmap_line[x] = rgb_t(r, g, b); - } - else - { - priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask]; - if ( priority != pri ) - { - stv_sprite_priorities_used[priority] = 1; - stv_sprite_priorities_in_fb_line[y][priority] = 1; - continue; - }; - - // Pretty Fighter X, Game Tengoku shadows - // TODO: Pretty Fighter X doesn't read what's behind on title screen, VDP1 bug? - // TODO: seldomly Game Tengoku shadows aren't drawn properly - if(pix & 0x8000 && STV_VDP2_SDCTL & 0x100) - { - rgb_t p = bitmap_line[x]; - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - else - { - pix &= sprite_colormask; - if ( pix == (sprite_colormask - 1) ) - { - /*shadow - in reality, we should check from what layer pixel beneath comes...*/ - if ( STV_VDP2_SDCTL & 0x3f ) - { - rgb_t p = bitmap_line[x]; - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - /* note that when shadows are disabled, "shadow" palette entries are not drawn */ - } - else if ( pix ) - { - pix += (STV_VDP2_SPCAOS << 8); - pix &= 0x7ff; - pix += color_offset_pal; - bitmap_line[x] = m_palette->pen( pix ); - - } - } - - /* TODO: I don't think this one makes much sense ... (1) */ - if ( pix & sprite_shadow ) - { - if ( pix & ~sprite_shadow ) - { - rgb_t p = bitmap_line[x]; - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - } - } - } - } - } - else //alpha_enabled == 1 - { - for ( y = cliprect.top(); y <= cliprect.bottom(); y++ ) - { - if ( stv_sprite_priorities_usage_valid ) - if (stv_sprite_priorities_in_fb_line[y][pri] == 0) - continue; - - framebuffer_line = m_vdp1.framebuffer_display_lines[y]; - bitmap_line = &bitmap.pix(y); - - for ( x = cliprect.left(); x <= cliprect.right(); x++ ) - { - if(!stv_vdp2_window_process(x,y)) - continue; - - pix = framebuffer_line[x]; - if ( (pix & 0x8000) && sprite_color_mode) - { - if ( sprite_priorities[0] != pri ) - { - stv_sprite_priorities_used[sprite_priorities[0]] = 1; - stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1; - continue; - }; - - b = pal5bit((pix & 0x7c00) >> 10); - g = pal5bit((pix & 0x03e0) >> 5); - r = pal5bit( pix & 0x001f); - if ( color_offset_pal ) - { - stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL ); - } - ccr = sprite_ccr[0]; - if ( STV_VDP2_CCMD ) - { - bitmap_line[x] = add_blend_r32( bitmap_line[x], rgb_t(r, g, b)); - } - else - { - bitmap_line[x] = alpha_blend_r32( bitmap_line[x], rgb_t(r, g ,b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); - } - } - else - { - priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask]; - if ( priority != pri ) - { - stv_sprite_priorities_used[priority] = 1; - stv_sprite_priorities_in_fb_line[y][priority] = 1; - continue; - }; - - ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ]; - if ( alpha_enabled == 2 ) - { - if ( ( pix & 0x8000 ) == 0 ) - { - ccr = 0; - } - } - - - { - pix &= sprite_colormask; - if ( pix == (sprite_colormask - 1) ) - { - /*shadow - in reality, we should check from what layer pixel beneath comes...*/ - if ( STV_VDP2_SDCTL & 0x3f ) - { - rgb_t p = bitmap_line[x]; - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - /* note that when shadows are disabled, "shadow" palette entries are not drawn */ - } else if ( pix ) - { - pix += (STV_VDP2_SPCAOS << 8); - pix &= 0x7ff; - pix += color_offset_pal; - if ( ccr > 0 ) - { - if ( STV_VDP2_CCMD ) - { - bitmap_line[x] = add_blend_r32( bitmap_line[x], m_palette->pen(pix) ); - } - else - { - bitmap_line[x] = alpha_blend_r32( bitmap_line[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - } - } - else - bitmap_line[x] = m_palette->pen(pix); - } - } - - /* TODO: (1) */ - if ( pix & sprite_shadow ) - { - if ( pix & ~sprite_shadow ) - { - rgb_t p = bitmap_line[x]; - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - } - } - } - } - } - } - else - { - for ( y = cliprect.top(); y <= cliprect.bottom() / (interlace_framebuffer+1); y++ ) - { - if ( stv_sprite_priorities_usage_valid ) - if (stv_sprite_priorities_in_fb_line[y][pri] == 0) - continue; - - framebuffer_line = m_vdp1.framebuffer_display_lines[y]; - if ( interlace_framebuffer == 0 ) - { - bitmap_line = &bitmap.pix(y); - } - else - { - bitmap_line = &bitmap.pix(2*y); - bitmap_line2 = &bitmap.pix(2*y + 1); - } - - for ( x = cliprect.left(); x <= cliprect.right() /(double_x+1) ; x++ ) - { - if(!stv_vdp2_window_process(x,y)) - continue; - - pix = framebuffer_line[x]; - if ( (pix & 0x8000) && sprite_color_mode) - { - if ( sprite_priorities[0] != pri ) - { - stv_sprite_priorities_used[sprite_priorities[0]] = 1; - stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1; - continue; - }; - - b = pal5bit((pix & 0x7c00) >> 10); - g = pal5bit((pix & 0x03e0) >> 5); - r = pal5bit( pix & 0x001f); - if ( color_offset_pal ) - { - stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL ); - } - if ( alpha_enabled == 0 ) - { - if(double_x) - { - bitmap_line[x*2] = rgb_t(r, g, b); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = rgb_t(r, g, b); - bitmap_line[x*2+1] = rgb_t(r, g, b); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = rgb_t(r, g, b); - } - else - { - bitmap_line[x] = rgb_t(r, g, b); - if ( interlace_framebuffer == 1 ) bitmap_line2[x] = rgb_t(r, g, b); - } - } - else // alpha_blend == 1 - { - ccr = sprite_ccr[0]; - - if ( STV_VDP2_CCMD ) - { - if(double_x) - { - bitmap_line[x*2] = add_blend_r32( bitmap_line[x*2], rgb_t(r, g, b) ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = add_blend_r32( bitmap_line2[x*2], rgb_t(r, g, b) ); - bitmap_line[x*2+1] = add_blend_r32( bitmap_line[x*2+1], rgb_t(r, g, b) ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = add_blend_r32( bitmap_line2[x*2+1], rgb_t(r, g, b) ); - } - else - { - bitmap_line[x] = add_blend_r32( bitmap_line[x], rgb_t(r, g, b) ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x] = add_blend_r32( bitmap_line2[x], rgb_t(r, g, b) ); - } - } - else - { - if(double_x) - { - bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x*2], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x*2+1], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); - } - else - { - bitmap_line[x] = alpha_blend_r32( bitmap_line[x], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); - if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); - } - } - } - } - else - { - priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask]; - if ( priority != pri ) - { - stv_sprite_priorities_used[priority] = 1; - stv_sprite_priorities_in_fb_line[y][priority] = 1; - continue; - }; - - if ( alpha_enabled ) - ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ]; - - if ( alpha_enabled == 2 ) - { - if ( ( pix & 0x8000 ) == 0 ) - { - ccr = 0; - } - } - - { - pix &= sprite_colormask; - if ( pix == (sprite_colormask - 1) ) - { - /*shadow - in reality, we should check from what layer pixel beneath comes...*/ - if ( STV_VDP2_SDCTL & 0x3f ) - { - rgb_t p = bitmap_line[x]; - if(double_x) - { - p = bitmap_line[x*2]; - bitmap_line[x*2] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - p = bitmap_line[x*2+1]; - bitmap_line[x*2+1] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - else - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - /* note that when shadows are disabled, "shadow" palette entries are not drawn */ - } else if ( pix ) - { - pix += (STV_VDP2_SPCAOS << 8); - pix &= 0x7ff; - pix += color_offset_pal; - if ( alpha_enabled == 0 ) - { - if(double_x) - { - bitmap_line[x*2] = m_palette->pen( pix ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = m_palette->pen( pix ); - bitmap_line[x*2+1] = m_palette->pen( pix ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = m_palette->pen( pix ); - } - else - { - bitmap_line[x] = m_palette->pen( pix ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x] = m_palette->pen( pix ); - } - } - else // alpha_blend == 1 - { - if ( STV_VDP2_CCMD ) - { - if(double_x) - { - bitmap_line[x*2] = add_blend_r32( bitmap_line[x*2], m_palette->pen(pix) ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = add_blend_r32( bitmap_line2[x], m_palette->pen(pix) ); - bitmap_line[x*2+1] = add_blend_r32( bitmap_line[x*2+1], m_palette->pen(pix) ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = add_blend_r32( bitmap_line2[x], m_palette->pen(pix) ); - } - else - { - bitmap_line[x] = add_blend_r32( bitmap_line[x], m_palette->pen(pix) ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x] = add_blend_r32( bitmap_line2[x], m_palette->pen(pix) ); - } - } - else - { - if(double_x) - { - bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - } - else - { - bitmap_line[x] = alpha_blend_r32( bitmap_line[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); - } - } - } - } - } - - /* TODO: (1) */ - if ( pix & sprite_shadow ) - { - if ( pix & ~sprite_shadow ) - { - rgb_t p = bitmap_line[x]; - if(double_x) - { - p = bitmap_line[x*2]; - bitmap_line[x*2] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - p = bitmap_line[x*2+1]; - bitmap_line[x*2+1] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - else - bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); - } - } - } - } - } - } - - stv_sprite_priorities_usage_valid = 1; -} - -uint32_t saturn_state::screen_update_stv_vdp2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - stv_vdp2_fade_effects(); - - stv_vdp2_draw_back(m_tmpbitmap,cliprect); - - if(STV_VDP2_DISP) - { - uint8_t pri; - - stv_sprite_priorities_usage_valid = 0; - memset(stv_sprite_priorities_used, 0, sizeof(stv_sprite_priorities_used)); - memset(stv_sprite_priorities_in_fb_line, 0, sizeof(stv_sprite_priorities_in_fb_line)); - - /*If a plane has a priority value of zero it isn't shown at all.*/ - for(pri=1;pri<8;pri++) - { - if(pri==STV_VDP2_N3PRIN) { stv_vdp2_draw_NBG3(m_tmpbitmap,cliprect); } - if(pri==STV_VDP2_N2PRIN) { stv_vdp2_draw_NBG2(m_tmpbitmap,cliprect); } - if(pri==STV_VDP2_N1PRIN) { stv_vdp2_draw_NBG1(m_tmpbitmap,cliprect); } - if(pri==STV_VDP2_N0PRIN) { stv_vdp2_draw_NBG0(m_tmpbitmap,cliprect); } - if(pri==STV_VDP2_R0PRIN) { stv_vdp2_draw_RBG0(m_tmpbitmap,cliprect); } - { draw_sprites(m_tmpbitmap,cliprect,pri); } - } - } - - copybitmap(bitmap, m_tmpbitmap, 0, 0, 0, 0, cliprect); - - #if 0 - /* Do NOT remove me, used to test video code performance. */ - if(machine().input().code_pressed(KEYCODE_Q)) - { - popmessage("Halt CPUs"); - m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - } - #endif - return 0; -} diff --git a/src/devices/video/stvvdp2.h b/src/devices/video/stvvdp2.h deleted file mode 100644 index 6acafefe66a..00000000000 --- a/src/devices/video/stvvdp2.h +++ /dev/null @@ -1,2 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:David Haywood, Angelo Salese, Olivier Galibert, Mariusz Wojcieszek, R. Belmont diff --git a/src/mame/video/saturn.cpp b/src/mame/video/saturn.cpp new file mode 100644 index 00000000000..6ce6662ad29 --- /dev/null +++ b/src/mame/video/saturn.cpp @@ -0,0 +1,9365 @@ +// license:LGPL-2.1+ +// copyright-holders:David Haywood, Angelo Salese, Olivier Galibert, Mariusz Wojcieszek, R. Belmont +// Contains STV1 and STV2 code. STV2 starts at line 2210. +/* + +STV - VDP1 + +the vdp1 draws to the FRAMEBUFFER which is mapped in memory + +-------------------------- WARNING WARNING WARNING -------------------------- +This is a legacy core, all game based notes are for a future device rewrite. +Please don't remove them if for no reason you truly want to mess with this. +-------------------------- WARNING WARNING WARNING -------------------------- + +Framebuffer todo: +- finish manual erase +- add proper framebuffer erase +- 8 bpp support - now we always draw as 16 bpp, but this is not a problem since + VDP2 interprets framebuffer as 8 bpp in these cases + +*/ + + +#include "emu.h" +#include "includes/saturn.h" // FIXME: this is a dependency from devices on MAME + + +#define VDP1_LOG 0 + + +enum { FRAC_SHIFT = 16 }; + +struct spoint { + int32_t x, y; + int32_t u, v; +}; + +struct shaded_point +{ + int32_t x,y; + int32_t r,g,b; +}; + +#define RGB_R(_color) (_color & 0x1f) +#define RGB_G(_color) ((_color >> 5) & 0x1f) +#define RGB_B(_color) ((_color >> 10) & 0x1f) + +#define SWAP_INT32(_a,_b) \ + { \ + int32_t t; \ + t = _a; \ + _a = _b; \ + _b = t; \ + } + +#define SWAP_INT32PTR(_p1, _p2) \ + { \ + int32_t *p; \ + p = _p1; \ + _p1 = _p2; \ + _p2 = p; \ + } + +/*TV Mode Selection Register */ +/* + xxxx xxxx xxxx ---- | UNUSED + ---- ---- ---- x--- | VBlank Erase/Write (VBE) + ---- ---- ---- -xxx | TV Mode (TVM) + TV-Mode: + This sets the Frame Buffer size,the rotation of the Frame Buffer & the bit width. + bit 2 HDTV disable(0)/enable(1) + bit 1 non-rotation/rotation(1) + bit 0 16(0)/8(1) bits per pixel + Size of the Frame Buffer: + 7 invalid + 6 invalid + 5 invalid + 4 512x256 + 3 512x512 + 2 512x256 + 1 1024x256 + 0 512x256 +*/ + +/*Frame Buffer Change Mode Register*/ +/* + xxxx xxxx xxx- ---- | UNUSED + ---- ---- ---x ---- | Even/Odd Coordinate Select Bit (EOS) + ---- ---- ---- x--- | Double Interlace Mode (DIE) + ---- ---- ---- -x-- | Double Interlace Draw Line (DIL) + ---- ---- ---- --x- | Frame Buffer Change Trigger (FCM) + ---- ---- ---- ---x | Frame Buffer Change Mode (FCT) +*/ +#define STV_VDP1_FBCR ((m_vdp1_regs[0x002/2] >> 0)&0xffff) +#define STV_VDP1_EOS ((STV_VDP1_FBCR & 0x0010) >> 4) +#define STV_VDP1_DIE ((STV_VDP1_FBCR & 0x0008) >> 3) +#define STV_VDP1_DIL ((STV_VDP1_FBCR & 0x0004) >> 2) +#define STV_VDP1_FCM ((STV_VDP1_FBCR & 0x0002) >> 1) +#define STV_VDP1_FCT ((STV_VDP1_FBCR & 0x0001) >> 0) + +/*Plot Trigger Register*/ +/* + xxxx xxxx xxxx xx-- | UNUSED + ---- ---- ---- --xx | Plot Trigger Mode (PTM) + + Plot Trigger Mode: + 3 Invalid + 2 Automatic draw + 1 VDP1 draw by request + 0 VDP1 Idle (no access) +*/ +#define STV_VDP1_PTMR ((m_vdp1_regs[0x004/2])&0xffff) +#define STV_VDP1_PTM ((STV_VDP1_PTMR & 0x0003) >> 0) +#define PTM_0 m_vdp1_regs[0x004/2]&=~0x0001 + +/* + Erase/Write Data Register + 16 bpp = data + 8 bpp = erase/write data for even/odd X coordinates +*/ +#define STV_VDP1_EWDR ((m_vdp1_regs[0x006/2])&0xffff) + +/*Erase/Write Upper-Left register*/ +/* + x--- ---- ---- ---- | UNUSED + -xxx xxx- ---- ---- | X1 register + ---- ---x xxxx xxxx | Y1 register + +*/ +#define STV_VDP1_EWLR ((m_vdp1_regs[0x008/2])&0xffff) +#define STV_VDP1_EWLR_X1 ((STV_VDP1_EWLR & 0x7e00) >> 9) +#define STV_VDP1_EWLR_Y1 ((STV_VDP1_EWLR & 0x01ff) >> 0) +/*Erase/Write Lower-Right register*/ +/* + xxxx xxx- ---- ---- | X3 register + ---- ---x xxxx xxxx | Y3 register + +*/ +#define STV_VDP1_EWRR ((m_vdp1_regs[0x00a/2])&0xffff) +#define STV_VDP1_EWRR_X3 ((STV_VDP1_EWRR & 0xfe00) >> 9) +#define STV_VDP1_EWRR_Y3 ((STV_VDP1_EWRR & 0x01ff) >> 0) +/*Transfer End Status Register*/ +/* + xxxx xxxx xxxx xx-- | UNUSED + ---- ---- ---- --x- | CEF + ---- ---- ---- ---x | BEF + +*/ +#define STV_VDP1_EDSR ((m_vdp1_regs[0x010/2])&0xffff) +#define STV_VDP1_CEF (STV_VDP1_EDSR & 2) +#define STV_VDP1_BEF (STV_VDP1_EDSR & 1) +/**/ + + + +uint16_t saturn_state::saturn_vdp1_regs_r(offs_t offset) +{ + //logerror ("%s VDP1: Read from Registers, Offset %04x\n", machine().describe_context(), offset); + + switch(offset) + { + case 0x02/2: + return 0; + case 0x10/2: + break; + case 0x12/2: return m_vdp1.lopr; + case 0x14/2: return m_vdp1.copr; + /* MODR register, read register for the other VDP1 regs + (Shienryu SS version abuses of this during intro) */ + case 0x16/2: + uint16_t modr; + + modr = 0x1000; //vdp1 VER + modr |= (STV_VDP1_PTM >> 1) << 8; // PTM1 + modr |= STV_VDP1_EOS << 7; // EOS + modr |= STV_VDP1_DIE << 6; // DIE + modr |= STV_VDP1_DIL << 5; // DIL + modr |= STV_VDP1_FCM << 4; //FCM + modr |= STV_VDP1_VBE << 3; //VBE + modr |= STV_VDP1_TVM & 7; //TVM + + return modr; + default: + if(!machine().side_effects_disabled()) + logerror("%s VDP1: Read from Registers, Offset %04x\n", machine().describe_context(), offset*2); + break; + } + + return m_vdp1_regs[offset]; //TODO: write-only regs should return open bus or zero +} + +/* TODO: TVM & 1 is just a kludgy work-around, the VDP1 actually needs to be rewritten from scratch. */ +/* Daisenryaku Strong Style (daisenss) uses it */ +void saturn_state::stv_clear_framebuffer( int which_framebuffer ) +{ + int start_x, end_x, start_y, end_y; + + start_x = STV_VDP1_EWLR_X1 * ((STV_VDP1_TVM & 1) ? 16 : 8); + start_y = STV_VDP1_EWLR_Y1 * (m_vdp1.framebuffer_double_interlace+1); + end_x = STV_VDP1_EWRR_X3 * ((STV_VDP1_TVM & 1) ? 16 : 8); + end_y = (STV_VDP1_EWRR_Y3+1) * (m_vdp1.framebuffer_double_interlace+1); +// popmessage("%d %d %d %d %d",STV_VDP1_EWLR_X1,STV_VDP1_EWLR_Y1,STV_VDP1_EWRR_X3,STV_VDP1_EWRR_Y3,m_vdp1.framebuffer_double_interlace); + + if(STV_VDP1_TVM & 1) + { + for(int y=start_y;y 0xdf) && ((offset * 4) < 0x140)) +// { +// logerror("%s: VRAM dword write to %08X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask); +// } + + data = m_vdp1_vram[offset]; + /* put in gfx region for easy decoding */ + vdp1[offset*4+0] = (data & 0xff000000) >> 24; + vdp1[offset*4+1] = (data & 0x00ff0000) >> 16; + vdp1[offset*4+2] = (data & 0x0000ff00) >> 8; + vdp1[offset*4+3] = (data & 0x000000ff) >> 0; +} + +void saturn_state::saturn_vdp1_framebuffer0_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + //popmessage ("STV VDP1 Framebuffer 0 WRITE offset %08x data %08x",offset, data); + if ( STV_VDP1_TVM & 1 ) + { + /* 8-bit mode */ + //printf("VDP1 8-bit mode %08x %02x\n",offset,data); + if ( ACCESSING_BITS_24_31 ) + { + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0x00ff; + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0xff00; + } + if ( ACCESSING_BITS_16_23 ) + { + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0xff00; + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0x00ff; + } + if ( ACCESSING_BITS_8_15 ) + { + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0x00ff; + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0xff00; + } + if ( ACCESSING_BITS_0_7 ) + { + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0xff00; + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0x00ff; + } + } + else + { + /* 16-bit mode */ + if ( ACCESSING_BITS_16_31 ) + { + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] = (data >> 16) & 0xffff; + } + if ( ACCESSING_BITS_0_15 ) + { + m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] = data & 0xffff; + } + } +} + +uint32_t saturn_state::saturn_vdp1_framebuffer0_r(offs_t offset, uint32_t mem_mask) +{ + uint32_t result = 0; + //popmessage ("STV VDP1 Framebuffer 0 READ offset %08x",offset); + if ( STV_VDP1_TVM & 1 ) + { + /* 8-bit mode */ + //printf("VDP1 8-bit mode %08x\n",offset); + if ( ACCESSING_BITS_24_31 ) + result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0xff00) << 16); + if ( ACCESSING_BITS_16_23 ) + result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0x00ff) << 16); + if ( ACCESSING_BITS_8_15 ) + result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0xff00)); + if ( ACCESSING_BITS_0_7 ) + result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0x00ff)); + } + else + { + /* 16-bit mode */ + if ( ACCESSING_BITS_16_31 ) + { + result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] << 16); + } + if ( ACCESSING_BITS_0_15 ) + { + result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1]); + } + + } + + return result; +} + + +/* + +there is a command every 0x20 bytes +the first word is the control word +the rest are data used by it + +--- +00 CMDCTRL + e--- ---- ---- ---- | end bit (15) + -jjj ---- ---- ---- | jump select bits (12-14) + ---- zzzz ---- ---- | zoom point / hotspot (8-11) + ---- ---- 00-- ---- | UNUSED + ---- ---- --dd ---- | character read direction (4,5) + ---- ---- ---- cccc | command bits (0-3) + +02 CMDLINK + llll llll llll ll-- | link + ---- ---- ---- --00 | UNUSED + +04 CMDPMOD + m--- ---- ---- ---- | MON (looks at MSB and apply shadows etc.) + -00- ---- ---- ---- | UNUSED + ---h ---- ---- ---- | HSS (High Speed Shrink) + ---- p--- ---- ---- | PCLIP (Pre Clipping Disable) + ---- -c-- ---- ---- | CLIP (Clipping Mode Bit) + ---- --m- ---- ---- | CMOD (User Clipping Enable Bit) + ---- ---M ---- ---- | MESH (Mesh Enable Bit) + ---- ---- e--- ---- | ECD (End Code Disable) + ---- ---- -S-- ---- | SPD (Transparent Pixel Disable) + ---- ---- --cc c--- | Colour Mode + ---- ---- ---- -CCC | Colour Calculation bits + ---- ---- ---- -1-- | Gouraud shading enable + ---- ---- ---- --1- | 1/2 original GFX enable + ---- ---- ---- ---1 | 1/2 background enable + +06 CMDCOLR + mmmm mmmm mmmm mmmm | Colour Bank, Colour Lookup /8 + +08 CMDSRCA (Character Address) + aaaa aaaa aaaa aa-- | Character Address + ---- ---- ---- --00 | UNUSED + +0a CMDSIZE (Character Size) + 00-- ---- ---- ---- | UNUSED + --xx xxxx ---- ---- | Character Size (X) + ---- ---- yyyy yyyy | Character Size (Y) + +0c CMDXA (used for normal sprite) + eeee ee-- ---- ---- | extension bits + ---- --xx xxxx xxxx | x position + +0e CMDYA (used for normal sprite) + eeee ee-- ---- ---- | extension bits + ---- --yy yyyy yyyy | y position + +10 CMDXB +12 CMDYB +14 CMDXC +16 CMDYC +18 CMDXD +1a CMDYD +1c CMDGRDA (Gouraud Shading Table) +1e UNUSED +--- + + +*/ + +void saturn_state::stv_clear_gouraud_shading(void) +{ + memset( &stv_gouraud_shading, 0, sizeof( stv_gouraud_shading ) ); +} + +uint8_t saturn_state::stv_read_gouraud_table( void ) +{ + int gaddr; + + if ( stv2_current_sprite.CMDPMOD & 0x4 ) + { + gaddr = stv2_current_sprite.CMDGRDA * 8; + stv_gouraud_shading.GA = (m_vdp1_vram[gaddr/4] >> 16) & 0xffff; + stv_gouraud_shading.GB = (m_vdp1_vram[gaddr/4] >> 0) & 0xffff; + stv_gouraud_shading.GC = (m_vdp1_vram[gaddr/4 + 1] >> 16) & 0xffff; + stv_gouraud_shading.GD = (m_vdp1_vram[gaddr/4 + 1] >> 0) & 0xffff; + return 1; + } + else + { + return 0; + } +} + +static inline int32_t _shading( int32_t color, int32_t correction ) +{ + correction = (correction >> 16) & 0x1f; + color += (correction - 16); + + if ( color < 0 ) color = 0; + if ( color > 0x1f ) color = 0x1f; + + return color; +} + +uint16_t saturn_state::stv_vdp1_apply_gouraud_shading( int x, int y, uint16_t pix ) +{ + int32_t r,g,b, msb; + + msb = pix & 0x8000; + +#ifdef MAME_DEBUG + if ( (stv_vdp1_shading_data->scanline[y].x[0] >> 16) != x ) + { + logerror( "ERROR in computing x coordinates (line %d, x = %x, %d, xc = %x, %d)\n", y, x, x, stv_vdp1_shading_data->scanline[y].x[0], stv_vdp1_shading_data->scanline[y].x[0] >> 16 ); + }; +#endif + + b = RGB_B(pix); + g = RGB_G(pix); + r = RGB_R(pix); + + b = _shading( b, stv_vdp1_shading_data->scanline[y].b[0] ); + g = _shading( g, stv_vdp1_shading_data->scanline[y].g[0] ); + r = _shading( r, stv_vdp1_shading_data->scanline[y].r[0] ); + + stv_vdp1_shading_data->scanline[y].b[0] += stv_vdp1_shading_data->scanline[y].db; + stv_vdp1_shading_data->scanline[y].g[0] += stv_vdp1_shading_data->scanline[y].dg; + stv_vdp1_shading_data->scanline[y].r[0] += stv_vdp1_shading_data->scanline[y].dr; + + stv_vdp1_shading_data->scanline[y].x[0] += 1 << FRAC_SHIFT; + + return msb | b << 10 | g << 5 | r; +} + +void saturn_state::stv_vdp1_setup_shading_for_line(int32_t y, int32_t x1, int32_t x2, + int32_t r1, int32_t g1, int32_t b1, + int32_t r2, int32_t g2, int32_t b2) +{ + int xx1 = x1>>FRAC_SHIFT; + int xx2 = x2>>FRAC_SHIFT; + + + if ( xx1 > xx2 ) + { + SWAP_INT32(xx1, xx2); + SWAP_INT32(r1, r2); + SWAP_INT32(g1, g2); + SWAP_INT32(b1, b2); + } + + if ( (y >= 0) && (y < 512) ) + { + int32_t dx; + int32_t gbd, ggd, grd; + + dx = xx2 - xx1; + + if ( dx == 0 ) + { + gbd = ggd = grd = 0; + } + else + { + gbd = abs(b2 - b1) / dx; + if (b2 < b1) gbd = -gbd; + ggd = abs(g2 - g1) / dx; + if (g2 < g1) ggd = -ggd; + grd = abs(r2 - r1) / dx; + if (r2 < r1) grd = -grd; + } + + stv_vdp1_shading_data->scanline[y].x[0] = x1; + stv_vdp1_shading_data->scanline[y].x[1] = x2; + + stv_vdp1_shading_data->scanline[y].b[0] = b1; + stv_vdp1_shading_data->scanline[y].g[0] = g1; + stv_vdp1_shading_data->scanline[y].r[0] = r1; + stv_vdp1_shading_data->scanline[y].b[1] = b2; + stv_vdp1_shading_data->scanline[y].g[1] = g2; + stv_vdp1_shading_data->scanline[y].r[1] = r2; + + stv_vdp1_shading_data->scanline[y].db = gbd; + stv_vdp1_shading_data->scanline[y].dg = ggd; + stv_vdp1_shading_data->scanline[y].dr = grd; + + } +} + +void saturn_state::stv_vdp1_setup_shading_for_slope( + int32_t x1, int32_t x2, int32_t sl1, int32_t sl2, int32_t *nx1, int32_t *nx2, + int32_t r1, int32_t r2, int32_t slr1, int32_t slr2, int32_t *nr1, int32_t *nr2, + int32_t g1, int32_t g2, int32_t slg1, int32_t slg2, int32_t *ng1, int32_t *ng2, + int32_t b1, int32_t b2, int32_t slb1, int32_t slb2, int32_t *nb1, int32_t *nb2, + int32_t _y1, int32_t y2) +{ + if(x1 > x2 || (x1==x2 && sl1 > sl2)) { + SWAP_INT32(x1,x2); + SWAP_INT32(sl1,sl2); + SWAP_INT32PTR(nx1, nx2); + SWAP_INT32(r1,r2); + SWAP_INT32(slr1, slr2); + SWAP_INT32PTR(nr1, nr2); + SWAP_INT32(g1, g2); + SWAP_INT32(slg1, slg2); + SWAP_INT32PTR(ng1, ng2); + SWAP_INT32(b1, b2); + SWAP_INT32(slb1, slb2); + SWAP_INT32PTR(nb1, nb2); + } + + while(_y1 < y2) + { + stv_vdp1_setup_shading_for_line(_y1, x1, x2, r1, g1, b1, r2, g2, b2); + x1 += sl1; + r1 += slr1; + g1 += slg1; + b1 += slb1; + + x2 += sl2; + r2 += slr2; + g2 += slg2; + b2 += slb2; + _y1++; + } + *nx1 = x1; + *nr1 = r1; + *ng1 = g1; + *nb1 = b1; + + *nx2 = x2; + *nr2 = r2; + *nb2 = b2; + *ng2 = g2; +} + +void saturn_state::stv_vdp1_setup_shading(const struct spoint* q, const rectangle &cliprect) +{ + int32_t x1, x2, delta, cury, limy; + int32_t r1, g1, b1, r2, g2, b2; + int32_t sl1, slg1, slb1, slr1; + int32_t sl2, slg2, slb2, slr2; + int pmin, pmax, i, ps1, ps2; + struct shaded_point p[8]; + uint16_t gd[4]; + + if ( stv_read_gouraud_table() == 0 ) return; + + gd[0] = stv_gouraud_shading.GA; + gd[1] = stv_gouraud_shading.GB; + gd[2] = stv_gouraud_shading.GC; + gd[3] = stv_gouraud_shading.GD; + + for(i=0; i<4; i++) { + p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT; + p[i].y = p[i+4].y = q[i].y; + p[i].r = p[i+4].r = RGB_R(gd[i]) << FRAC_SHIFT; + p[i].g = p[i+4].g = RGB_G(gd[i]) << FRAC_SHIFT; + p[i].b = p[i+4].b = RGB_B(gd[i]) << FRAC_SHIFT; + } + + pmin = pmax = 0; + for(i=1; i<4; i++) { + if(p[i].y < p[pmin].y) + pmin = i; + if(p[i].y > p[pmax].y) + pmax = i; + } + + cury = p[pmin].y; + limy = p[pmax].y; + + stv_vdp1_shading_data->sy = cury; + stv_vdp1_shading_data->ey = limy; + + if(cury == limy) { + x1 = x2 = p[0].x; + ps1 = ps2 = 0; + for(i=1; i<4; i++) { + if(p[i].x < x1) { + x1 = p[i].x; + ps1 = i; + } + if(p[i].x > x2) { + x2 = p[i].x; + ps2 = i; + } + } + stv_vdp1_setup_shading_for_line(cury, x1, x2, p[ps1].r, p[ps1].g, p[ps1].b, p[ps2].r, p[ps2].g, p[ps2].b); + goto finish; + } + + ps1 = pmin+4; + ps2 = pmin; + + goto startup; + + for(;;) { + if(p[ps1-1].y == p[ps2+1].y) { + stv_vdp1_setup_shading_for_slope( + x1, x2, sl1, sl2, &x1, &x2, + r1, r2, slr1, slr2, &r1, &r2, + g1, g2, slg1, slg2, &g1, &g2, + b1, b2, slb1, slb2, &b1, &b2, + cury, p[ps1-1].y); + cury = p[ps1-1].y; + if(cury >= limy) + break; + ps1--; + ps2++; + + startup: + while(p[ps1-1].y == cury) + ps1--; + while(p[ps2+1].y == cury) + ps2++; + x1 = p[ps1].x; + r1 = p[ps1].r; + g1 = p[ps1].g; + b1 = p[ps1].b; + x2 = p[ps2].x; + r2 = p[ps2].r; + g2 = p[ps2].g; + b2 = p[ps2].b; + + delta = cury-p[ps1-1].y; + sl1 = (x1-p[ps1-1].x)/delta; + slr1 = (r1-p[ps1-1].r)/delta; + slg1 = (g1-p[ps1-1].g)/delta; + slb1 = (b1-p[ps1-1].b)/delta; + + delta = cury-p[ps2+1].y; + sl2 = (x2-p[ps2+1].x)/delta; + slr2 = (r2-p[ps2+1].r)/delta; + slg2 = (g2-p[ps2+1].g)/delta; + slb2 = (b2-p[ps2+1].b)/delta; + } else if(p[ps1-1].y < p[ps2+1].y) { + stv_vdp1_setup_shading_for_slope( + x1, x2, sl1, sl2, &x1, &x2, + r1, r2, slr1, slr2, &r1, &r2, + g1, g2, slg1, slg2, &g1, &g2, + b1, b2, slb1, slb2, &b1, &b2, + cury, p[ps1-1].y); + cury = p[ps1-1].y; + if(cury >= limy) + break; + ps1--; + while(p[ps1-1].y == cury) + ps1--; + x1 = p[ps1].x; + r1 = p[ps1].r; + g1 = p[ps1].g; + b1 = p[ps1].b; + + delta = cury-p[ps1-1].y; + sl1 = (x1-p[ps1-1].x)/delta; + slr1 = (r1-p[ps1-1].r)/delta; + slg1 = (g1-p[ps1-1].g)/delta; + slb1 = (b1-p[ps1-1].b)/delta; + } else { + stv_vdp1_setup_shading_for_slope( + x1, x2, sl1, sl2, &x1, &x2, + r1, r2, slr1, slr2, &r1, &r2, + g1, g2, slg1, slg2, &g1, &g2, + b1, b2, slb1, slb2, &b1, &b2, + cury, p[ps2+1].y); + cury = p[ps2+1].y; + if(cury >= limy) + break; + ps2++; + while(p[ps2+1].y == cury) + ps2++; + x2 = p[ps2].x; + r2 = p[ps2].r; + g2 = p[ps2].g; + b2 = p[ps2].b; + + delta = cury-p[ps2+1].y; + sl2 = (x2-p[ps2+1].x)/delta; + slr2 = (r2-p[ps2+1].r)/delta; + slg2 = (g2-p[ps2+1].g)/delta; + slb2 = (b2-p[ps2+1].b)/delta; + } + } + if(cury == limy) + stv_vdp1_setup_shading_for_line(cury, x1, x2, r1, g1, b1, r2, g2, b2 ); + +finish: + + if ( stv_vdp1_shading_data->sy < 0 ) stv_vdp1_shading_data->sy = 0; + if ( stv_vdp1_shading_data->sy >= 512 ) return; + if ( stv_vdp1_shading_data->ey < 0 ) return; + if ( stv_vdp1_shading_data->ey >= 512 ) stv_vdp1_shading_data->ey = 511; + + for ( cury = stv_vdp1_shading_data->sy; cury <= stv_vdp1_shading_data->ey; cury++ ) + { + while( (stv_vdp1_shading_data->scanline[cury].x[0] >> 16) < cliprect.min_x ) + { + stv_vdp1_shading_data->scanline[cury].x[0] += (1 << FRAC_SHIFT); + stv_vdp1_shading_data->scanline[cury].b[0] += stv_vdp1_shading_data->scanline[cury].db; + stv_vdp1_shading_data->scanline[cury].g[0] += stv_vdp1_shading_data->scanline[cury].dg; + stv_vdp1_shading_data->scanline[cury].r[0] += stv_vdp1_shading_data->scanline[cury].dr; + } + } + +} + +/* note that if we're drawing +to the framebuffer we CAN'T frameskip the vdp1 drawing as the hardware can READ the framebuffer +and if we skip the drawing the content could be incorrect when it reads it, although i have no idea +why they would want to */ + + + +void saturn_state::drawpixel_poly(int x, int y, int patterndata, int offsetcnt) +{ + /* Capcom Collection Dai 4 uses a dummy polygon to clear VDP1 framebuffer that goes over our current max size ... */ + if(x >= 1024 || y >= 512) + return; + + m_vdp1.framebuffer_draw_lines[y][x] = stv2_current_sprite.CMDCOLR; +} + +void saturn_state::drawpixel_8bpp_trans(int x, int y, int patterndata, int offsetcnt) +{ + uint16_t pix; + + pix = m_vdp1.gfx_decode[patterndata+offsetcnt] & 0xff; + if ( pix != 0 ) + { + m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank; + } +} + +void saturn_state::drawpixel_4bpp_notrans(int x, int y, int patterndata, int offsetcnt) +{ + uint16_t pix; + + pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2]; + pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4); + m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank; +} + +void saturn_state::drawpixel_4bpp_trans(int x, int y, int patterndata, int offsetcnt) +{ + uint16_t pix; + + pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2]; + pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4); + if ( pix != 0 ) + m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank; +} + +void saturn_state::drawpixel_generic(int x, int y, int patterndata, int offsetcnt) +{ + int pix,transpen, spd = stv2_current_sprite.CMDPMOD & 0x40; +// int mode; + int mesh = stv2_current_sprite.CMDPMOD & 0x100; + int raw,endcode; + + if ( mesh && !((x ^ y) & 1) ) + { + return; + } + + if(x >= 1024 || y >= 512) + return; + + if ( stv2_current_sprite.ispoly ) + { + raw = pix = stv2_current_sprite.CMDCOLR&0xffff; + + transpen = 0; + endcode = 0xffff; + #if 0 + if ( pix & 0x8000 ) + { + mode = 5; + } + else + { + mode = 1; + } + #endif + } + else + { + switch (stv2_current_sprite.CMDPMOD&0x0038) + { + case 0x0000: // mode 0 16 colour bank mode (4bits) (hanagumi blocks) + // most of the shienryu sprites use this mode + raw = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff]; + raw = offsetcnt&1 ? (raw & 0x0f) : ((raw & 0xf0)>>4); + pix = raw+((stv2_current_sprite.CMDCOLR&0xfff0)); + //mode = 0; + transpen = 0; + endcode = 0xf; + break; + case 0x0008: // mode 1 16 colour lookup table mode (4bits) + // shienryu explosions (and some enemies) use this mode + raw = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff]; + raw = offsetcnt&1 ? (raw & 0x0f) : ((raw & 0xf0)>>4); + pix = raw&1 ? + ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((raw&0xfffe)/2)])) & 0x0000ffff) >> 0): + ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((raw&0xfffe)/2)])) & 0xffff0000) >> 16); + //mode = 5; + transpen = 0; + endcode = 0xf; + break; + case 0x0010: // mode 2 64 colour bank mode (8bits) (character select portraits on hanagumi) + raw = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff; + //mode = 2; + pix = raw+(stv2_current_sprite.CMDCOLR&0xffc0); + transpen = 0; + endcode = 0xff; + // Notes of interest: + // Scud: the disposable assassin wants transparent pen on 0 + // sasissu: racing stage background clouds + break; + case 0x0018: // mode 3 128 colour bank mode (8bits) (little characters on hanagumi use this mode) + raw = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff; + pix = raw+(stv2_current_sprite.CMDCOLR&0xff80); + transpen = 0; + endcode = 0xff; + //mode = 3; + break; + case 0x0020: // mode 4 256 colour bank mode (8bits) (hanagumi title) + raw = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff] & 0xff; + pix = raw+(stv2_current_sprite.CMDCOLR&0xff00); + transpen = 0; + endcode = 0xff; + //mode = 4; + break; + case 0x0028: // mode 5 32,768 colour RGB mode (16bits) + raw = m_vdp1.gfx_decode[(patterndata+offsetcnt*2+1) & 0xfffff] | (m_vdp1.gfx_decode[(patterndata+offsetcnt*2) & 0xfffff]<<8); + //mode = 5; + // TODO: 0x1-0x7ffe reserved (color bank) + pix = raw; + transpen = 0; + endcode = 0x7fff; + break; + case 0x0038: // invalid + // game tengoku uses this on hi score screen (tate mode) + // according to Charles, reads from VRAM address 0 + raw = pix = m_vdp1.gfx_decode[1] | (m_vdp1.gfx_decode[0]<<8) ; + // TODO: check transpen + transpen = 0; + endcode = -1; + break; + default: // other settings illegal + pix = machine().rand(); + raw = pix & 0xff; // just mimic old driver behavior + //mode = 0; + transpen = 0; + endcode = 0xff; + popmessage("Illegal Sprite Mode %02x, contact MAMEdev",stv2_current_sprite.CMDPMOD&0x0038); + } + + + // preliminary end code disable support + if ( ((stv2_current_sprite.CMDPMOD & 0x80) == 0) && + (raw == endcode) ) + { + return; + } + } + + /* MSBON */ + // TODO: does this always applies to the frame buffer regardless of the mode? + pix |= stv2_current_sprite.CMDPMOD & 0x8000; + /* + TODO: from docs: + "Except for the color calculation of replace and shadow, color calculation can only be performed when the color code of the original picture is RGB code. + Color calculation can be executed when the color code is color bank code, but the results are not guaranteed." + Currently no idea about the "result not guaranteed" part, let's disable this branch for the time being ... + */ + #if 0 + if ( mode != 5 ) + { + if ( (raw != transpen) || spd ) + { + m_vdp1.framebuffer_draw_lines[y][x] = pix; + } + } + else + #endif + { + if ( (raw != transpen) || spd ) + { + if ( stv2_current_sprite.CMDPMOD & 0x4 ) /* Gouraud shading */ + pix = stv_vdp1_apply_gouraud_shading( x, y, pix ); + + switch( stv2_current_sprite.CMDPMOD & 0x3 ) + { + case 0: /* replace */ + m_vdp1.framebuffer_draw_lines[y][x] = pix; + break; + case 1: /* shadow */ + if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 ) + { + m_vdp1.framebuffer_draw_lines[y][x] = ((m_vdp1.framebuffer_draw_lines[y][x] & ~0x8421) >> 1) | 0x8000; + } + break; + case 2: /* half luminance */ + m_vdp1.framebuffer_draw_lines[y][x] = ((pix & ~0x8421) >> 1) | 0x8000; + break; + case 3: /* half transparent */ + if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 ) + { + m_vdp1.framebuffer_draw_lines[y][x] = alpha_blend_r16( m_vdp1.framebuffer_draw_lines[y][x], pix, 0x80 ) | 0x8000; + } + else + { + m_vdp1.framebuffer_draw_lines[y][x] = pix; + } + break; + //case 4: /* Gouraud shading */ + // TODO: Pro Yakyuu Team mo Tsukurou (during team creation, on PR girl select) + //case 6: + // break; + //case 7: /* Gouraud-shading + half-transparent */ + // Lupin the 3rd Pyramid no Kenja enemy shadows + // Death Crimson lives indicators + // TODO: latter looks really bad. + default: + // TODO: mode 5: prohibited, mode 6: gouraud shading + half-luminance, mode 7: gouraud-shading + half-transparent + popmessage("VDP1 PMOD = %02x, contact MAMEdev",stv2_current_sprite.CMDPMOD & 0x7); + m_vdp1.framebuffer_draw_lines[y][x] = pix; + break; + } + } + } +} + + +void saturn_state::stv_vdp1_set_drawpixel( void ) +{ + int sprite_type = stv2_current_sprite.CMDCTRL & 0x000f; + int sprite_mode = stv2_current_sprite.CMDPMOD&0x0038; + int spd = stv2_current_sprite.CMDPMOD & 0x40; + int mesh = stv2_current_sprite.CMDPMOD & 0x100; + int ecd = stv2_current_sprite.CMDPMOD & 0x80; + + if ( mesh || !ecd || ((stv2_current_sprite.CMDPMOD & 0x7) != 0) ) + { + drawpixel = &saturn_state::drawpixel_generic; + return; + } + + if(stv2_current_sprite.CMDPMOD & 0x8000) + { + drawpixel = &saturn_state::drawpixel_generic; + return; + } + + // polygon / polyline / line with replace case + if (sprite_type & 4 && ((stv2_current_sprite.CMDPMOD & 0x7) == 0)) + { + drawpixel = &saturn_state::drawpixel_poly; + } + else if ( (sprite_mode == 0x20) && !spd ) + { + m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xff00); + drawpixel = &saturn_state::drawpixel_8bpp_trans; + } + else if ((sprite_mode == 0x00) && spd) + { + m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0); + drawpixel = &saturn_state::drawpixel_4bpp_notrans; + } + else if (sprite_mode == 0x00 && !spd ) + { + m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0); + drawpixel = &saturn_state::drawpixel_4bpp_trans; + } + else + { + drawpixel = &saturn_state::drawpixel_generic; + } +} + + +void saturn_state::vdp1_fill_slope(const rectangle &cliprect, int patterndata, int xsize, + int32_t x1, int32_t x2, int32_t sl1, int32_t sl2, int32_t *nx1, int32_t *nx2, + int32_t u1, int32_t u2, int32_t slu1, int32_t slu2, int32_t *nu1, int32_t *nu2, + int32_t v1, int32_t v2, int32_t slv1, int32_t slv2, int32_t *nv1, int32_t *nv2, + int32_t _y1, int32_t y2) +{ + if(_y1 > cliprect.max_y) + return; + + if(y2 <= cliprect.min_y) { + int delta = y2-_y1; + *nx1 = x1+delta*sl1; + *nu1 = u1+delta*slu1; + *nv1 = v1+delta*slv1; + *nx2 = x2+delta*sl2; + *nu2 = u2+delta*slu2; + *nv2 = v2+delta*slv2; + return; + } + + if(y2 > cliprect.max_y) + y2 = cliprect.max_y+1; + + if(_y1 < cliprect.min_y) { + int delta = cliprect.min_y - _y1; + x1 += delta*sl1; + u1 += delta*slu1; + v1 += delta*slv1; + x2 += delta*sl2; + u2 += delta*slu2; + v2 += delta*slv2; + _y1 = cliprect.min_y; + } + + if(x1 > x2 || (x1==x2 && sl1 > sl2)) { + int32_t t, *tp; + t = x1; + x1 = x2; + x2 = t; + t = sl1; + sl1 = sl2; + sl2 = t; + tp = nx1; + nx1 = nx2; + nx2 = tp; + + t = u1; + u1 = u2; + u2 = t; + t = slu1; + slu1 = slu2; + slu2 = t; + tp = nu1; + nu1 = nu2; + nu2 = tp; + + t = v1; + v1 = v2; + v2 = t; + t = slv1; + slv1 = slv2; + slv2 = t; + tp = nv1; + nv1 = nv2; + nv2 = tp; + } + + while(_y1 < y2) { + if(_y1 >= cliprect.min_y) { + int32_t slux = 0, slvx = 0; + int xx1 = x1>>FRAC_SHIFT; + int xx2 = x2>>FRAC_SHIFT; + int32_t u = u1; + int32_t v = v1; + if(xx1 != xx2) { + int delta = xx2-xx1; + slux = (u2-u1)/delta; + slvx = (v2-v1)/delta; + } + if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) { + if(xx1 < cliprect.min_x) { + int delta = cliprect.min_x-xx1; + u += slux*delta; + v += slvx*delta; + xx1 = cliprect.min_x; + } + if(xx2 > cliprect.max_x) + xx2 = cliprect.max_x; + + while(xx1 <= xx2) { + (this->*drawpixel)(xx1,_y1, patterndata, (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT)); + xx1++; + u += slux; + v += slvx; + } + } + } + + x1 += sl1; + u1 += slu1; + v1 += slv1; + x2 += sl2; + u2 += slu2; + v2 += slv2; + _y1++; + } + *nx1 = x1; + *nu1 = u1; + *nv1 = v1; + *nx2 = x2; + *nu2 = u2; + *nv2 = v2; +} + +void saturn_state::vdp1_fill_line(const rectangle &cliprect, int patterndata, int xsize, int32_t y, + int32_t x1, int32_t x2, int32_t u1, int32_t u2, int32_t v1, int32_t v2) +{ + int xx1 = x1>>FRAC_SHIFT; + int xx2 = x2>>FRAC_SHIFT; + + if(y > cliprect.max_y || y < cliprect.min_y) + return; + + if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) { + int32_t slux = 0, slvx = 0; + int32_t u = u1; + int32_t v = v1; + if(xx1 != xx2) { + int delta = xx2-xx1; + slux = (u2-u1)/delta; + slvx = (v2-v1)/delta; + } + if(xx1 < cliprect.min_x) { + int delta = cliprect.min_x-xx1; + u += slux*delta; + v += slvx*delta; + xx1 = cliprect.min_x; + } + if(xx2 > cliprect.max_x) + xx2 = cliprect.max_x; + + while(xx1 <= xx2) { + (this->*drawpixel)(xx1,y,patterndata,(v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT)); + xx1++; + u += slux; + v += slvx; + } + } +} + +void saturn_state::vdp1_fill_quad(const rectangle &cliprect, int patterndata, int xsize, const struct spoint *q) +{ + int32_t sl1, sl2, slu1, slu2, slv1, slv2, cury, limy, x1, x2, u1, u2, v1, v2, delta; + int pmin, pmax, i, ps1, ps2; + struct spoint p[8]; + + for(i=0; i<4; i++) { + p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT; + p[i].y = p[i+4].y = q[i].y; + p[i].u = p[i+4].u = q[i].u << FRAC_SHIFT; + p[i].v = p[i+4].v = q[i].v << FRAC_SHIFT; + } + + pmin = pmax = 0; + for(i=1; i<4; i++) { + if(p[i].y < p[pmin].y) + pmin = i; + if(p[i].y > p[pmax].y) + pmax = i; + } + + cury = p[pmin].y; + limy = p[pmax].y; + + if(cury == limy) { + x1 = x2 = p[0].x; + u1 = u2 = p[0].u; + v1 = v2 = p[0].v; + for(i=1; i<4; i++) { + if(p[i].x < x1) { + x1 = p[i].x; + u1 = p[i].u; + v1 = p[i].v; + } + if(p[i].x > x2) { + x2 = p[i].x; + u2 = p[i].u; + v2 = p[i].v; + } + } + vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2); + return; + } + + if(cury > cliprect.max_y) + return; + if(limy <= cliprect.min_y) + return; + + if(limy > cliprect.max_y) + limy = cliprect.max_y; + + ps1 = pmin+4; + ps2 = pmin; + + goto startup; + + for(;;) { + if(p[ps1-1].y == p[ps2+1].y) { + vdp1_fill_slope(cliprect, patterndata, xsize, + x1, x2, sl1, sl2, &x1, &x2, + u1, u2, slu1, slu2, &u1, &u2, + v1, v2, slv1, slv2, &v1, &v2, + cury, p[ps1-1].y); + cury = p[ps1-1].y; + if(cury >= limy) + break; + ps1--; + ps2++; + + startup: + while(p[ps1-1].y == cury) + ps1--; + while(p[ps2+1].y == cury) + ps2++; + x1 = p[ps1].x; + u1 = p[ps1].u; + v1 = p[ps1].v; + x2 = p[ps2].x; + u2 = p[ps2].u; + v2 = p[ps2].v; + + delta = cury-p[ps1-1].y; + sl1 = (x1-p[ps1-1].x)/delta; + slu1 = (u1-p[ps1-1].u)/delta; + slv1 = (v1-p[ps1-1].v)/delta; + + delta = cury-p[ps2+1].y; + sl2 = (x2-p[ps2+1].x)/delta; + slu2 = (u2-p[ps2+1].u)/delta; + slv2 = (v2-p[ps2+1].v)/delta; + } else if(p[ps1-1].y < p[ps2+1].y) { + vdp1_fill_slope(cliprect, patterndata, xsize, + x1, x2, sl1, sl2, &x1, &x2, + u1, u2, slu1, slu2, &u1, &u2, + v1, v2, slv1, slv2, &v1, &v2, + cury, p[ps1-1].y); + cury = p[ps1-1].y; + if(cury >= limy) + break; + ps1--; + while(p[ps1-1].y == cury) + ps1--; + x1 = p[ps1].x; + u1 = p[ps1].u; + v1 = p[ps1].v; + + delta = cury-p[ps1-1].y; + sl1 = (x1-p[ps1-1].x)/delta; + slu1 = (u1-p[ps1-1].u)/delta; + slv1 = (v1-p[ps1-1].v)/delta; + } else { + vdp1_fill_slope(cliprect, patterndata, xsize, + x1, x2, sl1, sl2, &x1, &x2, + u1, u2, slu1, slu2, &u1, &u2, + v1, v2, slv1, slv2, &v1, &v2, + cury, p[ps2+1].y); + cury = p[ps2+1].y; + if(cury >= limy) + break; + ps2++; + while(p[ps2+1].y == cury) + ps2++; + x2 = p[ps2].x; + u2 = p[ps2].u; + v2 = p[ps2].v; + + delta = cury-p[ps2+1].y; + sl2 = (x2-p[ps2+1].x)/delta; + slu2 = (u2-p[ps2+1].u)/delta; + slv2 = (v2-p[ps2+1].v)/delta; + } + } + if(cury == limy) + vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2); +} + +int saturn_state::x2s(int v) +{ + return (int32_t)(int16_t)v + m_vdp1.local_x; +} + +int saturn_state::y2s(int v) +{ + return (int32_t)(int16_t)v + m_vdp1.local_y; +} + +void saturn_state::stv_vdp1_draw_line(const rectangle &cliprect) +{ + struct spoint q[4]; + + q[0].x = x2s(stv2_current_sprite.CMDXA); + q[0].y = y2s(stv2_current_sprite.CMDYA); + q[1].x = x2s(stv2_current_sprite.CMDXB); + q[1].y = y2s(stv2_current_sprite.CMDYB); + q[2].x = x2s(stv2_current_sprite.CMDXA); + q[2].y = y2s(stv2_current_sprite.CMDYA); + q[3].x = x2s(stv2_current_sprite.CMDXB); + q[3].y = y2s(stv2_current_sprite.CMDYB); + + q[0].u = q[3].u = q[1].u = q[2].u = 0; + q[0].v = q[1].v = q[2].v = q[3].v = 0; + + vdp1_fill_quad(cliprect, 0, 1, q); +} + +void saturn_state::stv_vdp1_draw_poly_line(const rectangle &cliprect) +{ + struct spoint q[4]; + + q[0].x = x2s(stv2_current_sprite.CMDXA); + q[0].y = y2s(stv2_current_sprite.CMDYA); + q[1].x = x2s(stv2_current_sprite.CMDXB); + q[1].y = y2s(stv2_current_sprite.CMDYB); + q[2].x = x2s(stv2_current_sprite.CMDXA); + q[2].y = y2s(stv2_current_sprite.CMDYA); + q[3].x = x2s(stv2_current_sprite.CMDXB); + q[3].y = y2s(stv2_current_sprite.CMDYB); + + q[0].u = q[3].u = q[1].u = q[2].u = 0; + q[0].v = q[1].v = q[2].v = q[3].v = 0; + + vdp1_fill_quad(cliprect, 0, 1, q); + + q[0].x = x2s(stv2_current_sprite.CMDXB); + q[0].y = y2s(stv2_current_sprite.CMDYB); + q[1].x = x2s(stv2_current_sprite.CMDXC); + q[1].y = y2s(stv2_current_sprite.CMDYC); + q[2].x = x2s(stv2_current_sprite.CMDXB); + q[2].y = y2s(stv2_current_sprite.CMDYB); + q[3].x = x2s(stv2_current_sprite.CMDXC); + q[3].y = y2s(stv2_current_sprite.CMDYC); + + q[0].u = q[3].u = q[1].u = q[2].u = 0; + q[0].v = q[1].v = q[2].v = q[3].v = 0; + + vdp1_fill_quad(cliprect, 0, 1, q); + + q[0].x = x2s(stv2_current_sprite.CMDXC); + q[0].y = y2s(stv2_current_sprite.CMDYC); + q[1].x = x2s(stv2_current_sprite.CMDXD); + q[1].y = y2s(stv2_current_sprite.CMDYD); + q[2].x = x2s(stv2_current_sprite.CMDXC); + q[2].y = y2s(stv2_current_sprite.CMDYC); + q[3].x = x2s(stv2_current_sprite.CMDXD); + q[3].y = y2s(stv2_current_sprite.CMDYD); + + q[0].u = q[3].u = q[1].u = q[2].u = 0; + q[0].v = q[1].v = q[2].v = q[3].v = 0; + + vdp1_fill_quad(cliprect, 0, 1, q); + + q[0].x = x2s(stv2_current_sprite.CMDXD); + q[0].y = y2s(stv2_current_sprite.CMDYD); + q[1].x = x2s(stv2_current_sprite.CMDXA); + q[1].y = y2s(stv2_current_sprite.CMDYA); + q[2].x = x2s(stv2_current_sprite.CMDXD); + q[2].y = y2s(stv2_current_sprite.CMDYD); + q[3].x = x2s(stv2_current_sprite.CMDXA); + q[3].y = y2s(stv2_current_sprite.CMDYA); + + q[0].u = q[3].u = q[1].u = q[2].u = 0; + q[0].v = q[1].v = q[2].v = q[3].v = 0; + + stv_vdp1_setup_shading(q, cliprect); + vdp1_fill_quad(cliprect, 0, 1, q); + +} + +void saturn_state::stv_vdp1_draw_distorted_sprite(const rectangle &cliprect) +{ + struct spoint q[4]; + + int xsize, ysize; + int direction; + int patterndata; + + direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4; + + if ( stv2_current_sprite.ispoly ) + { + xsize = ysize = 1; + patterndata = 0; + } + else + { + xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8; + xsize = xsize * 8; + if (xsize == 0) return; /* setting prohibited */ + + ysize = (stv2_current_sprite.CMDSIZE & 0x00ff); + if (ysize == 0) return; /* setting prohibited */ + + patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff; + patterndata = patterndata * 0x8; + + } + + + q[0].x = x2s(stv2_current_sprite.CMDXA); + q[0].y = y2s(stv2_current_sprite.CMDYA); + q[1].x = x2s(stv2_current_sprite.CMDXB); + q[1].y = y2s(stv2_current_sprite.CMDYB); + q[2].x = x2s(stv2_current_sprite.CMDXC); + q[2].y = y2s(stv2_current_sprite.CMDYC); + q[3].x = x2s(stv2_current_sprite.CMDXD); + q[3].y = y2s(stv2_current_sprite.CMDYD); + + if(direction & 1) { // xflip + q[0].u = q[3].u = xsize-1; + q[1].u = q[2].u = 0; + } else { + q[0].u = q[3].u = 0; + q[1].u = q[2].u = xsize-1; + } + if(direction & 2) { // yflip + q[0].v = q[1].v = ysize-1; + q[2].v = q[3].v = 0; + } else { + q[0].v = q[1].v = 0; + q[2].v = q[3].v = ysize-1; + } + + stv_vdp1_setup_shading(q, cliprect); + vdp1_fill_quad(cliprect, patterndata, xsize, q); +} + +void saturn_state::stv_vdp1_draw_scaled_sprite(const rectangle &cliprect) +{ + struct spoint q[4]; + + int xsize, ysize; + int direction; + int patterndata; + int zoompoint; + int x,y; + int x2,y2; + int screen_width,screen_height,screen_height_negative = 0; + + direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4; + + xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8; + xsize = xsize * 8; + + ysize = (stv2_current_sprite.CMDSIZE & 0x00ff); + + patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff; + patterndata = patterndata * 0x8; + + zoompoint = (stv2_current_sprite.CMDCTRL & 0x0f00)>>8; + + x = stv2_current_sprite.CMDXA; + y = stv2_current_sprite.CMDYA; + + screen_width = (int16_t)stv2_current_sprite.CMDXB; + if ( (screen_width < 0) && zoompoint) + { + screen_width = -screen_width; + direction |= 1; + } + + screen_height = (int16_t)stv2_current_sprite.CMDYB; + if ( (screen_height < 0) && zoompoint ) + { + screen_height_negative = 1; + screen_height = -screen_height; + direction |= 2; + } + + x2 = stv2_current_sprite.CMDXC; // second co-ordinate set x + y2 = stv2_current_sprite.CMDYC; // second co-ordinate set y + + switch (zoompoint) + { + case 0x0: // specified co-ordinates + break; + case 0x5: // up left + break; + case 0x6: // up center + x -= screen_width/2 ; + break; + case 0x7: // up right + x -= screen_width; + break; + + case 0x9: // center left + y -= screen_height/2 ; + break; + case 0xa: // center center + y -= screen_height/2 ; + x -= screen_width/2 ; + + break; + + case 0xb: // center right + y -= screen_height/2 ; + x -= screen_width; + break; + + case 0xd: // center left + y -= screen_height; + break; + + case 0xe: // center center + y -= screen_height; + x -= screen_width/2 ; + break; + + case 0xf: // center right + y -= screen_height; + x -= screen_width; + break; + + default: // illegal + break; + + } + + /* 0----1 + | | + | | + 3----2 */ + + if (zoompoint) + { + q[0].x = x2s(x); + q[0].y = y2s(y); + q[1].x = x2s(x)+screen_width; + q[1].y = y2s(y); + q[2].x = x2s(x)+screen_width; + q[2].y = y2s(y)+screen_height; + q[3].x = x2s(x); + q[3].y = y2s(y)+screen_height; + + if ( screen_height_negative ) + { + q[0].y += screen_height; + q[1].y += screen_height; + q[2].y += screen_height; + q[3].y += screen_height; + } + } + else + { + q[0].x = x2s(x); + q[0].y = y2s(y); + q[1].x = x2s(x2); + q[1].y = y2s(y); + q[2].x = x2s(x2); + q[2].y = y2s(y2); + q[3].x = x2s(x); + q[3].y = y2s(y2); + } + + + if(direction & 1) { // xflip + q[0].u = q[3].u = xsize-1; + q[1].u = q[2].u = 0; + } else { + q[0].u = q[3].u = 0; + q[1].u = q[2].u = xsize-1; + } + if(direction & 2) { // yflip + q[0].v = q[1].v = ysize-1; + q[2].v = q[3].v = 0; + } else { + q[0].v = q[1].v = 0; + q[2].v = q[3].v = ysize-1; + } + + stv_vdp1_setup_shading(q, cliprect); + vdp1_fill_quad(cliprect, patterndata, xsize, q); +} + + + + +void saturn_state::stv_vdp1_draw_normal_sprite(const rectangle &cliprect, int sprite_type) +{ + int y, ysize, drawypos; + int x, xsize, drawxpos; + int direction; + int patterndata; + uint8_t shading; + int su, u, dux, duy; + int maxdrawypos, maxdrawxpos; + + x = x2s(stv2_current_sprite.CMDXA); + y = y2s(stv2_current_sprite.CMDYA); + + direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4; + + xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8; + xsize = xsize * 8; + + ysize = (stv2_current_sprite.CMDSIZE & 0x00ff); + + patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff; + patterndata = patterndata * 0x8; + + if (VDP1_LOG) logerror ("Drawing Normal Sprite x %04x y %04x xsize %04x ysize %04x patterndata %06x\n",x,y,xsize,ysize,patterndata); + + if ( x > cliprect.max_x ) return; + if ( y > cliprect.max_y ) return; + + shading = stv_read_gouraud_table(); + if ( shading ) + { + struct spoint q[4]; + q[0].x = x; q[0].y = y; + q[1].x = x + xsize; q[1].y = y; + q[2].x = x + xsize; q[2].y = y + ysize; + q[3].x = x; q[3].y = y + ysize; + + stv_vdp1_setup_shading( q, cliprect ); + } + + u = 0; + dux = 1; + duy = xsize; + if ( direction & 0x1 ) //xflip + { + dux = -1; + u = xsize - 1; + } + if ( direction & 0x2 ) //yflip + { + duy = -xsize; + u += xsize*(ysize-1); + } + if ( y < cliprect.min_y ) //clip y + { + u += xsize*(cliprect.min_y - y); + ysize -= (cliprect.min_y - y); + y = cliprect.min_y; + } + if ( x < cliprect.min_x ) //clip x + { + u += dux*(cliprect.min_x - x); + xsize -= (cliprect.min_x - x); + x = cliprect.min_x; + } + maxdrawypos = std::min(y+ysize-1,cliprect.max_y); + maxdrawxpos = std::min(x+xsize-1,cliprect.max_x); + for (drawypos = y; drawypos <= maxdrawypos; drawypos++ ) + { + //destline = m_vdp1.framebuffer_draw_lines[drawypos]; + su = u; + for (drawxpos = x; drawxpos <= maxdrawxpos; drawxpos++ ) + { + (this->*drawpixel)( drawxpos, drawypos, patterndata, u ); + u += dux; + } + u = su + duy; + } +} + +TIMER_CALLBACK_MEMBER(saturn_state::vdp1_draw_end ) +{ + /* set CEF to 1*/ + CEF_1; + + // TODO: temporary for Batman Forever, presumably anonymous timer not behaving well. + #if 0 + if(!(m_scu.ism & IRQ_VDP1_END)) + { + m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d); // SH2 + scu_do_transfer(6); + } + else + m_scu.ist |= (IRQ_VDP1_END); + #endif +} + + +void saturn_state::stv_vdp1_process_list( void ) +{ + int position; + int spritecount; + int vdp1_nest; + rectangle *cliprect; + + spritecount = 0; + position = 0; + + if (VDP1_LOG) logerror ("Sprite List Process START\n"); + + vdp1_nest = -1; + + stv_clear_gouraud_shading(); + + /*Set CEF bit to 0*/ + CEF_0; + + // TODO: is there an actual limit for this? + while (spritecount<16383) // max 16383 with texture or max 16384 without texture - vitrually unlimited + { + int draw_this_sprite; + + draw_this_sprite = 1; + + // if (position >= ((0x80000/0x20)/4)) // safety check + // { + // if (VDP1_LOG) logerror ("Sprite List Position Too High!\n"); + // position = 0; + // } + + spritecount++; + + stv2_current_sprite.CMDCTRL = (m_vdp1_vram[position * (0x20/4)+0] & 0xffff0000) >> 16; + + if (stv2_current_sprite.CMDCTRL == 0x8000) + { + if (VDP1_LOG) logerror ("List Terminator (0x8000) Encountered, Sprite List Process END\n"); + goto end; // end of list + } + + stv2_current_sprite.CMDLINK = (m_vdp1_vram[position * (0x20/4)+0] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDPMOD = (m_vdp1_vram[position * (0x20/4)+1] & 0xffff0000) >> 16; + stv2_current_sprite.CMDCOLR = (m_vdp1_vram[position * (0x20/4)+1] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDSRCA = (m_vdp1_vram[position * (0x20/4)+2] & 0xffff0000) >> 16; + stv2_current_sprite.CMDSIZE = (m_vdp1_vram[position * (0x20/4)+2] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDXA = (m_vdp1_vram[position * (0x20/4)+3] & 0xffff0000) >> 16; + stv2_current_sprite.CMDYA = (m_vdp1_vram[position * (0x20/4)+3] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDXB = (m_vdp1_vram[position * (0x20/4)+4] & 0xffff0000) >> 16; + stv2_current_sprite.CMDYB = (m_vdp1_vram[position * (0x20/4)+4] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDXC = (m_vdp1_vram[position * (0x20/4)+5] & 0xffff0000) >> 16; + stv2_current_sprite.CMDYC = (m_vdp1_vram[position * (0x20/4)+5] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDXD = (m_vdp1_vram[position * (0x20/4)+6] & 0xffff0000) >> 16; + stv2_current_sprite.CMDYD = (m_vdp1_vram[position * (0x20/4)+6] & 0x0000ffff) >> 0; + stv2_current_sprite.CMDGRDA = (m_vdp1_vram[position * (0x20/4)+7] & 0xffff0000) >> 16; +// stv2_current_sprite.UNUSED = (m_vdp1_vram[position * (0x20/4)+7] & 0x0000ffff) >> 0; + + /* proecess jump / skip commands, set position for next sprite */ + switch (stv2_current_sprite.CMDCTRL & 0x7000) + { + case 0x0000: // jump next + if (VDP1_LOG) logerror ("Sprite List Process + Next (Normal)\n"); + position++; + break; + case 0x1000: // jump assign + if (VDP1_LOG) logerror ("Sprite List Process + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2)); + position= (stv2_current_sprite.CMDLINK>>2); + break; + case 0x2000: // jump call + if (vdp1_nest == -1) + { + if (VDP1_LOG) logerror ("Sprite List Process + Call Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2)); + vdp1_nest = position+1; + position = (stv2_current_sprite.CMDLINK>>2); + } + else + { + if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n"); + position++; + } + break; + case 0x3000: + if (vdp1_nest != -1) + { + if (VDP1_LOG) logerror ("Sprite List Process + Return\n"); + position = vdp1_nest; + vdp1_nest = -1; + } + else + { + if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n"); + position++; + goto end; // end of list + } + break; + case 0x4000: + draw_this_sprite = 0; + position++; + break; + case 0x5000: + if (VDP1_LOG) logerror ("Sprite List Skip + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2)); + draw_this_sprite = 0; + position= (stv2_current_sprite.CMDLINK>>2); + + break; + case 0x6000: + draw_this_sprite = 0; + if (vdp1_nest == -1) + { + if (VDP1_LOG) logerror ("Sprite List Skip + Call To Subroutine Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2)); + + vdp1_nest = position+1; + position = (stv2_current_sprite.CMDLINK>>2); + } + else + { + if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n"); + position++; + } + break; + case 0x7000: + draw_this_sprite = 0; + if (vdp1_nest != -1) + { + if (VDP1_LOG) logerror ("Sprite List Skip + Return from Subroutine\n"); + + position = vdp1_nest; + vdp1_nest = -1; + } + else + { + if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n"); + position++; + goto end; // end of list + } + break; + } + + /* continue to draw this sprite only if the command wasn't to skip it */ + if (draw_this_sprite ==1) + { + if ( stv2_current_sprite.CMDPMOD & 0x0400 ) + { + //if(stv2_current_sprite.CMDPMOD & 0x0200) /* TODO: Bio Hazard inventory screen uses outside cliprect */ + // cliprect = &m_vdp1.system_cliprect; + //else + cliprect = &m_vdp1.user_cliprect; + } + else + { + cliprect = &m_vdp1.system_cliprect; + } + + stv_vdp1_set_drawpixel(); + + switch (stv2_current_sprite.CMDCTRL & 0x000f) + { + case 0x0000: + if (VDP1_LOG) logerror ("Sprite List Normal Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA); + stv2_current_sprite.ispoly = 0; + stv_vdp1_draw_normal_sprite(*cliprect, 0); + break; + + case 0x0001: + if (VDP1_LOG) logerror ("Sprite List Scaled Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA); + stv2_current_sprite.ispoly = 0; + stv_vdp1_draw_scaled_sprite(*cliprect); + break; + + case 0x0002: + case 0x0003: // used by Hardcore 4x4 + if (VDP1_LOG) logerror ("Sprite List Distorted Sprite\n"); + if (VDP1_LOG) logerror ("(A: %d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA); + if (VDP1_LOG) logerror ("(B: %d %d)\n",stv2_current_sprite.CMDXB,stv2_current_sprite.CMDYB); + if (VDP1_LOG) logerror ("(C: %d %d)\n",stv2_current_sprite.CMDXC,stv2_current_sprite.CMDYC); + if (VDP1_LOG) logerror ("(D: %d %d)\n",stv2_current_sprite.CMDXD,stv2_current_sprite.CMDYD); + if (VDP1_LOG) logerror ("CMDPMOD = %04x\n",stv2_current_sprite.CMDPMOD); + + stv2_current_sprite.ispoly = 0; + stv_vdp1_draw_distorted_sprite(*cliprect); + break; + + case 0x0004: + if (VDP1_LOG) logerror ("Sprite List Polygon\n"); + stv2_current_sprite.ispoly = 1; + stv_vdp1_draw_distorted_sprite(*cliprect); + break; + + case 0x0005: +// case 0x0007: // mirror? Baroque uses it, crashes for whatever reason + if (VDP1_LOG) logerror ("Sprite List Polyline\n"); + stv2_current_sprite.ispoly = 1; + stv_vdp1_draw_poly_line(*cliprect); + break; + + case 0x0006: + if (VDP1_LOG) logerror ("Sprite List Line\n"); + stv2_current_sprite.ispoly = 1; + stv_vdp1_draw_line(*cliprect); + break; + + case 0x0008: +// case 0x000b: // mirror? Bug 2 + if (VDP1_LOG) logerror ("Sprite List Set Command for User Clipping (%d,%d),(%d,%d)\n", stv2_current_sprite.CMDXA, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC); + m_vdp1.user_cliprect.set(stv2_current_sprite.CMDXA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDYC); + break; + + case 0x0009: + if (VDP1_LOG) logerror ("Sprite List Set Command for System Clipping (0,0),(%d,%d)\n", stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC); + m_vdp1.system_cliprect.set(0, stv2_current_sprite.CMDXC, 0, stv2_current_sprite.CMDYC); + break; + + case 0x000a: + if (VDP1_LOG) logerror ("Sprite List Local Co-Ordinate Set (%d %d)\n",(int16_t)stv2_current_sprite.CMDXA,(int16_t)stv2_current_sprite.CMDYA); + m_vdp1.local_x = (int16_t)stv2_current_sprite.CMDXA; + m_vdp1.local_y = (int16_t)stv2_current_sprite.CMDYA; + break; + + default: + popmessage ("VDP1: Sprite List Illegal %02x (%d), contact MAMEdev",stv2_current_sprite.CMDCTRL & 0xf,spritecount); + m_vdp1.lopr = (position * 0x20) >> 3; + //m_vdp1.copr = (position * 0x20) >> 3; + // prematurely kill the VDP1 process if an illegal opcode is executed + // Sexy Parodius calls multiple illegals and expects VDP1 irq to be fired anyway! + goto end; + } + } + + } + + + end: + m_vdp1.copr = (position * 0x20) >> 3; + + + /* TODO: what's the exact formula? Guess it should be a mix between number of pixels written and actual command data fetched. */ + // if spritecount = 10000 don't send a vdp1 draw end +// if(spritecount < 10000) + machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(spritecount*16), timer_expired_delegate(FUNC(saturn_state::vdp1_draw_end),this)); + + if (VDP1_LOG) logerror ("End of list processing!\n"); +} + +void saturn_state::video_update_vdp1( void ) +{ + int framebuffer_changed = 0; + +// int enable; +// if (machine.input().code_pressed (KEYCODE_R)) VDP1_LOG = 1; +// if (machine.input().code_pressed (KEYCODE_T)) VDP1_LOG = 0; + +// if (machine.input().code_pressed (KEYCODE_Y)) VDP1_LOG = 0; +// { +// FILE *fp; +// +// fp=fopen("vdp1_ram.dmp", "w+b"); +// if (fp) +// { +// fwrite(stv_vdp1, 0x00100000, 1, fp); +// fclose(fp); +// } +// } + if (VDP1_LOG) logerror("video_update_vdp1 called\n"); + if (VDP1_LOG) logerror( "FBCR = %0x, accessed = %d\n", STV_VDP1_FBCR, m_vdp1.fbcr_accessed ); + + if(STV_VDP1_CEF) + BEF_1; + else + BEF_0; + + if ( m_vdp1.framebuffer_clear_on_next_frame ) + { + if ( ((STV_VDP1_FBCR & 0x3) == 3) && + m_vdp1.fbcr_accessed ) + { + stv_clear_framebuffer(m_vdp1.framebuffer_current_display); + m_vdp1.framebuffer_clear_on_next_frame = 0; + } + } + + switch( STV_VDP1_FBCR & 0x3 ) + { + case 0: /* Automatic mode */ + stv_vdp1_change_framebuffers(); + stv_clear_framebuffer(m_vdp1.framebuffer_current_draw); + framebuffer_changed = 1; + break; + case 1: /* Setting prohibited */ + break; + case 2: /* Manual mode - erase */ + if ( m_vdp1.fbcr_accessed ) + { + m_vdp1.framebuffer_clear_on_next_frame = 1; + } + break; + case 3: /* Manual mode - change */ + if ( m_vdp1.fbcr_accessed ) + { + stv_vdp1_change_framebuffers(); + if ( STV_VDP1_VBE ) + { + stv_clear_framebuffer(m_vdp1.framebuffer_current_draw); + } + /* TODO: Slam n Jam 96 & Cross Romance doesn't like this, investigate. */ + framebuffer_changed = 1; + } + // framebuffer_changed = 1; + break; + } + m_vdp1.fbcr_accessed = 0; + + if (VDP1_LOG) logerror( "PTM = %0x, TVM = %x\n", STV_VDP1_PTM, STV_VDP1_TVM ); + /*Set CEF bit to 0*/ + //CEF_0; + switch(STV_VDP1_PTM & 3) + { + case 0:/*Idle Mode*/ + /*Set CEF bit to 0*/ + //CEF_0; + break; + case 1:/*Draw by request*/ + /*Set CEF bit to 0*/ + //CEF_0; + break; + case 2:/*Automatic Draw*/ + if ( framebuffer_changed || VDP1_LOG ) + { + /*set CEF to 1*/ + stv_vdp1_process_list(); + } + break; + case 3: /**/ + logerror("Warning: Invalid PTM mode set for VDP1!\n"); + break; + } + //popmessage("%04x %04x",STV_VDP1_EWRR_X3,STV_VDP1_EWRR_Y3); +} + +void saturn_state::stv_vdp1_state_save_postload( void ) +{ + uint8_t *vdp1 = m_vdp1.gfx_decode.get(); + int offset; + uint32_t data; + + m_vdp1.framebuffer_mode = -1; + m_vdp1.framebuffer_double_interlace = -1; + + stv_set_framebuffer_config(); + + for (offset = 0; offset < 0x80000/4; offset++ ) + { + data = m_vdp1_vram[offset]; + /* put in gfx region for easy decoding */ + vdp1[offset*4+0] = (data & 0xff000000) >> 24; + vdp1[offset*4+1] = (data & 0x00ff0000) >> 16; + vdp1[offset*4+2] = (data & 0x0000ff00) >> 8; + vdp1[offset*4+3] = (data & 0x000000ff) >> 0; + } +} + +int saturn_state::stv_vdp1_start ( void ) +{ + m_vdp1_regs = make_unique_clear(0x020/2 ); + m_vdp1_vram = make_unique_clear(0x100000/4 ); + m_vdp1.gfx_decode = std::make_unique(0x100000 ); + + stv_vdp1_shading_data = std::make_unique(); + + m_vdp1.framebuffer[0] = std::make_unique(1024 * 256 * 2 ); /* *2 is for double interlace */ + m_vdp1.framebuffer[1] = std::make_unique(1024 * 256 * 2 ); + + m_vdp1.framebuffer_display_lines = std::make_unique(512); + m_vdp1.framebuffer_draw_lines = std::make_unique(512); + + m_vdp1.framebuffer_width = m_vdp1.framebuffer_height = 0; + m_vdp1.framebuffer_mode = -1; + m_vdp1.framebuffer_double_interlace = -1; + m_vdp1.fbcr_accessed = 0; + m_vdp1.framebuffer_current_display = 0; + m_vdp1.framebuffer_current_draw = 1; + stv_clear_framebuffer(m_vdp1.framebuffer_current_draw); + m_vdp1.framebuffer_clear_on_next_frame = 0; + + m_vdp1.system_cliprect.set(0, 0, 0, 0); + /* Kidou Senshi Z Gundam - Zenpen Zeta no Kodou loves to use the user cliprect vars in an undefined state ... */ + m_vdp1.user_cliprect.set(0, 512, 0, 256); + + // save state + save_pointer(NAME(m_vdp1_regs), 0x020/2); + save_pointer(NAME(m_vdp1_vram), 0x100000/4); + save_item(NAME(m_vdp1.fbcr_accessed)); + save_item(NAME(m_vdp1.framebuffer_current_display)); + save_item(NAME(m_vdp1.framebuffer_current_draw)); + save_item(NAME(m_vdp1.framebuffer_clear_on_next_frame)); + save_item(NAME(m_vdp1.local_x)); + save_item(NAME(m_vdp1.local_y)); + machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp1_state_save_postload), this)); + return 0; +} + + +/**********************************************************************************************************************/ + +/* Sega Saturn VDP2 */ + +/* + +-------------------------- WARNING WARNING WARNING -------------------------- +This is a legacy core, all game based notes are for a future device rewrite. +Please don't remove them if for no reason you truly want to mess with this. +-------------------------- WARNING WARNING WARNING -------------------------- + +the dirty marking stuff and tile decoding will probably be removed in the end anyway as we'll need custom +rendering code since mame's drawgfx / tilesytem don't offer everything st-v needs + +this system seems far too complex to use Mame's tilemap system + +4 'scroll' planes (scroll screens) + +the scroll planes have slightly different capabilities + +NBG0 +NBG1 +NBG2 +NBG3 + +2 'rotate' planes + +RBG0 +RBG1 + +-- other crap +EXBG (external) + +----------------------------------------------------------------------------------------------------------- + +Video emulation TODO: +-all games: + \-priorities (check myfairld,thunt) + \-complete windows effects + \-mosaic effect + \-ODD bit/H/V Counter not yet emulated properly + \-Reduction enable bits (zooming limiters) + \-Check if there are any remaining video registers that are yet to be macroized & added to the rumble. +-batmanfr: + \-If you reset the game after the character selection screen,when you get again to it there's garbage + floating behind Batman. +-elandore: + \-(BTANB) priorities at the VS. screen apparently is wrong,but it's like this on the Saturn version too. +-hanagumi: + \-ending screens have corrupt graphics. (*untested*) +-kiwames: + \-(fixed) incorrect color emulation for the alpha blended flames on the title screen,it's caused by a schizoid + linescroll emulation quirk. + \-the VDP1 sprites refresh is too slow,causing the "Draw by request" mode to + flicker. Moved back to default ATM. +-pblbeach: + \-Sprites are offset, because it doesn't clear vdp1 local coordinates set by bios, + I guess that they are cleared when some vdp1 register is written (kludged for now) +-prikura: + \-Attract mode presentation has corrupted graphics in various places,probably caused by incomplete + framebuffer data delete. +-seabass: + \-(fixed) Player sprite is corrupt/missing during movements,caused by incomplete framebuffer switching. +-shienryu: + \-level 2 background colors on statues, caused by special color calculation usage (per dot); +(Saturn games) +- scud the disposable assassin: + \- when zooming on melee attack background gets pink, color calculation issue? +- virtual hydlide: + \- transparent pens usage on most vdp1 items should be black instead. + \- likewise "press start button" is the other way around, i.e. black pen where it should be transparent instead. + +Notes of Interest & Unclear features: + +-the test mode / bios is drawn with layer NBG3; +-hanagumi puts a 'RED' dragon logo in tileram (base 0x64000, 4bpp, 8x8 tiles) but +its not displayed because its priority value is 0.Left-over? + +-scrolling is screen display wise,meaning that a scrolling value is masked with the +screen resolution size values; + +-H-Blank bit is INDIPENDENT of the V-Blank bit...trying to fix enable/disable it during V-Blank period + causes wrong gameplay speed in Golden Axe:The Duel. + +-Bitmaps uses transparency pens,examples are: +\-elandore's energy bars; +\-mausuke's foreground(the one used on the playfield) +\-shanhigw's tile-based sprites; +The transparency pen table is like this: + +|------------------|---------------------| +| Character count | Transparency code | +|------------------|---------------------| +| 16 colors |=0x0 (4 bits) | +| 256 colors |=0x00 (8 bits) | +| 2048 colors |=0x000 (11 bits) | +| 32,768 colors |MSB=0 (bit 15) | +| 16,770,000 colors|MSB=0 (bit 31) | +|------------------|---------------------| +In other words,the first three types uses the offset and not the color allocated. + +-double density interlace setting (LSMD == 3) apparently does a lot of fancy stuff in the graphics sizes. + +-Debug key list(only if you enable the debug mode on top of this file): + \-T: NBG3 layer toggle + \-Y: NBG2 layer toggle + \-U: NBG1 layer toggle + \-I: NBG0 layer toggle + \-O: SPRITE toggle + \-K: RBG0 layer toggle + \-W Decodes the graphics for F4 menu. + \-M Stores VDP1 ram contents from a file. + \-N Stores VDP1 ram contents into a file. +*/ + +#include "emu.h" +#include "includes/saturn.h" // FIXME: this is a dependency from devices on MAME + + +#define DEBUG_MODE 0 +#define TEST_FUNCTIONS 0 +#define POPMESSAGE_DEBUG 0 + + +enum +{ + STV_TRANSPARENCY_PEN = 0x0, + STV_TRANSPARENCY_NONE = 0x1, + STV_TRANSPARENCY_ADD_BLEND = 0x2, + STV_TRANSPARENCY_ALPHA = 0x4 +}; + +#if DEBUG_MODE +#define LOG_VDP2 1 +#define LOG_ROZ 0 +#else +#define LOG_VDP2 0 +#define LOG_ROZ 0 +#endif + +/* + +-------------------------------------------------|-----------------------------|------------------------------ +| Function | Normal Scroll Screen | Rotation Scroll Screen | +| |-----------------------------|-----------------------------|------------------------------ +| | NBG0 | NBG1 | NBG2 | NBG3 | RBG0 | RBG1 | +-------------------------------------------------|-----------------------------|------------------------------ +| Character Colour | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours | 16 colours | +| Count | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " | 256 " " | +| | 2048 " " | 2048 " " | | | 2048 " " | 2048 " " | +| | 32768 " " | 32768 " " | | | 32768 " " | 32768 " " | +| | 16770000 " " | | | | 16770000 " " | 16770000 " " | +-------------------------------------------------|-----------------------------|------------------------------ +| Character Size | 1x1 Cells , 2x2 Cells | +-------------------------------------------------|-----------------------------|------------------------------ +| Pattern Name | 1 word , 2 words | +| Data Size | | +-------------------------------------------------|-----------------------------|------------------------------ +| Plane Size | 1 H x 1 V 1 Pages ; 2 H x 1 V 1 Pages ; 2 H x 2 V Pages | +-------------------------------------------------|-----------------------------|------------------------------ +| Plane Count | 4 | 16 | +-------------------------------------------------|-----------------------------|------------------------------ +| Bitmap Possible | Yes | No | Yes | No | +-------------------------------------------------|-----------------------------|------------------------------ +| Bitmap Size | 512 x 256 | N/A | 512x256 | N/A | +| | 512 x 512 | | 512x512 | | +| | 1024 x 256 | | | | +| | 1024 x 512 | | | | +-------------------------------------------------|-----------------------------|------------------------------ +| Scale | 0.25 x - 256 x | None | Any ? | +-------------------------------------------------|-----------------------------|------------------------------ +| Rotation | No | Yes | +-------------------------------------------------|-----------------------------|-----------------------------| +| Linescroll | Yes | No | +-------------------------------------------------|-----------------------------|------------------------------ +| Column Scroll | Yes | No | +-------------------------------------------------|-----------------------------|------------------------------ +| Mosaic | Yes | Horizontal Only | +-------------------------------------------------|-----------------------------|------------------------------ + +*/ + +/* 180000 - r/w - TVMD - TV Screen Mode + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | DISP | -- | -- | -- | -- | -- | -- | BDCLMD | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | LSMD1 | LSMD0 | VRESO1 | VRESO0 | -- | HRESO2 | HRESO1 | HRESO0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_TVMD (m_vdp2_regs[0x000/2]) + + #define STV_VDP2_DISP ((STV_VDP2_TVMD & 0x8000) >> 15) + #define STV_VDP2_BDCLMD ((STV_VDP2_TVMD & 0x0100) >> 8) + #define STV_VDP2_LSMD ((STV_VDP2_TVMD & 0x00c0) >> 6) + #define STV_VDP2_VRES ((STV_VDP2_TVMD & 0x0030) >> 4) + #define STV_VDP2_HRES ((STV_VDP2_TVMD & 0x0007) >> 0) + +/* 180002 - r/w - EXTEN - External Signal Enable Register + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | EXLTEN | EXSYEN | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | DASEL | EXBGEN | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_EXTEN (m_vdp2_regs[0x002/2]) + + #define STV_VDP2_EXLTEN ((STV_VDP2_EXTEN & 0x0200) >> 9) + +/* 180004 - r/o - TVSTAT - Screen Status + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | EXLTFG | EXSYFG | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | VBLANK | HBLANK | ODD | PAL | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + +/* 180006 - r/w - VRSIZE - VRAM Size + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VRAMSZ | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | VER3 | VER2 | VER1 | VER0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_VRSIZE (m_vdp2_regs[0x006/2]) + + #define STV_VDP2_VRAMSZ ((STV_VDP2_VRSIZE & 0x8000) >> 15) + +/* 180008 - r/o - HCNT - H-Counter + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | HCT9 | HCT8 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | HCT7 | HCT6 | HCT5 | HCT4 | HCT3 | HCT2 | HCT1 | HCT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_HCNT (m_vdp2_regs[0x008/2]) + +/* 18000A - r/o - VCNT - V-Counter + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | VCT9 | VCT8 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCT7 | VCT6 | VCT5 | VCT4 | VCT3 | VCT2 | VCT1 | VCT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_VCNT (m_vdp2_regs[0x00a/2]) + +/* 18000C - RESERVED + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + +/* 18000E - r/w - RAMCTL - RAM Control + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | CRKTE | -- | CRMD1 | CRMD0 | -- | -- | VRBMD | VRAMD | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | RDBSB11 | RDBSB10 | RDBSB01 | RDBSB00 | RDBSA11 | RDBSA10 | RDBSA01 | RDBSA00 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_RAMCTL (m_vdp2_regs[0x00e/2]) + + #define STV_VDP2_CRKTE ((STV_VDP2_RAMCTL & 0x8000) >> 15) + #define STV_VDP2_CRMD ((STV_VDP2_RAMCTL & 0x3000) >> 12) + #define STV_VDP2_RDBSB1 ((STV_VDP2_RAMCTL & 0x00c0) >> 6) + #define STV_VDP2_RDBSB0 ((STV_VDP2_RAMCTL & 0x0030) >> 4) + #define STV_VDP2_RDBSA1 ((STV_VDP2_RAMCTL & 0x000c) >> 2) + #define STV_VDP2_RDBSA0 ((STV_VDP2_RAMCTL & 0x0003) >> 0) + + +/* 180010 - r/w - -CYCA0L - VRAM CYCLE PATTERN (BANK A0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP0A03 | VCP0A02 | VCP0A01 | VCP0A00 | VCP1A03 | VCP1A02 | VCP1A01 | VCP1A00 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP2A03 | VCP2A02 | VCP2A01 | VCP2A00 | VCP3A03 | VCP3A02 | VCP3A01 | VCP3A00 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA0L (m_vdp2_regs[0x010/2]) + +/* 180012 - r/w - -CYCA0U - VRAM CYCLE PATTERN (BANK A0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP4A03 | VCP4A02 | VCP4A01 | VCP4A00 | VCP5A03 | VCP5A02 | VCP5A01 | VCP5A00 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP6A03 | VCP6A02 | VCP6A01 | VCP6A00 | VCP7A03 | VCP7A02 | VCP7A01 | VCP7A00 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA0U (m_vdp2_regs[0x012/2]) + +/* 180014 - r/w - -CYCA1L - VRAM CYCLE PATTERN (BANK A1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP0A13 | VCP0A12 | VCP0A11 | VCP0A10 | VCP1A13 | VCP1A12 | VCP1A11 | VCP1A10 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP2A13 | VCP2A12 | VCP2A11 | VCP2A10 | VCP3A13 | VCP3A12 | VCP3A11 | VCP3A10 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA1L (m_vdp2_regs[0x014/2]) + +/* 180016 - r/w - -CYCA1U - VRAM CYCLE PATTERN (BANK A1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP4A13 | VCP4A12 | VCP4A11 | VCP4A10 | VCP5A13 | VCP5A12 | VCP5A11 | VCP5A10 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP6A13 | VCP6A12 | VCP6A11 | VCP6A10 | VCP7A13 | VCP7A12 | VCP7A11 | VCP7A10 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA1U (m_vdp2_regs[0x016/2]) + +/* 180018 - r/w - -CYCB0L - VRAM CYCLE PATTERN (BANK B0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP0B03 | VCP0B02 | VCP0B01 | VCP0B00 | VCP1B03 | VCP1B02 | VCP1B01 | VCP1B00 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP2B03 | VCP2B02 | VCP2B01 | VCP2B00 | VCP3B03 | VCP3B02 | VCP3B01 | VCP3B00 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA2L (m_vdp2_regs[0x018/2]) + +/* 18001A - r/w - -CYCB0U - VRAM CYCLE PATTERN (BANK B0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP4B03 | VCP4B02 | VCP4B01 | VCP4B00 | VCP5B03 | VCP5B02 | VCP5B01 | VCP5B00 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP6B03 | VCP6B02 | VCP6B01 | VCP6B00 | VCP7B03 | VCP7B02 | VCP7B01 | VCP7B00 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA2U (m_vdp2_regs[0x01a/2]) + +/* 18001C - r/w - -CYCB1L - VRAM CYCLE PATTERN (BANK B1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP0B13 | VCP0B12 | VCP0B11 | VCP0B10 | VCP1B13 | VCP1B12 | VCP1B11 | VCP1B10 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP2B13 | VCP2B12 | VCP2B11 | VCP2B10 | VCP3B13 | VCP3B12 | VCP3B11 | VCP3B10 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA3L (m_vdp2_regs[0x01c/2]) + +/* 18001E - r/w - -CYCB1U - VRAM CYCLE PATTERN (BANK B1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | VCP4B13 | VCP4B12 | VCP4B11 | VCP4B10 | VCP5B13 | VCP5B12 | VCP5B11 | VCP5B10 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | VCP6B13 | VCP6B12 | VCP6B11 | VCP6B10 | VCP7B13 | VCP7B12 | VCP7B11 | VCP7B10 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CYCA3U (m_vdp2_regs[0x01e/2]) + +/* 180020 - r/w - BGON - SCREEN DISPLAY ENABLE + + this register allows each tilemap to be enabled or disabled and also which layers are solid + + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | R0TPON | N3TPON | N2TPON | N1TPON | N0TPON | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | R1ON | R0ON | N3ON | N2ON | N1ON | N0ON | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_BGON (m_vdp2_regs[0x020/2]) + + // NxOn - Layer Enable Register + #define STV_VDP2_xxON ((STV_VDP2_BGON & 0x001f) >> 0) /* to see if anything is enabled */ + + #define STV_VDP2_N0ON ((STV_VDP2_BGON & 0x0001) >> 0) /* N0On = NBG0 Enable */ + #define STV_VDP2_N1ON ((STV_VDP2_BGON & 0x0002) >> 1) /* N1On = NBG1 Enable */ + #define STV_VDP2_N2ON ((STV_VDP2_BGON & 0x0004) >> 2) /* N2On = NBG2 Enable */ + #define STV_VDP2_N3ON ((STV_VDP2_BGON & 0x0008) >> 3) /* N3On = NBG3 Enable */ + #define STV_VDP2_R0ON ((STV_VDP2_BGON & 0x0010) >> 4) /* R0On = RBG0 Enable */ + #define STV_VDP2_R1ON ((STV_VDP2_BGON & 0x0020) >> 5) /* R1On = RBG1 Enable */ + + // NxTPON - Transparency Pen Enable Registers + #define STV_VDP2_N0TPON ((STV_VDP2_BGON & 0x0100) >> 8) /* N0TPON = NBG0 Draw Transparent Pen (as solid) /or/ RBG1 Draw Transparent Pen */ + #define STV_VDP2_N1TPON ((STV_VDP2_BGON & 0x0200) >> 9) /* N1TPON = NBG1 Draw Transparent Pen (as solid) /or/ EXBG Draw Transparent Pen */ + #define STV_VDP2_N2TPON ((STV_VDP2_BGON & 0x0400) >> 10)/* N2TPON = NBG2 Draw Transparent Pen (as solid) */ + #define STV_VDP2_N3TPON ((STV_VDP2_BGON & 0x0800) >> 11)/* N3TPON = NBG3 Draw Transparent Pen (as solid) */ + #define STV_VDP2_R0TPON ((STV_VDP2_BGON & 0x1000) >> 12)/* R0TPON = RBG0 Draw Transparent Pen (as solid) */ + +/* +180022 - MZCTL - Mosaic Control +bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MZCTL (m_vdp2_regs[0x022/2]) + + #define STV_VDP2_MZSZV ((STV_VDP2_MZCTL & 0xf000) >> 12) + #define STV_VDP2_MZSZH ((STV_VDP2_MZCTL & 0x0f00) >> 8) + #define STV_VDP2_R0MZE ((STV_VDP2_MZCTL & 0x0010) >> 4) + #define STV_VDP2_N3MZE ((STV_VDP2_MZCTL & 0x0008) >> 3) + #define STV_VDP2_N2MZE ((STV_VDP2_MZCTL & 0x0004) >> 2) + #define STV_VDP2_N1MZE ((STV_VDP2_MZCTL & 0x0002) >> 1) + #define STV_VDP2_N0MZE ((STV_VDP2_MZCTL & 0x0001) >> 0) + +/*180024 - Special Function Code Select + +*/ + + #define STV_VDP2_SFSEL (m_vdp2_regs[0x024/2]) + +/*180026 - Special Function Code + +*/ + + #define STV_VDP2_SFCODE (m_vdp2_regs[0x026/2]) + + +/* +180028 - CHCTLA - Character Control (NBG0, NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | N1CHCN1 | N1CHCN0 | N1BMSZ1 | N1BMSZ0 | N1BMEN | N1CHSZ | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | N0CHCN2 | N0CHCN1 | N0CHCN0 | N0BMSZ1 | N0BMSZ0 | N0BMEN | N0CHSZ | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CHCTLA (m_vdp2_regs[0x028/2]) + +/* -------------------------- NBG0 Character Control Registers -------------------------- */ + +/* N0CHCNx NBG0 (or RGB1) Colour Depth + 000 - 16 Colours + 001 - 256 Colours + 010 - 2048 Colours + 011 - 32768 Colours (RGB5) + 100 - 16770000 Colours (RGB8) + 101 - invalid + 110 - invalid + 111 - invalid */ + #define STV_VDP2_N0CHCN ((STV_VDP2_CHCTLA & 0x0070) >> 4) + +/* N0BMSZx - NBG0 Bitmap Size *guessed* + 00 - 512 x 256 + 01 - 512 x 512 + 10 - 1024 x 256 + 11 - 1024 x 512 */ + #define STV_VDP2_N0BMSZ ((STV_VDP2_CHCTLA & 0x000c) >> 2) + +/* N0BMEN - NBG0 Bitmap Enable + 0 - use cell mode + 1 - use bitmap mode */ + #define STV_VDP2_N0BMEN ((STV_VDP2_CHCTLA & 0x0002) >> 1) + +/* N0CHSZ - NBG0 Character (Tile) Size + 0 - 1 cell x 1 cell (8x8) + 1 - 2 cells x 2 cells (16x16) */ + #define STV_VDP2_N0CHSZ ((STV_VDP2_CHCTLA & 0x0001) >> 0) + +/* -------------------------- NBG1 Character Control Registers -------------------------- */ + +/* N1CHCNx - NBG1 (or EXB1) Colour Depth + 00 - 16 Colours + 01 - 256 Colours + 10 - 2048 Colours + 11 - 32768 Colours (RGB5) */ + #define STV_VDP2_N1CHCN ((STV_VDP2_CHCTLA & 0x3000) >> 12) + +/* N1BMSZx - NBG1 Bitmap Size *guessed* + 00 - 512 x 256 + 01 - 512 x 512 + 10 - 1024 x 256 + 11 - 1024 x 512 */ + #define STV_VDP2_N1BMSZ ((STV_VDP2_CHCTLA & 0x0c00) >> 10) + +/* N1BMEN - NBG1 Bitmap Enable + 0 - use cell mode + 1 - use bitmap mode */ + #define STV_VDP2_N1BMEN ((STV_VDP2_CHCTLA & 0x0200) >> 9) + +/* N1CHSZ - NBG1 Character (Tile) Size + 0 - 1 cell x 1 cell (8x8) + 1 - 2 cells x 2 cells (16x16) */ + #define STV_VDP2_N1CHSZ ((STV_VDP2_CHCTLA & 0x0100) >> 8) + +/* +18002A - CHCTLB - Character Control (NBG2, NBG1, RBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | R0CHCN2 | R0CHCN1 | R0CHCN0 | -- | R0BMSZ | R0BMEN | R0CHSZ | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | N3CHCN | N3CHSZ | -- | -- | N2CHCN | N2CHSZ | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CHCTLB (m_vdp2_regs[0x02a/2]) + +/* -------------------------- RBG0 Character Control Registers -------------------------- */ + + +/* R0CHCNx RBG0 Colour Depth + 000 - 16 Colours + 001 - 256 Colours + 010 - 2048 Colours + 011 - 32768 Colours (RGB5) + 100 - 16770000 Colours (RGB8) + 101 - invalid + 110 - invalid + 111 - invalid */ + #define STV_VDP2_R0CHCN ((STV_VDP2_CHCTLB & 0x7000) >> 12) + +/* R0BMSZx - RBG0 Bitmap Size *guessed* + 00 - 512 x 256 + 01 - 512 x 512 */ + #define STV_VDP2_R0BMSZ ((STV_VDP2_CHCTLB & 0x0400) >> 10) + +/* R0BMEN - RBG0 Bitmap Enable + 0 - use cell mode + 1 - use bitmap mode */ + #define STV_VDP2_R0BMEN ((STV_VDP2_CHCTLB & 0x0200) >> 9) + +/* R0CHSZ - RBG0 Character (Tile) Size + 0 - 1 cell x 1 cell (8x8) + 1 - 2 cells x 2 cells (16x16) */ + #define STV_VDP2_R0CHSZ ((STV_VDP2_CHCTLB & 0x0100) >> 8) + + #define STV_VDP2_N3CHCN ((STV_VDP2_CHCTLB & 0x0020) >> 5) + #define STV_VDP2_N3CHSZ ((STV_VDP2_CHCTLB & 0x0010) >> 4) + #define STV_VDP2_N2CHCN ((STV_VDP2_CHCTLB & 0x0002) >> 1) + #define STV_VDP2_N2CHSZ ((STV_VDP2_CHCTLB & 0x0001) >> 0) + + +/* +18002C - BMPNA - Bitmap Palette Number (NBG0, NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_BMPNA (m_vdp2_regs[0x02c/2]) + + #define STV_VDP2_N1BMP ((STV_VDP2_BMPNA & 0x0700) >> 8) + #define STV_VDP2_N0BMP ((STV_VDP2_BMPNA & 0x0007) >> 0) + +/* 18002E - Bitmap Palette Number (RBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_BMPNB (m_vdp2_regs[0x02e/2]) + + #define STV_VDP2_R0BMP ((STV_VDP2_BMPNB & 0x0007) >> 0) + +/* 180030 - PNCN0 - Pattern Name Control (NBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | N0PNB | N0CNSM | -- | -- | -- | -- | N0SPR | N0SCC | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | N0SPLT6 | N0SPLT5 | N0SPLT4 | N0SPCN4 | N0SPCN3 | N0SPCN2 | N0SPCN1 | N0SPCN0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PNCN0 (m_vdp2_regs[0x030/2]) + +/* Pattern Data Size + 0 = 2 bytes + 1 = 1 byte */ + #define STV_VDP2_N0PNB ((STV_VDP2_PNCN0 & 0x8000) >> 15) + +/* Character Number Supplement (in 1 byte mode) + 0 = Character Number = 10bits + 2bits for flip + 1 = Character Number = 12 bits, no flip */ + #define STV_VDP2_N0CNSM ((STV_VDP2_PNCN0 & 0x4000) >> 14) + +/* NBG0 Special Priority Register (in 1 byte mode) */ + #define STV_VDP2_N0SPR ((STV_VDP2_PNCN0 & 0x0200) >> 9) + +/* NBG0 Special Colour Control Register (in 1 byte mode) */ + #define STV_VDP2_N0SCC ((STV_VDP2_PNCN0 & 0x0100) >> 8) + +/* Supplementary Palette Bits (in 1 byte mode) */ + #define STV_VDP2_N0SPLT ((STV_VDP2_PNCN0 & 0x00e0) >> 5) + +/* Supplementary Character Bits (in 1 byte mode) */ + #define STV_VDP2_N0SPCN ((STV_VDP2_PNCN0 & 0x001f) >> 0) + +/* 180032 - Pattern Name Control (NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PNCN1 (m_vdp2_regs[0x032/2]) + +/* Pattern Data Size + 0 = 2 bytes + 1 = 1 byte */ + #define STV_VDP2_N1PNB ((STV_VDP2_PNCN1 & 0x8000) >> 15) + +/* Character Number Supplement (in 1 byte mode) + 0 = Character Number = 10bits + 2bits for flip + 1 = Character Number = 12 bits, no flip */ + #define STV_VDP2_N1CNSM ((STV_VDP2_PNCN1 & 0x4000) >> 14) + +/* NBG0 Special Priority Register (in 1 byte mode) */ + #define STV_VDP2_N1SPR ((STV_VDP2_PNCN1 & 0x0200) >> 9) + +/* NBG0 Special Colour Control Register (in 1 byte mode) */ + #define STV_VDP2_N1SCC ((STV_VDP2_PNCN1 & 0x0100) >> 8) + +/* Supplementary Palette Bits (in 1 byte mode) */ + #define STV_VDP2_N1SPLT ((STV_VDP2_PNCN1 & 0x00e0) >> 5) + +/* Supplementary Character Bits (in 1 byte mode) */ + #define STV_VDP2_N1SPCN ((STV_VDP2_PNCN1 & 0x001f) >> 0) + + +/* 180034 - Pattern Name Control (NBG2) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PNCN2 (m_vdp2_regs[0x034/2]) + +/* Pattern Data Size + 0 = 2 bytes + 1 = 1 byte */ + #define STV_VDP2_N2PNB ((STV_VDP2_PNCN2 & 0x8000) >> 15) + +/* Character Number Supplement (in 1 byte mode) + 0 = Character Number = 10bits + 2bits for flip + 1 = Character Number = 12 bits, no flip */ + #define STV_VDP2_N2CNSM ((STV_VDP2_PNCN2 & 0x4000) >> 14) + +/* NBG0 Special Priority Register (in 1 byte mode) */ + #define STV_VDP2_N2SPR ((STV_VDP2_PNCN2 & 0x0200) >> 9) + +/* NBG0 Special Colour Control Register (in 1 byte mode) */ + #define STV_VDP2_N2SCC ((STV_VDP2_PNCN2 & 0x0100) >> 8) + +/* Supplementary Palette Bits (in 1 byte mode) */ + #define STV_VDP2_N2SPLT ((STV_VDP2_PNCN2 & 0x00e0) >> 5) + +/* Supplementary Character Bits (in 1 byte mode) */ + #define STV_VDP2_N2SPCN ((STV_VDP2_PNCN2 & 0x001f) >> 0) + + +/* 180036 - Pattern Name Control (NBG3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | N3PNB | N3CNSM | -- | -- | -- | -- | N3SPR | N3SCC | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | N3SPLT6 | N3SPLT5 | N3SPLT4 | N3SPCN4 | N3SPCN3 | N3SPCN2 | N3SPCN1 | N3SPCN0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PNCN3 (m_vdp2_regs[0x036/2]) + +/* Pattern Data Size + 0 = 2 bytes + 1 = 1 byte */ + #define STV_VDP2_N3PNB ((STV_VDP2_PNCN3 & 0x8000) >> 15) + +/* Character Number Supplement (in 1 byte mode) + 0 = Character Number = 10bits + 2bits for flip + 1 = Character Number = 12 bits, no flip */ + #define STV_VDP2_N3CNSM ((STV_VDP2_PNCN3 & 0x4000) >> 14) + +/* NBG0 Special Priority Register (in 1 byte mode) */ + #define STV_VDP2_N3SPR ((STV_VDP2_PNCN3 & 0x0200) >> 9) + +/* NBG0 Special Colour Control Register (in 1 byte mode) */ + #define STV_VDP2_N3SCC ((STV_VDP2_PNCN3 & 0x0100) >> 8) + +/* Supplementary Palette Bits (in 1 byte mode) */ + #define STV_VDP2_N3SPLT ((STV_VDP2_PNCN3 & 0x00e0) >> 5) + +/* Supplementary Character Bits (in 1 byte mode) */ + #define STV_VDP2_N3SPCN ((STV_VDP2_PNCN3 & 0x001f) >> 0) + + +/* 180038 - Pattern Name Control (RBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PNCR (m_vdp2_regs[0x038/2]) + +/* Pattern Data Size + 0 = 2 bytes + 1 = 1 byte */ + #define STV_VDP2_R0PNB ((STV_VDP2_PNCR & 0x8000) >> 15) + +/* Character Number Supplement (in 1 byte mode) + 0 = Character Number = 10bits + 2bits for flip + 1 = Character Number = 12 bits, no flip */ + #define STV_VDP2_R0CNSM ((STV_VDP2_PNCR & 0x4000) >> 14) + +/* NBG0 Special Priority Register (in 1 byte mode) */ + #define STV_VDP2_R0SPR ((STV_VDP2_PNCR & 0x0200) >> 9) + +/* NBG0 Special Colour Control Register (in 1 byte mode) */ + #define STV_VDP2_R0SCC ((STV_VDP2_PNCR & 0x0100) >> 8) + +/* Supplementary Palette Bits (in 1 byte mode) */ + #define STV_VDP2_R0SPLT ((STV_VDP2_PNCR & 0x00e0) >> 5) + +/* Supplementary Character Bits (in 1 byte mode) */ + #define STV_VDP2_R0SPCN ((STV_VDP2_PNCR & 0x001f) >> 0) + +/* 18003A - PLSZ - Plane Size + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | N3PLSZ1 | N3PLSZ0 | -- | -- | N1PLSZ1 | N1PLSZ0 | N0PLSZ1 | N0PLSZ0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PLSZ (m_vdp2_regs[0x03a/2]) + + /* NBG0 Plane Size + 00 1H Page x 1V Page + 01 2H Pages x 1V Page + 10 invalid + 11 2H Pages x 2V Pages */ + #define STV_VDP2_RBOVR ((STV_VDP2_PLSZ & 0xc000) >> 14) + #define STV_VDP2_RBPLSZ ((STV_VDP2_PLSZ & 0x3000) >> 12) + #define STV_VDP2_RAOVR ((STV_VDP2_PLSZ & 0x0c00) >> 10) + #define STV_VDP2_RAPLSZ ((STV_VDP2_PLSZ & 0x0300) >> 8) + #define STV_VDP2_N3PLSZ ((STV_VDP2_PLSZ & 0x00c0) >> 6) + #define STV_VDP2_N2PLSZ ((STV_VDP2_PLSZ & 0x0030) >> 4) + #define STV_VDP2_N1PLSZ ((STV_VDP2_PLSZ & 0x000c) >> 2) + #define STV_VDP2_N0PLSZ ((STV_VDP2_PLSZ & 0x0003) >> 0) + +/* 18003C - MPOFN - Map Offset (NBG0, NBG1, NBG2, NBG3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | N3MP8 | N3MP7 | N3MP6 | -- | N2MP8 | N2MP7 | N2MP6 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | N1MP8 | N1MP7 | N1MP6 | -- | N0MP8 | N0MP7 | N0MP6 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPOFN_ (m_vdp2_regs[0x03c/2]) + + /* Higher 3 bits of the map offset for each layer */ + #define STV_VDP2_N3MP_ ((STV_VDP2_MPOFN_ & 0x3000) >> 12) + #define STV_VDP2_N2MP_ ((STV_VDP2_MPOFN_ & 0x0300) >> 8) + #define STV_VDP2_N1MP_ ((STV_VDP2_MPOFN_ & 0x0030) >> 4) + #define STV_VDP2_N0MP_ ((STV_VDP2_MPOFN_ & 0x0003) >> 0) + + + + +/* 18003E - Map Offset (Rotation Parameter A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPOFR_ (m_vdp2_regs[0x03e/2]) + + #define STV_VDP2_RBMP_ ((STV_VDP2_MPOFR_ & 0x0030) >> 4) + #define STV_VDP2_RAMP_ ((STV_VDP2_MPOFR_ & 0x0003) >> 0) + +/* 180040 - MPABN0 - Map (NBG0, Plane A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | N0MPB5 | N0MPB4 | N0MPB3 | N0MPB2 | N0MPB1 | N0MPB0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | N0MPA5 | N0MPA4 | N0MPA3 | N0MPA2 | N0MPA1 | N0MPA0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPABN0 (m_vdp2_regs[0x040/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */ + #define STV_VDP2_N0MPB ((STV_VDP2_MPABN0 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */ + #define STV_VDP2_N0MPA ((STV_VDP2_MPABN0 & 0x003f) >> 0) + + +/* 180042 - MPCDN0 - (NBG0, Plane C,D) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | N0MPD5 | N0MPD4 | N0MPD3 | N0MPD2 | N0MPD1 | N0MPD0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | N0MPC5 | N0MPC4 | N0MPC3 | N0MPC2 | N0MPC1 | N0MPC0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPCDN0 (m_vdp2_regs[0x042/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */ + #define STV_VDP2_N0MPD ((STV_VDP2_MPCDN0 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */ + #define STV_VDP2_N0MPC ((STV_VDP2_MPCDN0 & 0x003f) >> 0) + + +/* 180044 - Map (NBG1, Plane A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPABN1 (m_vdp2_regs[0x044/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */ + #define STV_VDP2_N1MPB ((STV_VDP2_MPABN1 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */ + #define STV_VDP2_N1MPA ((STV_VDP2_MPABN1 & 0x003f) >> 0) + +/* 180046 - Map (NBG1, Plane C,D) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPCDN1 (m_vdp2_regs[0x046/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */ + #define STV_VDP2_N1MPD ((STV_VDP2_MPCDN1 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */ + #define STV_VDP2_N1MPC ((STV_VDP2_MPCDN1 & 0x003f) >> 0) + + +/* 180048 - Map (NBG2, Plane A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPABN2 (m_vdp2_regs[0x048/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG2 */ + #define STV_VDP2_N2MPB ((STV_VDP2_MPABN2 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG2 */ + #define STV_VDP2_N2MPA ((STV_VDP2_MPABN2 & 0x003f) >> 0) + +/* 18004a - Map (NBG2, Plane C,D) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPCDN2 (m_vdp2_regs[0x04a/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG2 */ + #define STV_VDP2_N2MPD ((STV_VDP2_MPCDN2 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG2 */ + #define STV_VDP2_N2MPC ((STV_VDP2_MPCDN2 & 0x003f) >> 0) + +/* 18004c - Map (NBG3, Plane A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPABN3 (m_vdp2_regs[0x04c/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */ + #define STV_VDP2_N3MPB ((STV_VDP2_MPABN3 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */ + #define STV_VDP2_N3MPA ((STV_VDP2_MPABN3 & 0x003f) >> 0) + + +/* 18004e - Map (NBG3, Plane C,D) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPCDN3 (m_vdp2_regs[0x04e/2]) + + /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */ + #define STV_VDP2_N3MPD ((STV_VDP2_MPCDN3 & 0x3f00) >> 8) + + /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */ + #define STV_VDP2_N3MPC ((STV_VDP2_MPCDN3 & 0x003f) >> 0) + +/* 180050 - Map (Rotation Parameter A, Plane A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPABRA (m_vdp2_regs[0x050/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */ + #define STV_VDP2_RAMPB ((STV_VDP2_MPABRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */ + #define STV_VDP2_RAMPA ((STV_VDP2_MPABRA & 0x003f) >> 0) + + + +/* 180052 - Map (Rotation Parameter A, Plane C,D) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPCDRA (m_vdp2_regs[0x052/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */ + #define STV_VDP2_RAMPD ((STV_VDP2_MPCDRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */ + #define STV_VDP2_RAMPC ((STV_VDP2_MPCDRA & 0x003f) >> 0) + +/* 180054 - Map (Rotation Parameter A, Plane E,F) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPEFRA (m_vdp2_regs[0x054/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */ + #define STV_VDP2_RAMPF ((STV_VDP2_MPEFRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */ + #define STV_VDP2_RAMPE ((STV_VDP2_MPEFRA & 0x003f) >> 0) + +/* 180056 - Map (Rotation Parameter A, Plane G,H) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPGHRA (m_vdp2_regs[0x056/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */ + #define STV_VDP2_RAMPH ((STV_VDP2_MPGHRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */ + #define STV_VDP2_RAMPG ((STV_VDP2_MPGHRA & 0x003f) >> 0) + +/* 180058 - Map (Rotation Parameter A, Plane I,J) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPIJRA (m_vdp2_regs[0x058/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */ + #define STV_VDP2_RAMPJ ((STV_VDP2_MPIJRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane I of Tilemap RBG0 */ + #define STV_VDP2_RAMPI ((STV_VDP2_MPIJRA & 0x003f) >> 0) + +/* 18005a - Map (Rotation Parameter A, Plane K,L) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPKLRA (m_vdp2_regs[0x05a/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */ + #define STV_VDP2_RAMPL ((STV_VDP2_MPKLRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */ + #define STV_VDP2_RAMPK ((STV_VDP2_MPKLRA & 0x003f) >> 0) + +/* 18005c - Map (Rotation Parameter A, Plane M,N) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPMNRA (m_vdp2_regs[0x05c/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */ + #define STV_VDP2_RAMPN ((STV_VDP2_MPMNRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */ + #define STV_VDP2_RAMPM ((STV_VDP2_MPMNRA & 0x003f) >> 0) + +/* 18005e - Map (Rotation Parameter A, Plane O,P) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_MPOPRA (m_vdp2_regs[0x05e/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */ + #define STV_VDP2_RAMPP ((STV_VDP2_MPOPRA & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */ + #define STV_VDP2_RAMPO ((STV_VDP2_MPOPRA & 0x003f) >> 0) + +/* 180060 - Map (Rotation Parameter B, Plane A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPABRB (m_vdp2_regs[0x060/2]) + + /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */ + #define STV_VDP2_RBMPB ((STV_VDP2_MPABRB & 0x3f00) >> 8) + + /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */ + #define STV_VDP2_RBMPA ((STV_VDP2_MPABRB & 0x003f) >> 0) + + +/* 180062 - Map (Rotation Parameter B, Plane C,D) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPCDRB (m_vdp2_regs[0x062/2]) + + /* R0MPD5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */ + #define STV_VDP2_RBMPD ((STV_VDP2_MPCDRB & 0x3f00) >> 8) + + /* R0MPc5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */ + #define STV_VDP2_RBMPC ((STV_VDP2_MPCDRB & 0x003f) >> 0) + +/* 180064 - Map (Rotation Parameter B, Plane E,F) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPEFRB (m_vdp2_regs[0x064/2]) + + /* R0MPF5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */ + #define STV_VDP2_RBMPF ((STV_VDP2_MPEFRB & 0x3f00) >> 8) + + /* R0MPE5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */ + #define STV_VDP2_RBMPE ((STV_VDP2_MPEFRB & 0x003f) >> 0) + +/* 180066 - Map (Rotation Parameter B, Plane G,H) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPGHRB (m_vdp2_regs[0x066/2]) + + /* R0MPH5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */ + #define STV_VDP2_RBMPH ((STV_VDP2_MPGHRB & 0x3f00) >> 8) + + /* R0MPG5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */ + #define STV_VDP2_RBMPG ((STV_VDP2_MPGHRB & 0x003f) >> 0) + +/* 180068 - Map (Rotation Parameter B, Plane I,J) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPIJRB (m_vdp2_regs[0x068/2]) + + /* R0MPJ5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */ + #define STV_VDP2_RBMPJ ((STV_VDP2_MPIJRB & 0x3f00) >> 8) + + /* R0MPI5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */ + #define STV_VDP2_RBMPI ((STV_VDP2_MPIJRB & 0x003f) >> 0) + +/* 18006a - Map (Rotation Parameter B, Plane K,L) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPKLRB (m_vdp2_regs[0x06a/2]) + + /* R0MPL5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */ + #define STV_VDP2_RBMPL ((STV_VDP2_MPKLRB & 0x3f00) >> 8) + + /* R0MPK5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */ + #define STV_VDP2_RBMPK ((STV_VDP2_MPKLRB & 0x003f) >> 0) + +/* 18006c - Map (Rotation Parameter B, Plane M,N) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPMNRB (m_vdp2_regs[0x06c/2]) + + /* R0MPN5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */ + #define STV_VDP2_RBMPN ((STV_VDP2_MPMNRB & 0x3f00) >> 8) + + /* R0MPM5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */ + #define STV_VDP2_RBMPM ((STV_VDP2_MPMNRB & 0x003f) >> 0) + +/* 18006e - Map (Rotation Parameter B, Plane O,P) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_MPOPRB (m_vdp2_regs[0x06e/2]) + + /* R0MPP5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */ + #define STV_VDP2_RBMPP ((STV_VDP2_MPOPRB & 0x3f00) >> 8) + + /* R0MPO5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */ + #define STV_VDP2_RBMPO ((STV_VDP2_MPOPRB & 0x003f) >> 0) + +/* 180070 - SCXIN0 - Screen Scroll (NBG0, Horizontal Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCXIN0 (m_vdp2_regs[0x070/2]) + + +/* 180072 - Screen Scroll (NBG0, Horizontal Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCXDN0 (m_vdp2_regs[0x072/2]) + +/* 180074 - SCYIN0 - Screen Scroll (NBG0, Vertical Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_SCYIN0 (m_vdp2_regs[0x074/2]) + + +/* 180076 - Screen Scroll (NBG0, Vertical Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCYDN0 (m_vdp2_regs[0x076/2]) + +/* 180078 - Coordinate Inc (NBG0, Horizontal Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMXIN0 (m_vdp2_regs[0x078/2]) + + #define STV_VDP2_N0ZMXI ((STV_VDP2_ZMXIN0 & 0x0007) >> 0) + +/* 18007a - Coordinate Inc (NBG0, Horizontal Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMXDN0 (m_vdp2_regs[0x07a/2]) + + #define STV_VDP2_N0ZMXD ((STV_VDP2_ZMXDN0 >> 8)& 0xff) + #define STV_VDP2_ZMXN0 (((STV_VDP2_N0ZMXI<<16) | (STV_VDP2_N0ZMXD<<8)) & 0x0007ff00) + + +/* 18007c - Coordinate Inc (NBG0, Vertical Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMYIN0 (m_vdp2_regs[0x07c/2]) + + #define STV_VDP2_N0ZMYI ((STV_VDP2_ZMYIN0 & 0x0007) >> 0) + +/* 18007e - Coordinate Inc (NBG0, Vertical Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMYDN0 (m_vdp2_regs[0x07e/2]) + + #define STV_VDP2_N0ZMYD ((STV_VDP2_ZMYDN0 >> 8)& 0xff) + #define STV_VDP2_ZMYN0 (((STV_VDP2_N0ZMYI<<16) | (STV_VDP2_N0ZMYD<<8)) & 0x0007ff00) + +/* 180080 - SCXIN1 - Screen Scroll (NBG1, Horizontal Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCXIN1 (m_vdp2_regs[0x080/2]) + +/* 180082 - Screen Scroll (NBG1, Horizontal Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCXDN1 (m_vdp2_regs[0x082/2]) + +/* 180084 - SCYIN1 - Screen Scroll (NBG1, Vertical Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCYIN1 (m_vdp2_regs[0x084/2]) + +/* 180086 - Screen Scroll (NBG1, Vertical Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCYDN1 (m_vdp2_regs[0x086/2]) + +/* 180088 - Coordinate Inc (NBG1, Horizontal Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMXIN1 (m_vdp2_regs[0x088/2]) + + #define STV_VDP2_N1ZMXI ((STV_VDP2_ZMXIN1 & 0x0007) >> 0) + +/* 18008a - Coordinate Inc (NBG1, Horizontal Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMXDN1 (m_vdp2_regs[0x08a/2]) + + #define STV_VDP2_N1ZMXD ((STV_VDP2_ZMXDN1 >> 8)& 0xff) + #define STV_VDP2_ZMXN1 (((STV_VDP2_N1ZMXI<<16) | (STV_VDP2_N1ZMXD<<8)) & 0x0007ff00) + +/* 18008c - Coordinate Inc (NBG1, Vertical Integer Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMYIN1 (m_vdp2_regs[0x08c/2]) + + #define STV_VDP2_N1ZMYI ((STV_VDP2_ZMYIN1 & 0x0007) >> 0) + +/* 18008e - Coordinate Inc (NBG1, Vertical Fractional Part) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMYDN1 (m_vdp2_regs[0x08e/2]) + + #define STV_VDP2_N1ZMYD ((STV_VDP2_ZMYDN1 >> 8)& 0xff) + #define STV_VDP2_ZMYN1 (((STV_VDP2_N1ZMYI<<16) | (STV_VDP2_N1ZMYD<<8)) & 0x007ff00) + +/* 180090 - SCXN2 - Screen Scroll (NBG2, Horizontal) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCXN2 (m_vdp2_regs[0x090/2]) + +/* 180092 - SCYN2 - Screen Scroll (NBG2, Vertical) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCYN2 (m_vdp2_regs[0x092/2]) + +/* 180094 - SCXN3 - Screen Scroll (NBG3, Horizontal) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCXN3 (m_vdp2_regs[0x094/2]) + +/* 180096 - SCYN3 - Screen Scroll (NBG3, Vertical) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCYN3 (m_vdp2_regs[0x096/2]) + +/* 180098 - Reduction Enable + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | N1ZMQT | N1ZMHF | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | N0ZMQT | N0ZMHF | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_ZMCTL (m_vdp2_regs[0x098/2]) + + #define STV_VDP2_N1ZMQT ((STV_VDP2_ZMCTL & 0x0200) >> 9) + #define STV_VDP2_N1ZMHF ((STV_VDP2_ZMCTL & 0x0100) >> 8) + #define STV_VDP2_N0ZMQT ((STV_VDP2_ZMCTL & 0x0002) >> 1) + #define STV_VDP2_N0ZMHF ((STV_VDP2_ZMCTL & 0x0001) >> 0) + +/* 18009a - Line and Vertical Cell Scroll Control (NBG0, NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SCRCTL (m_vdp2_regs[0x09a/2]) + + #define STV_VDP2_N1LSS ((STV_VDP2_SCRCTL & 0x3000) >> 12) + #define STV_VDP2_N1LZMX ((STV_VDP2_SCRCTL & 0x0800) >> 11) + #define STV_VDP2_N1LSCY ((STV_VDP2_SCRCTL & 0x0400) >> 10) + #define STV_VDP2_N1LSCX ((STV_VDP2_SCRCTL & 0x0200) >> 9) + #define STV_VDP2_N1VCSC ((STV_VDP2_SCRCTL & 0x0100) >> 8) + #define STV_VDP2_N0LSS ((STV_VDP2_SCRCTL & 0x0030) >> 4) + #define STV_VDP2_N0LZMX ((STV_VDP2_SCRCTL & 0x0008) >> 3) + #define STV_VDP2_N0LSCY ((STV_VDP2_SCRCTL & 0x0004) >> 2) + #define STV_VDP2_N0LSCX ((STV_VDP2_SCRCTL & 0x0002) >> 1) + #define STV_VDP2_N0VCSC ((STV_VDP2_SCRCTL & 0x0001) >> 0) + +/* 18009c - Vertical Cell Table Address (NBG0, NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_VCSTAU (m_vdp2_regs[0x09c/2] & 7) + + +/* 18009e - Vertical Cell Table Address (NBG0, NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_VCSTAL (m_vdp2_regs[0x09e/2]) + +/* 1800a0 - LSTA0U - Line Scroll Table Address (NBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + /*bit 2 unused when VRAM = 4 Mbits*/ + #define STV_VDP2_LSTA0U (m_vdp2_regs[0x0a0/2] & 7) + +/* 1800a2 - LSTA0L - Line Scroll Table Address (NBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LSTA0L (m_vdp2_regs[0x0a2/2]) + +/* 1800a4 - LSTA1U - Line Scroll Table Address (NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + /*bit 2 unused when VRAM = 4 Mbits*/ + #define STV_VDP2_LSTA1U (m_vdp2_regs[0x0a4/2] & 7) + +/* 1800a6 - LSTA1L - Line Scroll Table Address (NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LSTA1L (m_vdp2_regs[0x0a6/2]) + +/* 1800a8 - LCTAU - Line Colour Screen Table Address + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LCTAU (m_vdp2_regs[0x0a8/2]) + #define STV_VDP2_LCCLMD ((STV_VDP2_LCTAU & 0x8000) >> 15) + +/* 1800aa - LCTAL - Line Colour Screen Table Address + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_LCTAL (m_vdp2_regs[0x0aa/2]) + + #define STV_VDP2_LCTA (((STV_VDP2_LCTAU & 0x0007) << 16) | (STV_VDP2_LCTAL & 0xffff)) + +/* 1800ac - Back Screen Table Address + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | BKCLMD | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | BKTA18 | BKTA17 | BKTA16 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_BKTAU (m_vdp2_regs[0x0ac/2]) + + #define STV_VDP2_BKCLMD ((STV_VDP2_BKTAU & 0x8000) >> 15) + + +/* 1800ae - Back Screen Table Address + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | BKTA15 | BKTA14 | BKTA13 | BKTA12 | BKTA11 | BKTA10 | BKTA9 | BKTA8 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | BKTA7 | BKTA7 | BKTA6 | BKTA5 | BKTA4 | BKTA3 | BKTA2 | BKTA0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_BKTAL (m_vdp2_regs[0x0ae/2]) + + #define STV_VDP2_BKTA (((STV_VDP2_BKTAU & 0x0007) << 16) | (STV_VDP2_BKTAL & 0xffff)) + +/* 1800b0 - RPMD - Rotation Parameter Mode + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_RPMD ((m_vdp2_regs[0x0b0/2]) & 0x0003) + +/* 1800b2 - RPRCTL - Rotation Parameter Read Control + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | RBKASTRE | RBYSTRE | RBXSTRE | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | RAKASTRE | RAYSTRE | RBXSTRE | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_RPRCTL (m_vdp2_regs[0x0b2/2]) + #define STV_VDP2_RBKASTRE ((STV_VDP2_RPRCTL & 0x0400) >> 10) + #define STV_VDP2_RBYSTRE ((STV_VDP2_RPRCTL & 0x0200) >> 9) + #define STV_VDP2_RBXSTRE ((STV_VDP2_RPRCTL & 0x0100) >> 8) + #define STV_VDP2_RAKASTRE ((STV_VDP2_RPRCTL & 0x0004) >> 2) + #define STV_VDP2_RAYSTRE ((STV_VDP2_RPRCTL & 0x0002) >> 1) + #define STV_VDP2_RAXSTRE ((STV_VDP2_RPRCTL & 0x0001) >> 0) + +/* 1800b4 - KTCTL - Coefficient Table Control + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | RBKLCE | RBKMD1 | RBKMD0 | RBKDBS | RBKTE | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | RAKLCE | RAKMD1 | RAKMD0 | RAKDBS | RAKTE | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_KTCTL (m_vdp2_regs[0x0b4/2]) + #define STV_VDP2_RBUNK ((STV_VDP2_KTCTL & 0x6000) >> 13) + #define STV_VDP2_RBKLCE ((STV_VDP2_KTCTL & 0x1000) >> 12) + #define STV_VDP2_RBKMD ((STV_VDP2_KTCTL & 0x0c00) >> 10) + #define STV_VDP2_RBKDBS ((STV_VDP2_KTCTL & 0x0200) >> 9) + #define STV_VDP2_RBKTE ((STV_VDP2_KTCTL & 0x0100) >> 8) + #define STV_VDP2_RAUNK ((STV_VDP2_KTCTL & 0x0060) >> 5) + #define STV_VDP2_RAKLCE ((STV_VDP2_KTCTL & 0x0010) >> 4) + #define STV_VDP2_RAKMD ((STV_VDP2_KTCTL & 0x000c) >> 2) + #define STV_VDP2_RAKDBS ((STV_VDP2_KTCTL & 0x0002) >> 1) + #define STV_VDP2_RAKTE ((STV_VDP2_KTCTL & 0x0001) >> 0) + +/* 1800b6 - KTAOF - Coefficient Table Address Offset (Rotation Parameter A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | RBKTAOS2 | RBKTAOS1 | RBKTAOS0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | RAKTAOS2 | RAKTAOS1 | RAKTAOS0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_KTAOF (m_vdp2_regs[0x0b6/2]) + #define STV_VDP2_RBKTAOS ((STV_VDP2_KTAOF & 0x0700) >> 8) + #define STV_VDP2_RAKTAOS ((STV_VDP2_KTAOF & 0x0007) >> 0) + +/* 1800b8 - OVPNRA - Screen Over Pattern Name (Rotation Parameter A) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_OVPNRA (m_vdp2_regs[0x0b8/2]) + +/* 1800ba - Screen Over Pattern Name (Rotation Parameter B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_OVPNRB (m_vdp2_regs[0x0ba/2]) + +/* 1800bc - RPTAU - Rotation Parameter Table Address (Rotation Parameter A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | RPTA18 | RPTA17 | RPTA16 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_RPTAU (m_vdp2_regs[0x0bc/2] & 7) + +/* 1800be - RPTAL - Rotation Parameter Table Address (Rotation Parameter A,B) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | RPTA15 | RPTA14 | RPTA13 | RPTA12 | RPTA11 | RPTA10 | RPTA9 | RPTA8 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | RPTA7 | RPTA6 | RPTA5 | RPTA4 | RPTA3 | RPTA2 | RPTA1 | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_RPTAL (m_vdp2_regs[0x0be/2] & 0x0000ffff) + +/* 1800c0 - Window Position (W0, Horizontal Start Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPSX0 (m_vdp2_regs[0x0c0/2]) + + #define STV_VDP2_W0SX ((STV_VDP2_WPSX0 & 0x03ff) >> 0) + +/* 1800c2 - Window Position (W0, Vertical Start Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPSY0 (m_vdp2_regs[0x0c2/2]) + + #define STV_VDP2_W0SY ((STV_VDP2_WPSY0 & 0x07ff) >> 0) + +/* 1800c4 - Window Position (W0, Horizontal End Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPEX0 (m_vdp2_regs[0x0c4/2]) + + #define STV_VDP2_W0EX ((STV_VDP2_WPEX0 & 0x03ff) >> 0) + +/* 1800c6 - Window Position (W0, Vertical End Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPEY0 (m_vdp2_regs[0x0c6/2]) + + #define STV_VDP2_W0EY ((STV_VDP2_WPEY0 & 0x07ff) >> 0) + +/* 1800c8 - Window Position (W1, Horizontal Start Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPSX1 (m_vdp2_regs[0x0c8/2]) + + #define STV_VDP2_W1SX ((STV_VDP2_WPSX1 & 0x03ff) >> 0) + +/* 1800ca - Window Position (W1, Vertical Start Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPSY1 (m_vdp2_regs[0x0ca/2]) + + #define STV_VDP2_W1SY ((STV_VDP2_WPSY1 & 0x07ff) >> 0) + +/* 1800cc - Window Position (W1, Horizontal End Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPEX1 (m_vdp2_regs[0x0cc/2]) + + #define STV_VDP2_W1EX ((STV_VDP2_WPEX1 & 0x03ff) >> 0) + +/* 1800ce - Window Position (W1, Vertical End Point) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WPEY1 (m_vdp2_regs[0x0ce/2]) + + #define STV_VDP2_W1EY ((STV_VDP2_WPEY1 & 0x07ff) >> 0) + +/* 1800d0 - Window Control (NBG0, NBG1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WCTLA (m_vdp2_regs[0x0d0/2]) + #define STV_VDP2_N1LOG ((STV_VDP2_WCTLA & 0x8000) >> 15) + #define STV_VDP2_N1SWE ((STV_VDP2_WCTLA & 0x2000) >> 13) + #define STV_VDP2_N1SWA ((STV_VDP2_WCTLA & 0x1000) >> 12) + #define STV_VDP2_N1W1E ((STV_VDP2_WCTLA & 0x0800) >> 11) + #define STV_VDP2_N1W1A ((STV_VDP2_WCTLA & 0x0400) >> 10) + #define STV_VDP2_N1W0E ((STV_VDP2_WCTLA & 0x0200) >> 9) + #define STV_VDP2_N1W0A ((STV_VDP2_WCTLA & 0x0100) >> 8) + #define STV_VDP2_N0LOG ((STV_VDP2_WCTLA & 0x0080) >> 7) + #define STV_VDP2_N0SWE ((STV_VDP2_WCTLA & 0x0020) >> 5) + #define STV_VDP2_N0SWA ((STV_VDP2_WCTLA & 0x0010) >> 4) + #define STV_VDP2_N0W1E ((STV_VDP2_WCTLA & 0x0008) >> 3) + #define STV_VDP2_N0W1A ((STV_VDP2_WCTLA & 0x0004) >> 2) + #define STV_VDP2_N0W0E ((STV_VDP2_WCTLA & 0x0002) >> 1) + #define STV_VDP2_N0W0A ((STV_VDP2_WCTLA & 0x0001) >> 0) + +/* 1800d2 - Window Control (NBG2, NBG3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WCTLB (m_vdp2_regs[0x0d2/2]) + #define STV_VDP2_N3LOG ((STV_VDP2_WCTLB & 0x8000) >> 15) + #define STV_VDP2_N3SWE ((STV_VDP2_WCTLB & 0x2000) >> 13) + #define STV_VDP2_N3SWA ((STV_VDP2_WCTLB & 0x1000) >> 12) + #define STV_VDP2_N3W1E ((STV_VDP2_WCTLB & 0x0800) >> 11) + #define STV_VDP2_N3W1A ((STV_VDP2_WCTLB & 0x0400) >> 10) + #define STV_VDP2_N3W0E ((STV_VDP2_WCTLB & 0x0200) >> 9) + #define STV_VDP2_N3W0A ((STV_VDP2_WCTLB & 0x0100) >> 8) + #define STV_VDP2_N2LOG ((STV_VDP2_WCTLB & 0x0080) >> 7) + #define STV_VDP2_N2SWE ((STV_VDP2_WCTLB & 0x0020) >> 5) + #define STV_VDP2_N2SWA ((STV_VDP2_WCTLB & 0x0010) >> 4) + #define STV_VDP2_N2W1E ((STV_VDP2_WCTLB & 0x0008) >> 3) + #define STV_VDP2_N2W1A ((STV_VDP2_WCTLB & 0x0004) >> 2) + #define STV_VDP2_N2W0E ((STV_VDP2_WCTLB & 0x0002) >> 1) + #define STV_VDP2_N2W0A ((STV_VDP2_WCTLB & 0x0001) >> 0) + +/* 1800d4 - Window Control (RBG0, Sprite) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WCTLC (m_vdp2_regs[0x0d4/2]) + #define STV_VDP2_SPLOG ((STV_VDP2_WCTLC & 0x8000) >> 15) + #define STV_VDP2_SPSWE ((STV_VDP2_WCTLC & 0x2000) >> 13) + #define STV_VDP2_SPSWA ((STV_VDP2_WCTLC & 0x1000) >> 12) + #define STV_VDP2_SPW1E ((STV_VDP2_WCTLC & 0x0800) >> 11) + #define STV_VDP2_SPW1A ((STV_VDP2_WCTLC & 0x0400) >> 10) + #define STV_VDP2_SPW0E ((STV_VDP2_WCTLC & 0x0200) >> 9) + #define STV_VDP2_SPW0A ((STV_VDP2_WCTLC & 0x0100) >> 8) + #define STV_VDP2_R0LOG ((STV_VDP2_WCTLC & 0x0080) >> 7) + #define STV_VDP2_R0SWE ((STV_VDP2_WCTLC & 0x0020) >> 5) + #define STV_VDP2_R0SWA ((STV_VDP2_WCTLC & 0x0010) >> 4) + #define STV_VDP2_R0W1E ((STV_VDP2_WCTLC & 0x0008) >> 3) + #define STV_VDP2_R0W1A ((STV_VDP2_WCTLC & 0x0004) >> 2) + #define STV_VDP2_R0W0E ((STV_VDP2_WCTLC & 0x0002) >> 1) + #define STV_VDP2_R0W0A ((STV_VDP2_WCTLC & 0x0001) >> 0) + +/* 1800d6 - Window Control (Parameter Window, Colour Calc. Window) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_WCTLD (m_vdp2_regs[0x0d6/2]) + #define STV_VDP2_CCLOG ((STV_VDP2_WCTLD & 0x8000) >> 15) + #define STV_VDP2_CCSWE ((STV_VDP2_WCTLD & 0x2000) >> 13) + #define STV_VDP2_CCSWA ((STV_VDP2_WCTLD & 0x1000) >> 12) + #define STV_VDP2_CCW1E ((STV_VDP2_WCTLD & 0x0800) >> 11) + #define STV_VDP2_CCW1A ((STV_VDP2_WCTLD & 0x0400) >> 10) + #define STV_VDP2_CCW0E ((STV_VDP2_WCTLD & 0x0200) >> 9) + #define STV_VDP2_CCW0A ((STV_VDP2_WCTLD & 0x0100) >> 8) + #define STV_VDP2_RPLOG ((STV_VDP2_WCTLD & 0x0080) >> 7) + #define STV_VDP2_RPW1E ((STV_VDP2_WCTLD & 0x0008) >> 3) + #define STV_VDP2_RPW1A ((STV_VDP2_WCTLD & 0x0004) >> 2) + #define STV_VDP2_RPW0E ((STV_VDP2_WCTLD & 0x0002) >> 1) + #define STV_VDP2_RPW0A ((STV_VDP2_WCTLD & 0x0001) >> 0) + +/* 1800d8 - Line Window Table Address (W0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LWTA0U (m_vdp2_regs[0x0d8/2]) + + #define STV_VDP2_W0LWE ((STV_VDP2_LWTA0U & 0x8000) >> 15) + +/* 1800da - Line Window Table Address (W0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LWTA0L (m_vdp2_regs[0x0da/2]) + + /* bit 19 isn't used when VRAM = 4 Mbit */ + #define STV_VDP2_W0LWTA (((STV_VDP2_LWTA0U & 0x0007) << 16) | (STV_VDP2_LWTA0L & 0xfffe)) + + +/* 1800dc - Line Window Table Address (W1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LWTA1U (m_vdp2_regs[0x0dc/2]) + + #define STV_VDP2_W1LWE ((STV_VDP2_LWTA1U & 0x8000) >> 15) + + +/* 1800de - Line Window Table Address (W1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LWTA1L (m_vdp2_regs[0x0de/2]) + + /* bit 19 isn't used when VRAM = 4 Mbit */ + #define STV_VDP2_W1LWTA (((STV_VDP2_LWTA1U & 0x0007) << 16) | (STV_VDP2_LWTA1L & 0xfffe)) + + +/* 1800e0 - Sprite Control + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | SPCCCS1 | SPCCCS0 | -- | SPCCN2 | SPCCN1 | SPCCN0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | SPCLMD | SPWINEN | SPTYPE3 | SPTYPE2 | SPTYPE1 | SPTYPE0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SPCTL (m_vdp2_regs[0x0e0/2]) + #define STV_VDP2_SPCCCS ((STV_VDP2_SPCTL & 0x3000) >> 12) + #define STV_VDP2_SPCCN ((STV_VDP2_SPCTL & 0x700) >> 8) + #define STV_VDP2_SPCLMD ((STV_VDP2_SPCTL & 0x20) >> 5) + #define STV_VDP2_SPWINEN ((STV_VDP2_SPCTL & 0x10) >> 4) + #define STV_VDP2_SPTYPE (STV_VDP2_SPCTL & 0xf) + +/* 1800e2 - Shadow Control + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SDCTL (m_vdp2_regs[0x0e2/2]) + +/* 1800e4 - CRAOFA - Colour Ram Address Offset (NBG0 - NBG3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | N0CAOS2 | N3CAOS1 | N3CAOS0 | -- | N2CAOS2 | N2CAOS1 | N2CAOS0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | N1CAOS2 | N1CAOS1 | N1CAOS0 | -- | N0CAOS2 | N0CAOS1 | N0CAOS0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CRAOFA (m_vdp2_regs[0x0e4/2]) + + /* NxCAOS = */ + #define STV_VDP2_N0CAOS ((STV_VDP2_CRAOFA & 0x0007) >> 0) + #define STV_VDP2_N1CAOS ((STV_VDP2_CRAOFA & 0x0070) >> 4) + #define STV_VDP2_N2CAOS ((STV_VDP2_CRAOFA & 0x0700) >> 8) + #define STV_VDP2_N3CAOS ((STV_VDP2_CRAOFA & 0x7000) >> 12) + + +/* 1800e6 - Colour Ram Address Offset (RBG0, SPRITE) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_CRAOFB (m_vdp2_regs[0x0e6/2]) + #define STV_VDP2_R0CAOS ((STV_VDP2_CRAOFB & 0x0007) >> 0) + #define STV_VDP2_SPCAOS ((STV_VDP2_CRAOFB & 0x0070) >> 4) + +/* 1800e8 - LNCLEN - Line Colour Screen Enable + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | SPLCEN | R0LCEN | N3LCEN | N2LCEN | N1LCEN | N0LCEN | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_LNCLEN (m_vdp2_regs[0x0e8/2]) + #define STV_VDP2_SPLCEN ((STV_VDP2_LNCLEN & 0x0020) >> 5) + #define STV_VDP2_R0LCEN ((STV_VDP2_LNCLEN & 0x0010) >> 4) + #define STV_VDP2_N3LCEN ((STV_VDP2_LNCLEN & 0x0008) >> 3) + #define STV_VDP2_N2LCEN ((STV_VDP2_LNCLEN & 0x0004) >> 2) + #define STV_VDP2_N1LCEN ((STV_VDP2_LNCLEN & 0x0002) >> 1) + #define STV_VDP2_N0LCEN ((STV_VDP2_LNCLEN & 0x0001) >> 0) + +/* 1800ea - Special Priority Mode + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SFPRMD (m_vdp2_regs[0x0ea/2]) + + +/* 1800ec - Colour Calculation Control + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | BOKEN | BOKN2 | BOKN1 | BOKN0 | -- | EXCCEN | CCRTMD | CCMD | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | SPCCEN | LCCCEN | R0CCEN | N3CCEN | N2CCEN | N1CCEN | N0CCEN | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCCR (m_vdp2_regs[0x0ec/2]) + #define STV_VDP2_CCMD ((STV_VDP2_CCCR & 0x100) >> 8) + #define STV_VDP2_SPCCEN ((STV_VDP2_CCCR & 0x40) >> 6) + #define STV_VDP2_LCCCEN ((STV_VDP2_CCCR & 0x20) >> 5) + #define STV_VDP2_R0CCEN ((STV_VDP2_CCCR & 0x10) >> 4) + #define STV_VDP2_N3CCEN ((STV_VDP2_CCCR & 0x8) >> 3) + #define STV_VDP2_N2CCEN ((STV_VDP2_CCCR & 0x4) >> 2) + #define STV_VDP2_N1CCEN ((STV_VDP2_CCCR & 0x2) >> 1) + #define STV_VDP2_N0CCEN ((STV_VDP2_CCCR & 0x1) >> 0) + + +/* 1800ee - Special Colour Calculation Mode + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_SFCCMD (m_vdp2_regs[0x0ee/2]) + +/* 1800f0 - Priority Number (Sprite 0,1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | S1PRIN2 | S1PRIN1 | S1PRIN0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | S0PRIN2 | S0PRIN1 | S0PRIN0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PRISA (m_vdp2_regs[0x0f0/2]) + #define STV_VDP2_S1PRIN ((STV_VDP2_PRISA & 0x0700) >> 8) + #define STV_VDP2_S0PRIN ((STV_VDP2_PRISA & 0x0007) >> 0) + +/* 1800f2 - Priority Number (Sprite 2,3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | S3PRIN2 | S3PRIN1 | S3PRIN0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | S2PRIN2 | S2PRIN1 | S2PRIN0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PRISB (m_vdp2_regs[0x0f2/2]) + #define STV_VDP2_S3PRIN ((STV_VDP2_PRISB & 0x0700) >> 8) + #define STV_VDP2_S2PRIN ((STV_VDP2_PRISB & 0x0007) >> 0) + +/* 1800f4 - Priority Number (Sprite 4,5) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | S5PRIN2 | S5PRIN1 | S5PRIN0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | S4PRIN2 | S4PRIN1 | S4PRIN0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PRISC (m_vdp2_regs[0x0f4/2]) + #define STV_VDP2_S5PRIN ((STV_VDP2_PRISC & 0x0700) >> 8) + #define STV_VDP2_S4PRIN ((STV_VDP2_PRISC & 0x0007) >> 0) + +/* 1800f6 - Priority Number (Sprite 6,7) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | S7PRIN2 | S7PRIN1 | S7PRIN0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | S6PRIN2 | S6PRIN1 | S6PRIN0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PRISD (m_vdp2_regs[0x0f6/2]) + #define STV_VDP2_S7PRIN ((STV_VDP2_PRISD & 0x0700) >> 8) + #define STV_VDP2_S6PRIN ((STV_VDP2_PRISD & 0x0007) >> 0) + + +/* 1800f8 - PRINA - Priority Number (NBG 0,1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PRINA (m_vdp2_regs[0x0f8/2]) + + #define STV_VDP2_N1PRIN ((STV_VDP2_PRINA & 0x0700) >> 8) + #define STV_VDP2_N0PRIN ((STV_VDP2_PRINA & 0x0007) >> 0) + +/* 1800fa - PRINB - Priority Number (NBG 2,3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_PRINB (m_vdp2_regs[0x0fa/2]) + + #define STV_VDP2_N3PRIN ((STV_VDP2_PRINB & 0x0700) >> 8) + #define STV_VDP2_N2PRIN ((STV_VDP2_PRINB & 0x0007) >> 0) + +/* 1800fc - Priority Number (RBG0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_PRIR (m_vdp2_regs[0x0fc/2]) + + #define STV_VDP2_R0PRIN ((STV_VDP2_PRIR & 0x0007) >> 0) + +/* 1800fe - Reserved + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + +/* 180100 - Colour Calculation Ratio (Sprite 0,1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | S1CCRT4 | S1CCRT3 | S1CCRT2 | S1CCRT1 | S1CCRT0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | S0CCRT4 | S0CCRT3 | S0CCRT2 | S0CCRT1 | S0CCRT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRSA (m_vdp2_regs[0x100/2]) + #define STV_VDP2_S1CCRT ((STV_VDP2_CCRSA & 0x1f00) >> 8) + #define STV_VDP2_S0CCRT ((STV_VDP2_CCRSA & 0x001f) >> 0) + +/* 180102 - Colour Calculation Ratio (Sprite 2,3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | S3CCRT4 | S3CCRT3 | S3CCRT2 | S3CCRT1 | S3CCRT0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | S2CCRT4 | S2CCRT3 | S2CCRT2 | S2CCRT1 | S2CCRT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRSB (m_vdp2_regs[0x102/2]) + #define STV_VDP2_S3CCRT ((STV_VDP2_CCRSB & 0x1f00) >> 8) + #define STV_VDP2_S2CCRT ((STV_VDP2_CCRSB & 0x001f) >> 0) + +/* 180104 - Colour Calculation Ratio (Sprite 4,5) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | S5CCRT4 | S5CCRT3 | S5CCRT2 | S5CCRT1 | S5CCRT0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | S4CCRT4 | S4CCRT3 | S4CCRT2 | S4CCRT1 | S4CCRT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRSC (m_vdp2_regs[0x104/2]) + #define STV_VDP2_S5CCRT ((STV_VDP2_CCRSC & 0x1f00) >> 8) + #define STV_VDP2_S4CCRT ((STV_VDP2_CCRSC & 0x001f) >> 0) + +/* 180106 - Colour Calculation Ratio (Sprite 6,7) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | S7CCRT4 | S7CCRT3 | S7CCRT2 | S7CCRT1 | S7CCRT0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | S6CCRT4 | S6CCRT3 | S6CCRT2 | S6CCRT1 | S6CCRT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRSD (m_vdp2_regs[0x106/2]) + #define STV_VDP2_S7CCRT ((STV_VDP2_CCRSD & 0x1f00) >> 8) + #define STV_VDP2_S6CCRT ((STV_VDP2_CCRSD & 0x001f) >> 0) + +/* 180108 - Colour Calculation Ratio (NBG 0,1) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | N1CCRT4 | N1CCRT3 | N1CCRT2 | N1CCRT1 | N1CCRT0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | N0CCRT4 | N0CCRT3 | N0CCRT2 | N0CCRT1 | N0CCRT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRNA (m_vdp2_regs[0x108/2]) + #define STV_VDP2_N1CCRT ((STV_VDP2_CCRNA & 0x1f00) >> 8) + #define STV_VDP2_N0CCRT (STV_VDP2_CCRNA & 0x1f) + +/* 18010a - Colour Calculation Ratio (NBG 2,3) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | N3CCRT4 | N3CCRT3 | N3CCRT2 | N3CCRT1 | N3CCRT0 | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | N2CCRT4 | N2CCRT3 | N2CCRT2 | N2CCRT1 | N2CCRT0 | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRNB (m_vdp2_regs[0x10a/2]) + #define STV_VDP2_N3CCRT ((STV_VDP2_CCRNB & 0x1f00) >> 8) + #define STV_VDP2_N2CCRT (STV_VDP2_CCRNB & 0x1f) + +/* 18010c - Colour Calculation Ratio (RBG 0) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRR (m_vdp2_regs[0x10c/2]) + #define STV_VDP2_R0CCRT (STV_VDP2_CCRR & 0x1f) + +/* 18010e - Colour Calculation Ratio (Line Colour Screen, Back Colour Screen) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CCRLB (m_vdp2_regs[0x10e/2]) + + +/* 180110 - Colour Offset Enable + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CLOFEN (m_vdp2_regs[0x110/2]) + #define STV_VDP2_N0COEN ((STV_VDP2_CLOFEN & 0x01) >> 0) + #define STV_VDP2_N1COEN ((STV_VDP2_CLOFEN & 0x02) >> 1) + #define STV_VDP2_N2COEN ((STV_VDP2_CLOFEN & 0x04) >> 2) + #define STV_VDP2_N3COEN ((STV_VDP2_CLOFEN & 0x08) >> 3) + #define STV_VDP2_R0COEN ((STV_VDP2_CLOFEN & 0x10) >> 4) + #define STV_VDP2_BKCOEN ((STV_VDP2_CLOFEN & 0x20) >> 5) + #define STV_VDP2_SPCOEN ((STV_VDP2_CLOFEN & 0x40) >> 6) + +/* 180112 - Colour Offset Select + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_CLOFSL (m_vdp2_regs[0x112/2]) + #define STV_VDP2_N0COSL ((STV_VDP2_CLOFSL & 0x01) >> 0) + #define STV_VDP2_N1COSL ((STV_VDP2_CLOFSL & 0x02) >> 1) + #define STV_VDP2_N2COSL ((STV_VDP2_CLOFSL & 0x04) >> 2) + #define STV_VDP2_N3COSL ((STV_VDP2_CLOFSL & 0x08) >> 3) + #define STV_VDP2_R0COSL ((STV_VDP2_CLOFSL & 0x10) >> 4) + #define STV_VDP2_BKCOSL ((STV_VDP2_CLOFSL & 0x20) >> 5) + #define STV_VDP2_SPCOSL ((STV_VDP2_CLOFSL & 0x40) >> 6) + +/* 180114 - Colour Offset A (Red) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_COAR (m_vdp2_regs[0x114/2]) + +/* 180116 - Colour Offset A (Green) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_COAG (m_vdp2_regs[0x116/2]) + +/* 180118 - Colour Offset A (Blue) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + + #define STV_VDP2_COAB (m_vdp2_regs[0x118/2]) + +/* 18011a - Colour Offset B (Red) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_COBR (m_vdp2_regs[0x11a/2]) + +/* 18011c - Colour Offset B (Green) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_COBG (m_vdp2_regs[0x11c/2]) + +/* 18011e - Colour Offset B (Blue) + bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\ + | -- | -- | -- | -- | -- | -- | -- | -- | + |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----| + | -- | -- | -- | -- | -- | -- | -- | -- | + \----------|----------|----------|----------|----------|----------|----------|---------*/ + #define STV_VDP2_COBB (m_vdp2_regs[0x11e/2]) + + +#define STV_VDP2_RBG_ROTATION_PARAMETER_A 1 +#define STV_VDP2_RBG_ROTATION_PARAMETER_B 2 + + +#define mul_fixed32( a, b ) mul_32x32_shift( a, b, 16 ) + +void saturn_state::stv_vdp2_fill_rotation_parameter_table( uint8_t rot_parameter ) +{ + uint32_t address; + + address = (((STV_VDP2_RPTAU << 16) | STV_VDP2_RPTAL) << 1); + if ( rot_parameter == 1 ) + { + address &= ~0x00000080; + } + else if ( rot_parameter == 2 ) + { + address |= 0x00000080; + } + + stv_current_rotation_parameter_table.xst = (m_vdp2_vram[address/4] & 0x1fffffc0) | ((m_vdp2_vram[address/4] & 0x10000000) ? 0xe0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.yst = (m_vdp2_vram[address/4 + 1] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 1] & 0x10000000) ? 0xe0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.zst = (m_vdp2_vram[address/4 + 2] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 2] & 0x10000000) ? 0xe0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.dxst = (m_vdp2_vram[address/4 + 3] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 3] & 0x00040000) ? 0xfff80000 : 0x00000000 ); + stv_current_rotation_parameter_table.dyst = (m_vdp2_vram[address/4 + 4] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 4] & 0x00040000) ? 0xfff80000 : 0x00000000 ); + stv_current_rotation_parameter_table.dx = (m_vdp2_vram[address/4 + 5] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 5] & 0x00040000) ? 0xfff80000 : 0x00000000 ); + stv_current_rotation_parameter_table.dy = (m_vdp2_vram[address/4 + 6] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 6] & 0x00040000) ? 0xfff80000 : 0x00000000 ); + stv_current_rotation_parameter_table.A = (m_vdp2_vram[address/4 + 7] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 7] & 0x00080000) ? 0xfff00000 : 0x00000000 ); + stv_current_rotation_parameter_table.B = (m_vdp2_vram[address/4 + 8] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 8] & 0x00080000) ? 0xfff00000 : 0x00000000 ); + stv_current_rotation_parameter_table.C = (m_vdp2_vram[address/4 + 9] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 9] & 0x00080000) ? 0xfff00000 : 0x00000000 ); + stv_current_rotation_parameter_table.D = (m_vdp2_vram[address/4 + 10] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 10] & 0x00080000) ? 0xfff00000 : 0x00000000 ); + stv_current_rotation_parameter_table.E = (m_vdp2_vram[address/4 + 11] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 11] & 0x00080000) ? 0xfff00000 : 0x00000000 ); + stv_current_rotation_parameter_table.F = (m_vdp2_vram[address/4 + 12] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 12] & 0x00080000) ? 0xfff00000 : 0x00000000 ); + stv_current_rotation_parameter_table.px = (m_vdp2_vram[address/4 + 13] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 13] & 0x30000000) ? 0xc0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.py = (m_vdp2_vram[address/4 + 13] & 0x00003fff) << 16; + if ( stv_current_rotation_parameter_table.py & 0x20000000 ) stv_current_rotation_parameter_table.py |= 0xc0000000; + stv_current_rotation_parameter_table.pz = (m_vdp2_vram[address/4 + 14] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 14] & 0x20000000) ? 0xc0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.cx = (m_vdp2_vram[address/4 + 15] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 15] & 0x20000000) ? 0xc0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.cy = (m_vdp2_vram[address/4 + 15] & 0x00003fff) << 16; + if ( stv_current_rotation_parameter_table.cy & 0x20000000 ) stv_current_rotation_parameter_table.cy |= 0xc0000000; + stv_current_rotation_parameter_table.cz = (m_vdp2_vram[address/4 + 16] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 16] & 0x20000000) ? 0xc0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.mx = (m_vdp2_vram[address/4 + 17] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 17] & 0x20000000) ? 0xc0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.my = (m_vdp2_vram[address/4 + 18] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 18] & 0x20000000) ? 0xc0000000 : 0x00000000 ); + stv_current_rotation_parameter_table.kx = (m_vdp2_vram[address/4 + 19] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 19] & 0x00800000) ? 0xff000000 : 0x00000000 ); + stv_current_rotation_parameter_table.ky = (m_vdp2_vram[address/4 + 20] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 20] & 0x00800000) ? 0xff000000 : 0x00000000 ); + stv_current_rotation_parameter_table.kast = (m_vdp2_vram[address/4 + 21] & 0xffffffc0); + stv_current_rotation_parameter_table.dkast= (m_vdp2_vram[address/4 + 22] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 22] & 0x02000000) ? 0xfc000000 : 0x00000000 ); + stv_current_rotation_parameter_table.dkax = (m_vdp2_vram[address/4 + 23] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 23] & 0x02000000) ? 0xfc000000 : 0x00000000 ); + + // check rotation parameter read control, override if specific bits are disabled + // (Batman Forever The Riddler stage relies on this) + switch(rot_parameter) + { + case 1: + // TODO: disable read control if these undocumented bits are on (Radiant Silvergun Xiga final boss) + if(!STV_VDP2_RAUNK) + { + if(!STV_VDP2_RAXSTRE) + stv_current_rotation_parameter_table.xst = 0; + + if(!STV_VDP2_RAYSTRE) + stv_current_rotation_parameter_table.yst = 0; + + if(!STV_VDP2_RAKASTRE) + stv_current_rotation_parameter_table.dkax = 0; + } + break; + case 2: + // same as above + if(!STV_VDP2_RBUNK) + { + if(!STV_VDP2_RBXSTRE) + stv_current_rotation_parameter_table.xst = 0; + + if(!STV_VDP2_RBYSTRE) + stv_current_rotation_parameter_table.yst = 0; + + if(!STV_VDP2_RBKASTRE) + stv_current_rotation_parameter_table.dkax = 0; + } + break; + } + +#define RP stv_current_rotation_parameter_table + + if(LOG_ROZ == 1) logerror( "Rotation parameter table (%d)\n", rot_parameter ); + if(LOG_ROZ == 1) logerror( "xst = %x, yst = %x, zst = %x\n", RP.xst, RP.yst, RP.zst ); + if(LOG_ROZ == 1) logerror( "dxst = %x, dyst = %x\n", RP.dxst, RP.dyst ); + if(LOG_ROZ == 1) logerror( "dx = %x, dy = %x\n", RP.dx, RP.dy ); + if(LOG_ROZ == 1) logerror( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x\n", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); + if(LOG_ROZ == 1) logerror( "px = %x, py = %x, pz = %x\n", RP.px, RP.py, RP.pz ); + if(LOG_ROZ == 1) logerror( "cx = %x, cy = %x, cz = %x\n", RP.cx, RP.cy, RP.cz ); + if(LOG_ROZ == 1) logerror( "mx = %x, my = %x\n", RP.mx, RP.my ); + if(LOG_ROZ == 1) logerror( "kx = %x, ky = %x\n", RP.kx, RP.ky ); + if(LOG_ROZ == 1) logerror( "kast = %x, dkast = %x, dkax = %x\n", RP.kast, RP.dkast, RP.dkax ); + + /*Attempt to show on screen the rotation table*/ + #if 0 + if(LOG_ROZ == 2) + { + if(machine().input().code_pressed_once(JOYCODE_Y_UP_SWITCH)) + m_vdpdebug_roz++; + + if(machine().input().code_pressed_once(JOYCODE_Y_DOWN_SWITCH)) + m_vdpdebug_roz--; + + if(m_vdpdebug_roz > 10) + m_vdpdebug_roz = 10; + + switch(m_vdpdebug_roz) + { + case 0: popmessage( "Rotation parameter Table (%d)", rot_parameter ); break; + case 1: popmessage( "xst = %x, yst = %x, zst = %x", RP.xst, RP.yst, RP.zst ); break; + case 2: popmessage( "dxst = %x, dyst = %x", RP.dxst, RP.dyst ); break; + case 3: popmessage( "dx = %x, dy = %x", RP.dx, RP.dy ); break; + case 4: popmessage( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); break; + case 5: popmessage( "px = %x, py = %x, pz = %x", RP.px, RP.py, RP.pz ); break; + case 6: popmessage( "cx = %x, cy = %x, cz = %x", RP.cx, RP.cy, RP.cz ); break; + case 7: popmessage( "mx = %x, my = %x", RP.mx, RP.my ); break; + case 8: popmessage( "kx = %x, ky = %x", RP.kx, RP.ky ); break; + case 9: popmessage( "kast = %x, dkast = %x, dkax = %x", RP.kast, RP.dkast, RP.dkax ); break; + case 10: break; + } + } + #endif +} + +/* check if RGB layer has rotation applied */ +uint8_t saturn_state::stv_vdp2_is_rotation_applied(void) +{ +#define _FIXED_1 (0x00010000) +#define _FIXED_0 (0x00000000) + + if ( RP.A == _FIXED_1 && + RP.B == _FIXED_0 && + RP.C == _FIXED_0 && + RP.D == _FIXED_0 && + RP.E == _FIXED_1 && + RP.F == _FIXED_0 && + RP.dxst == _FIXED_0 && + RP.dyst == _FIXED_1 && + RP.dx == _FIXED_1 && + RP.dy == _FIXED_0 && + RP.kx == _FIXED_1 && + RP.ky == _FIXED_1 && + STV_VDP2_RPMD < 2) // disable optimizations if roz mode is 2 or 3 + { + return 0; + } + else + { + return 1; + } +} + +uint8_t saturn_state::stv_vdp2_are_map_registers_equal(void) +{ + int i; + + for ( i = 1; i < stv2_current_tilemap.map_count; i++ ) + { + if ( stv2_current_tilemap.map_offset[i] != stv2_current_tilemap.map_offset[0] ) + { + return 0; + } + } + return 1; +} + +void saturn_state::stv_vdp2_check_fade_control_for_layer( void ) +{ + if ( stv2_current_tilemap.fade_control & 1 ) + { + if ( stv2_current_tilemap.fade_control & 2 ) + { + if ((STV_VDP2_COBR & 0x1ff) == 0 && + (STV_VDP2_COBG & 0x1ff) == 0 && + (STV_VDP2_COBB & 0x1ff) == 0 ) + { + stv2_current_tilemap.fade_control = 0; + } + } + else + { + if ((STV_VDP2_COAR & 0x1ff) == 0 && + (STV_VDP2_COAG & 0x1ff) == 0 && + (STV_VDP2_COAB & 0x1ff) == 0 ) + { + stv2_current_tilemap.fade_control = 0; + } + } + } +} + +#define STV_VDP2_CP_NBG0_PNMDR 0x0 +#define STV_VDP2_CP_NBG1_PNMDR 0x1 +#define STV_VDP2_CP_NBG2_PNMDR 0x2 +#define STV_VDP2_CP_NBG3_PNMDR 0x3 +#define STV_VDP2_CP_NBG0_CPDR 0x4 +#define STV_VDP2_CP_NBG1_CPDR 0x5 +#define STV_VDP2_CP_NBG2_CPDR 0x6 +#define STV_VDP2_CP_NBG3_CPDR 0x7 + +uint8_t saturn_state::stv_vdp2_check_vram_cycle_pattern_registers( uint8_t access_command_pnmdr, uint8_t access_command_cpdr, uint8_t bitmap_enable ) +{ + int i; + uint8_t access_command_ok = 0; + uint16_t cp_regs[8]; + cp_regs[0] = STV_VDP2_CYCA0L; + cp_regs[1] = STV_VDP2_CYCA0U; + cp_regs[2] = STV_VDP2_CYCA1L; + cp_regs[3] = STV_VDP2_CYCA1U; + cp_regs[4] = STV_VDP2_CYCA2L; + cp_regs[5] = STV_VDP2_CYCA2U; + cp_regs[6] = STV_VDP2_CYCA3L; + cp_regs[7] = STV_VDP2_CYCA3U; + + if ( bitmap_enable ) access_command_ok = 1; + + for ( i = 0; i < 8; i++ ) + { + if ( ((cp_regs[i] >> 12) & 0xf) == access_command_pnmdr ) + { + access_command_ok |= 1; + } + if ( ((cp_regs[i] >> 12) & 0xf) == access_command_cpdr ) + { + access_command_ok |= 2; + } + if ( ((cp_regs[i] >> 8) & 0xf) == access_command_pnmdr ) + { + access_command_ok |= 1; + } + if ( ((cp_regs[i] >> 8) & 0xf) == access_command_cpdr ) + { + access_command_ok |= 2; + } + if ( ((cp_regs[i] >> 4) & 0xf) == access_command_pnmdr ) + { + access_command_ok |= 1; + } + if ( ((cp_regs[i] >> 4) & 0xf) == access_command_cpdr ) + { + access_command_ok |= 2; + } + if ( ((cp_regs[i] >> 0) & 0xf) == access_command_pnmdr ) + { + access_command_ok |= 1; + } + if ( ((cp_regs[i] >> 0) & 0xf) == access_command_cpdr ) + { + access_command_ok |= 2; + } + } + return access_command_ok == 3 ? 1 : 0; +} + + +void saturn_state::stv_vdp2_compute_color_offset( int *r, int *g, int *b, int cor ) +{ + if ( cor == 0 ) + { + *r = (STV_VDP2_COAR & 0x100) ? (*r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + *r); + *g = (STV_VDP2_COAG & 0x100) ? (*g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + *g); + *b = (STV_VDP2_COAB & 0x100) ? (*b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + *b); + } + else + { + *r = (STV_VDP2_COBR & 0x100) ? (*r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + *r); + *g = (STV_VDP2_COBG & 0x100) ? (*g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + *g); + *b = (STV_VDP2_COBB & 0x100) ? (*b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + *b); + } + if(*r < 0) { *r = 0; } + if(*r > 0xff) { *r = 0xff; } + if(*g < 0) { *g = 0; } + if(*g > 0xff) { *g = 0xff; } + if(*b < 0) { *b = 0; } + if(*b > 0xff) { *b = 0xff; } +} + +void saturn_state::stv_vdp2_compute_color_offset_UINT32(rgb_t *rgb, int cor) +{ + int _r = rgb->r(); + int _g = rgb->g(); + int _b = rgb->b(); + if ( cor == 0 ) + { + _r = (STV_VDP2_COAR & 0x100) ? (_r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + _r); + _g = (STV_VDP2_COAG & 0x100) ? (_g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + _g); + _b = (STV_VDP2_COAB & 0x100) ? (_b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + _b); + } + else + { + _r = (STV_VDP2_COBR & 0x100) ? (_r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + _r); + _g = (STV_VDP2_COBG & 0x100) ? (_g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + _g); + _b = (STV_VDP2_COBB & 0x100) ? (_b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + _b); + } + if(_r < 0) { _r = 0; } + if(_r > 0xff) { _r = 0xff; } + if(_g < 0) { _g = 0; } + if(_g > 0xff) { _g = 0xff; } + if(_b < 0) { _b = 0; } + if(_b > 0xff) { _b = 0xff; } + + *rgb = rgb_t(_r, _g, _b); +} + +void saturn_state::stv_vdp2_drawgfxzoom( + bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, + uint32_t code,uint32_t color,int flipx,int flipy,int sx,int sy, + int transparency,int scalex, int scaley, + int sprite_screen_width, int sprite_screen_height, int alpha) +{ + rectangle myclip; + + if (!scalex || !scaley) return; + + if (gfx->has_pen_usage() && !(transparency & STV_TRANSPARENCY_NONE)) + { + int transmask; + + transmask = 1 << (0 & 0xff); + + if ((gfx->pen_usage(code) & ~transmask) == 0) + /* character is totally transparent, no need to draw */ + return; + else if ((gfx->pen_usage(code) & transmask) == 0) + /* character is totally opaque, can disable transparency */ + transparency |= STV_TRANSPARENCY_NONE; + } + + /* + scalex and scaley are 16.16 fixed point numbers + 1<<15 : shrink to 50% + 1<<16 : uniform scale + 1<<17 : double to 200% + */ + + + /* KW 991012 -- Added code to force clip to bitmap boundary */ + myclip = clip; + myclip &= dest_bmp.cliprect(); + + if( gfx ) + { + const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); + const uint8_t *source_base = gfx->get_data(code % gfx->elements()); + + //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16; + //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16; + + if (sprite_screen_width && sprite_screen_height) + { + /* compute sprite increment per screen pixel */ + //int dx = (gfx->width()<<16)/sprite_screen_width; + //int dy = (gfx->height()<<16)/sprite_screen_height; + int dx = stv2_current_tilemap.incx; + int dy = stv2_current_tilemap.incy; + + int ex = sx+sprite_screen_width; + int ey = sy+sprite_screen_height; + + int x_index_base; + int y_index; + + if( flipx ) + { + x_index_base = (sprite_screen_width-1)*dx; + dx = -dx; + } + else + { + x_index_base = 0; + } + + if( flipy ) + { + y_index = (sprite_screen_height-1)*dy; + dy = -dy; + } + else + { + y_index = 0; + } + + if( sx < myclip.left()) + { /* clip left */ + int pixels = myclip.left()-sx; + sx += pixels; + x_index_base += pixels*dx; + } + if( sy < myclip.top() ) + { /* clip top */ + int pixels = myclip.top()-sy; + sy += pixels; + y_index += pixels*dy; + } + /* NS 980211 - fixed incorrect clipping */ + if( ex > myclip.right()+1 ) + { /* clip right */ + int pixels = ex-myclip.right()-1; + ex -= pixels; + } + if( ey > myclip.bottom()+1 ) + { /* clip bottom */ + int pixels = ey-myclip.bottom()-1; + ey -= pixels; + } + + if( ex>sx ) + { /* skip if inner loop doesn't draw anything */ + int y; + + /* case : STV_TRANSPARENCY_ALPHA */ + if (transparency & STV_TRANSPARENCY_ALPHA) + { + for( y=sy; y>16) * gfx->rowbytes(); + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16]; + if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) + dest[x] = alpha_blend_r32(dest[x], pal[c], alpha); + } + x_index += dx; + } + + y_index += dy; + } + } /* case : STV_TRANSPARENCY_ADD_BLEND */ + else if (transparency & STV_TRANSPARENCY_ADD_BLEND) + { + for( y=sy; y>16) * gfx->rowbytes(); + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16]; + if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) + dest[x] = add_blend_r32(dest[x],pal[c]); + } + x_index += dx; + } + + y_index += dy; + } + } /* case : STV_TRANSPARENCY_PEN */ + else + { + for( y=sy; y>16) * gfx->rowbytes(); + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16]; + if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) + dest[x] = pal[c]; + } + x_index += dx; + } + + y_index += dy; + } + } + } + } + } +} + +void saturn_state::stv_vdp2_drawgfxzoom_rgb555( + bitmap_rgb32 &dest_bmp,const rectangle &clip, + uint32_t code,uint32_t color,int flipx,int flipy,int sx,int sy, + int transparency,int scalex, int scaley, + int sprite_screen_width, int sprite_screen_height, int alpha) +{ + rectangle myclip; + uint8_t* gfxdata; + + gfxdata = m_vdp2.gfx_decode.get() + code * 0x20; + + if(stv2_current_tilemap.window_control.enabled[0] || + stv2_current_tilemap.window_control.enabled[1]) + popmessage("Window Enabled for RGB555 Zoom"); + + if (!scalex || !scaley) return; + + #if 0 + if (gfx->has_pen_usage() && !(transparency & STV_TRANSPARENCY_NONE)) + { + int transmask = 0; + + transmask = 1 << (0 & 0xff); + + if ((gfx->pen_usage(code) & ~transmask) == 0) + /* character is totally transparent, no need to draw */ + return; + else if ((gfx->pen_usage(code) & transmask) == 0) + /* character is totally opaque, can disable transparency */ + transparency |= STV_TRANSPARENCY_NONE; + } + #endif + + /* + scalex and scaley are 16.16 fixed point numbers + 1<<15 : shrink to 50% + 1<<16 : uniform scale + 1<<17 : double to 200% + */ + + + /* KW 991012 -- Added code to force clip to bitmap boundary */ + myclip = clip; + myclip &= dest_bmp.cliprect(); + +// if( gfx ) + { +// const uint8_t *source_base = gfx->get_data(code % gfx->elements()); + + //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16; + //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16; + + if (sprite_screen_width && sprite_screen_height) + { + /* compute sprite increment per screen pixel */ + //int dx = (gfx->width()<<16)/sprite_screen_width; + //int dy = (gfx->height()<<16)/sprite_screen_height; + int dx = stv2_current_tilemap.incx; + int dy = stv2_current_tilemap.incy; + + int ex = sx+sprite_screen_width; + int ey = sy+sprite_screen_height; + + int x_index_base; + int y_index; + + if( flipx ) + { + x_index_base = (sprite_screen_width-1)*dx; + dx = -dx; + } + else + { + x_index_base = 0; + } + + if( flipy ) + { + y_index = (sprite_screen_height-1)*dy; + dy = -dy; + } + else + { + y_index = 0; + } + + if( sx < myclip.left()) + { /* clip left */ + int pixels = myclip.left()-sx; + sx += pixels; + x_index_base += pixels*dx; + } + if( sy < myclip.top() ) + { /* clip top */ + int pixels = myclip.top()-sy; + sy += pixels; + y_index += pixels*dy; + } + /* NS 980211 - fixed incorrect clipping */ + if( ex > myclip.right()+1 ) + { /* clip right */ + int pixels = ex-myclip.right()-1; + ex -= pixels; + } + if( ey > myclip.bottom()+1 ) + { /* clip bottom */ + int pixels = ey-myclip.bottom()-1; + ey -= pixels; + } + + if( ex>sx ) + { /* skip if inner loop doesn't draw anything */ + int y; + + /* case : STV_TRANSPARENCY_ALPHA */ + if (transparency & STV_TRANSPARENCY_ALPHA) + { + for( y=sy; y>16)*16; + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16)*2] << 8) | source[(x_index>>16)*2+1]; + int b = pal5bit((data & 0x7c00) >> 10); + int g = pal5bit((data & 0x03e0) >> 5); + int r = pal5bit( data & 0x001f); + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000)) + dest[x] = alpha_blend_r32(dest[x], rgb_t(r, g, b), alpha); + + x_index += dx; + } + + y_index += dy; + } + } /* case : STV_TRANSPARENCY_ADD_BLEND */ + else if (transparency & STV_TRANSPARENCY_ADD_BLEND) + { + for( y=sy; y>16)*16; + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16]<<0)|(source[(x_index*2+1)>>16]<<8); + int b = pal5bit((data & 0x7c00) >> 10); + int g = pal5bit((data & 0x03e0) >> 5); + int r = pal5bit( data & 0x001f); + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000)) + dest[x] = add_blend_r32(dest[x], rgb_t(r, g, b)); + + x_index += dx; + } + + y_index += dy; + } + } /* case : STV_TRANSPARENCY_PEN */ + else + { + for( y=sy; y>16)*16; + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16)*2] << 8) | source[(x_index>>16)*2+1]; + int b = pal5bit((data & 0x7c00) >> 10); + int g = pal5bit((data & 0x03e0) >> 5); + int r = pal5bit( data & 0x001f); + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if ((transparency & STV_TRANSPARENCY_NONE) || (data & 0x8000)) + dest[x] = rgb_t(r, g, b); + + x_index += dx; + } + + y_index += dy; + } + } + } + } + } + +} + + +void saturn_state::stv_vdp2_drawgfx_rgb555( bitmap_rgb32 &dest_bmp, const rectangle &clip, uint32_t code, int flipx, int flipy, int sx, int sy, int transparency, int alpha) +{ + rectangle myclip; + uint8_t* gfxdata; + int sprite_screen_width, sprite_screen_height; + + gfxdata = m_vdp2.gfx_decode.get() + code * 0x20; + sprite_screen_width = sprite_screen_height = 8; + + if(stv2_current_tilemap.window_control.enabled[0] || + stv2_current_tilemap.window_control.enabled[1]) + popmessage("Window Enabled for RGB555 tiles"); + + /* KW 991012 -- Added code to force clip to bitmap boundary */ + myclip = clip; + myclip &= dest_bmp.cliprect(); + + { + int dx = stv2_current_tilemap.incx; + int dy = stv2_current_tilemap.incy; + + int ex = sx+sprite_screen_width; + int ey = sy+sprite_screen_height; + + int x_index_base; + int y_index; + + if( flipx ) + { + x_index_base = (sprite_screen_width-1)*dx; + dx = -dx; + } + else + { + x_index_base = 0; + } + + if( flipy ) + { + y_index = (sprite_screen_height-1)*dy; + dy = -dy; + } + else + { + y_index = 0; + } + + if( sx < myclip.left()) + { /* clip left */ + int pixels = myclip.left()-sx; + sx += pixels; + x_index_base += pixels*dx; + } + if( sy < myclip.top() ) + { /* clip top */ + int pixels = myclip.top()-sy; + sy += pixels; + y_index += pixels*dy; + } + /* NS 980211 - fixed incorrect clipping */ + if( ex > myclip.right()+1 ) + { /* clip right */ + int pixels = ex-myclip.right()-1; + ex -= pixels; + } + if( ey > myclip.bottom()+1 ) + { /* clip bottom */ + int pixels = ey-myclip.bottom()-1; + ey -= pixels; + } + + if( ex>sx ) + { /* skip if inner loop doesn't draw anything */ + int y; + + for( y=sy; y>16)*16; + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + for( int x=sx; x>16)*2] << 8) | source[(x_index>>16)*2+1]; + if ((data & 0x8000) || (transparency & STV_TRANSPARENCY_NONE)) + { + int b = pal5bit((data & 0x7c00) >> 10); + int g = pal5bit((data & 0x03e0) >> 5); + int r = pal5bit( data & 0x001f); + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if (transparency & STV_TRANSPARENCY_ALPHA) + dest[x] = alpha_blend_r32( dest[x], rgb_t(r, g, b), alpha ); + else + dest[x] = rgb_t(r, g, b); + } + x_index += dx; + } + + y_index += dy; + } + + } + + } + +} + + +void saturn_state::stv_vdp2_drawgfx_rgb888( bitmap_rgb32 &dest_bmp, const rectangle &clip, uint32_t code, int flipx, int flipy, + int sx, int sy, int transparency, int alpha) +{ + rectangle myclip; + uint8_t* gfxdata; + int sprite_screen_width, sprite_screen_height; + + gfxdata = m_vdp2.gfx_decode.get() + code * 0x20; + sprite_screen_width = sprite_screen_height = 8; + + if(stv2_current_tilemap.window_control.enabled[0] || + stv2_current_tilemap.window_control.enabled[1]) + popmessage("Window Enabled for RGB888 tiles"); + + /* KW 991012 -- Added code to force clip to bitmap boundary */ + myclip = clip; + myclip &= dest_bmp.cliprect(); + { + int dx = stv2_current_tilemap.incx; + int dy = stv2_current_tilemap.incy; + + int ex = sx+sprite_screen_width; + int ey = sy+sprite_screen_height; + + int x_index_base; + int y_index; + + if( flipx ) + { + x_index_base = (sprite_screen_width-1)*dx; + dx = -dx; + } + else + { + x_index_base = 0; + } + + if( flipy ) + { + y_index = (sprite_screen_height-1)*dy; + dy = -dy; + } + else + { + y_index = 0; + } + + if( sx < myclip.left()) + { /* clip left */ + int pixels = myclip.left()-sx; + sx += pixels; + x_index_base += pixels*dx; + } + if( sy < myclip.top() ) + { /* clip top */ + int pixels = myclip.top()-sy; + sy += pixels; + y_index += pixels*dy; + } + /* NS 980211 - fixed incorrect clipping */ + if( ex > myclip.right()+1 ) + { /* clip right */ + int pixels = ex-myclip.right()-1; + ex -= pixels; + } + if( ey > myclip.bottom()+1 ) + { /* clip bottom */ + int pixels = ey-myclip.bottom()-1; + ey -= pixels; + } + + if( ex>sx ) + { /* skip if inner loop doesn't draw anything */ + for( int y=sy; y>16)*32; + uint32_t *const dest = &dest_bmp.pix(y); + + int x_index = x_index_base; + + for( int x=sx; x>16)*4+0] << 24) | (source[(x_index>>16)*4+1] << 16) | (source[(x_index>>16)*4+2] << 8) | (source[(x_index>>16)*4+3] << 0); + if ((data & 0x80000000) || (transparency & STV_TRANSPARENCY_NONE)) + { + int b = (data & 0xff0000) >> 16; + int g = (data & 0x00ff00) >> 8; + int r = (data & 0x0000ff); + + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if (transparency & STV_TRANSPARENCY_ALPHA) + dest[x] = alpha_blend_r32( dest[x], rgb_t(r, g, b), alpha ); + else + dest[x] = rgb_t(r, g, b); + } + x_index += dx; + } + + y_index += dy; + } + + } + + } +} + +void saturn_state::stv_vdp2_drawgfx_alpha(bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, + uint32_t code,uint32_t color, int flipx,int flipy,int offsx,int offsy, + int transparency, int alpha) +{ + const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); + const uint8_t *source_base = gfx->get_data(code % gfx->elements()); + int x_index_base, y_index, sx, sy, ex, ey; + int xinc, yinc; + + xinc = flipx ? -1 : 1; + yinc = flipy ? -1 : 1; + + x_index_base = flipx ? gfx->width()-1 : 0; + y_index = flipy ? gfx->height()-1 : 0; + + /* start coordinates */ + sx = offsx; + sy = offsy; + + /* end coordinates */ + ex = sx + gfx->width(); + ey = sy + gfx->height(); + + /* clip left */ + if (sx < clip.left()) + { + int pixels = clip.left()-sx; + sx += pixels; + x_index_base += xinc*pixels; + } + + /* clip top */ + if (sy < clip.top()) + { int pixels = clip.top()-sy; + sy += pixels; + y_index += yinc*pixels; + } + + /* clip right */ + if (ex > clip.right()+1) + { + ex = clip.right()+1; + } + /* clip bottom */ + if (ey > clip.bottom()+1) + { + ey = clip.bottom()+1; + } + + /* skip if inner loop doesn't draw anything */ + if (ex > sx) + { + for (int y = sy; y < ey; y++) + { + uint8_t const *const source = source_base + y_index*gfx->rowbytes(); + uint32_t *const dest = &dest_bmp.pix(y); + int x_index = x_index_base; + for (int x = sx; x < ex; x++) + { + if(stv_vdp2_window_process(x,y)) + { + int c = (source[x_index]); + if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) + dest[x] = alpha_blend_r32( dest[x], pal[c], alpha ); + } + + x_index += xinc; + } + y_index += yinc; + } + } +} + +void saturn_state::stv_vdp2_drawgfx_transpen(bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, + uint32_t code,uint32_t color, int flipx,int flipy,int offsx,int offsy, + int transparency) +{ + const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); + const uint8_t *source_base = gfx->get_data(code % gfx->elements()); + int x_index_base, y_index, sx, sy, ex, ey; + int xinc, yinc; + + xinc = flipx ? -1 : 1; + yinc = flipy ? -1 : 1; + + x_index_base = flipx ? gfx->width()-1 : 0; + y_index = flipy ? gfx->height()-1 : 0; + + /* start coordinates */ + sx = offsx; + sy = offsy; + + /* end coordinates */ + ex = sx + gfx->width(); + ey = sy + gfx->height(); + + /* clip left */ + if (sx < clip.left()) + { + int pixels = clip.left()-sx; + sx += pixels; + x_index_base += xinc*pixels; + } + + /* clip top */ + if (sy < clip.top()) + { int pixels = clip.top()-sy; + sy += pixels; + y_index += yinc*pixels; + } + + /* clip right */ + if (ex > clip.right()+1) + { + ex = clip.right()+1; + } + /* clip bottom */ + if (ey > clip.bottom()+1) + { + ey = clip.bottom()+1; + } + + /* skip if inner loop doesn't draw anything */ + if (ex > sx) + { + for (int y = sy; y < ey; y++) + { + uint8_t const *const source = source_base + y_index*gfx->rowbytes(); + uint32_t *const dest = &dest_bmp.pix(y); + int x_index = x_index_base; + for (int x = sx; x < ex; x++) + { + if(stv_vdp2_window_process(x,y)) + { + int c = (source[x_index]); + if ((transparency & STV_TRANSPARENCY_NONE) || (c != 0)) + dest[x] = pal[c]; + } + + x_index += xinc; + } + y_index += yinc; + } + } +} + +void saturn_state::draw_4bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int xsize, ysize, xsize_mask, ysize_mask; + int xsrc,ysrc,xdst,ydst; + int src_offs; + uint8_t* vram = m_vdp2.gfx_decode.get(); + uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; + int scrollx = stv2_current_tilemap.scrollx; + int scrolly = stv2_current_tilemap.scrolly; + uint16_t dot_data; + uint16_t pal_bank; + + xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; + ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; + + xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; + ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; + + pal_bank = stv2_current_tilemap.bitmap_palette_number; + pal_bank+= stv2_current_tilemap.colour_ram_address_offset; + pal_bank&= 7; + pal_bank<<=8; + if(stv2_current_tilemap.fade_control & 1) + pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048)); + + for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) + { + for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) + { + if(!stv_vdp2_window_process(xdst,ydst)) + continue; + + xsrc = (xdst + scrollx) & (xsize_mask-1); + ysrc = (ydst + scrolly) & (ysize_mask-1); + src_offs = (xsrc + (ysrc*xsize)); + src_offs/= 2; + src_offs += map_offset; + src_offs &= 0x7ffff; + + dot_data = vram[src_offs] >> ((xsrc & 1) ? 0 : 4); + dot_data&= 0xf; + + if ((dot_data != 0) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) + { + dot_data += pal_bank; + + if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) + bitmap.pix(ydst, xdst) = m_palette->pen(dot_data); + else + bitmap.pix(ydst, xdst) = alpha_blend_r32(bitmap.pix(ydst, xdst), m_palette->pen(dot_data), stv2_current_tilemap.alpha); + } + } + } +} + + +void saturn_state::draw_8bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int xsize, ysize, xsize_mask, ysize_mask; + int xsrc,ysrc,xdst,ydst; + int src_offs; + uint8_t* vram = m_vdp2.gfx_decode.get(); + uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; + int scrollx = stv2_current_tilemap.scrollx; + int scrolly = stv2_current_tilemap.scrolly; + uint16_t dot_data; + uint16_t pal_bank; + int xf, yf; + + xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; + ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; + + xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; + ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; + + pal_bank = stv2_current_tilemap.bitmap_palette_number; + pal_bank+= stv2_current_tilemap.colour_ram_address_offset; + pal_bank&= 7; + pal_bank<<=8; + if(stv2_current_tilemap.fade_control & 1) + pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048)); + + for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) + { + for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) + { + if(!stv_vdp2_window_process(xdst,ydst)) + continue; + + xf = stv2_current_tilemap.incx * xdst; + xf>>=16; + yf = stv2_current_tilemap.incy * ydst; + yf>>=16; + + xsrc = (xf + scrollx) & (xsize_mask-1); + ysrc = (yf + scrolly) & (ysize_mask-1); + src_offs = (xsrc + (ysrc*xsize)); + src_offs += map_offset; + src_offs &= 0x7ffff; + + dot_data = vram[src_offs]; + + if ((dot_data != 0) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) + { + dot_data += pal_bank; + + if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) + bitmap.pix(ydst, xdst) = m_palette->pen(dot_data); + else + bitmap.pix(ydst, xdst) = alpha_blend_r32(bitmap.pix(ydst, xdst), m_palette->pen(dot_data), stv2_current_tilemap.alpha); + } + } + } +} + +void saturn_state::draw_11bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int xsize, ysize, xsize_mask, ysize_mask; + int xsrc,ysrc,xdst,ydst; + int src_offs; + uint8_t* vram = m_vdp2.gfx_decode.get(); + uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; + int scrollx = stv2_current_tilemap.scrollx; + int scrolly = stv2_current_tilemap.scrolly; + uint16_t dot_data; + uint16_t pal_bank; + int xf, yf; + + xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; + ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; + + xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; + ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; + + pal_bank = 0; + if(stv2_current_tilemap.fade_control & 1) + pal_bank = ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048)); + + for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) + { + for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) + { + if(!stv_vdp2_window_process(xdst,ydst)) + continue; + + xf = stv2_current_tilemap.incx * xdst; + xf>>=16; + yf = stv2_current_tilemap.incy * ydst; + yf>>=16; + + xsrc = (xf + scrollx) & (xsize_mask-1); + ysrc = (yf + scrolly) & (ysize_mask-1); + src_offs = (xsrc + (ysrc*xsize)); + src_offs *= 2; + src_offs += map_offset; + src_offs &= 0x7ffff; + + dot_data = ((vram[src_offs]<<8)|(vram[src_offs+1]<<0)) & 0x7ff; + + if ((dot_data != 0) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) + { + dot_data += pal_bank; + + if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) + bitmap.pix(ydst, xdst) = m_palette->pen(dot_data); + else + bitmap.pix(ydst, xdst) = alpha_blend_r32(bitmap.pix(ydst, xdst), m_palette->pen(dot_data), stv2_current_tilemap.alpha); + } + } + } +} + + +void saturn_state::draw_rgb15_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int xsize, ysize, xsize_mask, ysize_mask; + int xsrc,ysrc,xdst,ydst; + int src_offs; + uint8_t* vram = m_vdp2.gfx_decode.get(); + uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; + int scrollx = stv2_current_tilemap.scrollx; + int scrolly = stv2_current_tilemap.scrolly; + int r,g,b; + uint16_t dot_data; + int xf, yf; + + xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; + ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; + + xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; + ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; + + for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) + { + for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) + { + if(!stv_vdp2_window_process(xdst,ydst)) + continue; + + xf = stv2_current_tilemap.incx * xdst; + xf>>=16; + yf = stv2_current_tilemap.incy * ydst; + yf>>=16; + + xsrc = (xf + scrollx) & (xsize_mask-1); + ysrc = (yf + scrolly) & (ysize_mask-1); + src_offs = (xsrc + (ysrc*xsize)); + src_offs *= 2; + src_offs += map_offset; + src_offs &= 0x7ffff; + + dot_data =(vram[src_offs]<<8)|(vram[src_offs+1]<<0); + + if ((dot_data & 0x8000) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) + { + b = pal5bit((dot_data & 0x7c00) >> 10); + g = pal5bit((dot_data & 0x03e0) >> 5); + r = pal5bit((dot_data & 0x001f) >> 0); + + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) + bitmap.pix(ydst, xdst) = rgb_t(r, g, b); + else + bitmap.pix(ydst, xdst) = alpha_blend_r32( bitmap.pix(ydst, xdst), rgb_t(r, g, b), stv2_current_tilemap.alpha ); + } + } + } +} + +void saturn_state::draw_rgb32_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int xsize, ysize, xsize_mask, ysize_mask; + int xsrc,ysrc,xdst,ydst; + int src_offs; + uint8_t* vram = m_vdp2.gfx_decode.get(); + uint32_t map_offset = stv2_current_tilemap.bitmap_map * 0x20000; + int scrollx = stv2_current_tilemap.scrollx; + int scrolly = stv2_current_tilemap.scrolly; + int r,g,b; + uint32_t dot_data; + int xf, yf; + + xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512; + ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256; + + xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize; + ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize; + + for(ydst=cliprect.top();ydst<=cliprect.bottom();ydst++) + { + for(xdst=cliprect.left();xdst<=cliprect.right();xdst++) + { + if(!stv_vdp2_window_process(xdst,ydst)) + continue; + + xf = stv2_current_tilemap.incx * xdst; + xf>>=16; + yf = stv2_current_tilemap.incy * ydst; + yf>>=16; + + xsrc = (xf + scrollx) & (xsize_mask-1); + ysrc = (yf + scrolly) & (ysize_mask-1); + src_offs = (xsrc + (ysrc*xsize)); + src_offs *= 4; + src_offs += map_offset; + src_offs &= 0x7ffff; + + dot_data = (vram[src_offs+0]<<24)|(vram[src_offs+1]<<16)|(vram[src_offs+2]<<8)|(vram[src_offs+3]<<0); + + if ((dot_data & 0x80000000) || (stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE)) + { + b = ((dot_data & 0x00ff0000) >> 16); + g = ((dot_data & 0x0000ff00) >> 8); + r = ((dot_data & 0x000000ff) >> 0); + + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2); + + if ( stv2_current_tilemap.colour_calculation_enabled == 0 ) + bitmap.pix(ydst, xdst) = rgb_t(r, g, b); + else + bitmap.pix(ydst, xdst) = alpha_blend_r32( bitmap.pix(ydst, xdst), rgb_t(r, g, b), stv2_current_tilemap.alpha ); + } + } + } +} + + +void saturn_state::stv_vdp2_draw_basic_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if (!stv2_current_tilemap.enabled) return; + + /* new bitmap code, supposed to rewrite the old one. Not supposed to be clean, but EFFICIENT! */ + if(stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) + { + switch(stv2_current_tilemap.colour_depth) + { + case 0: draw_4bpp_bitmap(bitmap,cliprect); return; + case 1: draw_8bpp_bitmap(bitmap,cliprect); return; + case 2: draw_11bpp_bitmap(bitmap, cliprect); return; + case 3: draw_rgb15_bitmap(bitmap,cliprect); return; + case 4: draw_rgb32_bitmap(bitmap,cliprect); return; + } + + /* intentional fall-through*/ + popmessage("%d %s %s %s",stv2_current_tilemap.colour_depth, + stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE ? "no trans" : "trans", + stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc", + (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom"); + } + else + { + switch(stv2_current_tilemap.colour_depth) + { + // case 0: draw_4bpp_bitmap(bitmap,cliprect); return; + case 1: draw_8bpp_bitmap(bitmap,cliprect); return; + // case 2: draw_11bpp_bitmap(bitmap, cliprect); return; + case 3: draw_rgb15_bitmap(bitmap,cliprect); return; + case 4: draw_rgb32_bitmap(bitmap,cliprect); return; + } + + /* intentional fall-through*/ + popmessage("%d %s %s %s",stv2_current_tilemap.colour_depth, + stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE ? "no trans" : "trans", + stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc", + (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom"); + } +} + + /*--------------------------------------------------------------------------- + | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address | + ----------------------------------------------------------------------------| + | | | 1 H x 1 V | bits 6-0 * 0x02000 | + | | 1 word |-------------------------------------| + | | | 2 H x 2 V | bits 8-0 * 0x00800 | + | 1 H x 1 V ---------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-0 * 0x04000 | + | | 2 words |-------------------------------------| + | | | 2 H x 2 V | bits 7-0 * 0x01000 | + ----------------------------------------------------------------------------- + | | | 1 H x 1 V | bits 6-1 * 0x04000 | + | | 1 word |-------------------------------------| + | | | 2 H x 2 V | bits 8-1 * 0x01000 | + | 2 H x 1 V ---------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-1 * 0x08000 | + | | 2 words |-------------------------------------| + | | | 2 H x 2 V | bits 7-1 * 0x02000 | + ----------------------------------------------------------------------------- + | | | 1 H x 1 V | bits 6-2 * 0x08000 | + | | 1 word |-------------------------------------| + | | | 2 H x 2 V | bits 8-2 * 0x02000 | + | 2 H x 2 V ---------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-2 * 0x10000 | + | | 2 words |-------------------------------------| + | | | 2 H x 2 V | bits 7-2 * 0x04000 | + --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/ + + +/* +4.2 Sega's Cell / Character Pattern / Page / Plane / Map system, aka a rather annoying thing that makes optimizations hard + (this is only for the normal tilemaps at the moment, i haven't even thought about the ROZ ones) + +Tiles: + +Cells are 8x8 gfx stored in video ram, they can be of various colour depths + +Character Patterns can be 8x8 or 16x16 (1 hcell x 1 vcell or 2 hcell x 2 vcell) + (a 16x16 character pattern is 4 8x8 cells put together) + +A page is made up of 64x64 cells, thats 64x64 character patterns in 8x8 mode or 32x32 character patterns in 16x16 mode. + 64 * 8 = 512 (0x200) + 32 * 16 = 512 (0x200) +A page is _always_ 512 (0x200) pixels in each direction + +in 1 word mode a 32*16 x 32*16 page is 0x0800 bytes +in 1 word mode a 64*8 x 64*8 page is 0x2000 bytes +in 2 word mode a 32*16 x 32*16 page is 0x1000 bytes +in 2 word mode a 64*8 x 64*8 page is 0x4000 bytes + +either 1, 2 or 4 pages make each plane depending on the plane size register (per tilemap) + therefore each plane is either + 64 * 8 * 1 x 64 * 8 * 1 (512 x 512) + 64 * 8 * 2 x 64 * 8 * 1 (1024 x 512) + 64 * 8 * 2 x 64 * 8 * 2 (1024 x 1024) + + 32 * 16 * 1 x 32 * 16 * 1 (512 x 512) + 32 * 16 * 2 x 32 * 16 * 1 (1024 x 512) + 32 * 16 * 2 x 32 * 16 * 2 (1024 x 1024) + +map is always enabled? + map is a 2x2 arrangement of planes, all 4 of the planes can be the same. + +*/ + +void saturn_state::stv_vdp2_get_map_page( int x, int y, int *_map, int *_page ) +{ + int page = 0; + int map; + + if ( stv2_current_tilemap.map_count == 4 ) + { + if ( stv2_current_tilemap.tile_size == 0 ) + { + if ( stv2_current_tilemap.plane_size & 1 ) + { + page = ((x >> 6) & 1); + map = (x >> 7) & 1; + } + else + { + map = (x >> 6) & 1; + } + + if ( stv2_current_tilemap.plane_size & 2 ) + { + page |= ((y >> (6-1)) & 2); + map |= ((y >> (7-1)) & 2); + } + else + { + map |= ((y >> (6-1)) & 2); + } + } + else + { + if ( stv2_current_tilemap.plane_size & 1 ) + { + page = ((x >> 5) & 1); + map = (x >> 6) & 1; + } + else + { + map = (x >> 5) & 1; + } + + if ( stv2_current_tilemap.plane_size & 2 ) + { + page |= ((y >> (5 - 1)) & 2); + map |= ((y >> (6-1)) & 2); + } + else + { + map |= ((y >> (5-1)) & 2); + } + } + } + else //16 + { + if ( stv2_current_tilemap.tile_size == 0 ) + { + if ( stv2_current_tilemap.plane_size & 1 ) + { + page = ((x >> 6) & 1); + map = (x >> 7) & 3; + } + else + { + map = (x >> 6) & 3; + } + + if ( stv2_current_tilemap.plane_size & 2 ) + { + page |= ((y >> (6-1)) & 2); + map |= ((y >> (7-2)) & 12); + } + else + { + map |= ((y >> (6-2)) & 12); + } + } + else + { + if ( stv2_current_tilemap.plane_size & 1 ) + { + page = ((x >> 5) & 1); + map = (x >> 6) & 3; + } + else + { + map = (x >> 5) & 3; + } + + if ( stv2_current_tilemap.plane_size & 2 ) + { + page |= ((y >> (5 - 1)) & 2); + map |= ((y >> (6-2)) & 12); + } + else + { + map |= ((y >> (5-2)) & 12); + } + } + } + *_page = page; + *_map = map; +} + +void saturn_state::stv_vdp2_draw_basic_tilemap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + /* hopefully this is easier to follow than it is efficient .. */ + + /* I call character patterns tiles .. even if they represent up to 4 tiles */ + + /* Page variables */ + int pgtiles_x, pgpixels_x; + int pgtiles_y, pgpixels_y; + int pgsize_bytes, pgsize_dwords; + + /* Plane Variables */ + int pltiles_x, plpixels_x; + int pltiles_y, plpixels_y; + int plsize_bytes/*, plsize_dwords*/; + + /* Map Variables */ + int mptiles_x, mppixels_x; + int mptiles_y, mppixels_y; + int mpsize_bytes, mpsize_dwords; + + /* work Variables */ + int i, x, y; + int base[16]; + + int scalex,scaley; + int tilesizex, tilesizey; + int drawypos, drawxpos; + + int tilecodemin = 0x10000000, tilecodemax = 0; + + if ( stv2_current_tilemap.incx == 0 || stv2_current_tilemap.incy == 0 ) return; + + if ( stv2_current_tilemap.colour_calculation_enabled == 1 ) + { + if ( STV_VDP2_CCMD ) + { + stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ADD_BLEND; + } + else + { + stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA; + } + } + + scalex = s32(s64(0x100000000U) / s64(stv2_current_tilemap.incx)); + scaley = s32(s64(0x100000000U) / s64(stv2_current_tilemap.incy)); + tilesizex = scalex * 8; + tilesizey = scaley * 8; + drawypos = drawxpos = 0; + + /* Calculate the Number of tiles for x / y directions of each page (actually these will be the same */ + /* (2-stv2_current_tilemap.tile_size) << 5) */ + pgtiles_x = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode) + pgtiles_y = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode) + + /* Calculate the Page Size in BYTES */ + /* 64 * 64 * (1 * 2) = 0x2000 bytes + 32 * 32 * (1 * 2) = 0x0800 bytes + 64 * 64 * (2 * 2) = 0x4000 bytes + 32 * 32 * (2 * 2) = 0x1000 bytes */ + + pgsize_bytes = (pgtiles_x * pgtiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2); + + /*--------------------------------------------------------------------------- + | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address | + ----------------------------------------------------------------------------| + | | | 1 H x 1 V | bits 6-0 * 0x02000 | + | | 1 word |-------------------------------------| + | | | 2 H x 2 V | bits 8-0 * 0x00800 | + | 1 H x 1 V ---------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-0 * 0x04000 | + | | 2 words |-------------------------------------| + | | | 2 H x 2 V | bits 7-0 * 0x01000 | + ---------------------------------------------------------------------------*/ + + + /* Page Dimensions are always 0x200 pixes (512x512) */ + pgpixels_x = 0x200; + pgpixels_y = 0x200; + + /* Work out the Plane Size in tiles and Plane Dimensions (pixels) */ + switch (stv2_current_tilemap.plane_size & 3) + { + case 0: // 1 page * 1 page + pltiles_x = pgtiles_x; + plpixels_x = pgpixels_x; + pltiles_y = pgtiles_y; + plpixels_y = pgpixels_y; + break; + + case 1: // 2 pages * 1 page + pltiles_x = pgtiles_x * 2; + plpixels_x = pgpixels_x * 2; + pltiles_y = pgtiles_y; + plpixels_y = pgpixels_y; + break; + + case 3: // 2 pages * 2 pages + pltiles_x = pgtiles_x * 2; + plpixels_x = pgpixels_x * 2; + pltiles_y = pgtiles_y * 2; + plpixels_y = pgpixels_y * 2; + break; + + default: + // illegal + pltiles_x = pgtiles_x; + plpixels_x = pgpixels_x; + pltiles_y = pgtiles_y * 2; + plpixels_y = pgpixels_y * 2; + break; + } + + /* Plane Size in BYTES */ + /* still the same as before + (64 * 1) * (64 * 1) * (1 * 2) = 0x02000 bytes + (32 * 1) * (32 * 1) * (1 * 2) = 0x00800 bytes + (64 * 1) * (64 * 1) * (2 * 2) = 0x04000 bytes + (32 * 1) * (32 * 1) * (2 * 2) = 0x01000 bytes + changed + (64 * 2) * (64 * 1) * (1 * 2) = 0x04000 bytes + (32 * 2) * (32 * 1) * (1 * 2) = 0x01000 bytes + (64 * 2) * (64 * 1) * (2 * 2) = 0x08000 bytes + (32 * 2) * (32 * 1) * (2 * 2) = 0x02000 bytes + changed + (64 * 2) * (64 * 1) * (1 * 2) = 0x08000 bytes + (32 * 2) * (32 * 1) * (1 * 2) = 0x02000 bytes + (64 * 2) * (64 * 1) * (2 * 2) = 0x10000 bytes + (32 * 2) * (32 * 1) * (2 * 2) = 0x04000 bytes + */ + + plsize_bytes = (pltiles_x * pltiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2); + + /*--------------------------------------------------------------------------- + | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address | + ----------------------------------------------------------------------------- + | 1 H x 1 V see above, nothing has changed | + ----------------------------------------------------------------------------- + | | | 1 H x 1 V | bits 6-1 * 0x04000 | + | | 1 word |-------------------------------------| + | | | 2 H x 2 V | bits 8-1 * 0x01000 | + | 2 H x 1 V ---------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-1 * 0x08000 | + | | 2 words |-------------------------------------| + | | | 2 H x 2 V | bits 7-1 * 0x02000 | + ----------------------------------------------------------------------------- + | | | 1 H x 1 V | bits 6-2 * 0x08000 | + | | 1 word |-------------------------------------| + | | | 2 H x 2 V | bits 8-2 * 0x02000 | + | 2 H x 2 V ---------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-2 * 0x10000 | + | | 2 words |-------------------------------------| + | | | 2 H x 2 V | bits 7-2 * 0x04000 | + --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/ + + + /* Work out the Map Sizes in tiles, Map Dimensions */ + /* maps are always enabled? */ + if ( stv2_current_tilemap.map_count == 4 ) + { + mptiles_x = pltiles_x * 2; + mptiles_y = pltiles_y * 2; + mppixels_x = plpixels_x * 2; + mppixels_y = plpixels_y * 2; + } + else + { + mptiles_x = pltiles_x * 4; + mptiles_y = pltiles_y * 4; + mppixels_x = plpixels_x * 4; + mppixels_y = plpixels_y * 4; + } + + /* Map Size in BYTES */ + mpsize_bytes = (mptiles_x * mptiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2); + + + /*----------------------------------------------------------------------------------------------------------- + | | | 1 H x 1 V | bits 6-1 (upper mask 0x07f) (0x1ff >> 2) * 0x04000 | + | | 1 word |---------------------------------------------------------------------| + | | | 2 H x 2 V | bits 8-1 (upper mask 0x1ff) (0x1ff >> 0) * 0x01000 | + | 2 H x 1 V -----------------------------------------------------------------------------------------------| + | | | 1 H x 1 V | bits 5-1 (upper mask 0x03f) (0x1ff >> 3) * 0x08000 | + | | 2 words |---------------------------------------------------------------------| + | | | 2 H x 2 V | bits 7-1 (upper mask 0x0ff) (0x1ff >> 1) * 0x02000 | + ------------------------------------------------------------------------------------------------------------- + lower mask = ~stv2_current_tilemap.plane_size + -----------------------------------------------------------------------------------------------------------*/ + + /* Precalculate bases from MAP registers */ + for (i = 0; i < stv2_current_tilemap.map_count; i++) + { + static const int shifttable[4] = {0,1,2,2}; + + int uppermask, uppermaskshift; + + uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1); + uppermask = 0x1ff >> uppermaskshift; + + base[i] = ((stv2_current_tilemap.map_offset[i] & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes; + + base[i] &= 0x7ffff; /* shienryu needs this for the text layer, is there a problem elsewhere or is it just right without the ram cart */ + + base[i] = base[i] / 4; // convert bytes to DWORDS + } + + /* other bits */ + //stv2_current_tilemap.trans_enabled = stv2_current_tilemap.trans_enabled ? STV_TRANSPARENCY_NONE : STV_TRANSPARENCY_PEN; + stv2_current_tilemap.scrollx &= mppixels_x-1; + stv2_current_tilemap.scrolly &= mppixels_y-1; + + pgsize_dwords = pgsize_bytes /4; + //plsize_dwords = plsize_bytes /4; + mpsize_dwords = mpsize_bytes /4; + +// if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit %08x", stv2_current_tilemap.map_offset[0]); +// if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit %08x %08x %08x %08x", stv2_current_tilemap.plane_size, pgtiles_x, pltiles_x, mptiles_x); + + if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... + + /* most things we need (or don't need) to work out are now worked out */ + + for (y = 0; y> 16) < cliprect.top() ) + { + drawypos += drawyposinc; + y++; + } + mptiles_y += y; + } + else + { + drawypos += tilesizey*(stv2_current_tilemap.tile_size ? 2 : 1); + } + if ((drawypos >> 16) > cliprect.bottom()) break; + + ypageoffs = y & (pgtiles_y-1); + + for (x = 0; x> 16) < cliprect.left() ) + { + drawxpos += drawxposinc; + x++; + } + mptiles_x += x; + } + else + { + drawxpos+=tilesizex*(stv2_current_tilemap.tile_size ? 2 : 1); + } + if ( (drawxpos >> 16) > cliprect.right() ) break; + + xpageoffs = x & (pgtiles_x-1); + + stv_vdp2_get_map_page(x,y,&map,&page); + + newbase = base[map] + page * pgsize_dwords; + offs = (ypageoffs * pgtiles_x) + xpageoffs; + +/* GET THE TILE INFO ... */ + /* 1 word per tile mode with supplement bits */ + if (stv2_current_tilemap.pattern_data_size ==1) + { + data = m_vdp2_vram[newbase + offs/2]; + data = (offs&1) ? (data & 0x0000ffff) : ((data & 0xffff0000) >> 16); + + /* Supplement Mode 12 bits, no flip */ + if (stv2_current_tilemap.character_number_supplement == 1) + { +/* no flip */ flipyx = 0; +/* 8x8 */ if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x0fff) + ( (stv2_current_tilemap.supplementary_character_bits&0x1c) << 10); +/* 16x16 */ else tilecode = ((data & 0x0fff) << 2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x10) << 10); + } + /* Supplement Mode 10 bits, with flip */ + else + { +/* flip bits */ flipyx = (data & 0x0c00) >> 10; +/* 8x8 */ if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x03ff) + ( (stv2_current_tilemap.supplementary_character_bits) << 10); +/* 16x16 */ else tilecode = ((data & 0x03ff) <<2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x1c) << 10); + } + +/*>16cols*/ if (stv2_current_tilemap.colour_depth != 0) pal = ((data & 0x7000)>>8); +/*16 cols*/ else pal = ((data & 0xf000)>>12) +( (stv2_current_tilemap.supplementary_palette_bits) << 4); + + } + /* 2 words per tile, no supplement bits */ + else + { + data = m_vdp2_vram[newbase + offs]; + tilecode = (data & 0x00007fff); + pal = (data & 0x007f0000)>>16; + // specialc = (data & 0x10000000)>>28; + flipyx = (data & 0xc0000000)>>30; + } +/* WE'VE GOT THE TILE INFO ... */ + + if ( tilecode < tilecodemin ) tilecodemin = tilecode; + if ( tilecode > tilecodemax ) tilecodemax = tilecode; + +/* DECODE ANY TILES WE NEED TO DECODE */ + + pal += stv2_current_tilemap.colour_ram_address_offset<< 4; // bios uses this .. + + /*Enable fading bit*/ + if(stv2_current_tilemap.fade_control & 1) + { + /*Select fading bit*/ + pal += ((stv2_current_tilemap.fade_control & 2) ? (0x100) : (0x80)); + } + + if (stv2_current_tilemap.colour_depth == 1) + { + gfx = 2; + pal = pal >>4; + tilecode &=0x7fff; + if (tilecode == 0x7fff) tilecode--; /* prevents crash but unsure what should happen; wrapping? */ + tilecodespacing = 2; + } + else if (stv2_current_tilemap.colour_depth == 0) + { + gfx = 0; + tilecode &=0x7fff; + tilecodespacing = 1; + } +/* TILES ARE NOW DECODED */ + + if(!STV_VDP2_VRAMSZ) + tilecode &= 0x3fff; + +/* DRAW! */ + if(stv2_current_tilemap.incx != 0x10000 || + stv2_current_tilemap.incy != 0x10000 || + stv2_current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND ) + { +#define SCR_TILESIZE_X (((drawxpos + tilesizex) >> 16) - (drawxpos >> 16)) +#define SCR_TILESIZE_X1(startx) (((drawxpos + (startx) + tilesizex) >> 16) - ((drawxpos + (startx))>>16)) +#define SCR_TILESIZE_Y (((drawypos + tilesizey) >> 16) - (drawypos >> 16)) +#define SCR_TILESIZE_Y1(starty) (((drawypos + (starty) + tilesizey) >> 16) - ((drawypos + (starty))>>16)) + if (stv2_current_tilemap.tile_size==1) + { + if ( stv2_current_tilemap.colour_depth == 4 ) + { + popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 1, contact MAMEdev"); + } + else if ( stv2_current_tilemap.colour_depth == 3 ) + { + /* RGB555 */ + stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha); + stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha); + stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); + stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); + } + else + { + /* normal */ + stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha); + stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha); + stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); + stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha); + } + } + else + { + if ( stv2_current_tilemap.colour_depth == 4 ) + popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 0, contact MAMEdev"); + else if ( stv2_current_tilemap.colour_depth == 3) + { + stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha); + } + else + stv_vdp2_drawgfxzoom(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha); + } + } + else + { + int olddrawxpos, olddrawypos; + olddrawxpos = drawxpos; drawxpos >>= 16; + olddrawypos = drawypos; drawypos >>= 16; + if (stv2_current_tilemap.tile_size==1) + { + if ( stv2_current_tilemap.colour_depth == 4 ) + { + /* normal */ + stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + } + else if ( stv2_current_tilemap.colour_depth == 3 ) + { + /* normal */ + stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + } + else if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) + { + /* alpha */ + stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + } + else + { + /* normal */ + stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency); + stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency); + stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency); + stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency); + } + } + else + { + if ( stv2_current_tilemap.colour_depth == 4) + { + stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + } + else if ( stv2_current_tilemap.colour_depth == 3) + { + stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + } + else + { + if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) + stv_vdp2_drawgfx_alpha(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha); + else + stv_vdp2_drawgfx_transpen(bitmap,cliprect,m_gfxdecode->gfx(gfx),tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,stv2_current_tilemap.transparency); + } + } + drawxpos = olddrawxpos; + drawypos = olddrawypos; + } +/* DRAWN?! */ + + } + } + if ( stv2_current_tilemap.layer_name & 0x80 ) + { + static const int shifttable[4] = {0,1,2,2}; + int uppermask, uppermaskshift; + int mapsize; + uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1); + uppermask = 0x1ff >> uppermaskshift; + + if ( LOG_VDP2 ) + { + logerror( "Layer RBG%d, size %d x %d\n", stv2_current_tilemap.layer_name & 0x7f, cliprect.right() + 1, cliprect.bottom() + 1 ); + logerror( "Tiles: min %08X, max %08X\n", tilecodemin, tilecodemax ); + logerror( "MAP size in dwords %08X\n", mpsize_dwords ); + for (i = 0; i < stv2_current_tilemap.map_count; i++) + { + logerror( "Map register %d: base %08X\n", stv2_current_tilemap.map_offset[i], base[i] ); + } + } + + // store map information + stv_vdp2_layer_data_placement.map_offset_min = 0x7fffffff; + stv_vdp2_layer_data_placement.map_offset_max = 0x00000000; + + for (i = 0; i < stv2_current_tilemap.map_count; i++) + { + uint32_t max_base; + + if ( base[i] < stv_vdp2_layer_data_placement.map_offset_min ) + stv_vdp2_layer_data_placement.map_offset_min = base[i]; + + // Head On in Sega Memorial Collection 1 cares (uses RBG0 with all map regs equal to 0x20) + max_base = (base[i] + plsize_bytes/4); + if ( max_base > stv_vdp2_layer_data_placement.map_offset_max ) + stv_vdp2_layer_data_placement.map_offset_max = max_base; + } + + + mapsize = ((1 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes - + ((0 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes; + mapsize /= 4; + + stv_vdp2_layer_data_placement.map_offset_max += mapsize; + + stv_vdp2_layer_data_placement.tile_offset_min = tilecodemin * 0x20 / 4; + stv_vdp2_layer_data_placement.tile_offset_max = (tilecodemax + 1) * 0x20 / 4; + } + +} + +#define STV_VDP2_READ_VERTICAL_LINESCROLL( _val, _address ) \ + { \ + _val = m_vdp2_vram[ _address ]; \ + _val &= 0x07ffff00; \ + if ( _val & 0x04000000 ) _val |= 0xf8000000; \ + } + + +void saturn_state::stv_vdp2_check_tilemap_with_linescroll(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + rectangle mycliprect; + int cur_line = cliprect.top(); + int address; + int active_functions = 0; + int32_t scroll_values[3], prev_scroll_values[3]; + int i; + int scroll_values_equal; + int lines; + int16_t main_scrollx, main_scrolly; +// int32_t incx; + int linescroll_enable, vertical_linescroll_enable, linezoom_enable; + int vertical_linescroll_index = -1; + + // read original scroll values + main_scrollx = stv2_current_tilemap.scrollx; + main_scrolly = stv2_current_tilemap.scrolly; +// incx = stv2_current_tilemap.incx; + + // prepare linescroll flags + linescroll_enable = stv2_current_tilemap.linescroll_enable; +// stv2_current_tilemap.linescroll_enable = 0; + vertical_linescroll_enable = stv2_current_tilemap.vertical_linescroll_enable; +// stv2_current_tilemap.vertical_linescroll_enable = 0; + linezoom_enable = stv2_current_tilemap.linezoom_enable; +// stv2_current_tilemap.linezoom_enable = 0; + + // prepare working clipping rectangle + memcpy( &mycliprect, &cliprect, sizeof(rectangle) ); + + // calculate the number of active functions + if ( linescroll_enable ) active_functions++; + if ( vertical_linescroll_enable ) + { + vertical_linescroll_index = active_functions; + active_functions++; + } + if ( linezoom_enable ) active_functions++; + + // address of data table + address = stv2_current_tilemap.linescroll_table_address + active_functions*4*cliprect.top(); + + // get the first scroll values + for ( i = 0; i < active_functions; i++ ) + { + if ( i == vertical_linescroll_index ) + { + STV_VDP2_READ_VERTICAL_LINESCROLL( prev_scroll_values[i], (address / 4) + i ); + prev_scroll_values[i] -= (cur_line * stv2_current_tilemap.incy); + } + else + { + prev_scroll_values[i] = m_vdp2_vram[ (address / 4) + i ]; + } + } + + while( cur_line <= cliprect.bottom() ) + { + lines = 0; + do + { + // update address + address += active_functions*4; + + // update lines count + lines += stv2_current_tilemap.linescroll_interval; + + // get scroll values + for ( i = 0; i < active_functions; i++ ) + { + if ( i == vertical_linescroll_index ) + { + STV_VDP2_READ_VERTICAL_LINESCROLL( scroll_values[i], (address/4) + i ); + scroll_values[i] -= (cur_line + lines) * stv2_current_tilemap.incy; + } + else + { + scroll_values[i] = m_vdp2_vram[ (address / 4) + i ]; + } + } + + // compare scroll values + scroll_values_equal = 1; + for ( i = 0; i < active_functions; i++ ) + { + scroll_values_equal &= (scroll_values[i] == prev_scroll_values[i]); + } + } while( scroll_values_equal && ((cur_line + lines) <= cliprect.bottom()) ); + + // determined how many lines can be drawn + // prepare clipping rectangle + mycliprect.sety(cur_line, cur_line + lines - 1); + + // prepare scroll values + i = 0; + // linescroll + if ( linescroll_enable ) + { + prev_scroll_values[i] &= 0x07ffff00; + if ( prev_scroll_values[i] & 0x04000000 ) prev_scroll_values[i] |= 0xf8000000; + stv2_current_tilemap.scrollx = main_scrollx + (prev_scroll_values[i] >> 16); + i++; + } + // vertical line scroll + if ( vertical_linescroll_enable ) + { + stv2_current_tilemap.scrolly = main_scrolly + (prev_scroll_values[i] >> 16); + i++; + } + + // linezooom + if ( linezoom_enable ) + { + prev_scroll_values[i] &= 0x0007ff00; + if ( prev_scroll_values[i] & 0x00040000 ) prev_scroll_values[i] |= 0xfff80000; + stv2_current_tilemap.incx = prev_scroll_values[i]; + i++; + } + +// if ( LOG_VDP2 ) logerror( "Linescroll: y < %d, %d >, scrollx = %d, scrolly = %d, incx = %f\n", mycliprect.top(), mycliprect.bottom(), stv2_current_tilemap.scrollx, stv2_current_tilemap.scrolly, (float)stv2_current_tilemap.incx/65536.0 ); + // render current tilemap portion + if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap + { + stv_vdp2_draw_basic_bitmap(bitmap, mycliprect); + } + else + { + //stv_vdp2_apply_window_on_layer(mycliprect); + stv_vdp2_draw_basic_tilemap(bitmap, mycliprect); + } + + // update parameters for next iteration + memcpy( prev_scroll_values, scroll_values, sizeof(scroll_values)); + cur_line += lines; + } +} + +void saturn_state::stv_vdp2_draw_line(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int x,y; + uint8_t* gfxdata = m_vdp2.gfx_decode.get(); + uint32_t base_offs,base_mask; + uint32_t pix; + uint8_t interlace; + + interlace = (STV_VDP2_LSMD == 3)+1; + + { + base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; + + for(y=cliprect.top();y<=cliprect.bottom();y++) + { + base_offs = (STV_VDP2_LCTA & base_mask) << 1; + + if(STV_VDP2_LCCLMD) + base_offs += (y / interlace) << 1; + + for(x=cliprect.left();x<=cliprect.right();x++) + { + uint16_t pen; + + pen = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1]; + pix = bitmap.pix(y, x); + + bitmap.pix(y, x) = add_blend_r32(m_palette->pen(pen & 0x7ff),pix); + } + } + } +} + +void saturn_state::stv_vdp2_draw_mosaic(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint8_t is_roz) +{ + uint8_t h_size = STV_VDP2_MZSZH+1; + uint8_t v_size = STV_VDP2_MZSZV+1; + + if(is_roz) + v_size = 1; + + if(h_size == 1 && v_size == 1) + return; // don't bother + + if(STV_VDP2_LSMD == 3) + v_size <<= 1; + + for(int y=cliprect.top();y<=cliprect.bottom();y+=v_size) + { + for(int x=cliprect.left();x<=cliprect.right();x+=h_size) + { + uint32_t pix = bitmap.pix(y, x); + + for(int yi=0;yi>= 2; + + base_offset = 0; + base_multiplier = 1; + // offset for both enabled + if(STV_VDP2_N0VCSC && STV_VDP2_N1VCSC) + { + // NBG1 + if(stv2_current_tilemap.layer_name & 1) + base_offset = 1; + + base_multiplier = 2; + } + + base_scrollx = stv2_current_tilemap.scrollx; + base_scrolly = stv2_current_tilemap.scrolly; + //base_incx = stv2_current_tilemap.incx; + //base_incy = stv2_current_tilemap.incy; + + while(cur_char <= cliprect.right()) + { + mycliprect.setx(cur_char, cur_char + 8 - 1); + + uint32_t cur_address; + int16_t char_scroll; + + cur_address = vcsc_address; + cur_address += ((cur_char >> 3) * base_multiplier) + base_offset; + + char_scroll = m_vdp2_vram[ cur_address ] >> 16; + char_scroll &= 0x07ff; + if ( char_scroll & 0x0400 ) char_scroll |= 0xf800; + stv2_current_tilemap.scrollx = base_scrollx; + stv2_current_tilemap.scrolly = base_scrolly + (char_scroll); + //stv2_current_tilemap.incx = base_incx; + //stv2_current_tilemap.incy = base_incy; + + stv_vdp2_check_tilemap_with_linescroll(bitmap, mycliprect); + + // TODO: + 16 for tilemap and char size = 16? + cur_char += 8; + + } + } + else + stv_vdp2_check_tilemap_with_linescroll(bitmap, cliprect); + + return; + } + + if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap + { + stv_vdp2_draw_basic_bitmap(bitmap, mycliprect); + } + else + { + //stv_vdp2_apply_window_on_layer(mycliprect); + stv_vdp2_draw_basic_tilemap(bitmap, mycliprect); + } + + /* post-processing functions */ + // (TODO: needs layer bitmaps to be individual planes to work correctly) + if(stv2_current_tilemap.line_screen_enabled && TEST_FUNCTIONS) + stv_vdp2_draw_line(bitmap,cliprect); + + if(stv2_current_tilemap.mosaic_screen_enabled && TEST_FUNCTIONS) + stv_vdp2_draw_mosaic(bitmap,cliprect,stv2_current_tilemap.layer_name & 0x80); + + + { + if(stv2_current_tilemap.colour_depth == 2 && !stv2_current_tilemap.bitmap_enable) + popmessage("2048 color mode used on a non-bitmap plane"); + +// if(STV_VDP2_SCXDN0 || STV_VDP2_SCXDN1 || STV_VDP2_SCYDN0 || STV_VDP2_SCYDN1) +// popmessage("Fractional part scrolling write, contact MAMEdev"); + + /* Pukunpa */ + //if(STV_VDP2_SPWINEN) + // popmessage("Sprite Window enabled"); + + /* Capcom Collection Dai 2 - Choh Makaimura (Duh!) */ + if(STV_VDP2_MZCTL & 0x1f && POPMESSAGE_DEBUG) + popmessage("Mosaic control enabled = %04x\n",STV_VDP2_MZCTL); + + /* Bio Hazard bit 1 */ + /* Airs Adventure 0x3e */ + /* Bakuretsu Hunter */ + if(STV_VDP2_LNCLEN & ~2 && POPMESSAGE_DEBUG) + popmessage("Line Colour screen enabled %04x %08x, contact MAMEdev",STV_VDP2_LNCLEN,STV_VDP2_LCTAU<<16|STV_VDP2_LCTAL); + + /* Bio Hazard 0x400 = extended color calculation enabled */ + /* Advanced World War 0x200 = color calculation ratio mode */ + /* Whizz = 0x8100 */ + /* Dark Saviour = 0x9051 on save select screen (the one with a Saturn in the background) */ + if(STV_VDP2_CCCR & 0x6000) + popmessage("Gradation enabled %04x, contact MAMEdev",STV_VDP2_CCCR); + + /* Advanced VG, Shining Force III */ + if(STV_VDP2_SFCCMD && POPMESSAGE_DEBUG) + popmessage("Special Color Calculation enable %04x, contact MAMEdev",STV_VDP2_SFCCMD); + + /* Cleopatra Fortune Transparent Shadow */ + /* Pretty Fighter X Back & Transparent Shadow*/ + //if(STV_VDP2_SDCTL & 0x0120) + // popmessage("%s shadow select bit enabled, contact MAMEdev",STV_VDP2_SDCTL & 0x100 ? "Transparent" : "Back"); + + /* Langrisser III bit 3 normal, bit 1 during battle field */ + /* Metal Slug bit 0 during gameplay */ + /* Bug! Sega Away Logo onward 0x470 */ + /* Command & Conquer 0x0004 0xc000 */ + if(STV_VDP2_SFSEL & ~0x47f) + popmessage("Special Function Code Select enable %04x %04x, contact MAMEdev",STV_VDP2_SFSEL,STV_VDP2_SFCODE); + + /* Albert Odyssey Gaiden 0x0001 */ + /* Asuka 120% 0x0101 */ + /* Slam n Jam 96 0x0003 */ + if(STV_VDP2_ZMCTL & 0x0200) + popmessage("Reduction enable %04x, contact MAMEdev",STV_VDP2_ZMCTL); + + /* Burning Rangers and friends FMV, J.League Pro Soccer Club Wo Tsukurou!! backgrounds */ + if(STV_VDP2_SCRCTL & 0x0101 && POPMESSAGE_DEBUG) + popmessage("Vertical cell scroll enable %04x, contact MAMEdev",STV_VDP2_SCRCTL); + + /* Magical Drop III 0x200 -> color calculation window */ + /* Ide Yousuke Meijin No Shin Jissen Mahjong 0x0303 */ + /* Decathlete 0x088 */ + /* Sexy Parodius 0x2300 */ +// if(STV_VDP2_WCTLD & 0x2000) +// popmessage("Special window enabled %04x, contact MAMEdev",STV_VDP2_WCTLD); + + /* Shining Force III, After Burner 2 (doesn't make a proper use tho?) */ + /* Layer Section */ + //if(STV_VDP2_W0LWE || STV_VDP2_W1LWE) + // popmessage("Line Window %s %08x enabled, contact MAMEdev",STV_VDP2_W0LWE ? "0" : "1",STV_VDP2_W0LWTA); + + /* Akumajou Dracula, bits 2-4 */ + /* Arcana Strikes bit 5 */ + /* Choh Makai Mura 0x0055 */ + /* Sega Rally 0x0155 */ + /* Find Love 0x4400 */ + /* Dragon Ball Z 0x3800 - 0x2c00 */ + /* Assault Suit Leynos 2 0x0200*/ + /* Bug! 0x8800 */ + /* Wonder 3 0x0018 */ + if(STV_VDP2_SFPRMD & ~0xff7f) + popmessage("Special Priority Mode enabled %04x, contact MAMEdev",STV_VDP2_SFPRMD); + } +} + + +void saturn_state::stv_vdp2_copy_roz_bitmap(bitmap_rgb32 &bitmap, + bitmap_rgb32 &roz_bitmap, + const rectangle &cliprect, + int iRP, + int planesizex, + int planesizey, + int planerenderedsizex, + int planerenderedsizey) +{ + int32_t xsp, ysp, xp, yp, dx, dy, x, y, xs, ys, dxs, dys; + int32_t vcnt, hcnt; + int32_t kx, ky; + int8_t use_coeff_table, coeff_table_mode, coeff_table_size, coeff_table_shift; + int8_t screen_over_process; + uint8_t vcnt_shift, hcnt_shift; + uint8_t coeff_msb; + uint32_t *coeff_table_base, coeff_table_offset; + int32_t coeff_table_val; + uint32_t address; + uint32_t *line; + rgb_t pix; + //uint32_t coeff_line_color_screen_data; + int32_t clipxmask = 0, clipymask = 0; + + + vcnt_shift = ((STV_VDP2_LSMD & 3) == 3); + hcnt_shift = ((STV_VDP2_HRES & 2) == 2); + + planesizex--; + planesizey--; + planerenderedsizex--; + planerenderedsizey--; + + kx = RP.kx; + ky = RP.ky; + + use_coeff_table = coeff_table_mode = coeff_table_size = coeff_table_shift = 0; + coeff_table_offset = 0; + coeff_table_val = 0; + coeff_table_base = nullptr; + + if ( LOG_ROZ == 1 ) logerror( "Rendering RBG with parameter %s\n", iRP == 1 ? "A" : "B" ); + if ( LOG_ROZ == 1 ) logerror( "RPMD (parameter mode) = %x\n", STV_VDP2_RPMD ); + if ( LOG_ROZ == 1 ) logerror( "RPRCTL (parameter read control) = %04x\n", STV_VDP2_RPRCTL ); + if ( LOG_ROZ == 1 ) logerror( "KTCTL (coefficient table control) = %04x\n", STV_VDP2_KTCTL ); + if ( LOG_ROZ == 1 ) logerror( "KTAOF (coefficient table address offset) = %04x\n", STV_VDP2_KTAOF ); + if ( LOG_ROZ == 1 ) logerror( "RAOVR (screen-over process) = %x\n", STV_VDP2_RAOVR ); + if ( iRP == 1 ) + { + use_coeff_table = STV_VDP2_RAKTE; + if ( use_coeff_table == 1 ) + { + coeff_table_mode = STV_VDP2_RAKMD; + coeff_table_size = STV_VDP2_RAKDBS; + coeff_table_offset = STV_VDP2_RAKTAOS; + } + screen_over_process = STV_VDP2_RAOVR; + } + else + { + use_coeff_table = STV_VDP2_RBKTE; + if ( use_coeff_table == 1 ) + { + coeff_table_mode = STV_VDP2_RBKMD; + coeff_table_size = STV_VDP2_RBKDBS; + coeff_table_offset = STV_VDP2_RBKTAOS; + } + screen_over_process = STV_VDP2_RBOVR; + } + if ( use_coeff_table ) + { + if ( STV_VDP2_CRKTE == 0 ) + { + coeff_table_base = m_vdp2_vram.get(); + } + else + { + coeff_table_base = m_vdp2_cram.get(); + } + if ( coeff_table_size == 0 ) + { + coeff_table_offset = (coeff_table_offset & 0x0003) * 0x40000; + coeff_table_shift = 2; + } + else + { + coeff_table_offset = (coeff_table_offset & 0x0007) * 0x20000; + coeff_table_shift = 1; + } + } + + if ( stv2_current_tilemap.colour_calculation_enabled == 1 ) + { + if ( STV_VDP2_CCMD ) + { + stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ADD_BLEND; + } + else + { + stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA; + } + } + + /* clipping */ + switch( screen_over_process ) + { + case 0: + /* repeated */ + clipxmask = clipymask = 0; + break; + case 1: + /* screen over pattern */ + // TODO: not supported, cfr. STV_VDP2_OVPNRA / STV_VDP2_OVPNRB + // D-Xhird uses this on practice stage + clipxmask = ~planesizex; + clipymask = ~planesizey; + break; + case 2: + /* outside display area, scroll screen is transparent */ + clipxmask = ~planesizex; + clipymask = ~planesizey; + break; + case 3: + /* display area is 512x512, outside is transparent */ + clipxmask = ~511; + clipymask = ~511; + break; + } + + //dx = (RP.A * RP.dx) + (RP.B * RP.dy); + //dy = (RP.D * RP.dx) + (RP.E * RP.dy); + dx = mul_fixed32( RP.A, RP.dx ) + mul_fixed32( RP.B, RP.dy ); + dy = mul_fixed32( RP.D, RP.dx ) + mul_fixed32( RP.E, RP.dy ); + + //xp = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx; + //yp = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my; + xp = mul_fixed32( RP.A, RP.px - RP.cx ) + mul_fixed32( RP.B, RP.py - RP.cy ) + mul_fixed32( RP.C, RP.pz - RP.cz ) + RP.cx + RP.mx; + yp = mul_fixed32( RP.D, RP.px - RP.cx ) + mul_fixed32( RP.E, RP.py - RP.cy ) + mul_fixed32( RP.F, RP.pz - RP.cz ) + RP.cy + RP.my; + + for (vcnt = cliprect.top(); vcnt <= cliprect.bottom(); vcnt++ ) + { + /*xsp = RP.A * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) + + RP.B * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) + + RP.C * ( RP.zst - RP.pz); + ysp = RP.D * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) + + RP.E * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) + + RP.F * ( RP.zst - RP.pz );*/ + xsp = mul_fixed32( RP.A, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) + + mul_fixed32( RP.B, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) + + mul_fixed32( RP.C, RP.zst - RP.pz ); + ysp = mul_fixed32( RP.D, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) + + mul_fixed32( RP.E, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) + + mul_fixed32( RP.F, RP.zst - RP.pz ); + //xp = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx; + //yp = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my; + //dx = (RP.A * RP.dx) + (RP.B * RP.dy); + //dy = (RP.D * RP.dx) + (RP.E * RP.dy); + + line = &bitmap.pix(vcnt); + + // TODO: nuke this spaghetti code + if ( !use_coeff_table || RP.dkax == 0 ) + { + if ( use_coeff_table ) + { + switch( coeff_table_size ) + { + case 0: + address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 4; + coeff_table_val = coeff_table_base[ address / 4 ]; + //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24; + coeff_msb = (coeff_table_val & 0x80000000) > 0; + if ( coeff_table_val & 0x00800000 ) + { + coeff_table_val |= 0xff000000; + } + else + { + coeff_table_val &= 0x007fffff; + } + break; + case 1: + address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 2; + coeff_table_val = coeff_table_base[ address / 4 ]; + if ( (address & 2) == 0 ) + { + coeff_table_val >>= 16; + } + coeff_table_val &= 0xffff; + //coeff_line_color_screen_data = 0; + coeff_msb = (coeff_table_val & 0x8000) > 0; + if ( coeff_table_val & 0x4000 ) + { + coeff_table_val |= 0xffff8000; + } + else + { + coeff_table_val &= 0x3fff; + } + coeff_table_val <<= 6; /* to form 16.16 fixed point val */ + break; + default: + coeff_msb = 1; + break; + } + if ( coeff_msb ) continue; + + switch( coeff_table_mode ) + { + case 0: + kx = ky = coeff_table_val; + break; + case 1: + kx = coeff_table_val; + break; + case 2: + ky = coeff_table_val; + break; + case 3: + xp = coeff_table_val; + break; + } + } + + //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp; + //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp; + xs = mul_fixed32( kx, xsp ) + xp; + ys = mul_fixed32( ky, ysp ) + yp; + dxs = mul_fixed32( kx, mul_fixed32( dx, 1 << (16-hcnt_shift))); + dys = mul_fixed32( ky, mul_fixed32( dy, 1 << (16-hcnt_shift))); + + for (hcnt = cliprect.left(); hcnt <= cliprect.right(); xs+=dxs, ys+=dys, hcnt++ ) + { + x = xs >> 16; + y = ys >> 16; + + if ( x & clipxmask || y & clipymask ) continue; + if ( stv_vdp2_roz_window(hcnt, vcnt) == false ) + continue; + + if ( stv2_current_tilemap.roz_mode3 == true ) + { + if( stv_vdp2_roz_mode3_window(hcnt, vcnt, iRP-1) == false ) + continue; + } + + pix = roz_bitmap.pix(y & planerenderedsizey, x & planerenderedsizex); + if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) + { + if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) + { + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); + + line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha ); + } + } + else if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND) + { + if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) + { + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); + + line[hcnt] = add_blend_r32( line[hcnt], pix ); + } + } + else + { + if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) + { + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); + + line[hcnt] = pix; + } + } + } + } + else + { + for (hcnt = cliprect.left(); hcnt <= cliprect.right(); hcnt++ ) + { + switch( coeff_table_size ) + { + case 0: + address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 4; + coeff_table_val = coeff_table_base[ address / 4 ]; + //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24; + coeff_msb = (coeff_table_val & 0x80000000) > 0; + if ( coeff_table_val & 0x00800000 ) + { + coeff_table_val |= 0xff000000; + } + else + { + coeff_table_val &= 0x007fffff; + } + break; + case 1: + address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 2; + coeff_table_val = coeff_table_base[ address / 4 ]; + if ( (address & 2) == 0 ) + { + coeff_table_val >>= 16; + } + coeff_table_val &= 0xffff; + //coeff_line_color_screen_data = 0; + coeff_msb = (coeff_table_val & 0x8000) > 0; + if ( coeff_table_val & 0x4000 ) + { + coeff_table_val |= 0xffff8000; + } + else + { + coeff_table_val &= 0x3fff; + } + coeff_table_val <<= 6; /* to form 16.16 fixed point val */ + break; + default: + coeff_msb = 1; + break; + } + if ( coeff_msb ) continue; + switch( coeff_table_mode ) + { + case 0: + kx = ky = coeff_table_val; + break; + case 1: + kx = coeff_table_val; + break; + case 2: + ky = coeff_table_val; + break; + case 3: + xp = coeff_table_val; + break; + } + + //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp; + //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp; + x = mul_fixed32( kx, xsp + mul_fixed32( dx, (hcnt>>hcnt_shift) << 16 ) ) + xp; + y = mul_fixed32( ky, ysp + mul_fixed32( dy, (hcnt>>hcnt_shift) << 16 ) ) + yp; + + x >>= 16; + y >>= 16; + + if ( x & clipxmask || y & clipymask ) continue; + + pix = roz_bitmap.pix(y & planerenderedsizey, x & planerenderedsizex); + if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ALPHA) + { + if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) + { + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); + + line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha ); + } + } + else if (stv2_current_tilemap.transparency & STV_TRANSPARENCY_ADD_BLEND) + { + if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) + { + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); + + line[hcnt] = add_blend_r32( line[hcnt], pix ); + } + } + else + { + if ((stv2_current_tilemap.transparency & STV_TRANSPARENCY_NONE) || (pix & 0xffffff)) + { + if(stv2_current_tilemap.fade_control & 1) + stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2); + + line[hcnt] = pix; + } + } + } + } + } +} + +inline bool saturn_state::stv_vdp2_roz_window(int x, int y) +{ + int s_x=0,e_x=0,s_y=0,e_y=0; + int w0_pix, w1_pix; + uint8_t logic = STV_VDP2_R0LOG; + uint8_t w0_enable = STV_VDP2_R0W0E; + uint8_t w1_enable = STV_VDP2_R0W1E; + uint8_t w0_area = STV_VDP2_R0W0A; + uint8_t w1_area = STV_VDP2_R0W1A; + + if (w0_enable == 0 && + w1_enable == 0) + return true; + + stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y); + w0_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w0_enable, w0_area); + + stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y); + w1_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w1_enable, w1_area); + + return (logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix)); +} + +inline bool saturn_state::stv_vdp2_roz_mode3_window(int x, int y, int rot_parameter) +{ + int s_x=0,e_x=0,s_y=0,e_y=0; + int w0_pix, w1_pix; + uint8_t logic = STV_VDP2_RPLOG; + uint8_t w0_enable = STV_VDP2_RPW0E; + uint8_t w1_enable = STV_VDP2_RPW1E; + uint8_t w0_area = STV_VDP2_RPW0A; + uint8_t w1_area = STV_VDP2_RPW1A; + + if (w0_enable == 0 && + w1_enable == 0) + return rot_parameter ^ 1; + + stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y); + w0_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w0_enable, w0_area); + + stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y); + w1_pix = get_roz_window_pixel(s_x,e_x,s_y,e_y,x,y,w1_enable, w1_area); + + return (logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix)) ^ rot_parameter; +} + +inline int saturn_state::get_roz_window_pixel(int s_x,int e_x,int s_y,int e_y,int x, int y,uint8_t winenable, uint8_t winarea) +{ + int res; + + res = 1; + if(winenable) + { + if(winarea) + res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x); + else + res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x) ^ 1; + } + + return res; +} + + +void saturn_state::stv_vdp2_draw_NBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + uint32_t base_mask; + + base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; + + /* + Colours : 16, 256, 2048, 32768, 16770000 + Char Size : 1x1 cells, 2x2 cells + Pattern Data Size : 1 word, 2 words + Plane Layouts : 1 x 1, 2 x 1, 2 x 2 + Planes : 4 + Bitmap : Possible + Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512 + Scale : 0.25 x - 256 x + Rotation : No + Linescroll : Yes + Column Scroll : Yes + Mosaic : Yes + */ + + stv2_current_tilemap.enabled = STV_VDP2_N0ON | STV_VDP2_R1ON; + +// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... + + //stv2_current_tilemap.trans_enabled = STV_VDP2_N0TPON; + if ( STV_VDP2_N0CCEN ) + { + stv2_current_tilemap.colour_calculation_enabled = 1; + stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N0CCRT)*0xff)/0x1f; + } + else + { + stv2_current_tilemap.colour_calculation_enabled = 0; + } + if ( STV_VDP2_N0TPON == 0 ) + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; + } + else + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; + } + stv2_current_tilemap.colour_depth = STV_VDP2_N0CHCN; + stv2_current_tilemap.tile_size = STV_VDP2_N0CHSZ; + stv2_current_tilemap.bitmap_enable = STV_VDP2_N0BMEN; + stv2_current_tilemap.bitmap_size = STV_VDP2_N0BMSZ; + stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N0BMP; + stv2_current_tilemap.bitmap_map = STV_VDP2_N0MP_; + stv2_current_tilemap.map_offset[0] = STV_VDP2_N0MPA | (STV_VDP2_N0MP_ << 6); + stv2_current_tilemap.map_offset[1] = STV_VDP2_N0MPB | (STV_VDP2_N0MP_ << 6); + stv2_current_tilemap.map_offset[2] = STV_VDP2_N0MPC | (STV_VDP2_N0MP_ << 6); + stv2_current_tilemap.map_offset[3] = STV_VDP2_N0MPD | (STV_VDP2_N0MP_ << 6); + stv2_current_tilemap.map_count = 4; + + stv2_current_tilemap.pattern_data_size = STV_VDP2_N0PNB; + stv2_current_tilemap.character_number_supplement = STV_VDP2_N0CNSM; + stv2_current_tilemap.special_priority_register = STV_VDP2_N0SPR; + stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN0; + stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N0SPLT; + stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N0SPCN; + + stv2_current_tilemap.scrollx = STV_VDP2_SCXIN0; + stv2_current_tilemap.scrolly = STV_VDP2_SCYIN0; + stv2_current_tilemap.incx = STV_VDP2_ZMXN0; + stv2_current_tilemap.incy = STV_VDP2_ZMYN0; + + stv2_current_tilemap.linescroll_enable = STV_VDP2_N0LSCX; + stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N0LSS); + stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA0U << 16) | STV_VDP2_LSTA0L) & base_mask) * 2; + stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N0LSCY; + stv2_current_tilemap.linezoom_enable = STV_VDP2_N0LZMX; + stv2_current_tilemap.vertical_cell_scroll_enable = STV_VDP2_N0VCSC; + + stv2_current_tilemap.plane_size = (STV_VDP2_R1ON) ? STV_VDP2_RBPLSZ : STV_VDP2_N0PLSZ; + stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N0CAOS; + stv2_current_tilemap.fade_control = (STV_VDP2_N0COEN * 1) | (STV_VDP2_N0COSL * 2); + stv_vdp2_check_fade_control_for_layer(); + stv2_current_tilemap.window_control.logic = STV_VDP2_N0LOG; + stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N0W0E; + stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N0W1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_N0SWE; + stv2_current_tilemap.window_control.area[0] = STV_VDP2_N0W0A; + stv2_current_tilemap.window_control.area[1] = STV_VDP2_N0W1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_N0SWA; + + stv2_current_tilemap.line_screen_enabled = STV_VDP2_N0LCEN; + stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N0MZE; + + stv2_current_tilemap.layer_name=(STV_VDP2_R1ON) ? 0x81 : 0; + + if ( stv2_current_tilemap.enabled && (!(STV_VDP2_R1ON))) /* TODO: check cycle pattern for RBG1 */ + { + stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG0_PNMDR, STV_VDP2_CP_NBG0_CPDR, stv2_current_tilemap.bitmap_enable ); + } + + if(STV_VDP2_R1ON) + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); + else + stv_vdp2_check_tilemap(bitmap, cliprect); +} + +void saturn_state::stv_vdp2_draw_NBG1(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + uint32_t base_mask; + + base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; + + /* + Colours : 16, 256, 2048, 32768 + Char Size : 1x1 cells, 2x2 cells + Pattern Data Size : 1 word, 2 words + Plane Layouts : 1 x 1, 2 x 1, 2 x 2 + Planes : 4 + Bitmap : Possible + Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512 + Scale : 0.25 x - 256 x + Rotation : No + Linescroll : Yes + Column Scroll : Yes + Mosaic : Yes + */ + stv2_current_tilemap.enabled = STV_VDP2_N1ON; + +// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... + + //stv2_current_tilemap.trans_enabled = STV_VDP2_N1TPON; + if ( STV_VDP2_N1CCEN ) + { + stv2_current_tilemap.colour_calculation_enabled = 1; + stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N1CCRT)*0xff)/0x1f; + } + else + { + stv2_current_tilemap.colour_calculation_enabled = 0; + } + if ( STV_VDP2_N1TPON == 0 ) + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; + } + else + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; + } + stv2_current_tilemap.colour_depth = STV_VDP2_N1CHCN; + stv2_current_tilemap.tile_size = STV_VDP2_N1CHSZ; + stv2_current_tilemap.bitmap_enable = STV_VDP2_N1BMEN; + stv2_current_tilemap.bitmap_size = STV_VDP2_N1BMSZ; + stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N1BMP; + stv2_current_tilemap.bitmap_map = STV_VDP2_N1MP_; + stv2_current_tilemap.map_offset[0] = STV_VDP2_N1MPA | (STV_VDP2_N1MP_ << 6); + stv2_current_tilemap.map_offset[1] = STV_VDP2_N1MPB | (STV_VDP2_N1MP_ << 6); + stv2_current_tilemap.map_offset[2] = STV_VDP2_N1MPC | (STV_VDP2_N1MP_ << 6); + stv2_current_tilemap.map_offset[3] = STV_VDP2_N1MPD | (STV_VDP2_N1MP_ << 6); + stv2_current_tilemap.map_count = 4; + + stv2_current_tilemap.pattern_data_size = STV_VDP2_N1PNB; + stv2_current_tilemap.character_number_supplement = STV_VDP2_N1CNSM; + stv2_current_tilemap.special_priority_register = STV_VDP2_N1SPR; + stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN1; + stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N1SPLT; + stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N1SPCN; + + stv2_current_tilemap.scrollx = STV_VDP2_SCXIN1; + stv2_current_tilemap.scrolly = STV_VDP2_SCYIN1; + stv2_current_tilemap.incx = STV_VDP2_ZMXN1; + stv2_current_tilemap.incy = STV_VDP2_ZMYN1; + + stv2_current_tilemap.linescroll_enable = STV_VDP2_N1LSCX; + stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N1LSS); + stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA1U << 16) | STV_VDP2_LSTA1L) & base_mask) * 2; + stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N1LSCY; + stv2_current_tilemap.linezoom_enable = STV_VDP2_N1LZMX; + stv2_current_tilemap.vertical_cell_scroll_enable = STV_VDP2_N1VCSC; + + stv2_current_tilemap.plane_size = STV_VDP2_N1PLSZ; + stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N1CAOS; + stv2_current_tilemap.fade_control = (STV_VDP2_N1COEN * 1) | (STV_VDP2_N1COSL * 2); + stv_vdp2_check_fade_control_for_layer(); + stv2_current_tilemap.window_control.logic = STV_VDP2_N1LOG; + stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N1W0E; + stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N1W1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_N1SWE; + stv2_current_tilemap.window_control.area[0] = STV_VDP2_N1W0A; + stv2_current_tilemap.window_control.area[1] = STV_VDP2_N1W1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_N1SWA; + + stv2_current_tilemap.line_screen_enabled = STV_VDP2_N1LCEN; + stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N1MZE; + + stv2_current_tilemap.layer_name=1; + + if ( stv2_current_tilemap.enabled ) + { + stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG1_PNMDR, STV_VDP2_CP_NBG1_CPDR, stv2_current_tilemap.bitmap_enable ); + } + + stv_vdp2_check_tilemap(bitmap, cliprect); +} + +void saturn_state::stv_vdp2_draw_NBG2(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + /* + NBG2 is the first of the 2 more basic tilemaps, it has exactly the same capabilities as NBG3 + + Colours : 16, 256 + Char Size : 1x1 cells, 2x2 cells + Pattern Data Size : 1 word, 2 words + Plane Layouts : 1 x 1, 2 x 1, 2 x 2 + Planes : 4 + Bitmap : No + Bitmap Sizes : N/A + Scale : No + Rotation : No + Linescroll : No + Column Scroll : No + Mosaic : Yes + */ + + stv2_current_tilemap.enabled = STV_VDP2_N2ON; + + /* these modes for N0 disable this layer */ + if (STV_VDP2_N0CHCN == 0x03) stv2_current_tilemap.enabled = 0; + if (STV_VDP2_N0CHCN == 0x04) stv2_current_tilemap.enabled = 0; + +// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... + + //stv2_current_tilemap.trans_enabled = STV_VDP2_N2TPON; + if ( STV_VDP2_N2CCEN ) + { + stv2_current_tilemap.colour_calculation_enabled = 1; + stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N2CCRT)*0xff)/0x1f; + } + else + { + stv2_current_tilemap.colour_calculation_enabled = 0; + } + if ( STV_VDP2_N2TPON == 0 ) + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; + } + else + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; + } + stv2_current_tilemap.colour_depth = STV_VDP2_N2CHCN; + stv2_current_tilemap.tile_size = STV_VDP2_N2CHSZ; + /* this layer can't be a bitmap,so ignore these registers*/ + stv2_current_tilemap.bitmap_enable = 0; + stv2_current_tilemap.bitmap_size = 0; + stv2_current_tilemap.bitmap_palette_number = 0; + stv2_current_tilemap.bitmap_map = 0; + stv2_current_tilemap.map_offset[0] = STV_VDP2_N2MPA | (STV_VDP2_N2MP_ << 6); + stv2_current_tilemap.map_offset[1] = STV_VDP2_N2MPB | (STV_VDP2_N2MP_ << 6); + stv2_current_tilemap.map_offset[2] = STV_VDP2_N2MPC | (STV_VDP2_N2MP_ << 6); + stv2_current_tilemap.map_offset[3] = STV_VDP2_N2MPD | (STV_VDP2_N2MP_ << 6); + stv2_current_tilemap.map_count = 4; + + stv2_current_tilemap.pattern_data_size = STV_VDP2_N2PNB; + stv2_current_tilemap.character_number_supplement = STV_VDP2_N2CNSM; + stv2_current_tilemap.special_priority_register = STV_VDP2_N2SPR; + stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN2; + stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N2SPLT; + stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N2SPCN; + + stv2_current_tilemap.scrollx = STV_VDP2_SCXN2; + stv2_current_tilemap.scrolly = STV_VDP2_SCYN2; + /*This layer can't be scaled*/ + stv2_current_tilemap.incx = 0x10000; + stv2_current_tilemap.incy = 0x10000; + + stv2_current_tilemap.linescroll_enable = 0; + stv2_current_tilemap.linescroll_interval = 0; + stv2_current_tilemap.linescroll_table_address = 0; + stv2_current_tilemap.vertical_linescroll_enable = 0; + stv2_current_tilemap.linezoom_enable = 0; + stv2_current_tilemap.vertical_cell_scroll_enable = 0; + + stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N2CAOS; + stv2_current_tilemap.fade_control = (STV_VDP2_N2COEN * 1) | (STV_VDP2_N2COSL * 2); + stv_vdp2_check_fade_control_for_layer(); + stv2_current_tilemap.window_control.logic = STV_VDP2_N2LOG; + stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N2W0E; + stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N2W1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_N2SWE; + stv2_current_tilemap.window_control.area[0] = STV_VDP2_N2W0A; + stv2_current_tilemap.window_control.area[1] = STV_VDP2_N2W1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_N2SWA; + + stv2_current_tilemap.line_screen_enabled = STV_VDP2_N2LCEN; + stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N2MZE; + + stv2_current_tilemap.layer_name=2; + + stv2_current_tilemap.plane_size = STV_VDP2_N2PLSZ; + + if ( stv2_current_tilemap.enabled ) + { + stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG2_PNMDR, STV_VDP2_CP_NBG2_CPDR, stv2_current_tilemap.bitmap_enable ); + } + + stv_vdp2_check_tilemap(bitmap, cliprect); +} + +void saturn_state::stv_vdp2_draw_NBG3(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + /* + NBG3 is the second of the 2 more basic tilemaps, it has exactly the same capabilities as NBG2 + + Colours : 16, 256 + Char Size : 1x1 cells, 2x2 cells + Pattern Data Size : 1 word, 2 words + Plane Layouts : 1 x 1, 2 x 1, 2 x 2 + Planes : 4 + Bitmap : No + Bitmap Sizes : N/A + Scale : No + Rotation : No + Linescroll : No + Column Scroll : No + Mosaic : Yes + */ + + stv2_current_tilemap.enabled = STV_VDP2_N3ON; + +// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... + + /* these modes for N1 disable this layer */ + if (STV_VDP2_N1CHCN == 0x03) stv2_current_tilemap.enabled = 0; + if (STV_VDP2_N1CHCN == 0x04) stv2_current_tilemap.enabled = 0; + + //stv2_current_tilemap.trans_enabled = STV_VDP2_N3TPON; + if ( STV_VDP2_N3CCEN ) + { + stv2_current_tilemap.colour_calculation_enabled = 1; + stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_N3CCRT)*0xff)/0x1f; + } + else + { + stv2_current_tilemap.colour_calculation_enabled = 0; + } + if ( STV_VDP2_N3TPON == 0 ) + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; + } + else + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; + } + stv2_current_tilemap.colour_depth = STV_VDP2_N3CHCN; + stv2_current_tilemap.tile_size = STV_VDP2_N3CHSZ; + /* this layer can't be a bitmap,so ignore these registers*/ + stv2_current_tilemap.bitmap_enable = 0; + stv2_current_tilemap.bitmap_size = 0; + stv2_current_tilemap.bitmap_palette_number = 0; + stv2_current_tilemap.bitmap_map = 0; + stv2_current_tilemap.map_offset[0] = STV_VDP2_N3MPA | (STV_VDP2_N3MP_ << 6); + stv2_current_tilemap.map_offset[1] = STV_VDP2_N3MPB | (STV_VDP2_N3MP_ << 6); + stv2_current_tilemap.map_offset[2] = STV_VDP2_N3MPC | (STV_VDP2_N3MP_ << 6); + stv2_current_tilemap.map_offset[3] = STV_VDP2_N3MPD | (STV_VDP2_N3MP_ << 6); + stv2_current_tilemap.map_count = 4; + + stv2_current_tilemap.pattern_data_size = STV_VDP2_N3PNB; + stv2_current_tilemap.character_number_supplement = STV_VDP2_N3CNSM; + stv2_current_tilemap.special_priority_register = STV_VDP2_N3SPR; + stv2_current_tilemap.special_colour_control_register = STV_VDP2_N3SCC; + stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N3SPLT; + stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N3SPCN; + + stv2_current_tilemap.scrollx = STV_VDP2_SCXN3; + stv2_current_tilemap.scrolly = STV_VDP2_SCYN3; + /*This layer can't be scaled*/ + stv2_current_tilemap.incx = 0x10000; + stv2_current_tilemap.incy = 0x10000; + + stv2_current_tilemap.linescroll_enable = 0; + stv2_current_tilemap.linescroll_interval = 0; + stv2_current_tilemap.linescroll_table_address = 0; + stv2_current_tilemap.vertical_linescroll_enable = 0; + stv2_current_tilemap.linezoom_enable = 0; + stv2_current_tilemap.vertical_cell_scroll_enable = 0; + + stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N3CAOS; + stv2_current_tilemap.fade_control = (STV_VDP2_N3COEN * 1) | (STV_VDP2_N3COSL * 2); + stv_vdp2_check_fade_control_for_layer(); + stv2_current_tilemap.window_control.logic = STV_VDP2_N3LOG; + stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_N3W0E; + stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_N3W1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_N3SWE; + stv2_current_tilemap.window_control.area[0] = STV_VDP2_N3W0A; + stv2_current_tilemap.window_control.area[1] = STV_VDP2_N3W1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_N3SWA; + + stv2_current_tilemap.line_screen_enabled = STV_VDP2_N3LCEN; + stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N3MZE; + + stv2_current_tilemap.layer_name=3; + + stv2_current_tilemap.plane_size = STV_VDP2_N3PLSZ; + + if ( stv2_current_tilemap.enabled ) + { + stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG3_PNMDR, STV_VDP2_CP_NBG3_CPDR, stv2_current_tilemap.bitmap_enable ); + } + + stv_vdp2_check_tilemap(bitmap, cliprect); +} + + +void saturn_state::stv_vdp2_draw_rotation_screen(bitmap_rgb32 &bitmap, const rectangle &cliprect, int iRP) +{ + rectangle roz_clip_rect; + int planesizex = 0, planesizey = 0; + int planerenderedsizex, planerenderedsizey; + uint8_t colour_calculation_enabled; + uint8_t fade_control; + + if ( iRP == 1) + { + stv2_current_tilemap.bitmap_map = STV_VDP2_RAMP_; + stv2_current_tilemap.map_offset[0] = STV_VDP2_RAMPA | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[1] = STV_VDP2_RAMPB | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[2] = STV_VDP2_RAMPC | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[3] = STV_VDP2_RAMPD | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[4] = STV_VDP2_RAMPE | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[5] = STV_VDP2_RAMPF | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[6] = STV_VDP2_RAMPG | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[7] = STV_VDP2_RAMPH | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[8] = STV_VDP2_RAMPI | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[9] = STV_VDP2_RAMPJ | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[10] = STV_VDP2_RAMPK | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[11] = STV_VDP2_RAMPL | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[12] = STV_VDP2_RAMPM | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[13] = STV_VDP2_RAMPN | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[14] = STV_VDP2_RAMPO | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_offset[15] = STV_VDP2_RAMPP | (STV_VDP2_RAMP_ << 6); + stv2_current_tilemap.map_count = 16; + } + else + { + stv2_current_tilemap.bitmap_map = STV_VDP2_RBMP_; + stv2_current_tilemap.map_offset[0] = STV_VDP2_RBMPA | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[1] = STV_VDP2_RBMPB | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[2] = STV_VDP2_RBMPC | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[3] = STV_VDP2_RBMPD | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[4] = STV_VDP2_RBMPE | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[5] = STV_VDP2_RBMPF | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[6] = STV_VDP2_RBMPG | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[7] = STV_VDP2_RBMPH | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[8] = STV_VDP2_RBMPI | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[9] = STV_VDP2_RBMPJ | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[10] = STV_VDP2_RBMPK | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[11] = STV_VDP2_RBMPL | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[12] = STV_VDP2_RBMPM | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[13] = STV_VDP2_RBMPN | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[14] = STV_VDP2_RBMPO | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_offset[15] = STV_VDP2_RBMPP | (STV_VDP2_RBMP_ << 6); + stv2_current_tilemap.map_count = 16; + } + + stv_vdp2_fill_rotation_parameter_table(iRP); + + if ( iRP == 1 ) + { + stv2_current_tilemap.plane_size = STV_VDP2_RAPLSZ; + } + else + { + stv2_current_tilemap.plane_size = STV_VDP2_RBPLSZ; + } + + if (stv2_current_tilemap.bitmap_enable) + { + switch (stv2_current_tilemap.bitmap_size) + { + case 0: planesizex=512; planesizey=256; break; + case 1: planesizex=512; planesizey=512; break; + case 2: planesizex=1024; planesizey=256; break; + case 3: planesizex=1024; planesizey=512; break; + } + } + else + { + switch( stv2_current_tilemap.plane_size ) + { + case 0: + planesizex = planesizey = 2048; + break; + case 1: + planesizex = 4096; + planesizey = 2048; + break; + case 2: + planesizex = 0; + planesizey = 0; + break; + case 3: + planesizex = planesizey = 4096; + break; + } + } + + if ( stv_vdp2_is_rotation_applied() == 0 ) + { + stv2_current_tilemap.scrollx = stv_current_rotation_parameter_table.mx >> 16; + stv2_current_tilemap.scrolly = stv_current_rotation_parameter_table.my >> 16; + + if(stv2_current_tilemap.roz_mode3 == true) + { + // TODO: Cotton 2 enables mode 3 without an actual RP window enabled + // Technically you could use split screen effect without rotation applied, + // which will be annoying to emulate with this video structure. + // Let's see if anything will do it ... + if(STV_VDP2_RPW0E || STV_VDP2_RPW1E) + popmessage("ROZ Mode 3 window enabled without zooming, contact MAMEdev!"); + + if(iRP == 2) + return; + } + + // TODO: legacy code, to be removed + stv2_current_tilemap.window_control.logic = STV_VDP2_R0LOG; + stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_R0W0E; + stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_R0W1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWE; + stv2_current_tilemap.window_control.area[0] = STV_VDP2_R0W0A; + stv2_current_tilemap.window_control.area[1] = STV_VDP2_R0W1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWA; + + rectangle mycliprect = cliprect; + + if ( stv2_current_tilemap.window_control.enabled[0] || stv2_current_tilemap.window_control.enabled[1] ) + { + //popmessage("Window control for RBG"); + stv_vdp2_apply_window_on_layer(mycliprect); + stv2_current_tilemap.window_control.enabled[0] = 0; + stv2_current_tilemap.window_control.enabled[1] = 0; + } + + stv_vdp2_check_tilemap(bitmap,mycliprect); + } + else + { + if ( !m_vdp2.roz_bitmap[iRP-1].valid() ) + m_vdp2.roz_bitmap[iRP-1].allocate(4096, 4096); + + roz_clip_rect.min_x = roz_clip_rect.min_y = 0; + if ( (iRP == 1 && STV_VDP2_RAOVR == 3) || + (iRP == 2 && STV_VDP2_RBOVR == 3) ) + { + roz_clip_rect.max_x = roz_clip_rect.max_y = 511; + planerenderedsizex = planerenderedsizey = 512; + } + else if (stv_vdp2_are_map_registers_equal() && + !stv2_current_tilemap.bitmap_enable) + { + roz_clip_rect.max_x = (planesizex / 4) - 1; + roz_clip_rect.max_y = (planesizey / 4) - 1; + planerenderedsizex = planesizex / 4; + planerenderedsizey = planesizey / 4; + } + else + { + roz_clip_rect.max_x = planesizex - 1; + roz_clip_rect.max_y = planesizey - 1; + planerenderedsizex = planesizex; + planerenderedsizey = planesizey; + } + + + colour_calculation_enabled = stv2_current_tilemap.colour_calculation_enabled; + stv2_current_tilemap.colour_calculation_enabled = 0; +// window_control = stv2_current_tilemap.window_control; +// stv2_current_tilemap.window_control = 0; + fade_control = stv2_current_tilemap.fade_control; + stv2_current_tilemap.fade_control = 0; + g_profiler.start(PROFILER_USER1); + if ( LOG_VDP2 ) logerror( "Checking for cached RBG bitmap, cache_dirty = %d, memcmp() = %d\n", stv_rbg_cache_data.is_cache_dirty, memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap))); + if ( (stv_rbg_cache_data.is_cache_dirty & iRP) || + memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap)) != 0 ) + { + m_vdp2.roz_bitmap[iRP-1].fill(m_palette->black_pen(), roz_clip_rect ); + stv_vdp2_check_tilemap(m_vdp2.roz_bitmap[iRP-1], roz_clip_rect); + // prepare cache data + stv_rbg_cache_data.watch_vdp2_vram_writes |= iRP; + stv_rbg_cache_data.is_cache_dirty &= ~iRP; + memcpy(&stv_rbg_cache_data.layer_data[iRP-1], &stv2_current_tilemap, sizeof(stv2_current_tilemap)); + stv_rbg_cache_data.map_offset_min[iRP-1] = stv_vdp2_layer_data_placement.map_offset_min; + stv_rbg_cache_data.map_offset_max[iRP-1] = stv_vdp2_layer_data_placement.map_offset_max; + stv_rbg_cache_data.tile_offset_min[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_min; + stv_rbg_cache_data.tile_offset_max[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_max; + if ( LOG_VDP2 ) logerror( "Cache watch: map = %06X - %06X, tile = %06X - %06X\n", stv_rbg_cache_data.map_offset_min[iRP-1], + stv_rbg_cache_data.map_offset_max[iRP-1], stv_rbg_cache_data.tile_offset_min[iRP-1], stv_rbg_cache_data.tile_offset_max[iRP-1] ); + } + + g_profiler.stop(); + + stv2_current_tilemap.colour_calculation_enabled = colour_calculation_enabled; + if ( colour_calculation_enabled ) + { + stv2_current_tilemap.transparency |= STV_TRANSPARENCY_ALPHA; + } + +#if 0 + // old reference code + mycliprect = cliprect; + + if ( stv2_current_tilemap.window_control.enabled[0] || stv2_current_tilemap.window_control.enabled[1] ) + { + //popmessage("Window control for RBG"); + stv_vdp2_apply_window_on_layer(mycliprect); + stv2_current_tilemap.window_control.enabled[0] = 0; + stv2_current_tilemap.window_control.enabled[1] = 0; + } +#endif + + stv2_current_tilemap.fade_control = fade_control; + + g_profiler.start(PROFILER_USER2); + stv_vdp2_copy_roz_bitmap(bitmap, m_vdp2.roz_bitmap[iRP-1], cliprect, iRP, planesizex, planesizey, planerenderedsizex, planerenderedsizey ); + g_profiler.stop(); + } + +} + +void saturn_state::stv_vdp2_draw_RBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + /* + Colours : 16, 256, 2048, 32768, 16770000 + Char Size : 1x1 cells, 2x2 cells + Pattern Data Size : 1 word, 2 words + Plane Layouts : 1 x 1, 2 x 1, 2 x 2 + Planes : 4 + Bitmap : Possible + Bitmap Sizes : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512 + Scale : 0.25 x - 256 x + Rotation : Yes + Linescroll : Yes + Column Scroll : Yes + Mosaic : Yes + */ + + stv2_current_tilemap.enabled = STV_VDP2_R0ON; + +// if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ... + + //stv2_current_tilemap.trans_enabled = STV_VDP2_R0TPON; + if ( STV_VDP2_R0CCEN ) + { + stv2_current_tilemap.colour_calculation_enabled = 1; + stv2_current_tilemap.alpha = ((uint16_t)(0x1f-STV_VDP2_R0CCRT)*0xff)/0x1f; + } + else + { + stv2_current_tilemap.colour_calculation_enabled = 0; + } + if ( STV_VDP2_R0TPON == 0 ) + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN; + } + else + { + stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE; + } + stv2_current_tilemap.colour_depth = STV_VDP2_R0CHCN; + stv2_current_tilemap.tile_size = STV_VDP2_R0CHSZ; + stv2_current_tilemap.bitmap_enable = STV_VDP2_R0BMEN; + stv2_current_tilemap.bitmap_size = STV_VDP2_R0BMSZ; + stv2_current_tilemap.bitmap_palette_number = STV_VDP2_R0BMP; + + stv2_current_tilemap.pattern_data_size = STV_VDP2_R0PNB; + stv2_current_tilemap.character_number_supplement = STV_VDP2_R0CNSM; + stv2_current_tilemap.special_priority_register = STV_VDP2_R0SPR; + stv2_current_tilemap.special_colour_control_register = STV_VDP2_R0SCC; + stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_R0SPLT; + stv2_current_tilemap.supplementary_character_bits = STV_VDP2_R0SPCN; + + stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_R0CAOS; + stv2_current_tilemap.fade_control = (STV_VDP2_R0COEN * 1) | (STV_VDP2_R0COSL * 2); + stv_vdp2_check_fade_control_for_layer(); + // disable these, we apply them in the roz routines (they were interfering with stv_vdp2_roz_window() ?) + stv2_current_tilemap.window_control.logic = 0; //STV_VDP2_R0LOG; + stv2_current_tilemap.window_control.enabled[0] = 0; //STV_VDP2_R0W0E; + stv2_current_tilemap.window_control.enabled[1] = 0; //STV_VDP2_R0W1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWE; + stv2_current_tilemap.window_control.area[0] = 0; //STV_VDP2_R0W0A; + stv2_current_tilemap.window_control.area[1] = 0; //STV_VDP2_R0W1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_R0SWA; + + stv2_current_tilemap.scrollx = 0; + stv2_current_tilemap.scrolly = 0; + stv2_current_tilemap.incx = 0x10000; + stv2_current_tilemap.incy = 0x10000; + + stv2_current_tilemap.linescroll_enable = 0; + stv2_current_tilemap.linescroll_interval = 0; + stv2_current_tilemap.linescroll_table_address = 0; + stv2_current_tilemap.vertical_linescroll_enable = 0; + stv2_current_tilemap.linezoom_enable = 0; + stv2_current_tilemap.vertical_cell_scroll_enable = 0; + + stv2_current_tilemap.line_screen_enabled = STV_VDP2_R0LCEN; + stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_R0MZE; + + /*Use 0x80 as a normal/rotate switch*/ + stv2_current_tilemap.layer_name=0x80; + + if ( !stv2_current_tilemap.enabled ) return; + + switch(STV_VDP2_RPMD) + { + case 0://Rotation Parameter A + stv2_current_tilemap.roz_mode3 = false; + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 ); + break; + case 1://Rotation Parameter B + //case 2: + stv2_current_tilemap.roz_mode3 = false; + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); + break; + case 2://Rotation Parameter A & B CKTE + stv2_current_tilemap.roz_mode3 = false; + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 ); + break; + case 3://Rotation Parameter A & B Window + stv2_current_tilemap.roz_mode3 = true; + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 ); + stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 ); + break; + } + +} + +void saturn_state::stv_vdp2_draw_back(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + uint8_t const *const gfxdata = m_vdp2.gfx_decode.get(); + + uint8_t interlace = (STV_VDP2_LSMD == 3)+1; + +// popmessage("Back screen %08x %08x %08x",STV_VDP2_BDCLMD,STV_VDP2_BKCLMD,STV_VDP2_BKTA); + + /* draw black if BDCLMD and DISP are cleared */ + if(!(STV_VDP2_BDCLMD) && !(STV_VDP2_DISP)) + bitmap.fill(m_palette->black_pen(), cliprect); + else + { + uint32_t base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; + + for(int y=cliprect.top();y<=cliprect.bottom();y++) + { + uint32_t base_offs = ((STV_VDP2_BKTA ) & base_mask) << 1; + if(STV_VDP2_BKCLMD) + base_offs += ((y / interlace) << 1); + + for(int x=cliprect.left();x<=cliprect.right();x++) + { + uint16_t dot = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1]; + int b = pal5bit((dot & 0x7c00) >> 10); + int g = pal5bit((dot & 0x03e0) >> 5); + int r = pal5bit( dot & 0x001f); + if(STV_VDP2_BKCOEN) + stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_BKCOSL ); + + bitmap.pix(y, x) = rgb_t(r, g, b); + } + } + } +} + +uint32_t saturn_state::saturn_vdp2_vram_r(offs_t offset) +{ + return m_vdp2_vram[offset]; +} + +void saturn_state::saturn_vdp2_vram_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + uint8_t* gfxdata = m_vdp2.gfx_decode.get(); + + COMBINE_DATA(&m_vdp2_vram[offset]); + + data = m_vdp2_vram[offset]; + /* put in gfx region for easy decoding */ + gfxdata[offset*4+0] = (data & 0xff000000) >> 24; + gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16; + gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8; + gfxdata[offset*4+3] = (data & 0x000000ff) >> 0; + + m_gfxdecode->gfx(0)->mark_dirty(offset/8); + m_gfxdecode->gfx(1)->mark_dirty(offset/8); + m_gfxdecode->gfx(2)->mark_dirty(offset/8); + m_gfxdecode->gfx(3)->mark_dirty(offset/8); + + /* 8-bit tiles overlap, so this affects the previous one as well */ + if (offset/8 != 0) + { + m_gfxdecode->gfx(2)->mark_dirty(offset/8 - 1); + m_gfxdecode->gfx(3)->mark_dirty(offset/8 - 1); + } + + if ( stv_rbg_cache_data.watch_vdp2_vram_writes ) + { + if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_A ) + { + if ( (offset >= stv_rbg_cache_data.map_offset_min[0] && + offset < stv_rbg_cache_data.map_offset_max[0]) || + (offset >= stv_rbg_cache_data.tile_offset_min[0] && + offset < stv_rbg_cache_data.tile_offset_max[0]) ) + { + if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 1, write at offset = %06X\n", offset ); + stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_A; + stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_A; + } + } + if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_B ) + { + if ( (offset >= stv_rbg_cache_data.map_offset_min[1] && + offset < stv_rbg_cache_data.map_offset_max[1]) || + (offset >= stv_rbg_cache_data.tile_offset_min[1] && + offset < stv_rbg_cache_data.tile_offset_max[1]) ) + { + if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 2, write at offset = %06X\n", offset ); + stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_B; + stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_B; + } + } + } +} + +uint16_t saturn_state::saturn_vdp2_regs_r(offs_t offset) +{ + switch(offset) + { + case 0x002/2: + { + /* latch h/v signals through HV latch*/ + if(!STV_VDP2_EXLTEN) + { + if(!machine().side_effects_disabled()) + { + m_vdp2.h_count = get_hcounter(); + m_vdp2.v_count = get_vcounter(); + /* latch flag */ + m_vdp2.exltfg |= 1; + } + } + + break; + } + case 0x004/2: + { + /*Screen Status Register*/ + /*VBLANK HBLANK ODD PAL */ + m_vdp2_regs[offset] = (m_vdp2.exltfg<<9) | + (m_vdp2.exsyfg<<8) | + (get_vblank() << 3) | + (get_hblank() << 2) | + (get_odd_bit() << 1) | + (m_vdp2.pal << 0); + + /* vblank bit is always 1 if DISP bit is disabled */ + if(!STV_VDP2_DISP) + m_vdp2_regs[offset] |= 1 << 3; + + /* HV latches clears if this register is read */ + if(!machine().side_effects_disabled()) + { + m_vdp2.exltfg &= ~1; + m_vdp2.exsyfg &= ~1; + } + break; + } + case 0x006/2: + { + m_vdp2_regs[offset] = (STV_VDP2_VRAMSZ << 15) | + ((0 << 0) & 0xf); // VDP2 version + + /* Games basically r/w the entire VDP2 register area when this is tripped. (example: Silhouette Mirage) + Disable log for the time being. */ + //if(!machine().side_effects_disabled()) + // printf("Warning: VDP2 version read\n"); + break; + } + + /* HCNT */ + case 0x008/2: + { + m_vdp2_regs[offset] = (m_vdp2.h_count); + break; + } + + /* VCNT */ + case 0x00a/2: + { + m_vdp2_regs[offset] = (m_vdp2.v_count); + break; + } + + default: + //if(!machine().side_effects_disabled()) + // printf("VDP2: read from register %08x %08x\n",offset*4,mem_mask); + break; + } + + return m_vdp2_regs[offset]; +} + +uint32_t saturn_state::saturn_vdp2_cram_r(offs_t offset) +{ + offset &= (0xfff) >> (2); + return m_vdp2_cram[offset]; +} + + + + +void saturn_state::saturn_vdp2_cram_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + int r,g,b; + uint8_t cmode0; + + cmode0 = (STV_VDP2_CRMD & 3) == 0; + + offset &= (0xfff) >> (2); + COMBINE_DATA(&m_vdp2_cram[offset]); + + switch( STV_VDP2_CRMD ) + { + /*Mode 2/3*/ + case 2: + case 3: + { + //offset &= (0xfff) >> 2; + + b = ((m_vdp2_cram[offset] & 0x00ff0000) >> 16); + g = ((m_vdp2_cram[offset] & 0x0000ff00) >> 8); + r = ((m_vdp2_cram[offset] & 0x000000ff) >> 0); + m_palette->set_pen_color(offset,rgb_t(r,g,b)); + m_palette->set_pen_color(offset^0x400,rgb_t(r,g,b)); + } + break; + /*Mode 0*/ + case 0: + case 1: + { + offset &= (0xfff) >> (cmode0+2); + + b = ((m_vdp2_cram[offset] & 0x00007c00) >> 10); + g = ((m_vdp2_cram[offset] & 0x000003e0) >> 5); + r = ((m_vdp2_cram[offset] & 0x0000001f) >> 0); + m_palette->set_pen_color((offset*2)+1,pal5bit(r),pal5bit(g),pal5bit(b)); + if(cmode0) + m_palette->set_pen_color(((offset*2)+1)^0x400,pal5bit(r),pal5bit(g),pal5bit(b)); + + b = ((m_vdp2_cram[offset] & 0x7c000000) >> 26); + g = ((m_vdp2_cram[offset] & 0x03e00000) >> 21); + r = ((m_vdp2_cram[offset] & 0x001f0000) >> 16); + m_palette->set_pen_color(offset*2,pal5bit(r),pal5bit(g),pal5bit(b)); + if(cmode0) + m_palette->set_pen_color((offset*2)^0x400,pal5bit(r),pal5bit(g),pal5bit(b)); + } + break; + } +} + +void saturn_state::refresh_palette_data( void ) +{ + int r,g,b; + int c_i; + uint8_t bank; + + switch( STV_VDP2_CRMD ) + { + case 2: + case 3: + { + for(c_i=0;c_i<0x400;c_i++) + { + b = ((m_vdp2_cram[c_i] & 0x00ff0000) >> 16); + g = ((m_vdp2_cram[c_i] & 0x0000ff00) >> 8); + r = ((m_vdp2_cram[c_i] & 0x000000ff) >> 0); + m_palette->set_pen_color(c_i,rgb_t(r,g,b)); + m_palette->set_pen_color(c_i+0x400,rgb_t(r,g,b)); + } + } + break; + case 0: + { + for(bank=0;bank<2;bank++) + { + for(c_i=0;c_i<0x400;c_i++) + { + b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10); + g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5); + r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0); + m_palette->set_pen_color((c_i*2)+1+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b)); + b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26); + g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21); + r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16); + m_palette->set_pen_color(c_i*2+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b)); + } + } + } + break; + case 1: + { + for(c_i=0;c_i<0x800;c_i++) + { + b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10); + g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5); + r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0); + m_palette->set_pen_color((c_i*2)+1,pal5bit(r),pal5bit(g),pal5bit(b)); + b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26); + g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21); + r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16); + m_palette->set_pen_color(c_i*2,pal5bit(r),pal5bit(g),pal5bit(b)); + } + } + break; + } +} + +void saturn_state::saturn_vdp2_regs_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_vdp2_regs[offset]); + + if(m_vdp2.old_crmd != STV_VDP2_CRMD) + { + m_vdp2.old_crmd = STV_VDP2_CRMD; + refresh_palette_data(); + } + if(m_vdp2.old_tvmd != STV_VDP2_TVMD) + { + m_vdp2.old_tvmd = STV_VDP2_TVMD; + stv_vdp2_dynamic_res_change(); + } + + if(STV_VDP2_VRAMSZ) + printf("VDP2 sets up 8 Mbit VRAM!\n"); +} + +int saturn_state::get_hblank_duration( void ) +{ + int res; + + res = (STV_VDP2_HRES & 1) ? 455 : 427; + + /* double pump horizontal max res */ + if(STV_VDP2_HRES & 2) + res<<=1; + + return res; +} + +/*some vblank lines measurements (according to Charles MacDonald)*/ +/* TODO: interlace mode "eats" one line, should be 262.5 */ +int saturn_state::get_vblank_duration( void ) +{ + int res; + + res = (m_vdp2.pal) ? 313 : 263; + + /* compensate for interlacing */ + if((STV_VDP2_LSMD & 3) == 3) + res<<=1; + + if(STV_VDP2_HRES & 4) + res = (STV_VDP2_HRES & 1) ? 561 : 525; //Hi-Vision / 31kHz Monitor + + return res; +} + +int saturn_state::get_pixel_clock( void ) +{ + int res,divider; + + res = (m_vdp2.dotsel ? MASTER_CLOCK_352 : MASTER_CLOCK_320).value(); + /* TODO: divider is ALWAYS 8, this thing is just to over-compensate for MAME framework faults ... */ + divider = 8; + + if(STV_VDP2_HRES & 2) + divider>>=1; + + if((STV_VDP2_LSMD & 3) == 3) + divider>>=1; + + if(STV_VDP2_HRES & 4) //TODO + divider>>=1; + + return res/divider; +} + +/* TODO: hblank position and hblank firing doesn't really match HW behaviour. */ +uint8_t saturn_state::get_hblank( void ) +{ + const rectangle &visarea = m_screen->visible_area(); + int cur_h = m_screen->hpos(); + + if (cur_h > visarea.right()) //TODO + return 1; + + return 0; +} + +uint8_t saturn_state::get_vblank( void ) +{ + int cur_v,vblank; + cur_v = m_screen->vpos(); + + vblank = get_vblank_start_position() * get_ystep_count(); + + if (cur_v >= vblank) + return 1; + + return 0; +} + +uint8_t saturn_state::get_odd_bit( void ) +{ + if(STV_VDP2_HRES & 4) //exclusive monitor mode makes this bit to be always 1 + return 1; + +// TODO: seabass explicitly wants this bit to be 0 when screen is disabled from bios to game transition. +// But the documentation claims that "non-interlaced" mode is always 1. +// grdforce tests this bit to be 1 from title screen to gameplay, ditto for finlarch/sasissu/magzun. +// Assume documentation is wrong and actually always flip this bit. + return m_vdp2.odd;//m_screen->frame_number() & 1; +} + +int saturn_state::get_vblank_start_position( void ) +{ + // TODO: test says that second setting happens at 241, might need further investigation ... + // also first one happens at 240, but needs mods in SMPC otherwise we get 2 credits at startup in shanhigw and sokyugrt + // (i.e. make a special screen device that handles this for us) + const int d_vres[4] = { 224, 240, 256, 256 }; + int vres_mask; + int vblank_line; + + vres_mask = (m_vdp2.pal << 1)|1; //PAL uses mask 3, NTSC uses mask 1 + vblank_line = d_vres[STV_VDP2_VRES & vres_mask]; + + return vblank_line; +} + +int saturn_state::get_ystep_count( void ) +{ + int max_y = m_screen->height(); + int y_step; + + y_step = 2; + + if((max_y == 263 && m_vdp2.pal == 0) || (max_y == 313 && m_vdp2.pal == 1)) + y_step = 1; + + return y_step; +} + +/* TODO: these needs to be checked via HW tests! */ +int saturn_state::get_hcounter( void ) +{ + int hcount; + + hcount = m_screen->hpos(); + + switch(STV_VDP2_HRES & 6) + { + /* Normal */ + case 0: + hcount &= 0x1ff; + hcount <<= 1; + break; + /* Hi-Res */ + case 2: + hcount &= 0x3ff; + break; + /* Exclusive Normal*/ + case 4: + hcount &= 0x1ff; + break; + /* Exclusive Hi-Res */ + case 6: + hcount >>= 1; + hcount &= 0x1ff; + break; + } + + return hcount; +} + +int saturn_state::get_vcounter( void ) +{ + int vcount; + + vcount = m_screen->vpos(); + + /* Exclusive Monitor */ + if(STV_VDP2_HRES & 4) + return vcount & 0x3ff; + + /* Double Density Interlace */ + if((STV_VDP2_LSMD & 3) == 3) + return (vcount & ~1) | (m_screen->frame_number() & 1); + + /* docs says << 1, but according to HW tests it's a typo. */ + assert((vcount & 0x1ff) < std::size(true_vcount)); + return (true_vcount[vcount & 0x1ff][STV_VDP2_VRES]); // Non-interlace +} + +void saturn_state::stv_vdp2_state_save_postload( void ) +{ + uint8_t *gfxdata = m_vdp2.gfx_decode.get(); + int offset; + uint32_t data; + + for ( offset = 0; offset < 0x100000/4; offset++ ) + { + data = m_vdp2_vram[offset]; + /* put in gfx region for easy decoding */ + gfxdata[offset*4+0] = (data & 0xff000000) >> 24; + gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16; + gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8; + gfxdata[offset*4+3] = (data & 0x000000ff) >> 0; + + m_gfxdecode->gfx(0)->mark_dirty(offset/8); + m_gfxdecode->gfx(1)->mark_dirty(offset/8); + m_gfxdecode->gfx(2)->mark_dirty(offset/8); + m_gfxdecode->gfx(3)->mark_dirty(offset/8); + + /* 8-bit tiles overlap, so this affects the previous one as well */ + if (offset/8 != 0) + { + m_gfxdecode->gfx(2)->mark_dirty(offset/8 - 1); + m_gfxdecode->gfx(3)->mark_dirty(offset/8 - 1); + } + + } + + memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data)); + stv_rbg_cache_data.is_cache_dirty = 3; + memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement)); + + refresh_palette_data(); +} + +void saturn_state::stv_vdp2_exit ( void ) +{ + m_vdp2.roz_bitmap[0].reset(); + m_vdp2.roz_bitmap[1].reset(); +} + +int saturn_state::stv_vdp2_start ( void ) +{ + machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&saturn_state::stv_vdp2_exit, this)); + + m_vdp2_regs = make_unique_clear(0x040000/2 ); + m_vdp2_vram = make_unique_clear(0x100000/4 ); + m_vdp2_cram = make_unique_clear(0x080000/4 ); + m_vdp2.gfx_decode = std::make_unique(0x100000 ); + +// m_gfxdecode->gfx(0)->granularity()=4; +// m_gfxdecode->gfx(1)->granularity()=4; + + memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data)); + stv_rbg_cache_data.is_cache_dirty = 3; + memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement)); + + save_pointer(NAME(m_vdp2_regs), 0x040000/2); + save_pointer(NAME(m_vdp2_vram), 0x100000/4); + save_pointer(NAME(m_vdp2_cram), 0x080000/4); + machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp2_state_save_postload), this)); + + return 0; +} + +/* maybe we should move this to video/stv.c */ +VIDEO_START_MEMBER(saturn_state,stv_vdp2) +{ + int i; + m_screen->register_screen_bitmap(m_tmpbitmap); + stv_vdp2_start(); + stv_vdp1_start(); + m_vdpdebug_roz = 0; + m_gfxdecode->gfx(0)->set_source(m_vdp2.gfx_decode.get()); + m_gfxdecode->gfx(1)->set_source(m_vdp2.gfx_decode.get()); + m_gfxdecode->gfx(2)->set_source(m_vdp2.gfx_decode.get()); + m_gfxdecode->gfx(3)->set_source(m_vdp2.gfx_decode.get()); + + /* calc V counter offsets */ + /* 224 mode */ + for(i=0;i<263;i++) + { + true_vcount[i][0] = i; + if(i>0xec) + true_vcount[i][0]+=0xf9; + } + + for(i=0;i<263;i++) + { + true_vcount[i][1] = i; + if(i>0xf5) + true_vcount[i][1]+=0xf9; + } + + /* 256 mode, todo */ + for(i=0;i<263;i++) + { + true_vcount[i][2] = i; + true_vcount[i][3] = i; + } +} + +void saturn_state::stv_vdp2_dynamic_res_change( void ) +{ + const int d_vres[4] = { 224, 240, 256, 256 }; + const int d_hres[4] = { 320, 352, 640, 704 }; + int horz_res,vert_res; + int vres_mask; + + // reset odd bit if a dynamic resolution change occurs, seabass ST-V cares! + m_vdp2.odd = 1; + vres_mask = (m_vdp2.pal << 1)|1; //PAL uses mask 3, NTSC uses mask 1 + vert_res = d_vres[STV_VDP2_VRES & vres_mask]; + + if((STV_VDP2_VRES & 3) == 3) + popmessage("Illegal VRES MODE, contact MAMEdev"); + + /*Double-density interlace mode,doubles the vertical res*/ + if((STV_VDP2_LSMD & 3) == 3) { vert_res*=2; } + + horz_res = d_hres[STV_VDP2_HRES & 3]; + /*Exclusive modes,they sets the Vertical Resolution without considering the + VRES register.*/ + if(STV_VDP2_HRES & 4) + vert_res = 480; + + { + int vblank_period,hblank_period; + attoseconds_t refresh; + rectangle visarea(0, horz_res-1, 0, vert_res-1); + + vblank_period = get_vblank_duration(); + hblank_period = get_hblank_duration(); + refresh = HZ_TO_ATTOSECONDS(get_pixel_clock()) * (hblank_period) * vblank_period; + //printf("%d %d %d %d\n",horz_res,vert_res,horz_res+hblank_period,vblank_period); + + m_screen->configure(hblank_period, vblank_period, visarea, refresh ); + } +// m_screen->set_visible_area(0*8, horz_res-1,0*8, vert_res-1); +} + +/*This is for calculating the rgb brightness*/ +/*TODO: Optimize this...*/ +void saturn_state::stv_vdp2_fade_effects( void ) +{ + /* + Note:We have to use temporary storages because palette_get_color must use + variables setted with unsigned int8 + */ + int16_t t_r,t_g,t_b; + uint8_t r,g,b; + rgb_t color; + int i; + //popmessage("%04x %04x",STV_VDP2_CLOFEN,STV_VDP2_CLOFSL); + for(i=0;i<2048;i++) + { + /*Fade A*/ + color = m_palette->pen_color(i); + t_r = (STV_VDP2_COAR & 0x100) ? (color.r() - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + color.r()); + t_g = (STV_VDP2_COAG & 0x100) ? (color.g() - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + color.g()); + t_b = (STV_VDP2_COAB & 0x100) ? (color.b() - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + color.b()); + if(t_r < 0) { t_r = 0; } + if(t_r > 0xff) { t_r = 0xff; } + if(t_g < 0) { t_g = 0; } + if(t_g > 0xff) { t_g = 0xff; } + if(t_b < 0) { t_b = 0; } + if(t_b > 0xff) { t_b = 0xff; } + r = t_r; + g = t_g; + b = t_b; + m_palette->set_pen_color(i+(2048*1),rgb_t(r,g,b)); + + /*Fade B*/ + color = m_palette->pen_color(i); + t_r = (STV_VDP2_COBR & 0x100) ? (color.r() - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + color.r()); + t_g = (STV_VDP2_COBG & 0x100) ? (color.g() - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + color.g()); + t_b = (STV_VDP2_COBB & 0x100) ? (color.b() - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + color.b()); + if(t_r < 0) { t_r = 0; } + if(t_r > 0xff) { t_r = 0xff; } + if(t_g < 0) { t_g = 0; } + if(t_g > 0xff) { t_g = 0xff; } + if(t_b < 0) { t_b = 0; } + if(t_b > 0xff) { t_b = 0xff; } + r = t_r; + g = t_g; + b = t_b; + m_palette->set_pen_color(i+(2048*2),rgb_t(r,g,b)); + } + //popmessage("%04x %04x %04x %04x %04x %04x",STV_VDP2_COAR,STV_VDP2_COAG,STV_VDP2_COAB,STV_VDP2_COBR,STV_VDP2_COBG,STV_VDP2_COBB); +} + +void saturn_state::stv_vdp2_get_window0_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y) +{ + /*W0*/ + switch(STV_VDP2_LSMD & 3) + { + case 0: + case 1: + case 2: + *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0); + *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0); + break; + case 3: + *s_y = ((STV_VDP2_W0SY & 0x7ff) >> 0); + *e_y = ((STV_VDP2_W0EY & 0x7ff) >> 0); + break; + } + // check if line window is enabled + if(STV_VDP2_W0LWE) + { + uint32_t base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; + uint32_t address = (STV_VDP2_W0LWTA & base_mask) * 2; + // double density makes the line window to fetch data every two lines + uint8_t interlace = (STV_VDP2_LSMD == 3); + uint32_t vram_data = m_vdp2_vram[(address >> 2)+(y >> interlace)]; + + *s_x = (vram_data >> 16) & 0x3ff; + *e_x = (vram_data & 0x3ff); + } + else + { + switch(STV_VDP2_HRES & 6) + { + /*Normal*/ + case 0: + *s_x = ((STV_VDP2_W0SX & 0x3fe) >> 1); + *e_x = ((STV_VDP2_W0EX & 0x3fe) >> 1); + break; + /*Hi-Res*/ + case 2: + *s_x = ((STV_VDP2_W0SX & 0x3ff) >> 0); + *e_x = ((STV_VDP2_W0EX & 0x3ff) >> 0); + break; + /*Exclusive Normal*/ + case 4: + *s_x = ((STV_VDP2_W0SX & 0x1ff) >> 0); + *e_x = ((STV_VDP2_W0EX & 0x1ff) >> 0); + *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0); + *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0); + break; + /*Exclusive Hi-Res*/ + case 6: + *s_x = ((STV_VDP2_W0SX & 0x1ff) << 1); + *e_x = ((STV_VDP2_W0EX & 0x1ff) << 1); + *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0); + *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0); + break; + } + } +} + +void saturn_state::stv_vdp2_get_window1_coordinates(int *s_x, int *e_x, int *s_y, int *e_y, int y) +{ + /*W1*/ + switch(STV_VDP2_LSMD & 3) + { + case 0: + case 1: + case 2: + *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0); + *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0); + break; + case 3: + *s_y = ((STV_VDP2_W1SY & 0x7ff) >> 0); + *e_y = ((STV_VDP2_W1EY & 0x7ff) >> 0); + break; + } + // check if line window is enabled + if(STV_VDP2_W1LWE) + { + uint32_t base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff; + uint32_t address = (STV_VDP2_W1LWTA & base_mask) * 2; + // double density makes the line window to fetch data every two lines + uint8_t interlace = (STV_VDP2_LSMD == 3); + uint32_t vram_data = m_vdp2_vram[(address >> 2)+(y >> interlace)]; + + *s_x = (vram_data >> 16) & 0x3ff; + *e_x = (vram_data & 0x3ff); + } + else + { + switch(STV_VDP2_HRES & 6) + { + /*Normal*/ + case 0: + *s_x = ((STV_VDP2_W1SX & 0x3fe) >> 1); + *e_x = ((STV_VDP2_W1EX & 0x3fe) >> 1); + break; + /*Hi-Res*/ + case 2: + *s_x = ((STV_VDP2_W1SX & 0x3ff) >> 0); + *e_x = ((STV_VDP2_W1EX & 0x3ff) >> 0); + break; + /*Exclusive Normal*/ + case 4: + *s_x = ((STV_VDP2_W1SX & 0x1ff) >> 0); + *e_x = ((STV_VDP2_W1EX & 0x1ff) >> 0); + *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0); + *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0); + break; + /*Exclusive Hi-Res*/ + case 6: + *s_x = ((STV_VDP2_W1SX & 0x1ff) << 1); + *e_x = ((STV_VDP2_W1EX & 0x1ff) << 1); + *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0); + *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0); + break; + } + } +} + +int saturn_state::get_window_pixel(int s_x,int e_x,int s_y,int e_y,int x, int y,uint8_t win_num) +{ + int res; + + res = 1; + if(stv2_current_tilemap.window_control.enabled[win_num]) + { + if(stv2_current_tilemap.window_control.area[win_num]) + res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x); + else + res = (y >= s_y && y <= e_y && x >= s_x && x <= e_x) ^ 1; + } + + return res; +} + +inline int saturn_state::stv_vdp2_window_process(int x,int y) +{ + int s_x=0,e_x=0,s_y=0,e_y=0; + int w0_pix, w1_pix; + + if (stv2_current_tilemap.window_control.enabled[0] == 0 && + stv2_current_tilemap.window_control.enabled[1] == 0) + return 1; + + stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, y); + w0_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,0); + + stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, y); + w1_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,1); + + return stv2_current_tilemap.window_control.logic & 1 ? (w0_pix | w1_pix) : (w0_pix & w1_pix); +} + +/* TODO: remove this crap. */ +int saturn_state::stv_vdp2_apply_window_on_layer(rectangle &cliprect) +{ + int s_x=0,e_x=0,s_y=0,e_y=0; + + if ( stv2_current_tilemap.window_control.enabled[0] && (!stv2_current_tilemap.window_control.area[0])) + { + /* w0, transparent outside supported */ + stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y, 0); + + if ( s_x > cliprect.min_x ) cliprect.min_x = s_x; + if ( e_x < cliprect.max_x ) cliprect.max_x = e_x; + if ( s_y > cliprect.min_y ) cliprect.min_y = s_y; + if ( e_y < cliprect.max_y ) cliprect.max_y = e_y; + + return 1; + } + else if ( stv2_current_tilemap.window_control.enabled[1] && (!stv2_current_tilemap.window_control.area[1]) ) + { + /* w1, transparent outside supported */ + stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y, 0); + + if ( s_x > cliprect.min_x ) cliprect.min_x = s_x; + if ( e_x < cliprect.max_x ) cliprect.max_x = e_x; + if ( s_y > cliprect.min_y ) cliprect.min_y = s_y; + if ( e_y < cliprect.max_y ) cliprect.max_y = e_y; + + return 1; + } + else + { + return 0; + } +} + +void saturn_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint8_t pri) +{ + int x,y,r,g,b; + int i; + uint16_t pix; + uint16_t *framebuffer_line; + uint32_t *bitmap_line, *bitmap_line2 = nullptr; + uint8_t interlace_framebuffer; + uint8_t double_x; + static const uint16_t sprite_colormask_table[] = { + 0x07ff, 0x07ff, 0x07ff, 0x07ff, 0x03ff, 0x07ff, 0x03ff, 0x01ff, + 0x007f, 0x003f, 0x003f, 0x003f, 0x00ff, 0x00ff, 0x00ff, 0x00ff + }; + static const uint16_t priority_shift_table[] = { 14, 13, 14, 13, 13, 12, 12, 12, 7, 7, 6, 0, 7, 7, 6, 0 }; + static const uint16_t priority_mask_table[] = { 3, 7, 1, 3, 3, 7, 7, 7, 1, 1, 3, 0, 1, 1, 3, 0 }; + static const uint16_t ccrr_shift_table[] = { 11, 11, 11, 11, 10, 11, 10, 9, 0, 6, 0, 6, 0, 6, 0, 6 }; + static const uint16_t ccrr_mask_table[] = { 7, 3, 7, 3, 7, 1, 3, 7, 0, 1, 0, 3, 0, 1, 0, 3 }; + static const uint16_t shadow_mask_table[] = { 0, 0, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint16_t alpha_enabled; + + int sprite_type; + int sprite_colormask; + int color_offset_pal; + int sprite_shadow; + uint16_t sprite_priority_shift, sprite_priority_mask, sprite_ccrr_shift, sprite_ccrr_mask; + uint8_t priority; + uint8_t ccr = 0; + uint8_t sprite_priorities[8]; + uint8_t sprite_ccr[8]; + int sprite_color_mode = STV_VDP2_SPCLMD; + + if ( (stv_sprite_priorities_usage_valid == 1) && (stv_sprite_priorities_used[pri] == 0) ) + return; + + sprite_priorities[0] = STV_VDP2_S0PRIN; + sprite_priorities[1] = STV_VDP2_S1PRIN; + sprite_priorities[2] = STV_VDP2_S2PRIN; + sprite_priorities[3] = STV_VDP2_S3PRIN; + sprite_priorities[4] = STV_VDP2_S4PRIN; + sprite_priorities[5] = STV_VDP2_S5PRIN; + sprite_priorities[6] = STV_VDP2_S6PRIN; + sprite_priorities[7] = STV_VDP2_S7PRIN; + + sprite_ccr[0] = STV_VDP2_S0CCRT; + sprite_ccr[1] = STV_VDP2_S1CCRT; + sprite_ccr[2] = STV_VDP2_S2CCRT; + sprite_ccr[3] = STV_VDP2_S3CCRT; + sprite_ccr[4] = STV_VDP2_S4CCRT; + sprite_ccr[5] = STV_VDP2_S5CCRT; + sprite_ccr[6] = STV_VDP2_S6CCRT; + sprite_ccr[7] = STV_VDP2_S7CCRT; + + sprite_type = STV_VDP2_SPTYPE; + sprite_colormask = sprite_colormask_table[sprite_type]; + sprite_priority_shift = priority_shift_table[sprite_type]; + sprite_priority_mask = priority_mask_table[sprite_type]; + sprite_ccrr_shift = ccrr_shift_table[sprite_type]; + sprite_ccrr_mask = ccrr_mask_table[sprite_type]; + sprite_shadow = shadow_mask_table[sprite_type]; + + for ( i = 0; i < (sprite_priority_mask+1); i++ ) if ( sprite_priorities[i] == pri ) break; + if ( i == (sprite_priority_mask+1) ) return; + + /* color offset (RGB brightness) */ + color_offset_pal = 0; + if ( STV_VDP2_SPCOEN ) + { + if ( STV_VDP2_SPCOSL == 0 ) + { color_offset_pal = 2048; } + else + { color_offset_pal = 2048*2; } + } + + /* color calculation (alpha blending)*/ + if ( STV_VDP2_SPCCEN ) + { + alpha_enabled = 0; + switch( STV_VDP2_SPCCCS ) + { + case 0x0: if ( pri <= STV_VDP2_SPCCN ) alpha_enabled = 1; break; + case 0x1: if ( pri == STV_VDP2_SPCCN ) alpha_enabled = 1; break; + case 0x2: if ( pri >= STV_VDP2_SPCCN ) alpha_enabled = 1; break; + case 0x3: alpha_enabled = 2; sprite_shadow = 0; break; + } + } + else + { + alpha_enabled = 0; + } + + /* framebuffer interlace */ + if ( (STV_VDP2_LSMD == 3) && m_vdp1.framebuffer_double_interlace == 0 ) + interlace_framebuffer = 1; + else + interlace_framebuffer = 0; + + /*Guess:Some games needs that the horizontal sprite size to be doubled + (TODO: understand the proper settings,it might not work like this)*/ + if(STV_VDP1_TVM == 0 && STV_VDP2_HRES & 2) // astrass & findlove + double_x = 1; + else + double_x = 0; + + /* window control */ + stv2_current_tilemap.window_control.logic = STV_VDP2_SPLOG; + stv2_current_tilemap.window_control.enabled[0] = STV_VDP2_SPW0E; + stv2_current_tilemap.window_control.enabled[1] = STV_VDP2_SPW1E; +// stv2_current_tilemap.window_control.? = STV_VDP2_SPSWE; + stv2_current_tilemap.window_control.area[0] = STV_VDP2_SPW0A; + stv2_current_tilemap.window_control.area[1] = STV_VDP2_SPW1A; +// stv2_current_tilemap.window_control.? = STV_VDP2_SPSWA; + +// stv_vdp2_apply_window_on_layer(mycliprect); + + if (interlace_framebuffer == 0 && double_x == 0 ) + { + if ( alpha_enabled == 0 ) + { + for ( y = cliprect.top(); y <= cliprect.bottom(); y++ ) + { + if ( stv_sprite_priorities_usage_valid ) + if (stv_sprite_priorities_in_fb_line[y][pri] == 0) + continue; + + framebuffer_line = m_vdp1.framebuffer_display_lines[y]; + bitmap_line = &bitmap.pix(y); + + for ( x = cliprect.left(); x <= cliprect.right(); x++ ) + { + if(!stv_vdp2_window_process(x,y)) + continue; + + pix = framebuffer_line[x]; + if ( (pix & 0x8000) && sprite_color_mode) + { + if ( sprite_priorities[0] != pri ) + { + stv_sprite_priorities_used[sprite_priorities[0]] = 1; + stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1; + continue; + }; + + if(STV_VDP2_SPWINEN && pix == 0x8000) /* Pukunpa */ + continue; + + b = pal5bit((pix & 0x7c00) >> 10); + g = pal5bit((pix & 0x03e0) >> 5); + r = pal5bit( pix & 0x001f); + if ( color_offset_pal ) + { + stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL ); + } + + bitmap_line[x] = rgb_t(r, g, b); + } + else + { + priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask]; + if ( priority != pri ) + { + stv_sprite_priorities_used[priority] = 1; + stv_sprite_priorities_in_fb_line[y][priority] = 1; + continue; + }; + + // Pretty Fighter X, Game Tengoku shadows + // TODO: Pretty Fighter X doesn't read what's behind on title screen, VDP1 bug? + // TODO: seldomly Game Tengoku shadows aren't drawn properly + if(pix & 0x8000 && STV_VDP2_SDCTL & 0x100) + { + rgb_t p = bitmap_line[x]; + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + else + { + pix &= sprite_colormask; + if ( pix == (sprite_colormask - 1) ) + { + /*shadow - in reality, we should check from what layer pixel beneath comes...*/ + if ( STV_VDP2_SDCTL & 0x3f ) + { + rgb_t p = bitmap_line[x]; + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + /* note that when shadows are disabled, "shadow" palette entries are not drawn */ + } + else if ( pix ) + { + pix += (STV_VDP2_SPCAOS << 8); + pix &= 0x7ff; + pix += color_offset_pal; + bitmap_line[x] = m_palette->pen( pix ); + + } + } + + /* TODO: I don't think this one makes much sense ... (1) */ + if ( pix & sprite_shadow ) + { + if ( pix & ~sprite_shadow ) + { + rgb_t p = bitmap_line[x]; + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + } + } + } + } + } + else //alpha_enabled == 1 + { + for ( y = cliprect.top(); y <= cliprect.bottom(); y++ ) + { + if ( stv_sprite_priorities_usage_valid ) + if (stv_sprite_priorities_in_fb_line[y][pri] == 0) + continue; + + framebuffer_line = m_vdp1.framebuffer_display_lines[y]; + bitmap_line = &bitmap.pix(y); + + for ( x = cliprect.left(); x <= cliprect.right(); x++ ) + { + if(!stv_vdp2_window_process(x,y)) + continue; + + pix = framebuffer_line[x]; + if ( (pix & 0x8000) && sprite_color_mode) + { + if ( sprite_priorities[0] != pri ) + { + stv_sprite_priorities_used[sprite_priorities[0]] = 1; + stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1; + continue; + }; + + b = pal5bit((pix & 0x7c00) >> 10); + g = pal5bit((pix & 0x03e0) >> 5); + r = pal5bit( pix & 0x001f); + if ( color_offset_pal ) + { + stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL ); + } + ccr = sprite_ccr[0]; + if ( STV_VDP2_CCMD ) + { + bitmap_line[x] = add_blend_r32( bitmap_line[x], rgb_t(r, g, b)); + } + else + { + bitmap_line[x] = alpha_blend_r32( bitmap_line[x], rgb_t(r, g ,b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); + } + } + else + { + priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask]; + if ( priority != pri ) + { + stv_sprite_priorities_used[priority] = 1; + stv_sprite_priorities_in_fb_line[y][priority] = 1; + continue; + }; + + ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ]; + if ( alpha_enabled == 2 ) + { + if ( ( pix & 0x8000 ) == 0 ) + { + ccr = 0; + } + } + + + { + pix &= sprite_colormask; + if ( pix == (sprite_colormask - 1) ) + { + /*shadow - in reality, we should check from what layer pixel beneath comes...*/ + if ( STV_VDP2_SDCTL & 0x3f ) + { + rgb_t p = bitmap_line[x]; + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + /* note that when shadows are disabled, "shadow" palette entries are not drawn */ + } else if ( pix ) + { + pix += (STV_VDP2_SPCAOS << 8); + pix &= 0x7ff; + pix += color_offset_pal; + if ( ccr > 0 ) + { + if ( STV_VDP2_CCMD ) + { + bitmap_line[x] = add_blend_r32( bitmap_line[x], m_palette->pen(pix) ); + } + else + { + bitmap_line[x] = alpha_blend_r32( bitmap_line[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + } + } + else + bitmap_line[x] = m_palette->pen(pix); + } + } + + /* TODO: (1) */ + if ( pix & sprite_shadow ) + { + if ( pix & ~sprite_shadow ) + { + rgb_t p = bitmap_line[x]; + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + } + } + } + } + } + } + else + { + for ( y = cliprect.top(); y <= cliprect.bottom() / (interlace_framebuffer+1); y++ ) + { + if ( stv_sprite_priorities_usage_valid ) + if (stv_sprite_priorities_in_fb_line[y][pri] == 0) + continue; + + framebuffer_line = m_vdp1.framebuffer_display_lines[y]; + if ( interlace_framebuffer == 0 ) + { + bitmap_line = &bitmap.pix(y); + } + else + { + bitmap_line = &bitmap.pix(2*y); + bitmap_line2 = &bitmap.pix(2*y + 1); + } + + for ( x = cliprect.left(); x <= cliprect.right() /(double_x+1) ; x++ ) + { + if(!stv_vdp2_window_process(x,y)) + continue; + + pix = framebuffer_line[x]; + if ( (pix & 0x8000) && sprite_color_mode) + { + if ( sprite_priorities[0] != pri ) + { + stv_sprite_priorities_used[sprite_priorities[0]] = 1; + stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1; + continue; + }; + + b = pal5bit((pix & 0x7c00) >> 10); + g = pal5bit((pix & 0x03e0) >> 5); + r = pal5bit( pix & 0x001f); + if ( color_offset_pal ) + { + stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL ); + } + if ( alpha_enabled == 0 ) + { + if(double_x) + { + bitmap_line[x*2] = rgb_t(r, g, b); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = rgb_t(r, g, b); + bitmap_line[x*2+1] = rgb_t(r, g, b); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = rgb_t(r, g, b); + } + else + { + bitmap_line[x] = rgb_t(r, g, b); + if ( interlace_framebuffer == 1 ) bitmap_line2[x] = rgb_t(r, g, b); + } + } + else // alpha_blend == 1 + { + ccr = sprite_ccr[0]; + + if ( STV_VDP2_CCMD ) + { + if(double_x) + { + bitmap_line[x*2] = add_blend_r32( bitmap_line[x*2], rgb_t(r, g, b) ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = add_blend_r32( bitmap_line2[x*2], rgb_t(r, g, b) ); + bitmap_line[x*2+1] = add_blend_r32( bitmap_line[x*2+1], rgb_t(r, g, b) ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = add_blend_r32( bitmap_line2[x*2+1], rgb_t(r, g, b) ); + } + else + { + bitmap_line[x] = add_blend_r32( bitmap_line[x], rgb_t(r, g, b) ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x] = add_blend_r32( bitmap_line2[x], rgb_t(r, g, b) ); + } + } + else + { + if(double_x) + { + bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x*2], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x*2+1], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); + } + else + { + bitmap_line[x] = alpha_blend_r32( bitmap_line[x], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); + if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], rgb_t(r, g, b), ((uint16_t)(0x1f-ccr)*0xff)/0x1f); + } + } + } + } + else + { + priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask]; + if ( priority != pri ) + { + stv_sprite_priorities_used[priority] = 1; + stv_sprite_priorities_in_fb_line[y][priority] = 1; + continue; + }; + + if ( alpha_enabled ) + ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ]; + + if ( alpha_enabled == 2 ) + { + if ( ( pix & 0x8000 ) == 0 ) + { + ccr = 0; + } + } + + { + pix &= sprite_colormask; + if ( pix == (sprite_colormask - 1) ) + { + /*shadow - in reality, we should check from what layer pixel beneath comes...*/ + if ( STV_VDP2_SDCTL & 0x3f ) + { + rgb_t p = bitmap_line[x]; + if(double_x) + { + p = bitmap_line[x*2]; + bitmap_line[x*2] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + p = bitmap_line[x*2+1]; + bitmap_line[x*2+1] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + else + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + /* note that when shadows are disabled, "shadow" palette entries are not drawn */ + } else if ( pix ) + { + pix += (STV_VDP2_SPCAOS << 8); + pix &= 0x7ff; + pix += color_offset_pal; + if ( alpha_enabled == 0 ) + { + if(double_x) + { + bitmap_line[x*2] = m_palette->pen( pix ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = m_palette->pen( pix ); + bitmap_line[x*2+1] = m_palette->pen( pix ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = m_palette->pen( pix ); + } + else + { + bitmap_line[x] = m_palette->pen( pix ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x] = m_palette->pen( pix ); + } + } + else // alpha_blend == 1 + { + if ( STV_VDP2_CCMD ) + { + if(double_x) + { + bitmap_line[x*2] = add_blend_r32( bitmap_line[x*2], m_palette->pen(pix) ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = add_blend_r32( bitmap_line2[x], m_palette->pen(pix) ); + bitmap_line[x*2+1] = add_blend_r32( bitmap_line[x*2+1], m_palette->pen(pix) ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = add_blend_r32( bitmap_line2[x], m_palette->pen(pix) ); + } + else + { + bitmap_line[x] = add_blend_r32( bitmap_line[x], m_palette->pen(pix) ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x] = add_blend_r32( bitmap_line2[x], m_palette->pen(pix) ); + } + } + else + { + if(double_x) + { + bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + } + else + { + bitmap_line[x] = alpha_blend_r32( bitmap_line[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], m_palette->pen(pix), ((uint16_t)(0x1f-ccr)*0xff)/0x1f ); + } + } + } + } + } + + /* TODO: (1) */ + if ( pix & sprite_shadow ) + { + if ( pix & ~sprite_shadow ) + { + rgb_t p = bitmap_line[x]; + if(double_x) + { + p = bitmap_line[x*2]; + bitmap_line[x*2] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + p = bitmap_line[x*2+1]; + bitmap_line[x*2+1] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + else + bitmap_line[x] = rgb_t(p.r() >> 1, p.g() >> 1, p.b() >> 1); + } + } + } + } + } + } + + stv_sprite_priorities_usage_valid = 1; +} + +uint32_t saturn_state::screen_update_stv_vdp2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + stv_vdp2_fade_effects(); + + stv_vdp2_draw_back(m_tmpbitmap,cliprect); + + if(STV_VDP2_DISP) + { + uint8_t pri; + + stv_sprite_priorities_usage_valid = 0; + memset(stv_sprite_priorities_used, 0, sizeof(stv_sprite_priorities_used)); + memset(stv_sprite_priorities_in_fb_line, 0, sizeof(stv_sprite_priorities_in_fb_line)); + + /*If a plane has a priority value of zero it isn't shown at all.*/ + for(pri=1;pri<8;pri++) + { + if(pri==STV_VDP2_N3PRIN) { stv_vdp2_draw_NBG3(m_tmpbitmap,cliprect); } + if(pri==STV_VDP2_N2PRIN) { stv_vdp2_draw_NBG2(m_tmpbitmap,cliprect); } + if(pri==STV_VDP2_N1PRIN) { stv_vdp2_draw_NBG1(m_tmpbitmap,cliprect); } + if(pri==STV_VDP2_N0PRIN) { stv_vdp2_draw_NBG0(m_tmpbitmap,cliprect); } + if(pri==STV_VDP2_R0PRIN) { stv_vdp2_draw_RBG0(m_tmpbitmap,cliprect); } + { draw_sprites(m_tmpbitmap,cliprect,pri); } + } + } + + copybitmap(bitmap, m_tmpbitmap, 0, 0, 0, 0, cliprect); + + #if 0 + /* Do NOT remove me, used to test video code performance. */ + if(machine().input().code_pressed(KEYCODE_Q)) + { + popmessage("Halt CPUs"); + m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); + m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); + m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); + } + #endif + return 0; +} -- cgit v1.2.3