sinclair/tsconf.cpp: Use RGB screen bitmap so mid-screen palette changes work. (#12277)

This commit is contained in:
holub 2024-04-19 12:29:38 -04:00 committed by GitHub
parent 799b048ce9
commit f4986ce781
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 89 additions and 39 deletions

View file

@ -313,6 +313,9 @@ void tsconf_state::tsconf(machine_config &config)
PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256);
m_screen->set_raw(14_MHz_XTAL / 2, 448, with_hblank(0), 448, 320, with_vblank(0), 320);
m_screen->set_screen_update(FUNC(tsconf_state::screen_update));
m_screen->set_no_palette();
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_tsconf);
RAM(config, m_cram).set_default_size("512").set_default_value(0);
RAM(config, m_sfile).set_default_size("512").set_default_value(0); // 85*6

View file

@ -51,9 +51,9 @@ public:
static constexpr u16 with_vblank(u16 pixclocks) { return 32 + pixclocks; }
protected:
virtual void video_start() override;
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override ATTR_COLD;
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
virtual TIMER_CALLBACK_MEMBER(irq_off) override;
TIMER_CALLBACK_MEMBER(irq_frame);
@ -152,11 +152,12 @@ private:
virtual u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0) override;
u32 get_vpage_offset();
virtual rectangle get_screen_area() override;
virtual void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override;
void tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void tsconf_UpdateTxtBitmap(bitmap_ind16 &bitmap, const rectangle &cliprect);
void tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void tsconf_update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void tsconf_draw_zx(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void tsconf_draw_txt(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void tsconf_palette(palette_device &palette) const;
void tsconf_update_video_mode();

View file

@ -112,6 +112,33 @@ u32 tsconf_state::get_vpage_offset()
return PAGE4K(m_regs[V_PAGE] & ((VM == VM_16C) ? 0xf8 : 0xf0));
}
u32 tsconf_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
rectangle scr = get_screen_area();
rectangle vis = screen.visible_area();
if (vis != scr)
{
rectangle bsides[4] = {
rectangle(vis.left(), vis.right(), vis.top(), scr.top() - 1),
rectangle(vis.left(), scr.left() - 1, scr.top(), scr.bottom()),
rectangle(scr.right() + 1, vis.right(), scr.top(), scr.bottom()),
rectangle(vis.left(), vis.right(), scr.bottom() + 1, vis.bottom())
};
for (auto i = 0; i < 4; i++)
{
rectangle border = bsides[i] & cliprect;
if (!border.empty())
bitmap.fill(m_palette->pen_color(get_border_color()), border);
}
}
scr &= cliprect;
if (!scr.empty())
tsconf_update_screen(screen, bitmap, scr);
return 0;
}
/*
Layered as:
+ Border - already updated with screen_update_spectrum()
@ -122,32 +149,38 @@ Layered as:
+ Tiles 1
+ Sprites 2
*/
void tsconf_state::spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
void tsconf_state::tsconf_update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
if (!BIT(m_regs[V_CONFIG], 5))
{
if (VM == VM_ZX)
tsconf_UpdateZxScreenBitmap(screen, bitmap, cliprect);
tsconf_draw_zx(screen, bitmap, cliprect);
else if (VM == VM_TXT)
tsconf_UpdateTxtBitmap(bitmap, cliprect);
tsconf_draw_txt(bitmap, cliprect);
else
tsconf_UpdateGfxBitmap(bitmap, cliprect);
tsconf_draw_gfx(bitmap, cliprect);
}
else
{
bitmap.fill(get_border_color(), cliprect);
bitmap.fill(m_palette->pen_color(get_border_color()), cliprect);
}
if (!BIT(m_regs[V_CONFIG], 4))
{
screen.priority().fill(0, cliprect);
if (BIT(m_regs[TS_CONFIG], 5))
m_ts_tilemap[TM_TILES0]->draw(screen, bitmap, cliprect,
BIT(m_regs[TS_CONFIG], 2) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 1);
{
m_ts_tilemap[TM_TILES0]->draw(
screen, bitmap, cliprect,
BIT(m_regs[TS_CONFIG], 2) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 1);
}
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);
{
m_ts_tilemap[TM_TILES1]->draw(
screen, bitmap, cliprect,
BIT(m_regs[TS_CONFIG], 3) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 2);
}
if (BIT(m_regs[TS_CONFIG], 7))
{
@ -159,7 +192,7 @@ void tsconf_state::spectrum_update_screen(screen_device &screen, bitmap_ind16 &b
}
}
void tsconf_state::tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
void tsconf_state::tsconf_draw_zx(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
u8 pal_offset = m_regs[PAL_SEL] << 4;
u8 *screen_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]);
@ -172,7 +205,7 @@ void tsconf_state::tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind
u16 y = vpos - get_screen_area().top();
u8 *scr = &screen_location[((y & 7) << 8) | ((y & 0x38) << 2) | ((y & 0xc0) << 5) | (x >> 3)];
u8 *attr = &attrs_location[((y & 0xf8) << 2) | (x >> 3)];
u16 *pix = &(bitmap.pix(vpos, hpos));
u32 *pix = &(bitmap.pix(vpos, hpos));
while (hpos <= cliprect.right())
{
u16 ink = pal_offset | ((*attr >> 3) & 0x08) | (*attr & 0x07);
@ -180,14 +213,14 @@ void tsconf_state::tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind
u8 pix8 = (invert_attrs && (*attr & 0x80)) ? ~*scr : *scr;
for (u8 b = 0x80 >> (x & 0x07); b != 0 && hpos <= cliprect.right(); b >>= 1, x++, hpos++)
*pix++ = (pix8 & b) ? ink : pap;
*pix++ = m_palette->pen_color((pix8 & b) ? ink : pap);
scr++;
attr++;
}
}
}
void tsconf_state::tsconf_UpdateTxtBitmap(bitmap_ind16 &bitmap, const rectangle &cliprect)
void tsconf_state::tsconf_draw_txt(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
u8 *font_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE] ^ 0x01);
u8 pal_offset = m_regs[PAL_SEL] << 4;
@ -200,20 +233,20 @@ void tsconf_state::tsconf_UpdateTxtBitmap(bitmap_ind16 &bitmap, const rectangle
// TODO? u16 x_offset = OFFS_512(G_X_OFFS_L);
u8 *text_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + (y_offset / 8 * 256 + x / 8);
u16 *pix = &(bitmap.pix(vpos, hpos));
u32 *pix = &(bitmap.pix(vpos, hpos));
while (hpos <= cliprect.right())
{
u8 font_color = *(text_location + 128) & 0x0f;
u8 bg_color = (*(text_location + 128) & 0xf0) >> 4;
u8 char_x = *(font_location + (*text_location * 8) + (y_offset % 8));
for (u8 b = 0x80 >> (x & 0x07); b != 0 && hpos <= cliprect.right(); b >>= 1, x++, hpos++)
*pix++ = pal_offset | ((char_x & b) ? font_color : bg_color);
*pix++ = m_palette->pen_color(pal_offset | ((char_x & b) ? font_color : bg_color));
text_location++;
}
}
}
void tsconf_state::tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle &cliprect)
void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
u8 pal_offset = m_regs[PAL_SEL] << 4;
for (u16 vpos = cliprect.top(); vpos <= cliprect.bottom(); vpos++)
@ -221,13 +254,13 @@ void tsconf_state::tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle
u16 y_offset = (OFFS_512(G_Y_OFFS_L) + m_gfx_y_frame_offset + vpos) & 0x1ff;
u16 x_offset = (OFFS_512(G_X_OFFS_L) + (cliprect.left() - get_screen_area().left())) & 0x1ff;
u8 *video_location = m_ram->pointer() + get_vpage_offset() + ((y_offset * 512 + x_offset) >> (2 - VM));
u16 *bm = &(bitmap.pix(vpos, cliprect.left()));
u32 *bm = &(bitmap.pix(vpos, cliprect.left()));
s16 width = cliprect.width();
if (VM == VM_16C)
{
if (x_offset & 1)
{
*bm++ = pal_offset | (*video_location++ & 0x0f);
*bm++ = m_palette->pen_color(pal_offset | (*video_location++ & 0x0f));
x_offset++;
width--;
}
@ -236,9 +269,9 @@ void tsconf_state::tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle
if (x_offset == 512)
video_location -= 256;
u8 pix = *video_location++;
*bm++ = pal_offset | (pix >> 4);
*bm++ = m_palette->pen_color(pal_offset | (pix >> 4));
if (width != 1)
*bm++ = pal_offset | (pix & 0x0f);
*bm++ = m_palette->pen_color(pal_offset | (pix & 0x0f));
}
}
else // VM_256C
@ -247,7 +280,7 @@ void tsconf_state::tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle
{
if (x_offset == 512)
video_location -= 512;
*bm++ = *video_location++;
*bm++ = m_palette->pen_color(*video_location++);
}
}
}
@ -262,7 +295,7 @@ SFILE Reg.16 7 6 5 4 3 2 1 0
4 R2L TNUM[7:0]
5 R2H SPAL[7:4] TNUM[11:8]
*/
void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_ind16 &bitmap, const rectangle &cliprect)
void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
rectangle screen = get_screen_area();
@ -303,15 +336,28 @@ void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_ind16 &bitmap, c
u8 pal = BIT(*sinfo, 4, 4);
sinfo -= 11;
u32 pmask = layer ? (layer == 1 ? GFX_PMASK_2 : 0) : (GFX_PMASK_1 | GFX_PMASK_2);
u8 tile_row = code / 64 + flipy * height8;
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)
{
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(), pmask, 0);
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;
@ -412,8 +458,8 @@ void tsconf_state::sfile_write16(offs_t offset, u16 data)
u8 tsconf_state::tsconf_port_xx1f_r(offs_t offset) {
return m_beta->started() && m_beta->is_active()
? m_beta->status_r()
: 0x00; // TODO kempston read
? m_beta->status_r()
: 0x00; // TODO kempston read
}
void tsconf_state::tsconf_port_7ffd_w(u8 data)
@ -637,8 +683,8 @@ u8 tsconf_state::tsconf_port_f7_r(offs_t offset)
{
// BFF7
return (m_port_f7_ext == PS2KEYBOARDS_LOG && m_glukrs->address_r() == 0xf0)
? m_keyboard->read()
: m_glukrs->data_r();
? m_keyboard->read()
: m_glukrs->data_r();
}
void tsconf_state::tsconf_port_f7_w(offs_t offset, u8 data)
@ -849,8 +895,8 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline)
case G_Y_OFFS_L:
case G_Y_OFFS_H:
m_gfx_y_frame_offset = screen_vpos < get_screen_area().top()
? -get_screen_area().top()
: -screen_vpos;
? -get_screen_area().top()
: -screen_vpos;
break;
case T0_G_PAGE: