Skip to content

Commit 3b618bd

Browse files
committed
nichibutsu/shettle.cpp: improve colors, convert background layer to tilemap, workaround stuck sprite
1 parent 3cd4e2e commit 3b618bd

File tree

1 file changed

+85
-107
lines changed

1 file changed

+85
-107
lines changed

src/mame/nichibutsu/shettle.cpp

Lines changed: 85 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Hardware has similarities with that of various Nichibutsu games of the same era.
1515
1616
TODO:
1717
- what is the 24-pin chip marked Z4? Same is present on Clash Road. Maybe some kind of protection?;
18-
- input reading isn't probably totally correct (see weird lives DIPs);
19-
- colors are completely wrong according to available pictures;
18+
- reads area $6000-$61ff on player life loss;
19+
- input reading isn't correct (see weird lives DIPs);
2020
- cocktail mode sprite positioning is wrong.
2121
*/
2222

@@ -32,6 +32,7 @@ Hardware has similarities with that of various Nichibutsu games of the same era.
3232
#include "emupal.h"
3333
#include "screen.h"
3434
#include "speaker.h"
35+
#include "tilemap.h"
3536

3637

3738
namespace {
@@ -55,6 +56,7 @@ class shettle_state : public driver_device
5556

5657
protected:
5758
virtual void machine_start() override;
59+
virtual void video_start() override;
5860

5961
private:
6062
required_device<cpu_device> m_maincpu;
@@ -75,8 +77,14 @@ class shettle_state : public driver_device
7577
void main_irq_mask_w(int state);
7678
void sound_irq_mask_w(int state);
7779

78-
void palette(palette_device &palette) const;
80+
void palette_init(palette_device &palette) const;
7981

82+
tilemap_t *m_tilemap = nullptr;
83+
84+
void vram_w(offs_t offset, uint8_t data);
85+
void attr_w(offs_t offset, uint8_t data);
86+
TILE_GET_INFO_MEMBER(get_tile_info);
87+
TILEMAP_MAPPER_MEMBER(tilemap_scan_rows_extra);
8088
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
8189

8290
INTERRUPT_GEN_MEMBER(vblank_irq);
@@ -93,7 +101,7 @@ class shettle_state : public driver_device
93101
94102
***************************************************************************/
95103

96-
void shettle_state::palette(palette_device &palette) const // TODO: wrong, colors don't match available reference pics
104+
void shettle_state::palette_init(palette_device &palette) const
97105
{
98106
const uint8_t *color_prom = memregion("proms")->base();
99107
static constexpr int resistances_rg[3] = { 1000, 470, 220 };
@@ -111,23 +119,20 @@ void shettle_state::palette(palette_device &palette) const // TODO: wrong, color
111119
{
112120
int bit0, bit1, bit2;
113121

114-
// red component
115122
bit0 = BIT(color_prom[i], 0);
116123
bit1 = BIT(color_prom[i], 1);
117124
bit2 = BIT(color_prom[i], 2);
118-
int const r = combine_weights(rweights, bit0, bit1, bit2);
125+
int const g = combine_weights(gweights, bit0, bit1, bit2);
119126

120-
// green component
121127
bit0 = BIT(color_prom[i], 3);
122128
bit1 = BIT(color_prom[i], 4);
123-
bit2 = BIT(color_prom[i], 5);
124-
int const g = combine_weights(gweights, bit0, bit1, bit2);
125-
126-
// blue component
127-
bit0 = BIT(color_prom[i], 6);
128-
bit1 = BIT(color_prom[i], 7);
129129
int const b = combine_weights(bweights, bit0, bit1);
130130

131+
bit0 = BIT(color_prom[i], 5);
132+
bit1 = BIT(color_prom[i], 6);
133+
bit2 = BIT(color_prom[i], 7);
134+
int const r = combine_weights(rweights, bit0, bit1, bit2);
135+
131136
palette.set_indirect_color(i, rgb_t(r, g, b));
132137
}
133138

@@ -137,111 +142,84 @@ void shettle_state::palette(palette_device &palette) const // TODO: wrong, color
137142
// chars and sprites use colors 0-15
138143
for (int i = 0; i < 0x200; i++)
139144
{
140-
uint8_t const ctabentry = color_prom[i ^ 0x03] & 0x0f;
145+
uint8_t const ctabentry = color_prom[i] & 0x0f;
141146
palette.set_pen_indirect(i, ctabentry);
142147
}
143148
}
144149

145-
uint32_t shettle_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
150+
TILE_GET_INFO_MEMBER(shettle_state::get_tile_info)
146151
{
147-
for (int offs = 0x3ff; offs > 0; offs--)
148-
{
149-
int sx, sy;
152+
const u8 tile = m_videoram[tile_index];
153+
const u8 attr = m_colorram[tile_index];
154+
// unused by the game, ported from wiping.cpp
155+
tileinfo.group = (attr >> 7) & 1;
156+
tileinfo.set(0, tile, attr & 0x3f, 0);
157+
}
150158

151-
int const mx = offs % 32;
152-
int const my = offs / 32;
159+
// same as clshroad.cpp:
160+
// flips scanning per-column instead of per-row on left/right 16 pixels, for a 288 layout
161+
TILEMAP_MAPPER_MEMBER(shettle_state::tilemap_scan_rows_extra)
162+
{
163+
if (col <= 0x01) return row + (col + 0x1e) * 0x20;
164+
if (col >= 0x22) return row + (col - 0x22) * 0x20;
153165

154-
if (my < 2)
155-
{
156-
sx = my + 34;
157-
sy = mx - 2;
158-
}
159-
else if (my >= 30)
160-
{
161-
sx = my - 30;
162-
sy = mx - 2;
163-
}
164-
else
165-
{
166-
sx = mx + 2;
167-
sy = my - 2;
168-
}
166+
if (row <= 0x01) return 0;
167+
if (row >= 0x1e) return 0;
169168

170-
if (flip_screen())
171-
{
172-
sx = 35 - sx;
173-
sy = 27 - sy;
174-
}
169+
return (col - 2) + row * 0x20;
170+
}
175171

176-
m_gfxdecode->gfx(0)->opaque(bitmap, cliprect,
177-
m_videoram[offs],
178-
m_colorram[offs] & 0x3f,
179-
flip_screen(), flip_screen(),
180-
sx * 8, sy * 8);
181-
}
182172

183-
for (int offs = m_spriteram.bytes() - 8; offs >= 0; offs -= 8)
173+
void shettle_state::vram_w(offs_t offset, uint8_t data)
174+
{
175+
m_videoram[offset] = data;
176+
m_tilemap->mark_tile_dirty(offset);
177+
}
178+
179+
void shettle_state::attr_w(offs_t offset, uint8_t data)
180+
{
181+
m_colorram[offset] = data;
182+
m_tilemap->mark_tile_dirty(offset);
183+
}
184+
185+
void shettle_state::video_start()
186+
{
187+
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);
188+
m_tilemap->set_scrolldy(-16, -16);
189+
}
190+
191+
uint32_t shettle_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
192+
{
193+
m_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
194+
195+
// top to bottom, ensure bridges goes behind player/enemy sprites
196+
for (int offs = 0; offs < m_spriteram.bytes(); offs += 8)
184197
{
185198
int x = m_spriteram[offs + 3] + 0x0b;
186199
int y = 224 - m_spriteram[offs + 2];
187200

188-
int code = (m_spriteram[offs + 0] & 0x3f) | (m_spriteram[offs + 4] << 6);
201+
u8 color = m_spriteram[offs + 1] & 0x3f;
189202

190-
int color = m_spriteram[offs + 1] & 0x0f; // TODO: check this
203+
// color entry 0 seems fully transparent
204+
// (would otherwise "stick" bonus points after using yoyo, transmask?)
205+
if (!color)
206+
continue;
191207

208+
u16 code = (m_spriteram[offs + 0] & 0x3f) | (m_spriteram[offs + 4] << 6);
192209
int flipx = m_spriteram[offs + 0] & 0x80;
193210
int flipy = m_spriteram[offs + 0] & 0x40;
194211

195212
if (flip_screen())
196213
{
197-
x = 240 - x; // TODO: wrong
214+
y = 209 - y;
198215
flipx = !flipx;
199-
y = 224 - y;
200216
flipy = !flipy;
201217
}
202218

203-
m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, x, y, 0);
219+
m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, x, y, 3);
204220
}
205221

