sinclair/tsconf.cpp: fix layers priority, screen updates (#12647)

This commit is contained in:
holub 2024-08-11 11:08:12 -04:00 committed by GitHub
parent 0aad7c75a7
commit a1bc579274
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 114 additions and 70 deletions

View File

@ -229,6 +229,7 @@ void tsconf_state::machine_reset()
m_zctl_di = 0xff;
m_ay_selected = 0;
m_sprites_cache.clear();
tsconf_update_bank0();
tsconf_update_video_mode();

View File

@ -136,6 +136,17 @@ private:
T1_Y_OFFSET_H = 0x47
};
struct sprite_data
{
u32 code;
u32 color;
int flipx;
int flipy;
s32 destx;
s32 desty;
u32 pmask;
};
void update_frame_timer();
emu_timer *m_frame_irq_timer = nullptr;
emu_timer *m_scanline_irq_timer = nullptr;
@ -222,6 +233,7 @@ private:
required_device<ram_device> m_cram;
required_device<ram_device> m_sfile;
required_device<centronics_device> m_centronics;
std::vector<sprite_data> m_sprites_cache;
required_device_array<ym2149_device, 2> m_ay;
u8 m_ay_selected;

View File

@ -154,11 +154,18 @@ void tsconf_state::tsconf_update_screen(screen_device &screen, bitmap_rgb32 &bit
if (!BIT(m_regs[V_CONFIG], 5))
{
if (VM == VM_ZX)
{
tsconf_draw_zx(screen, bitmap, cliprect);
}
else if (VM == VM_TXT)
{
tsconf_draw_txt(bitmap, cliprect);
}
else
{
bitmap.fill(m_palette->pen_color(get_border_color()), cliprect);
tsconf_draw_gfx(bitmap, cliprect);
}
}
else
{
@ -172,22 +179,19 @@ void tsconf_state::tsconf_update_screen(screen_device &screen, bitmap_rgb32 &bit
{
m_ts_tilemap[TM_TILES0]->draw(
screen, bitmap, cliprect,
BIT(m_regs[TS_CONFIG], 2) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 1);
BIT(m_regs[TS_CONFIG], 2) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 1, 0);
}
if (BIT(m_regs[TS_CONFIG], 6))
{
m_ts_tilemap[TM_TILES1]->draw(
screen, bitmap, cliprect,
BIT(m_regs[TS_CONFIG], 3) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 2);
BIT(m_regs[TS_CONFIG], 3) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 2, 0);
}
if (BIT(m_regs[TS_CONFIG], 7))
{
// draw_sprites(screen, bitmap, cliprect);
// Avoid frequent expensive updates for now. Currently once per frame
if (cliprect.bottom() == get_screen_area().bottom() && cliprect.right() == get_screen_area().right())
draw_sprites(screen, bitmap, get_screen_area());
draw_sprites(screen, bitmap, get_screen_area());
}
}
}
@ -249,6 +253,7 @@ void tsconf_state::tsconf_draw_txt(bitmap_rgb32 &bitmap, const rectangle &clipre
void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
u8 pal_offset = m_regs[PAL_SEL] << 4;
const rgb_t transparent = m_palette->pen_color(0);
for (u16 vpos = cliprect.top(); vpos <= cliprect.bottom(); vpos++)
{
u16 y_offset = (OFFS_512(G_Y_OFFS_L) + m_gfx_y_frame_offset + vpos) & 0x1ff;
@ -269,9 +274,21 @@ void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &clipre
if (x_offset == 512)
video_location -= 256;
u8 pix = *video_location++;
*bm++ = m_palette->pen_color(pal_offset | (pix >> 4));
rgb_t pen = m_palette->pen_color(pal_offset | (pix >> 4));
if (pen != transparent)
{
*bm = pen;
}
bm++;
if (width != 1)
*bm++ = m_palette->pen_color(pal_offset | (pix & 0x0f));
{
pen = m_palette->pen_color(pal_offset | (pix & 0x0f));
if (pen != transparent)
{
*bm = pen;
}
bm++;
}
}
}
else // VM_256C
@ -280,7 +297,12 @@ void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &clipre
{
if (x_offset == 512)
video_location -= 512;
*bm++ = m_palette->pen_color(*video_location++);
rgb_t pen = m_palette->pen_color(*video_location++);
if (pen != transparent)
{
*bm = pen;
}
bm++;
}
}
}
@ -297,73 +319,69 @@ SFILE Reg.16 7 6 5 4 3 2 1 0
*/
void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
rectangle screen = get_screen_area();
u8 layer = 0;
u8 *sinfo = m_sfile->pointer() + 1;
u8 sid = 1;
// Higher Sprite draws on top. Prepare to iterate backwards.
for (; sid < 85 && layer < 3; sid++)
if (m_sprites_cache.empty())
{
if (BIT(*sinfo, 6))
layer++;
sinfo += 6;
}
sinfo -= 1;
for (; sid; sid--)
{
s16 y = *sinfo++;
y |= BIT(*sinfo, 0) << 8;
y += screen.top() - (y >= screen.height() ? 512 : 0);
u8 height8 = BIT(*sinfo, 1, 3);
layer -= BIT(*sinfo, 6);
if (!BIT(*sinfo, 5))
const rectangle screen = get_screen_area();
u8 layer = 0;
u8 *sinfo = m_sfile->pointer();
for (u8 sid = 0; sid < 85 && layer < 3; sid++)
{
// sprite disabled -> move to previous
sinfo -= 7;
}
else
{
bool flipy = BIT(*sinfo++, 7);
s16 x = *sinfo++;
x |= BIT(*sinfo, 0) << 8;
x += screen.left() - (x >= screen.width() ? 512 : 0);
u8 width8 = BIT(*sinfo, 1, 3);
bool flipx = BIT(*sinfo++, 7);
u16 code = *sinfo++;
code |= BIT(*sinfo, 0, 4) << 8;
u8 pal = BIT(*sinfo, 4, 4);
sinfo -= 11;
u8 tile_row = code / 64 + flipy * height8;
for (auto iy = y; iy <= y + height8 * 8; iy = iy + 8)
s16 y = *sinfo++;
y |= BIT(*sinfo, 0) << 8;
y += screen.top() - (y >= screen.height() ? 512 : 0);
const u8 height8 = BIT(*sinfo, 1, 3);
const bool leap_next = BIT(*sinfo, 6);
if (!BIT(*sinfo, 5))
{
u8 tile_col = (code % 64) + flipx * width8;
for (auto ix = x; ix <= x + width8 * 8; ix = ix + 8)
{
if (layer == 2)
{
m_gfxdecode->gfx(TM_SPRITES)->transpen(
bitmap, cliprect,
tmp_tile_oversized_to_code((tile_row % 64) * 64 + (tile_col % 64)),
pal, flipx, flipy, ix, iy,
0);
}
else
{
m_gfxdecode->gfx(TM_SPRITES)->prio_transpen(
bitmap, cliprect,
tmp_tile_oversized_to_code((tile_row % 64) * 64 + (tile_col % 64)),
pal, flipx, flipy, ix, iy,
screen_d.priority(), GFX_PMASK_2 | (layer ? GFX_PMASK_1 : 0), 0);
}
tile_col += flipx ? -1 : 1;
}
tile_row += flipy ? -1 : 1;
// sprite disabled -> move to next
sinfo += 5;
}
else
{
const bool flipy = BIT(*sinfo++, 7);
s16 x = *sinfo++;
x |= BIT(*sinfo, 0) << 8;
x += screen.left() - (x >= screen.width() ? 512 : 0);
const u8 width8 = BIT(*sinfo, 1, 3);
const bool flipx = BIT(*sinfo++, 7);
u16 code = *sinfo++;
code |= BIT(*sinfo, 0, 4) << 8;
const u8 pal = BIT(*sinfo++, 4, 4);
u8 tile_row = code / 64 + flipy * height8;
const u32 pmask = (~1) << layer;
for (auto iy = y; iy <= y + height8 * 8; iy = iy + 8)
{
u8 tile_col = (code % 64) + flipx * width8;
for (auto ix = x; ix <= x + width8 * 8; ix = ix + 8)
{
sprite_data spr = {};
spr.code = (tile_row % 64) * 64 + (tile_col % 64);
spr.color = pal;
spr.flipx = flipx;
spr.flipy = flipy;
spr.destx = ix;
spr.desty = iy;
spr.pmask = pmask;
m_sprites_cache.push_back(spr);
tile_col += flipx ? -1 : 1;
}
tile_row += flipy ? -1 : 1;
}
}
layer += leap_next;
}
}
// Higher Sprite draws on top. Iterate backwards.
for (auto spr = m_sprites_cache.rbegin(); spr != m_sprites_cache.rend(); ++spr)
{
m_gfxdecode->gfx(TM_SPRITES)->prio_transpen(bitmap, cliprect,
tmp_tile_oversized_to_code(spr->code), spr->color, spr->flipx, spr->flipy, spr->destx, spr->desty,
screen_d.priority(), spr->pmask, 0);
}
}
void tsconf_state::ram_bank_write(u8 bank, offs_t offset, u8 data)
@ -378,7 +396,10 @@ void tsconf_state::ram_bank_write(u8 bank, offs_t offset, u8 data)
if (addr_w < 512)
cram_write(addr_w, data);
else if (addr_w < 1024)
{
m_sprites_cache.clear();
m_sfile->write(addr_w - 512, data);
}
else
tsconf_port_xxaf_w((addr_w - 1024) << 8, data);
}
@ -399,10 +420,16 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
else
{
if (ram_addr >= PAGE4K(m_regs[T0_G_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[T0_G_PAGE] & 0xf8) + 8))
{
m_gfxdecode->gfx(TM_TILES0)->mark_all_dirty();
m_ts_tilemap[TM_TILES0]->mark_all_dirty();
}
if (ram_addr >= PAGE4K(m_regs[T1_G_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[T1_G_PAGE] & 0xf8) + 8))
{
m_gfxdecode->gfx(TM_TILES1)->mark_all_dirty();
m_ts_tilemap[TM_TILES1]->mark_all_dirty();
}
}
if (ram_addr >= get_vpage_offset() && ram_addr < get_vpage_offset() + PAGE4K((VM == VM_16C) ? 8 : 16))
@ -451,6 +478,8 @@ void tsconf_state::cram_write16(offs_t offset, u16 data)
void tsconf_state::sfile_write16(offs_t offset, u16 data)
{
m_sprites_cache.clear();
u16 dest = offset & 0x1fe;
m_sfile->write(dest, data >> 8);
m_sfile->write(dest | 1, data & 0xff);
@ -901,10 +930,12 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline)
case T0_G_PAGE:
m_gfxdecode->gfx(TM_TILES0)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8));
m_ts_tilemap[TM_TILES0]->mark_all_dirty();
break;
case T1_G_PAGE:
m_gfxdecode->gfx(TM_TILES1)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8));
m_ts_tilemap[TM_TILES1]->mark_all_dirty();
break;
case T0_X_OFFSET_L: