From a1bc5792742cf8760219af12bd31abbcbbb94a9f Mon Sep 17 00:00:00 2001 From: holub Date: Sun, 11 Aug 2024 11:08:12 -0400 Subject: sinclair/tsconf.cpp: fix layers priority, screen updates (#12647) --- src/mame/sinclair/tsconf.cpp | 1 + src/mame/sinclair/tsconf.h | 12 +++ src/mame/sinclair/tsconf_m.cpp | 163 ++++++++++++++++++++++++----------------- 3 files changed, 110 insertions(+), 66 deletions(-) diff --git a/src/mame/sinclair/tsconf.cpp b/src/mame/sinclair/tsconf.cpp index dac2edb06ea..f56ef0cd975 100644 --- a/src/mame/sinclair/tsconf.cpp +++ b/src/mame/sinclair/tsconf.cpp @@ -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(); diff --git a/src/mame/sinclair/tsconf.h b/src/mame/sinclair/tsconf.h index 31f07e0a788..157a5560a17 100644 --- a/src/mame/sinclair/tsconf.h +++ b/src/mame/sinclair/tsconf.h @@ -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 m_cram; required_device m_sfile; required_device m_centronics; + std::vector m_sprites_cache; required_device_array m_ay; u8 m_ay_selected; diff --git a/src/mame/sinclair/tsconf_m.cpp b/src/mame/sinclair/tsconf_m.cpp index bbda418f46e..518c705af8d 100644 --- a/src/mame/sinclair/tsconf_m.cpp +++ b/src/mame/sinclair/tsconf_m.cpp @@ -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)) + { + // sprite disabled -> move to next + sinfo += 5; + } + else { - u8 tile_col = (code % 64) + flipx * width8; - for (auto ix = x; ix <= x + width8 * 8; ix = ix + 8) + 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) { - if (layer == 2) + u8 tile_col = (code % 64) + flipx * width8; + for (auto ix = x; ix <= x + width8 * 8; ix = ix + 8) { - 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); + 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; } - 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; } - 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: -- cgit v1.2.3