1 /***************************************************************************
2
3 Operation Thunderbolt (Taito)
4 ---------------------
5
6 David Graves
7
8 (this is based on the F2 driver by Bryan McPhail, Brad Oliver, Andrew Prime,
9 Nicola Salmoria. Thanks to Richard Bush and the Raine team, whose open
10 source was very helpful in many areas particularly the sprites.)
11
12 *****
13
14 Operation Thunderbolt operates on hardware very similar to the Taito Z
15 system, in particular the game Spacegun. The lightgun hardware in these
16 two (as well as the eerom and calibration process) looks identical.
17
18 The game has 4 separate layers of graphics - one 64x64 tiled scrolling
19 background plane of 8x8 tiles, a similar foreground plane, a sprite plane,
20 and a text plane with character definitions held in ram.
21
22 The sprites are 16x8 tiles aggregated through a spritemap rom into 64x64
23 zoomable sprites.
24
25 The main difference is that Operation Thunderbolt uses only a single 68000
26 CPU, whereas Spacegun has twin 68Ks. (Operation Thunderbolt has a Z80
27 taking over sound duties, which Spacegun doesn't.)
28
29
30 TODO
31 ====
32
33 Light gun interrupt timing is arbitrary.
34
35 Saved states invariably freeze.
36
37 TC0100SCN problem: text vs. bg0/1 offsets are wrong: first level
38 wants bg0 4 further right. Cut screens (all?) want bg0 4 pixels
39 further left. But the bg0 x scroll value is zero in both cases!
40 (and the code setting it is a CLR, so there's no doubt it's meant
41 to be).
42
43 There are no set bits in the TC0100SCN ctrl regs which might be
44 causing this. So I'm mystified. (Maybe it's related to game being
45 ORIENTATION_FLIP_X ??)
46
47 DIPs
48
49
50 ***************************************************************************/
51
52 #include "driver.h"
53 #include "state.h"
54 #include "cpu/m68000/m68000.h"
55 #include "machine/eeprom.h"
56 #include "vidhrdw/generic.h"
57 #include "vidhrdw/taitoic.h"
58 #include "sndhrdw/taitosnd.h"
59
60 VIDEO_START( othunder );
61 VIDEO_UPDATE( othunder );
62
63 static data16_t eep_latch = 0;
64
65 extern data16_t *othunder_ram;
66
67
68 /***********************************************************
69 INTERRUPTS
70 ***********************************************************/
71
othunder_gun_interrupt(int x)72 static void othunder_gun_interrupt(int x)
73 {
74 cpu_set_irq_line(0,6,HOLD_LINE);
75 }
76
77
78 /******************************************************************
79 EEPROM
80
81 This is an earlier version of the eeprom used in some TaitoB games.
82 The eeprom unlock command is different, and the write/clock/reset
83 bits are different.
84 ******************************************************************/
85
86 static data8_t default_eeprom[128]=
87 {
88 0x00,0x00,0x00,0xff,0x00,0x01,0x41,0x41,0x00,0x00,0x00,0xff,0x00,0x00,0xf0,0xf0,
89 0x00,0x00,0x00,0xff,0x00,0x01,0x41,0x41,0x00,0x00,0x00,0xff,0x00,0x00,0xf0,0xf0,
90 0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x01,0x40,0x00,0x00,0x00,0xf0,0x00,
91 0x00,0x01,0x42,0x85,0x00,0x00,0xf1,0xe3,0x00,0x01,0x40,0x00,0x00,0x00,0xf0,0x00,
92 0x00,0x01,0x42,0x85,0x00,0x00,0xf1,0xe3,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
93 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
94 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
95 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
96 };
97
98 static struct EEPROM_interface eeprom_interface =
99 {
100 6, /* address bits */
101 16, /* data bits */
102 "0110", /* read command */
103 "0101", /* write command */
104 "0111", /* erase command */
105 "0100000000", /* lock command */
106 "0100111111" /* unlock command */
107 };
108
NVRAM_HANDLER(othunder)109 static NVRAM_HANDLER( othunder )
110 {
111 if (read_or_write)
112 EEPROM_save(file);
113 else
114 {
115 EEPROM_init(&eeprom_interface);
116
117 if (file)
118 EEPROM_load(file);
119 else
120 EEPROM_set_data(default_eeprom,128); /* Default the gun setup values */
121 }
122 }
123
eeprom_r(void)124 static int eeprom_r(void)
125 {
126 return (EEPROM_read_bit() & 0x01)<<7;
127 }
128
129 #if 0
130 static READ16_HANDLER( eep_latch_r )
131 {
132 return eep_latch;
133 }
134 #endif
135
WRITE16_HANDLER(othunder_output_bypass_w)136 static WRITE16_HANDLER( othunder_output_bypass_w )
137 {
138 switch (offset)
139 {
140 case 0x03:
141
142 /* 0000xxxx (unused)
143 000x0000 eeprom reset (active low)
144 00x00000 eeprom clock
145 0x000000 eeprom data
146 x0000000 (unused) */
147
148 COMBINE_DATA(&eep_latch);
149 EEPROM_write_bit(data & 0x40);
150 EEPROM_set_clock_line((data & 0x20) ? ASSERT_LINE : CLEAR_LINE);
151 EEPROM_set_cs_line((data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
152 break;
153
154 default:
155 TC0220IOC_w(offset,data & 0xff);
156 }
157 }
158
159
160 /**********************************************************
161 GAME INPUTS
162 **********************************************************/
163
READ16_HANDLER(othunder_input_bypass_r)164 static READ16_HANDLER( othunder_input_bypass_r )
165 {
166 switch (offset)
167 {
168 case 0x03:
169 return eeprom_r();
170
171 default:
172 return TC0220IOC_r( offset );
173 }
174 }
175
READ16_HANDLER(othunder_lightgun_r)176 static READ16_HANDLER( othunder_lightgun_r )
177 {
178 switch (offset)
179 {
180 case 0x00:
181 return input_port_5_word_r(0,mem_mask); /* P1X */
182
183 case 0x01:
184 return input_port_6_word_r(0,mem_mask); /* P1Y */
185
186 case 0x02:
187 return input_port_7_word_r(0,mem_mask); /* P2X */
188
189 case 0x03:
190 return input_port_8_word_r(0,mem_mask); /* P2Y */
191 }
192
193 //logerror("CPU #0 lightgun_r offset %06x: warning - read unmapped memory address %06x\n",activecpu_get_pc(),offset);
194
195 return 0x0;
196 }
197
WRITE16_HANDLER(othunder_lightgun_w)198 static WRITE16_HANDLER( othunder_lightgun_w )
199 {
200 /* Each write invites a new lightgun interrupt as soon as the
201 hardware has got the next coordinate ready. We set a token
202 delay of 10000 cycles, small enough so they can all be
203 collected inside one frame. */
204
205 timer_set(TIME_IN_CYCLES(10000,0),0, othunder_gun_interrupt);
206 }
207
208
209 /*****************************************
210 SOUND
211 *****************************************/
212
213 static int banknum = -1;
214
reset_sound_region(void)215 static void reset_sound_region(void)
216 {
217 cpu_setbank( 10, memory_region(REGION_CPU2) + (banknum * 0x4000) + 0x10000 );
218 }
219
WRITE_HANDLER(sound_bankswitch_w)220 static WRITE_HANDLER( sound_bankswitch_w )
221 {
222 banknum = (data - 1) & 7;
223 reset_sound_region();
224 }
225
WRITE16_HANDLER(othunder_sound_w)226 static WRITE16_HANDLER( othunder_sound_w )
227 {
228 if (offset == 0)
229 taitosound_port_w (0, data & 0xff);
230 else if (offset == 1)
231 taitosound_comm_w (0, data & 0xff);
232 }
233
READ16_HANDLER(othunder_sound_r)234 static READ16_HANDLER( othunder_sound_r )
235 {
236 if (offset == 1)
237 return ((taitosound_comm_r (0) & 0xff));
238 else return 0;
239 }
240
241
242 /***********************************************************
243 MEMORY STRUCTURES
244 ***********************************************************/
245
MEMORY_READ16_START(othunder_readmem)246 static MEMORY_READ16_START( othunder_readmem )
247 { 0x000000, 0x07ffff, MRA16_ROM },
248 { 0x080000, 0x08ffff, MRA16_RAM }, /* main ram */
249 { 0x090000, 0x09000f, othunder_input_bypass_r },
250 { 0x100000, 0x100007, TC0110PCR_word_r }, /* palette */
251 { 0x200000, 0x20ffff, TC0100SCN_word_0_r }, /* tilemaps */
252 { 0x220000, 0x22000f, TC0100SCN_ctrl_word_0_r },
253 { 0x300000, 0x300003, othunder_sound_r },
254 { 0x400000, 0x4005ff, MRA16_RAM }, /* sprite ram */
255 { 0x500000, 0x500007, othunder_lightgun_r },
256 MEMORY_END
257
258 static MEMORY_WRITE16_START( othunder_writemem )
259 { 0x000000, 0x07ffff, MWA16_ROM },
260 { 0x080000, 0x08ffff, MWA16_RAM, &othunder_ram },
261 { 0x090000, 0x09000f, othunder_output_bypass_w },
262 // { 0x090006, 0x090007, eeprom_w },
263 // { 0x090008, 0x090009, MWA16_NOP }, /* coin ctr, lockout ? */
264 // { 0x09000c, 0x09000d, MWA16_NOP }, /* ?? (keeps writing 0x77) */
265 { 0x100000, 0x100007, TC0110PCR_step1_rbswap_word_w }, /* palette */
266 { 0x200000, 0x20ffff, TC0100SCN_word_0_w }, /* tilemaps */
267 { 0x220000, 0x22000f, TC0100SCN_ctrl_word_0_w },
268 { 0x300000, 0x300003, othunder_sound_w },
269 { 0x400000, 0x4005ff, MWA16_RAM, &spriteram16, &spriteram_size },
270 { 0x500000, 0x500007, othunder_lightgun_w },
271 { 0x600000, 0x600003, MWA16_NOP }, /* zeros written: see code at $854 */
272 MEMORY_END
273
274
275 /***************************************************************************/
276
277 static MEMORY_READ_START( z80_sound_readmem )
278 { 0x0000, 0x3fff, MRA_ROM },
279 { 0x4000, 0x7fff, MRA_BANK10 },
280 { 0xc000, 0xdfff, MRA_RAM },
281 { 0xe000, 0xe000, YM2610_status_port_0_A_r },
282 { 0xe001, 0xe001, YM2610_read_port_0_r },
283 { 0xe002, 0xe002, YM2610_status_port_0_B_r },
284 { 0xe200, 0xe200, MRA_NOP },
285 { 0xe201, 0xe201, taitosound_slave_comm_r },
286 { 0xea00, 0xea00, MRA_NOP },
287 MEMORY_END
288
289 static MEMORY_WRITE_START( z80_sound_writemem )
290 { 0x0000, 0x7fff, MWA_ROM },
291 { 0xc000, 0xdfff, MWA_RAM },
292 { 0xe000, 0xe000, YM2610_control_port_0_A_w },
293 { 0xe001, 0xe001, YM2610_data_port_0_A_w },
294 { 0xe002, 0xe002, YM2610_control_port_0_B_w },
295 { 0xe003, 0xe003, YM2610_data_port_0_B_w },
296 { 0xe200, 0xe200, taitosound_slave_port_w },
297 { 0xe201, 0xe201, taitosound_slave_comm_w },
298 { 0xe400, 0xe403, MWA_NOP }, /* pan */
299 { 0xee00, 0xee00, MWA_NOP }, /* ? */
300 { 0xf000, 0xf000, MWA_NOP }, /* ? */
301 { 0xf200, 0xf200, sound_bankswitch_w },
302 MEMORY_END
303
304
305 /***********************************************************
306 INPUT PORTS, DIPs
307 ***********************************************************/
308
309 #define TAITO_COINAGE_WORLD_8 \
310 PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) ) \
311 PORT_DIPSETTING( 0x00, DEF_STR( 4C_1C ) ) \
312 PORT_DIPSETTING( 0x10, DEF_STR( 3C_1C ) ) \
313 PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) \
314 PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) \
315 PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) ) \
316 PORT_DIPSETTING( 0xc0, DEF_STR( 1C_2C ) ) \
317 PORT_DIPSETTING( 0x80, DEF_STR( 1C_3C ) ) \
318 PORT_DIPSETTING( 0x40, DEF_STR( 1C_4C ) ) \
319 PORT_DIPSETTING( 0x00, DEF_STR( 1C_6C ) )
320
321 #define TAITO_COINAGE_JAPAN_8 \
322 PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) ) \
323 PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C ) ) \
324 PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) \
325 PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) ) \
326 PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) ) \
327 PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) ) \
328 PORT_DIPSETTING( 0x40, DEF_STR( 2C_1C ) ) \
329 PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) ) \
330 PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) ) \
331 PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) )
332
333 #define TAITO_DIFFICULTY_8 \
334 PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) ) \
335 PORT_DIPSETTING( 0x02, "Easy" ) \
336 PORT_DIPSETTING( 0x03, "Medium" ) \
337 PORT_DIPSETTING( 0x01, "Hard" ) \
338 PORT_DIPSETTING( 0x00, "Hardest" )
339
340 INPUT_PORTS_START( othunder )
341 PORT_START /* DSW A */
342 PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unused ) )
343 PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
344 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
345 PORT_DIPNAME( 0x02, 0x02, "Allow Continue" )
346 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
347 PORT_DIPSETTING( 0x02, DEF_STR( On ) )
348 PORT_SERVICE( 0x04, IP_ACTIVE_LOW )
349 PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) )
350 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
351 PORT_DIPSETTING( 0x08, DEF_STR( On ) )
352 TAITO_COINAGE_WORLD_8
353
354 PORT_START /* DSW B */
355 TAITO_DIFFICULTY_8
356 PORT_DIPNAME( 0x0c, 0x0c, "Magazines/Rockets" )
357 PORT_DIPSETTING( 0x0c, "5/3" )
358 PORT_DIPSETTING( 0x08, "6/4" )
359 PORT_DIPSETTING( 0x04, "7/5" )
360 PORT_DIPSETTING( 0x00, "8/6" )
361 PORT_DIPNAME( 0x30, 0x30, "Bullets per Magazine" )
362 PORT_DIPSETTING( 0x00, "30" )
363 PORT_DIPSETTING( 0x10, "35" )
364 PORT_DIPSETTING( 0x30, "40" )
365 PORT_DIPSETTING( 0x20, "50" )
366 PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) )
367 PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
368 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
369 PORT_DIPNAME( 0x80, 0x00, "Language" )
370 PORT_DIPSETTING( 0x80, "Japanese" )
371 PORT_DIPSETTING( 0x00, "English" )
372
373 PORT_START /* IN0 */
374 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
375 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
376 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 )
377 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 )
378 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
379 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
380 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1)
381 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2)
382
383 PORT_START /* IN1, unused */
384
385 PORT_START /* IN2 */
386 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
387 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
388 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
389 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
390 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
391 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
392 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
393 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
394
395 /* speed of 13 is compromise between moving aim around screen fast
396 enough and being accurate enough not to miss targets. 20 is too
397 inaccurate, and 10 is too slow. */
398
399 PORT_START
400 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_X | IPF_REVERSE | IPF_PLAYER1, 25, 13, 0, 0xff)
401
402 PORT_START
403 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_Y | IPF_PLAYER1, 25, 13, 0, 0xff)
404
405 PORT_START
406 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_X | IPF_REVERSE | IPF_PLAYER2, 25, 13, 0, 0xff)
407
408 PORT_START
409 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_Y | IPF_PLAYER2, 25, 13, 0, 0xff)
410 INPUT_PORTS_END
411
412 INPUT_PORTS_START( othundu )
413 PORT_START /* DSW A */
414 PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unused ) )
415 PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
416 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
417 PORT_DIPNAME( 0x02, 0x02, "Allow Continue" )
418 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
419 PORT_DIPSETTING( 0x02, DEF_STR( On ) )
420 PORT_SERVICE( 0x04, IP_ACTIVE_LOW )
421 PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) )
422 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
423 PORT_DIPSETTING( 0x08, DEF_STR( On ) )
424 TAITO_COINAGE_JAPAN_8
425
426 PORT_START /* DSW B */
427 TAITO_DIFFICULTY_8
428 PORT_DIPNAME( 0x0c, 0x0c, "Magazines/Rockets" )
429 PORT_DIPSETTING( 0x0c, "5/3" )
430 PORT_DIPSETTING( 0x08, "6/4" )
431 PORT_DIPSETTING( 0x04, "7/5" )
432 PORT_DIPSETTING( 0x00, "8/6" )
433 PORT_DIPNAME( 0x30, 0x30, "Bullets per Magazine" )
434 PORT_DIPSETTING( 0x00, "30" )
435 PORT_DIPSETTING( 0x10, "35" )
436 PORT_DIPSETTING( 0x30, "40" )
437 PORT_DIPSETTING( 0x20, "50" )
438 PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) )
439 PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
440 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
441 PORT_DIPNAME( 0x80, 0x00, "Language" )
442 PORT_DIPSETTING( 0x80, "Japanese" )
443 PORT_DIPSETTING( 0x00, "English" )
444
445 PORT_START /* IN0 */
446 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
447 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
448 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 )
449 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 )
450 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
451 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
452 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1)
453 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2)
454
455 PORT_START /* IN1, unused */
456
457 PORT_START /* IN2 */
458 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
459 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
460 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
461 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
462 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
463 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
464 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
465 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
466
467 /* speed of 13 is compromise between moving aim around screen fast
468 enough and being accurate enough not to miss targets. 20 is too
469 inaccurate, and 10 is too slow. */
470
471 PORT_START
472 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_X | IPF_REVERSE | IPF_PLAYER1, 25, 13, 0, 0xff)
473
474 PORT_START
475 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_Y | IPF_PLAYER1, 25, 13, 0, 0xff)
476
477 PORT_START
478 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_X | IPF_REVERSE | IPF_PLAYER2, 25, 13, 0, 0xff)
479
480 PORT_START
481 PORT_ANALOG( 0xff, 0x80, IPT_LIGHTGUN_Y | IPF_PLAYER2, 25, 13, 0, 0xff)
482 INPUT_PORTS_END
483
484
485 /***********************************************************
486 GFX DECODING
487 ***********************************************************/
488
489 static struct GfxLayout tile16x8_layout =
490 {
491 16,8, /* 16*8 sprites */
492 RGN_FRAC(1,1),
493 4, /* 4 bits per pixel */
494 { 0, 8, 16, 24 },
495 { 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7 },
496 { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
497 64*8 /* every sprite takes 64 consecutive bytes */
498 };
499
500 static struct GfxLayout charlayout =
501 {
502 8,8, /* 8*8 characters */
503 RGN_FRAC(1,1),
504 4, /* 4 bits per pixel */
505 { 0, 1, 2, 3 },
506 { 2*4, 3*4, 0*4, 1*4, 6*4, 7*4, 4*4, 5*4 },
507 { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
508 32*8 /* every sprite takes 32 consecutive bytes */
509 };
510
511 static struct GfxDecodeInfo othunder_gfxdecodeinfo[] =
512 {
513 { REGION_GFX2, 0, &tile16x8_layout, 0, 256 }, /* sprite parts */
514 { REGION_GFX1, 0, &charlayout, 0, 256 }, /* sprites & playfield */
515 { -1 } /* end of array */
516 };
517
518
519 /**************************************************************
520 YM2610 (SOUND)
521 **************************************************************/
522
523 /* handler called by the YM2610 emulator when the internal timers cause an IRQ */
irqhandler(int irq)524 static void irqhandler(int irq)
525 {
526 cpu_set_irq_line(1,0,irq ? ASSERT_LINE : CLEAR_LINE);
527 }
528
529 static struct YM2610interface ym2610_interface =
530 {
531 1, /* 1 chip */
532 16000000/2, /* 8 MHz ?? */
533 { 25 },
534 { 0 },
535 { 0 },
536 { 0 },
537 { 0 },
538 { irqhandler },
539 { REGION_SOUND2 }, /* Delta-T */
540 { REGION_SOUND1 }, /* ADPCM */
541 { YM3012_VOL(100,MIXER_PAN_LEFT,100,MIXER_PAN_RIGHT) }
542 };
543
544
545 /***********************************************************
546 MACHINE DRIVERS
547 ***********************************************************/
548
549 static MACHINE_DRIVER_START( othunder )
550
551 /* basic machine hardware */
552 MDRV_CPU_ADD(M68000, 12000000 ) /* 12 MHz ??? */
MDRV_CPU_MEMORY(othunder_readmem,othunder_writemem)553 MDRV_CPU_MEMORY(othunder_readmem,othunder_writemem)
554 MDRV_CPU_VBLANK_INT(irq5_line_hold,1)
555
556 MDRV_CPU_ADD(Z80,16000000/4 )
557 MDRV_CPU_FLAGS(CPU_AUDIO_CPU) /* 4 MHz ??? */
558 MDRV_CPU_MEMORY(z80_sound_readmem,z80_sound_writemem)
559
560 MDRV_FRAMES_PER_SECOND(60)
561 MDRV_VBLANK_DURATION(DEFAULT_60HZ_VBLANK_DURATION)
562
563 MDRV_NVRAM_HANDLER(othunder)
564
565 /* video hardware */
566 MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
567 MDRV_SCREEN_SIZE(40*8, 32*8)
568 MDRV_VISIBLE_AREA(0*8, 40*8-1, 2*8, 32*8-1)
569 MDRV_GFXDECODE(othunder_gfxdecodeinfo)
570 MDRV_PALETTE_LENGTH(4096)
571
572 MDRV_VIDEO_START(othunder)
573 MDRV_VIDEO_UPDATE(othunder)
574
575 /* sound hardware */
576 MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
577 MDRV_SOUND_ADD(YM2610, ym2610_interface)
578 MACHINE_DRIVER_END
579
580
581 /***************************************************************************
582 DRIVERS
583 ***************************************************************************/
584
585 ROM_START( othunder )
586 ROM_REGION( 0x80000, REGION_CPU1, 0 ) /* 512K for 68000 code */
587 ROM_LOAD16_BYTE( "b67-20", 0x00000, 0x20000, CRC(21439ea2) SHA1(d5b5a194e9698cf43513c0d56146772e8132ab07) )
588 ROM_LOAD16_BYTE( "b67-23", 0x00001, 0x20000, CRC(789e9daa) SHA1(15bb0eec68aeea0b9f55889566338c9ce0ac9b5e) )
589 ROM_LOAD16_BYTE( "b67-14.61", 0x40000, 0x20000, CRC(7f3dd724) SHA1(2f2eeae0ee31e20082237b9a947c6848771eb73c) )
590 ROM_LOAD16_BYTE( "b67-15.62", 0x40001, 0x20000, CRC(e84f62d0) SHA1(3b4a55a14dee7d592467fde9a75bde64deabd27d) )
591
592 ROM_REGION( 0x1c000, REGION_CPU2, 0 ) /* sound cpu */
593 ROM_LOAD( "b67-13.40", 0x00000, 0x04000, CRC(2936b4b1) SHA1(39b41643464dd89e456ab6eb15a0ff0aef30afde) )
594 ROM_CONTINUE( 0x10000, 0x0c000 ) /* banked stuff */
595
596 ROM_REGION( 0x80000, REGION_GFX1, ROMREGION_DISPOSE )
597 ROM_LOAD( "b67-06", 0x00000, 0x80000, CRC(b9a38d64) SHA1(7ae8165b444d9da6ccdbc4a769535bcbb6738aaa) ) /* SCR */
598
599 ROM_REGION( 0x200000, REGION_GFX2, ROMREGION_DISPOSE )
600 ROM_LOAD32_BYTE( "b67-01", 0x00000, 0x80000, CRC(81ad9acb) SHA1(d9ad3f6332c6ca6b9872da57526a8158a3cf5b2f) ) /* OBJ: each rom has 1 bitplane, forming 16x8 tiles */
601 ROM_LOAD32_BYTE( "b67-02", 0x00001, 0x80000, CRC(c20cd2fb) SHA1(b015e1fe167e19826aa451b45cd143d66a6db83c) )
602 ROM_LOAD32_BYTE( "b67-03", 0x00002, 0x80000, CRC(bc9019ed) SHA1(7eddc83d71be97ce6637e6b35c226d58e6c39c3f) )
603 ROM_LOAD32_BYTE( "b67-04", 0x00003, 0x80000, CRC(2af4c8af) SHA1(b2ae7aad0c59ffc368811f4bd5546dbb6860f9a9) )
604
605 ROM_REGION16_LE( 0x80000, REGION_USER1, 0 )
606 ROM_LOAD16_WORD( "b67-05", 0x00000, 0x80000, CRC(9593e42b) SHA1(54b5538c302a1734ff4b752ab87a8c45d5c6b23d) ) /* STY, index used to create 64x64 sprites on the fly */
607
608 ROM_REGION( 0x80000, REGION_SOUND1, 0 ) /* ADPCM samples */
609 ROM_LOAD( "b67-08", 0x00000, 0x80000, CRC(458f41fb) SHA1(acca7c95acd1ae7a1cc51fb7fe644ad6d00ff5ac) )
610
611 ROM_REGION( 0x80000, REGION_SOUND2, 0 ) /* Delta-T samples */
612 ROM_LOAD( "b67-07", 0x00000, 0x80000, CRC(4f834357) SHA1(f34705ce64870a8b24ec2639505079cc031fb719) )
613
614 ROM_REGION( 0x10000, REGION_USER2, 0 )
615 // ROM_LOAD( "b67-09", 0x00000, 0xd56, CRC(130fd2ab) ) /* pals ? */
616 // ROM_LOAD( "b67-10", 0x00000, 0xcd5, CRC(312f9e2a) )
617 // ROM_LOAD( "b67-11", 0x00000, 0xada, CRC(f863b864) )
618 // ROM_LOAD( "b67-12", 0x00000, 0xcd5, CRC(653d86bb) )
619 ROM_END
620
621 ROM_START( othundu )
622 ROM_REGION( 0x80000, REGION_CPU1, 0 ) /* 512K for 68000 code */
623 ROM_LOAD16_BYTE( "b67-20-1.63", 0x00000, 0x20000, CRC(851a453b) SHA1(48b8c379e78cd79463f1e24dc23816a97cf819b8) )
624 ROM_LOAD16_BYTE( "b67-22-1.64", 0x00001, 0x20000, CRC(19480dc0) SHA1(8bbc982c89f0878e7639330970df5aa93ecbb083) )
625 ROM_LOAD16_BYTE( "b67-14.61", 0x40000, 0x20000, CRC(7f3dd724) SHA1(2f2eeae0ee31e20082237b9a947c6848771eb73c) )
626 ROM_LOAD16_BYTE( "b67-15.62", 0x40001, 0x20000, CRC(e84f62d0) SHA1(3b4a55a14dee7d592467fde9a75bde64deabd27d) )
627
628 ROM_REGION( 0x1c000, REGION_CPU2, 0 ) /* sound cpu */
629 ROM_LOAD( "b67-13.40", 0x00000, 0x04000, CRC(2936b4b1) SHA1(39b41643464dd89e456ab6eb15a0ff0aef30afde) )
630 ROM_CONTINUE( 0x10000, 0x0c000 ) /* banked stuff */
631
632 ROM_REGION( 0x80000, REGION_GFX1, ROMREGION_DISPOSE )
633 ROM_LOAD( "b67-06", 0x00000, 0x80000, CRC(b9a38d64) SHA1(7ae8165b444d9da6ccdbc4a769535bcbb6738aaa) ) /* SCR */
634
635 ROM_REGION( 0x200000, REGION_GFX2, ROMREGION_DISPOSE )
636 ROM_LOAD32_BYTE( "b67-01", 0x00000, 0x80000, CRC(81ad9acb) SHA1(d9ad3f6332c6ca6b9872da57526a8158a3cf5b2f) ) /* OBJ: each rom has 1 bitplane, forming 16x8 tiles */
637 ROM_LOAD32_BYTE( "b67-02", 0x00001, 0x80000, CRC(c20cd2fb) SHA1(b015e1fe167e19826aa451b45cd143d66a6db83c) )
638 ROM_LOAD32_BYTE( "b67-03", 0x00002, 0x80000, CRC(bc9019ed) SHA1(7eddc83d71be97ce6637e6b35c226d58e6c39c3f) )
639 ROM_LOAD32_BYTE( "b67-04", 0x00003, 0x80000, CRC(2af4c8af) SHA1(b2ae7aad0c59ffc368811f4bd5546dbb6860f9a9) )
640
641 ROM_REGION16_LE( 0x80000, REGION_USER1, 0 )
642 ROM_LOAD16_WORD( "b67-05", 0x00000, 0x80000, CRC(9593e42b) SHA1(54b5538c302a1734ff4b752ab87a8c45d5c6b23d) ) /* STY, index used to create 64x64 sprites on the fly */
643
644 ROM_REGION( 0x80000, REGION_SOUND1, 0 ) /* ADPCM samples */
645 ROM_LOAD( "b67-08", 0x00000, 0x80000, CRC(458f41fb) SHA1(acca7c95acd1ae7a1cc51fb7fe644ad6d00ff5ac) )
646
647 ROM_REGION( 0x80000, REGION_SOUND2, 0 ) /* Delta-T samples */
648 ROM_LOAD( "b67-07", 0x00000, 0x80000, CRC(4f834357) SHA1(f34705ce64870a8b24ec2639505079cc031fb719) )
649 ROM_END
650
651
652 static DRIVER_INIT( othunder )
653 {
654 state_save_register_int("sound1", 0, "sound region", &banknum);
655 state_save_register_func_postload(reset_sound_region);
656 }
657
658
659 GAME( 1988, othunder, 0, othunder, othunder, othunder, ORIENTATION_FLIP_X, "Taito Corporation Japan", "Operation Thunderbolt (World)" )
660 GAME( 1988, othundu, othunder, othunder, othundu, othunder, ORIENTATION_FLIP_X, "Taito America Corporation", "Operation Thunderbolt (US)" )
661