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