diff options
Diffstat (limited to 'src/mame/video/tmap038.cpp')
-rw-r--r-- | src/mame/video/tmap038.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/mame/video/tmap038.cpp b/src/mame/video/tmap038.cpp new file mode 100644 index 00000000000..ef66c49c868 --- /dev/null +++ b/src/mame/video/tmap038.cpp @@ -0,0 +1,266 @@ +// license:BSD-3-Clause +// copyright-holders:Luca Elia, Paul Priest, David Haywood +/* 038 Tilemap generator manufactured by NEC */ + +/* + [ Scrolling Layers ] + + Each 038 chip generates 1 layer. Up to 4 chips are used + (4 layers) + + Layer Size: 512 x 512 + Tiles: 8 x 8 & 16 x 16. + + There are 2 tilemaps in memory, one per tiles dimension. + A bit decides which one gets displayed. + The tiles depth varies with games, from 16 to 256 colors. + + A per layer row-scroll / row-select effect can be enabled: + + a different scroll value is fetched (from tile RAM) for each + scan line, and a different tilemap line for each scan line + + + +*************************************************************************** + + Callbacks for the TileMap code + + [ Tiles Format ] + + Offset: Bits: Value: + + 0.w fe-- ---- ---- --- Priority + --dc ba98 ---- ---- Color + ---- ---- 7654 3210 + + 2.w Code + + + When a row-scroll / row-select effect is enabled, the scroll values are + fetched starting from tile RAM + $1000, 4 bytes per scan line: + + Offset: Value: + + 0.w Tilemap line to display + 2.w X Scroll value + +*************************************************************************** + +*************************************************************************** + + Layers Registers + + + Offset: Bits: Value: + + 0.w f--- ---- ---- ---- 0 = Layer Flip X + -e-- ---- ---- ---- Activate Row-scroll + --d- ---- ---- ---- + ---c ba9- ---- ---- + ---- ---8 7654 3210 Scroll X + + 2.w f--- ---- ---- ---- 0 = Layer Flip Y + -e-- ---- ---- ---- Activate Row-select + --d- ---- ---- ---- 0 = 8x8 tiles, 1 = 16x16 tiles + ---c ba9- ---- ---- + ---- ---8 7654 3210 Scroll Y + + 4.w fedc ba98 765- ---- + ---- ---- ---4 ---- Layer Disable + ---- ---- ---- 3210 Varies* + + *color bank for mcatadv or Layer-Layer priority for cave + +There are more! + +*************************************************************************** + +TODO: + de-fragmentation and merge drawing behavior into tmap038.cpp + +*************************************************************************** + +*/ + +#include "emu.h" +#include "tmap038.h" + +void tilemap038_device::vram_map(address_map &map) +{ + map(0x0000, 0x0fff).rw(FUNC(tilemap038_device::vram_16x16_r), FUNC(tilemap038_device::vram_16x16_w)).share("vram_16x16"); + map(0x1000, 0x17ff).rw(FUNC(tilemap038_device::lineram_r), FUNC(tilemap038_device::lineram_w)).share("lineram"); + map(0x1800, 0x3fff).ram().share("scratchpad"); // scratchpad? + map(0x4000, 0x7fff).rw(FUNC(tilemap038_device::vram_8x8_r), FUNC(tilemap038_device::vram_8x8_w)).share("vram_8x8"); +} + +void tilemap038_device::vram_writeonly_map(address_map &map) +{ + map(0x0000, 0x0fff).w(FUNC(tilemap038_device::vram_16x16_w)).share("vram_16x16"); + map(0x1000, 0x17ff).w(FUNC(tilemap038_device::lineram_w)).share("lineram"); + map(0x1800, 0x3fff).writeonly().share("scratchpad"); // scratchpad? + map(0x4000, 0x7fff).w(FUNC(tilemap038_device::vram_8x8_w)).share("vram_8x8"); +} + +void tilemap038_device::vram_16x16_map(address_map &map) +{ + map(0x0000, 0x0fff).rw(FUNC(tilemap038_device::vram_16x16_r), FUNC(tilemap038_device::vram_16x16_w)).share("vram_16x16"); + map(0x1000, 0x17ff).rw(FUNC(tilemap038_device::lineram_r), FUNC(tilemap038_device::lineram_w)).share("lineram"); + map(0x1800, 0x3fff).ram().share("scratchpad"); // scratchpad? +} + +void tilemap038_device::vram_16x16_writeonly_map(address_map &map) +{ + map(0x0000, 0x0fff).w(FUNC(tilemap038_device::vram_16x16_w)).share("vram_16x16"); + map(0x1000, 0x17ff).w(FUNC(tilemap038_device::lineram_w)).share("lineram"); + map(0x1800, 0x3fff).writeonly().share("scratchpad"); // scratchpad? +} + +/* Some games, that only ever use the 8x8 tiles and no line scroll, + use mirror ram. For example in donpachi, writes to 400000-403fff + and 408000-407fff both go to the 8x8 tilemap ram. Use this function + in this cases. Note that the get_tile_info function looks in the + 4000-7fff range for tiles, so we have to write the data there. */ +void tilemap038_device::vram_8x8_map(address_map &map) +{ + map(0x0000, 0x3fff).mirror(0x4000).rw(FUNC(tilemap038_device::vram_8x8_r), FUNC(tilemap038_device::vram_8x8_w)).share("vram_8x8"); +} + +DEFINE_DEVICE_TYPE(TMAP038, tilemap038_device, "tmap038", "038 Tilemap generator") + +tilemap038_device::tilemap038_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, TMAP038, tag, owner, clock) + , m_vram_8x8(*this, "vram_8x8") + , m_vram_16x16(*this, "vram_16x16") + , m_lineram(*this, "lineram") + , m_vregs(nullptr) + , m_tiledim(false) + , m_gfxdecode(*this, finder_base::DUMMY_TAG) + , m_gfxno(0) +{ +} + +TILE_GET_INFO_MEMBER(tilemap038_device::get_tile_info) +{ + u32 tile, code, color, pri; + + if (m_tiledim) + { + tile = (tile_index % (512 / 8)) / 2 + ((tile_index / (512 / 8)) / 2) * (512 / 16); + tile = (m_vram_16x16 != nullptr) ? ((m_vram_16x16[tile * 2] << 16) + m_vram_16x16[(tile * 2) + 1]) : 0; + + color = (tile & 0x3f000000) >> (32 - 8); + pri = (tile & 0xc0000000) >> (32 - 2); + code = (tile & 0x0000ffff) * 4; + + code ^= tile_index & 1; + code ^= ((tile_index / (512 / 8)) & 1) * 2; + + if (!m_038_cb.isnull()) + m_038_cb(true, color, pri, code); + } + else + { + tile = (m_vram_8x8 != nullptr) ? ((m_vram_8x8[tile_index * 2] << 16) + m_vram_8x8[(tile_index * 2) + 1]) : 0; + + color = (tile & 0x3f000000) >> (32 - 8); + pri = (tile & 0xc0000000) >> (32 - 2); + code = (tile & 0x0003ffff); + + if (!m_038_cb.isnull()) + m_038_cb(false, color, pri, code); + } + + SET_TILE_INFO_MEMBER(m_gfxno, code, color, 0); + tileinfo.category = pri; +} + + +void tilemap038_device::device_start() +{ + m_038_cb.bind_relative_to(*owner()); + m_vregs = make_unique_clear<u16[]>(0x6/2); + + if (m_vram_16x16 == nullptr && m_vram_8x8 == nullptr) + fatalerror("Tilemap 038 %s: VRAM not found",this->tag()); + + if (m_vram_8x8 == nullptr) + m_tiledim = true; + else if (m_vram_16x16 == nullptr) + m_tiledim = false; + + m_tmap = &machine().tilemap().create( + *m_gfxdecode, + tilemap_get_info_delegate(FUNC(tilemap038_device::get_tile_info),this), + TILEMAP_SCAN_ROWS, + 8,8, 512 / 8,512 / 8); + + m_tmap->set_transparent_pen(0); + + set_scroll_rows(1); // Initialize scroll rows + set_scroll_cols(1); // Initialize scroll cols + + save_item(NAME(m_tiledim)); + save_pointer(NAME(m_vregs), 0x6/2); +} + +void tilemap038_device::device_reset() +{ +} + +u16 tilemap038_device::vram_8x8_r(offs_t offset) +{ + return m_vram_8x8[offset]; +} + +void tilemap038_device::vram_8x8_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_vram_8x8[offset]); + if (!m_tiledim) + m_tmap->mark_tile_dirty(offset/2); +} + +u16 tilemap038_device::vram_16x16_r(offs_t offset) +{ + return m_vram_16x16[offset]; +} + +void tilemap038_device::vram_16x16_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_vram_16x16[offset]); + if (m_tiledim) + { + offset /= 2; + offset = (offset % (512 / 16)) * 2 + (offset / (512 / 16)) * (512 / 8) * 2; + m_tmap->mark_tile_dirty(offset + 0); + m_tmap->mark_tile_dirty(offset + 1); + m_tmap->mark_tile_dirty(offset + 0 + 512 / 8); + m_tmap->mark_tile_dirty(offset + 1 + 512 / 8); + } +} + +void tilemap038_device::prepare() +{ + /* Enable layers */ + m_tmap->enable(enable()); + + // refresh tile size + if (m_vram_8x8 != nullptr && m_vram_16x16 != nullptr) + { + const bool new_tiledim = BIT(m_vregs[1], 13); + if (m_tiledim != new_tiledim) + { + m_tmap->mark_all_dirty(); + m_tiledim = new_tiledim; + } + } +} + +void tilemap038_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u32 flags, u8 pri, u8 pri_mask) { draw_common(screen, bitmap, cliprect, flags, pri, pri_mask); } +void tilemap038_device::draw(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 flags, u8 pri, u8 pri_mask) { draw_common(screen, bitmap, cliprect, flags, pri, pri_mask); } + +template<class _BitmapClass> +void tilemap038_device::draw_common(screen_device &screen, _BitmapClass &bitmap, const rectangle &cliprect, u32 flags, u8 pri, u8 pri_mask) +{ + m_tmap->draw(screen, bitmap, cliprect, flags, pri, pri_mask); +} |