Beast Busters - use single pass sprite render with priority buffer in case of cut-out effects

This commit is contained in:
bmcphail 2018-09-05 11:30:28 -04:00
parent 993b42e8b4
commit 1b776b299d
2 changed files with 34 additions and 22 deletions

View File

@ -7,6 +7,7 @@
#include "machine/gen_latch.h"
#include "video/bufsprite.h"
#include "screen.h"
class bbusters_state : public driver_device
{
@ -58,8 +59,8 @@ protected:
template<int Layer> DECLARE_WRITE16_MEMBER(pf_w);
inline const uint8_t *get_source_ptr(gfx_element *gfx, uint32_t sprite, int dx, int dy, int block);
void draw_block(bitmap_ind16 &dest,int x,int y,int size,int flipx,int flipy,uint32_t sprite,int color,int bank,int block);
void draw_sprites(bitmap_ind16 &bitmap, const uint16_t *source, int bank, int pass);
void draw_block(screen_device &screen, bitmap_ind16 &dest,int x,int y,int size,int flipx,int flipy,uint32_t sprite,int color,int bank,int block,int priority);
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const uint16_t *source, int bank);
void sound_map(address_map &map);
private:

View File

@ -128,7 +128,7 @@ inline const uint8_t *bbusters_state::get_source_ptr(gfx_element *gfx, uint32_t
return gfx->get_data((sprite+code) % gfx->elements()) + ((dy%16) * gfx->rowbytes());
}
void bbusters_state::draw_block(bitmap_ind16 &dest,int x,int y,int size,int flipx,int flipy,uint32_t sprite,int color,int bank,int block)
void bbusters_state::draw_block(screen_device &screen, bitmap_ind16 &dest,int x,int y,int size,int flipx,int flipy,uint32_t sprite,int color,int bank,int block,int priority)
{
gfx_element *gfx = m_gfxdecode->gfx(bank);
pen_t pen_base = gfx->colorbase() + gfx->granularity() * (color % gfx->colors());
@ -141,6 +141,7 @@ void bbusters_state::draw_block(bitmap_ind16 &dest,int x,int y,int size,int flip
while (m_scale_line_count) {
if (dy>=16 && dy<240) {
uint16_t *destline = &dest.pix16(dy);
uint8_t *priorityline = &screen.priority().pix8(dy);
uint8_t srcline=*m_scale_table_ptr;
const uint8_t *srcptr=nullptr;
@ -157,8 +158,11 @@ void bbusters_state::draw_block(bitmap_ind16 &dest,int x,int y,int size,int flip
srcptr=get_source_ptr(gfx,sprite,sx,srcline,block);
pixel=*srcptr++;
if (pixel!=15)
if (pixel!=15 && priority > priorityline[(x+(x_index>>16)) & 0x1ff])
{
priorityline[(x+(x_index>>16)) & 0x1ff] = priority;
destline[(x+(x_index>>16)) & 0x1ff]= pen_base + pixel;
}
if (flipx)
x_index-=xinc;
@ -173,14 +177,20 @@ void bbusters_state::draw_block(bitmap_ind16 &dest,int x,int y,int size,int flip
}
}
void bbusters_state::draw_sprites(bitmap_ind16 &bitmap, const uint16_t *source, int bank, int pass)
void bbusters_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const uint16_t *source, int bank)
{
int offs;
for (offs = 0;offs <0x800 ;offs += 4) {
// Sprites are stored in memory in back to front order.
// We draw them here front to back with a priority buffer in case any sprite
// with priority under a tilemap is later in the list than a sprite with
// above tilemap priority (which would cause a cut-out as only the top-most sprite
// in the line buffer goes to the priority mixer)
for (offs = 0x7fc;offs >=0 ;offs -= 4) {
int x,sprite,colour,fx,fy,scale;
int16_t y;
int block;
int priority;
sprite=source[offs+1];
colour=source[offs+0];
@ -215,36 +225,33 @@ void bbusters_state::draw_sprites(bitmap_ind16 &bitmap, const uint16_t *source,
fx=source[offs+0]&0x800;
sprite=sprite&0x3fff;
// Palettes 0xc-0xf confirmed to be behind tilemap on Beast Busters
if (pass==1 && (colour&0xc)!=0xc)
continue;
if (pass==0 && (colour&0xc)==0xc)
continue;
// Palettes 0xc-0xf confirmed to be behind tilemap on Beast Busters for 2nd sprite chip
priority = (bank==2) ? (((colour&0xc)==0xc) ? 1 : 4) : 8;
switch ((source[offs+0]>>8)&0x3) {
case 0:
scale=source[offs+0]&0x7;
m_scale_table_ptr = m_scale_table+0x387f+(0x80*scale);
m_scale_line_count = 0x10-scale;
draw_block(bitmap,x,y,16,fx,fy,sprite,colour,bank,block);
draw_block(screen,bitmap,x,y,16,fx,fy,sprite,colour,bank,block,priority);
break;
case 1: /* 2 x 2 */
scale=source[offs+0]&0xf;
m_scale_table_ptr = m_scale_table+0x707f+(0x80*scale);
m_scale_line_count = 0x20-scale;
draw_block(bitmap,x,y,32,fx,fy,sprite,colour,bank,block);
draw_block(screen,bitmap,x,y,32,fx,fy,sprite,colour,bank,block,priority);
break;
case 2: /* 64 by 64 block (2 x 2) x 2 */
scale=source[offs+0]&0x1f;
m_scale_table_ptr = m_scale_table+0xa07f+(0x80*scale);
m_scale_line_count = 0x40-scale;
draw_block(bitmap,x,y,64,fx,fy,sprite,colour,bank,block);
draw_block(screen,bitmap,x,y,64,fx,fy,sprite,colour,bank,block,priority);
break;
case 3: /* 2 x 2 x 2 x 2 */
scale=source[offs+0]&0x3f;
m_scale_table_ptr = m_scale_table+0xc07f+(0x80*scale);
m_scale_line_count = 0x80-scale;
draw_block(bitmap,x,y,128,fx,fy,sprite,colour,bank,block);
draw_block(screen,bitmap,x,y,128,fx,fy,sprite,colour,bank,block,priority);
break;
}
}
@ -254,22 +261,26 @@ void bbusters_state::draw_sprites(bitmap_ind16 &bitmap, const uint16_t *source,
uint32_t bbusters_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
screen.priority().fill(0, cliprect);
m_pf_tilemap[0]->set_scrollx(0, m_pf_scroll_data[0][0]);
m_pf_tilemap[0]->set_scrolly(0, m_pf_scroll_data[0][1]);
m_pf_tilemap[1]->set_scrollx(0, m_pf_scroll_data[1][0]);
m_pf_tilemap[1]->set_scrolly(0, m_pf_scroll_data[1][1]);
m_pf_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, m_spriteram[1]->buffer(), 2, 1);
m_pf_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, m_spriteram[1]->buffer(), 2, 0);
draw_sprites(bitmap, m_spriteram[0]->buffer(), 1, -1);
m_pf_tilemap[0]->draw(screen, bitmap, cliprect, 0, 2);
draw_sprites(screen, bitmap, m_spriteram[1]->buffer(), 2);
draw_sprites(screen, bitmap, m_spriteram[0]->buffer(), 1);
m_fix_tilemap->draw(screen, bitmap, cliprect, 0, 0);
return 0;
}
uint32_t mechatt_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
screen.priority().fill(0, cliprect);
m_pf_tilemap[0]->set_scrollx(0, m_pf_scroll_data[0][0]);
m_pf_tilemap[0]->set_scrolly(0, m_pf_scroll_data[0][1]);
m_pf_tilemap[1]->set_scrollx(0, m_pf_scroll_data[1][0]);
@ -277,7 +288,7 @@ uint32_t mechatt_state::screen_update(screen_device &screen, bitmap_ind16 &bitma
m_pf_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
m_pf_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, m_spriteram[0]->buffer(), 1, -1);
draw_sprites(screen, bitmap, m_spriteram[0]->buffer(), 1);
m_fix_tilemap->draw(screen, bitmap, cliprect, 0, 0);
return 0;
}