x68k: do the final mix in a single loop per-pixel

This commit is contained in:
cracyc 2022-07-21 19:32:58 -05:00
parent 424a3a6605
commit d28414c2a1
2 changed files with 112 additions and 128 deletions

View File

@ -321,11 +321,12 @@ protected:
void cpu_space_map(address_map &map);
inline void plot_pixel(bitmap_rgb32 &bitmap, int x, int y, uint32_t color);
void draw_text(bitmap_rgb32 &bitmap, int xscr, int yscr, rectangle rect);
rgb_t get_text_pixel(int line, int pixel);
bool draw_gfx_scanline(bitmap_ind16 &bitmap, rectangle cliprect, uint8_t priority);
void draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect);
bool draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect);
void draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle cliprect);
void draw_bg(bitmap_ind16 &bitmap, screen_device &screen, int layer, bool opaque, rectangle rect);
rgb_t get_gfx_pixel(int scanline, int pixel, bool gfxblend, rgb_t blendpix);
public:
static rgb_t GGGGGRRRRRBBBBBI(uint32_t raw);

View File

@ -188,41 +188,30 @@ uint16_t x68k_state::spriteram_r(offs_t offset)
return m_spriteram[offset];
}
void x68k_state::draw_text(bitmap_rgb32 &bitmap, int xscr, int yscr, rectangle rect)
rgb_t x68k_state::get_text_pixel(int line, int pixel)
{
unsigned int line,pixel; // location on screen
uint32_t loc; // location in TVRAM
uint32_t colour;
int bit;
int divisor = 1;
if(m_crtc->gfx_double_scan())
divisor = 2;
int xscr = (m_crtc->xscr_text() & 0x3ff) + (pixel - m_crtc->hbegin());
int yscr = (m_crtc->yscr_text() & 0x3ff);
for(line=rect.min_y;line<=rect.max_y;line++) // per scanline
{
// adjust for scroll registers
loc = ((((line- m_crtc->vbegin()) / divisor) + yscr) & 0x3ff) * 64;
loc += (xscr / 16) & 0x7f;
loc &= 0xffff;
bit = 15 - (xscr & 0x0f);
for(pixel=rect.min_x;pixel<=rect.max_x;pixel++) // per pixel
{
colour = (((m_tvram[loc] >> bit) & 0x01) ? 1 : 0)
+ (((m_tvram[loc+0x10000] >> bit) & 0x01) ? 2 : 0)
+ (((m_tvram[loc+0x20000] >> bit) & 0x01) ? 4 : 0)
+ (((m_tvram[loc+0x30000] >> bit) & 0x01) ? 8 : 0);
// Colour 0 is displayable if the text layer is at the priority level 2
if(((colour || (m_crtc->gfx_color_mode() == 3)) && (m_pcgpalette->pen(colour) & 0xffffff)) || ((m_video.reg[1] & 0x0c00) == 0x0800))
bitmap.pix(line, pixel) = m_pcgpalette->pen(colour);
bit--;
if(bit < 0)
{
bit = 15;
loc++;
loc &= 0xffff;
}
}
}
// adjust for scroll registers
loc = ((((line- m_crtc->vbegin()) / divisor) + yscr) & 0x3ff) * 64;
loc += (xscr / 16) & 0x7f;
loc &= 0xffff;
bit = 15 - (xscr & 0x0f);
colour = (((m_tvram[loc] >> bit) & 0x01) ? 1 : 0)
+ (((m_tvram[loc+0x10000] >> bit) & 0x01) ? 2 : 0)
+ (((m_tvram[loc+0x20000] >> bit) & 0x01) ? 4 : 0)
+ (((m_tvram[loc+0x30000] >> bit) & 0x01) ? 8 : 0);
// Colour 0 is displayable if the text layer is at the priority level 2
if(((colour || (m_crtc->gfx_color_mode() == 3)) && (m_pcgpalette->pen(colour) & 0xffffff)) || ((m_video.reg[1] & 0x0c00) == 0x0800))
return m_pcgpalette->pen(colour);
return 0;
}
bool x68k_state::draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprect, uint8_t priority)
@ -413,21 +402,19 @@ bool x68k_state::draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprect, ui
return ret;
}
void x68k_state::draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect)
bool x68k_state::draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect)
{
int priority, scanline, pixel;
int priority;
bool gfxblend=false;
rectangle gfxrect = cliprect;
int divisor = 1;
if(m_crtc->gfx_double_scan())
{
gfxrect.max_y >>= 1;
gfxrect.min_y >>= 1;
divisor = 2;
}
if(m_crtc->gfx_layer_buffer()) // if graphic layers are set to buffer, then they aren't visible
return;
return false;
m_gfxbitmap.fill(0, gfxrect);
if((m_video.reg[2] & 0x1800) == 0x1000)
@ -437,54 +424,56 @@ void x68k_state::draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect)
{
gfxblend = draw_gfx_scanline(m_gfxbitmap,gfxrect,priority);
}
return gfxblend;
}
for(scanline=cliprect.min_y;scanline<=cliprect.max_y;scanline++)
rgb_t x68k_state::get_gfx_pixel(int scanline, int pixel, bool gfxblend, rgb_t blendpix)
{
uint16_t colour;
bool blend = false;
int divisor = 1;
if(m_crtc->gfx_double_scan())
divisor = 2;
if((m_video.reg[0] & 0x03) == 3)
{
uint16_t colour;
bool blend = false;
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
colour = m_gfxbitmap.pix(scanline / divisor, pixel);
if(colour || (m_video.gfx_pri == 2))
return GGGGGRRRRRBBBBBI(colour);
}
else if(gfxblend)
{
colour = m_gfxbitmap.pix(scanline / divisor, pixel);
if(((m_video.reg[2] & 0x1900) == 0x1900) && (m_video.gfx_pri != 2) && (colour & 1))
blend = true;
else
blend = false;
if(colour || (m_video.gfx_pri == 2))
{
if((m_video.reg[0] & 0x03) == 3)
{
colour = m_gfxbitmap.pix(scanline / divisor, pixel);
if(colour || (m_video.gfx_pri == 2))
bitmap.pix(scanline, pixel) = GGGGGRRRRRBBBBBI(colour);
}
else if(gfxblend)
{
colour = m_gfxbitmap.pix(scanline / divisor, pixel);
if(((m_video.reg[2] & 0x1900) == 0x1900) && (m_video.gfx_pri != 2) && (colour & 1))
blend = true;
else
blend = false;
if(colour || (m_video.gfx_pri == 2))
{
if(blend)
bitmap.pix(scanline, pixel) = ((bitmap.pix(scanline, pixel) >> 1) & 0xff7f7f7f) + ((pal555(colour, 6, 11, 1) >> 1) & 0x7f7f7f);
else
bitmap.pix(scanline, pixel) = pal555(colour, 6, 11, 1);
}
}
if(blend)
return ((blendpix >> 1) & 0xff7f7f7f) + ((pal555(colour, 6, 11, 1) >> 1) & 0x7f7f7f);
else
{
colour = m_gfxbitmap.pix(scanline / divisor, pixel) & 0xff;
if(((m_video.reg[2] & 0x1900) == 0x1900) && (m_video.gfx_pri != 2) && (colour & 1))
{
blend = true;
colour &= 0xfe;
}
else
blend = false;
if((m_gfxpalette->pen(colour) & 0xffffff) || (m_video.gfx_pri == 2))
{
if(blend)
bitmap.pix(scanline, pixel) = ((bitmap.pix(scanline, pixel) >> 1) & 0xff7f7f7f) + ((m_gfxpalette->pen(colour) >> 1) & 0x7f7f7f);
else
bitmap.pix(scanline, pixel) = m_gfxpalette->pen(colour);
}
}
return pal555(colour, 6, 11, 1);
}
}
else
{
colour = m_gfxbitmap.pix(scanline / divisor, pixel) & 0xff;
if(((m_video.reg[2] & 0x1900) == 0x1900) && (m_video.gfx_pri != 2) && (colour & 1))
{
blend = true;
colour &= 0xfe;
}
else
blend = false;
if((m_gfxpalette->pen(colour) & 0xffffff) || (m_video.gfx_pri == 2))
{
if(blend)
return ((blendpix >> 1) & 0xff7f7f7f) + ((m_gfxpalette->pen(colour) >> 1) & 0x7f7f7f);
else
return m_gfxpalette->pen(colour);
}
}
return 0;
}
// Sprite controller "Cynthia" at 0xeb0000
@ -678,7 +667,6 @@ uint32_t x68k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
{
rectangle rect(0,0,0,0);
int priority;
int xscr,yscr;
int x;
int pixel = 0, scanline = 0;
//uint8_t *rom;
@ -751,70 +739,65 @@ uint32_t x68k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
else
bitmap.fill(m_pcgpalette->pen(0), rect);
for(priority=2;priority>=0;priority--)
bool blend = false;
int divisor = 1;
// Graphics screen(s)
blend = draw_gfx(bitmap,rect);
// Sprite / BG Tiles
if(/*(m_spritereg[0x404] & 0x0200) &&*/ (m_video.reg[2] & 0x0040))
{
// Graphics screen(s)
if(priority == m_video.gfx_pri)
draw_gfx(bitmap,rect);
// Sprite / BG Tiles
if(priority == m_video.sprite_pri /*&& (m_spritereg[0x404] & 0x0200)*/ && (m_video.reg[2] & 0x0040))
rectangle pcgrect = rect;
if((!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) || ((m_video.bg_hvres & 0x1c) == 0x10 && m_crtc->vfactor() == 1))
{
rectangle pcgrect = rect;
int divisor = 1;
if((!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) || ((m_video.bg_hvres & 0x1c) == 0x10 && m_crtc->vfactor() == 1))
{
pcgrect.max_y >>= 1;
pcgrect.min_y >>= 1;
divisor = 2;
}
m_pcgbitmap.fill(0, pcgrect);
draw_sprites(m_pcgbitmap,1,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);
for(scanline=rect.min_y;scanline<=rect.max_y;scanline++)
{
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
{
uint8_t colour = m_pcgbitmap.pix(scanline / divisor, pixel) & 0xff;
if(colour && (m_pcgpalette->pen(colour) & 0xffffff))
bitmap.pix(scanline, pixel) = m_pcgpalette->pen(colour);
}
}
pcgrect.max_y >>= 1;
pcgrect.min_y >>= 1;
divisor = 2;
}
m_pcgbitmap.fill(0, pcgrect);
draw_sprites(m_pcgbitmap,1,pcgrect);
if(m_spritereg[0x404] & 0x0008)
draw_bg(m_pcgbitmap, screen, 1, false, pcgrect);
// Text screen
if(m_video.reg[2] & 0x0020 && priority == m_video.text_pri)
{
xscr = (m_crtc->xscr_text() & 0x3ff);
yscr = (m_crtc->yscr_text() & 0x3ff);
if(!m_crtc->text_layer_buffer()) // if text layer is set to buffer, then it's not visible
draw_text(bitmap,xscr,yscr,rect);
}
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);
}
if((m_video.reg[2] & 0x1800) == 0x1000) // special priority
for(scanline=rect.min_y;scanline<=rect.max_y;scanline++)
{
uint16_t colour;
int divisor = 1;
if(m_crtc->gfx_double_scan())
divisor = 2;
for(scanline=rect.min_y;scanline<=rect.max_y;scanline++)
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
{
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
if((m_video.reg[2] & 0x1800) == 0x1000) // special priority
{
colour = m_special.pix(scanline / divisor, pixel) & 0xff;
uint16_t colour = m_special.pix(scanline / divisor, pixel) & 0xff;
// XXX: this might check the pen color not the palette index
if(colour & ~1)
{
bitmap.pix(scanline, pixel) = m_gfxpalette->pen(colour & ~1);
continue;
}
}
rgb_t outpix = bitmap.pix(scanline, pixel);
for(priority=2;priority>=0;priority--)
{
rgb_t pix = 0;
if(priority == m_video.gfx_pri && !m_crtc->gfx_layer_buffer())
pix = get_gfx_pixel(scanline, pixel, blend, outpix);
if(priority == m_video.sprite_pri /*&& (m_spritereg[0x404] & 0x0200)*/ && (m_video.reg[2] & 0x0040))
{
uint16_t colour = m_pcgbitmap.pix(scanline / divisor, pixel) & 0xff;
if(colour)
pix = m_pcgpalette->pen(colour);
}
if(priority == m_video.text_pri && (m_video.reg[2] & 0x0020) && !m_crtc->text_layer_buffer())
pix = get_text_pixel(scanline, pixel);
if(pix & 0xffffff)
outpix = pix;
}
bitmap.pix(scanline, pixel) = outpix;
}
}