mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
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).
This commit is contained in:
parent
a3151fd89a
commit
8462d66f4d
@ -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<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<fuukivid_device> m_fuukivid;
|
||||
required_device<fuukispr_device> m_fuukispr;
|
||||
required_device<fuukitmap_device> m_fuukitmap;
|
||||
required_device<generic_latch_8_device> m_soundlatch;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<u16> m_spriteram;
|
||||
required_shared_ptr_array<u16, 4> m_vram;
|
||||
required_shared_ptr<u16> m_vregs;
|
||||
required_shared_ptr<u16> m_unknown;
|
||||
required_shared_ptr<u16> 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<int Layer> void vram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
template<int Layer> void vram_buffered_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void oki_banking_w(u8 data);
|
||||
|
||||
template<int Layer> 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<int Layer>
|
||||
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_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_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_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<int Layer>
|
||||
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<int Layer>
|
||||
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
|
||||
|
@ -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<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<fuukivid_device> m_fuukivid;
|
||||
required_device<fuukispr_device> m_fuukispr;
|
||||
required_device<fuukitmap_device> m_fuukitmap;
|
||||
|
||||
// memory pointers
|
||||
memory_share_creator<u16> m_spriteram;
|
||||
required_shared_ptr_array<u32, 4> m_vram;
|
||||
memory_share_creator<u16> m_vregs;
|
||||
required_shared_ptr<u32> m_priority;
|
||||
required_shared_ptr<u32> m_tilebank;
|
||||
required_shared_ptr<u8> m_shared_ram;
|
||||
std::unique_ptr<u16[]> 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<int Layer> void vram_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
template<int Layer> void vram_buffered_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
|
||||
template<int Layer, int ColShift> 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<int Layer, int ColShift>
|
||||
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<u16[]>(spriteram_size / 2);
|
||||
m_buf_spriteram[1] = make_unique_clear<u16[]>(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_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_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_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<int Layer>
|
||||
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<int Layer>
|
||||
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) )
|
||||
|
@ -1,44 +1,44 @@
|
||||
// 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 "fuukifg.h"
|
||||
#include "fuukispr.h"
|
||||
#include "screen.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(FUUKI_VIDEO, fuukivid_device, "fuukivid", "Fuuki Video")
|
||||
DEFINE_DEVICE_TYPE(FUUKI_SPRITE, fuukispr_device, "fuukispr", "Fuuki Sprite hardware")
|
||||
|
||||
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)
|
||||
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_gfx_region(*this, DEVICE_SELF)
|
||||
, m_colbase(0)
|
||||
, m_colnum(0x100)
|
||||
{
|
||||
}
|
||||
|
||||
void fuukivid_device::device_start()
|
||||
GFXDECODE_MEMBER(fuukispr_device::gfxinfo)
|
||||
GFXDECODE_DEVICE(DEVICE_SELF, 0, gfx_16x16x4_packed_msb, 0, 16)
|
||||
GFXDECODE_END
|
||||
|
||||
void fuukispr_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);
|
||||
decode_gfx(gfxinfo);
|
||||
gfx(0)->set_colorbase(m_colbase);
|
||||
gfx(0)->set_colors(m_colnum);
|
||||
|
||||
m_tile_cb.resolve();
|
||||
m_colpri_cb.resolve();
|
||||
|
||||
set_gfx(0, std::make_unique<gfx_element>(&palette(), layout_16x16x4, m_gfx_region->base(), 0, m_colnum, m_colbase));
|
||||
}
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ void fuukivid_device::device_start()
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void fuukivid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, bool flip_screen, u16 *spriteram, u32 size)
|
||||
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.
|
||||
@ -95,17 +95,17 @@ void fuukivid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,
|
||||
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);
|
||||
|
||||
if (data0 & 0x400)
|
||||
continue;
|
||||
|
||||
int flipx = data0 & 0x0800;
|
||||
int flipy = data1 & 0x0800;
|
||||
bool flipx = BIT(data0, 11);
|
||||
bool flipy = BIT(data1, 11);
|
||||
|
||||
const int xnum = ((data0 >> 12) & 0xf) + 1;
|
||||
const int ynum = ((data1 >> 12) & 0xf) + 1;
|
@ -1,18 +1,18 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Luca Elia, David Haywood
|
||||
|
||||
#ifndef MAME_FUUKI_FUUKIFG_H
|
||||
#define MAME_FUUKI_FUUKIFG_H
|
||||
#ifndef MAME_FUUKI_FUUKISPR_H
|
||||
#define MAME_FUUKI_FUUKISPR_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class fuukivid_device : public device_t, public device_gfx_interface, public device_video_interface
|
||||
class fuukispr_device : public device_t, public device_gfx_interface, public device_video_interface
|
||||
{
|
||||
public:
|
||||
typedef device_delegate<void (u32 &code)> tile_delegate;
|
||||
typedef device_delegate<void (u32 &colour, u32 &pri_mask)> colpri_cb_delegate;
|
||||
|
||||
fuukivid_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
fuukispr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// configuration
|
||||
void set_color_base(u16 base) { m_colbase = base; }
|
||||
@ -28,11 +28,12 @@ protected:
|
||||
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_GFXDECODE_MEMBER(gfxinfo);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(FUUKI_VIDEO, fuukivid_device)
|
||||
DECLARE_DEVICE_TYPE(FUUKI_SPRITE, fuukispr_device)
|
||||
|
||||
#endif // MAME_FUUKI_FUUKIFG_H
|
||||
#endif // MAME_FUUKI_FUUKISPR_H
|
267
src/mame/fuuki/fuukitmap.cpp
Normal file
267
src/mame/fuuki/fuukitmap.cpp
Normal file
@ -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<u16 []>(0x2000 / 2);
|
||||
|
||||
save_pointer(NAME(m_vram[i]), 0x2000 / 2, i);
|
||||
}
|
||||
|
||||
m_vregs = make_unique_clear<u16 []>(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 <int Layer>
|
||||
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 <int Layer>
|
||||
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 <int Layer>
|
||||
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);
|
||||
}
|
119
src/mame/fuuki/fuukitmap.h
Normal file
119
src/mame/fuuki/fuukitmap.h
Normal file
@ -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<void (u8 layer, u32 &colour)> colour_cb_delegate;
|
||||
|
||||
fuukitmap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
template <typename T> 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<T>(palette_tag));
|
||||
}
|
||||
|
||||
// configuration
|
||||
template <typename... T> void set_colour_callback(T &&... args) { m_colour_cb.set(std::forward<T>(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<u16[]> m_vram[4];
|
||||
std::unique_ptr<u16[]> 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 <int Layer> u16 vram_r(offs_t offset) { return m_vram[Layer][offset]; }
|
||||
template <int Layer> void vram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
template <int Layer> 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 <int Layer> TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(FUUKI_TILEMAP, fuukitmap_device)
|
||||
|
||||
#endif // MAME_FUUKI_FUUKITMAP_H
|
Loading…
Reference in New Issue
Block a user