sinclair/tsconf.cpp Improved tiles decoding (#13145)

* sinclair/tsconf.cpp Improved tiles decoding

* rm palette hack

* replace math with bitswap

* simplify

* restore tile cache
This commit is contained in:
holub 2025-01-11 05:21:45 -05:00 committed by GitHub
parent 6d3d9c03a8
commit 53d73e817f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 44 deletions

View File

@ -56,14 +56,13 @@ TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_txt)
template <u8 Layer>
TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_16c)
{
u8 col_offset = (tile_index % tilemap.cols() + Layer * 64) << 1;
u16 row_offset = (tile_index / tilemap.cols() * 64 * 2) << 1;
const u8 col_offset = (tile_index & 0x03f) << 1;
const u16 row_offset = (tile_index & 0xfc0) << 2;
u8 *tile_info_addr = &m_ram->pointer()[(m_regs[T_MAP_PAGE] << 14) + row_offset + col_offset];
u8 *tile_info_addr = &m_ram->pointer()[(m_regs[T_MAP_PAGE] << 14) | row_offset | (Layer ? 0x80 : 0x00) | col_offset];
u8 hi = tile_info_addr[1];
u32 /*u16*/ tile = ((u16(hi) & 0x0f) << 8) | tile_info_addr[0];
tile = tile / tilemap.cols() * 64 * 8 + (tile % tilemap.cols()); // same as: tmp_tile_oversized_to_code()
u16 tile = ((u16(hi) & 0x0f) << 8) | tile_info_addr[0];
u8 pal = (BIT(m_regs[PAL_SEL], 4 + Layer * 2, 2) << 2) | BIT(hi, 4, 2);
tileinfo.set(TM_TILES0 + Layer, tile, pal, TILE_FLIPYX(BIT(hi, 6, 2)));
tileinfo.category = tile == 0 ? 2 : 1;
@ -139,23 +138,11 @@ static const gfx_layout tsconf_charlayout =
8 * 8
};
static const gfx_layout tsconf_tile_16cpp_layout =
{
8,
8,
64 * 64 * 8,
4,
{STEP4(0, 1)},
{STEP8(0, 4)},
{STEP8(0, 256 * 8)}, // Much more tiles when needed. Because tiles are in RAW format but we don't know region properties.
8 * 4
};
static GFXDECODE_START(gfx_tsconf)
GFXDECODE_ENTRY("maincpu", 0, tsconf_charlayout, 0xf7, 1) // TM_TS_CHAR : TXT
GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 16) // TM_TILES0 : T0 16cpp
GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 16) // TM_TILES1 : T1 16cpp
GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 16) // TM_SPRITES : Sprites 16cpp
GFXDECODE_RAM("tiles0_raw", 0, gfx_8x8x8_raw, 0, 16) // TM_TILES0 : T0 16cpp
GFXDECODE_RAM("tiles1_raw", 0, gfx_8x8x8_raw, 0, 16) // TM_TILES1 : T1 16cpp
GFXDECODE_RAM("sprites_raw", 0, gfx_8x8x8_raw, 0, 16) // TM_SPRITES : Sprites 16cpp
GFXDECODE_ENTRY("maincpu", 0x1fd00, spectrum_charlayout, 0xf7, 1) // TM_ZX_CHAR
GFXDECODE_END
@ -168,9 +155,13 @@ void tsconf_state::video_start()
m_ts_tilemap[TM_TILES0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_16c<0>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
m_ts_tilemap[TM_TILES0]->set_transparent_pen(0);
m_gfxdecode->gfx(TM_TILES0)->set_granularity(16);
m_ts_tilemap[TM_TILES1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_16c<1>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
m_ts_tilemap[TM_TILES1]->set_transparent_pen(0);
m_gfxdecode->gfx(TM_TILES1)->set_granularity(16);
m_gfxdecode->gfx(TM_SPRITES)->set_granularity(16);
m_frame_irq_timer = timer_alloc(FUNC(tsconf_state::irq_frame), this);
m_scanline_irq_timer = timer_alloc(FUNC(tsconf_state::irq_scanline), this);
@ -247,6 +238,9 @@ void tsconf_state::device_post_load()
{
spectrum_128_state::device_post_load();
m_sprites_cache.clear();
copy_tiles_to_raw(m_ram->pointer() + ((m_regs[SG_PAGE] & 0xf8) << 14), m_sprites_raw.target());
copy_tiles_to_raw(m_ram->pointer() + ((m_regs[T0_G_PAGE] & 0xf8) << 14), m_sprites_raw.target());
copy_tiles_to_raw(m_ram->pointer() + ((m_regs[T1_G_PAGE] & 0xf8) << 14), m_sprites_raw.target());
}
INPUT_PORTS_START( tsconf )
@ -323,7 +317,7 @@ void tsconf_state::tsconf(machine_config &config)
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "mono", 0.75);;
PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256);
PALETTE(config, "palette", palette_device::BLACK, 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();

View File

@ -29,6 +29,8 @@ public:
tsconf_state(const machine_config &mconfig, device_type type, const char *tag)
: spectrum_128_state(mconfig, type, tag)
, m_bank0_rom(*this, "bank0_rom")
, m_tiles_raw(*this, "tiles%u_raw", 0U, 64U * 64 * 8 * 8, ENDIANNESS_LITTLE)
, m_sprites_raw(*this, "sprites_raw", 64U * 64 * 8 * 8, ENDIANNESS_LITTLE)
, m_keyboard(*this, "pc_keyboard")
, m_io_mouse(*this, "mouse_input%u", 1U)
, m_beta(*this, BETA_DISK_TAG)
@ -170,8 +172,8 @@ private:
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();
void copy_tiles_to_raw(const u8 *tiles_src, u8 *raw_target);
u8 tsconf_port_xx1f_r(offs_t offset);
void tsconf_port_7ffd_w(u8 data);
@ -214,6 +216,8 @@ private:
memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_program;
memory_view m_bank0_rom;
memory_share_array_creator<u8, 2> m_tiles_raw;
memory_share_creator<u8> m_sprites_raw;
required_device<at_keyboard_device> m_keyboard;
required_ioport_array<3> m_io_mouse;

View File

@ -29,11 +29,6 @@ enum v_mode : u8
VM_TXT
};
static constexpr u32 tmp_tile_oversized_to_code(u16 code)
{
return code / 64 * 64 * 8 + (code % 64);
}
// https://github.com/tslabs/zx-evo/blob/master/pentevo/vdac/vdac1/cpld/top.v
static constexpr u8 pwm_to_rgb[32] = {
0, 10, 21, 31, 42, 53, 63, 74,
@ -54,12 +49,6 @@ rectangle tsconf_state::get_screen_area()
return info;
}
void tsconf_state::tsconf_palette(palette_device &palette) const
{
rgb_t colors[256] = {0};
palette.set_pen_colors(0, colors);
}
void tsconf_state::tsconf_update_bank0()
{
u8 page0 = m_regs[PAGE0];
@ -364,7 +353,7 @@ void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_rgb32 &bitmap, c
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,
spr->code, spr->color, spr->flipx, spr->flipy, spr->destx, spr->desty,
screen_d.priority(), spr->pmask, 0);
}
@ -395,6 +384,11 @@ void tsconf_state::ram_bank_write(u8 bank, offs_t offset, u8 data)
ram_page_write(m_regs[PAGE0 + bank], offset, data);
}
static int tiles_offset_to_raw(int t_offset)
{
return bitswap<17>(t_offset, 16, 15, 14, 13, 12, 11, 7, 6, 5, 4, 3, 2, 10, 9, 8, 1, 0) << 1;
}
void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
{
u32 ram_addr = PAGE4K(page) + offset;
@ -405,15 +399,21 @@ 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))
const int t0_offset = ram_addr - PAGE4K(m_regs[T0_G_PAGE] & 0xf8);
if ((t0_offset >= 0) && (t0_offset < PAGE4K(8)))
{
m_gfxdecode->gfx(TM_TILES0)->mark_all_dirty();
const int raw_offset = tiles_offset_to_raw(t0_offset);
m_tiles_raw[0][raw_offset] = data >> 4;
m_tiles_raw[0][raw_offset + 1] = data & 0x0f;
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))
const int t1_offset = ram_addr - PAGE4K(m_regs[T1_G_PAGE] & 0xf8);
if ((t1_offset >= 0) && (t1_offset < PAGE4K(8)))
{
m_gfxdecode->gfx(TM_TILES1)->mark_all_dirty();
const int raw_offset = tiles_offset_to_raw(t1_offset);
m_tiles_raw[1][raw_offset] = data >> 4;
m_tiles_raw[1][raw_offset + 1] = data & 0x0f;
m_ts_tilemap[TM_TILES1]->mark_all_dirty();
}
}
@ -424,8 +424,13 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
if (ram_addr >= PAGE4K(m_regs[m_regs[V_PAGE] ^ 0x01]) && ram_addr < PAGE4K(m_regs[m_regs[V_PAGE] ^ 0x01] + 1))
m_gfxdecode->gfx(TM_TS_CHAR)->mark_all_dirty();
if (ram_addr >= PAGE4K(m_regs[SG_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[SG_PAGE] & 0xf8) + 8))
m_gfxdecode->gfx(TM_SPRITES)->mark_all_dirty();
const int spr_offset = ram_addr - PAGE4K(m_regs[SG_PAGE] & 0xf8);
if ((spr_offset >= 0) && (spr_offset < PAGE4K(8)))
{
const int raw_offset = tiles_offset_to_raw(spr_offset);
m_sprites_raw[raw_offset] = data >> 4;
m_sprites_raw[raw_offset + 1] = data & 0x0f;
}
m_ram->pointer()[ram_addr] = data;
}
@ -438,7 +443,7 @@ u16 tsconf_state::ram_read16(offs_t offset)
void tsconf_state::ram_write16(offs_t offset, u16 data)
{
ram_page_write(0, offset & ~offs_t(1), data >> 8);
m_ram->pointer()[offset | 1] = data & 0xff;
ram_page_write(0, offset | 1, data & 0xff);
}
u16 tsconf_state::spi_read16()
@ -534,6 +539,20 @@ u8 tsconf_state::tsconf_port_xxaf_r(offs_t port)
return data;
}
void tsconf_state::copy_tiles_to_raw(const u8 *tiles_src, u8 *raw_target)
{
for(u32 ln = 0; ln < PAGE4K(8); ln += 4)
{
int targ = tiles_offset_to_raw(ln);
for (u8 x = 0; x < 4; ++x)
{
const u8 data = tiles_src[ln + x];
raw_target[targ + (x << 1)] = data >> 4;
raw_target[targ + (x << 1) + 1] = data & 0x0f;
}
}
}
void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
{
u8 nreg = port >> 8;
@ -666,7 +685,7 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
break;
case SG_PAGE:
m_gfxdecode->gfx(TM_SPRITES)->set_source(m_ram->pointer() + PAGE4K(data & 0xf8));
copy_tiles_to_raw(m_ram->pointer() + PAGE4K(data & 0xf8), m_sprites_raw.target());
break;
case SYS_CONFIG:
@ -916,12 +935,12 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline)
break;
case T0_G_PAGE:
m_gfxdecode->gfx(TM_TILES0)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8));
copy_tiles_to_raw(m_ram->pointer() + PAGE4K(val & 0xf8), m_tiles_raw[0].target());
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));
copy_tiles_to_raw(m_ram->pointer() + PAGE4K(val & 0xf8), m_tiles_raw[1].target());
m_ts_tilemap[TM_TILES1]->mark_all_dirty();
break;