From 1f4f1c4a30941dee2cb9b45bddd03055dd88ae8e Mon Sep 17 00:00:00 2001 From: David Haywood Date: Thu, 22 Nov 2018 01:54:50 +0000 Subject: World Rally / Blomby Car improvements (shadow / headlight in Blomby Car) (#4318) * experimental code (nw) * better code, fix issues (nw) * works for both games (nw) * refactor (nw) * this seems to match reference material (nw) --- scripts/target/mame/arcade.lua | 8 +- src/mame/drivers/blmbycar.cpp | 13 +- src/mame/drivers/wrally.cpp | 5 + src/mame/includes/blmbycar.h | 5 +- src/mame/includes/wrally.h | 9 +- src/mame/machine/wrally.cpp | 2 +- src/mame/video/blmbycar.cpp | 110 ++------------ src/mame/video/gaelco_wrally_sprites.cpp | 243 +++++++++++++++++++++++++++++++ src/mame/video/gaelco_wrally_sprites.h | 48 ++++++ src/mame/video/wrally.cpp | 137 +++-------------- 10 files changed, 350 insertions(+), 230 deletions(-) create mode 100644 src/mame/video/gaelco_wrally_sprites.cpp create mode 100644 src/mame/video/gaelco_wrally_sprites.h diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 9773c6c9f8c..2c2dca39817 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -1311,9 +1311,6 @@ files { createMAMEProjects(_target, _subtarget, "atlus") files { - MAME_DIR .. "src/mame/drivers/blmbycar.cpp", - MAME_DIR .. "src/mame/includes/blmbycar.h", - MAME_DIR .. "src/mame/video/blmbycar.cpp", MAME_DIR .. "src/mame/drivers/ohmygod.cpp", MAME_DIR .. "src/mame/includes/ohmygod.h", MAME_DIR .. "src/mame/video/ohmygod.cpp", @@ -1913,6 +1910,11 @@ files { MAME_DIR .. "src/mame/includes/wrally.h", MAME_DIR .. "src/mame/machine/wrally.cpp", MAME_DIR .. "src/mame/video/wrally.cpp", + MAME_DIR .. "src/mame/drivers/blmbycar.cpp", + MAME_DIR .. "src/mame/includes/blmbycar.h", + MAME_DIR .. "src/mame/video/blmbycar.cpp", + MAME_DIR .. "src/mame/video/gaelco_wrally_sprites.cpp", + MAME_DIR .. "src/mame/video/gaelco_wrally_sprites.h", MAME_DIR .. "src/mame/drivers/xorworld.cpp", MAME_DIR .. "src/mame/includes/xorworld.h", MAME_DIR .. "src/mame/video/xorworld.cpp", diff --git a/src/mame/drivers/blmbycar.cpp b/src/mame/drivers/blmbycar.cpp index 4cf229df310..1d5ae8648ec 100644 --- a/src/mame/drivers/blmbycar.cpp +++ b/src/mame/drivers/blmbycar.cpp @@ -120,8 +120,7 @@ void blmbycar_state::common_map(address_map &map) map(0x108000, 0x10bfff).writeonly(); // ??? map(0x10c000, 0x10c003).writeonly().share("scroll_1"); // Scroll 1 map(0x10c004, 0x10c007).writeonly().share("scroll_0"); // Scroll 0 - map(0x200000, 0x2005ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette").mirror(0x4000); // Palette - map(0x200600, 0x203fff).ram().mirror(0x4000); + map(0x200000, 0x203fff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette").mirror(0x4000); // Palette map(0x440000, 0x441fff).ram(); map(0x444000, 0x445fff).writeonly().share("spriteram");// Sprites (size?) map(0x700000, 0x700001).portr("DSW"); @@ -189,7 +188,7 @@ static INPUT_PORTS_START( blmbycar ) PORT_DIPSETTING( 0x0018, DEF_STR( Joystick ) ) PORT_DIPSETTING( 0x0010, "Pot Wheel" ) // Preliminary PORT_DIPSETTING( 0x0008, "Opt Wheel" ) // Preliminary -// PORT_DIPSETTING( 0x0000, DEF_STR( Unused ) ) // Time goes to 0 rally fast! + PORT_DIPSETTING( 0x0000, "invalid, breaks game" ) // Time goes to 0 rally fast! PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:3") PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) @@ -337,7 +336,7 @@ static const gfx_layout layout_16x16x4 = /* Layers both use the first $20 color codes. Sprites the next $10 */ static GFXDECODE_START( gfx_blmbycar ) - GFXDECODE_ENTRY( "sprites", 0, layout_16x16x4, 0x0, 0x30 ) // [0] Layers + Sprites + GFXDECODE_ENTRY( "sprites", 0, layout_16x16x4, 0x0, 64*8 ) // [0] Layers + Sprites GFXDECODE_END @@ -386,9 +385,13 @@ MACHINE_CONFIG_START(blmbycar_state::blmbycar) MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_blmbycar) - MCFG_PALETTE_ADD("palette", 0x300) + MCFG_PALETTE_ADD("palette", 0x2000) MCFG_PALETTE_FORMAT(xxxxBBBBRRRRGGGG) + BLMBYCAR_SPRITES(config, m_sprites, 0); + m_sprites->set_gfxdecode_tag("gfxdecode"); + m_sprites->set_screen_tag("screen"); + /* sound hardware */ SPEAKER(config, "mono").front_center(); diff --git a/src/mame/drivers/wrally.cpp b/src/mame/drivers/wrally.cpp index 5d9f0b2c825..a0322621d0b 100644 --- a/src/mame/drivers/wrally.cpp +++ b/src/mame/drivers/wrally.cpp @@ -187,6 +187,7 @@ static INPUT_PORTS_START( wrally ) PORT_DIPSETTING( 0x0018, DEF_STR( Joystick ) ) PORT_DIPSETTING( 0x0010, "Pot Wheel" ) PORT_DIPSETTING( 0x0000, "Optical Wheel" ) + PORT_DIPSETTING( 0x0008, "invalid" ) PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:3") PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) @@ -285,6 +286,10 @@ MACHINE_CONFIG_START(wrally_state::wrally) MCFG_PALETTE_ADD("palette", 1024*8) MCFG_PALETTE_FORMAT(xxxxBBBBRRRRGGGG) + GAELCO_WRALLY_SPRITES(config, m_sprites, 0); + m_sprites->set_gfxdecode_tag("gfxdecode"); + m_sprites->set_screen_tag("screen"); + LS259(config, m_outlatch); m_outlatch->q_out_cb<0>().set(FUNC(wrally_state::coin1_lockout_w)); m_outlatch->q_out_cb<1>().set(FUNC(wrally_state::coin2_lockout_w)); diff --git a/src/mame/includes/blmbycar.h b/src/mame/includes/blmbycar.h index 9734673753c..43ab525d0bd 100644 --- a/src/mame/includes/blmbycar.h +++ b/src/mame/includes/blmbycar.h @@ -7,6 +7,7 @@ ***************************************************************************/ #include "emupal.h" +#include "video/gaelco_wrally_sprites.h" class blmbycar_state : public driver_device { @@ -16,6 +17,7 @@ public: m_maincpu(*this, "maincpu"), m_gfxdecode(*this, "gfxdecode"), m_palette(*this, "palette"), + m_sprites(*this, "sprites"), m_vram(*this, "vram_%u", 0U), m_scroll(*this, "scroll_%u", 0U), m_spriteram(*this, "spriteram"), @@ -35,7 +37,8 @@ private: required_device m_maincpu; required_device m_gfxdecode; required_device m_palette; - + required_device m_sprites; + /* memory pointers */ required_shared_ptr_array m_vram; required_shared_ptr_array m_scroll; diff --git a/src/mame/includes/wrally.h b/src/mame/includes/wrally.h index 86f49940d3b..d9e04714e8c 100644 --- a/src/mame/includes/wrally.h +++ b/src/mame/includes/wrally.h @@ -7,6 +7,7 @@ #include "machine/74259.h" #include "emupal.h" +#include "video/gaelco_wrally_sprites.h" class wrally_state : public driver_device { @@ -17,12 +18,13 @@ public: m_outlatch(*this, "outlatch"), m_gfxdecode(*this, "gfxdecode"), m_palette(*this, "palette"), + m_sprites(*this, "sprites"), m_okibank(*this, "okibank"), m_videoram(*this, "videoram"), m_vregs(*this, "vregs"), m_spriteram(*this, "spriteram"), m_shareram(*this, "shareram"), - m_pant{ nullptr, nullptr } + m_tilemap{ nullptr, nullptr } { } @@ -49,12 +51,11 @@ private: void oki_map(address_map &map); void wrally_map(address_map &map); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority); - required_device m_maincpu; required_device m_outlatch; required_device m_gfxdecode; required_device m_palette; + required_device m_sprites; required_memory_bank m_okibank; required_shared_ptr m_videoram; @@ -62,7 +63,7 @@ private: required_shared_ptr m_spriteram; required_shared_ptr m_shareram; - tilemap_t *m_pant[2]; + tilemap_t *m_tilemap[2]; }; #endif // MAME_INCLUDES_WRALLY_H diff --git a/src/mame/machine/wrally.cpp b/src/mame/machine/wrally.cpp index 8e0e273f15e..7721b6cbe31 100644 --- a/src/mame/machine/wrally.cpp +++ b/src/mame/machine/wrally.cpp @@ -43,7 +43,7 @@ WRITE16_MEMBER(wrally_state::vram_w) data = gaelco_decrypt(space, offset, data, 0x1f, 0x522a); COMBINE_DATA(&m_videoram[offset]); - m_pant[(offset & 0x1fff) >> 12]->mark_tile_dirty(((offset << 1) & 0x1fff) >> 2); + m_tilemap[(offset & 0x1fff) >> 12]->mark_tile_dirty(((offset << 1) & 0x1fff) >> 2); } WRITE_LINE_MEMBER(wrally_state::flipscreen_w) diff --git a/src/mame/video/blmbycar.cpp b/src/mame/video/blmbycar.cpp index 68a9a38a649..d6bcb3f8e29 100644 --- a/src/mame/video/blmbycar.cpp +++ b/src/mame/video/blmbycar.cpp @@ -79,87 +79,9 @@ void blmbycar_state::video_start() { m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(blmbycar_state::get_tile_info<0>),this), TILEMAP_SCAN_ROWS, 16, 16, DIM_NX, DIM_NY ); m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(blmbycar_state::get_tile_info<1>),this), TILEMAP_SCAN_ROWS, 16, 16, DIM_NX, DIM_NY ); - - m_tilemap[0]->set_scroll_rows(1); - m_tilemap[0]->set_scroll_cols(1); - - m_tilemap[1]->set_scroll_rows(1); - m_tilemap[1]->set_scroll_cols(1); m_tilemap[1]->set_transparent_pen(0); } - -/*************************************************************************** - - - Sprites Drawing - - Offset: Bits: Value: - - 0.w f--- ---- ---- ---- End Of Sprites - -edc ba9- ---- ---- - ---- ---8 7654 3210 Y (Signed) - - 2.w Code - - 4.w f--- ---- ---- ---- Flip Y - -e-- ---- ---- ---- Flip X - --dc ba98 7654 ---- - ---- ---- ---- 3210 Color (Bit 3 = Priority) - - 6.w f--- ---- ---- ---- ? Is this ever used ? - -e-- ---- ---- ---- ? 1 = Don't Draw ? - --dc ba9- ---- ---- - ---- ---8 7654 3210 X (Signed) - - -***************************************************************************/ - -void blmbycar_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect ) -{ - uint16_t *source, *finish; - - source = m_spriteram + 0x6 / 2; // ! - finish = m_spriteram + m_spriteram.bytes() / 2 - 8 / 2; - - /* Find "the end of sprites" marker */ - - for ( ; source < finish; source += 8 / 2 ) - if (source[0] & 0x8000) break; - - /* Draw sprites in reverse order for pdrawfgfx */ - - source -= 8 / 2; - finish = m_spriteram; - - for ( ; source >= finish; source -= 8 / 2 ) - { - int y = source[0]; - int code = source[1]; - int attr = source[2]; - int x = source[3]; - - int flipx = attr & 0x4000; - int flipy = attr & 0x8000; - int pri = (~attr >> 3) & 0x1; // Priority (1 = Low) - int pri_mask = ~((1 << (pri+1)) - 1); // Above the first "pri" levels - - if (x & 0x4000) continue; // ? To get rid of the "shadow" blocks - - x = (x & 0x1ff) - 0x10; - y = 0xf0 - ((y & 0xff) - (y & 0x100)); - - m_gfxdecode->gfx(0)->prio_transpen(bitmap,cliprect, - code, - 0x20 + (attr & 0xf), - flipx, flipy, - x, y, - screen.priority(), - pri_mask,0); - } -} - - /*************************************************************************** @@ -170,7 +92,7 @@ void blmbycar_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, uint32_t blmbycar_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - int i, layers_ctrl = -1; + m_sprites->draw_sprites(cliprect,m_spriteram,flip_screen()); m_tilemap[0]->set_scrolly(0, m_scroll[0][0]); m_tilemap[0]->set_scrollx(0, m_scroll[0][1]); @@ -178,33 +100,19 @@ uint32_t blmbycar_state::screen_update(screen_device &screen, bitmap_ind16 &bitm m_tilemap[1]->set_scrolly(0, m_scroll[1][0] + 1); m_tilemap[1]->set_scrollx(0, m_scroll[1][1] + 5); -#ifdef MAME_DEBUG -if (machine().input().code_pressed(KEYCODE_Z)) -{ - int msk = 0; + screen.priority().fill(0, cliprect); - if (machine().input().code_pressed(KEYCODE_Q)) msk |= 1; - if (machine().input().code_pressed(KEYCODE_W)) msk |= 2; -// if (machine().input().code_pressed(KEYCODE_E)) msk |= 4; - if (machine().input().code_pressed(KEYCODE_A)) msk |= 8; - if (msk != 0) layers_ctrl &= msk; -} -#endif + bitmap.fill(0, cliprect); - screen.priority().fill(0, cliprect); + m_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0); + m_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0); - if (layers_ctrl & 1) - for (i = 0; i <= 1; i++) - m_tilemap[0]->draw(screen, bitmap, cliprect, i, i); - else - bitmap.fill(0, cliprect); + m_sprites->mix_sprites(bitmap, cliprect, 0); - if (layers_ctrl & 2) - for (i = 0; i <= 1; i++) - m_tilemap[1]->draw(screen, bitmap, cliprect, i, i); + m_tilemap[0]->draw(screen, bitmap, cliprect, 1, 1); + m_tilemap[1]->draw(screen, bitmap, cliprect, 1, 1); - if (layers_ctrl & 8) - draw_sprites(screen, bitmap, cliprect); + m_sprites->mix_sprites(bitmap, cliprect, 1); return 0; } diff --git a/src/mame/video/gaelco_wrally_sprites.cpp b/src/mame/video/gaelco_wrally_sprites.cpp new file mode 100644 index 00000000000..6ce719939c9 --- /dev/null +++ b/src/mame/video/gaelco_wrally_sprites.cpp @@ -0,0 +1,243 @@ +// license:BSD-3-Clause +// copyright-holders:Manuel Abadia, Mike Coates, Nicola Salmoria, Miguel Angel Horna, Luca Elia, David Haywood + +#include "emu.h" +#include "gaelco_wrally_sprites.h" + +DEFINE_DEVICE_TYPE(GAELCO_WRALLY_SPRITES, gaelco_wrally_sprites_device, "gaelco_wrally_sprites", "Gaelco World Rally Sprites") +DEFINE_DEVICE_TYPE(BLMBYCAR_SPRITES, blmbycar_sprites_device, "blmbycar_sprites", "Blomby Car Sprites") + +gaelco_wrally_sprites_device::gaelco_wrally_sprites_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , m_gfxdecode(*this, finder_base::DUMMY_TAG) + , m_screen(*this, finder_base::DUMMY_TAG) +{ +} + +gaelco_wrally_sprites_device::gaelco_wrally_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : gaelco_wrally_sprites_device(mconfig, GAELCO_WRALLY_SPRITES, tag, owner, clock) +{ +} + +void gaelco_wrally_sprites_device::device_start() +{ + m_screen->register_screen_bitmap(m_temp_bitmap_sprites); +} + +void gaelco_wrally_sprites_device::device_reset() +{ +} + + +/* + Sprite Format + ------------- + + Offs | Bit(s) | Description + -----+-FEDCBA98-76543210-+-------------------------- + 0 | -------- xxxxxxxx | y position + 0 | --xxxxxx -------- | not used? + 0 | -x------ -------- | flipx + 0 | x------- -------- | flipy + + 1 | xxxxxxxx xxxxxxxx | unknown + + 2 | ------xx xxxxxxxx | x position + 2 | --xxxx-- -------- | sprite color (low 4 bits) + 2 | -x------ -------- | shadows/highlights (see below) + 2 | x------- -------- | not used? + + 3 | --xxxxxx xxxxxxxx | sprite code + 3 | xx------ -------- | not used? + + For shadows/highlights, the tile color below the sprite will be set using a + palette (from the 8 available) based on the gfx pen of the sprite. Only pens + in the range 0x8-0xf are used. +*/ + +void gaelco_wrally_sprites_device::get_sprites_info(uint16_t* spriteram, int& sx, int& sy, int& number, int& color, int& color_effect, int& attr, int& high_priority, int &end) +{ + sx = spriteram[2] & 0x03ff; + sy = (240 - (spriteram[0] & 0x00ff)) & 0x00ff; + number = spriteram[3] & 0x3fff; + color = (spriteram[2] & 0x7c00) >> 10; + color_effect = (color & 0x10) >> 4; + attr = (spriteram[0] & 0xfe00) >> 9; + high_priority = number >= 0x3700; // HACK! this is almost certainly not how the priority is determined + end = 0; +} + +void gaelco_wrally_sprites_device::draw_sprites(const rectangle &cliprect, uint16_t* spriteram, int flip_screen) +{ + m_temp_bitmap_sprites.fill(0, cliprect); + + int i; + gfx_element *gfx = m_gfxdecode->gfx(0); + + for (i = 6 / 2; i < (0x1000 - 6) / 2; i += 4) + { + int sx, sy, number, color, attr, end, color_effect, high_priority; + + get_sprites_info(spriteram + i, sx, sy, number, color, color_effect, attr, high_priority, end); + + if (end) + break; + + int xflip = attr & 0x20; + int yflip = attr & 0x40; + color = color & 0x0f; + + if (flip_screen) + { + sy = sy + 248; + } + + // wrally adjusts sx by 0x0f, blmbycar implementation was 0x10 + const uint8_t *gfx_src = gfx->get_data(number % gfx->elements()); + + for (int py = 0; py < gfx->height(); py++) + { + /* get a pointer to the current line in the screen bitmap */ + int ypos = ((sy + py) & 0x1ff); + uint16_t *srcy = &m_temp_bitmap_sprites.pix16(ypos); + + int gfx_py = yflip ? (gfx->height() - 1 - py) : py; + + if ((ypos < cliprect.min_y) || (ypos > cliprect.max_y)) continue; + + for (int px = 0; px < gfx->width(); px++) + { + /* get current pixel */ + int xpos = (((sx + px) & 0x3ff) - 0x0f) & 0x3ff; + uint16_t *pixel = srcy + xpos; + int gfx_px = xflip ? (gfx->width() - 1 - px) : px; + + /* get asociated pen for the current sprite pixel */ + int gfx_pen = gfx_src[gfx->rowbytes()*gfx_py + gfx_px]; + + if ((xpos < cliprect.min_x) || (xpos > cliprect.max_x)) continue; + + if (!color_effect) + { + if (gfx_pen) + { + *pixel = gfx_pen | (color << 4) | (high_priority << 8); + } + } + else + { + int src_color = *pixel; + + /* pens 8..15 are used to select a palette */ + if ((gfx_pen < 8) || (gfx_pen >= 16)) continue; + + // if there's already a sprite pixel use the existing priority value? (or you get a glitch against the start line arch at the start of a night stage) possibly because existing priority scheme is bogus? + // this causes a slight shadow of your car to be visible as you pass through the arch instead, but looking at 14:01 in this video seems to show the same on a PCB https://www.youtube.com/watch?v=vZUUK8c-GZ0 + if (src_color != 0) + { + *pixel = src_color |= ((gfx_pen - 8) << 12) | 0x200; + } + else + { + /* modify the color of the tile - the pen modifier can be applied over existing sprite pixels, so we store it in the upper bits that we send to the mixer */ + *pixel = (src_color &0xff) | ((gfx_pen - 8) << 12) | (high_priority << 8) | 0x200; + } + } + } + } + } +} + +void gaelco_wrally_sprites_device::mix_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority) +{ + for (int y = cliprect.min_y; y < cliprect.max_y; y++) + { + const uint16_t* spriteptr = &m_temp_bitmap_sprites.pix16(y); + uint16_t* dstptr = &bitmap.pix16(y); + + for (int x = cliprect.min_x; x < cliprect.max_x; x++) + { + if (spriteptr[x] != 0) + { + // this is how we've packed the bits here + // ssss --ez PPPP pppp s = shadow multiplier e = shadow enabled, z = priority, P = palette select, p = pen + + const int pridat = (spriteptr[x] & 0x100) >> 8; + + if (pridat == priority) + { + const int shadow = (spriteptr[x] & 0x200) >> 9; + + if (!shadow) + { + const uint16_t pendat = (spriteptr[x] & 0xff); + dstptr[x] = pendat + 0x200; + } + else + { + const uint16_t pendat = (spriteptr[x] & 0xff); + const int shadowlevel = (spriteptr[x] & 0xf000) >> 12; + + if (pendat != 0) + { + dstptr[x] = (pendat + 0x200) + (shadowlevel * 0x400); + } + else + { + dstptr[x] = (dstptr[x]&0x3ff) + (shadowlevel * 0x400); + } + } + } + } + + } + } +} + +/*************************************************************************** + + + Sprites Drawing + + Offset: Bits: Value: + + 0 f--- ---- ---- ---- End Of Sprites + -edc ba9- ---- ---- + ---- ---8 7654 3210 Y (Signed) + + 1 Code + + 2 f--- ---- ---- ---- Flip Y + -e-- ---- ---- ---- Flip X + --dc ba98 7654 ---- + ---- ---- ---- 3210 Color (Bit 3 = Priority) + + 3 f--- ---- ---- ---- ? Is this ever used ? + -e-- ---- ---- ---- ? 1 = shadow sprite! + --dc ba9- ---- ---- + ---- ---8 7654 3210 X (Signed) + + +***************************************************************************/ + +blmbycar_sprites_device::blmbycar_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : gaelco_wrally_sprites_device(mconfig, BLMBYCAR_SPRITES, tag, owner, clock) +{ +} + +void blmbycar_sprites_device::get_sprites_info(uint16_t* spriteram, int& sx, int& sy, int& number, int& color, int& color_effect, int& attr, int& high_priority, int &end) +{ + // bytes are swapped around and color attribute is moved + sx = spriteram[3] & 0x03ff; + sy = (spriteram[0] & 0x01ff); + sy = 0xf0 - ((sy & 0xff) - (sy & 0x100)); // check if this logic works for wrally + + number = spriteram[1] & 0x3fff; + color = (spriteram[2] & 0x000f) >> 0; // note moved + color_effect = (spriteram[3] & 0x4000) >> 14; + + attr = (spriteram[2] & 0xfe00) >> 9; + end = (spriteram[0] & 0x8000); // does wrally have this too? + + high_priority = (~(color >> 3))&1; +} diff --git a/src/mame/video/gaelco_wrally_sprites.h b/src/mame/video/gaelco_wrally_sprites.h new file mode 100644 index 00000000000..19b450d8217 --- /dev/null +++ b/src/mame/video/gaelco_wrally_sprites.h @@ -0,0 +1,48 @@ +// license:BSD-3-Clause +// copyright-holders:Manuel Abadia, Mike Coates, Nicola Salmoria, Miguel Angel Horna, Luca Elia, David Haywood +#ifndef MAME_VIDEO_GAELCO_WRALLY_SPRITES_H +#define MAME_VIDEO_GAELCO_WRALLY_SPRITES_H + +#pragma once + +#include "screen.h" + +class gaelco_wrally_sprites_device : public device_t +{ +public: + gaelco_wrally_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template void set_gfxdecode_tag(T &&tag) { m_gfxdecode.set_tag(std::forward(tag)); } + template void set_screen_tag(T &&tag) { m_screen.set_tag(std::forward(tag)); } + + void draw_sprites(const rectangle &cliprect, uint16_t* spriteram, int flip_screen); + void mix_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority); + +protected: + gaelco_wrally_sprites_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + virtual void get_sprites_info(uint16_t* spriteram, int& sx, int& sy, int& number, int& color, int& color_effect, int& attr, int& high_priotiy, int &end); + +private: + required_device m_gfxdecode; + required_device m_screen; + + bitmap_ind16 m_temp_bitmap_sprites; +}; + +class blmbycar_sprites_device : public gaelco_wrally_sprites_device +{ +public: + blmbycar_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void get_sprites_info(uint16_t* spriteram, int& sx, int& sy, int& number, int& color, int& color_effect, int& attr, int& high_priotiy, int &end) override; +}; + +DECLARE_DEVICE_TYPE(GAELCO_WRALLY_SPRITES, gaelco_wrally_sprites_device) +DECLARE_DEVICE_TYPE(BLMBYCAR_SPRITES, blmbycar_sprites_device) + +#endif // MAME_VIDEO_GAELCO_WRALLY_SPRITES_H diff --git a/src/mame/video/wrally.cpp b/src/mame/video/wrally.cpp index 7f24ecb63b9..c3a96bc6fb7 100644 --- a/src/mame/video/wrally.cpp +++ b/src/mame/video/wrally.cpp @@ -56,106 +56,11 @@ TILE_GET_INFO_MEMBER(wrally_state::get_tile_info) void wrally_state::video_start() { - m_pant[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(wrally_state::get_tile_info<0>),this),TILEMAP_SCAN_ROWS,16,16,64,32); - m_pant[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(wrally_state::get_tile_info<1>),this),TILEMAP_SCAN_ROWS,16,16,64,32); + m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(wrally_state::get_tile_info<0>),this),TILEMAP_SCAN_ROWS,16,16,64,32); + m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(wrally_state::get_tile_info<1>),this),TILEMAP_SCAN_ROWS,16,16,64,32); - m_pant[0]->set_transmask(0,0xff01,0x00ff); /* this layer is split in two (pens 1..7, pens 8-15) */ - m_pant[1]->set_transparent_pen(0); -} - - -/*************************************************************************** - - Sprites - -***************************************************************************/ - -/* - Sprite Format - ------------- - - Word | Bit(s) | Description - -----+-FEDCBA98-76543210-+-------------------------- - 0 | -------- xxxxxxxx | y position - 0 | --xxxxxx -------- | not used? - 0 | -x------ -------- | flipx - 0 | x------- -------- | flipy - 1 | xxxxxxxx xxxxxxxx | unknown - 2 | ------xx xxxxxxxx | x position - 2 | --xxxx-- -------- | sprite color (low 4 bits) - 2 | -x------ -------- | shadows/highlights (see below) - 2 | x------- -------- | not used? - 3 | --xxxxxx xxxxxxxx | sprite code - 3 | xx------ -------- | not used? - - For shadows/highlights, the tile color below the sprite will be set using a - palette (from the 8 available) based on the gfx pen of the sprite. Only pens - in the range 0x8-0xf are used. -*/ - -void wrally_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority) -{ - int i, px, py; - gfx_element *gfx = m_gfxdecode->gfx(0); - - for (i = 6/2; i < (0x1000 - 6)/2; i += 4) { - int sx = m_spriteram[i+2] & 0x03ff; - int sy = (240 - (m_spriteram[i] & 0x00ff)) & 0x00ff; - int number = m_spriteram[i+3] & 0x3fff; - int color = (m_spriteram[i+2] & 0x7c00) >> 10; - int attr = (m_spriteram[i] & 0xfe00) >> 9; - - int xflip = attr & 0x20; - int yflip = attr & 0x40; - int color_effect = (color & 0x10) >> 4; - int high_priority = number >= 0x3700; - color = color & 0x0f; - - if (high_priority != priority) continue; - - if (flip_screen()) { - sy = sy + 248; - } - - if (!color_effect) { - gfx->transpen(bitmap,cliprect,number, - 0x20 + color,xflip,yflip, - sx - 0x0f,sy,0); - } else { - /* get a pointer to the current sprite's gfx data */ - const uint8_t *gfx_src = gfx->get_data(number % gfx->elements()); - - for (py = 0; py < gfx->height(); py++){ - /* get a pointer to the current line in the screen bitmap */ - int ypos = ((sy + py) & 0x1ff); - uint16_t *srcy = &bitmap.pix16(ypos); - - int gfx_py = yflip ? (gfx->height() - 1 - py) : py; - - if ((ypos < cliprect.min_y) || (ypos > cliprect.max_y)) continue; - - for (px = 0; px < gfx->width(); px++){ - /* get current pixel */ - int xpos = (((sx + px) & 0x3ff) - 0x0f) & 0x3ff; - uint16_t *pixel = srcy + xpos; - int src_color = *pixel; - - int gfx_px = xflip ? (gfx->width() - 1 - px) : px; - - /* get asociated pen for the current sprite pixel */ - int gfx_pen = gfx_src[gfx->rowbytes()*gfx_py + gfx_px]; - - /* pens 8..15 are used to select a palette */ - if ((gfx_pen < 8) || (gfx_pen >= 16)) continue; - - if ((xpos < cliprect.min_x) || (xpos > cliprect.max_x)) continue; - - /* modify the color of the tile */ - *pixel = src_color + (gfx_pen-8)*1024; - } - } - } - } + m_tilemap[0]->set_transmask(0,0xff01,0x00ff); /* this layer is split in two (pens 1..7, pens 8-15) */ + m_tilemap[1]->set_transparent_pen(0); } /*************************************************************************** @@ -166,32 +71,34 @@ void wrally_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint32_t wrally_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { + m_sprites->draw_sprites(cliprect,m_spriteram,flip_screen()); + /* set scroll registers */ if (!flip_screen()) { - m_pant[0]->set_scrolly(0, m_vregs[0]); - m_pant[0]->set_scrollx(0, m_vregs[1]+4); - m_pant[1]->set_scrolly(0, m_vregs[2]); - m_pant[1]->set_scrollx(0, m_vregs[3]); + m_tilemap[0]->set_scrolly(0, m_vregs[0]); + m_tilemap[0]->set_scrollx(0, m_vregs[1]+4); + m_tilemap[1]->set_scrolly(0, m_vregs[2]); + m_tilemap[1]->set_scrollx(0, m_vregs[3]); } else { - m_pant[0]->set_scrolly(0, 248 - m_vregs[0]); - m_pant[0]->set_scrollx(0, 1024 - m_vregs[1] - 4); - m_pant[1]->set_scrolly(0, 248 - m_vregs[2]); - m_pant[1]->set_scrollx(0, 1024 - m_vregs[3]); + m_tilemap[0]->set_scrolly(0, 248 - m_vregs[0]); + m_tilemap[0]->set_scrollx(0, 1024 - m_vregs[1] - 4); + m_tilemap[1]->set_scrolly(0, 248 - m_vregs[2]); + m_tilemap[1]->set_scrollx(0, 1024 - m_vregs[3]); } /* draw tilemaps + sprites */ - m_pant[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE,0); - m_pant[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(0) | TILEMAP_DRAW_LAYER0,0); - m_pant[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(0) | TILEMAP_DRAW_LAYER1,0); + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE,0); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(0) | TILEMAP_DRAW_LAYER0,0); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(0) | TILEMAP_DRAW_LAYER1,0); - m_pant[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(1),0); - m_pant[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(1) | TILEMAP_DRAW_LAYER0,0); + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(1),0); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(1) | TILEMAP_DRAW_LAYER0,0); - draw_sprites(bitmap,cliprect,0); + m_sprites->mix_sprites(bitmap, cliprect, 0); - m_pant[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(1) | TILEMAP_DRAW_LAYER1,0); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(1) | TILEMAP_DRAW_LAYER1,0); - draw_sprites(bitmap,cliprect,1); + m_sprites->mix_sprites(bitmap, cliprect, 1); return 0; } -- cgit v1.2.3