summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/tmap038.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/tmap038.cpp')
-rw-r--r--src/mame/video/tmap038.cpp266
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);
+}