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