x68k: fix bitmap layer clear and sprite priority

This commit is contained in:
cracyc 2023-09-04 10:59:20 -05:00
parent d2830312cf
commit 085525bb79
3 changed files with 54 additions and 55 deletions

View File

@ -288,7 +288,7 @@ protected:
bool get_text_pixel(int line, int pixel, uint16_t *pix);
bool draw_gfx_scanline(bitmap_ind16 &bitmap, rectangle cliprect, uint8_t priority);
bool draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect);
void draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle cliprect);
void draw_sprites(bitmap_ind16 &bitmap, screen_device &screen, rectangle cliprect);
void draw_bg(bitmap_ind16 &bitmap, screen_device &screen, int layer, bool opaque, rectangle rect);
template <bool Blend> rgb_t get_gfx_pixel(int scanline, int pixel, bool gfxblend, rgb_t blendpix);

View File

@ -409,54 +409,55 @@ void x68k_crtc_device::crtc_w(offs_t offset, u16 data, u16 mem_mask)
break;
case 576: // operation register
m_operation = data & ~2;
if (data & 0x02) // high-speed graphic screen clear
if ((data & 0x02) && (m_reg[21] & 0xf)) // high-speed graphic screen clear
{
// this is based on the docs except for the higher color depth modes which isn't
// explicitly described this way but is likely based on how the plane scroll works
// XXX: not sufficiently tested especially in hires modes
// it seems that it only uses the 0 page scroll registers for where to clear see atomrobo
uint16_t xscr = xscr_gfx(0) & 0x1ff;
uint16_t yscr = yscr_gfx(0) & 0x1ff;
uint16_t mask = 0;
for (int page = 0; page < 4; page++)
{
if (!(m_reg[21] & (1 << page)))
continue;
uint16_t xscr = xscr_gfx(page) & 0x1ff;
uint16_t yscr = yscr_gfx(page) & 0x1ff;
uint16_t mask = ~(0xf << (page * 4));
for (int y = yscr; y < (m_height + yscr); y++)
mask |= (0xf << (page * 4));
}
for (int y = yscr; y < (m_height + yscr); y++)
{
if (is_1024x1024())
{
if (is_1024x1024())
if (m_width > 256)
{
if (m_width > 256)
{
for (int x = 0; x < 512; x++)
{
uint16_t data = m_gvram_read_callback(((y * 512) + x) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x) & 0x3ffff, data & mask, 0xffff);
}
}
else
{
for (int x = 0; x < 256; x++)
{
uint16_t data = m_gvram_read_callback(((y * 512) + x + xscr) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x + xscr) & 0x3ffff, data & mask, 0xffff);
data = m_gvram_read_callback(((y * 512) + x + xscr + 256) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x + xscr + 256) & 0x3ffff, data & mask, mask);
}
}
}
else
{
for (int x = 0; x < m_width; x++)
for (int x = 0; x < 512; x++)
{
uint16_t data = m_gvram_read_callback(((y * 512) + x) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x) & 0x3ffff, data & mask, 0xffff);
}
}
else
{
for (int x = 0; x < 256; x++)
{
uint16_t data = m_gvram_read_callback(((y * 512) + x + xscr) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x + xscr) & 0x3ffff, data & mask, 0xffff);
data = m_gvram_read_callback(((y * 512) + x + xscr + 256) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x + xscr + 256) & 0x3ffff, data & mask, mask);
}
}
}
else
{
for (int x = 0; x < m_width; x++)
{
uint16_t data = m_gvram_read_callback(((y * 512) + x + xscr) & 0x3ffff, 0xffff);
m_gvram_write_callback(((y * 512) + x + xscr) & 0x3ffff, data & mask, 0xffff);
}
}
}
m_operation_end_timer->adjust(attotime::from_msec(5), 0x02); // time taken to do operation is a complete guess.
}
m_operation_end_timer->adjust(attotime::from_msec(5), 0x02); // time taken to do operation is a complete guess.
break;
}
// LOG("%s CRTC: Wrote %04x to CRTC register %i\n",machine().describe_context(), data, offset);

View File

