@@ -15,8 +15,8 @@ Hardware has similarities with that of various Nichibutsu games of the same era.
15
15
16
16
TODO:
17
17
- 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) ;
20
20
- cocktail mode sprite positioning is wrong.
21
21
*/
22
22
@@ -32,6 +32,7 @@ Hardware has similarities with that of various Nichibutsu games of the same era.
32
32
#include " emupal.h"
33
33
#include " screen.h"
34
34
#include " speaker.h"
35
+ #include " tilemap.h"
35
36
36
37
37
38
namespace {
@@ -55,6 +56,7 @@ class shettle_state : public driver_device
55
56
56
57
protected:
57
58
virtual void machine_start () override ;
59
+ virtual void video_start () override ;
58
60
59
61
private:
60
62
required_device<cpu_device> m_maincpu;
@@ -75,8 +77,14 @@ class shettle_state : public driver_device
75
77
void main_irq_mask_w (int state);
76
78
void sound_irq_mask_w (int state);
77
79
78
- void palette (palette_device &palette) const ;
80
+ void palette_init (palette_device &palette) const ;
79
81
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);
80
88
uint32_t screen_update (screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
81
89
82
90
INTERRUPT_GEN_MEMBER (vblank_irq);
@@ -93,7 +101,7 @@ class shettle_state : public driver_device
93
101
94
102
***************************************************************************/
95
103
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
97
105
{
98
106
const uint8_t *color_prom = memregion (" proms" )->base ();
99
107
static constexpr int resistances_rg[3 ] = { 1000 , 470 , 220 };
@@ -111,23 +119,20 @@ void shettle_state::palette(palette_device &palette) const // TODO: wrong, color
111
119
{
112
120
int bit0, bit1, bit2;
113
121
114
- // red component
115
122
bit0 = BIT (color_prom[i], 0 );
116
123
bit1 = BIT (color_prom[i], 1 );
117
124
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);
119
126
120
- // green component
121
127
bit0 = BIT (color_prom[i], 3 );
122
128
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 );
129
129
int const b = combine_weights (bweights, bit0, bit1);
130
130
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
+
131
136
palette.set_indirect_color (i, rgb_t (r, g, b));
132
137
}
133
138
@@ -137,111 +142,84 @@ void shettle_state::palette(palette_device &palette) const // TODO: wrong, color
137
142
// chars and sprites use colors 0-15
138
143
for (int i = 0 ; i < 0x200 ; i++)
139
144
{
140
- uint8_t const ctabentry = color_prom[i ^ 0x03 ] & 0x0f ;
145
+ uint8_t const ctabentry = color_prom[i] & 0x0f ;
141
146
palette.set_pen_indirect (i, ctabentry);
142
147
}
143
148
}
144
149
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 )
146
151
{
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
+ }
150
158
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 ;
153
165
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 ;
169
168
170
- if (flip_screen ())
171
- {
172
- sx = 35 - sx;
173
- sy = 27 - sy;
174
- }
169
+ return (col - 2 ) + row * 0x20 ;
170
+ }
175
171
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
- }
182
172
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 )
184
197
{
185
198
int x = m_spriteram[offs + 3 ] + 0x0b ;
186
199
int y = 224 - m_spriteram[offs + 2 ];
187
200
188
- int code = ( m_spriteram[offs + 0 ] & 0x3f ) | (m_spriteram[offs + 4 ] << 6 ) ;
201
+ u8 color = m_spriteram[offs + 1 ] & 0x3f ;
189
202
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 ;
191
207
208
+ u16 code = (m_spriteram[offs + 0 ] & 0x3f ) | (m_spriteram[offs + 4 ] << 6 );
192
209
int flipx = m_spriteram[offs + 0 ] & 0x80 ;
193
210
int flipy = m_spriteram[offs + 0 ] & 0x40 ;
194
211
195
212
if (flip_screen ())
196
213
{
197
- x = 240 - x; // TODO: wrong
214
+ y = 209 - y;
198
215
flipx = !flipx;
199
- y = 224 - y;
200
216
flipy = !flipy;
201
217
}
202
218
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 );
204
220
}
205
221
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 );
245
223
246
224
return 0 ;
247
225
}
@@ -291,8 +269,8 @@ INTERRUPT_GEN_MEMBER(shettle_state::sound_timer_irq)
291
269
void shettle_state::main_map (address_map &map)
292
270
{
293
271
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);
296
274
map (0x8e00 , 0x8fff ).ram ().share (m_spriteram);
297
275
map (0x9000 , 0x93ff ).ram ();
298
276
map (0x9600 , 0x97ff ).ram ().share (" main_sound" );
@@ -357,12 +335,12 @@ static INPUT_PORTS_START( shettle )
357
335
PORT_DIPSETTING( 0x80 , DEF_STR( On ) )
358
336
359
337
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" )
361
339
PORT_DIPSETTING( 0x04 , DEF_STR( 2C_1C ) )
362
340
PORT_DIPSETTING( 0x05 , DEF_STR( 2C_2C ) )
363
341
PORT_DIPSETTING( 0x00 , DEF_STR( 1C_1C ) )
364
342
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" )
366
344
PORT_DIPSETTING( 0x02 , DEF_STR( Upright ) )
367
345
PORT_DIPSETTING( 0x00 , DEF_STR( Cocktail ) )
368
346
PORT_DIPNAME( 0x08 , 0x00 , DEF_STR( Unknown ) ) PORT_DIPLOCATION(" SW2:4" )
@@ -385,13 +363,13 @@ INPUT_PORTS_END
385
363
386
364
static const gfx_layout charlayout =
387
365
{
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
395
373
};
396
374
397
375
static const gfx_layout spritelayout =
@@ -408,8 +386,8 @@ static const gfx_layout spritelayout =
408
386
};
409
387
410
388
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 )
413
391
GFXDECODE_END
414
392
415
393
@@ -439,7 +417,7 @@ void shettle_state::shettle(machine_config &config)
439
417
screen.set_palette (m_palette);
440
418
441
419
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 );
443
421
444
422
// sound hardware
445
423
SPEAKER (config, " mono" ).front_center ();
@@ -464,10 +442,10 @@ ROM_START( shettle )
464
442
ROM_REGION ( 0x10000 , " audiocpu" , 0 )
465
443
ROM_LOAD ( " d.bin" , 0x0000 , 0x2000 , CRC(1e2e7365) SHA1(ad6d0c94d5cb172d3a29523706ccd901a72e90be) )
466
444
467
- ROM_REGION ( 0x1000 , " chars" , 0 )
445
+ ROM_REGION ( 0x1000 , " chars" , ROMREGION_INVERT )
468
446
ROM_LOAD ( " 0.5d" , 0x0000 , 0x1000 , CRC(fa6261da) SHA1(e7ab7eb2ab2ba2497d06606861a804d317d306ff) )
469
447
470
- ROM_REGION ( 0x2000 , " sprites" , 0 )
448
+ ROM_REGION ( 0x2000 , " sprites" , ROMREGION_INVERT )
471
449
ROM_LOAD ( " e.bin" , 0x0000 , 0x2000 , CRC(a3cef381) SHA1(ed511f5b695f0abdbaea8414d9de260f696f5318) )
472
450
473
451
ROM_REGION ( 0x0340 , " proms" , 0 )
0 commit comments