1 // license:BSD-3-Clause
2 // copyright-holders:Manuel Abadia, Peter Ferrie, David Haywood
3 /***************************************************************************
4 
5 Thunder Hoop II: Strikes Back (c) 1994 Gaelco
6 
7 Driver by Manuel Abadia <emumanu+mame@gmail.com>
8 
9 updated by Peter Ferrie <peter.ferrie@gmail.com>
10 
11 There is a priority bug on the title screen (Gaelco logo is hidden by black
12 borders)  It seems sprite priority is hacked around on most of the older
13 Gaelco drivers.
14 
15 
16 REF.940411
17 +-------------------------------------------------+
18 |       C1                                  6116  |
19 |  VOL  C2*                                 6116  |
20 |          30MHz                            6116  |
21 |    M6295                    +----------+  6116  |
22 |     1MHz                    |TMS       |        |
23 |       6116                  |TPC1020AFN|        |
24 |J      6116                  |   -084C  |    H8  |
25 |A     +------------+         +----------+        |
26 |M     |DS5002FP Box|         +----------+        |
27 |M     +------------+         |TMS       |    H12 |
28 |A             65756          |TPC1020AFN|        |
29 |              65756          |   -084C  |        |
30 |                             +----------+        |
31 |SW1                                   PAL   65764|
32 |     24MHz    MC68000P12                    65764|
33 |SW2           C22                    6116        |
34 |      PAL     C23                    6116        |
35 +-------------------------------------------------+
36 
37   CPU: MC68000P12 & DS5002FP (used for protection)
38 Sound: OKI M6295
39   OSC: 30MHz, 24MHz & 1MHz resonator
40   RAM: MHS HM3-65756K-5  32K x 8 SRAM (x2)
41        MHS HM3-65764E-5  8K x 8 SRAM (x2)
42        UM6116BK-35  2K x 8 SRAM (x8)
43   PAL: TI F20L8-25CNT DIP24 (x2)
44   VOL: Volume pot
45    SW: Two 8 switch dipswitches
46 
47 DS5002FP Box contains:
48   Dallas DS5002SP @ 12MHz
49   KM62256BLG-7L - 32Kx8 Low Power CMOS SRAM
50   3.6v Battery
51   JP1 - 5 pin port to program SRAM
52 
53 Measurements from actual PCB:
54   DS5002FP - 12MHz
55   OKI MSM6295 - 1MHz, pin 7 is disconnected (neither pulled LOW or HIGH)
56   H-SYNC - 15.151KHz
57   V-SYNC - 59.24Hz
58 
59 ***************************************************************************/
60 
61 #include "emu.h"
62 #include "includes/thoop2.h"
63 
64 #include "machine/gaelco_ds5002fp.h"
65 
66 #include "cpu/m68000/m68000.h"
67 #include "cpu/mcs51/mcs51.h"
68 #include "machine/74259.h"
69 #include "machine/watchdog.h"
70 #include "sound/okim6295.h"
71 
72 #include "screen.h"
73 #include "speaker.h"
74 
75 
machine_start()76 void thoop2_state::machine_start()
77 {
78 	m_okibank->configure_entries(0, 16, memregion("oki")->base(), 0x10000);
79 }
80 
oki_bankswitch_w(uint8_t data)81 void thoop2_state::oki_bankswitch_w(uint8_t data)
82 {
83 	m_okibank->set_entry(data & 0x0f);
84 }
85 
WRITE_LINE_MEMBER(thoop2_state::coin1_lockout_w)86 WRITE_LINE_MEMBER(thoop2_state::coin1_lockout_w)
87 {
88 	machine().bookkeeping().coin_lockout_w(0, !state);
89 }
90 
WRITE_LINE_MEMBER(thoop2_state::coin2_lockout_w)91 WRITE_LINE_MEMBER(thoop2_state::coin2_lockout_w)
92 {
93 	machine().bookkeeping().coin_lockout_w(1, !state);
94 }
95 
WRITE_LINE_MEMBER(thoop2_state::coin1_counter_w)96 WRITE_LINE_MEMBER(thoop2_state::coin1_counter_w)
97 {
98 	machine().bookkeeping().coin_counter_w(0, state);
99 }
100 
WRITE_LINE_MEMBER(thoop2_state::coin2_counter_w)101 WRITE_LINE_MEMBER(thoop2_state::coin2_counter_w)
102 {
103 	machine().bookkeeping().coin_counter_w(1, state);
104 }
105 
shareram_w(offs_t offset,uint8_t data)106 void thoop2_state::shareram_w(offs_t offset, uint8_t data)
107 {
108 	// why isn't there address map functionality for this?
109 	reinterpret_cast<u8 *>(m_shareram.target())[BYTE_XOR_BE(offset)] = data;
110 }
111 
shareram_r(offs_t offset)112 uint8_t thoop2_state::shareram_r(offs_t offset)
113 {
114 	// why isn't there address map functionality for this?
115 	return reinterpret_cast<u8 const *>(m_shareram.target())[BYTE_XOR_BE(offset)];
116 }
117 
118 
mcu_hostmem_map(address_map & map)119 void thoop2_state::mcu_hostmem_map(address_map &map)
120 {
121 	map(0x8000, 0xffff).rw(FUNC(thoop2_state::shareram_r), FUNC(thoop2_state::shareram_w)); // confirmed that 0x8000 - 0xffff is a window into 68k shared RAM
122 }
123 
124 
thoop2_map(address_map & map)125 void thoop2_state::thoop2_map(address_map &map)
126 {
127 	map(0x000000, 0x0fffff).rom();                                                 /* ROM */
128 	map(0x100000, 0x101fff).ram().w(FUNC(thoop2_state::vram_w)).share("videoram");   /* Video RAM */
129 	map(0x108000, 0x108007).writeonly().share("vregs");                 /* Video Registers */
130 	map(0x10800c, 0x10800d).w("watchdog", FUNC(watchdog_timer_device::reset16_w));                           /* INT 6 ACK/Watchdog timer */
131 	map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");/* Palette */
132 	map(0x440000, 0x440fff).ram().share("spriteram");                       /* Sprite RAM */
133 	map(0x700000, 0x700001).portr("DSW2");
134 	map(0x700002, 0x700003).portr("DSW1");
135 	map(0x700004, 0x700005).portr("P1");
136 	map(0x700006, 0x700007).portr("P2");
137 	map(0x700008, 0x700009).portr("SYSTEM");
138 	map(0x70000b, 0x70000b).select(0x000070).lw8(NAME([this] (offs_t offset, u8 data) { m_outlatch->write_d0(offset >> 4, data); }));
139 	map(0x70000d, 0x70000d).w(FUNC(thoop2_state::oki_bankswitch_w));               /* OKI6295 bankswitch */
140 	map(0x70000f, 0x70000f).rw("oki", FUNC(okim6295_device::read), FUNC(okim6295_device::write));                  /* OKI6295 data register */
141 	map(0xfe0000, 0xfe7fff).ram();                                          /* Work RAM */
142 	map(0xfe8000, 0xfeffff).ram().share("shareram");                     /* Work RAM (shared with D5002FP) */
143 }
144 
145 
oki_map(address_map & map)146 void thoop2_state::oki_map(address_map &map)
147 {
148 	map(0x00000, 0x2ffff).rom();
149 	map(0x30000, 0x3ffff).bankr("okibank");
150 }
151 
152 
153 static INPUT_PORTS_START( thoop2 )
154 	PORT_START("DSW1")
155 	PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_B ) )
156 	PORT_DIPSETTING(    0x02, DEF_STR( 6C_1C ) )
157 	PORT_DIPSETTING(    0x03, DEF_STR( 5C_1C ) )
158 	PORT_DIPSETTING(    0x04, DEF_STR( 4C_1C ) )
159 	PORT_DIPSETTING(    0x05, DEF_STR( 3C_1C ) )
160 	PORT_DIPSETTING(    0x06, DEF_STR( 2C_1C ) )
161 	PORT_DIPSETTING(    0x01, DEF_STR( 3C_2C ) )
162 	PORT_DIPSETTING(    0x00, DEF_STR( 4C_3C ) )
163 	PORT_DIPSETTING(    0x07, DEF_STR( 1C_1C ) )
164 	PORT_DIPNAME( 0x38, 0x38, DEF_STR( Coin_A ) )
165 	PORT_DIPSETTING(    0x38, DEF_STR( 1C_1C ) )
166 	PORT_DIPSETTING(    0x00, DEF_STR( 3C_4C ) )
167 	PORT_DIPSETTING(    0x08, DEF_STR( 2C_3C ) )
168 	PORT_DIPSETTING(    0x30, DEF_STR( 1C_2C ) )
169 	PORT_DIPSETTING(    0x28, DEF_STR( 1C_3C ) )
170 	PORT_DIPSETTING(    0x20, DEF_STR( 1C_4C ) )
171 	PORT_DIPSETTING(    0x18, DEF_STR( 1C_5C ) )
172 	PORT_DIPSETTING(    0x10, DEF_STR( 1C_6C ) )
173 	PORT_DIPNAME( 0x40, 0x40, "Credit configuration" )
174 	PORT_DIPSETTING(    0x40, "Start 1C/Continue 1C" )
175 	PORT_DIPSETTING(    0x00, "Start 2C/Continue 1C" )
176 	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Free_Play ) )
177 	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
178 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
179 
180 	PORT_START("DSW2")
181 	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) )
182 	PORT_DIPSETTING(    0x03, DEF_STR( Normal ) )
183 	PORT_DIPSETTING(    0x02, DEF_STR( Easy ) )
184 	PORT_DIPSETTING(    0x01, DEF_STR( Hard ) )
185 	PORT_DIPSETTING(    0x00, DEF_STR( Hardest ) )
186 	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
187 	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
188 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
189 	PORT_DIPNAME( 0x18, 0x18, DEF_STR( Lives ) )
190 	PORT_DIPSETTING(    0x18, "2" )
191 	PORT_DIPSETTING(    0x10, "3" )
192 	PORT_DIPSETTING(    0x08, "4" )
193 	PORT_DIPSETTING(    0x00, "1" )
194 	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Demo_Sounds ) )
195 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
196 	PORT_DIPSETTING(    0x20, DEF_STR( On ) )
197 	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
198 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
199 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
200 	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )
201 
202 	PORT_START("P1")
203 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
204 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
205 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
206 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
207 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
208 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
209 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
210 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )
211 
212 	PORT_START("P2")
213 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
214 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
215 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
216 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
217 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
218 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
219 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )
220 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 )
221 
222 	PORT_START("SYSTEM")
223 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 )
224 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE2 )   /* test button */
225 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
226 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
227 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
228 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
229 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
230 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
231 INPUT_PORTS_END
232 
233 
234 static const gfx_layout thoop2_tilelayout =
235 {
236 	8,8,                                    /* 8x8 tiles */
237 	RGN_FRAC(1,2),                            /* number of tiles */
238 	4,                                      /* 4 bpp */
239 	{ 8, 0, RGN_FRAC(1,2)+8, RGN_FRAC(1,2)+0 },
240 	{ STEP8(0,1) },
241 	{ STEP8(0,8*2) },
242 	16*8
243 };
244 
245 static const gfx_layout thoop2_tilelayout_16 =
246 {
247 	16,16,                                  /* 16x16 tiles */
248 	RGN_FRAC(1,2),                            /* number of tiles */
249 	4,                                      /* 4 bpp */
250 	{ 8, 0, RGN_FRAC(1,2)+8, RGN_FRAC(1,2)+0 },
251 	{ STEP8(0,1), STEP8(8*2*16,1) },
252 	{ STEP16(0,8*2) },
253 	64*8
254 };
255 
256 
257 static GFXDECODE_START( gfx_thoop2 )
258 	GFXDECODE_ENTRY( "gfx1", 0x000000, thoop2_tilelayout,    0, 64 )
259 	GFXDECODE_ENTRY( "gfx1", 0x000000, thoop2_tilelayout_16, 0, 64 )
260 GFXDECODE_END
261 
262 
thoop2(machine_config & config)263 void thoop2_state::thoop2(machine_config &config)
264 {
265 	/* basic machine hardware */
266 	M68000(config, m_maincpu, XTAL(24'000'000) / 2); // 12MHz verified
267 	m_maincpu->set_addrmap(AS_PROGRAM, &thoop2_state::thoop2_map);
268 	m_maincpu->set_vblank_int("screen", FUNC(thoop2_state::irq6_line_hold));
269 
270 	gaelco_ds5002fp_device &ds5002fp(GAELCO_DS5002FP(config, "gaelco_ds5002fp", XTAL(24'000'000) / 2)); // 12MHz verified
271 	ds5002fp.set_addrmap(0, &thoop2_state::mcu_hostmem_map);
272 	config.set_perfect_quantum("gaelco_ds5002fp:mcu");
273 
274 	LS259(config, m_outlatch);
275 	m_outlatch->q_out_cb<0>().set(FUNC(thoop2_state::coin1_lockout_w));
276 	m_outlatch->q_out_cb<1>().set(FUNC(thoop2_state::coin2_lockout_w));
277 	m_outlatch->q_out_cb<2>().set(FUNC(thoop2_state::coin1_counter_w));
278 	m_outlatch->q_out_cb<3>().set(FUNC(thoop2_state::coin2_counter_w));
279 	m_outlatch->q_out_cb<4>().set_nop(); // unknown. Sound related?
280 	m_outlatch->q_out_cb<5>().set_nop(); // unknown
281 
282 	WATCHDOG_TIMER(config, "watchdog");
283 
284 	/* video hardware */
285 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
286 	screen.set_refresh_hz(59.24);
287 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
288 	screen.set_size(32*16, 32*16);
289 	screen.set_visarea(0, 320-1, 16, 256-1);
290 	screen.set_screen_update(FUNC(thoop2_state::screen_update));
291 	screen.set_palette(m_palette);
292 
293 	GFXDECODE(config, m_gfxdecode, m_palette, gfx_thoop2);
294 	PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 1024);
295 
296 	/* sound hardware */
297 	SPEAKER(config, "mono").front_center();
298 
299 	okim6295_device &oki(OKIM6295(config, "oki", XTAL(1'000'000), okim6295_device::PIN7_HIGH)); // 1MHz resonator - pin 7 not connected
300 	oki.set_addrmap(0, &thoop2_state::oki_map);
301 	oki.add_route(ALL_OUTPUTS, "mono", 1.0);
302 }
303 
304 
305 
306 ROM_START( thoop2 ) /* REF.940411 PCB */
307 	ROM_REGION( 0x100000, "maincpu", 0 )    /* 68000 code */
308 	ROM_LOAD16_BYTE(    "th2c23.c23",   0x000000, 0x080000, CRC(3e465753) SHA1(1ea1173b9fe5d652e7b5fafb822e2535cecbc198) )
309 	ROM_LOAD16_BYTE(    "th2c22.c22",   0x000001, 0x080000, CRC(837205b7) SHA1(f78b90c2be0b4dddaba26f074ea00eff863cfdb2) )
310 
311 	ROM_REGION( 0x8000, "gaelco_ds5002fp:sram", 0 ) /* DS5002FP code */
312 	ROM_LOAD( "thoop2_ds5002fp.bin", 0x00000, 0x8000, CRC(6881384d) SHA1(c1eff5558716293e1325b766e2205783286c12f9) ) /* dumped from 3 boards, reconstructed with 2/3 wins rule, all bytes verified by hand as correct */
313 
314 	ROM_REGION( 0x100, "gaelco_ds5002fp:mcu:internal", ROMREGION_ERASE00 )
315 	/* these are the default states stored in NVRAM */
316 	DS5002FP_SET_MON( 0x79 )
317 	DS5002FP_SET_RPCTL( 0x00 )
318 	DS5002FP_SET_CRCR( 0x80 )
319 
320 	ROM_REGION( 0x800000, "gfx1", 0 )
321 	ROM_LOAD( "th2-h8.h8",     0x000000, 0x400000, CRC(60328a11) SHA1(fcdb374d2fc7ef5351a4181c471d192199dc2081) )
322 	ROM_LOAD( "th2-h12.h12",   0x400000, 0x400000, CRC(b25c2d3e) SHA1(d70f3e4e2432d80c2ac87cd81208ada303bac04a) )
323 
324 	ROM_REGION( 0x100000, "oki", 0 )    /* ADPCM samples - sound chip is OKIM6295 */
325 	ROM_LOAD( "th2-c1.c1",     0x000000, 0x100000, CRC(8fac8c30) SHA1(8e49bb596144761eae95f3e1266e57fb386664f2) )
326 	/* 0x00000-0x2ffff is fixed, 0x30000-0x3ffff is bank switched */
327 ROM_END
328 
329 ROM_START( thoop2a ) /* REF.940411 PCB */
330 	ROM_REGION( 0x100000, "maincpu", 0 )    /* 68000 code */
331 	ROM_LOAD16_BYTE(    "3.c23",   0x000000, 0x080000, CRC(6cd4a8dc) SHA1(7d0cdce64b390c3f9769b07d57cf1eee1e6a7bf5) )
332 	ROM_LOAD16_BYTE(    "2.c22",   0x000001, 0x080000, CRC(59ba9b43) SHA1(6c6690a2e389fc9f1e166c87748da1175e3b58f8) )
333 
334 	ROM_REGION( 0x8000, "gaelco_ds5002fp:sram", 0 ) /* DS5002FP code */
335 	ROM_LOAD( "thoop2_ds5002fp.bin", 0x00000, 0x8000, CRC(6881384d) SHA1(c1eff5558716293e1325b766e2205783286c12f9) ) /* dumped from 3 boards, reconstructed with 2/3 wins rule, all bytes verified by hand as correct */
336 
337 	ROM_REGION( 0x100, "gaelco_ds5002fp:mcu:internal", ROMREGION_ERASE00 )
338 	/* these are the default states stored in NVRAM */
339 	DS5002FP_SET_MON( 0x79 )
340 	DS5002FP_SET_RPCTL( 0x00 )
341 	DS5002FP_SET_CRCR( 0x80 )
342 
343 	ROM_REGION( 0x800000, "gfx1", 0 )
344 	ROM_LOAD( "th2-h8.h8",     0x000000, 0x400000, CRC(60328a11) SHA1(fcdb374d2fc7ef5351a4181c471d192199dc2081) )
345 	ROM_LOAD( "th2-h12.h12",   0x400000, 0x400000, CRC(b25c2d3e) SHA1(d70f3e4e2432d80c2ac87cd81208ada303bac04a) )
346 
347 	ROM_REGION( 0x100000, "oki", 0 )    /* ADPCM samples - sound chip is OKIM6295 */
348 	ROM_LOAD( "th2-c1.c1",     0x000000, 0x100000, CRC(8fac8c30) SHA1(8e49bb596144761eae95f3e1266e57fb386664f2) )
349 	/* 0x00000-0x2ffff is fixed, 0x30000-0x3ffff is bank switched */
350 ROM_END
351 
352 GAME( 1994, thoop2,       0, thoop2, thoop2, thoop2_state, empty_init, ROT0, "Gaelco", "TH Strikes Back (Non North America, Version 1.0, Checksum 020E0867)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
353 GAME( 1994, thoop2a, thoop2, thoop2, thoop2, thoop2_state, empty_init, ROT0, "Gaelco", "TH Strikes Back (Non North America, Version 1.0, Checksum 020EB356)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
354