206-
// redraw high priority chars
207-
for (int offs = 0x3ff; offs > 0; offs--)
208-
{
209-
if (m_colorram[offs] & 0x80)
210-
{
211-
int sx, sy;
212-
213-
int const mx = offs % 32;
214-
int const my = offs / 32;
215-
216-
if (my < 2)
217-
{
218-
sx = my + 34;
219-
sy = mx - 2;
220-
}
221-
else if (my >= 30)
222-
{
223-
sx = my - 30;
224-
sy = mx - 2;
225-
}
226-
else
227-
{
228-
sx = mx + 2;
229-
sy = my - 2;
230-
}
231-
232-
if (flip_screen())
233-
{
234-
sx = 35 - sx;
235-
sy = 27 - sy;
236-
}
237-
238-
m_gfxdecode->gfx(0)->opaque(bitmap, cliprect,
239-
m_videoram[offs],
240-
m_colorram[offs] & 0x3f,
241-
flip_screen(), flip_screen(),
242-
sx * 8, sy * 8);
243-
}
244-
}
222+
m_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
245223

246224
return 0;
247225
}
@@ -291,8 +269,8 @@ INTERRUPT_GEN_MEMBER(shettle_state::sound_timer_irq)
291269
void shettle_state::main_map(address_map &map)
292270
{
293271
map(0x0000, 0x7fff).rom(); // TODO: some reads after 0x5fff. Interactions with the Z4 chip?
294-
map(0x8000, 0x83ff).ram().share(m_videoram);
295-
map(0x8400, 0x87ff).ram().share(m_colorram);
272+
map(0x8000, 0x83ff).ram().w(FUNC(shettle_state::vram_w)).share(m_videoram);
273+
map(0x8400, 0x87ff).ram().w(FUNC(shettle_state::attr_w)).share(m_colorram);
296274
map(0x8e00, 0x8fff).ram().share(m_spriteram);
297275
map(0x9000, 0x93ff).ram();
298276
map(0x9600, 0x97ff).ram().share("main_sound");
@@ -357,12 +335,12 @@ static INPUT_PORTS_START( shettle )
357335
PORT_DIPSETTING( 0x80, DEF_STR( On ) )
358336

359337
PORT_START("DSW2")
360-
PORT_DIPNAME( 0x05, 0x00, "0x01" ) PORT_DIPLOCATION("SW2:1,3")
338+
PORT_DIPNAME( 0x05, 0x00, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW2:1,3")
361339
PORT_DIPSETTING( 0x04, DEF_STR( 2C_1C ) )
362340
PORT_DIPSETTING( 0x05, DEF_STR( 2C_2C ) )
363341
PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) )
364342
PORT_DIPSETTING( 0x01, DEF_STR( 1C_2C ) )
365-
PORT_DIPNAME (0x02, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW2:2")
343+
PORT_DIPNAME (0x02, 0x02, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW2:2")
366344
PORT_DIPSETTING( 0x02, DEF_STR( Upright ) )
367345
PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
368346
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:4")
@@ -385,13 +363,13 @@ INPUT_PORTS_END
385363

386364
static const gfx_layout charlayout =
387365
{
388-
8,8, // 8*8 characters
389-
256, // 256 characters
390-
2, // 2 bits per pixel
391-
{ 0, 4 }, // the two bitplanes are packed in one byte
392-
{ 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3 },
393-
{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
394-
16*8 // every char takes 16 consecutive bytes
366+
8,8,
367+
RGN_FRAC(1,1),
368+
2,
369+
{ 0, 4 },
370+
{ STEP4(0,1), STEP4(8,1) },
371+
{ STEP8(0,8*2) },
372+
8*8*2
395373
};
396374

397375
static const gfx_layout spritelayout =
@@ -408,8 +386,8 @@ static const gfx_layout spritelayout =
408386
};
409387

410388
static GFXDECODE_START( gfx_wiping )
411-
GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 64 )
412-
GFXDECODE_ENTRY( "sprites", 0, spritelayout, 64*4, 64 )
389+
GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 64 )
390+
GFXDECODE_ENTRY( "sprites", 0, spritelayout, 0x100, 64 )
413391
GFXDECODE_END
414392

