From 8462d66f4ddfd786a13208c3516bfd811ad47b24 Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 21 Nov 2024 03:51:52 +0900 Subject: fuuki/fuukitmap.cpp: Extracted common tilemap handling from fuukifg2.cpp and fuukifg3.cpp. (#12981) fuuki/fuukispr.cpp: Use generic graphics decoding layout, improve naming (it just emulates sprite hardware). --- src/mame/fuuki/fuukifg.cpp | 180 -------------------------- src/mame/fuuki/fuukifg.h | 38 ------ src/mame/fuuki/fuukifg2.cpp | 278 ++++++---------------------------------- src/mame/fuuki/fuukifg3.cpp | 295 ++++++++----------------------------------- src/mame/fuuki/fuukispr.cpp | 180 ++++++++++++++++++++++++++ src/mame/fuuki/fuukispr.h | 39 ++++++ src/mame/fuuki/fuukitmap.cpp | 267 +++++++++++++++++++++++++++++++++++++++ src/mame/fuuki/fuukitmap.h | 119 +++++++++++++++++ 8 files changed, 698 insertions(+), 698 deletions(-) delete mode 100644 src/mame/fuuki/fuukifg.cpp delete mode 100644 src/mame/fuuki/fuukifg.h create mode 100644 src/mame/fuuki/fuukispr.cpp create mode 100644 src/mame/fuuki/fuukispr.h create mode 100644 src/mame/fuuki/fuukitmap.cpp create mode 100644 src/mame/fuuki/fuukitmap.h diff --git a/src/mame/fuuki/fuukifg.cpp b/src/mame/fuuki/fuukifg.cpp deleted file mode 100644 index f12ad67850b..00000000000 --- a/src/mame/fuuki/fuukifg.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders: Luca Elia, David Haywood - - -#include "emu.h" -#include "fuukifg.h" -#include "screen.h" - -DEFINE_DEVICE_TYPE(FUUKI_VIDEO, fuukivid_device, "fuukivid", "Fuuki Video") - -fuukivid_device::fuukivid_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, FUUKI_VIDEO, tag, owner, clock) - , device_gfx_interface(mconfig, *this, nullptr) - , device_video_interface(mconfig, *this) - , m_tile_cb(*this) - , m_colpri_cb(*this) - , m_gfx_region(*this, DEVICE_SELF) - , m_colbase(0) - , m_colnum(0x100) -{ -} - -void fuukivid_device::device_start() -{ - // 16x16x4 - gfx_layout layout_16x16x4 = - { - 16,16, - 0, - 4, - { STEP4(0,1) }, - { STEP16(0,4) }, - { STEP16(0,16*4) }, - 16*16*4 - }; - layout_16x16x4.total = m_gfx_region->bytes() / ((16*16*4) / 8); - - m_tile_cb.resolve(); - m_colpri_cb.resolve(); - - set_gfx(0, std::make_unique(&palette(), layout_16x16x4, m_gfx_region->base(), 0, m_colnum, m_colbase)); -} - - -/*************************************************************************** - - - Sprites Drawing - - Offset: Bits: Value: - - 0.w fedc ---- ---- ---- Number Of Tiles Along X - 1 - ---- b--- ---- ---- Flip X - ---- -a-- ---- ---- 1 = Don't Draw This Sprite - ---- --98 7654 3210 X (Signed) - - 2.w fedc ---- ---- ---- Number Of Tiles Along Y - 1 - ---- b--- ---- ---- Flip Y - ---- -a-- ---- ---- - ---- --98 7654 3210 Y (Signed) - - 4.w fedc ---- ---- ---- Zoom X ($0 = Full Size, $F = Half Size) - ---- ba98 ---- ---- Zoom Y "" - ---- ---- 76-- ---- Priority - ---- ---- --54 3210 Color - - 6.w Tile Code - - for FG3 hardware - - 6.w fe-- ---- ---- ---- Tile Bank - --dc ba98 7654 3210 Tile Code - -***************************************************************************/ - -void fuukivid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, bool flip_screen, u16 *spriteram, u32 size) -{ - // as we're likely framebuffered (sprites are delayed by 2-3 frames, at least on FG3, and doing rasters on sprites causes glitches) we - // only draw the sprites when MAME wants to draw the final screen line. Ideally we should framebuffer them instead. - if (cliprect.max_y != screen.visible_area().max_y) - return; - - const bool tilebank = !m_tile_cb.isnull(); - const bool priority = !m_colpri_cb.isnull(); - const rectangle spriteclip = screen.visible_area(); - - const int max_x = spriteclip.max_x + 1; - const int max_y = spriteclip.max_y + 1; - - int start, end, inc; - if (priority) { start = size - 4; end = -4; inc = -4; } - else { start = 0; end = size; inc = +4; } - - // Draw them backwards, for pdrawgfx - for (int offs = start; offs != end; offs += inc) - { - const u16 data0 = spriteram[offs + 0]; - const u16 data1 = spriteram[offs + 1]; - const u16 attr = spriteram[offs + 2]; - u32 code = spriteram[offs + 3]; - if (tilebank) - m_tile_cb(code); - - if (data0 & 0x400) - continue; - - int flipx = data0 & 0x0800; - int flipy = data1 & 0x0800; - - const int xnum = ((data0 >> 12) & 0xf) + 1; - const int ynum = ((data1 >> 12) & 0xf) + 1; - - const int xzoom = 16 * 8 - (8 * ((attr >> 12) & 0xf)) / 2; - const int yzoom = 16 * 8 - (8 * ((attr >> 8) & 0xf)) / 2; - - u32 pri_mask = 0; - u32 colour = attr & 0xff; - if (priority) - m_colpri_cb(colour, pri_mask); - - int sx = (data0 & 0x1ff) - (data0 & 0x200); - int sy = (data1 & 0x1ff) - (data1 & 0x200); - - if (flip_screen) - { - flipx = !flipx; sx = max_x - sx - xnum * 16; - flipy = !flipy; sy = max_y - sy - ynum * 16; - } - - int xstart, ystart, xend, yend, xinc, yinc; - if (flipx) { xstart = xnum-1; xend = -1; xinc = -1; } - else { xstart = 0; xend = xnum; xinc = +1; } - - if (flipy) { ystart = ynum-1; yend = -1; yinc = -1; } - else { ystart = 0; yend = ynum; yinc = +1; } - - for (int y = ystart; y != yend; y += yinc) - { - for (int x = xstart; x != xend; x += xinc) - { - if (priority) - { - if (xzoom == (16*8) && yzoom == (16*8)) - gfx(0)->prio_transpen(bitmap, spriteclip, - code++, - colour, - flipx, flipy, - sx + x * 16, sy + y * 16, - screen.priority(), pri_mask, 15); - else - gfx(0)->prio_zoom_transpen(bitmap, spriteclip, - code++, - colour, - flipx, flipy, - sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, - (0x10000/0x10/8) * (xzoom + 8), (0x10000/0x10/8) * (yzoom + 8),// nearest greater integer value to avoid holes - screen.priority(), pri_mask, 15); - } - else - { - if (xzoom == (16*8) && yzoom == (16*8)) - gfx(0)->transpen(bitmap, spriteclip, - code++, - colour, - flipx, flipy, - sx + x * 16, sy + y * 16, - 15); - else - gfx(0)->zoom_transpen(bitmap, spriteclip, - code++, - colour, - flipx, flipy, - sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, - (0x10000/0x10/8) * (xzoom + 8), (0x10000/0x10/8) * (yzoom + 8),// nearest greater integer value to avoid holes - 15); - } - } - } - } -} diff --git a/src/mame/fuuki/fuukifg.h b/src/mame/fuuki/fuukifg.h deleted file mode 100644 index e4f924bc3be..00000000000 --- a/src/mame/fuuki/fuukifg.h +++ /dev/null @@ -1,38 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders: Luca Elia, David Haywood - -#ifndef MAME_FUUKI_FUUKIFG_H -#define MAME_FUUKI_FUUKIFG_H - -#pragma once - -class fuukivid_device : public device_t, public device_gfx_interface, public device_video_interface -{ -public: - typedef device_delegate tile_delegate; - typedef device_delegate colpri_cb_delegate; - - fuukivid_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - - // configuration - void set_color_base(u16 base) { m_colbase = base; } - void set_color_num(u16 num) { m_colnum = num; } - template void set_tile_callback(T &&... args) { m_tile_cb.set(std::forward(args)...); } - template void set_colpri_callback(T &&... args) { m_colpri_cb.set(std::forward(args)...); } - - void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, bool flip_screen, u16 *spriteram, u32 size); - -protected: - virtual void device_start() override ATTR_COLD; - -private: - tile_delegate m_tile_cb; - colpri_cb_delegate m_colpri_cb; - required_memory_region m_gfx_region; - u16 m_colbase; - u16 m_colnum; -}; - -DECLARE_DEVICE_TYPE(FUUKI_VIDEO, fuukivid_device) - -#endif // MAME_FUUKI_FUUKIFG_H diff --git a/src/mame/fuuki/fuukifg2.cpp b/src/mame/fuuki/fuukifg2.cpp index f34a6a7f8fe..07107373944 100644 --- a/src/mame/fuuki/fuukifg2.cpp +++ b/src/mame/fuuki/fuukifg2.cpp @@ -48,7 +48,8 @@ To Do: #include "emu.h" -#include "fuukifg.h" +#include "fuukispr.h" +#include "fuukitmap.h" #include "cpu/z80/z80.h" #include "cpu/m68000/m68000.h" @@ -76,13 +77,10 @@ public: , m_gfxdecode(*this, "gfxdecode") , m_screen(*this, "screen") , m_palette(*this, "palette") - , m_fuukivid(*this, "fuukivid") + , m_fuukispr(*this, "fuukispr") + , m_fuukitmap(*this, "fuukitmap") , m_soundlatch(*this, "soundlatch") , m_spriteram(*this, "spriteram") - , m_vram(*this, "vram.%u", 0) - , m_vregs(*this, "vregs") - , m_unknown(*this, "unknown") - , m_priority(*this, "priority") , m_soundbank(*this, "soundbank") { } @@ -90,7 +88,6 @@ public: protected: virtual void machine_start() override ATTR_COLD; - virtual void machine_reset() override ATTR_COLD; virtual void video_start() override ATTR_COLD; private: @@ -101,46 +98,25 @@ private: required_device m_gfxdecode; required_device m_screen; required_device m_palette; - required_device m_fuukivid; + required_device m_fuukispr; + required_device m_fuukitmap; required_device m_soundlatch; // memory pointers required_shared_ptr m_spriteram; - required_shared_ptr_array m_vram; - required_shared_ptr m_vregs; - required_shared_ptr m_unknown; - required_shared_ptr m_priority; required_memory_bank m_soundbank; - // video-related - tilemap_t *m_tilemap[3]{}; - - // misc - emu_timer *m_level_1_interrupt_timer = nullptr; - emu_timer *m_vblank_interrupt_timer = nullptr; - emu_timer *m_raster_interrupt_timer = nullptr; - void main_map(address_map &map) ATTR_COLD; void sound_io_map(address_map &map) ATTR_COLD; void sound_map(address_map &map) ATTR_COLD; - TIMER_CALLBACK_MEMBER(level1_interrupt); - TIMER_CALLBACK_MEMBER(vblank_interrupt); - TIMER_CALLBACK_MEMBER(raster_interrupt); - - void vregs_w(offs_t offset, u16 data, u16 mem_mask = ~0); void sound_command_w(u8 data); void sound_rombank_w(u8 data); - template void vram_w(offs_t offset, u16 data, u16 mem_mask = ~0); - template void vram_buffered_w(offs_t offset, u16 data, u16 mem_mask = ~0); void oki_banking_w(u8 data); - template TILE_GET_INFO_MEMBER(get_tile_info); - void colpri_cb(u32 &colour, u32 &pri_mask); u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u8 i, int flag, u8 pri, u8 primask = 0xff); }; @@ -164,32 +140,6 @@ private: ***************************************************************************/ -/*************************************************************************** - - - Tilemaps - - Offset: Bits: Value: - - 0.w Code - - 2.w fedc ba98 ---- ---- - ---- ---- 7--- ---- Flip Y - ---- ---- -6-- ---- Flip X - ---- ---- --54 3210 Color - - -***************************************************************************/ - -template -TILE_GET_INFO_MEMBER(fuuki16_state::get_tile_info) -{ - const int buffer = (Layer < 2) ? 0 : (m_vregs[0x1e / 2] & 0x40) >> 6; - const u16 code = m_vram[Layer|buffer][2 * tile_index + 0]; - const u16 attr = m_vram[Layer|buffer][2 * tile_index + 1]; - tileinfo.set(Layer, code, attr & 0x3f, TILE_FLIPYX((attr >> 6) & 3)); -} - /*************************************************************************** @@ -200,15 +150,11 @@ TILE_GET_INFO_MEMBER(fuuki16_state::get_tile_info) void fuuki16_state::video_start() { - m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fuuki16_state::get_tile_info<0>)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); - m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fuuki16_state::get_tile_info<1>)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); - m_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fuuki16_state::get_tile_info<2>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); - - m_tilemap[0]->set_transparent_pen(0x0f); // 4 bits - m_tilemap[1]->set_transparent_pen(0xff); // 8 bits - m_tilemap[2]->set_transparent_pen(0x0f); // 4 bits + m_fuukitmap->set_transparent_pen(0, 0x0f); // 4 bits + m_fuukitmap->set_transparent_pen(1, 0xff); // 8 bits + m_fuukitmap->set_transparent_pen(2, 0x0f); // 4 bits - m_gfxdecode->gfx(1)->set_granularity(16); // 256 colour tiles with palette selectable on 16 colour boundaries + m_fuukitmap->gfx(1)->set_granularity(16); // 256 colour tiles with palette selectable on 16 colour boundaries } @@ -227,100 +173,25 @@ void fuuki16_state::colpri_cb(u32 &colour, u32 &pri_mask) } -/*************************************************************************** - - - Screen Drawing - - Video Registers (vregs): - - 00.w Layer 0 Scroll Y - 02.w Layer 0 Scroll X - 04.w Layer 1 Scroll Y - 06.w Layer 1 Scroll X - 08.w Layer 2 Scroll Y - 0a.w Layer 2 Scroll X - 0c.w Layers Y Offset - 0e.w Layers X Offset - - 10-1a.w ? 0 - 1c.w Trigger a level 5 irq on this raster line - 1e.w ? $3390/$3393 (Flip Screen Off/On), $0040 is buffer for tilemap 2 - - Priority Register (priority): - - fedc ba98 7654 3--- - ---- ---- ---- -210 Layer Order - - - Unknown Registers (unknown): - - 00.w ? $0200/$0201 (Flip Screen Off/On) - 02.w ? $f300/$0330 - -***************************************************************************/ - -// Wrapper to handle bg and bg2 together -void fuuki16_state::draw_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u8 i, int flag, u8 pri, u8 primask) -{ - m_tilemap[i]->draw(screen, bitmap, cliprect, flag, pri, primask); -} - u32 fuuki16_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - /* - It's not independent bits causing layers to switch, that wouldn't make sense with 3 bits. - See fuukifg3 for more justification - */ - static const u8 pri_table[6][3] = { - { 0, 1, 2 }, - { 0, 2, 1 }, - { 1, 0, 2 }, - { 1, 2, 0 }, - { 2, 0, 1 }, - { 2, 1, 0 }}; - - const u8 tm_front = pri_table[m_priority[0] & 0x0f][0]; - const u8 tm_middle = pri_table[m_priority[0] & 0x0f][1]; - const u8 tm_back = pri_table[m_priority[0] & 0x0f][2]; - - flip_screen_set(m_vregs[0x1e / 2] & 1); - - // Layers scrolling - - const u16 scrolly_offs = m_vregs[0xc / 2] - (flip_screen() ? 0x103 : 0x1f3); - const u16 scrollx_offs = m_vregs[0xe / 2] - (flip_screen() ? 0x2a7 : 0x3f6); - - const u16 layer0_scrolly = m_vregs[0x0 / 2] + scrolly_offs; - const u16 layer0_scrollx = m_vregs[0x2 / 2] + scrollx_offs; - const u16 layer1_scrolly = m_vregs[0x4 / 2] + scrolly_offs; - const u16 layer1_scrollx = m_vregs[0x6 / 2] + scrollx_offs; - - const u16 layer2_scrolly = m_vregs[0x8 / 2]; - const u16 layer2_scrollx = m_vregs[0xa / 2]; - - m_tilemap[0]->set_scrollx(0, layer0_scrollx); - m_tilemap[0]->set_scrolly(0, layer0_scrolly); - m_tilemap[1]->set_scrollx(0, layer1_scrollx); - m_tilemap[1]->set_scrolly(0, layer1_scrolly); - - m_tilemap[2]->set_scrollx(0, layer2_scrollx + 0x10); - m_tilemap[2]->set_scrolly(0, layer2_scrolly /*+ 0x02*/); + m_fuukitmap->prepare(); + flip_screen_set(m_fuukitmap->flip_screen()); /* The backmost tilemap decides the background color(s) but sprites can go below the opaque pixels of that tilemap. We thus need to mark the transparent pixels of this layer with a different priority value */ -// draw_layer(screen, bitmap, cliprect, tm_back, TILEMAP_DRAW_OPAQUE, 0); +// m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_back(), TILEMAP_DRAW_OPAQUE, 0); /* Actually, bg colour is simply the last pen i.e. 0x1fff -pjp */ bitmap.fill((0x800 * 4) - 1, cliprect); screen.priority().fill(0, cliprect); - draw_layer(screen, bitmap, cliprect, tm_back, 0, 1); - draw_layer(screen, bitmap, cliprect, tm_middle, 0, 2); - draw_layer(screen, bitmap, cliprect, tm_front, 0, 4); + m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_back(), 0, 1); + m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_middle(), 0, 2); + m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_front(), 0, 4); - m_fuukivid->draw_sprites(screen, bitmap, cliprect, flip_screen(), m_spriteram, m_spriteram.bytes() / 2); + m_fuukispr->draw_sprites(screen, bitmap, cliprect, flip_screen(), m_spriteram, m_spriteram.bytes() / 2); return 0; } @@ -330,26 +201,6 @@ u32 fuuki16_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, co // memory - main CPU //------------------------------------------------- -void fuuki16_state::vregs_w(offs_t offset, u16 data, u16 mem_mask) -{ - const u16 old = m_vregs[offset]; - data = COMBINE_DATA(&m_vregs[offset]); - if (old != data) - { - if (offset == 0x1c / 2) - { - const rectangle &visarea = m_screen->visible_area(); - attotime period = m_screen->frame_period(); - m_raster_interrupt_timer->adjust(m_screen->time_until_pos(data, visarea.max_x + 1), 0, period); - } - if (offset == 0x1e / 2) - { - if ((old ^ data) & 0x40) - m_tilemap[2]->mark_all_dirty(); - } - } -} - void fuuki16_state::sound_command_w(u8 data) { m_soundlatch->write(data); @@ -358,39 +209,18 @@ void fuuki16_state::sound_command_w(u8 data) machine().scheduler().perfect_quantum(attotime::from_usec(50)); // Fixes glitching in rasters } -template -void fuuki16_state::vram_w(offs_t offset, u16 data, u16 mem_mask) -{ - COMBINE_DATA(&m_vram[Layer][offset]); - m_tilemap[Layer]->mark_tile_dirty(offset / 2); -} - -template -void fuuki16_state::vram_buffered_w(offs_t offset, u16 data, u16 mem_mask) -{ - const int buffer = (m_vregs[0x1e / 2] & 0x40) >> 6; - COMBINE_DATA(&m_vram[Layer][offset]); - if ((Layer & 1) == buffer) - m_tilemap[2]->mark_tile_dirty(offset / 2); -} - void fuuki16_state::main_map(address_map &map) { map(0x000000, 0x0fffff).rom(); map(0x400000, 0x40ffff).ram(); - map(0x500000, 0x501fff).ram().w(FUNC(fuuki16_state::vram_w<0>)).share(m_vram[0]); - map(0x502000, 0x503fff).ram().w(FUNC(fuuki16_state::vram_w<1>)).share(m_vram[1]); - map(0x504000, 0x505fff).ram().w(FUNC(fuuki16_state::vram_buffered_w<2>)).share(m_vram[2]); - map(0x506000, 0x507fff).ram().w(FUNC(fuuki16_state::vram_buffered_w<3>)).share(m_vram[3]); + map(0x500000, 0x507fff).m(m_fuukitmap, FUNC(fuukitmap_device::vram_map)); map(0x600000, 0x601fff).mirror(0x008000).ram().share(m_spriteram); // mirrored? map(0x700000, 0x703fff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); map(0x800000, 0x800001).portr("SYSTEM"); map(0x810000, 0x810001).portr("P1_P2"); map(0x880000, 0x880001).portr("DSW"); map(0x8a0001, 0x8a0001).w(FUNC(fuuki16_state::sound_command_w)); - map(0x8c0000, 0x8c001f).ram().w(FUNC(fuuki16_state::vregs_w)).share(m_vregs); - map(0x8d0000, 0x8d0003).ram().share(m_unknown); - map(0x8e0000, 0x8e0001).ram().share(m_priority); + map(0x8c0000, 0x8effff).m(m_fuukitmap, FUNC(fuukitmap_device::vregs_map)); } @@ -643,45 +473,11 @@ GFXDECODE_END also used for water effects and titlescreen linescroll on gogomile */ -TIMER_CALLBACK_MEMBER(fuuki16_state::level1_interrupt) -{ - m_maincpu->set_input_line(1, HOLD_LINE); - m_level_1_interrupt_timer->adjust(m_screen->time_until_pos(248)); -} - -TIMER_CALLBACK_MEMBER(fuuki16_state::vblank_interrupt) -{ - m_maincpu->set_input_line(3, HOLD_LINE); // VBlank IRQ - m_vblank_interrupt_timer->adjust(m_screen->time_until_vblank_start()); -} - -TIMER_CALLBACK_MEMBER(fuuki16_state::raster_interrupt) -{ - m_maincpu->set_input_line(5, HOLD_LINE); // Raster Line IRQ - m_screen->update_partial(m_screen->vpos()); - m_raster_interrupt_timer->adjust(m_screen->frame_period()); -} - - void fuuki16_state::machine_start() { u8 *rom = memregion("audiocpu")->base(); m_soundbank->configure_entries(0, 3, &rom[0x8000], 0x8000); - - m_level_1_interrupt_timer = timer_alloc(FUNC(fuuki16_state::level1_interrupt), this); - m_vblank_interrupt_timer = timer_alloc(FUNC(fuuki16_state::vblank_interrupt), this); - m_raster_interrupt_timer = timer_alloc(FUNC(fuuki16_state::raster_interrupt), this); -} - - -void fuuki16_state::machine_reset() -{ - const rectangle &visarea = m_screen->visible_area(); - - m_level_1_interrupt_timer->adjust(m_screen->time_until_pos(248)); - m_vblank_interrupt_timer->adjust(m_screen->time_until_vblank_start()); - m_raster_interrupt_timer->adjust(m_screen->time_until_pos(0, visarea.max_x + 1)); } @@ -706,11 +502,21 @@ void fuuki16_state::fuuki16(machine_config &config) GFXDECODE(config, m_gfxdecode, m_palette, gfx_fuuki16); PALETTE(config, m_palette, palette_device::BLACK).set_format(palette_device::xRGB_555, 0x4000 / 2); - FUUKI_VIDEO(config, m_fuukivid, 0); - m_fuukivid->set_palette(m_palette); - m_fuukivid->set_color_base(0x400*2); - m_fuukivid->set_color_num(0x40); - m_fuukivid->set_colpri_callback(FUNC(fuuki16_state::colpri_cb)); + FUUKI_SPRITE(config, m_fuukispr, 0); + m_fuukispr->set_palette(m_palette); + m_fuukispr->set_color_base(0x400*2); + m_fuukispr->set_color_num(0x40); + m_fuukispr->set_colpri_callback(FUNC(fuuki16_state::colpri_cb)); + + FUUKI_TILEMAP(config, m_fuukitmap, 0, m_palette, gfx_fuuki16); + m_fuukitmap->set_screen(m_screen); + m_fuukitmap->level_1_irq_callback().set_inputline(m_maincpu, 1, HOLD_LINE); + m_fuukitmap->vblank_irq_callback().set_inputline(m_maincpu, 3, HOLD_LINE); + m_fuukitmap->raster_irq_callback().set_inputline(m_maincpu, 5, HOLD_LINE); + m_fuukitmap->set_xoffs(0x1f3, 0x103); + m_fuukitmap->set_yoffs(0x3f6, 0x2a7); + m_fuukitmap->set_layer2_xoffs(0x10); + //m_fuukitmap->set_layer2_yoffs(0x02); // sound hardware SPEAKER(config, "mono").front_center(); @@ -787,7 +593,7 @@ ROM_START( gogomile ) ROM_REGION( 0x20000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "fs1.rom24", 0x00000, 0x20000, CRC(4e4bd371) SHA1(429e776135ce8960e147762763d952d16ed3f9d4) ) - ROM_REGION( 0x200000, "fuukivid", 0 ) // 16x16x4 sprites + ROM_REGION( 0x200000, "fuukispr", 0 ) // 16x16x4 sprites ROM_LOAD16_WORD_SWAP( "lh537k2r.rom20", 0x000000, 0x200000, CRC(525dbf51) SHA1(f21876676cc60ed65bc86884da894b24830826bb) ) ROM_REGION( 0x200000, "tiles_l0", 0 ) // 16x16x4 tiles @@ -799,7 +605,7 @@ ROM_START( gogomile ) ROM_LOAD32_WORD_SWAP( "lh5370h9.rom16", 0x400000, 0x200000, CRC(e0118483) SHA1(36f9068e6c81c171b4426c3794277742bbc926f5) ) ROM_LOAD32_WORD_SWAP( "lh5370ha.rom12", 0x400002, 0x200000, CRC(5f2a87de) SHA1(d7ed8f01b40aaf58126aaeee10ec7d948a144080) ) - ROM_REGION( 0x200000, "tiles_l2", 0 ) // 16x16x4 tiles + ROM_REGION( 0x200000, "tiles_l2", 0 ) // 8x8x4 tiles ROM_LOAD16_WORD_SWAP( "lh5370hb.rom19", 0x000000, 0x200000, CRC(bd1e896f) SHA1(075f7600cbced1d285cf32fc196844720eb12671) ) // FIRST AND SECOND HALF IDENTICAL // 0x40000 * 4: sounds+speech (Japanese), sounds+speech (English) @@ -815,7 +621,7 @@ ROM_START( gogomileo ) ROM_REGION( 0x20000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "fs1.rom24", 0x00000, 0x20000, CRC(4e4bd371) SHA1(429e776135ce8960e147762763d952d16ed3f9d4) ) - ROM_REGION( 0x200000, "fuukivid", 0 ) // 16x16x4 sprites + ROM_REGION( 0x200000, "fuukispr", 0 ) // 16x16x4 sprites ROM_LOAD16_WORD_SWAP( "lh537k2r.rom20", 0x000000, 0x200000, CRC(525dbf51) SHA1(f21876676cc60ed65bc86884da894b24830826bb) ) ROM_REGION( 0x200000, "tiles_l0", 0 ) // 16x16x4 tiles @@ -827,7 +633,7 @@ ROM_START( gogomileo ) ROM_LOAD32_WORD_SWAP( "lh5370h9.rom16", 0x400000, 0x200000, CRC(e0118483) SHA1(36f9068e6c81c171b4426c3794277742bbc926f5) ) ROM_LOAD32_WORD_SWAP( "lh5370ha.rom12", 0x400002, 0x200000, CRC(5f2a87de) SHA1(d7ed8f01b40aaf58126aaeee10ec7d948a144080) ) - ROM_REGION( 0x200000, "tiles_l2", 0 ) // 16x16x4 tiles + ROM_REGION( 0x200000, "tiles_l2", 0 ) // 8x8x4 tiles ROM_LOAD16_WORD_SWAP( "lh5370hb.rom19", 0x000000, 0x200000, CRC(bd1e896f) SHA1(075f7600cbced1d285cf32fc196844720eb12671) ) // FIRST AND SECOND HALF IDENTICAL // 0x40000 * 4: sounds+speech (Japanese), sounds+speech (English) @@ -877,7 +683,7 @@ ROM_START( pbancho ) // ROMs NO1 & NO2 had an addition block dot on labels ROM_REGION( 0x20000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "no4.rom23", 0x00000, 0x20000, CRC(dfbfdb81) SHA1(84b0cbe843a9bbae43975afdbd029a9b76fd488b) ) - ROM_REGION( 0x200000, "fuukivid", 0 ) // 16x16x4 sprites + ROM_REGION( 0x200000, "fuukispr", 0 ) // 16x16x4 sprites ROM_LOAD16_WORD_SWAP( "58.rom20", 0x000000, 0x200000, CRC(4dad0a2e) SHA1(a4f70557503110a5457b9096a79a5f249095fa55) ) ROM_REGION( 0x200000, "tiles_l0", 0 ) // 16x16x4 tiles @@ -887,7 +693,7 @@ ROM_START( pbancho ) // ROMs NO1 & NO2 had an addition block dot on labels ROM_LOAD32_WORD_SWAP( "59.rom15", 0x000000, 0x200000, CRC(b83dcb70) SHA1(b0b9df451535d85612fa095b4f694cf2e7930bca) ) ROM_LOAD32_WORD_SWAP( "61.rom11", 0x000002, 0x200000, CRC(7f1213b9) SHA1(f8d6432b270c4d0954602e430ddd26841eb05656) ) - ROM_REGION( 0x200000, "tiles_l2", 0 ) // 16x16x4 tiles + ROM_REGION( 0x200000, "tiles_l2", 0 ) // 8x8x4 tiles ROM_LOAD16_WORD_SWAP( "60.rom3", 0x000000, 0x200000, CRC(a50a3c1b) SHA1(a2b30f9f83f5dc2e069d7559aefbda9929fc640c) ) // ?maybe? ROM_REGION( 0x040000, "oki", 0 ) // samples @@ -902,7 +708,7 @@ ROM_START( pbanchoa ) ROM_REGION( 0x20000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "no4.rom23", 0x00000, 0x20000, CRC(dfbfdb81) SHA1(84b0cbe843a9bbae43975afdbd029a9b76fd488b) ) - ROM_REGION( 0x200000, "fuukivid", 0 ) // 16x16x4 sprites + ROM_REGION( 0x200000, "fuukispr", 0 ) // 16x16x4 sprites ROM_LOAD16_WORD_SWAP( "58.rom20", 0x000000, 0x200000, CRC(4dad0a2e) SHA1(a4f70557503110a5457b9096a79a5f249095fa55) ) ROM_REGION( 0x200000, "tiles_l0", 0 ) // 16x16x4 tiles @@ -912,7 +718,7 @@ ROM_START( pbanchoa ) ROM_LOAD32_WORD_SWAP( "59.rom15", 0x000000, 0x200000, CRC(b83dcb70) SHA1(b0b9df451535d85612fa095b4f694cf2e7930bca) ) ROM_LOAD32_WORD_SWAP( "61.rom11", 0x000002, 0x200000, CRC(7f1213b9) SHA1(f8d6432b270c4d0954602e430ddd26841eb05656) ) - ROM_REGION( 0x200000, "tiles_l2", 0 ) // 16x16x4 tiles + ROM_REGION( 0x200000, "tiles_l2", 0 ) // 8x8x4 tiles ROM_LOAD16_WORD_SWAP( "60.rom3", 0x000000, 0x200000, CRC(a50a3c1b) SHA1(a2b30f9f83f5dc2e069d7559aefbda9929fc640c) ) // ?maybe? ROM_REGION( 0x040000, "oki", 0 ) // samples diff --git a/src/mame/fuuki/fuukifg3.cpp b/src/mame/fuuki/fuukifg3.cpp index 685a449a835..176c6d06c6a 100644 --- a/src/mame/fuuki/fuukifg3.cpp +++ b/src/mame/fuuki/fuukifg3.cpp @@ -167,7 +167,8 @@ There is an Asura Buster known to exist on a FG3-SUB-EP containing all EPROMs #include "emu.h" -#include "fuukifg.h" +#include "fuukispr.h" +#include "fuukitmap.h" #include "cpu/m68000/m68020.h" #include "cpu/z80/z80.h" @@ -190,25 +191,21 @@ public: , m_gfxdecode(*this, "gfxdecode") , m_screen(*this, "screen") , m_palette(*this, "palette") - , m_fuukivid(*this, "fuukivid") + , m_fuukispr(*this, "fuukispr") + , m_fuukitmap(*this, "fuukitmap") , m_spriteram(*this, "spriteram", 0x2000, ENDIANNESS_BIG) - , m_vram(*this, "vram.%u", 0) - , m_vregs(*this, "vregs", 0x20, ENDIANNESS_BIG) - , m_priority(*this, "priority") , m_tilebank(*this, "tilebank") , m_shared_ram(*this, "shared_ram") , m_soundbank(*this, "soundbank") , m_system(*this, "SYSTEM") , m_inputs(*this, "INPUTS") - , m_dsw1(*this, "DSW1") - , m_dsw2(*this, "DSW2") + , m_dsw(*this, "DSW%u", 1U) { } void fuuki32(machine_config &config); protected: virtual void machine_start() override ATTR_COLD; - virtual void machine_reset() override ATTR_COLD; virtual void video_start() override ATTR_COLD; private: @@ -217,13 +214,11 @@ private: required_device m_gfxdecode; required_device m_screen; required_device m_palette; - required_device m_fuukivid; + required_device m_fuukispr; + required_device m_fuukitmap; // memory pointers memory_share_creator m_spriteram; - required_shared_ptr_array m_vram; - memory_share_creator m_vregs; - required_shared_ptr m_priority; required_shared_ptr m_tilebank; required_shared_ptr m_shared_ram; std::unique_ptr m_buf_spriteram[2]; @@ -232,43 +227,26 @@ private: required_ioport m_system; required_ioport m_inputs; - required_ioport m_dsw1; - required_ioport m_dsw2; + required_ioport_array<2> m_dsw; // video-related - tilemap_t *m_tilemap[3]{}; u32 m_spr_buffered_tilebank[2]{}; - // misc - emu_timer *m_level_1_interrupt_timer = nullptr; - emu_timer *m_vblank_interrupt_timer = nullptr; - emu_timer *m_raster_interrupt_timer = nullptr; - void main_map(address_map &map) ATTR_COLD; void sound_io_map(address_map &map) ATTR_COLD; void sound_map(address_map &map) ATTR_COLD; - TIMER_CALLBACK_MEMBER(level1_interrupt); - TIMER_CALLBACK_MEMBER(vblank_interrupt); - TIMER_CALLBACK_MEMBER(raster_interrupt); - u8 snd_020_r(offs_t offset); void snd_020_w(offs_t offset, u8 data, u8 mem_mask = ~0); void sprram_w(offs_t offset, u16 data, u16 mem_mask = ~0); u16 sprram_r(offs_t offset); - u16 vregs_r(offs_t offset); - void vregs_w(offs_t offset, u16 data, u16 mem_mask = ~0); void sound_bw_w(u8 data); - template void vram_w(offs_t offset, u32 data, u32 mem_mask = ~0); - template void vram_buffered_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template TILE_GET_INFO_MEMBER(get_tile_info); - void tile_cb(u32 &code); - void colpri_cb(u32 &colour, u32 &pri_mask); + void spr_tile_cb(u32 &code); + void spr_colpri_cb(u32 &colour, u32 &pri_mask); + void tmap_colour_cb(u8 layer, u32 &colour); u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void screen_vblank(int state); - void draw_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u8 i, int flag, u8 pri, u8 primask = 0xff); }; @@ -295,33 +273,6 @@ private: ***************************************************************************/ - -/*************************************************************************** - - - Tilemaps - - Offset: Bits: Value: - - 0.w Code - - 2.w fedc ba98 ---- ---- - ---- ---- 7--- ---- Flip Y - ---- ---- -6-- ---- Flip X - ---- ---- --54 3210 Color - - -***************************************************************************/ - -template -TILE_GET_INFO_MEMBER(fuuki32_state::get_tile_info) -{ - const int buffer = (Layer < 2) ? 0 : (m_vregs[0x1e / 2] & 0x40) >> 6; - const u16 code = (m_vram[Layer|buffer][tile_index] & 0xffff0000) >> 16; - const u16 attr = (m_vram[Layer|buffer][tile_index] & 0x0000ffff); - tileinfo.set(Layer, code, (attr & 0x3f) >> ColShift, TILE_FLIPYX(attr >> 6)); -} - /*************************************************************************** @@ -336,16 +287,12 @@ void fuuki32_state::video_start() m_buf_spriteram[0] = make_unique_clear(spriteram_size / 2); m_buf_spriteram[1] = make_unique_clear(spriteram_size / 2); - m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, NAME((&fuuki32_state::get_tile_info<0, 4>))), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); - m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, NAME((&fuuki32_state::get_tile_info<1, 4>))), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); - m_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, NAME((&fuuki32_state::get_tile_info<2, 0>))), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); - - m_tilemap[0]->set_transparent_pen(0xff); // 8 bits - m_tilemap[1]->set_transparent_pen(0xff); // 8 bits - m_tilemap[2]->set_transparent_pen(0x0f); // 4 bits + m_fuukitmap->set_transparent_pen(0, 0xff); // 8 bits + m_fuukitmap->set_transparent_pen(1, 0xff); // 8 bits + m_fuukitmap->set_transparent_pen(2, 0x0f); // 4 bits - //m_gfxdecode->gfx(0)->set_granularity(16); // 256 colour tiles with palette selectable on 16 colour boundaries - //m_gfxdecode->gfx(1)->set_granularity(16); + //m_fuukitmap->gfx(0)->set_granularity(16); // 256 colour tiles with palette selectable on 16 colour boundaries + //m_fuukitmap->gfx(1)->set_granularity(16); save_pointer(NAME(m_buf_spriteram[0]), spriteram_size / 2); save_pointer(NAME(m_buf_spriteram[1]), spriteram_size / 2); @@ -362,7 +309,7 @@ u16 fuuki32_state::sprram_r(offs_t offset) return m_spriteram[offset]; } -void fuuki32_state::tile_cb(u32 &code) +void fuuki32_state::spr_tile_cb(u32 &code) { const u32 bank = (code & 0xc000) >> 14; @@ -371,7 +318,7 @@ void fuuki32_state::tile_cb(u32 &code) code += bank_lookedup * 0x4000; } -void fuuki32_state::colpri_cb(u32 &colour, u32 &pri_mask) +void fuuki32_state::spr_colpri_cb(u32 &colour, u32 &pri_mask) { const u8 priority = (colour >> 6) & 3; switch (priority) @@ -385,95 +332,26 @@ void fuuki32_state::colpri_cb(u32 &colour, u32 &pri_mask) colour &= 0x3f; } -/*************************************************************************** - - - Screen Drawing - - Video Registers (vregs): - - 00.w Layer 0 Scroll Y - 02.w Layer 0 Scroll X - 04.w Layer 1 Scroll Y - 06.w Layer 1 Scroll X - 08.w Layer 2 Scroll Y - 0a.w Layer 2 Scroll X - 0c.w Layers Y Offset - 0e.w Layers X Offset - - 10-1a.w ? 0 - 1c.w Trigger a level 5 irq on this raster line - 1e.w ? $3390/$3393 (Flip Screen Off/On), $0040 is buffer for tilemap 2 - - Priority Register (priority): - - fedc ba98 7654 3--- - ---- ---- ---- -210 Layer Order - - - Unknown Registers ($de0000.l): - - 00.w ? $0200/$0201 (Flip Screen Off/On) - 02.w ? $f300/$0330 - -***************************************************************************/ - -// Wrapper to handle bg and bg2 together -void fuuki32_state::draw_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u8 i, int flag, u8 pri, u8 primask) +void fuuki32_state::tmap_colour_cb(u8 layer, u32 &colour) { - m_tilemap[i]->draw(screen, bitmap, cliprect, flag, pri, primask); + if (layer < 2) + colour >>= 4; } u32 fuuki32_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - /* - It's not independent bits causing layers to switch, that wouldn't make sense with 3 bits. - */ - - static const u8 pri_table[6][3] = { - { 0, 1, 2 }, // Special moves 0>1, 0>2 (0,1,2 or 0,2,1) - { 0, 2, 1 }, // Two Levels - 0>1 (0,1,2 or 0,2,1 or 2,0,1) - { 1, 0, 2 }, // Most Levels - 2>1 1>0 2>0 (1,0,2) - { 1, 2, 0 }, // Not used? - { 2, 0, 1 }, // Title etc. - 0>1 (0,1,2 or 0,2,1 or 2,0,1) - { 2, 1, 0 }}; // Char Select, prison stage 1>0 (leaves 1,2,0 or 2,1,0) - - const u8 tm_front = pri_table[(m_priority[0] >> 16) & 0x0f][0]; - const u8 tm_middle = pri_table[(m_priority[0] >> 16) & 0x0f][1]; - const u8 tm_back = pri_table[(m_priority[0] >> 16) & 0x0f][2]; - - flip_screen_set(m_vregs[0x1e / 2] & 1); - - // Layers scrolling - - const u16 scrolly_offs = m_vregs[0xc / 2] - (flip_screen() ? 0x103 : 0x1f3); - const u16 scrollx_offs = m_vregs[0xe / 2] - (flip_screen() ? 0x2c7 : 0x3f6); - - const u16 layer0_scrolly = m_vregs[0x0 / 2] + scrolly_offs; - const u16 layer0_scrollx = m_vregs[0x2 / 2] + scrollx_offs; - const u16 layer1_scrolly = m_vregs[0x4 / 2] + scrolly_offs; - const u16 layer1_scrollx = m_vregs[0x6 / 2] + scrollx_offs; - - const u16 layer2_scrolly = m_vregs[0x8 / 2]; - const u16 layer2_scrollx = m_vregs[0xa / 2]; - - m_tilemap[0]->set_scrollx(0, layer0_scrollx); - m_tilemap[0]->set_scrolly(0, layer0_scrolly); - m_tilemap[1]->set_scrollx(0, layer1_scrollx); - m_tilemap[1]->set_scrolly(0, layer1_scrolly); - - m_tilemap[2]->set_scrollx(0, layer2_scrollx); - m_tilemap[2]->set_scrolly(0, layer2_scrolly); + m_fuukitmap->prepare(); + flip_screen_set(m_fuukitmap->flip_screen()); // The bg colour is the last pen i.e. 0x1fff bitmap.fill((0x800 * 4) - 1, cliprect); screen.priority().fill(0, cliprect); - draw_layer(screen, bitmap, cliprect, tm_back, 0, 1); - draw_layer(screen, bitmap, cliprect, tm_middle, 0, 2); - draw_layer(screen, bitmap, cliprect, tm_front, 0, 4); + m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_back(), 0, 1); + m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_middle(), 0, 2); + m_fuukitmap->draw_layer(screen, bitmap, cliprect, m_fuukitmap->tmap_front(), 0, 4); - m_fuukivid->draw_sprites(screen, bitmap, cliprect, flip_screen(), m_buf_spriteram[1].get(), m_spriteram.bytes() / 2); + m_fuukispr->draw_sprites(screen, bitmap, cliprect, flip_screen(), m_buf_spriteram[1].get(), m_spriteram.bytes() / 2); return 0; } @@ -508,69 +386,23 @@ void fuuki32_state::snd_020_w(offs_t offset, u8 data, u8 mem_mask) COMBINE_DATA(&m_shared_ram[offset]); } -u16 fuuki32_state::vregs_r(offs_t offset) -{ - return m_vregs[offset]; -} - -void fuuki32_state::vregs_w(offs_t offset, u16 data, u16 mem_mask) -{ - const u16 old = m_vregs[offset]; - data = COMBINE_DATA(&m_vregs[offset]); - if (old != data) - { - if (offset == 0x1c / 2) - { - const rectangle &visarea = m_screen->visible_area(); - attotime period = m_screen->frame_period(); - m_raster_interrupt_timer->adjust(m_screen->time_until_pos(data, visarea.max_x + 1), 0, period); - } - if (offset == 0x1e / 2) - { - if ((old ^ data) & 0x40) - m_tilemap[2]->mark_all_dirty(); - } - } -} - -template -void fuuki32_state::vram_w(offs_t offset, u32 data, u32 mem_mask) -{ - COMBINE_DATA(&m_vram[Layer][offset]); - m_tilemap[Layer]->mark_tile_dirty(offset); -} - -template -void fuuki32_state::vram_buffered_w(offs_t offset, u32 data, u32 mem_mask) -{ - const int buffer = (m_vregs[0x1e / 2] & 0x40) >> 6; - COMBINE_DATA(&m_vram[Layer][offset]); - if ((Layer & 1) == buffer) - m_tilemap[2]->mark_tile_dirty(offset); -} - void fuuki32_state::main_map(address_map &map) { map(0x000000, 0x1fffff).rom(); map(0x400000, 0x40ffff).ram(); // Work RAM map(0x410000, 0x41ffff).ram(); // Work RAM (used by asurabus) - map(0x500000, 0x501fff).ram().w(FUNC(fuuki32_state::vram_w<0>)).share(m_vram[0]); // Tilemap 1 - map(0x502000, 0x503fff).ram().w(FUNC(fuuki32_state::vram_w<1>)).share(m_vram[1]); // Tilemap 2 - map(0x504000, 0x505fff).ram().w(FUNC(fuuki32_state::vram_buffered_w<2>)).share(m_vram[2]); // Tilemap bg - map(0x506000, 0x507fff).ram().w(FUNC(fuuki32_state::vram_buffered_w<3>)).share(m_vram[3]); // Tilemap bg2 + map(0x500000, 0x507fff).m(m_fuukitmap, FUNC(fuukitmap_device::vram_map)); map(0x508000, 0x517fff).ram(); // More tilemap, or linescroll? Seems to be empty all of the time map(0x600000, 0x601fff).rw(FUNC(fuuki32_state::sprram_r), FUNC(fuuki32_state::sprram_w)); map(0x700000, 0x703fff).ram().w(m_palette, FUNC(palette_device::write32)).share("palette"); map(0x800000, 0x800003).lr16(NAME([this] () { return u16(m_system->read()); })).nopw(); // Coin map(0x810000, 0x810003).lr16(NAME([this] () { return u16(m_inputs->read()); })).nopw(); // Player inputs - map(0x880000, 0x880003).lr16(NAME([this] () { return u16(m_dsw1->read()); })); // Service + DIPs - map(0x890000, 0x890003).lr16(NAME([this] () { return u16(m_dsw2->read()); })); // More DIPs + map(0x880000, 0x880003).lr16(NAME([this] () { return u16(m_dsw[0]->read()); })); // Service + DIPs + map(0x890000, 0x890003).lr16(NAME([this] () { return u16(m_dsw[1]->read()); })); // More DIPs - map(0x8c0000, 0x8c001f).rw(FUNC(fuuki32_state::vregs_r), FUNC(fuuki32_state::vregs_w)); - map(0x8d0000, 0x8d0003).ram(); // Flipscreen related - map(0x8e0000, 0x8e0003).ram().share(m_priority); // Controls layer order + map(0x8c0000, 0x8effff).m(m_fuukitmap, FUNC(fuukitmap_device::vregs_map)); map(0x903fe0, 0x903fff).rw(FUNC(fuuki32_state::snd_020_r), FUNC(fuuki32_state::snd_020_w)).umask32(0x00ff00ff); // Shared with Z80 map(0xa00000, 0xa00003).writeonly().share(m_tilebank); } @@ -771,50 +603,16 @@ GFXDECODE_END // driver functions //------------------------------------------------- -TIMER_CALLBACK_MEMBER(fuuki32_state::level1_interrupt) -{ - m_maincpu->set_input_line(1, HOLD_LINE); - m_level_1_interrupt_timer->adjust(m_screen->time_until_pos(248)); -} - -TIMER_CALLBACK_MEMBER(fuuki32_state::vblank_interrupt) -{ - m_maincpu->set_input_line(3, HOLD_LINE); // VBlank IRQ - m_vblank_interrupt_timer->adjust(m_screen->time_until_vblank_start()); -} - -TIMER_CALLBACK_MEMBER(fuuki32_state::raster_interrupt) -{ - m_maincpu->set_input_line(5, HOLD_LINE); // Raster Line IRQ - m_screen->update_partial(m_screen->vpos()); - m_raster_interrupt_timer->adjust(m_screen->frame_period()); -} - - void fuuki32_state::machine_start() { u8 *rom = memregion("soundcpu")->base(); m_soundbank->configure_entries(0, 0x10, &rom[0], 0x8000); - m_level_1_interrupt_timer = timer_alloc(FUNC(fuuki32_state::level1_interrupt), this); - m_vblank_interrupt_timer = timer_alloc(FUNC(fuuki32_state::vblank_interrupt), this); - m_raster_interrupt_timer = timer_alloc(FUNC(fuuki32_state::raster_interrupt), this); - save_item(NAME(m_spr_buffered_tilebank)); } -void fuuki32_state::machine_reset() -{ - const rectangle &visarea = m_screen->visible_area(); - - m_level_1_interrupt_timer->adjust(m_screen->time_until_pos(248)); - m_vblank_interrupt_timer->adjust(m_screen->time_until_vblank_start()); - m_raster_interrupt_timer->adjust(m_screen->time_until_pos(0, visarea.max_x + 1)); -} - - void fuuki32_state::fuuki32(machine_config &config) { // basic machine hardware @@ -837,12 +635,21 @@ void fuuki32_state::fuuki32(machine_config &config) GFXDECODE(config, m_gfxdecode, m_palette, gfx_fuuki32); PALETTE(config, m_palette, palette_device::BLACK).set_format(palette_device::xRGB_555, 0x4000 / 2); - FUUKI_VIDEO(config, m_fuukivid, 0); - m_fuukivid->set_palette(m_palette); - m_fuukivid->set_color_base(0x400*2); - m_fuukivid->set_color_num(0x40); - m_fuukivid->set_tile_callback(FUNC(fuuki32_state::tile_cb)); - m_fuukivid->set_colpri_callback(FUNC(fuuki32_state::colpri_cb)); + FUUKI_SPRITE(config, m_fuukispr, 0); + m_fuukispr->set_palette(m_palette); + m_fuukispr->set_color_base(0x400*2); + m_fuukispr->set_color_num(0x40); + m_fuukispr->set_tile_callback(FUNC(fuuki32_state::spr_tile_cb)); + m_fuukispr->set_colpri_callback(FUNC(fuuki32_state::spr_colpri_cb)); + + FUUKI_TILEMAP(config, m_fuukitmap, 0, m_palette, gfx_fuuki32); + m_fuukitmap->set_screen(m_screen); + m_fuukitmap->set_colour_callback(FUNC(fuuki32_state::tmap_colour_cb)); + m_fuukitmap->level_1_irq_callback().set_inputline(m_maincpu, 1, HOLD_LINE); + m_fuukitmap->vblank_irq_callback().set_inputline(m_maincpu, 3, HOLD_LINE); + m_fuukitmap->raster_irq_callback().set_inputline(m_maincpu, 5, HOLD_LINE); + m_fuukitmap->set_xoffs(0x1f3, 0x103); + m_fuukitmap->set_yoffs(0x3f6, 0x2c7); // sound hardware SPEAKER(config, "lspeaker").front_left(); @@ -880,7 +687,7 @@ ROM_START( asurabld ) ROM_REGION( 0x80000, "soundcpu", 0 ) // Z80 ROM_LOAD( "srom.u7", 0x00000, 0x80000, CRC(bb1deb89) SHA1(b1c70abddc0b9a88beb69a592376ff69a7e091eb) ) - ROM_REGION( 0x2000000, "fuukivid", 0 ) + ROM_REGION( 0x2000000, "fuukispr", 0 ) // 0x0000000 - 0x03fffff empty */ /* spXX.uYY - XX is the bank number! ROM_LOAD16_WORD_SWAP( "sp23.u14", 0x0400000, 0x400000, CRC(7df492eb) SHA1(30b88a3cd025ffc8c28fef06e0784755be37ef8e) ) ROM_LOAD16_WORD_SWAP( "sp45.u15", 0x0800000, 0x400000, CRC(1890f42a) SHA1(22254fe38fd83f4602a25e1ccba32df16edaf3f9) ) @@ -922,7 +729,7 @@ ROM_START( asurabus ) ROM_REGION( 0x80000, "soundcpu", 0 ) // Z80 ROM_LOAD( "srom.u7", 0x00000, 0x80000, CRC(368da389) SHA1(1423b709da40bf3033c9032c4bd07658f1a969de) ) - ROM_REGION( 0x2000000, "fuukivid", 0 ) + ROM_REGION( 0x2000000, "fuukispr", 0 ) ROM_LOAD16_WORD_SWAP( "sp01.u13", 0x0000000, 0x400000, CRC(5edea463) SHA1(22a780912f060bae0c9a403a7bfd4d27f25b76e3) ) ROM_LOAD16_WORD_SWAP( "sp23.u14", 0x0400000, 0x400000, CRC(91b1b0de) SHA1(341367966559ef2027415b673eb0db704680c81f) ) ROM_LOAD16_WORD_SWAP( "sp45.u15", 0x0800000, 0x400000, CRC(96c69aac) SHA1(cf053523026651427f884b9dd7c095af362dd24e) ) @@ -957,7 +764,7 @@ ROM_START( asurabusj ) ROM_REGION( 0x80000, "soundcpu", 0 ) // Z80 ROM_LOAD( "srom.u7", 0x00000, 0x80000, CRC(368da389) SHA1(1423b709da40bf3033c9032c4bd07658f1a969de) ) - ROM_REGION( 0x2000000, "fuukivid", 0 ) + ROM_REGION( 0x2000000, "fuukispr", 0 ) ROM_LOAD16_WORD_SWAP( "sp01.u13", 0x0000000, 0x400000, CRC(5edea463) SHA1(22a780912f060bae0c9a403a7bfd4d27f25b76e3) ) ROM_LOAD16_WORD_SWAP( "sp23.u14", 0x0400000, 0x400000, CRC(91b1b0de) SHA1(341367966559ef2027415b673eb0db704680c81f) ) ROM_LOAD16_WORD_SWAP( "sp45.u15", 0x0800000, 0x400000, CRC(96c69aac) SHA1(cf053523026651427f884b9dd7c095af362dd24e) ) @@ -992,7 +799,7 @@ ROM_START( asurabusja ) ROM_REGION( 0x80000, "soundcpu", 0 ) // Z80 ROM_LOAD( "srom.u7", 0x00000, 0x80000, CRC(368da389) SHA1(1423b709da40bf3033c9032c4bd07658f1a969de) ) - ROM_REGION( 0x2000000, "fuukivid", 0 ) + ROM_REGION( 0x2000000, "fuukispr", 0 ) ROM_LOAD16_WORD_SWAP( "sp01.u13", 0x0000000, 0x400000, CRC(5edea463) SHA1(22a780912f060bae0c9a403a7bfd4d27f25b76e3) ) ROM_LOAD16_WORD_SWAP( "sp23.u14", 0x0400000, 0x400000, CRC(91b1b0de) SHA1(341367966559ef2027415b673eb0db704680c81f) ) ROM_LOAD16_WORD_SWAP( "sp45.u15", 0x0800000, 0x400000, CRC(96c69aac) SHA1(cf053523026651427f884b9dd7c095af362dd24e) ) @@ -1027,7 +834,7 @@ ROM_START( asurabusjr ) // ARCADIA review build ROM_REGION( 0x80000, "soundcpu", 0 ) // Z80 ROM_LOAD( "srom.u7", 0x00000, 0x80000, CRC(368da389) SHA1(1423b709da40bf3033c9032c4bd07658f1a969de) ) - ROM_REGION( 0x2000000, "fuukivid", 0 ) + ROM_REGION( 0x2000000, "fuukispr", 0 ) ROM_LOAD16_WORD_SWAP( "sp01.u13", 0x0000000, 0x400000, CRC(5edea463) SHA1(22a780912f060bae0c9a403a7bfd4d27f25b76e3) ) ROM_LOAD16_WORD_SWAP( "sp23.u14", 0x0400000, 0x400000, CRC(91b1b0de) SHA1(341367966559ef2027415b673eb0db704680c81f) ) ROM_LOAD16_WORD_SWAP( "sp45.u15", 0x0800000, 0x400000, CRC(96c69aac) SHA1(cf053523026651427f884b9dd7c095af362dd24e) ) diff --git a/src/mame/fuuki/fuukispr.cpp b/src/mame/fuuki/fuukispr.cpp new file mode 100644 index 00000000000..cf48231c1c2 --- /dev/null +++ b/src/mame/fuuki/fuukispr.cpp @@ -0,0 +1,180 @@ +// license:BSD-3-Clause +// copyright-holders: Luca Elia, David Haywood + +/* + Fuuki Sprite hardware + + Used by: + fuukifg2.cpp + fuukifg3.cpp (with sprite tile bankswitching, triple buffered) +*/ + + +#include "emu.h" +#include "fuukispr.h" +#include "screen.h" + +DEFINE_DEVICE_TYPE(FUUKI_SPRITE, fuukispr_device, "fuukispr", "Fuuki Sprite hardware") + +fuukispr_device::fuukispr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, FUUKI_SPRITE, tag, owner, clock) + , device_gfx_interface(mconfig, *this) + , device_video_interface(mconfig, *this) + , m_tile_cb(*this) + , m_colpri_cb(*this) + , m_colbase(0) + , m_colnum(0x100) +{ +} + +GFXDECODE_MEMBER(fuukispr_device::gfxinfo) + GFXDECODE_DEVICE(DEVICE_SELF, 0, gfx_16x16x4_packed_msb, 0, 16) +GFXDECODE_END + +void fuukispr_device::device_start() +{ + decode_gfx(gfxinfo); + gfx(0)->set_colorbase(m_colbase); + gfx(0)->set_colors(m_colnum); + + m_tile_cb.resolve(); + m_colpri_cb.resolve(); +} + + +/*************************************************************************** + + + Sprites Drawing + + Offset: Bits: Value: + + 0.w fedc ---- ---- ---- Number Of Tiles Along X - 1 + ---- b--- ---- ---- Flip X + ---- -a-- ---- ---- 1 = Don't Draw This Sprite + ---- --98 7654 3210 X (Signed) + + 2.w fedc ---- ---- ---- Number Of Tiles Along Y - 1 + ---- b--- ---- ---- Flip Y + ---- -a-- ---- ---- + ---- --98 7654 3210 Y (Signed) + + 4.w fedc ---- ---- ---- Zoom X ($0 = Full Size, $F = Half Size) + ---- ba98 ---- ---- Zoom Y "" + ---- ---- 76-- ---- Priority + ---- ---- --54 3210 Color + + 6.w Tile Code + + for FG3 hardware + + 6.w fe-- ---- ---- ---- Tile Bank + --dc ba98 7654 3210 Tile Code + +***************************************************************************/ + +void fuukispr_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, bool flip_screen, u16 *spriteram, u32 size) +{ + // as we're likely framebuffered (sprites are delayed by 2-3 frames, at least on FG3, and doing rasters on sprites causes glitches) we + // only draw the sprites when MAME wants to draw the final screen line. Ideally we should framebuffer them instead. + if (cliprect.max_y != screen.visible_area().max_y) + return; + + const bool tilebank = !m_tile_cb.isnull(); + const bool priority = !m_colpri_cb.isnull(); + const rectangle spriteclip = screen.visible_area(); + + const int max_x = spriteclip.max_x + 1; + const int max_y = spriteclip.max_y + 1; + + int start, end, inc; + if (priority) { start = size - 4; end = -4; inc = -4; } + else { start = 0; end = size; inc = +4; } + + // Draw them backwards, for pdrawgfx + for (int offs = start; offs != end; offs += inc) + { + const u16 data0 = spriteram[offs + 0]; + if (BIT(data0, 10)) + continue; + + const u16 data1 = spriteram[offs + 1]; + const u16 attr = spriteram[offs + 2]; + u32 code = spriteram[offs + 3]; + if (tilebank) + m_tile_cb(code); + + bool flipx = BIT(data0, 11); + bool flipy = BIT(data1, 11); + + const int xnum = ((data0 >> 12) & 0xf) + 1; + const int ynum = ((data1 >> 12) & 0xf) + 1; + + const int xzoom = 16 * 8 - (8 * ((attr >> 12) & 0xf)) / 2; + const int yzoom = 16 * 8 - (8 * ((attr >> 8) & 0xf)) / 2; + + u32 pri_mask = 0; + u32 colour = attr & 0xff; + if (priority) + m_colpri_cb(colour, pri_mask); + + int sx = (data0 & 0x1ff) - (data0 & 0x200); + int sy = (data1 & 0x1ff) - (data1 & 0x200); + + if (flip_screen) + { + flipx = !flipx; sx = max_x - sx - xnum * 16; + flipy = !flipy; sy = max_y - sy - ynum * 16; + } + + int xstart, ystart, xend, yend, xinc, yinc; + if (flipx) { xstart = xnum-1; xend = -1; xinc = -1; } + else { xstart = 0; xend = xnum; xinc = +1; } + + if (flipy) { ystart = ynum-1; yend = -1; yinc = -1; } + else { ystart = 0; yend = ynum; yinc = +1; } + + for (int y = ystart; y != yend; y += yinc) + { + for (int x = xstart; x != xend; x += xinc) + { + if (priority) + { + if (xzoom == (16*8) && yzoom == (16*8)) + gfx(0)->prio_transpen(bitmap, spriteclip, + code++, + colour, + flipx, flipy, + sx + x * 16, sy + y * 16, + screen.priority(), pri_mask, 15); + else + gfx(0)->prio_zoom_transpen(bitmap, spriteclip, + code++, + colour, + flipx, flipy, + sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, + (0x10000/0x10/8) * (xzoom + 8), (0x10000/0x10/8) * (yzoom + 8),// nearest greater integer value to avoid holes + screen.priority(), pri_mask, 15); + } + else + { + if (xzoom == (16*8) && yzoom == (16*8)) + gfx(0)->transpen(bitmap, spriteclip, + code++, + colour, + flipx, flipy, + sx + x * 16, sy + y * 16, + 15); + else + gfx(0)->zoom_transpen(bitmap, spriteclip, + code++, + colour, + flipx, flipy, + sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, + (0x10000/0x10/8) * (xzoom + 8), (0x10000/0x10/8) * (yzoom + 8),// nearest greater integer value to avoid holes + 15); + } + } + } + } +} diff --git a/src/mame/fuuki/fuukispr.h b/src/mame/fuuki/fuukispr.h new file mode 100644 index 00000000000..661da0afd9a --- /dev/null +++ b/src/mame/fuuki/fuukispr.h @@ -0,0 +1,39 @@ +// license:BSD-3-Clause +// copyright-holders: Luca Elia, David Haywood + +#ifndef MAME_FUUKI_FUUKISPR_H +#define MAME_FUUKI_FUUKISPR_H + +#pragma once + +class fuukispr_device : public device_t, public device_gfx_interface, public device_video_interface +{ +public: + typedef device_delegate tile_delegate; + typedef device_delegate colpri_cb_delegate; + + fuukispr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration + void set_color_base(u16 base) { m_colbase = base; } + void set_color_num(u16 num) { m_colnum = num; } + template void set_tile_callback(T &&... args) { m_tile_cb.set(std::forward(args)...); } + template void set_colpri_callback(T &&... args) { m_colpri_cb.set(std::forward(args)...); } + + void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, bool flip_screen, u16 *spriteram, u32 size); + +protected: + virtual void device_start() override ATTR_COLD; + +private: + tile_delegate m_tile_cb; + colpri_cb_delegate m_colpri_cb; + u16 m_colbase; + u16 m_colnum; + + DECLARE_GFXDECODE_MEMBER(gfxinfo); +}; + +DECLARE_DEVICE_TYPE(FUUKI_SPRITE, fuukispr_device) + +#endif // MAME_FUUKI_FUUKISPR_H diff --git a/src/mame/fuuki/fuukitmap.cpp b/src/mame/fuuki/fuukitmap.cpp new file mode 100644 index 00000000000..f1c0aa758e7 --- /dev/null +++ b/src/mame/fuuki/fuukitmap.cpp @@ -0,0 +1,267 @@ +// license:BSD-3-Clause +// copyright-holders: Luca Elia, David Haywood + +/* + Fuuki Tilemap hardware + + Used by: + fuukifg2.cpp + fuukifg3.cpp +*/ + +#include "emu.h" +#include "fuukitmap.h" + + +void fuukitmap_device::vram_map(address_map &map) +{ + map(0x0000, 0x1fff).rw(FUNC(fuukitmap_device::vram_r<0>), FUNC(fuukitmap_device::vram_w<0>)); + map(0x2000, 0x3fff).rw(FUNC(fuukitmap_device::vram_r<1>), FUNC(fuukitmap_device::vram_w<1>)); + map(0x4000, 0x5fff).rw(FUNC(fuukitmap_device::vram_r<2>), FUNC(fuukitmap_device::vram_buffered_w<2>)); + map(0x6000, 0x7fff).rw(FUNC(fuukitmap_device::vram_r<3>), FUNC(fuukitmap_device::vram_buffered_w<3>)); +} + +void fuukitmap_device::vregs_map(address_map &map) +{ + map(0x00000, 0x0001f).rw(FUNC(fuukitmap_device::vregs_r), FUNC(fuukitmap_device::vregs_w)); + map(0x10000, 0x10003).rw(FUNC(fuukitmap_device::unknown_r), FUNC(fuukitmap_device::unknown_w)); // Flipscreen related + map(0x20000, 0x20001).rw(FUNC(fuukitmap_device::priority_r), FUNC(fuukitmap_device::priority_w)); // Controls layer order +} + + +DEFINE_DEVICE_TYPE(FUUKI_TILEMAP, fuukitmap_device, "fuukitmap", "Fuuki Tilemap hardware") + +fuukitmap_device::fuukitmap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, FUUKI_TILEMAP, tag, owner, clock) + , device_gfx_interface(mconfig, *this, nullptr) + , device_video_interface(mconfig, *this, true) + , m_colour_cb(*this) + , m_level_1_irq_cb(*this) + , m_vblank_irq_cb(*this) + , m_raster_irq_cb(*this) + , m_xoffs(0) + , m_xoffs_flip(0) + , m_yoffs(0) + , m_yoffs_flip(0) + , m_layer2_xoffs(0) + , m_layer2_yoffs(0) + , m_tilemap{ nullptr, nullptr, nullptr } + , m_unknown{ 0, 0 } + , m_priority(0) + , m_flip(false) + , m_tmap_front(0) + , m_tmap_middle(1) + , m_tmap_back(2) + , m_level_1_interrupt_timer(nullptr) + , m_vblank_interrupt_timer(nullptr) + , m_raster_interrupt_timer(nullptr) +{ +} + +void fuukitmap_device::device_start() +{ + m_colour_cb.resolve(); + + for (int i = 0; i < 4; i++) + { + m_vram[i] = make_unique_clear(0x2000 / 2); + + save_pointer(NAME(m_vram[i]), 0x2000 / 2, i); + } + + m_vregs = make_unique_clear(0x20 / 2); + + m_tilemap[0] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(fuukitmap_device::get_tile_info<0>)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); + m_tilemap[1] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(fuukitmap_device::get_tile_info<1>)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); + m_tilemap[2] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(fuukitmap_device::get_tile_info<2>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); + + m_level_1_interrupt_timer = timer_alloc(FUNC(fuukitmap_device::level1_interrupt), this); + m_vblank_interrupt_timer = timer_alloc(FUNC(fuukitmap_device::vblank_interrupt), this); + m_raster_interrupt_timer = timer_alloc(FUNC(fuukitmap_device::raster_interrupt), this); + + save_pointer(NAME(m_vregs), 0x20 / 2); + save_item(NAME(m_unknown)); + save_item(NAME(m_priority)); + save_item(NAME(m_flip)); + save_item(NAME(m_tmap_front)); + save_item(NAME(m_tmap_middle)); + save_item(NAME(m_tmap_back)); +} + +void fuukitmap_device::device_reset() +{ + const rectangle &visarea = screen().visible_area(); + + m_level_1_interrupt_timer->adjust(screen().time_until_pos(248)); + m_vblank_interrupt_timer->adjust(screen().time_until_vblank_start()); + m_raster_interrupt_timer->adjust(screen().time_until_pos(0, visarea.max_x + 1)); +} + + +TIMER_CALLBACK_MEMBER(fuukitmap_device::level1_interrupt) +{ + m_level_1_irq_cb(ASSERT_LINE); + m_level_1_interrupt_timer->adjust(screen().time_until_pos(248)); +} + +TIMER_CALLBACK_MEMBER(fuukitmap_device::vblank_interrupt) +{ + m_vblank_irq_cb(ASSERT_LINE); // VBlank IRQ + m_vblank_interrupt_timer->adjust(screen().time_until_vblank_start()); +} + +TIMER_CALLBACK_MEMBER(fuukitmap_device::raster_interrupt) +{ + m_raster_irq_cb(ASSERT_LINE); // Raster Line IRQ + screen().update_partial(screen().vpos()); + m_raster_interrupt_timer->adjust(screen().frame_period()); +} + + +template +void fuukitmap_device::vram_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_vram[Layer][offset]); + m_tilemap[Layer]->mark_tile_dirty(offset / 2); +} + +template +void fuukitmap_device::vram_buffered_w(offs_t offset, u16 data, u16 mem_mask) +{ + const int buffer = (m_vregs[0x1e / 2] & 0x40) >> 6; + COMBINE_DATA(&m_vram[Layer][offset]); + if ((Layer & 1) == buffer) + m_tilemap[2]->mark_tile_dirty(offset / 2); +} + + +void fuukitmap_device::vregs_w(offs_t offset, u16 data, u16 mem_mask) +{ + const u16 old = m_vregs[offset]; + data = COMBINE_DATA(&m_vregs[offset]); + if (old != data) + { + if (offset == 0x1c / 2) + { + const rectangle &visarea = screen().visible_area(); + attotime period = screen().frame_period(); + m_raster_interrupt_timer->adjust(screen().time_until_pos(data, visarea.max_x + 1), 0, period); + } + if (offset == 0x1e / 2) + { + if ((old ^ data) & 0x40) + m_tilemap[2]->mark_all_dirty(); + + m_flip = BIT(m_vregs[0x1e / 2], 0); + } + } +} + + +/*************************************************************************** + + + Tilemaps + + Offset: Bits: Value: + + 0.w Code + + 2.w fedc ba98 ---- ---- + ---- ---- 7--- ---- Flip Y + ---- ---- -6-- ---- Flip X + ---- ---- --54 3210 Color + + +***************************************************************************/ + +template +TILE_GET_INFO_MEMBER(fuukitmap_device::get_tile_info) +{ + const int buffer = (Layer < 2) ? 0 : (m_vregs[0x1e / 2] & 0x40) >> 6; + const u16 code = m_vram[Layer|buffer][2 * tile_index + 0]; + const u16 attr = m_vram[Layer|buffer][2 * tile_index + 1]; + u32 colour = attr & 0x3f; + if (!m_colour_cb.isnull()) + m_colour_cb(Layer, colour); + tileinfo.set(Layer, code, colour, TILE_FLIPYX((attr >> 6) & 3)); +} + + +/*************************************************************************** + + + Screen Drawing + + Video Registers (vregs): + + 00.w Layer 0 Scroll Y + 02.w Layer 0 Scroll X + 04.w Layer 1 Scroll Y + 06.w Layer 1 Scroll X + 08.w Layer 2 Scroll Y + 0a.w Layer 2 Scroll X + 0c.w Layers Y Offset + 0e.w Layers X Offset + + 10-1a.w ? 0 + 1c.w Trigger a level 5 irq on this raster line + 1e.w ? $3390/$3393 (Flip Screen Off/On), $0040 is buffer for tilemap 2 + + Priority Register (priority): + + fedc ba98 7654 3--- + ---- ---- ---- -210 Layer Order + + + Unknown Registers (unknown): + + 00.w ? $0200/$0201 (Flip Screen Off/On) + 02.w ? $f300/$0330 + +***************************************************************************/ + +// Wrapper to handle bg and bg2 together +void fuukitmap_device::draw_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u8 i, int flag, u8 pri, u8 primask) +{ + m_tilemap[i]->draw(screen, bitmap, cliprect, flag, pri, primask); +} + +void fuukitmap_device::prepare() +{ + /* + It's not independent bits causing layers to switch, that wouldn't make sense with 3 bits. + */ + + static const u8 pri_table[6][3] = { + { 0, 1, 2 }, // Special moves 0>1, 0>2 (0,1,2 or 0,2,1) + { 0, 2, 1 }, // Two Levels - 0>1 (0,1,2 or 0,2,1 or 2,0,1) + { 1, 0, 2 }, // Most Levels - 2>1 1>0 2>0 (1,0,2) + { 1, 2, 0 }, // Not used? + { 2, 0, 1 }, // Title etc. - 0>1 (0,1,2 or 0,2,1 or 2,0,1) + { 2, 1, 0 }}; // Char Select, prison stage 1>0 (leaves 1,2,0 or 2,1,0) + + m_tmap_front = pri_table[m_priority & 0x0f][0]; + m_tmap_middle = pri_table[m_priority & 0x0f][1]; + m_tmap_back = pri_table[m_priority & 0x0f][2]; + + // Layers scrolling + const u16 scrolly_offs = m_vregs[0xc / 2] - (m_flip ? m_xoffs_flip : m_xoffs); + const u16 scrollx_offs = m_vregs[0xe / 2] - (m_flip ? m_yoffs_flip : m_yoffs); + + const u16 layer0_scrolly = m_vregs[0x0 / 2] + scrolly_offs; + const u16 layer0_scrollx = m_vregs[0x2 / 2] + scrollx_offs; + const u16 layer1_scrolly = m_vregs[0x4 / 2] + scrolly_offs; + const u16 layer1_scrollx = m_vregs[0x6 / 2] + scrollx_offs; + + const u16 layer2_scrolly = m_vregs[0x8 / 2]; + const u16 layer2_scrollx = m_vregs[0xa / 2]; + + m_tilemap[0]->set_scrollx(0, layer0_scrollx); + m_tilemap[0]->set_scrolly(0, layer0_scrolly); + m_tilemap[1]->set_scrollx(0, layer1_scrollx); + m_tilemap[1]->set_scrolly(0, layer1_scrolly); + + m_tilemap[2]->set_scrollx(0, layer2_scrollx + m_layer2_xoffs); + m_tilemap[2]->set_scrolly(0, layer2_scrolly + m_layer2_yoffs); +} diff --git a/src/mame/fuuki/fuukitmap.h b/src/mame/fuuki/fuukitmap.h new file mode 100644 index 00000000000..6927b9f55f9 --- /dev/null +++ b/src/mame/fuuki/fuukitmap.h @@ -0,0 +1,119 @@ +// license:BSD-3-Clause +// copyright-holders: Luca Elia, David Haywood + +#ifndef MAME_FUUKI_FUUKITMAP_H +#define MAME_FUUKI_FUUKITMAP_H + +#pragma once + +#include "tilemap.h" +#include "screen.h" + +class fuukitmap_device : public device_t, public device_gfx_interface, public device_video_interface +{ +public: + typedef device_delegate colour_cb_delegate; + + fuukitmap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + template fuukitmap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&palette_tag, const gfx_decode_entry *gfxinfo) + : fuukitmap_device(mconfig, tag, owner, clock) + { + set_info(gfxinfo); + set_palette(std::forward(palette_tag)); + } + + // configuration + template void set_colour_callback(T &&... args) { m_colour_cb.set(std::forward(args)...); } + + auto level_1_irq_callback() { return m_level_1_irq_cb.bind(); } + auto vblank_irq_callback() { return m_vblank_irq_cb.bind(); } + auto raster_irq_callback() { return m_raster_irq_cb.bind(); } + + void set_xoffs(int xoffs, int xoffs_flip) + { + m_xoffs = xoffs; + m_xoffs_flip = xoffs_flip; + } + + void set_yoffs(int yoffs, int yoffs_flip) + { + m_yoffs = yoffs; + m_yoffs_flip = yoffs_flip; + } + + void set_layer2_xoffs(int xoffs) { m_layer2_xoffs = xoffs; } + void set_layer2_yoffs(int yoffs) { m_layer2_yoffs = yoffs; } + + // getters, setters + bool flip_screen() { return m_flip; } + u8 tmap_front() { return m_tmap_front; } + u8 tmap_middle() { return m_tmap_middle; } + u8 tmap_back() { return m_tmap_back; } + + void set_transparent_pen(int layer, pen_t pen) { m_tilemap[layer]->set_transparent_pen(pen); } + + void prepare(); + void draw_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, u8 i, int flag, u8 pri, u8 primask = 0xff); + + void vram_map(address_map &map) ATTR_COLD; + void vregs_map(address_map &map) ATTR_COLD; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + +private: + // configurations + colour_cb_delegate m_colour_cb; + + devcb_write_line m_level_1_irq_cb; + devcb_write_line m_vblank_irq_cb; + devcb_write_line m_raster_irq_cb; + + int m_xoffs, m_xoffs_flip; + int m_yoffs, m_yoffs_flip; + int m_layer2_xoffs; + int m_layer2_yoffs; + + // video-related + tilemap_t *m_tilemap[3]{}; + + std::unique_ptr m_vram[4]; + std::unique_ptr m_vregs; + u16 m_unknown[2]; + u16 m_priority; + + bool m_flip; + u8 m_tmap_front; + u8 m_tmap_middle; + u8 m_tmap_back; + + // misc + emu_timer *m_level_1_interrupt_timer; + emu_timer *m_vblank_interrupt_timer; + emu_timer *m_raster_interrupt_timer; + + // handlers + template u16 vram_r(offs_t offset) { return m_vram[Layer][offset]; } + template void vram_w(offs_t offset, u16 data, u16 mem_mask = ~0); + template void vram_buffered_w(offs_t offset, u16 data, u16 mem_mask = ~0); + + u16 vregs_r(offs_t offset) { return m_vregs[offset]; } + void vregs_w(offs_t offset, u16 data, u16 mem_mask = ~0); + + u16 unknown_r(offs_t offset) { return m_unknown[offset]; } + void unknown_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_unknown[offset]); } + + u16 priority_r() { return m_priority; } + void priority_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_priority); } + + TIMER_CALLBACK_MEMBER(level1_interrupt); + TIMER_CALLBACK_MEMBER(vblank_interrupt); + TIMER_CALLBACK_MEMBER(raster_interrupt); + + template TILE_GET_INFO_MEMBER(get_tile_info); +}; + +DECLARE_DEVICE_TYPE(FUUKI_TILEMAP, fuukitmap_device) + +#endif // MAME_FUUKI_FUUKITMAP_H -- cgit v1.2.3