attempt to emulate the sprite trail effect (partial sprite framebuffer clear etc.) of megasys1, probably not accurate yet

This commit is contained in:
David Haywood 2015-12-13 15:06:58 +00:00
parent 8f28a57176
commit 62a00daa2a
3 changed files with 128 additions and 42 deletions

View File

@ -1499,6 +1499,7 @@ static MACHINE_CONFIG_START( system_A, megasys1_state )
MCFG_SCREEN_UPDATE_DRIVER(megasys1_state, screen_update_megasys1)
MCFG_SCREEN_VBLANK_DRIVER(megasys1_state, screen_eof_megasys1)
MCFG_SCREEN_PALETTE("palette")
MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_ALWAYS_UPDATE)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", ABC)
MCFG_PALETTE_ADD("palette", 1024)
@ -1560,6 +1561,7 @@ static MACHINE_CONFIG_START( system_Bbl, megasys1_state )
MCFG_SCREEN_UPDATE_DRIVER(megasys1_state, screen_update_megasys1)
MCFG_SCREEN_VBLANK_DRIVER(megasys1_state, screen_eof_megasys1)
MCFG_SCREEN_PALETTE("palette")
MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_ALWAYS_UPDATE)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", ABC)
MCFG_PALETTE_ADD("palette", 1024)

View File

@ -39,7 +39,9 @@ public:
m_io_dsw1(*this, "DSW1"),
m_io_dsw2(*this, "DSW2"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette") { }
m_palette(*this, "palette"),
m_screen(*this, "screen")
{ }
required_shared_ptr<UINT16> m_vregs;
required_shared_ptr<UINT16> m_objectram;
@ -58,6 +60,9 @@ public:
optional_ioport m_io_dsw2;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_device<screen_device> m_screen;
bitmap_ind16 m_sprite_buffer_bitmap;
UINT16 *m_spriteram;
UINT16 m_ip_select;
@ -154,6 +159,8 @@ public:
inline void scrollram_w(offs_t offset, UINT16 data, UINT16 mem_mask, int which);
void create_tilemaps();
void megasys1_priority_create();
void mix_sprite_bitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void partial_clear_sprite_bitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, UINT8 param);
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect);
inline void draw_16x16_priority_sprite(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, UINT8 mosaic, UINT8 mosaicsol, INT32 priority);
void rodland_gfx_unmangle(const char *region);

View File