415393

@@ -439,7 +417,7 @@ void shettle_state::shettle(machine_config &config)
439417
screen.set_palette(m_palette);
440418

441419
GFXDECODE(config, m_gfxdecode, m_palette, gfx_wiping);
442-
PALETTE(config, m_palette, FUNC(shettle_state::palette), 64 * 4 + 64 * 4, 32);
420+
PALETTE(config, m_palette, FUNC(shettle_state::palette_init), 256 + 256, 32);
443421

444422
// sound hardware
445423
SPEAKER(config, "mono").front_center();
@@ -464,10 +442,10 @@ ROM_START( shettle )
464442
ROM_REGION( 0x10000, "audiocpu", 0 )
465443
ROM_LOAD( "d.bin", 0x0000, 0x2000, CRC(1e2e7365) SHA1(ad6d0c94d5cb172d3a29523706ccd901a72e90be) )
466444

467-
ROM_REGION( 0x1000, "chars", 0 )
445+
ROM_REGION( 0x1000, "chars", ROMREGION_INVERT )
468446
ROM_LOAD( "0.5d", 0x0000, 0x1000, CRC(fa6261da) SHA1(e7ab7eb2ab2ba2497d06606861a804d317d306ff) )
469447

470-
ROM_REGION( 0x2000, "sprites", 0 )
448+
ROM_REGION( 0x2000, "sprites", ROMREGION_INVERT )
471449
ROM_LOAD( "e.bin", 0x0000, 0x2000, CRC(a3cef381) SHA1(ed511f5b695f0abdbaea8414d9de260f696f5318) )
472450

473451
ROM_REGION( 0x0340, "proms", 0 )

0 commit comments

Comments
 (0)