summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2024-04-25 21:22:53 +0200
committer angelosa <lordkale4@gmail.com>2024-04-25 21:22:53 +0200
commit3b618bd7f04b8164fbcbb1fc106502e05ee85d6a (patch)
tree92c2ecccfda548db85ffd4cbd2e7e34ac050d61f /src
parent3cd4e2e5d5c3dcfde2a538d5c8c9c1b9bd2373b1 (diff)
nichibutsu/shettle.cpp: improve colors, convert background layer to tilemap, workaround stuck sprite
Diffstat (limited to 'src')
-rw-r--r--src/mame/nichibutsu/shettle.cpp192
1 files changed, 85 insertions, 107 deletions
diff --git a/src/mame/nichibutsu/shettle.cpp b/src/mame/nichibutsu/shettle.cpp
index cd6d64ea921..2d78fa32152 100644
--- a/src/mame/nichibutsu/shettle.cpp
+++ b/src/mame/nichibutsu/shettle.cpp
@@ -15,8 +15,8 @@ Hardware has similarities with that of various Nichibutsu games of the same era.
TODO:
- what is the 24-pin chip marked Z4? Same is present on Clash Road. Maybe some kind of protection?;
-- input reading isn't probably totally correct (see weird lives DIPs);
-- colors are completely wrong according to available pictures;
+- reads area $6000-$61ff on player life loss;
+- input reading isn't correct (see weird lives DIPs);
- cocktail mode sprite positioning is wrong.
*/
@@ -32,6 +32,7 @@ TODO:
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
+#include "tilemap.h"
namespace {
@@ -55,6 +56,7 @@ public:
protected:
virtual void machine_start() override;
+ virtual void video_start() override;
private:
required_device<cpu_device> m_maincpu;
@@ -75,8 +77,14 @@ private:
void main_irq_mask_w(int state);
void sound_irq_mask_w(int state);
- void palette(palette_device &palette) const;
+ void palette_init(palette_device &palette) const;
+ tilemap_t *m_tilemap = nullptr;
+
+ void vram_w(offs_t offset, uint8_t data);
+ void attr_w(offs_t offset, uint8_t data);
+ TILE_GET_INFO_MEMBER(get_tile_info);
+ TILEMAP_MAPPER_MEMBER(tilemap_scan_rows_extra);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq);
@@ -93,7 +101,7 @@ private:
***************************************************************************/
-void shettle_state::palette(palette_device &palette) const // TODO: wrong, colors don't match available reference pics
+void shettle_state::palette_init(palette_device &palette) const
{
const uint8_t *color_prom = memregion("proms")->base();
static constexpr int resistances_rg[3] = { 1000, 470, 220 };
@@ -111,23 +119,20 @@ void shettle_state::palette(palette_device &palette) const // TODO: wrong, color
{
int bit0, bit1, bit2;
- // red component
bit0 = BIT(color_prom[i], 0);
bit1 = BIT(color_prom[i], 1);
bit2 = BIT(color_prom[i], 2);
- int const r = combine_weights(rweights, bit0, bit1, bit2);
+ int const g = combine_weights(gweights, bit0, bit1, bit2);
- // green component
bit0 = BIT(color_prom[i], 3);
bit1 = BIT(color_prom[i], 4);
- bit2 = BIT(color_prom[i], 5);
- int const g = combine_weights(gweights, bit0, bit1, bit2);
-
- // blue component
- bit0 = BIT(color_prom[i], 6);
- bit1 = BIT(color_prom[i], 7);
int const b = combine_weights(bweights, bit0, bit1);
+ bit0 = BIT(color_prom[i], 5);
+ bit1 = BIT(color_prom[i], 6);
+ bit2 = BIT(color_prom[i], 7);
+ int const r = combine_weights(rweights, bit0, bit1, bit2);
+
palette.set_indirect_color(i, rgb_t(r, g, b));
}
@@ -137,111 +142,84 @@ void shettle_state::palette(palette_device &palette) const // TODO: wrong, color
// chars and sprites use colors 0-15
for (int i = 0; i < 0x200; i++)
{
- uint8_t const ctabentry = color_prom[i ^ 0x03] & 0x0f;
+ uint8_t const ctabentry = color_prom[i] & 0x0f;
palette.set_pen_indirect(i, ctabentry);
}
}
-uint32_t shettle_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+TILE_GET_INFO_MEMBER(shettle_state::get_tile_info)
{
- for (int offs = 0x3ff; offs > 0; offs--)
- {
- int sx, sy;
+ const u8 tile = m_videoram[tile_index];
+ const u8 attr = m_colorram[tile_index];
+ // unused by the game, ported from wiping.cpp
+ tileinfo.group = (attr >> 7) & 1;
+ tileinfo.set(0, tile, attr & 0x3f, 0);
+}
- int const mx = offs % 32;
- int const my = offs / 32;
+// same as clshroad.cpp:
+// flips scanning per-column instead of per-row on left/right 16 pixels, for a 288 layout
+TILEMAP_MAPPER_MEMBER(shettle_state::tilemap_scan_rows_extra)
+{
+ if (col <= 0x01) return row + (col + 0x1e) * 0x20;
+ if (col >= 0x22) return row + (col - 0x22) * 0x20;
- if (my < 2)
- {
- sx = my + 34;
- sy = mx - 2;
- }
- else if (my >= 30)
- {
- sx = my - 30;
- sy = mx - 2;
- }
- else
- {
- sx = mx + 2;
- sy = my - 2;
- }
+ if (row <= 0x01) return 0;
+ if (row >= 0x1e) return 0;
- if (flip_screen())
- {
- sx = 35 - sx;
- sy = 27 - sy;
- }
+ return (col - 2) + row * 0x20;
+}
- m_gfxdecode->gfx(0)->opaque(bitmap, cliprect,
- m_videoram[offs],
- m_colorram[offs] & 0x3f,
- flip_screen(), flip_screen(),
- sx * 8, sy * 8);
- }
- for (int offs = m_spriteram.bytes() - 8; offs >= 0; offs -= 8)
+void shettle_state::vram_w(offs_t offset, uint8_t data)
+{
+ m_videoram[offset] = data;
+ m_tilemap->mark_tile_dirty(offset);
+}
+
+void shettle_state::attr_w(offs_t offset, uint8_t data)
+{
+ m_colorram[offset] = data;
+ m_tilemap->mark_tile_dirty(offset);
+}
+
+void shettle_state::video_start()
+{
+ m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(shettle_state::get_tile_info)), tilemap_mapper_delegate(*this, FUNC(shettle_state::tilemap_scan_rows_extra)), 8, 8, 36, 32);
+ m_tilemap->set_scrolldy(-16, -16);
+}
+
+uint32_t shettle_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ m_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
+
+ // top to bottom, ensure bridges goes behind player/enemy sprites
+ for (int offs = 0; offs < m_spriteram.bytes(); offs += 8)
{
int x = m_spriteram[offs + 3] + 0x0b;
int y = 224 - m_spriteram[offs + 2];
- int code = (m_spriteram[offs + 0] & 0x3f) | (m_spriteram[offs + 4] << 6);
+ u8 color = m_spriteram[offs + 1] & 0x3f;
- int color = m_spriteram[offs + 1] & 0x0f; // TODO: check this
+ // color entry 0 seems fully transparent
+ // (would otherwise "stick" bonus points after using yoyo, transmask?)
+ if (!color)
+ continue;
+ u16 code = (m_spriteram[offs + 0] & 0x3f) | (m_spriteram[offs + 4] << 6);
int flipx = m_spriteram[offs + 0] & 0x80;
int flipy = m_spriteram[offs + 0] & 0x40;
if (flip_screen())
{
- x = 240 - x; // TODO: wrong
+ y = 209 - y;
flipx = !flipx;
- y = 224 - y;
flipy = !flipy;
}
- m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, x, y, 0);
+ m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, x, y, 3);
}
- // redraw high priority chars
- for (int offs = 0x3ff; offs > 0; offs--)
- {
- if (m_colorram[offs] & 0x80)
- {
- int sx, sy;
-
- int const mx = offs % 32;
- int const my = offs / 32;
-
- if (my < 2)
- {
- sx = my + 34;
- sy = mx - 2;
- }
- else if (my >= 30)
- {
- sx = my - 30;
- sy = mx - 2;
- }
- else
- {
- sx = mx + 2;
- sy = my - 2;
- }
-
- if (flip_screen())
- {
- sx = 35 - sx;
- sy = 27 - sy;
- }
-
- m_gfxdecode->gfx(0)->opaque(bitmap, cliprect,
- m_videoram[offs],
- m_colorram[offs] & 0x3f,
- flip_screen(), flip_screen(),
- sx * 8, sy * 8);
- }
- }
+ m_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
return 0;
}
@@ -291,8 +269,8 @@ INTERRUPT_GEN_MEMBER(shettle_state::sound_timer_irq)
void shettle_state::main_map(address_map &map)
{
map(0x0000, 0x7fff).rom(); // TODO: some reads after 0x5fff. Interactions with the Z4 chip?
- map(0x8000, 0x83ff).ram().share(m_videoram);
- map(0x8400, 0x87ff).ram().share(m_colorram);
+ map(0x8000, 0x83ff).ram().w(FUNC(shettle_state::vram_w)).share(m_videoram);
+ map(0x8400, 0x87ff).ram().w(FUNC(shettle_state::attr_w)).share(m_colorram);
map(0x8e00, 0x8fff).ram().share(m_spriteram);
map(0x9000, 0x93ff).ram();
map(0x9600, 0x97ff).ram().share("main_sound");
@@ -357,12 +335,12 @@ static INPUT_PORTS_START( shettle )
PORT_DIPSETTING( 0x80, DEF_STR( On ) )
PORT_START("DSW2")
- PORT_DIPNAME( 0x05, 0x00, "0x01" ) PORT_DIPLOCATION("SW2:1,3")
+ PORT_DIPNAME( 0x05, 0x00, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW2:1,3")
PORT_DIPSETTING( 0x04, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x05, DEF_STR( 2C_2C ) )
PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x01, DEF_STR( 1C_2C ) )
- PORT_DIPNAME (0x02, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW2:2")
+ PORT_DIPNAME (0x02, 0x02, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW2:2")
PORT_DIPSETTING( 0x02, DEF_STR( Upright ) )
PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:4")
@@ -385,13 +363,13 @@ INPUT_PORTS_END
static const gfx_layout charlayout =
{
- 8,8, // 8*8 characters
- 256, // 256 characters
- 2, // 2 bits per pixel
- { 0, 4 }, // the two bitplanes are packed in one byte
- { 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3 },
- { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
- 16*8 // every char takes 16 consecutive bytes
+ 8,8,
+ RGN_FRAC(1,1),
+ 2,
+ { 0, 4 },
+ { STEP4(0,1), STEP4(8,1) },
+ { STEP8(0,8*2) },
+ 8*8*2
};
static const gfx_layout spritelayout =
@@ -408,8 +386,8 @@ static const gfx_layout spritelayout =
};
static GFXDECODE_START( gfx_wiping )
- GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 64 )
- GFXDECODE_ENTRY( "sprites", 0, spritelayout, 64*4, 64 )
+ GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 64 )
+ GFXDECODE_ENTRY( "sprites", 0, spritelayout, 0x100, 64 )
GFXDECODE_END
@@ -439,7 +417,7 @@ void shettle_state::shettle(machine_config &config)
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_wiping);
- PALETTE(config, m_palette, FUNC(shettle_state::palette), 64 * 4 + 64 * 4, 32);
+ PALETTE(config, m_palette, FUNC(shettle_state::palette_init), 256 + 256, 32);
// sound hardware
SPEAKER(config, "mono").front_center();
@@ -464,10 +442,10 @@ ROM_START( shettle )
ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "d.bin", 0x0000, 0x2000, CRC(1e2e7365) SHA1(ad6d0c94d5cb172d3a29523706ccd901a72e90be) )
- ROM_REGION( 0x1000, "chars", 0 )
+ ROM_REGION( 0x1000, "chars", ROMREGION_INVERT )
ROM_LOAD( "0.5d", 0x0000, 0x1000, CRC(fa6261da) SHA1(e7ab7eb2ab2ba2497d06606861a804d317d306ff) )
- ROM_REGION( 0x2000, "sprites", 0 )
+ ROM_REGION( 0x2000, "sprites", ROMREGION_INVERT )
ROM_LOAD( "e.bin", 0x0000, 0x2000, CRC(a3cef381) SHA1(ed511f5b695f0abdbaea8414d9de260f696f5318) )
ROM_REGION( 0x0340, "proms", 0 )