From eca8831836ab5ccbc9432a600a20fdfe14c86322 Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Sat, 23 Oct 2021 03:52:21 +0100 Subject: remove deco_zoomspr device, refactor deco32 - drgngun, lockload to use the namco_c355spr device instead (#8725) --- scripts/target/mame/arcade.lua | 2 - src/mame/drivers/deco32.cpp | 199 ++++++----- src/mame/drivers/gal3.cpp | 5 +- src/mame/drivers/namconb1.cpp | 1 + src/mame/drivers/namcos21_c67.cpp | 2 +- src/mame/drivers/namcos21_de.cpp | 2 +- src/mame/includes/deco32.h | 32 +- src/mame/video/deco32.cpp | 60 +++- src/mame/video/deco_zoomspr.cpp | 414 ---------------------- src/mame/video/deco_zoomspr.h | 39 --- src/mame/video/namco_c355spr.cpp | 702 ++++++++++++++++++++++++-------------- src/mame/video/namco_c355spr.h | 93 ++++- 12 files changed, 728 insertions(+), 823 deletions(-) delete mode 100644 src/mame/video/deco_zoomspr.cpp delete mode 100644 src/mame/video/deco_zoomspr.h diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 5f076388082..f339007eeb0 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -1754,8 +1754,6 @@ files { MAME_DIR .. "src/mame/video/dvi.cpp", MAME_DIR .. "src/mame/video/deco_ace.cpp", MAME_DIR .. "src/mame/video/deco_ace.h", - MAME_DIR .. "src/mame/video/deco_zoomspr.cpp", - MAME_DIR .. "src/mame/video/deco_zoomspr.h", MAME_DIR .. "src/mame/drivers/decocass.cpp", MAME_DIR .. "src/mame/includes/decocass.h", MAME_DIR .. "src/mame/machine/decocass.cpp", diff --git a/src/mame/drivers/deco32.cpp b/src/mame/drivers/deco32.cpp index df36f5819ac..182f8aee647 100644 --- a/src/mame/drivers/deco32.cpp +++ b/src/mame/drivers/deco32.cpp @@ -476,6 +476,18 @@ void fghthist_state::fghthsta_memmap(address_map &map) map(0x200000, 0x207fff).rw(FUNC(fghthist_state::ioprot_r), FUNC(fghthist_state::ioprot_w)).umask32(0xffff0000).share("prot32ram"); // only maps on 16-bits } +void dragngun_state::namcosprite_map(address_map &map) +{ + map(0x204800, 0x204fff).ram().share("spclip");// (all entries set to 320x256 here) + map(0x208000, 0x208fff).ram().share("lay0"); + map(0x20c000, 0x20cfff).ram().share("lay1"); + map(0x210000, 0x217fff).ram().share("look0"); + map(0x218000, 0x21ffff).ram().share("look1"); + map(0x220000, 0x221fff).ram().share("spriteram"); /* Main spriteram */ + map(0x228000, 0x2283ff).ram().share("spindex"); // sprite index (just a table 0x00-0xff here) + map(0x230000, 0x230003).w(FUNC(dragngun_state::spriteram_dma_w)); +} + // the video drawing (especially sprite) code on this is too slow to cope with proper partial updates // raster effects appear to need some work on it anyway? void dragngun_state::dragngun_map(address_map &map) @@ -504,14 +516,10 @@ void dragngun_state::dragngun_map(address_map &map) map(0x01d4000, 0x01d5fff).rw("tilegen2", FUNC(deco16ic_device::pf2_data_dword_r), FUNC(deco16ic_device::pf2_data_dword_w)); // unused map(0x01e0000, 0x01e3fff).ram().w(FUNC(dragngun_state::pf_rowscroll_w<2>)).share("pf3_rowscroll32"); map(0x01e4000, 0x01e5fff).ram().w(FUNC(dragngun_state::pf_rowscroll_w<3>)).share("pf4_rowscroll32"); // unused - map(0x0204800, 0x0204fff).ram(); // ace? 0x10 byte increments only // 13f ff stuff - map(0x0208000, 0x0208fff).ram().share("lay0"); - map(0x020c000, 0x020cfff).ram().share("lay1"); - map(0x0210000, 0x0217fff).ram().share("look0"); - map(0x0218000, 0x021ffff).ram().share("look1"); - map(0x0220000, 0x0221fff).ram().share("spriteram"); /* Main spriteram */ - map(0x0228000, 0x02283ff).ram(); //0x10 byte increments only - map(0x0230000, 0x0230003).w(FUNC(dragngun_state::spriteram_dma_w)); + + // 0x2xxxxx Namco Zooming Sprites + namcosprite_map(map); + map(0x0300000, 0x03fffff).rom().region("maincpu", 0x100000); map(0x0400000, 0x0400000).rw("oki3", FUNC(okim6295_device::read), FUNC(okim6295_device::write)); map(0x0410000, 0x0410003).w(FUNC(dragngun_state::volume_w)); @@ -555,14 +563,10 @@ void dragngun_state::lockload_map(address_map &map) map(0x1d4000, 0x1d5fff).rw("tilegen2", FUNC(deco16ic_device::pf2_data_dword_r), FUNC(deco16ic_device::pf2_data_dword_w)); // unused map(0x1e0000, 0x1e3fff).ram().w(FUNC(dragngun_state::pf_rowscroll_w<2>)).share("pf3_rowscroll32"); map(0x1e4000, 0x1e5fff).ram().w(FUNC(dragngun_state::pf_rowscroll_w<3>)).share("pf4_rowscroll32"); // unused - map(0x204800, 0x204fff).ram(); //0x10 byte increments only - map(0x208000, 0x208fff).ram().share("lay0"); - map(0x20c000, 0x20cfff).ram().share("lay1"); - map(0x210000, 0x217fff).ram().share("look0"); - map(0x218000, 0x21ffff).ram().share("look1"); - map(0x220000, 0x221fff).ram().share("spriteram"); /* Main spriteram */ - map(0x228000, 0x2283ff).ram(); //0x10 byte increments only - map(0x230000, 0x230003).w(FUNC(dragngun_state::spriteram_dma_w)); + + // 0x2xxxxx Namco Zooming Sprites + namcosprite_map(map); + map(0x300000, 0x3fffff).rom().region("maincpu", 0x100000); map(0x410000, 0x410003).w(FUNC(dragngun_state::volume_w)); map(0x420000, 0x420000).rw(FUNC(dragngun_state::eeprom_r), FUNC(dragngun_state::eeprom_w)); @@ -1205,6 +1209,49 @@ void captaven_state::init_captaven() extern void process_dvi_data(device_t *device,u8* dvi_data, int offset, int regionsize); +void dragngun_state::expand_sprite_data() +{ + u8 *rom = memregion("c355spr")->base(); + size_t len = memregion("c355spr")->bytes(); + + for (int i = 0; i < len / 2; i++) + { + u8 temp = rom[i]; + rom[i + len / 2] = temp & 0x0f; + rom[i] = (temp >> 4) & 0x0f; + } +} + + + +int dragngun_state::sprite_bank_callback(int sprite) +{ + /* High bits of the sprite reference into the sprite control bits for banking */ + switch (sprite & 0x3000) { + default: + case 0x0000: sprite = (sprite & 0xfff) | ((m_sprite_ctrl & 0x000f) << 12); break; + case 0x1000: sprite = (sprite & 0xfff) | ((m_sprite_ctrl & 0x00f0) << 8); break; + case 0x2000: sprite = (sprite & 0xfff) | ((m_sprite_ctrl & 0x0f00) << 4); break; + case 0x3000: sprite = (sprite & 0xfff) | ((m_sprite_ctrl & 0xf000) << 0); break; + } + + /* Because of the unusual interleaved rom layout, we have to mangle the bank bits + even further to suit our gfx decode */ + switch (sprite & 0xf000) { + case 0x0000: sprite = 0xc000 | (sprite & 0xfff); break; + case 0x1000: sprite = 0xd000 | (sprite & 0xfff); break; + case 0x2000: sprite = 0xe000 | (sprite & 0xfff); break; + case 0x3000: sprite = 0xf000 | (sprite & 0xfff); break; + + case 0xc000: sprite = 0x0000 | (sprite & 0xfff); break; + case 0xd000: sprite = 0x1000 | (sprite & 0xfff); break; + case 0xe000: sprite = 0x2000 | (sprite & 0xfff); break; + case 0xf000: sprite = 0x3000 | (sprite & 0xfff); break; + } + + return sprite; +} + void dragngun_state::dragngun_init_common() { const u8 *SRC_RAM = memregion("gfx1")->base(); @@ -1217,6 +1264,8 @@ void dragngun_state::dragngun_init_common() std::copy(&SRC_RAM[0x00000], &SRC_RAM[0x10000], &DST_RAM[0x080000]); std::copy(&SRC_RAM[0x10000], &SRC_RAM[0x20000], &DST_RAM[0x110000]); + expand_sprite_data(); + #if 0 { u8 *ROM = memregion("dvi")->base(); @@ -1277,6 +1326,8 @@ void dragngun_state::init_lockload() // ROM[0x1fe3cc/4] = 0xe1a00000;// NOP test switch lock // ROM[0x1fe40c/4] = 0xe1a00000;// NOP test switch lock + expand_sprite_data(); + save_item(NAME(m_oki2_bank)); } @@ -1803,28 +1854,6 @@ static const gfx_layout tilelayout_5bpp = 16*16*5 }; -static const gfx_layout spritelayout4 = -{ - 16,16, - RGN_FRAC(1,1), - 4, - { STEP4(0,1) }, - { STEP16(0,8) }, - { STEP16(0,16*8) }, - 16*16*8 -}; - -static const gfx_layout spritelayout5 = -{ - 16,16, - RGN_FRAC(1,1), - 4, - { STEP4(4,1) }, - { STEP16(0,8) }, - { STEP16(0,16*8) }, - 16*16*8 -}; - static GFXDECODE_START( gfx_captaven ) GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 128 ) /* Characters 8x8 */ GFXDECODE_ENTRY( "gfx1", 0, tilelayout, 0, 128 ) /* Tiles 16x16 */ @@ -1843,8 +1872,6 @@ static GFXDECODE_START( gfx_dragngun ) GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 64 ) /* Characters 8x8 */ GFXDECODE_ENTRY( "gfx2", 0, tilelayout, 0, 64 ) /* Tiles 16x16 */ GFXDECODE_ENTRY( "gfx3", 0, tilelayout_8bpp, 0, 8 ) /* Tiles 16x16 */ - GFXDECODE_ENTRY( "gfx4", 0, spritelayout4, 0, 32 ) /* Sprites 16x16 */ - GFXDECODE_ENTRY( "gfx4", 0, spritelayout5, 0, 32 ) /* Sprites 16x16 */ GFXDECODE_END static GFXDECODE_START( gfx_nslasher ) @@ -2108,8 +2135,7 @@ void dragngun_state::dragngun(machine_config &config) m_deco_tilegen[1]->set_pf12_16x16_bank(2); m_deco_tilegen[1]->set_gfxdecode_tag(m_gfxdecode); - DECO_ZOOMSPR(config, m_sprgenzoom, 0); - m_sprgenzoom->set_gfxdecode(m_gfxdecode); + namco_sprites(config); // I750, these aren't emulated //I82750PB(config, m_i82750pb, XTAL(25'000'000)); @@ -2171,6 +2197,22 @@ void dragngun_state::lockloadu(machine_config &config) m_ym2151->port_write_handler().set(FUNC(dragngun_state::lockload_okibank_lo_w)); } +void dragngun_state::namco_sprites(machine_config &config) +{ + NAMCO_C355SPR(config, m_sprgenzoom, 0); + m_sprgenzoom->set_tile_callback(namco_c355spr_device::c355_obj_code2tile_delegate(&dragngun_state::sprite_bank_callback, this)); + m_sprgenzoom->set_palette(m_palette); + m_sprgenzoom->set_colors(32); + m_sprgenzoom->set_granularity(16); + m_sprgenzoom->set_read_spritetile(FUNC(dragngun_state::read_spritetile)); + m_sprgenzoom->set_read_spriteformat(FUNC(dragngun_state::read_spriteformat)); + m_sprgenzoom->set_read_spritetable(FUNC(dragngun_state::read_spritetable)); + m_sprgenzoom->set_read_spritelist(FUNC(dragngun_state::read_spritelist)); + m_sprgenzoom->set_read_cliptable(FUNC(dragngun_state::read_cliptable)); + m_sprgenzoom->set_priority_callback(FUNC(dragngun_state::sprite_priority_callback)); + m_sprgenzoom->set_device_allocates_spriteram_and_bitmaps(false); +} + // DE-0420-1 + Bottom board DE-0421-0 void dragngun_state::lockload(machine_config &config) { @@ -2234,8 +2276,7 @@ void dragngun_state::lockload(machine_config &config) m_deco_tilegen[1]->set_pf12_16x16_bank(2); m_deco_tilegen[1]->set_gfxdecode_tag(m_gfxdecode); - DECO_ZOOMSPR(config, m_sprgenzoom, 0); - m_sprgenzoom->set_gfxdecode(m_gfxdecode); + namco_sprites(config); DECO146PROT(config, m_ioprot, 0); m_ioprot->port_a_cb().set_ioport("INPUTS"); @@ -2884,15 +2925,15 @@ ROM_START( dragngun ) ROM_CONTINUE( 0x2c0000, 0x40000 ) /* 2/4 */ ROM_CONTINUE( 0x3c0000, 0x40000 ) /* 3/4 */ - ROM_REGION( 0x800000, "gfx4", 0 ) - ROM_LOAD32_BYTE( "mar-09.bin", 0x000003, 0x100000, CRC(18fec9e1) SHA1(1290a9c13b4fd7d2197b39ec616206796e3a17a8) ) - ROM_LOAD32_BYTE( "mar-10.bin", 0x400003, 0x100000, CRC(73126fbc) SHA1(9b9c31335e4db726863b219072c83810008f88f9) ) - ROM_LOAD32_BYTE( "mar-11.bin", 0x000002, 0x100000, CRC(1fc638a4) SHA1(003dcfbb65a8f32a1a030502a11432287cf8b4e0) ) - ROM_LOAD32_BYTE( "mar-12.bin", 0x400002, 0x100000, CRC(4c412512) SHA1(ccd5014bc9f9648cf5fa56bb8d54fc72a7099ca3) ) - ROM_LOAD32_BYTE( "mar-13.bin", 0x000001, 0x100000, CRC(d675821c) SHA1(ff195422d0bef62d1f9c7784bba1e6b7ab5cd211) ) - ROM_LOAD32_BYTE( "mar-14.bin", 0x400001, 0x100000, CRC(22d38c71) SHA1(62273665975f3e6000fa4b01755aeb70e5dd002d) ) + ROM_REGION( 0x800000*2, "c355spr", ROMREGION_ERASE00 ) ROM_LOAD32_BYTE( "mar-15.bin", 0x000000, 0x100000, CRC(ec976b20) SHA1(c120b3c56d5e02162e41dc7f726c260d0f8d2f1a) ) + ROM_LOAD32_BYTE( "mar-13.bin", 0x000001, 0x100000, CRC(d675821c) SHA1(ff195422d0bef62d1f9c7784bba1e6b7ab5cd211) ) + ROM_LOAD32_BYTE( "mar-11.bin", 0x000002, 0x100000, CRC(1fc638a4) SHA1(003dcfbb65a8f32a1a030502a11432287cf8b4e0) ) + ROM_LOAD32_BYTE( "mar-09.bin", 0x000003, 0x100000, CRC(18fec9e1) SHA1(1290a9c13b4fd7d2197b39ec616206796e3a17a8) ) ROM_LOAD32_BYTE( "mar-16.bin", 0x400000, 0x100000, CRC(8b329bc8) SHA1(6e34eb6e2628a01a699d20a5155afb2febc31255) ) + ROM_LOAD32_BYTE( "mar-14.bin", 0x400001, 0x100000, CRC(22d38c71) SHA1(62273665975f3e6000fa4b01755aeb70e5dd002d) ) + ROM_LOAD32_BYTE( "mar-12.bin", 0x400002, 0x100000, CRC(4c412512) SHA1(ccd5014bc9f9648cf5fa56bb8d54fc72a7099ca3) ) + ROM_LOAD32_BYTE( "mar-10.bin", 0x400003, 0x100000, CRC(73126fbc) SHA1(9b9c31335e4db726863b219072c83810008f88f9) ) // this is standard DVI data, see http://www.fileformat.info/format/dvi/egff.htm // there are DVI headers at 0x000000, 0x580000, 0x800000, 0xB10000, 0xB80000 @@ -2964,15 +3005,15 @@ ROM_START( dragngunj ) ROM_CONTINUE( 0x2c0000, 0x40000 ) /* 2/4 */ ROM_CONTINUE( 0x3c0000, 0x40000 ) /* 3/4 */ - ROM_REGION( 0x800000, "gfx4", 0 ) - ROM_LOAD32_BYTE( "mar-09.bin", 0x000003, 0x100000, CRC(18fec9e1) SHA1(1290a9c13b4fd7d2197b39ec616206796e3a17a8) ) - ROM_LOAD32_BYTE( "mar-10.bin", 0x400003, 0x100000, CRC(73126fbc) SHA1(9b9c31335e4db726863b219072c83810008f88f9) ) - ROM_LOAD32_BYTE( "mar-11.bin", 0x000002, 0x100000, CRC(1fc638a4) SHA1(003dcfbb65a8f32a1a030502a11432287cf8b4e0) ) - ROM_LOAD32_BYTE( "mar-12.bin", 0x400002, 0x100000, CRC(4c412512) SHA1(ccd5014bc9f9648cf5fa56bb8d54fc72a7099ca3) ) - ROM_LOAD32_BYTE( "mar-13.bin", 0x000001, 0x100000, CRC(d675821c) SHA1(ff195422d0bef62d1f9c7784bba1e6b7ab5cd211) ) - ROM_LOAD32_BYTE( "mar-14.bin", 0x400001, 0x100000, CRC(22d38c71) SHA1(62273665975f3e6000fa4b01755aeb70e5dd002d) ) + ROM_REGION( 0x800000*2, "c355spr", ROMREGION_ERASE00 ) ROM_LOAD32_BYTE( "mar-15.bin", 0x000000, 0x100000, CRC(ec976b20) SHA1(c120b3c56d5e02162e41dc7f726c260d0f8d2f1a) ) + ROM_LOAD32_BYTE( "mar-13.bin", 0x000001, 0x100000, CRC(d675821c) SHA1(ff195422d0bef62d1f9c7784bba1e6b7ab5cd211) ) + ROM_LOAD32_BYTE( "mar-11.bin", 0x000002, 0x100000, CRC(1fc638a4) SHA1(003dcfbb65a8f32a1a030502a11432287cf8b4e0) ) + ROM_LOAD32_BYTE( "mar-09.bin", 0x000003, 0x100000, CRC(18fec9e1) SHA1(1290a9c13b4fd7d2197b39ec616206796e3a17a8) ) ROM_LOAD32_BYTE( "mar-16.bin", 0x400000, 0x100000, CRC(8b329bc8) SHA1(6e34eb6e2628a01a699d20a5155afb2febc31255) ) + ROM_LOAD32_BYTE( "mar-14.bin", 0x400001, 0x100000, CRC(22d38c71) SHA1(62273665975f3e6000fa4b01755aeb70e5dd002d) ) + ROM_LOAD32_BYTE( "mar-12.bin", 0x400002, 0x100000, CRC(4c412512) SHA1(ccd5014bc9f9648cf5fa56bb8d54fc72a7099ca3) ) + ROM_LOAD32_BYTE( "mar-10.bin", 0x400003, 0x100000, CRC(73126fbc) SHA1(9b9c31335e4db726863b219072c83810008f88f9) ) ROM_REGION32_LE( 0x1000000, "dvi", 0 ) /* Video data - unused for now */ ROM_LOAD32_BYTE( "mar-17.bin", 0x000003, 0x100000, CRC(7799ed23) SHA1(ae28ad4fa6033a3695fa83356701b3774b26e6b0) ) // 56 V / 41 A @@ -3399,15 +3440,15 @@ ROM_START( lockload ) /* Board No. DE-0420-1 + Bottom board DE-0421-0 slightly d ROM_CONTINUE( 0x5c0000, 0x40000 ) /* 2/4 */ ROM_CONTINUE( 0x7c0000, 0x40000 ) /* 3/4 */ - ROM_REGION( 0x800000, "gfx4", 0 ) - ROM_LOAD32_BYTE( "mbm-08.a14", 0x000003, 0x100000, CRC(5358a43b) SHA1(778637fc63a0957338c7da3adb2555ffada177c4) ) - ROM_LOAD32_BYTE( "mbm-09.a16", 0x400003, 0x100000, CRC(2cce162f) SHA1(db5795465a36971861e8fb7436db0805717ad101) ) - ROM_LOAD32_BYTE( "mbm-10.a19", 0x000002, 0x100000, CRC(232e1c91) SHA1(868d4eb4873ecc210cbb3a266cae0b6ad8f11add) ) - ROM_LOAD32_BYTE( "mbm-11.a20", 0x400002, 0x100000, CRC(8a2a2a9f) SHA1(d11e0ea2785e35123bc56a8f18ce22f58432b599) ) - ROM_LOAD32_BYTE( "mbm-12.a21", 0x000001, 0x100000, CRC(7d221d66) SHA1(25c9c20485e443969c0bf4d74c4211c3881dabcd) ) - ROM_LOAD32_BYTE( "mbm-13.a22", 0x400001, 0x100000, CRC(678b9052) SHA1(ae8fc921813e53e9dbc3960e772c1c4de94c22a7) ) + ROM_REGION( 0x800000*2, "c355spr", ROMREGION_ERASE00 ) ROM_LOAD32_BYTE( "mbm-14.a23", 0x000000, 0x100000, CRC(5aaaf929) SHA1(5ee30db9b83db664d77e6b5e0988ce3366460df6) ) + ROM_LOAD32_BYTE( "mbm-12.a21", 0x000001, 0x100000, CRC(7d221d66) SHA1(25c9c20485e443969c0bf4d74c4211c3881dabcd) ) + ROM_LOAD32_BYTE( "mbm-10.a19", 0x000002, 0x100000, CRC(232e1c91) SHA1(868d4eb4873ecc210cbb3a266cae0b6ad8f11add) ) + ROM_LOAD32_BYTE( "mbm-08.a14", 0x000003, 0x100000, CRC(5358a43b) SHA1(778637fc63a0957338c7da3adb2555ffada177c4) ) ROM_LOAD32_BYTE( "mbm-15.a25", 0x400000, 0x100000, CRC(789ce7b1) SHA1(3fb390ce0620ce7a63f7f46eac1ff0eb8ed76d26) ) + ROM_LOAD32_BYTE( "mbm-13.a22", 0x400001, 0x100000, CRC(678b9052) SHA1(ae8fc921813e53e9dbc3960e772c1c4de94c22a7) ) + ROM_LOAD32_BYTE( "mbm-11.a20", 0x400002, 0x100000, CRC(8a2a2a9f) SHA1(d11e0ea2785e35123bc56a8f18ce22f58432b599) ) + ROM_LOAD32_BYTE( "mbm-09.a16", 0x400003, 0x100000, CRC(2cce162f) SHA1(db5795465a36971861e8fb7436db0805717ad101) ) ROM_REGION(0x80000, "oki1", 0 ) ROM_LOAD( "mbm-07.n19", 0x00000, 0x80000, CRC(414f3793) SHA1(ed5f63e57390d503193fd1e9f7294ae1da6d3539) ) @@ -3468,15 +3509,15 @@ ROM_START( gunhard ) /* Board No. DE-0420-1 + Bottom board DE-0421-0 slightly di ROM_CONTINUE( 0x5c0000, 0x40000 ) /* 2/4 */ ROM_CONTINUE( 0x7c0000, 0x40000 ) /* 3/4 */ - ROM_REGION( 0x800000, "gfx4", 0 ) - ROM_LOAD32_BYTE( "mbm-08.a14", 0x000003, 0x100000, CRC(5358a43b) SHA1(778637fc63a0957338c7da3adb2555ffada177c4) ) - ROM_LOAD32_BYTE( "mbm-09.a16", 0x400003, 0x100000, CRC(2cce162f) SHA1(db5795465a36971861e8fb7436db0805717ad101) ) - ROM_LOAD32_BYTE( "mbm-10.a19", 0x000002, 0x100000, CRC(232e1c91) SHA1(868d4eb4873ecc210cbb3a266cae0b6ad8f11add) ) - ROM_LOAD32_BYTE( "mbm-11.a20", 0x400002, 0x100000, CRC(8a2a2a9f) SHA1(d11e0ea2785e35123bc56a8f18ce22f58432b599) ) - ROM_LOAD32_BYTE( "mbm-12.a21", 0x000001, 0x100000, CRC(7d221d66) SHA1(25c9c20485e443969c0bf4d74c4211c3881dabcd) ) - ROM_LOAD32_BYTE( "mbm-13.a22", 0x400001, 0x100000, CRC(678b9052) SHA1(ae8fc921813e53e9dbc3960e772c1c4de94c22a7) ) + ROM_REGION( 0x800000*2, "c355spr", ROMREGION_ERASE00 ) ROM_LOAD32_BYTE( "mbm-14.a23", 0x000000, 0x100000, CRC(5aaaf929) SHA1(5ee30db9b83db664d77e6b5e0988ce3366460df6) ) + ROM_LOAD32_BYTE( "mbm-12.a21", 0x000001, 0x100000, CRC(7d221d66) SHA1(25c9c20485e443969c0bf4d74c4211c3881dabcd) ) + ROM_LOAD32_BYTE( "mbm-10.a19", 0x000002, 0x100000, CRC(232e1c91) SHA1(868d4eb4873ecc210cbb3a266cae0b6ad8f11add) ) + ROM_LOAD32_BYTE( "mbm-08.a14", 0x000003, 0x100000, CRC(5358a43b) SHA1(778637fc63a0957338c7da3adb2555ffada177c4) ) ROM_LOAD32_BYTE( "mbm-15.a25", 0x400000, 0x100000, CRC(789ce7b1) SHA1(3fb390ce0620ce7a63f7f46eac1ff0eb8ed76d26) ) + ROM_LOAD32_BYTE( "mbm-13.a22", 0x400001, 0x100000, CRC(678b9052) SHA1(ae8fc921813e53e9dbc3960e772c1c4de94c22a7) ) + ROM_LOAD32_BYTE( "mbm-11.a20", 0x400002, 0x100000, CRC(8a2a2a9f) SHA1(d11e0ea2785e35123bc56a8f18ce22f58432b599) ) + ROM_LOAD32_BYTE( "mbm-09.a16", 0x400003, 0x100000, CRC(2cce162f) SHA1(db5795465a36971861e8fb7436db0805717ad101) ) ROM_REGION(0x80000, "oki1", 0 ) ROM_LOAD( "mbm-07.n19", 0x00000, 0x80000, CRC(414f3793) SHA1(ed5f63e57390d503193fd1e9f7294ae1da6d3539) ) @@ -3537,15 +3578,15 @@ ROM_START( lockloadu ) /* Board No. DE-0359-2 + Bottom board DE-0360-4, a Dragon ROM_CONTINUE( 0x5c0000, 0x40000 ) /* 2/4 */ ROM_CONTINUE( 0x7c0000, 0x40000 ) /* 3/4 */ - ROM_REGION( 0x800000, "gfx4", 0 ) - ROM_LOAD32_BYTE( "mbm-08.a14", 0x000003, 0x100000, CRC(5358a43b) SHA1(778637fc63a0957338c7da3adb2555ffada177c4) ) - ROM_LOAD32_BYTE( "mbm-09.a16", 0x400003, 0x100000, CRC(2cce162f) SHA1(db5795465a36971861e8fb7436db0805717ad101) ) - ROM_LOAD32_BYTE( "mbm-10.a19", 0x000002, 0x100000, CRC(232e1c91) SHA1(868d4eb4873ecc210cbb3a266cae0b6ad8f11add) ) - ROM_LOAD32_BYTE( "mbm-11.a20", 0x400002, 0x100000, CRC(8a2a2a9f) SHA1(d11e0ea2785e35123bc56a8f18ce22f58432b599) ) - ROM_LOAD32_BYTE( "mbm-12.a21", 0x000001, 0x100000, CRC(7d221d66) SHA1(25c9c20485e443969c0bf4d74c4211c3881dabcd) ) - ROM_LOAD32_BYTE( "mbm-13.a22", 0x400001, 0x100000, CRC(678b9052) SHA1(ae8fc921813e53e9dbc3960e772c1c4de94c22a7) ) + ROM_REGION( 0x800000*2, "c355spr", ROMREGION_ERASE00 ) ROM_LOAD32_BYTE( "mbm-14.a23", 0x000000, 0x100000, CRC(5aaaf929) SHA1(5ee30db9b83db664d77e6b5e0988ce3366460df6) ) + ROM_LOAD32_BYTE( "mbm-12.a21", 0x000001, 0x100000, CRC(7d221d66) SHA1(25c9c20485e443969c0bf4d74c4211c3881dabcd) ) + ROM_LOAD32_BYTE( "mbm-10.a19", 0x000002, 0x100000, CRC(232e1c91) SHA1(868d4eb4873ecc210cbb3a266cae0b6ad8f11add) ) + ROM_LOAD32_BYTE( "mbm-08.a14", 0x000003, 0x100000, CRC(5358a43b) SHA1(778637fc63a0957338c7da3adb2555ffada177c4) ) ROM_LOAD32_BYTE( "mbm-15.a25", 0x400000, 0x100000, CRC(789ce7b1) SHA1(3fb390ce0620ce7a63f7f46eac1ff0eb8ed76d26) ) + ROM_LOAD32_BYTE( "mbm-13.a22", 0x400001, 0x100000, CRC(678b9052) SHA1(ae8fc921813e53e9dbc3960e772c1c4de94c22a7) ) + ROM_LOAD32_BYTE( "mbm-11.a20", 0x400002, 0x100000, CRC(8a2a2a9f) SHA1(d11e0ea2785e35123bc56a8f18ce22f58432b599) ) + ROM_LOAD32_BYTE( "mbm-09.a16", 0x400003, 0x100000, CRC(2cce162f) SHA1(db5795465a36971861e8fb7436db0805717ad101) ) ROM_REGION32_LE( 0x1000000, "dvi", ROMREGION_ERASE00 ) /* Video data - same as Dragongun, probably leftover from a conversion */ // ROM_LOAD( "mar-17.bin", 0x00000, 0x100000, CRC(7799ed23) SHA1(ae28ad4fa6033a3695fa83356701b3774b26e6b0) ) diff --git a/src/mame/drivers/gal3.cpp b/src/mame/drivers/gal3.cpp index 34fb85a8935..5dc9a84a89a 100644 --- a/src/mame/drivers/gal3.cpp +++ b/src/mame/drivers/gal3.cpp @@ -208,7 +208,8 @@ uint32_t gal3_state::screen_update_left(screen_device &screen, bitmap_ind16 &bit { bitmap.fill(0xff, cliprect); // TODO : actually laserdisc layer screen.priority().fill(0, cliprect); - m_c355spr[0]->get_sprites(cliprect); // TODO : buffered? + + m_c355spr[0]->build_sprite_list_and_render_sprites(cliprect); // TODO : buffered? int i; char mst[18], slv[18]; @@ -262,7 +263,7 @@ uint32_t gal3_state::screen_update_right(screen_device &screen, bitmap_ind16 &bi { bitmap.fill(0xff, cliprect); // TODO : actually laserdisc layer screen.priority().fill(0, cliprect); - m_c355spr[1]->get_sprites(cliprect); // TODO : buffered? + m_c355spr[1]->build_sprite_list_and_render_sprites(cliprect); // TODO : buffered? static int pivot = 15; int pri; diff --git a/src/mame/drivers/namconb1.cpp b/src/mame/drivers/namconb1.cpp index 0876ee12ace..5464ec46d6c 100644 --- a/src/mame/drivers/namconb1.cpp +++ b/src/mame/drivers/namconb1.cpp @@ -995,6 +995,7 @@ void namconb1_state::namconb1(machine_config &config) m_c355spr->set_palxor(0x0); m_c355spr->set_buffer(2); // triple buffered m_c355spr->set_color_base(0); + m_c355spr->set_draw_2_lists(false); // prevents bad tile on top left of vshoot during certain scenes NAMCO_C123TMAP(config, m_c123tmap); m_c123tmap->set_palette(m_c116); diff --git a/src/mame/drivers/namcos21_c67.cpp b/src/mame/drivers/namcos21_c67.cpp index cdc9f210738..08305d7921a 100644 --- a/src/mame/drivers/namcos21_c67.cpp +++ b/src/mame/drivers/namcos21_c67.cpp @@ -372,7 +372,7 @@ uint32_t namcos21_c67_state::screen_update(screen_device &screen, bitmap_ind16 & int pri; bitmap.fill(0xff, cliprect ); screen.priority().fill(0, cliprect); - m_c355spr->get_sprites(cliprect); // TODO : buffered? + m_c355spr->build_sprite_list_and_render_sprites(cliprect); // TODO : buffered? m_c355spr->draw(screen, bitmap, cliprect, 2 ); diff --git a/src/mame/drivers/namcos21_de.cpp b/src/mame/drivers/namcos21_de.cpp index 08d7e3973d0..a037cca5c2d 100644 --- a/src/mame/drivers/namcos21_de.cpp +++ b/src/mame/drivers/namcos21_de.cpp @@ -221,7 +221,7 @@ uint32_t namco_de_pcbstack_device::screen_update(screen_device &screen, bitmap_i int pri; bitmap.fill(0xff, cliprect ); screen.priority().fill(0, cliprect); - m_c355spr->get_sprites(cliprect); // TODO : buffered? + m_c355spr->build_sprite_list_and_render_sprites(cliprect); // TODO : buffered? m_c355spr->draw(screen, bitmap, cliprect, 2 ); m_c355spr->draw(screen, bitmap, cliprect, 14 ); //driver's eyes diff --git a/src/mame/includes/deco32.h b/src/mame/includes/deco32.h index 0b1ecfad5af..c2c009a9789 100644 --- a/src/mame/includes/deco32.h +++ b/src/mame/includes/deco32.h @@ -14,7 +14,7 @@ #include "sound/ymopm.h" #include "machine/deco146.h" #include "machine/deco104.h" -#include "video/deco_zoomspr.h" +#include "video/namco_c355spr.h" #include "emupal.h" #include "screen.h" @@ -218,10 +218,12 @@ class dragngun_state : public deco32_state public: dragngun_state(const machine_config &mconfig, device_type type, const char *tag) : deco32_state(mconfig, type, tag) - , m_sprgenzoom(*this, "spritegen_zoom") + , m_sprgenzoom(*this, "c355spr") , m_spriteram(*this, "spriteram") - , m_sprite_layout_ram(*this, "lay%u", 0) - , m_sprite_lookup_ram(*this, "look%u", 0) + , m_sprite_spriteformat(*this, "lay%u", 0) + , m_sprite_spritetile(*this, "look%u", 0) + , m_sprite_cliptable(*this, "spclip") + , m_sprite_indextable(*this, "spindex") , m_vol_main(*this, "vol_main") , m_vol_gun(*this, "vol_gun") , m_io_inputs(*this, "INPUTS") @@ -241,11 +243,14 @@ public: DECLARE_INPUT_CHANGED_MEMBER(lockload_gun_trigger); private: - required_device m_sprgenzoom; + required_device m_sprgenzoom; required_device m_spriteram; - required_shared_ptr_array m_sprite_layout_ram; - required_shared_ptr_array m_sprite_lookup_ram; + required_shared_ptr_array m_sprite_spriteformat; + required_shared_ptr_array m_sprite_spritetile; + required_shared_ptr m_sprite_cliptable; + required_shared_ptr m_sprite_indextable; + required_device m_vol_main; optional_device m_vol_gun; @@ -276,6 +281,16 @@ private: void lockload_okibank_hi_w(u8 data); // lockload virtual void video_start() override; + + int sprite_bank_callback(int sprite); + u16 read_spritetile(int lookupram_offset); + u16 read_spriteformat(int spriteformatram_offset, u8 attr); + u16 read_spritetable(int offs, u8 attr, int whichlist); + u16 read_spritelist(int offs, int whichlist); + u16 read_cliptable(int offs, u8 attr); + int sprite_priority_callback(int priority); + + void expand_sprite_data(); void dragngun_init_common(); u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -283,6 +298,9 @@ private: DECO16IC_BANK_CB_MEMBER(bank_1_callback); DECO16IC_BANK_CB_MEMBER(bank_2_callback); + void namco_sprites(machine_config &config); + + void namcosprite_map(address_map &map); void dragngun_map(address_map &map); void lockload_map(address_map &map); void lockloadu_map(address_map &map); diff --git a/src/mame/video/deco32.cpp b/src/mame/video/deco32.cpp index 679dffd9f58..6d785feb4a1 100644 --- a/src/mame/video/deco32.cpp +++ b/src/mame/video/deco32.cpp @@ -176,6 +176,63 @@ u32 captaven_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c return 0; } +u16 dragngun_state::read_spritetile(int lookupram_offset) +{ + if (lookupram_offset & 0x2000) + return m_sprite_spritetile[1][lookupram_offset&0x1fff]; + else + return m_sprite_spritetile[0][lookupram_offset&0x1fff]; +} + +u16 dragngun_state::read_spriteformat(int spriteformatram_offset, u8 attr) +{ + if (spriteformatram_offset & 0x400) + return m_sprite_spriteformat[1][((spriteformatram_offset & 0x1ff)<<2) + attr]; + else + return m_sprite_spriteformat[0][((spriteformatram_offset & 0x1ff)<<2) + attr]; +} + +u16 dragngun_state::read_spritetable(int offs, u8 attr, int whichlist) +{ + return m_spriteram->buffer()[(offs << 3) + attr]; +} + +u16 dragngun_state::read_spritelist(int offs, int whichlist) +{ + return m_sprite_indextable[offs]; +} + +u16 dragngun_state::read_cliptable(int offs, u8 attr) +{ + return m_sprite_cliptable[(offs << 2) + attr]; +} + +int dragngun_state::sprite_priority_callback(int priority) +{ + /* For some reason, this bit when used in Dragon Gun causes the sprites + to flicker every other frame (fake transparency) + + This would usually be a priority bit, but the flicker can't be a + post-process mixing effect filtering out those priorities, because then + it would still cut holes in sprites where it was drawn, and it doesn't. + + Instead sprites with this priority must simple be disabled every other + frame. maybe there's a register in the sprite chip to control this on + a per-priority level? + */ + + if ((priority & 0x80) && (m_screen->frame_number() & 1)) // flicker + return -1; + + priority = (priority & 0x60) >> 5; + if (priority == 0) priority = 7; + else if (priority == 1) priority = 7; // set to 1 to have the 'masking effect' with the dragon on the dragngun attract mode, but that breaks the player select where it needs to be 3, probably missing some bits.. + else if (priority == 2) priority = 7; + else if (priority == 3) priority = 7; + return priority; +} + + u32 dragngun_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { screen.priority().fill(0, cliprect); @@ -200,8 +257,7 @@ u32 dragngun_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, c { rectangle clip(cliprect.left(), cliprect.right(), 8, 247); - m_sprgenzoom->dragngun_draw_sprites(screen,bitmap,clip,m_spriteram->buffer(), m_sprite_layout_ram[0], m_sprite_layout_ram[1], m_sprite_lookup_ram[0], m_sprite_lookup_ram[1], m_sprite_ctrl, screen.priority(), m_temp_render_bitmap); - + m_sprgenzoom->draw_dg(screen, bitmap, clip, screen.priority(), m_temp_render_bitmap); } return 0; diff --git a/src/mame/video/deco_zoomspr.cpp b/src/mame/video/deco_zoomspr.cpp deleted file mode 100644 index 7fc8327c981..00000000000 --- a/src/mame/video/deco_zoomspr.cpp +++ /dev/null @@ -1,414 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Bryan McPhail,David Haywood - -/* the sprites used by DragonGun + Lock 'n' Loaded */ - -/* probably 186 + 187 custom chips, although there is a 145 too? */ - -// helicopter in lockload is only half drawn? (3rd attract demo) -// how are we meant to mix these with the tilemaps, parts must go above / behind parts of tilemap '4/7' in lockload, could be more priority masking sprites we're missing / not drawing tho? -// dragongun also does a masking trick on the dragon during the attract intro, it should not be visible but rather cause the fire to be invisible in the shape of the dragon (see note / hack in code to enable this effect) -// dragongun 'waterfall' prior to one of the bosses also needs correct priority - -#include "emu.h" -#include "deco_zoomspr.h" - -DEFINE_DEVICE_TYPE(DECO_ZOOMSPR, deco_zoomspr_device, "deco_zoomspr", "DECO Zooming Sprites") - -deco_zoomspr_device::deco_zoomspr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, DECO_ZOOMSPR, tag, owner, clock) - , m_gfxdecode(*this, finder_base::DUMMY_TAG) -{ -} - -void deco_zoomspr_device::device_start() -{ -} - -void deco_zoomspr_device::device_reset() -{ -} - -/******************************************************************************/ - - -inline void deco_zoomspr_device::dragngun_drawgfxzoom( - bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, - uint32_t code,uint32_t color,int flipx,int flipy,int sx,int sy, - int transparent_color, - int scalex, int scaley,bitmap_ind8 *pri_buffer,uint32_t pri_mask, int sprite_screen_width, int sprite_screen_height, uint8_t alpha, - bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap, - int priority) -{ - rectangle myclip; - - if (!scalex || !scaley) return; - - /* - scalex and scaley are 16.16 fixed point numbers - 1<<15 : shrink to 50% - 1<<16 : uniform scale - 1<<17 : double to 200% - */ - - /* KW 991012 -- Added code to force clip to bitmap boundary */ - myclip = clip; - myclip &= temp_bitmap.cliprect(); - - { - if( gfx ) - { - const pen_t *pal = &m_gfxdecode->palette().pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); - const uint8_t *code_base = gfx->get_data(code % gfx->elements()); - - if (sprite_screen_width && sprite_screen_height) - { - /* compute sprite increment per screen pixel */ - int dx = (gfx->width()<<16)/sprite_screen_width; - int dy = (gfx->height()<<16)/sprite_screen_height; - - int ex = sx+sprite_screen_width; - int ey = sy+sprite_screen_height; - - int x_index_base; - int y_index; - - if( flipx ) - { - x_index_base = (sprite_screen_width-1)*dx; - dx = -dx; - } - else - { - x_index_base = 0; - } - - if( flipy ) - { - y_index = (sprite_screen_height-1)*dy; - dy = -dy; - } - else - { - y_index = 0; - } - - if( sx < clip.left()) - { /* clip left */ - int pixels = clip.left()-sx; - sx += pixels; - x_index_base += pixels*dx; - } - if( sy < clip.top() ) - { /* clip top */ - int pixels = clip.top()-sy; - sy += pixels; - y_index += pixels*dy; - } - /* NS 980211 - fixed incorrect clipping */ - if( ex > clip.right()+1 ) - { /* clip right */ - int pixels = ex-clip.right()-1; - ex -= pixels; - } - if( ey > clip.bottom()+1 ) - { /* clip bottom */ - int pixels = ey-clip.bottom()-1; - ey -= pixels; - } - - if( ex>sx ) - { /* skip if inner loop doesn't draw anything */ - - /* case 1: no alpha */ - if (alpha == 0xff) - { - { - for( int y=sy; y>16) * gfx->rowbytes(); - uint32_t *const dest = &temp_bitmap.pix(y); - uint8_t *const pri = &pri_bitmap.pix(y); - - - int x_index = x_index_base; - for( int x=sx; x>16]; - if (c != transparent_color) - { - if (priority >= pri[x]) - { - dest[x] = pal[c]; - dest[x] |= 0xff000000; - } - else // sprites can have a 'masking' effect on other sprites - { - dest[x] = 0x00000000; - } - } - - x_index += dx; - } - - y_index += dy; - } - } - } - - /* alpha-blended */ - else - { - { - for( int y=sy; y>16) * gfx->rowbytes(); - uint32_t *const dest = &temp_bitmap.pix(y); - uint8_t *const pri = &pri_bitmap.pix(y); - uint32_t *const tmapcolor = &dest_bmp.pix(y); - - - int x_index = x_index_base; - for( int x=sx; x>16]; - if (c != transparent_color) - { - if (priority >= pri[x]) - { - // this logic doesn't seem correct. Sprites CAN blend other sprites (needed in many places) but based on videos of the character select screen it appears that sprites can't blend already blended sprites - // I'm not sure which colour gets used but the video shows a single shade of yellow rather than the yellow blending the yellow) - - if ((dest[x] & 0xff000000) == 0x00000000) - dest[x] = alpha_blend_r32(tmapcolor[x] & 0x00ffffff, pal[c] & 0x00ffffff, alpha); // if nothing has been drawn pull the pixel from the tilemap to blend with - else - dest[x] = alpha_blend_r32(dest[x] & 0x00ffffff, pal[c] & 0x00ffffff, alpha); // otherwise blend with what was previously drawn - - dest[x] |= 0xff000000; - } - else // sprites can have a 'masking' effect on other sprites - { - dest[x] = 0x00000000; - } - } - - x_index += dx; - } - - y_index += dy; - } - } - } - } - } - } - } -} - -void deco_zoomspr_device::dragngun_draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, const uint32_t *spritedata, uint32_t* dragngun_sprite_layout_0_ram, uint32_t* dragngun_sprite_layout_1_ram, uint32_t* dragngun_sprite_lookup_0_ram, uint32_t* dragngun_sprite_lookup_1_ram, uint32_t dragngun_sprite_ctrl, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap) -{ - const uint32_t *layout_ram; - const uint32_t *lookup_ram; - int offs; - temp_bitmap.fill(0x00000000, cliprect); - - /* - Sprites are built from main control ram, which references tile - layout ram, which finally references tile lookup ram which holds - the actual tile indices to draw and index into the banking - control. Tile lookup and tile layout ram are double buffered. - - - Main sprite control ram, 8 * 32 bit words per sprite, so - - Word 0: - 0x0400 - Banking control for tile layout RAM + tile lookup ram - 0x0200 - ? - 0x01ff - Index into tile layout RAM - Word 1 : - Word 2 : X base position - Word 3 : Y base position - Word 4 : - 0x8000: X flip - 0x03ff: X size of block in pixels (for scaling) - Word 5 : - 0x8000: Y flip - 0x03ff: Y size of block in pixels (for scaling) - Word 6 : - 0x0000001f - colour. - 0x00000020 - ? Used for background at 'frog' boss and title screen dragon. - 0x00000040 - ? priority? - 0x00000080 - flicker - 0x40000000 - Additive/Subtractable blend? (dragngun) - Word 7 : - - - Tile layout ram, 4 * 32 bit words per sprite, so - - Word 0: - 0x2000 - Selector for tile lookup bank!?!?!?!?!?!? - 0x1fff - Index into tile lookup ram (16 bit word based, NOT 32) - Word 1: - 0xff00 - ? - 0x00f0 - Width - 0x000f - Height - Word 2: - 0x01ff - X block offset - Word 3: - 0x01ff - Y block offset - */ - - /* Sprite global disable bit - can't be, it's set in lockload calibration menu where the targets are sprites */ -// if (dragngun_sprite_ctrl&0x40000000) -// return; - - for (offs = 0;offs < 0x800;offs += 8) - { - if ((spritedata[offs+6]&0x80) && (screen.frame_number() & 1)) // flicker - continue; - - int sx,sy,colour,fx,fy,w,h,x,y,bx,by/*,alpha*/,scalex,scaley; - int zoomx,zoomy; - int xpos,ypos; - - scalex=spritedata[offs+4]&0x3ff; - scaley=spritedata[offs+5]&0x3ff; - if (!scalex || !scaley) /* Zero pixel size in X or Y - skip block */ - continue; - - int layoutram_offset = (spritedata[offs + 0] & 0x1ff) * 4; - - if (spritedata[offs + 0] & 0x400) - layout_ram = dragngun_sprite_layout_1_ram; - else - layout_ram = dragngun_sprite_layout_0_ram; - h = (layout_ram[layoutram_offset + 1]>>0)&0xf; - w = (layout_ram[layoutram_offset + 1]>>4)&0xf; - if (!h || !w) - continue; - - sx = spritedata[offs+2] & 0x3ff; - sy = spritedata[offs+3] & 0x3ff; - bx = layout_ram[layoutram_offset + 2] & 0x1ff; - by = layout_ram[layoutram_offset + 3] & 0x1ff; - if (bx&0x100) bx=1-(bx&0xff); - if (by&0x100) by=1-(by&0xff); /* '1 - ' is strange, but correct for Dragongun 'Winners' screen. */ - if (sx >= 512) sx -= 1024; - if (sy >= 512) sy -= 1024; - - colour = spritedata[offs+6]&0x1f; - - int priority = (spritedata[offs + 6] & 0x60) >> 5; - - - - -// printf("%02x\n", priority); - - if (priority == 0) priority = 7; - else if (priority == 1) priority = 7; // set to 1 to have the 'masking effect' with the dragon on the dragngun attract mode, but that breaks the player select where it needs to be 3, probably missing some bits.. - else if (priority == 2) priority = 7; - else if (priority == 3) priority = 7; - - fx = spritedata[offs+4]&0x8000; - fy = spritedata[offs+5]&0x8000; - - int lookupram_offset = layout_ram[layoutram_offset + 0] & 0x1fff; - -// if (spritedata[offs+0]&0x400) - if (layout_ram[layoutram_offset + 0] & 0x2000) - lookup_ram = dragngun_sprite_lookup_1_ram; - else - lookup_ram = dragngun_sprite_lookup_0_ram; - - zoomx=scalex * 0x10000 / (w*16); - zoomy=scaley * 0x10000 / (h*16); - - if (!fy) - ypos=(sy<<16) - (by*zoomy); /* The block offset scales with zoom, the base position does not */ - else - ypos=(sy<<16) + (by*zoomy) - (16*zoomy); - - for (y=0; ygfx(bank), - sprite, - colour, - fx,fy, - xpos>>16,ypos>>16, - 15,zoomx,zoomy,nullptr,0, - ((xpos+(zoomx<<4))>>16) - (xpos>>16), ((ypos+(zoomy<<4))>>16) - (ypos>>16), 0xff/*alpha*/, - pri_bitmap, temp_bitmap, - priority - ); - - - if (fx) - xpos-=zoomx<<4; - else - xpos+=zoomx<<4; - } - if (fy) - ypos-=zoomy<<4; - else - ypos+=zoomy<<4; - } - } - - for (int y = cliprect.top(); y <= cliprect.bottom(); y++) - { - uint32_t const *const src = &temp_bitmap.pix(y); - uint32_t *const dst = &bitmap.pix(y); - - for (int x = cliprect.left(); x <= cliprect.right(); x++) - { - uint32_t const srcpix = src[x]; - - if ((srcpix & 0xff000000) == 0xff000000) - { - dst[x] = srcpix & 0x00ffffff; - } - } - - } - -} diff --git a/src/mame/video/deco_zoomspr.h b/src/mame/video/deco_zoomspr.h deleted file mode 100644 index aa96be54f88..00000000000 --- a/src/mame/video/deco_zoomspr.h +++ /dev/null @@ -1,39 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Bryan McPhail,David Haywood -#ifndef MAME_VIDEO_DECO_ZOOMSPR_H -#define MAME_VIDEO_DECO_ZOOMSPR_H - -#pragma once - -#include "screen.h" - -class deco_zoomspr_device : public device_t -{ -public: - deco_zoomspr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - template void set_gfxdecode(T &&tag) { m_gfxdecode.set_tag(std::forward(tag)); } - - void dragngun_draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, const uint32_t *spritedata, uint32_t* dragngun_sprite_layout_0_ram, uint32_t* dragngun_sprite_layout_1_ram, uint32_t* dragngun_sprite_lookup_0_ram, uint32_t* dragngun_sprite_lookup_1_ram, uint32_t dragngun_sprite_ctrl, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap); - - -protected: - virtual void device_start() override; - virtual void device_reset() override; - -private: - required_device m_gfxdecode; - - void dragngun_drawgfxzoom( - bitmap_rgb32 &dest_bmp, const rectangle &clip, gfx_element *gfx, - uint32_t code, uint32_t color, int flipx, int flipy, int sx, int sy, - int transparent_color, - int scalex, int scaley, bitmap_ind8 *pri_buffer, uint32_t pri_mask, int sprite_screen_width, int sprite_screen_height, uint8_t alpha, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap, - int priority); - -}; - - -DECLARE_DEVICE_TYPE(DECO_ZOOMSPR, deco_zoomspr_device) - -#endif // MAME_VIDEO_DECO_ZOOMSPR_H diff --git a/src/mame/video/namco_c355spr.cpp b/src/mame/video/namco_c355spr.cpp index 43cd4cfb1f4..ea2780abaf9 100644 --- a/src/mame/video/namco_c355spr.cpp +++ b/src/mame/video/namco_c355spr.cpp @@ -1,14 +1,52 @@ // license:BSD-3-Clause -// copyright-holders:David Haywood, Phil Stroffolino +// copyright-holders:David Haywood, Phil Stroffolino, Bryan McPhail /* - C355 Zooming sprites + Namco 186/187 Zooming Sprites + Namco C355 Zooming sprites + used by namcofl.cpp (all games) namconb1.cpp (all games) gal3.cpp (all games) namcos21.cpp (Driver's Eyes, Solvalou, Starblade, Air Combat, Cyber Sled) (everything except Winning Run series) namcos2.cpp (Steel Gunner, Steel Gunner 2, Lucky & Wild, Suzuka 8 Hours, Suzuka 8 Hours 2) + deco32.cpp (Dragon Gun, Lock 'n' Loaded) + + earlier titles use the 186/187 pair (eg. Steel Gunner, Dragon Gun) while later boards appear to implement the + same functionality in a single C355 custom (NB1 hardware, Final Lap R etc.) It is not known if there are any + differences in capability. + + TODO: verify which boards use which chips + + + dragongun does a masking trick on the dragon during the attract intro, it should not be visible but rather + cause the fire to be invisible in the shape of the dragon + dragongun 'waterfall' prior to one of the bosses also needs correct priority + + + relative to the start of the sprite area these offets are typically used + it is not clear if this is implemented in a single RAM chip, or multiple on some boards + + * 0x00000 sprite attr (page0) (solvalou service mode) + * 0x02000 sprite list (page0) (solvalou service mode) + * + * 0x02400 window attributes + * 0x04000 format + * 0x08000 tile + * 0x10000 sprite attr (page1) + * 0x14000 sprite list (page1) + + TODO: solvalou service mode wants lists / attributes at 0x02000/2 & 0x00000/2 + Drawing this is what causes the bad tile in vshoot + + Do any games need 2 lists at the same time or should 1 list be configurable? + + It seems unlikely there are really 2 lists + + Maybe the list written by solvalou's service mode is where data gets copied for + rendering by the sprite DMA trigger, but solvalou is choosing to write it there + directly rather than trigger the DMA? */ @@ -17,17 +55,27 @@ #include -DEFINE_DEVICE_TYPE(NAMCO_C355SPR, namco_c355spr_device, "namco_c355spr", "Namco C355 (Sprites)") +DEFINE_DEVICE_TYPE(NAMCO_C355SPR, namco_c355spr_device, "namco_c355spr", "Namco 186/187 or C355 (Sprites)") -namco_c355spr_device::namco_c355spr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - device_t(mconfig, NAMCO_C355SPR, tag, owner, clock), +namco_c355spr_device::namco_c355spr_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), device_gfx_interface(mconfig, *this, nullptr), device_video_interface(mconfig, *this), + m_pri_cb(*this, DEVICE_SELF, FUNC(namco_c355spr_device::default_priority)), + m_read_spritetile(*this, DEVICE_SELF, FUNC(namco_c355spr_device::read_spritetile)), + m_read_spriteformat(*this, DEVICE_SELF, FUNC(namco_c355spr_device::read_spriteformat)), + m_read_spritetable(*this, DEVICE_SELF, FUNC(namco_c355spr_device::read_spritetable)), + m_read_cliptable(*this, DEVICE_SELF, FUNC(namco_c355spr_device::read_cliptable)), + m_read_spritelist(*this, DEVICE_SELF, FUNC(namco_c355spr_device::read_spritelist)), m_palxor(0), m_buffer(0), m_external_prifill(false), m_gfx_region(*this, DEVICE_SELF), - m_colbase(0) + m_colbase(0), + m_colors(16), + m_granularity(256), + m_draw_2_lists(true), + m_device_allocates_spriteram_and_bitmaps(true) { std::fill(std::begin(m_position), std::end(m_position), 0); std::fill(std::begin(m_scrolloffs), std::end(m_scrolloffs), 0); @@ -35,101 +83,132 @@ namco_c355spr_device::namco_c355spr_device(const machine_config &mconfig, const m_spriteram[i] = nullptr; } +namco_c355spr_device::namco_c355spr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + namco_c355spr_device(mconfig, NAMCO_C355SPR, tag, owner, clock) +{ +} /**************************************************************************************/ +template void namco_c355spr_device::zdrawgfxzoom( - bitmap_ind16 &dest_bmp,const rectangle &clip,gfx_element *gfx, - u32 code,u32 color,bool flipx,bool flipy,int sx,int sy, - int scalex, int scaley, u8 prival) + BitmapClass *dest_bmp, const rectangle &clip, gfx_element *gfx, + u32 code, u32 color, bool flipx, bool flipy, int hpos, int vpos, + int hsize, int vsize, u8 prival, + + bitmap_ind8 *pri_buffer, + int sprite_screen_width, int sprite_screen_height, + bitmap_ind8 *pri_bitmap) { - if (!scalex || !scaley) return; - if (dest_bmp.bpp() == 16) + if (!hsize || !vsize) return; + if (!gfx) return; + + const u32 pal = gfx->colorbase() + gfx->granularity() * (color % gfx->colors()); + const pen_t *palpen = &gfx->palette().pen(pal); + + const u8 *source_base = gfx->get_data(code % gfx->elements()); + if (sprite_screen_width && sprite_screen_height) { - if (gfx) - { - const u32 pal = gfx->colorbase() + gfx->granularity() * (color % gfx->colors()); - const u8 *source_base = gfx->get_data(code % gfx->elements()); - int sprite_screen_height = (scaley * gfx->height() + 0x8000) >> 16; - int sprite_screen_width = (scalex * gfx->width() + 0x8000) >> 16; - if (sprite_screen_width && sprite_screen_height) - { - /* compute sprite increment per screen pixel */ - int dx = (gfx->width() << 16) / sprite_screen_width; - int dy = (gfx->height() << 16) / sprite_screen_height; + /* compute sprite increment per screen pixel */ + int dx = (gfx->width() << 16) / sprite_screen_width; + int dy = (gfx->height() << 16) / sprite_screen_height; - int ex = sx + sprite_screen_width; - int ey = sy + sprite_screen_height; + int ex = hpos + sprite_screen_width; + int ey = vpos + sprite_screen_height; - int x_index_base; - int y_index; + int x_index_base; + int y_index; - if (flipx) - { - x_index_base = (sprite_screen_width - 1) * dx; - dx = -dx; - } - else - { - x_index_base = 0; - } + if (flipx) + { + x_index_base = (sprite_screen_width - 1) * dx; + dx = -dx; + } + else + { + x_index_base = 0; + } - if (flipy) - { - y_index = (sprite_screen_height - 1) * dy; - dy = -dy; - } - else - { - y_index = 0; - } + if (flipy) + { + y_index = (sprite_screen_height - 1) * dy; + dy = -dy; + } + else + { + y_index = 0; + } - if (sx < clip.min_x) - { /* clip left */ - int pixels = clip.min_x - sx; - sx += pixels; - x_index_base += pixels * dx; - } - if (sy < clip.min_y) - { /* clip top */ - int pixels = clip.min_y - sy; - sy += pixels; - y_index += pixels * dy; - } - if (ex > clip.max_x + 1) - { /* clip right */ - int pixels = ex - clip.max_x - 1; - ex -= pixels; - } - if (ey > clip.max_y + 1) - { /* clip bottom */ - int pixels = ey - clip.max_y - 1; - ey -= pixels; - } + if (hpos < clip.min_x) + { /* clip left */ + int pixels = clip.min_x - hpos; + hpos += pixels; + x_index_base += pixels * dx; + } + if (vpos < clip.min_y) + { /* clip top */ + int pixels = clip.min_y - vpos; + vpos += pixels; + y_index += pixels * dy; + } + if (ex > clip.max_x + 1) + { /* clip right */ + int pixels = ex - clip.max_x - 1; + ex -= pixels; + } + if (ey > clip.max_y + 1) + { /* clip bottom */ + int pixels = ey - clip.max_y - 1; + ey -= pixels; + } + + if (ex > hpos) + { /* skip if inner loop doesn't draw anything */ + for (int y = vpos; y < ey; y++) + { + u8 const *const source = source_base + (y_index >> 16) * gfx->rowbytes(); + auto *const dest = &dest_bmp->pix(y); + int x_index = x_index_base; + u8 *pri = nullptr; - if (ex > sx) - { /* skip if inner loop doesn't draw anything */ - for (int y = sy; y < ey; y++) + if (dest_bmp->bpp() == 32) + pri = &pri_bitmap->pix(y); + + for (int x = hpos; x < ex; x++) + { + if (dest_bmp->bpp() == 16) + { + const u8 c = source[x_index >> 16]; + if (c != 0xff) + { + dest[x] = ((prival & 0xf) << 12) | ((pal + c) & 0xfff); + } + x_index += dx; + } + else if (dest_bmp->bpp() == 32) { - u8 const *const source = source_base + (y_index>>16) * gfx->rowbytes(); - u16 *const dest = &dest_bmp.pix(y); - int x_index = x_index_base; - for (int x = sx; x < ex; x++) + int c = source[x_index >> 16]; + if (c != 15) { - const u8 c = source[x_index>>16]; - if (c != 0xff) + if (prival >= pri[x]) { - dest[x] = ((prival & 0xf) << 12) | ((pal + c) & 0xfff); + dest[x] = palpen[c]; + dest[x] |= 0xff000000; + } + else // sprites can have a 'masking' effect on other sprites + { + dest[x] = 0x00000000; } - x_index += dx; } - y_index += dy; + + x_index += dx; } } + y_index += dy; } } } -} /* zdrawgfxzoom */ +} void namco_c355spr_device::copybitmap(bitmap_ind16 &dest_bmp, const rectangle &clip, u8 pri) { @@ -137,7 +216,7 @@ void namco_c355spr_device::copybitmap(bitmap_ind16 &dest_bmp, const rectangle &c { for (int y = clip.min_y; y <= clip.max_y; y++) { - u16 *const src = &m_tempbitmap.pix(y); + u16 *const src = &m_renderbitmap.pix(y); u16 *const dest = &dest_bmp.pix(y); for (int x = clip.min_x; x <= clip.max_x; x++) { @@ -171,7 +250,7 @@ void namco_c355spr_device::copybitmap(bitmap_ind16 &dest_bmp, const rectangle &c { for (int y = clip.min_y; y <= clip.max_y; y++) { - u16 *const src = &m_tempbitmap.pix(y); + u16 *const src = &m_renderbitmap.pix(y); u16 *const dest = &dest_bmp.pix(y); for (int x = clip.min_x; x <= clip.max_x; x++) { @@ -207,7 +286,7 @@ void namco_c355spr_device::copybitmap(bitmap_rgb32 &dest_bmp, const rectangle &c { for (int y = clip.min_y; y <= clip.max_y; y++) { - u16 *const src = &m_tempbitmap.pix(y); + u16 *const src = &m_renderbitmap.pix(y); u16 *const srcrender = &m_screenbitmap.pix(y); u32 *const dest = &dest_bmp.pix(y); for (int x = clip.min_x; x <= clip.max_x; x++) @@ -245,7 +324,7 @@ void namco_c355spr_device::copybitmap(bitmap_rgb32 &dest_bmp, const rectangle &c { for (int y = clip.min_y; y <= clip.max_y; y++) { - u16 *const src = &m_tempbitmap.pix(y); + u16 *const src = &m_renderbitmap.pix(y); u16 *const srcrender = &m_screenbitmap.pix(y); u32 *const dest = &dest_bmp.pix(y); for (int x = clip.min_x; x <= clip.max_x; x++) @@ -279,8 +358,8 @@ void namco_c355spr_device::copybitmap(bitmap_rgb32 &dest_bmp, const rectangle &c void namco_c355spr_device::device_start() { - screen().register_screen_bitmap(m_tempbitmap); - screen().register_screen_bitmap(m_screenbitmap); + m_pri_cb.resolve(); + gfx_layout obj_layout = { 16,16, @@ -294,17 +373,37 @@ void namco_c355spr_device::device_start() obj_layout.total = m_gfx_region->bytes() / (16*16*8 / 8); std::fill(std::begin(m_position), std::end(m_position), 0x0000); + for (int i = 0; i < 2; i++) { - m_spritelist[i] = std::make_unique(0x100); + m_spritelist[i] = std::make_unique(0x100); m_sprite_end[i] = m_spritelist[i].get(); - m_spriteram[i] = std::make_unique(0x20000/2); - std::fill_n(m_spriteram[i].get(), 0x20000/2, 0); - save_pointer(NAME(m_spriteram[i]), 0x20000/2, i); } - set_gfx(0, std::make_unique(&palette(), obj_layout, m_gfx_region->base(), 0, 0x10, m_colbase)); + + if (m_device_allocates_spriteram_and_bitmaps) + { + for (int i = 0; i < 2; i++) + { + m_spriteram[i] = std::make_unique(0x20000 / 2); + std::fill_n(m_spriteram[i].get(), 0x20000 / 2, 0); + save_pointer(NAME(m_spriteram[i]), 0x20000 / 2, i); + } + + screen().register_screen_bitmap(m_renderbitmap); + screen().register_screen_bitmap(m_screenbitmap); + } + + set_gfx(0, std::make_unique(&palette(), obj_layout, m_gfx_region->base(), 0, m_colors, m_colbase)); + gfx(0)->set_granularity(m_granularity); + + m_read_spritetile.resolve(); + m_read_spriteformat.resolve(); + m_read_spritetable.resolve(); + m_read_cliptable.resolve(); + m_read_spritelist.resolve(); save_item(NAME(m_position)); + } void namco_c355spr_device::device_stop() @@ -317,13 +416,13 @@ void namco_c355spr_device::device_stop() device_t::device_stop(); } - /**************************************************************************************/ void namco_c355spr_device::position_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_position[offset]); } + u16 namco_c355spr_device::position_r(offs_t offset) { return m_position[offset]; @@ -331,49 +430,248 @@ u16 namco_c355spr_device::position_r(offs_t offset) /**************************************************************************************************************/ -/** - * 0x00000 sprite attr (page0) - * 0x02000 sprite list (page0) - * - * 0x02400 window attributes - * 0x04000 format - * 0x08000 tile - * 0x10000 sprite attr (page1) - * 0x14000 sprite list (page1) - */ -void namco_c355spr_device::get_single_sprite(const u16 *pSource, c355_sprite *sprite_ptr) +template +void namco_c355spr_device::draw_sprites(BitmapClass &bitmap, const rectangle &cliprect, int pri) +{ + if (pri == 0) + { + if (!m_external_prifill) + { + if (m_buffer == 0) // not buffered sprites + build_sprite_list_and_render_sprites(cliprect); + } + } + copybitmap(bitmap, cliprect, pri); +} + +void namco_c355spr_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri) +{ + draw_sprites(bitmap, cliprect, pri); +} + +void namco_c355spr_device::draw(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri) +{ + draw_sprites( bitmap, cliprect, pri); +} + +void namco_c355spr_device::spriteram_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_spriteram[0][offset]); +} + +u16 namco_c355spr_device::spriteram_r(offs_t offset) +{ + return m_spriteram[0][offset]; +} + +WRITE_LINE_MEMBER(namco_c355spr_device::vblank) +{ + if (state) + { + if (m_buffer > 0) + build_sprite_list_and_render_sprites(screen().visible_area()); + + if (m_buffer > 1) + std::copy_n(m_spriteram[0].get(), 0x20000/2, m_spriteram[1].get()); + } +} + +/******************************************************************************/ + +u16 namco_c355spr_device::read_spriteformat(int entry, u8 attr) { u16 *spriteram16 = &m_spriteram[std::max(0, m_buffer - 1)][0]; - const u16 *spriteformat16 = &spriteram16[0x4000 / 2]; - const u16 *spritetile16 = &spriteram16[0x8000 / 2]; - rectangle clip; + const u16 *spriteformat = &spriteram16[0x4000 / 2]; + return spriteformat[(entry << 2) + attr]; +} + +u16 namco_c355spr_device::read_spritetile(int entry) +{ + u16 *spriteram16 = &m_spriteram[std::max(0, m_buffer - 1)][0]; + const u16 *spritetile = &spriteram16[0x8000 / 2]; + return spritetile[entry]; +} + +u16 namco_c355spr_device::read_spritetable(int entry, u8 attr, int whichlist) +{ + u16 *ram; + int buffer = std::max(0, m_buffer - 1); + if (whichlist == 0) + ram = &m_spriteram[buffer][0x00000 / 2]; + else + ram = &m_spriteram[buffer][0x10000 / 2]; + + return ram[(entry << 3) + attr]; +} + +u16 namco_c355spr_device::read_cliptable(int entry, u8 attr) +{ + u16 *spriteram16 = &m_spriteram[std::max(0, m_buffer - 1)][0]; + const u16 *ram = &spriteram16[0x2400 / 2]; + return ram[(entry << 2) + attr]; +} + +u16 namco_c355spr_device::read_spritelist(int entry, int whichlist) +{ + u16 *ram; + int buffer = std::max(0, m_buffer - 1); + if (whichlist == 0) + ram = &m_spriteram[buffer][0x02000 / 2]; + else + ram = &m_spriteram[buffer][0x14000 / 2]; + + return ram[entry]; +} + +int namco_c355spr_device::default_code2tile(int code) +{ + return code; +} + +void namco_c355spr_device::build_sprite_list(int no) +{ + /* draw the sprites */ + c355_sprite *sprite_ptr = m_spritelist[no].get(); + for (int i = 0; i < 256; i++) + { + sprite_ptr->disable = false; + const u16 which = m_read_spritelist(i, no); + get_single_sprite(which & 0xff, sprite_ptr, no); + sprite_ptr++; + if (which & 0x100) break; + } + m_sprite_end[no] = sprite_ptr; +} + +void namco_c355spr_device::build_sprite_list_and_render_sprites(const rectangle cliprect) +{ + if (m_draw_2_lists) + build_sprite_list(0); + + build_sprite_list(1); + + render_sprites(cliprect, nullptr, m_renderbitmap, 0); +} + +template +void namco_c355spr_device::render_sprites(const rectangle cliprect, bitmap_ind8 *pri_bitmap, BitmapClass &temp_bitmap, int alt_precision) +{ + temp_bitmap.fill(0xffff, cliprect); + for (int no = 0; no < 2; no++) + { + int i = 0; + c355_sprite *sprite_ptr = m_spritelist[no].get(); + + while (sprite_ptr != m_sprite_end[no]) + { + if (sprite_ptr->disable == false) + { + rectangle clip = sprite_ptr->clip; + clip &= cliprect; + for (int ind = 0; ind < sprite_ptr->size; ind++) + { + if ((sprite_ptr->tile[ind] & 0x8000) == 0) + { + int sprite_screen_height; + int sprite_screen_width; + + if (alt_precision) + { + sprite_screen_width = ((sprite_ptr->x[ind] + (sprite_ptr->zoomx[ind] << 4)) >> 16) - (sprite_ptr->x[ind] >> 16); + sprite_screen_height = ((sprite_ptr->y[ind] + (sprite_ptr->zoomy[ind] << 4)) >> 16) - (sprite_ptr->y[ind] >> 16); + } + else + { + sprite_screen_height = (sprite_ptr->zoomy[ind] * 16 + 0x8000) >> 16; + sprite_screen_width = (sprite_ptr->zoomx[ind] * 16 + 0x8000) >> 16; + } + + zdrawgfxzoom( + &temp_bitmap, + clip, + gfx(0), + m_code2tile(sprite_ptr->tile[ind]) + sprite_ptr->offset, + sprite_ptr->color, + sprite_ptr->flipx, sprite_ptr->flipy, + sprite_ptr->x[ind] >> 16, sprite_ptr->y[ind] >> 16, + sprite_ptr->zoomx[ind], sprite_ptr->zoomy[ind], sprite_ptr->pri, + nullptr, + sprite_screen_width, sprite_screen_height, + pri_bitmap); + } + } + } + i++; + sprite_ptr++; + } + } +} + +void namco_c355spr_device::copybitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap) +{ + for (int y = cliprect.top(); y <= cliprect.bottom(); y++) + { + u32 const *const src = &temp_bitmap.pix(y); + u32 *const dst = &bitmap.pix(y); + + for (int x = cliprect.left(); x <= cliprect.right(); x++) + { + u32 const srcpix = src[x]; + + if ((srcpix & 0xff000000) == 0xff000000) + { + dst[x] = srcpix & 0x00ffffff; + } + } + } +} + +void namco_c355spr_device::draw_dg(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap) +{ + build_sprite_list(0); + + render_sprites(cliprect, &pri_bitmap, temp_bitmap, 1); + + copybitmap(screen, bitmap, cliprect, pri_bitmap, temp_bitmap); +} + +void namco_c355spr_device::get_single_sprite(u16 which, c355_sprite *sprite_ptr, int no) +{ /** * ----xxxx-------- window select * --------xxxx---- priority * ------------xxxx palette select */ - const u16 palette = pSource[6]; - sprite_ptr->pri = ((palette >> 4) & 0xf); - - const u16 linkno = pSource[0] & 0x7ff; /* LINKNO 0x000..0x7ff for format table entries - finalapr code masks with 0x3ff, but vshoot requires 0x7ff */ - sprite_ptr->offset = pSource[1]; /* OFFSET */ - int hpos = pSource[2]; /* HPOS 0x000..0x7ff (signed) */ - int vpos = pSource[3]; /* VPOS 0x000..0x7ff (signed) */ - u16 hsize = pSource[4]; /* HSIZE max 0x3ff pixels */ - u16 vsize = pSource[5]; /* VSIZE max 0x3ff pixels */ - /* pSource[6] contains priority/palette */ - /* pSource[7] is used in Lucky & Wild, possibly for sprite-road priority */ + const u16 palette = m_read_spritetable(which, 6, no); + + int priority = m_pri_cb(palette); + + if (priority == -1) + { + sprite_ptr->disable = true; + return; + } + + sprite_ptr->pri = priority; + + const u16 spriteformatram_offset = m_read_spritetable(which, 0, no) & 0x7ff; /* LINKNO 0x000..0x7ff for format table entries - finalapr code masks with 0x3ff, but vshoot requires 0x7ff */ + sprite_ptr->offset = m_read_spritetable(which, 1, no); /* OFFSET */ + int hpos = m_read_spritetable(which, 2, no); /* HPOS 0x000..0x7ff (signed) */ + int vpos = m_read_spritetable(which, 3, no); /* VPOS 0x000..0x7ff (signed) */ + u16 hsize = m_read_spritetable(which, 4, no); /* HSIZE max 0x3ff pixels */ + u16 vsize = m_read_spritetable(which, 5, no); /* VSIZE max 0x3ff pixels */ + /* m_read_spritetable(which, 6, no) contains priority/palette */ + /* m_read_spritetable(which, 7, no) is used in Lucky & Wild, possibly for sprite-road priority */ int xscroll = (s16)m_position[1]; int yscroll = (s16)m_position[0]; -// xscroll &= 0x3ff; if (xscroll & 0x200) xscroll |= ~0x3ff; xscroll &= 0x1ff; if (xscroll & 0x100) xscroll |= ~0x1ff; yscroll &= 0x1ff; if (yscroll & 0x100) yscroll |= ~0x1ff; if (screen().height() > 384) - { /* Medium Resolution: System21 adjust */ + { /* Medium Resolution: system21 adjust */ xscroll = (s16)m_position[1]; xscroll &= 0x3ff; if (xscroll & 0x200) xscroll |= ~0x3ff; if (yscroll < 0) @@ -390,36 +688,41 @@ void namco_c355spr_device::get_single_sprite(const u16 *pSource, c355_sprite *sp hpos -= xscroll; vpos -= yscroll; - const u16 *pWinAttr = &spriteram16[0x2400 / 2 + ((palette >> 8) & 0xf) * 4]; - clip.set(pWinAttr[0] - xscroll, pWinAttr[1] - xscroll, pWinAttr[2] - yscroll, pWinAttr[3] - yscroll); + + int clipentry = (palette >> 8) & 0xf; + rectangle clip; + clip.set(m_read_cliptable(clipentry, 0) - xscroll, m_read_cliptable(clipentry, 1) - xscroll, m_read_cliptable(clipentry, 2) - yscroll, m_read_cliptable(clipentry, 3) - yscroll); sprite_ptr->clip = clip; + hpos &= 0x7ff; if (hpos & 0x400) hpos |= ~0x7ff; /* sign extend */ vpos &= 0x7ff; if (vpos & 0x400) vpos |= ~0x7ff; /* sign extend */ - int tile_index = spriteformat16[linkno * 4 + 0]; - const u16 format = spriteformat16[linkno * 4 + 1]; - int dx = spriteformat16[linkno * 4 + 2]; // should this also be masked and have a sign bit like dy? - const int dy = spriteformat16[linkno * 4 + 3] & 0x1ff; + int tile_index = m_read_spriteformat(spriteformatram_offset, 0); + const u16 format = m_read_spriteformat(spriteformatram_offset, 1); + const int dx = m_read_spriteformat(spriteformatram_offset, 2) & 0x1ff; + const int dy = m_read_spriteformat(spriteformatram_offset, 3) & 0x1ff; int num_cols = (format >> 4) & 0xf; int num_rows = (format) & 0xf; if (num_cols == 0) num_cols = 0x10; const bool flipx = (hsize & 0x8000); - hsize &= 0x3ff;//0x1ff; + hsize &= 0x3ff; if (hsize == 0) { sprite_ptr->disable = true; return; } u32 zoomx = (hsize << 16) / (num_cols * 16); - dx = (dx * zoomx + 0x8000) >> 16; - if (flipx) + s32 dx_zoomed = ((dx & 0xff) * zoomx + 0x8000) >> 16; + if (dx & 0x100) dx_zoomed = -dx_zoomed; + + if (!flipx) { - hpos += dx; + hpos -= dx_zoomed; } else { - hpos -= dx; + hpos += dx_zoomed; } if (num_rows == 0) num_rows = 0x10; @@ -446,11 +749,11 @@ void namco_c355spr_device::get_single_sprite(const u16 *pSource, c355_sprite *sp sprite_ptr->flipx = flipx; sprite_ptr->flipy = flipy; sprite_ptr->size = num_rows * num_cols; - sprite_ptr->color = (palette & 0xf) ^ m_palxor; + sprite_ptr->color = (palette & (m_colors-1)) ^ m_palxor; u32 source_height_remaining = num_rows * 16; u32 screen_height_remaining = vsize; - int sy = vpos; + int y = vpos; int ind = 0; for (int row = 0; row < num_rows; row++) { @@ -458,31 +761,31 @@ void namco_c355spr_device::get_single_sprite(const u16 *pSource, c355_sprite *sp zoomy = (screen_height_remaining << 16) / source_height_remaining; if (flipy) { - sy -= tile_screen_height; + y -= tile_screen_height; } u32 source_width_remaining = num_cols * 16; u32 screen_width_remaining = hsize; - int sx = hpos; + int x = hpos; for (int col = 0; col < num_cols; col++) { int tile_screen_width = 16 * screen_width_remaining / source_width_remaining; zoomx = (screen_width_remaining << 16) / source_width_remaining; if (flipx) { - sx -= tile_screen_width; + x -= tile_screen_width; } - const u16 tile = spritetile16[tile_index++]; + const u16 tile = m_read_spritetile(tile_index++); sprite_ptr->tile[ind] = tile; if ((tile & 0x8000) == 0) { - sprite_ptr->x[ind] = sx; - sprite_ptr->y[ind] = sy; + sprite_ptr->x[ind] = x << 16; + sprite_ptr->y[ind] = y << 16; sprite_ptr->zoomx[ind] = zoomx; sprite_ptr->zoomy[ind] = zoomy; } if (!flipx) { - sx += tile_screen_width; + x += tile_screen_width; } screen_width_remaining -= tile_screen_width; source_width_remaining -= 16; @@ -490,131 +793,10 @@ void namco_c355spr_device::get_single_sprite(const u16 *pSource, c355_sprite *sp } /* next col */ if (!flipy) { - sy += tile_screen_height; + y += tile_screen_height; } screen_height_remaining -= tile_screen_height; source_height_remaining -= 16; } /* next row */ } - -int namco_c355spr_device::default_code2tile(int code) -{ - return code; -} - -void namco_c355spr_device::get_list(int no, const u16 *pSpriteList16, const u16 *pSpriteTable) -{ - /* draw the sprites */ - c355_sprite *sprite_ptr = m_spritelist[no].get(); - for (int i = 0; i < 256; i++) - { - sprite_ptr->disable = false; - const u16 which = pSpriteList16[i]; - get_single_sprite(&pSpriteTable[(which & 0xff) * 8], sprite_ptr); - sprite_ptr++; - if (which & 0x100) break; - } - m_sprite_end[no] = sprite_ptr; -} - -void namco_c355spr_device::get_sprites(const rectangle cliprect) -{ - int buffer = std::max(0, m_buffer - 1); -// int offs = spriteram16[0x18000/2]; /* end-of-sprite-list */ - -// if (offs == 0) // boot - // TODO: solvalou service mode wants 0x14000/2 & 0x00000/2 - // drawing this is what causes the bad tile in vshoot, do any games need 2 lists at the same time or should 1 list be configurable? - get_list(0, &m_spriteram[buffer][0x02000/2], &m_spriteram[buffer][0x00000/2]); -// else - get_list(1, &m_spriteram[buffer][0x14000/2], &m_spriteram[buffer][0x10000/2]); - - copy_sprites(cliprect); -} - -void namco_c355spr_device::copy_sprites(const rectangle cliprect) -{ -// int offs = spriteram16[0x18000/2]; /* end-of-sprite-list */ - m_tempbitmap.fill(0xffff, cliprect); - for (int no = 0; no < 2; no++) - { - //if (offs == no) - { - int i = 0; - c355_sprite *sprite_ptr = m_spritelist[no].get(); - - while (sprite_ptr != m_sprite_end[no]) - { - if (sprite_ptr->disable == false) - { - rectangle clip = sprite_ptr->clip; - clip &= cliprect; - for (int ind = 0; ind < sprite_ptr->size; ind++) - { - if ((sprite_ptr->tile[ind] & 0x8000) == 0) - { - zdrawgfxzoom( - m_tempbitmap, - clip, - gfx(0), - m_code2tile(sprite_ptr->tile[ind]) + sprite_ptr->offset, - sprite_ptr->color, - sprite_ptr->flipx, sprite_ptr->flipy, - sprite_ptr->x[ind], sprite_ptr->y[ind], - sprite_ptr->zoomx[ind], sprite_ptr->zoomy[ind], sprite_ptr->pri); - } - } - } - i++; - sprite_ptr++; - } - } - } -} - -template -void namco_c355spr_device::draw_sprites(screen_device &screen, BitmapClass &bitmap, const rectangle &cliprect, int pri) -{ - if (pri == 0) - { - if (!m_external_prifill) - { - if (m_buffer == 0) // not buffered sprites - get_sprites(cliprect); - } - } - copybitmap(bitmap, cliprect, pri); -} - -void namco_c355spr_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri) -{ - draw_sprites(screen, bitmap, cliprect, pri); -} - -void namco_c355spr_device::draw(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri) -{ - draw_sprites(screen, bitmap, cliprect, pri); -} - -void namco_c355spr_device::spriteram_w(offs_t offset, u16 data, u16 mem_mask) -{ - COMBINE_DATA(&m_spriteram[0][offset]); -} - -u16 namco_c355spr_device::spriteram_r(offs_t offset) -{ - return m_spriteram[0][offset]; -} - -WRITE_LINE_MEMBER(namco_c355spr_device::vblank) -{ - if (state) - { - if (m_buffer > 0) - get_sprites(screen().visible_area()); - - if (m_buffer > 1) - std::copy_n(m_spriteram[0].get(), 0x20000/2, m_spriteram[1].get()); - } -} diff --git a/src/mame/video/namco_c355spr.h b/src/mame/video/namco_c355spr.h index 3e55eacd3b7..3b72b16bfa6 100644 --- a/src/mame/video/namco_c355spr.h +++ b/src/mame/video/namco_c355spr.h @@ -20,6 +20,20 @@ public: void set_palxor(int palxor) { m_palxor = palxor; } void set_buffer(int buffer) { m_buffer = buffer; } void set_external_prifill(bool external) { m_external_prifill = external; } + void set_colors(int colors) { m_colors = colors; } + void set_granularity(int granularity) { m_granularity = granularity; } + void set_draw_2_lists(bool draw_2_lists) { m_draw_2_lists = draw_2_lists; } + + // the Namco code currently requires us to allocate memory in the device, the Data East hookup uses access callbacks + void set_device_allocates_spriteram_and_bitmaps(bool allocate_memory) { m_device_allocates_spriteram_and_bitmaps = allocate_memory; } + + + template void set_priority_callback(T &&... args) { m_pri_cb.set(std::forward(args)...); } + template void set_read_spritetile(T &&... args) { m_read_spritetile.set(std::forward(args)...); } + template void set_read_spriteformat(T &&... args) { m_read_spriteformat.set(std::forward(args)...); } + template void set_read_spritetable(T &&... args) { m_read_spritetable.set(std::forward(args)...); } + template void set_read_cliptable(T &&... args) { m_read_cliptable.set(std::forward(args)...); } + template void set_read_spritelist(T &&... args) { m_read_spritelist.set(std::forward(args)...); } u16 spriteram_r(offs_t offset); void spriteram_w(offs_t offset, u16 data, u16 mem_mask = ~0); @@ -28,6 +42,12 @@ public: DECLARE_WRITE_LINE_MEMBER(vblank); typedef delegate c355_obj_code2tile_delegate; + typedef device_delegate c355_obj_entry_attr_delegate; + typedef device_delegate c355_obj_entry_attr_which_delegate; + typedef device_delegate c355_obj_entry_delegate; + typedef device_delegate c355_obj_entry_which_delegate; + typedef device_delegate c355_priority_delegate; + void set_tile_callback(c355_obj_code2tile_delegate cb) { if (!cb.isnull()) @@ -36,21 +56,56 @@ public: m_code2tile = c355_obj_code2tile_delegate(&namco_c355spr_device::default_code2tile, this); } + void draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri); void draw(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri); - void get_sprites(const rectangle cliprect); - void copy_sprites(const rectangle cliprect); + + void draw_dg(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap); + + void build_sprite_list_and_render_sprites(const rectangle cliprect); + + template + void render_sprites(const rectangle cliprect, bitmap_ind8 *pri_bitmap, BitmapClass &temp_bitmap, int alt_precision); void clear_screen_bitmap() { m_screenbitmap.fill(0xffff); } void clear_screen_bitmap(const rectangle cliprect) { m_screenbitmap.fill(0xffff, cliprect); } bitmap_ind16 &screen_bitmap() { return m_screenbitmap; } protected: + namco_c355spr_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); + // device-level overrides virtual void device_start() override; virtual void device_stop() override; -private: + c355_obj_code2tile_delegate m_code2tile; + c355_priority_delegate m_pri_cb; + c355_obj_entry_delegate m_read_spritetile; + c355_obj_entry_attr_delegate m_read_spriteformat; + c355_obj_entry_attr_which_delegate m_read_spritetable; + c355_obj_entry_attr_delegate m_read_cliptable; + c355_obj_entry_which_delegate m_read_spritelist; + + u16 read_spritetile(int entry); + u16 read_spriteformat(int entry, u8 attr); + u16 read_spritetable(int entry, u8 attr, int whichlist); + u16 read_cliptable(int entry, u8 attr); + u16 read_spritelist(int entry, int whichlist); + + int default_priority(int pal_pri) { return ((pal_pri >> 4) & 0xf); } + + // general + template + void zdrawgfxzoom( + BitmapClass *dest_bmp, const rectangle &clip, gfx_element *gfx, + u32 code, u32 color, + bool flipx, bool flipy, + int sx, int sy, + int scalex, int scaley, + u8 prival, + bitmap_ind8 *pri_buffer, + int sprite_screen_width, int sprite_screen_height, + bitmap_ind8 *pri_bitmap); struct c355_sprite { @@ -66,29 +121,31 @@ private: int pri; }; - // general - void zdrawgfxzoom(bitmap_ind16 &dest_bmp, const rectangle &clip, gfx_element *gfx, u32 code, u32 color, bool flipx, bool flipy, int sx, int sy, int scalex, int scaley, u8 prival); + std::unique_ptr m_spritelist[2]; + const c355_sprite *m_sprite_end[2]; + int m_palxor; + u16 m_position[4]; + std::unique_ptr m_spriteram[2]; + bitmap_ind16 m_renderbitmap; + bitmap_ind16 m_screenbitmap; + + void build_sprite_list(int no); + +private: void copybitmap(bitmap_ind16 &dest_bmp, const rectangle &clip, u8 pri); void copybitmap(bitmap_rgb32 &dest_bmp, const rectangle &clip, u8 pri); + void copybitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap); + // C355 Motion Object Emulation // for pal_xor, supply either 0x0 (normal) or 0xf (palette mapping reversed) int default_code2tile(int code); // C355 Motion Object internals - void get_single_sprite(const u16 *pSource, c355_sprite *sprite_ptr); - void get_list(int no, const u16 *pSpriteList16, const u16 *pSpriteTable); - template void draw_sprites(screen_device &screen, BitmapClass &bitmap, const rectangle &cliprect, int pri); + void get_single_sprite(u16 which, c355_sprite *sprite_ptr, int no); + template void draw_sprites(BitmapClass &bitmap, const rectangle &cliprect, int pri); - std::unique_ptr m_spritelist[2]; - const c355_sprite *m_sprite_end[2]; - c355_obj_code2tile_delegate m_code2tile; - int m_palxor; - u16 m_position[4]; - std::unique_ptr m_spriteram[2]; - bitmap_ind16 m_tempbitmap; - bitmap_ind16 m_screenbitmap; int m_scrolloffs[2]; //u32 m_ramsize; @@ -97,6 +154,10 @@ private: required_memory_region m_gfx_region; u16 m_colbase; + int m_colors; + int m_granularity; + bool m_draw_2_lists; + bool m_device_allocates_spriteram_and_bitmaps; }; // device type definition -- cgit v1.2.3