@ -135,7 +135,7 @@ void x68k_state::spritereg_w(offs_t offset, uint16_t data, uint16_t mem_mask)
m_bg1_16->set_scrolly(0,(data - m_video.bg_vstart) & 0x3ff);
break;
case 0x406: // BG H-DISP (normally equals CRTC reg 2 value + 4)
m_video.bg_hstart = (data - 4) * 8;
m_video.bg_hstart = (data - 4) * 8 + 1;
break;
case 0x407: // BG V-DISP (like CRTC reg 6)
m_video.bg_vstart = data;
@ -470,7 +470,7 @@ template <bool Blend> rgb_t x68k_state::get_gfx_pixel(int scanline, int pixel, b
}
// Sprite controller "Cynthia" at 0xeb0000
void x68k_state::draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle cliprect)
void x68k_state::draw_sprites(bitmap_ind16 &bitmap, screen_device &screen, rectangle cliprect)
{
/*
0xeb0000 - 0xeb07ff - Sprite registers (up to 128)
@ -506,29 +506,28 @@ void x68k_state::draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle clip
if((!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) || ((m_video.bg_hvres & 0x1c) == 0x10 && m_crtc->vfactor() == 1))
divisor = 2;
for(ptr=508;ptr>=0;ptr-=4) // stepping through sprites
for(ptr=0;ptr<=508;ptr+=4) // stepping through sprites
{
pri = m_spritereg[ptr+3] & 0x03;
if(!pri) continue;
#ifdef MAME_DEBUG
if(!(machine().input().code_pressed(KEYCODE_I)))
if(machine().input().code_pressed(KEYCODE_I)) continue;
#endif
if(pri == priority)
{ // if at the right priority level, draw the sprite
rectangle rect;
int code = m_spritereg[ptr+2] & 0x00ff;
int colour = (m_spritereg[ptr+2] & 0x0f00) >> 8;
int xflip = m_spritereg[ptr+2] & 0x4000;
int yflip = m_spritereg[ptr+2] & 0x8000;
int sx = (m_spritereg[ptr+0] & 0x3ff) - 16;
int sy = (m_spritereg[ptr+1] & 0x3ff) - 16;
rectangle rect;
int code = m_spritereg[ptr+2] & 0x00ff;
int colour = (m_spritereg[ptr+2] & 0x0f00) >> 8;
int xflip = m_spritereg[ptr+2] & 0x4000;
int yflip = m_spritereg[ptr+2] & 0x8000;
int sx = (m_spritereg[ptr+0] & 0x3ff) - 16;
int sy = (m_spritereg[ptr+1] & 0x3ff) - 16;
rect.min_x=m_video.bg_hstart;
rect.min_y=m_video.bg_vstart;
rect.max_x=rect.min_x + m_crtc->visible_width()-1;
rect.max_y=rect.min_y + m_crtc->visible_height()-1;
rect.min_x=m_video.bg_hstart;
rect.min_y=m_video.bg_vstart;
rect.max_x=rect.min_x + m_crtc->visible_width()-1;
rect.max_y=rect.min_y + m_crtc->visible_height()-1;
int pmask = (pri == 1) ? 0xfffe : (pri == 2) ? 0xfffc : 0xfff0;
m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect,code,colour,xflip,yflip,m_video.bg_hstart+sx,(m_video.bg_vstart / divisor)+sy,0x10000,0x10000,0x00);
}
m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect,code,colour,xflip,yflip,m_video.bg_hstart+sx,(m_video.bg_vstart / divisor)+sy,screen.priority(),pmask,0x00);
}
}
@ -561,7 +560,7 @@ void x68k_state::draw_bg(bitmap_ind16 &bitmap, screen_device &screen, int layer,
map->set_scrollx(0,(sclx - m_video.bg_hstart) & 0x3ff);
map->set_scrolly(0,(scly - (m_video.bg_vstart / divisor)) & 0x3ff);
map->draw(screen, bitmap, rect, opaque ? TILEMAP_DRAW_OPAQUE : 0, 0);
map->draw(screen, bitmap, rect, opaque ? TILEMAP_DRAW_OPAQUE : 0, !layer ? 2 : 1);
}
static const gfx_layout x68k_pcg_8 =
@ -742,15 +741,14 @@ uint32_t x68k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
divisor = 2;
}
m_pcgbitmap.fill(0, pcgrect);
draw_sprites(m_pcgbitmap,1,pcgrect);
screen.priority().fill(0, pcgrect);
if(m_spritereg[0x404] & 0x0008)
draw_bg(m_pcgbitmap, screen, 1, false, pcgrect);
draw_sprites(m_pcgbitmap,2,pcgrect);
if(m_spritereg[0x404] & 0x0001)
draw_bg(m_pcgbitmap, screen, 0, false, pcgrect);
draw_sprites(m_pcgbitmap,3,pcgrect);
draw_sprites(m_pcgbitmap, screen, pcgrect);
}
int gfxprio = -1, textprio = -1, pcgprio = -1, currprio = 0;