@@ -15,8 +15,8 @@ Hardware has similarities with that of various Nichibutsu games of the same era.
1515
1616TODO:
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
3738namespace {
@@ -55,6 +56,7 @@ class shettle_state : public driver_device
5556
5657protected:
5758 virtual void machine_start () override ;
59+ virtual void video_start () override ;
5860
5961private:
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)
291269void 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
386364static 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
397375static const gfx_layout spritelayout =
@@ -408,8 +386,8 @@ static const gfx_layout spritelayout =
408386};
409387
410388static 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 )
413391GFXDECODE_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