1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4
5 The following Namco custom chips are all instances of the same 4-bit MCU,
6 the Fujitsu MB8843 (42-pin DIP package) and MB8842/MB8844 (28-pin DIP),
7 differently programmed.
8
9 chip MCU pins function
10 ---- ------ ---- --------
11 56XX 42 I/O (coin management built-in)
12 58XX 42 I/O (coin management built-in)
13 62XX 28 I/O and explosion (noise) generator
14
15 16XX interface:
16 ---------------
17 Super Pac Man 56XX 56XX ---- ----
18 Pac & Pal 56XX 59XX ---- ----
19 Mappy 58XX 58XX ---- ----
20 Phozon 58XX 56XX ---- ----
21 The Tower of Druaga 58XX 56XX ---- ----
22 Grobda 58XX 56XX ---- ----
23 Dig Dug II 58XX 56XX ---- ----
24 Motos 56XX 56XX ---- ----
25 Gaplus 56XX 58XX 62XX ----
26 Gaplus (alt.) 58XX 56XX 62XX ----
27 Libble Rabble 58XX 56XX 56XX ----
28 Toy Pop 58XX 56XX 56XX ----
29
30
31 Pinouts:
32
33 MB8843 MB8842/MB8844
34 +------+ +------+
35 EXTAL|1 42|Vcc EXTAL|1 28|Vcc
36 XTAL|2 41|K3 XTAL|2 27|K3
37 /RESET|3 40|K2 /RESET|3 26|K2
38 /IRQ|4 39|K1 O0|4 25|K1
39 SO|5 38|K0 O1|5 24|K0
40 SI|6 37|R15 O2|6 23|R10 /IRQ
41 /SC /TO|7 36|R14 O3|7 22|R9 /TC
42 /TC|8 35|R13 O4|8 21|R8
43 P0|9 34|R12 O5|9 20|R7
44 P1|10 33|R11 O6|10 19|R6
45 P2|11 32|R10 O7|11 18|R5
46 P3|12 31|R9 R0|12 17|R4
47 O0|13 30|R8 R1|13 16|R3
48 O1|14 29|R7 GND|14 15|R2
49 O2|15 28|R6 +------+
50 O3|16 27|R5
51 O4|17 26|R4
52 O5|18 25|R3
53 O6|19 24|R2
54 O7|20 23|R1
55 GND|21 22|R0
56 +------+
57
58
59 O O R R R K
60 62XX O O IO O I
61
62 P O O R R R R K
63 56XX O O O I I I IO I
64 58XX O O O I I I IO I
65 59XX O O O I I I IO I
66
67
68 Namco custom I/O chips 56XX, 58XX, 59XX
69
70 These chips work together with a 16XX, that interfaces them with the buffer
71 RAM. Each chip uses 16 nibbles of memory; the 16XX supports up to 4 chips,
72 but most games use only 2.
73
74 The 56XX, 58XX and 59XX are pin-to-pin compatible, but not functionally equivalent:
75 they provide the same functions, but the command codes and memory addresses
76 are different, so they cannot be exchanged.
77
78 The devices have 42 pins. There are 16 input lines and 8 output lines to be
79 used for I/O.
80
81
82 pin description
83 --- -----------
84 1 clock (Mappy, Super Pac-Man)
85 2 clock (Gaplus; equivalent to the above?)
86 3 reset
87 4 irq
88 5-6 (to/from 16XX) (this is probably a normal I/O port used to synchronize with the 16XX)
89 7-8 ?
90 9-12 address to r/w from RAM; 12 also goes to the 16XX and acts as r/w line, so
91 the chip can only read from addresses 0-7 and only write to addresses 8-F
92 (this is probably a normal I/O port used for that purpose)
93 13-16 out port A
94 17-20 out port B
95 21 GND
96 22-25 in port B
97 26-29 in port C
98 30-33 in port D
99 34-37 (to 16XX) probably data to r/w from RAM
100 (this is probably a normal I/O port used for that purpose)
101 38-41 in port A
102 42 Vcc
103
104 TODO:
105 - It's likely that the 56XX and 58XX chips, when in "coin mode", also internally
106 handle outputs for start lamps, coin counters and coin lockout, like the 51XX.
107 Such lines are NOT present in the Mappy and Super Pacman schematics, so they
108 were probably not used for those games, but they might have been used in
109 others (most likely Gaplus).
110
111 ***************************************************************************/
112
113 #include "burnint.h"
114 #include "namcoio.h"
115 #include "driver.h"
116
117 struct ChipData
118 {
119 UINT8 (*in_0_cb)(UINT8);
120 UINT8 (*in_1_cb)(UINT8);
121 UINT8 (*in_2_cb)(UINT8);
122 UINT8 (*in_3_cb)(UINT8);
123 void (*out_0_cb)(UINT8, UINT8);
124 void (*out_1_cb)(UINT8, UINT8);
125 void (*run_func)(INT32);
126 INT32 type;
127
128 UINT8 ram[16];
129 INT32 reset;
130 INT32 lastcoins;
131 INT32 lastbuttons;
132 INT32 credits;
133 INT32 coins[2];
134 INT32 coins_per_cred[2];
135 INT32 creds_per_coin[2];
136 INT32 in_count;
137 };
138
139 static struct ChipData Chips[5];
140
fakeIn(UINT8)141 static UINT8 fakeIn(UINT8) { return 0; }
fakeOut(UINT8,UINT8)142 static void fakeOut(UINT8,UINT8) { }
143
namcoio_init(INT32 chip,INT32 type,UINT8 (* in0)(UINT8),UINT8 (* in1)(UINT8),UINT8 (* in2)(UINT8),UINT8 (* in3)(UINT8),void (* out0)(UINT8,UINT8),void (* out1)(UINT8,UINT8))144 void namcoio_init(INT32 chip, INT32 type, UINT8 (*in0)(UINT8), UINT8 (*in1)(UINT8), UINT8 (*in2)(UINT8), UINT8 (*in3)(UINT8), void (*out0)(UINT8, UINT8), void (*out1)(UINT8, UINT8))
145 {
146 ChipData *ptr = &Chips[chip];
147
148 ptr->type = type;
149
150 ptr->in_0_cb = (in0 == NULL) ? fakeIn : in0;
151 ptr->in_1_cb = (in1 == NULL) ? fakeIn : in1;
152 ptr->in_2_cb = (in2 == NULL) ? fakeIn : in2;
153 ptr->in_3_cb = (in3 == NULL) ? fakeIn : in3;
154 ptr->out_0_cb = (out0 == NULL) ? fakeOut : out0;
155 ptr->out_1_cb = (out1 == NULL) ? fakeOut : out1;
156
157 switch (type)
158 {
159 case NAMCO56xx: ptr->run_func = namco56xx_customio_run; break;
160 case NAMCO58xx: ptr->run_func = namco58xx_customio_run; break;
161 case NAMCO59xx: ptr->run_func = namco59xx_customio_run; break;
162 }
163 }
164
165 //-------------------------------------------------
166 // device_reset - device-specific reset
167 //-------------------------------------------------
168
namcoio_set_reset_line(INT32 chip,INT32 state)169 void namcoio_set_reset_line(INT32 chip, INT32 state)
170 {
171 ChipData *ptr = &Chips[chip];
172
173 ptr->reset = (state == ASSERT_LINE) ? 1 : 0;
174 if (state != CLEAR_LINE)
175 {
176 /* reset internal registers */
177 ptr->credits = 0;
178 ptr->coins[0] = 0;
179 ptr->coins_per_cred[0] = 1;
180 ptr->creds_per_coin[0] = 1;
181 ptr->coins[1] = 0;
182 ptr->coins_per_cred[1] = 1;
183 ptr->creds_per_coin[1] = 1;
184 ptr->in_count = 0;
185 }
186 }
187
namcoio_reset(INT32 chip)188 void namcoio_reset(INT32 chip)
189 {
190 namcoio_set_reset_line(chip, ASSERT_LINE);
191 namcoio_set_reset_line(chip, CLEAR_LINE);
192 }
193
194 /*****************************************************************************
195 DEVICE HANDLERS
196 *****************************************************************************/
197
198 #define IORAM_READ(offset) (ptr->ram[offset] & 0x0f)
199 #define IORAM_WRITE(offset,data) {ptr->ram[offset] = (data) & 0x0f;}
200
handle_coins(INT32 chip,int swap)201 static void handle_coins( INT32 chip, int swap )
202 {
203 int val, toggled;
204 int credit_add = 0;
205 int credit_sub = 0;
206 int button;
207
208 ChipData *ptr = &Chips[chip];
209
210 val = ~ptr->in_0_cb(0 & 0x0f); // pins 38-41
211 toggled = val ^ ptr->lastcoins;
212 ptr->lastcoins = val;
213
214 /* check coin insertion */
215 if (val & toggled & 0x01)
216 {
217 ptr->coins[0]++;
218 if (ptr->coins[0] >= (ptr->coins_per_cred[0] & 7))
219 {
220 credit_add = ptr->creds_per_coin[0] - (ptr->coins_per_cred[0] >> 3);
221 ptr->coins[0] -= ptr->coins_per_cred[0] & 7;
222 }
223 else if (ptr->coins_per_cred[0] & 8)
224 credit_add = 1;
225 }
226 if (val & toggled & 0x02)
227 {
228 ptr->coins[1]++;
229 if (ptr->coins[1] >= (ptr->coins_per_cred[1] & 7))
230 {
231 credit_add = ptr->creds_per_coin[1] - (ptr->coins_per_cred[1] >> 3);
232 ptr->coins[1] -= ptr->coins_per_cred[1] & 7;
233 }
234 else if (ptr->coins_per_cred[1] & 8)
235 credit_add = 1;
236 }
237 if (val & toggled & 0x08)
238 {
239 credit_add = 1;
240 }
241
242 val = ~ptr->in_3_cb(0 & 0x0f); // pins 30-33
243 toggled = val ^ ptr->lastbuttons;
244 ptr->lastbuttons = val;
245
246 /* check start buttons, only if the game allows */
247 if (IORAM_READ(9) == 0)
248 // the other argument is IORAM_READ(10) = 1, meaning unknown
249 {
250 if (val & toggled & 0x04)
251 {
252 if (ptr->credits >= 1) credit_sub = 1;
253 }
254 else if (val & toggled & 0x08)
255 {
256 if (ptr->credits >= 2) credit_sub = 2;
257 }
258 }
259
260 ptr->credits += credit_add - credit_sub;
261
262 IORAM_WRITE(0 ^ swap, ptr->credits / 10); // BCD credits
263 IORAM_WRITE(1 ^ swap, ptr->credits % 10); // BCD credits
264 IORAM_WRITE(2 ^ swap, credit_add); // credit increment (coin inputs)
265 IORAM_WRITE(3 ^ swap, credit_sub); // credit decrement (start buttons)
266 IORAM_WRITE(4, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25
267 button = ((val & 0x05) << 1) | (val & toggled & 0x05);
268 IORAM_WRITE(5, button); // pins 30 & 32 normal and impulse
269 IORAM_WRITE(6, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29
270 button = (val & 0x0a) | ((val & toggled & 0x0a) >> 1);
271 IORAM_WRITE(7, button); // pins 31 & 33 normal and impulse
272 }
273
274
namco56xx_customio_run(INT32 chip)275 void namco56xx_customio_run(INT32 chip)
276 {
277 ChipData *ptr = &Chips[chip];
278
279 switch (IORAM_READ(8))
280 {
281 case 1: // read switch inputs
282 IORAM_WRITE(0, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41
283 IORAM_WRITE(1, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25
284 IORAM_WRITE(2, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29
285 IORAM_WRITE(3, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33
286 ptr->out_0_cb((UINT8)0, IORAM_READ(9)); // output to pins 13-16 (motos, pacnpal, gaplus)
287 ptr->out_1_cb((UINT8)0, IORAM_READ(10)); // output to pins 17-20 (gaplus)
288 break;
289
290 case 2: // initialize coinage settings
291 ptr->coins_per_cred[0] = IORAM_READ(9);
292 ptr->creds_per_coin[0] = IORAM_READ(10);
293 ptr->coins_per_cred[1] = IORAM_READ(11);
294 ptr->creds_per_coin[1] = IORAM_READ(12);
295 break;
296
297 case 4:
298 handle_coins(chip,0);
299 break;
300
301 case 7: // bootup check (liblrabl only)
302 {
303 IORAM_WRITE(2, 0xe);
304 IORAM_WRITE(7, 0x6);
305 }
306 break;
307
308 case 8: // bootup check
309 {
310 int i, sum;
311
312 sum = 0;
313 for (i = 9; i < 16; i++)
314 sum += IORAM_READ(i);
315 IORAM_WRITE(0, sum >> 4);
316 IORAM_WRITE(1, sum & 0xf);
317 }
318 break;
319
320 case 9: // read dip switches and inputs
321 ptr->out_0_cb((UINT8)0, 0 & 0x0f); // set pin 13 = 0
322 IORAM_WRITE(0, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41, pin 13 = 0
323 IORAM_WRITE(2, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25, pin 13 = 0
324 IORAM_WRITE(4, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29, pin 13 = 0
325 IORAM_WRITE(6, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33, pin 13 = 0
326 ptr->out_0_cb((UINT8)0, 1 & 0x0f); // set pin 13 = 1
327 IORAM_WRITE(1, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41, pin 13 = 1
328 IORAM_WRITE(3, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25, pin 13 = 1
329 IORAM_WRITE(5, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29, pin 13 = 1
330 IORAM_WRITE(7, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33, pin 13 = 1
331 break;
332 }
333 }
334
namco59xx_customio_run(INT32 chip)335 void namco59xx_customio_run(INT32 chip)
336 {
337 ChipData *ptr = &Chips[chip];
338
339 switch (IORAM_READ(8))
340 {
341 case 3: // pacnpal chip #1: read dip switches and inputs
342 IORAM_WRITE(4, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41, pin 13 = 0 ?
343 IORAM_WRITE(5, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29 ?
344 IORAM_WRITE(6, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25 ?
345 IORAM_WRITE(7, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33
346 break;
347 }
348 }
349
namco58xx_customio_run(INT32 chip)350 void namco58xx_customio_run(INT32 chip)
351 {
352 ChipData *ptr = &Chips[chip];
353
354 switch (IORAM_READ(8))
355 {
356 case 1: // read switch inputs
357 IORAM_WRITE(4, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41
358 IORAM_WRITE(5, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25
359 IORAM_WRITE(6, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29
360 IORAM_WRITE(7, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33
361 ptr->out_0_cb((UINT8)0, IORAM_READ(9)); // output to pins 13-16 (toypop)
362 ptr->out_1_cb((UINT8)0, IORAM_READ(10)); // output to pins 17-20 (toypop)
363 break;
364
365 case 2: // initialize coinage settings
366 ptr->coins_per_cred[0] = IORAM_READ(9);
367 ptr->creds_per_coin[0] = IORAM_READ(10);
368 ptr->coins_per_cred[1] = IORAM_READ(11);
369 ptr->creds_per_coin[1] = IORAM_READ(12);
370 break;
371
372 case 3: // process coin and start inputs, read switch inputs
373 handle_coins(chip,2);
374 break;
375
376 case 4: // read dip switches and inputs
377 ptr->out_0_cb((UINT8)0, 0 & 0x0f); // set pin 13 = 0
378 IORAM_WRITE(0, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41, pin 13 = 0
379 IORAM_WRITE(2, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25, pin 13 = 0
380 IORAM_WRITE(4, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29, pin 13 = 0
381 IORAM_WRITE(6, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33, pin 13 = 0
382 ptr->out_0_cb((UINT8)0, 1 & 0x0f); // set pin 13 = 1
383 IORAM_WRITE(1, ~ptr->in_0_cb(0 & 0x0f)); // pins 38-41, pin 13 = 1
384 IORAM_WRITE(3, ~ptr->in_1_cb(0 & 0x0f)); // pins 22-25, pin 13 = 1
385 IORAM_WRITE(5, ~ptr->in_2_cb(0 & 0x0f)); // pins 26-29, pin 13 = 1
386 IORAM_WRITE(7, ~ptr->in_3_cb(0 & 0x0f)); // pins 30-33, pin 13 = 1
387 break;
388
389 case 5: // bootup check
390 {
391 int i, n, rng, seed;
392 #define NEXT(n) ((((n) & 1) ? (n) ^ 0x90 : (n)) >> 1)
393
394 /* initialize the LFSR depending on the first two arguments */
395 n = (IORAM_READ(9) * 16 + IORAM_READ(10)) & 0x7f;
396 seed = 0x22;
397 for (i = 0; i < n; i++)
398 seed = NEXT(seed);
399
400 /* calculate the answer */
401 for (i = 1; i < 8; i++)
402 {
403 n = 0;
404 rng = seed;
405 if (rng & 1) { n ^= ~IORAM_READ(11); }
406 rng = NEXT(rng);
407 seed = rng; // save state for next loop
408 if (rng & 1) { n ^= ~IORAM_READ(10); }
409 rng = NEXT(rng);
410 if (rng & 1) { n ^= ~IORAM_READ(9); }
411 rng = NEXT(rng);
412 if (rng & 1) { n ^= ~IORAM_READ(15); }
413 rng = NEXT(rng);
414 if (rng & 1) { n ^= ~IORAM_READ(14); }
415 rng = NEXT(rng);
416 if (rng & 1) { n ^= ~IORAM_READ(13); }
417 rng = NEXT(rng);
418 if (rng & 1) { n ^= ~IORAM_READ(12); }
419
420 IORAM_WRITE(i, ~n);
421 }
422 IORAM_WRITE(0, 0x0);
423 /* kludge for gaplus */
424 if (IORAM_READ(9) == 0xf) IORAM_WRITE(0, 0xf);
425 }
426 break;
427 }
428 }
429
namcoio_run(INT32 chip)430 void namcoio_run(INT32 chip)
431 {
432 ChipData *ptr = &Chips[chip];
433
434 ptr->run_func(chip);
435 }
436
namcoio_read(INT32 chip,UINT8 offset)437 UINT8 namcoio_read(INT32 chip, UINT8 offset)
438 {
439 ChipData *ptr = &Chips[chip];
440
441 // RAM is 4-bit wide; Pac & Pal requires the | 0xf0 otherwise Easter egg doesn't work
442 offset &= 0x3f;
443
444 return 0xf0 | ptr->ram[offset];
445 }
446
namcoio_write(INT32 chip,UINT8 offset,UINT8 data)447 void namcoio_write(INT32 chip, UINT8 offset, UINT8 data)
448 {
449 ChipData *ptr = &Chips[chip];
450
451 offset &= 0x3f;
452 data &= 0x0f; // RAM is 4-bit wide
453
454 ptr->ram[offset] = data;
455 }
456
namcoio_read_reset_line(INT32 chip)457 UINT8 namcoio_read_reset_line(INT32 chip)
458 {
459 ChipData *ptr = &Chips[chip];
460
461 return ptr->reset;
462 }
463
namcoio_scan(INT32 chip)464 INT32 namcoio_scan(INT32 chip)
465 {
466 ChipData *ptr = &Chips[chip];
467
468 SCAN_VAR(ptr->ram);
469 SCAN_VAR(ptr->reset);
470 SCAN_VAR(ptr->lastcoins);
471 SCAN_VAR(ptr->lastbuttons);
472 SCAN_VAR(ptr->coins);
473 SCAN_VAR(ptr->credits);
474 SCAN_VAR(ptr->coins_per_cred);
475 SCAN_VAR(ptr->creds_per_coin);
476 SCAN_VAR(ptr->in_count);
477
478 return 0;
479 }
480