@ -143,13 +143,13 @@ No? No? c2108 Sprite Bank
84100 44100 c2200 Sprite Control
84100 44100 c2200 Sprite Control ( m_sprite_flag )
fedc ba9- ---- ---- ? (unused?)
---- ---8 ---- ---- Enable Sprite Splitting In 2 Groups:
Some Sprite Appear Over, Some Below The Layers
---- ---- 765- ---- ? (unused?)
---- ---- ---4 ---- Enable Effect (?)
---- ---- ---4 ---- Enable Effect (don't clear sprite framebuffer)
---- ---- ---- 3210 Effect Number (?)
I think bit 4 enables some sort of color cycling for sprites having priority
@ -275,6 +275,8 @@ VIDEO_START_MEMBER(megasys1_state,megasys1)
if (strcmp(machine().system().name, "lomakai") == 0 ||
strcmp(machine().system().name, "makaiden") == 0)
m_hardware_type_z = 1;
m_screen->register_screen_bitmap(m_sprite_buffer_bitmap);
}
/***************************************************************************
@ -600,6 +602,57 @@ WRITE16_MEMBER(megasys1_state::megasys1_vregs_D_w)
0C Y position
0E Code */
void megasys1_state::mix_sprite_bitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
gfx_element *decodegfx = m_gfxdecode->gfx(3);
UINT16 colorbase = decodegfx->colorbase();
for (int y = cliprect.min_y;y <= cliprect.max_y;y++)
{
UINT16* srcline = &m_sprite_buffer_bitmap.pix16(y);
UINT16* dstline = &bitmap.pix16(y);
UINT8 *prio = &screen.priority().pix8(y);
for (int x = cliprect.min_x;x <= cliprect.max_x;x++)
{
UINT16 pixel = srcline[x];
if ((pixel & 0xf) != 0xf)
{
int priority = (pixel & 0x4000) >> 14;
priority = (priority) ? 0x0c : 0x0a;
if ((priority & (1 << (prio[x] & 0x1f))) == 0)
{
UINT8 coldat = pixel & 0x3fff;
dstline[x] = coldat + colorbase;
}
}
}
}
}
void megasys1_state::partial_clear_sprite_bitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, UINT8 param)
{
for (int y = cliprect.min_y;y <= cliprect.max_y;y++)
{
UINT16* srcline = &m_sprite_buffer_bitmap.pix16(y);
for (int x = cliprect.min_x;x <= cliprect.max_x;x++)
{
UINT16 pixel = srcline[x];
srcline[x] = pixel & 0x7fff; // wipe our 'drawn here' marker otherwise trails will always have priority over new sprites, which is incorrect.
// guess, very unclear from the video refernece we have, used when removing p47 trails
if (((pixel & 0xf0) >> 4) < param)
srcline[x] = 0x7fff;
}
}
}
inline void megasys1_state::draw_16x16_priority_sprite(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, UINT8 mosaic, UINT8 mosaicsol, INT32 priority)
{
@ -612,14 +665,14 @@ inline void megasys1_state::draw_16x16_priority_sprite(screen_device &screen, bi
flipy = (flipy) ? 0x0f : 0;
flipx = (flipx) ? 0x0f : 0;
color = (color * 16) + decodegfx->colorbase();
color = color * 16;
for (INT32 y = 0; y < 16; y++, sy++, sx-=16)
{
UINT16 *dest = &bitmap.pix16(sy)+ sx;
UINT8 *prio = &screen.priority().pix8(sy) + sx;
// UINT16 *dest = &bitmap.pix16(sy)+ sx;
// UINT8 *prio = &screen.priority().pix8(sy) + sx;
UINT16* dest = &m_sprite_buffer_bitmap.pix16(sy)+ sx;
for (INT32 x = 0; x < 16; x++, sx++)
{
@ -634,9 +687,11 @@ inline void megasys1_state::draw_16x16_priority_sprite(screen_device &screen, bi
}
if (pxl != 0x0f) {
if ((priority & (1 << (prio[x] & 0x1f))) == 0 && prio[x] < 0x80) {
dest[x] = pxl + color;
prio[x] |= 0x80;
if (!(dest[x] & 0x8000)) {
dest[x] = (pxl+color) | (priority << 14);
dest[x] |= 0x8000;
}
}
}
@ -648,12 +703,26 @@ void megasys1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,co
{
int color,code,sx,sy,flipx,flipy,attr,sprite;
/* objram: 0x100*4 entries spritedata: 0x80 entries */
/* sprite order is from first in Sprite Data RAM (frontmost) to last */
if (m_hardware_type_z == 0) /* standard sprite hardware */
{
if (!(m_sprite_flag&0x10))
m_sprite_buffer_bitmap.fill(0x7fff, cliprect);
else
{
// P47 sprite trails effect.. not quite right tho
// I think the low 4 bits are used to clear specific pens?
// when the hardware wants to clear the trails from the screen
// it increases the value from 0x00 to 0x0e
//printf("m_sprite_flag %02x\n", m_sprite_flag);
partial_clear_sprite_bitmap(screen, bitmap, cliprect, m_sprite_flag&0x0f);
}
INT32 color_mask = (m_sprite_flag & 0x100) ? 0x07 : 0x0f;
UINT16 *objectram = (UINT16*)m_buffer2_objectram;
@ -680,7 +749,8 @@ void megasys1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,co
INT32 flipx = attr & 0x40;
INT32 flipy = attr & 0x80;
INT32 pri = (attr & 0x08) ? 0x0c : 0x0a;
//INT32 pri = (attr & 0x08) ? 0x0c : 0x0a;
INT32 pri = (attr & 0x08)>>3;
INT32 mosaic = (attr & 0x0f00)>>8;
INT32 mossol = (attr & 0x1000)>>8;
@ -1002,7 +1072,7 @@ PALETTE_INIT_MEMBER(megasys1_state,megasys1)
UINT32 megasys1_state::screen_update_megasys1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int i,flag,pri,primask;
int i, flag, pri, primask;
int active_layers;
if (m_hardware_type_z)
@ -1029,13 +1099,13 @@ UINT32 megasys1_state::screen_update_megasys1(screen_device &screen, bitmap_ind1
/* see what layers are really active (layers 4 & f will do no harm) */
for (i = 0;i < 5;i++)
reallyactive |= 1 << ((pri >> (4*i)) & 0x0f);
reallyactive |= 1 << ((pri >> (4 * i)) & 0x0f);
active_layers = m_active_layers & reallyactive;
active_layers |= 1 << ((pri & 0xf0000) >> 16); // bottom layer can't be disabled
}
machine().tilemap().set_flip_all((m_screen_flag & 1) ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0 );
machine().tilemap().set_flip_all((m_screen_flag & 1) ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
for (i = 0;i < 3;i++)
{
@ -1043,8 +1113,8 @@ UINT32 megasys1_state::screen_update_megasys1(screen_device &screen, bitmap_ind1
{
m_tmap[i]->enable(active_layers & (1 << i));
m_tmap[i]->set_scrollx(0,m_scrollx[i]);
m_tmap[i]->set_scrolly(0,m_scrolly[i]);
m_tmap[i]->set_scrollx(0, m_scrollx[i]);
m_tmap[i]->set_scrolly(0, m_scrolly[i]);
}
}
@ -1060,38 +1130,45 @@ UINT32 megasys1_state::screen_update_megasys1(screen_device &screen, bitmap_ind1
switch (layer)
{
case 0:
case 1:
case 2:
if ( (m_tmap[layer]) && (active_layers & (1 << layer) ) )
{
m_tmap[layer]->draw(screen, bitmap, cliprect, flag,primask);
flag = 0;
}
break;
case 3:
case 4:
if (flag != 0)
{
flag = 0;
bitmap.fill(0, cliprect);
}
case 0:
case 1:
case 2:
if ((m_tmap[layer]) && (active_layers & (1 << layer)))
{
m_tmap[layer]->draw(screen, bitmap, cliprect, flag, primask);
flag = 0;
}
break;
case 3:
case 4:
if (flag != 0)
{
flag = 0;
bitmap.fill(0, cliprect);
}
if (m_sprite_flag & 0x100) /* sprites are split */
{
/* following tilemaps will obscure this sprites layer */
primask |= 1 << (layer-3);
}
else
/* following tilemaps will obscure all sprites */
if (layer == 3) primask |= 3;
if (m_sprite_flag & 0x100) /* sprites are split */
{
/* following tilemaps will obscure this sprites layer */
primask |= 1 << (layer - 3);
}
else
/* following tilemaps will obscure all sprites */
if (layer == 3) primask |= 3;
break;
break;
}
}
if (active_layers & 0x08)
draw_sprites(screen,bitmap,cliprect);
{
draw_sprites(screen, bitmap, cliprect);
if (m_hardware_type_z == 0)
mix_sprite_bitmap(screen, bitmap, cliprect);
}
return 0;
}