1 /***************************************************************************
2 
3 	  Poly-Play
4 	  (c) 1985 by VEB Polytechnik Karl-Marx-Stadt
5 
6 	  driver by Martin Buchholz (buchholz@mail.uni-greifswald.de)
7 
8 	  Very special thanks to the following people, each one of them spent
9 	  some of their spare time to make this driver working:
10 	  - Juergen Oppermann and Volker Hann for electronical assistance,
11 	    repair work and ROM dumping.
12 	  - Jan-Ole Christian from the Videogamemuseum in Berlin, which houses
13 	    one of the last existing Poly-Play arcade automatons. He also
14 	    provided me with schematics and service manuals.
15 
16 
17 memory map:
18 
19 0000 - 03ff OS ROM
20 0400 - 07ff Game ROM (used for Abfahrtslauf)
21 0800 - 0cff Menu Screen ROM
22 
23 0d00 - 0fff work RAM
24 
25 1000 - 4fff GAME ROM (pcb 2 - Abfahrtslauf          (1000 - 1bff)
26                               Hirschjagd            (1c00 - 27ff)
27                               Hase und Wolf         (2800 - 3fff)
28                               Schmetterlingsfang    (4000 - 4fff)
29 5000 - 8fff GAME ROM (pcb 1 - Schiessbude           (5000 - 5fff)
30                               Autorennen            (6000 - 73ff)
31                               opto-akust. Merkspiel (7400 - 7fff)
32                               Wasserrohrbruch       (8000 - 8fff)
33 
34 e800 - ebff character ROM (chr 00..7f) 1 bit per pixel
35 ec00 - f7ff character RAM (chr 80..ff) 3 bit per pixel
36 f800 - ffff video RAM
37 
38 I/O ports:
39 
40 read:
41 
42 83        IN1
43           used as hardware random number generator
44 
45 84        IN0
46           bit 0 = fire button
47           bit 1 = right
48           bit 2 = left
49           bit 3 = up
50           bit 4 = down
51           bit 5 = unused
52           bit 6 = Summe Spiele
53           bit 7 = coinage (+IRQ to make the game acknowledge it)
54 
55 85        bit 0-4 = light organ (unemulated :)) )
56           bit 5-7 = sound parameter (unemulated, it's very difficult to
57                     figure out how those work)
58 
59 86        ???
60 
61 87        PIO Control register
62 
63 write:
64 80	      Sound Channel 1
65 81        Sound Channel 2
66 82        generates 40 Hz timer for timeout in game title screens
67 83        generates main 75 Hz timer interrupt
68 
69 The Poly-Play has a simple bookmarking system which can be activated
70 setting Bit 6 of PORTA (Summe Spiele) to low. It reads a double word
71 from 0c00 and displays it on the screen.
72 I currently haven't figured out how the I/O port handling for the book-
73 mark system works.
74 
75 Uniquely the Poly-Play has a light organ which totally confuses you whilst
76 playing the automaton. Bits 1-5 of PORTB control the organ but it's not
77 emulated now. ;)
78 
79 ***************************************************************************/
80 
81 #include "driver.h"
82 #include "vidhrdw/generic.h"
83 #include "cpu/z80/z80.h"
84 
85 /* video hardware access */
86 extern unsigned char *polyplay_characterram;
87 PALETTE_INIT( polyplay );
88 VIDEO_UPDATE( polyplay );
89 READ_HANDLER( polyplay_characterram_r );
90 WRITE_HANDLER( polyplay_characterram_w );
91 
92 /* I/O Port handling */
93 static READ_HANDLER( polyplay_random_read );
94 
95 /* sound handling */
96 void set_channel1(int active);
97 void set_channel2(int active);
98 static int prescale1;
99 static int prescale2;
100 static int channel1_active;
101 static int channel1_const;
102 static int channel2_active;
103 static int channel2_const;
104 void play_channel1(int data);
105 void play_channel2(int data);
106 int  polyplay_sh_start(const struct MachineSound *msound);
107 void polyplay_sh_stop(void);
108 void polyplay_sh_update(void);
109 
110 /* timer handling */
111 static void timer_callback(int param);
112 static void* polyplay_timer;
113 static WRITE_HANDLER( polyplay_start_timer2 );
114 static WRITE_HANDLER( polyplay_sound_channel );
115 
116 
117 /* Polyplay Sound Interface */
118 static struct CustomSound_interface custom_interface =
119 {
120 	polyplay_sh_start,
121 	polyplay_sh_stop,
122 	polyplay_sh_update
123 };
124 
125 
MACHINE_INIT(polyplay)126 static MACHINE_INIT( polyplay )
127 {
128 	channel1_active = 0;
129 	channel1_const = 0;
130 	channel2_active = 0;
131 	channel2_const = 0;
132 
133 	set_channel1(0);
134 	play_channel1(0);
135 	set_channel2(0);
136 	play_channel2(0);
137 
138 	polyplay_timer = timer_alloc(timer_callback);
139 }
140 
141 
INTERRUPT_GEN(periodic_interrupt)142 static INTERRUPT_GEN( periodic_interrupt )
143 {
144 	cpu_set_irq_line_and_vector(0, 0, HOLD_LINE, 0x4e);
145 }
146 
147 
INTERRUPT_GEN(coin_interrupt)148 static INTERRUPT_GEN( coin_interrupt )
149 {
150 	static int last = 0;
151 
152 	if (readinputport(0) & 0x80)
153 	{
154 		last = 0;
155 	}
156 	else
157 	{
158 		if (last == 0)    /* coin inserted */
159 		{
160 			cpu_set_irq_line_and_vector(0, 0, HOLD_LINE, 0x50);
161 		}
162 
163 		last = 1;
164 	}
165 }
166 
167 
168 /* memory mapping */
MEMORY_READ_START(polyplay_readmem)169 static MEMORY_READ_START( polyplay_readmem )
170 	{ 0x0000, 0x0bff, MRA_ROM },
171 	{ 0x0c00, 0x0fff, MRA_RAM },
172 	{ 0x1000, 0x8fff, MRA_ROM },
173 	{ 0xe800, 0xebff, MRA_ROM },
174 	{ 0xec00, 0xf7ff, polyplay_characterram_r },
175 	{ 0xf800, 0xffff, videoram_r },
176 MEMORY_END
177 
178 static MEMORY_WRITE_START( polyplay_writemem )
179 	{ 0x0000, 0x0bff, MWA_ROM },
180 	{ 0x0c00, 0x0fff, MWA_RAM },
181 	{ 0x1000, 0x8fff, MWA_ROM },
182 	{ 0xe800, 0xebff, MWA_ROM },
183 	{ 0xec00, 0xf7ff, polyplay_characterram_w, &polyplay_characterram },
184 	{ 0xf800, 0xffff, videoram_w, &videoram, &videoram_size },
185 MEMORY_END
186 
187 
188 /* port mapping */
189 static PORT_READ_START( readport_polyplay )
190 	{ 0x84, 0x84, input_port_0_r },
191 	{ 0x83, 0x83, polyplay_random_read },
192 PORT_END
193 
194 static PORT_WRITE_START( writeport_polyplay )
195 	{ 0x80, 0x81, polyplay_sound_channel },
196 	{ 0x82, 0x82, polyplay_start_timer2 },
197 PORT_END
198 
199 INPUT_PORTS_START( polyplay )
200 	PORT_START	/* IN0 */
201 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
202 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY )
203 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT  | IPF_8WAY )
204 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP    | IPF_8WAY )
205 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN  | IPF_8WAY )
206 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
207 	PORT_BITX(0x40, IP_ACTIVE_LOW, IPT_SERVICE, "Bookkeeping Info", KEYCODE_F2, IP_JOY_NONE )
208 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 )
209 INPUT_PORTS_END
210 
211 
212 static WRITE_HANDLER( polyplay_sound_channel )
213 {
214 	switch(offset) {
215 	case 0x00:
216 		if (channel1_const) {
217 			if (data <= 1) {
218 				set_channel1(0);
219 			}
220 			channel1_const = 0;
221 			play_channel1(data*prescale1);
222 
223 		}
224 		else {
225 			prescale1 = (data & 0x20) ? 16 : 1;
226 			if (data & 0x04) {
227 				set_channel1(1);
228 				channel1_const = 1;
229 			}
230 			if ((data == 0x41) || (data == 0x65) || (data == 0x45)) {
231 				set_channel1(0);
232 				play_channel1(0);
233 			}
234 		}
235 		break;
236 	case 0x01:
237 		if (channel2_const) {
238 			if (data <= 1) {
239 				set_channel2(0);
240 			}
241 			channel2_const = 0;
242 			play_channel2(data*prescale2);
243 
244 		}
245 		else {
246 			prescale2 = (data & 0x20) ? 16 : 1;
247 			if (data & 0x04) {
248 				set_channel2(1);
249 				channel2_const = 1;
250 			}
251 			if ((data == 0x41) || (data == 0x65) || (data == 0x45)) {
252 				set_channel2(0);
253 				play_channel2(0);
254 			}
255 		}
256 		break;
257 	}
258 }
259 
WRITE_HANDLER(polyplay_start_timer2)260 static WRITE_HANDLER( polyplay_start_timer2 )
261 {
262 	if (data == 0x03)
263 		timer_adjust(polyplay_timer, TIME_NEVER, 0, 0);
264 
265 	if (data == 0xb5)
266 		timer_adjust(polyplay_timer, TIME_IN_HZ(40), 0, TIME_IN_HZ(40));
267 }
268 
READ_HANDLER(polyplay_random_read)269 static READ_HANDLER( polyplay_random_read )
270 {
271 	return rand() & 0xff;
272 }
273 
274 /* graphic structures */
275 static struct GfxLayout charlayout_1_bit =
276 {
277 	8,8,	/* 8*8 characters */
278 	128,	/* 128 characters */
279 	1,  	/* 1 bit per pixel */
280 	{ 0 },
281 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
282 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
283 	8*8	/* every char takes 8 consecutive bytes */
284 };
285 
286 static struct GfxLayout charlayout_3_bit =
287 {
288 	8,8,	/* 8*8 characters */
289 	128,	/* 128 characters */
290 	3,  	/* 3 bit per pixel */
291 	{ 0, 128*8*8, 128*8*8 + 128*8*8 },    /* offset for each bitplane */
292 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
293 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
294 	8*8	/* every char takes 8 consecutive bytes */
295 };
296 
297 static struct GfxDecodeInfo gfxdecodeinfo[] =
298 {
299 	{ REGION_CPU1, 0xe800, &charlayout_1_bit, 0, 1 },
300 	{ REGION_CPU1, 0xec00, &charlayout_3_bit, 2, 1 },
301 	{ -1 }	/* end of array */
302 };
303 
304 
305 /* the machine driver */
306 
307 static MACHINE_DRIVER_START( polyplay )
308 
309 	/* basic machine hardware */
310 	MDRV_CPU_ADD(Z80, 9830400/4)
MDRV_CPU_MEMORY(polyplay_readmem,polyplay_writemem)311 	MDRV_CPU_MEMORY(polyplay_readmem,polyplay_writemem)
312 	MDRV_CPU_PORTS(readport_polyplay,writeport_polyplay)
313 	MDRV_CPU_PERIODIC_INT(periodic_interrupt,75)
314 	MDRV_CPU_VBLANK_INT(coin_interrupt,1)
315 
316 	MDRV_FRAMES_PER_SECOND(50)
317 
318 	MDRV_MACHINE_INIT(polyplay)
319 
320 	/* video hardware */
321 	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
322 	MDRV_SCREEN_SIZE(64*8, 32*8)
323 	MDRV_VISIBLE_AREA(0*8, 64*8-1, 0*8, 32*8-1)
324 	MDRV_GFXDECODE(gfxdecodeinfo)
325 	MDRV_PALETTE_LENGTH(10)
326 
327 	MDRV_PALETTE_INIT(polyplay)
328 	MDRV_VIDEO_START(generic)
329 	MDRV_VIDEO_UPDATE(polyplay)
330 
331 	/* sound hardware */
332 	MDRV_SOUND_ADD(CUSTOM, custom_interface)
333 MACHINE_DRIVER_END
334 
335 
336 /* ROM loading and mapping */
337 ROM_START( polyplay )
338 	ROM_REGION( 0x10000, REGION_CPU1, 0 )	/* 64k for code */
339 	ROM_LOAD( "cpu_0000.37",       0x0000, 0x0400, CRC(87884c5f) SHA1(849c6b3f40496c694a123d6eec268a7128c037f0) )
340 	ROM_LOAD( "cpu_0400.36",       0x0400, 0x0400, CRC(d5c84829) SHA1(baa8790e77db66e1e543b3a0e5390cc71256de2f) )
341 	ROM_LOAD( "cpu_0800.35",       0x0800, 0x0400, CRC(5f36d08e) SHA1(08ecf8143e818a9844b4f168e68629d6d4481a8a) )
342 	ROM_LOAD( "2_-_1000.14",       0x1000, 0x0400, CRC(950dfcdb) SHA1(74170d5c99d1ea61fe37d1fe023dca96efb1ca69) )
343 	ROM_LOAD( "2_-_1400.10",       0x1400, 0x0400, CRC(829f74ca) SHA1(4df9d3c24e1bc4c2c953dce9530e43a00ecf67fc) )
344 	ROM_LOAD( "2_-_1800.6",        0x1800, 0x0400, CRC(b69306f5) SHA1(66d7c3cf76782a5b6eafa3e1513ecc9a9df0e0e1) )
345 	ROM_LOAD( "2_-_1c00.2",        0x1c00, 0x0400, CRC(aede2280) SHA1(0a01394ab70d07d666e955c87a08cb4d4945767e) )
346 	ROM_LOAD( "2_-_2000.15",       0x2000, 0x0400, CRC(6c7ad0d8) SHA1(df959d1e43fde96b5e21e3c53b397209a98ea423) )
347 	ROM_LOAD( "2_-_2400.11",       0x2400, 0x0400, CRC(bc7462f0) SHA1(01ca680c74b92b9ba5a85f98e0933ef1e754bfc1) )
348 	ROM_LOAD( "2_-_2800.7",        0x2800, 0x0400, CRC(9ccf1958) SHA1(6bdf04d7796074af7327fab6717b52736540f97c) )
349 	ROM_LOAD( "2_-_2c00.3",        0x2c00, 0x0400, CRC(21827930) SHA1(71d27d68f6973a59996102381f8754d9b353c65a) )
350 	ROM_LOAD( "2_-_3000.16",       0x3000, 0x0400, CRC(b3b3c0ec) SHA1(a94cd9794d59ea2f9ddd8bef86e6e3a269b276ad) )
351 	ROM_LOAD( "2_-_3400.12",       0x3400, 0x0400, CRC(bd416cd0) SHA1(57391cc4a417468455b45014969067629fd629b8) )
352 	ROM_LOAD( "2_-_3800.8",        0x3800, 0x0400, CRC(1c470b7c) SHA1(f7c71ee1752ecd4f30a35f14ee392b37febefb9c) )
353 	ROM_LOAD( "2_-_3c00.4",        0x3c00, 0x0400, CRC(b8354a19) SHA1(58ea7798ecc1be987b1217f4078c7cb366622dd3) )
354 	ROM_LOAD( "2_-_4000.17",       0x4000, 0x0400, CRC(1e01041e) SHA1(ff63e4bb924d1c26e445a28c5f8cbc696b4b9f5a) )
355 	ROM_LOAD( "2_-_4400.13",       0x4400, 0x0400, CRC(fe4d8959) SHA1(233f97956f4c819558d5d38034d92edc0e86a0de) )
356 	ROM_LOAD( "2_-_4800.9",        0x4800, 0x0400, CRC(c45f1d9d) SHA1(f3373f1f5a3c6099fd38e65f66e024ef042a984c) )
357 	ROM_LOAD( "2_-_4c00.5",        0x4c00, 0x0400, CRC(26950ad6) SHA1(881f5f0f4806ba6f21d0b28a70fc43363d51419b) )
358 	ROM_LOAD( "1_-_5000.30",       0x5000, 0x0400, CRC(9f5e2ba1) SHA1(58c696afbda8932f5e401b0a82b2de5cdfc2d1fb) )
359 	ROM_LOAD( "1_-_5400.26",       0x5400, 0x0400, CRC(b5f9a780) SHA1(eb785b7668f6af0a9df84cbd1905173869377e6c) )
360 	ROM_LOAD( "1_-_5800.22",       0x5800, 0x0400, CRC(d973ad12) SHA1(81cc5e19e83f2e5b10b885583c250a2ff66bafe5) )
361 	ROM_LOAD( "1_-_5c00.18",       0x5c00, 0x0400, CRC(9c22ea79) SHA1(e25ed745589a83e297dba936a6e5979f1b31b2d5) )
362 	ROM_LOAD( "1_-_6000.31",       0x6000, 0x0400, CRC(245c49ca) SHA1(12e5a032327fb45b2a240aff11b0c5d1798932f4) )
363 	ROM_LOAD( "1_-_6400.27",       0x6400, 0x0400, CRC(181e427e) SHA1(6b65409cd8410e632093662f5de2989dd9134620) )
364 	ROM_LOAD( "1_-_6800.23",       0x6800, 0x0400, CRC(8a6c1f97) SHA1(bf9d4dda8ac933a4a700f52540dcd1197f0a64eb) )
365 	ROM_LOAD( "1_-_6c00.19",       0x6c00, 0x0400, CRC(77901dc9) SHA1(b1132e06011aa8f7a95c43f447cd422f01139bb1) )
366 	ROM_LOAD( "1_-_7000.32",       0x7000, 0x0400, CRC(83ffbe57) SHA1(1e06408f7b4c9a4e5cadab58f6efbc03a5bedc1e) )
367 	ROM_LOAD( "1_-_7400.28",       0x7400, 0x0400, CRC(e2a66531) SHA1(1c9eb54e9c8a13f26335d8fb79fe5e39c28b3255) )
368 	ROM_LOAD( "1_-_7800.24",       0x7800, 0x0400, CRC(1d0803ef) SHA1(15a1996f9262f26cf531f329e086b10b3c25ce92) )
369 	ROM_LOAD( "1_-_7c00.20",       0x7c00, 0x0400, CRC(17dfa7e4) SHA1(afb471dc6cb2faccfb4305540f75162fcee3d622) )
370 	ROM_LOAD( "1_-_8000.33",       0x8000, 0x0400, CRC(6ee02375) SHA1(fbf797b655639ee442804a30fd3a06bbf261999a) )
371 	ROM_LOAD( "1_-_8400.29",       0x8400, 0x0400, CRC(9db09598) SHA1(8eb385542a617b23caad3ce7bbdd9714c1dd684f) )
372 	ROM_LOAD( "1_-_8800.25",       0x8800, 0x0400, CRC(ca2f963f) SHA1(34295f02bfd1bca141d650bbbbc1989e01c67b2f) )
373 	ROM_LOAD( "1_-_8c00.21",       0x8c00, 0x0400, CRC(0c7dec2d) SHA1(48d776b97c1eca851f89b0c5df4d5765d9aa0319) )
374 	ROM_LOAD( "char.1",            0xe800, 0x0400, CRC(5242dd6b) SHA1(ba8f317df62fe4360757333215ce3c8223c68c4e) )
375 ROM_END
376 
377 
378 static void timer_callback(int param)
379 {
380 	cpu_set_irq_line_and_vector(0, 0, HOLD_LINE, 0x4c);
381 }
382 
383 /* game driver */
384 GAME( 1985, polyplay, 0, polyplay, polyplay, 0, ROT0, "VEB Polytechnik Karl-Marx-Stadt", "Poly-Play" )
385