1 // The New Zealand Story protection module
2 // Based on MAME version 0.67 mcu simulation
3
4 #include "burnint.h"
5 #include "tnzs_prot.h"
6
7 #define UNLOCK 0x0f
8 #define LOCK 0x0c
9
10 static INT32 mcu_type;
11
12 static INT32 mcu_initializing;
13 static INT32 mcu_coinage_init;
14 static INT32 mcu_command,mcu_readcredits;
15 static INT32 mcu_reportcoin;
16 static UINT8 mcu_coinage[4];
17 static UINT8 mcu_coinsA;
18 static UINT8 mcu_coinsB;
19 static UINT8 mcu_credits;
20 static UINT8 mcu_coin_lockout;
21
22 UINT8 *tnzs_mcu_inputs;
23
tnzs_mcu_reset()24 void tnzs_mcu_reset()
25 {
26 mcu_initializing = 3;
27 mcu_coinage_init = 0;
28 mcu_coinage[0] = 1;
29 mcu_coinage[1] = 1;
30 mcu_coinage[2] = 1;
31 mcu_coinage[3] = 1;
32 mcu_coinsA = 0;
33 mcu_coinsB = 0;
34 mcu_credits = 0;
35 mcu_reportcoin = 0;
36 mcu_command = 0;
37 mcu_coin_lockout = LOCK;
38 }
39
tnzs_mcu_init(INT32 type)40 void tnzs_mcu_init(INT32 type)
41 {
42 tnzs_mcu_reset();
43 mcu_type = type;
44 }
45
mcu_handle_coins(INT32 coin)46 static void mcu_handle_coins(INT32 coin)
47 {
48 static INT32 insertcoin;
49
50 if (coin & 0x08)
51 mcu_reportcoin = coin;
52 else if (coin && coin != insertcoin)
53 {
54 if (coin & 0x01)
55 {
56 mcu_coinsA++;
57 if (mcu_coinsA >= mcu_coinage[0])
58 {
59 mcu_coinsA -= mcu_coinage[0];
60 mcu_credits += mcu_coinage[1];
61 if (mcu_credits >= 9)
62 {
63 mcu_credits = 9;
64 mcu_coin_lockout = LOCK;
65 }
66 else
67 {
68 mcu_coin_lockout = UNLOCK;
69 }
70 }
71 }
72 if (coin & 0x02)
73 {
74 mcu_coinsB++;
75 if (mcu_coinsB >= mcu_coinage[2])
76 {
77 mcu_coinsB -= mcu_coinage[2];
78 mcu_credits += mcu_coinage[3];
79 if (mcu_credits >= 9)
80 {
81 mcu_credits = 9;
82 mcu_coin_lockout = LOCK;
83 }
84 else
85 {
86 mcu_coin_lockout = UNLOCK;
87 }
88 }
89 }
90 if (coin & 0x04)
91 {
92 mcu_credits++;
93 }
94 mcu_reportcoin = coin;
95 }
96 else
97 {
98 if (mcu_credits < 9)
99 mcu_coin_lockout = UNLOCK;
100 mcu_reportcoin = 0;
101 }
102 insertcoin = coin;
103 }
104
mcu_arknoid2_r(INT32 offset)105 static UINT8 mcu_arknoid2_r(INT32 offset)
106 {
107 const char *mcu_startup = "\x55\xaa\x5a";
108
109 if (offset == 0)
110 {
111 if (mcu_initializing)
112 {
113 mcu_initializing--;
114 return mcu_startup[2 - mcu_initializing];
115 }
116
117 switch (mcu_command)
118 {
119 case 0x41:
120 return mcu_credits;
121
122 case 0xc1:
123 if (mcu_readcredits == 0)
124 {
125 mcu_readcredits = 1;
126 if (mcu_reportcoin & 0x08)
127 {
128 mcu_initializing = 3;
129 return 0xee;
130 }
131 else return mcu_credits;
132 }
133 else return tnzs_mcu_inputs[0];
134
135 default:
136 return 0xff;
137 break;
138 }
139 }
140 else
141 {
142 if (mcu_reportcoin & 0x08) return 0xe1;
143 if (mcu_reportcoin & 0x01) return 0x11;
144 if (mcu_reportcoin & 0x02) return 0x21;
145 if (mcu_reportcoin & 0x04) return 0x31;
146 return 0x01;
147 }
148 }
149
mcu_arknoid2_w(INT32 offset,INT32 data)150 static void mcu_arknoid2_w(INT32 offset, INT32 data)
151 {
152 if (offset == 0)
153 {
154 if (mcu_command == 0x41)
155 {
156 mcu_credits = (mcu_credits + data) & 0xff;
157 }
158 }
159 else
160 {
161 if (mcu_initializing)
162 {
163 mcu_coinage[mcu_coinage_init++] = data;
164 if (mcu_coinage_init == 4) mcu_coinage_init = 0;
165 }
166
167 if (data == 0xc1)
168 mcu_readcredits = 0;
169
170 if (data == 0x15)
171 mcu_credits = (mcu_credits - 1) & 0xff;
172
173 mcu_command = data;
174 }
175 }
176
mcu_chukatai_r(INT32 offset)177 static UINT8 mcu_chukatai_r(INT32 offset)
178 {
179 const char *mcu_startup = "\xa5\x5a\xaa";
180
181 if (offset == 0)
182 {
183 if (mcu_initializing)
184 {
185 mcu_initializing--;
186 return mcu_startup[2 - mcu_initializing];
187 }
188
189 switch (mcu_command)
190 {
191 case 0x1f:
192 return (tnzs_mcu_inputs[2] >> 4) ^ 0x0f;
193
194 case 0x03:
195 return tnzs_mcu_inputs[2] & 0x0f;
196
197 case 0x41:
198 return mcu_credits;
199
200 case 0x93:
201 if (mcu_readcredits == 0)
202 {
203 mcu_readcredits += 1;
204 if (mcu_reportcoin & 0x08)
205 {
206 mcu_initializing = 3;
207 return 0xee;
208 }
209 else return mcu_credits;
210 }
211
212 if (mcu_readcredits == 1)
213 {
214 mcu_readcredits += 1;
215 return tnzs_mcu_inputs[0];
216 }
217
218 if (mcu_readcredits == 2)
219 {
220 return tnzs_mcu_inputs[1];
221 }
222
223 default:
224 return 0xff;
225 break;
226 }
227 }
228 else
229 {
230 if (mcu_reportcoin & 0x08) return 0xe1;
231 if (mcu_reportcoin & 0x01) return 0x11;
232 if (mcu_reportcoin & 0x02) return 0x21;
233 if (mcu_reportcoin & 0x04) return 0x31;
234 return 0x01;
235 }
236 }
237
mcu_chukatai_w(INT32 offset,INT32 data)238 static void mcu_chukatai_w(INT32 offset, INT32 data)
239 {
240 if (offset == 0)
241 {
242 if (mcu_command == 0x41)
243 {
244 mcu_credits = (mcu_credits + data) & 0xff;
245 }
246 }
247 else
248 {
249 if (mcu_initializing)
250 {
251 mcu_coinage[mcu_coinage_init++] = data;
252 if (mcu_coinage_init == 4) mcu_coinage_init = 0;
253 }
254
255 if (data == 0x93)
256 mcu_readcredits = 0;
257
258 mcu_command = data;
259 }
260 }
261
mcu_tnzs_r(INT32 offset)262 static UINT8 mcu_tnzs_r(INT32 offset)
263 {
264 const char *mcu_startup = "\x5a\xa5\x55";
265
266 if (offset == 0)
267 {
268 if (mcu_initializing)
269 {
270 mcu_initializing--;
271 return mcu_startup[2 - mcu_initializing];
272 }
273
274 switch (mcu_command)
275 {
276 case 0x01:
277 return ~tnzs_mcu_inputs[0];
278
279 case 0x02:
280 return ~tnzs_mcu_inputs[1];
281
282 case 0x1a:
283 if (mcu_type == MCU_DRTOPPEL) return (tnzs_mcu_inputs[2] >> 2) ^ 0x03;
284 return tnzs_mcu_inputs[2] >> 4;
285
286 case 0x21:
287 return tnzs_mcu_inputs[2] & 0x0f;
288
289 case 0x41:
290 return mcu_credits;
291
292 case 0xa0:
293 if (mcu_reportcoin & 0x08)
294 {
295 mcu_initializing = 3;
296 return 0xee;
297 }
298 else return mcu_credits;
299
300 case 0xa1:
301 if (mcu_readcredits == 0)
302 {
303 mcu_readcredits = 1;
304 if (mcu_reportcoin & 0x08)
305 {
306 mcu_initializing = 3;
307 return 0xee;
308 }
309 else return mcu_credits;
310 }
311 else
312 return ~((tnzs_mcu_inputs[0] & 0xf0) | ((tnzs_mcu_inputs[1] >> 4) & 0x0f));
313
314 default:
315 return 0xff;
316 break;
317 }
318 }
319 else
320 {
321 if (mcu_reportcoin & 0x08) return 0xe1;
322
323 if (mcu_type == MCU_TNZS)
324 {
325 if (mcu_reportcoin & 0x01) return 0x31;
326 if (mcu_reportcoin & 0x02) return 0x21;
327 if (mcu_reportcoin & 0x04) return 0x11;
328 }
329 else
330 {
331 if (mcu_reportcoin & 0x01) return 0x11;
332 if (mcu_reportcoin & 0x02) return 0x21;
333 if (mcu_reportcoin & 0x04) return 0x31;
334 }
335 return 0x01;
336 }
337 }
338
mcu_tnzs_w(INT32 offset,INT32 data)339 static void mcu_tnzs_w(INT32 offset, INT32 data)
340 {
341 if (offset == 0) {
342 if (mcu_command == 0x41) {
343 mcu_credits = (mcu_credits + data) & 0xff;
344 }
345 }
346 else
347 {
348 if (mcu_initializing)
349 {
350 mcu_coinage[mcu_coinage_init++] = data;
351 if (mcu_coinage_init == 4) mcu_coinage_init = 0;
352 }
353
354 if (data == 0xa1)
355 mcu_readcredits = 0;
356
357 if ((data == 0x09) && (mcu_type == MCU_DRTOPPEL || mcu_type == MCU_PLUMPOP))
358 mcu_credits = (mcu_credits - 1) & 0xff;
359
360 if ((data == 0x18) && (mcu_type == MCU_DRTOPPEL || mcu_type == MCU_PLUMPOP))
361 mcu_credits = (mcu_credits - 2) & 0xff;
362
363 mcu_command = data;
364 }
365 }
366
tnzs_mcu_read(INT32 offset)367 UINT8 tnzs_mcu_read(INT32 offset)
368 {
369 switch (mcu_type)
370 {
371 case MCU_ARKANOID:
372 return mcu_arknoid2_r(offset & 1);
373 break;
374
375 case MCU_CHUKATAI:
376 return mcu_chukatai_r(offset & 1);
377 break;
378
379 case MCU_EXTRMATN:
380 case MCU_DRTOPPEL:
381 case MCU_TNZS:
382 case MCU_PLUMPOP:
383 return mcu_tnzs_r(offset & 1);
384 break;
385
386 case MCU_NONE_INSECTX:
387 case MCU_NONE_KAGEKI:
388 case MCU_NONE_JPOPNICS:
389 case MCU_NONE:
390 return tnzs_mcu_inputs[offset & 1];
391 break;
392 }
393
394 return 0xff;
395 }
396
tnzs_mcu_write(INT32 offset,INT32 data)397 void tnzs_mcu_write(INT32 offset, INT32 data)
398 {
399 switch (mcu_type)
400 {
401 case MCU_ARKANOID:
402 mcu_arknoid2_w(offset & 1, data);
403 break;
404
405 case MCU_CHUKATAI:
406 mcu_chukatai_w(offset & 1, data);
407 break;
408
409 case MCU_EXTRMATN:
410 case MCU_DRTOPPEL:
411 case MCU_TNZS:
412 case MCU_PLUMPOP:
413 mcu_tnzs_w(offset & 1, data);
414 break;
415 }
416 }
417
tnzs_mcu_interrupt()418 void tnzs_mcu_interrupt()
419 {
420 INT32 coin;
421
422 switch (mcu_type)
423 {
424 case MCU_ARKANOID:
425 coin = (~tnzs_mcu_inputs[1] >> 4) & 0x0f;
426 coin = (coin & 0x08) | ((coin & 0x03) << 1) | ((coin & 0x04) >> 2);
427 coin &= mcu_coin_lockout;
428 mcu_handle_coins(coin);
429 break;
430
431 case MCU_EXTRMATN:
432 case MCU_DRTOPPEL:
433 case MCU_PLUMPOP:
434 case MCU_CHUKATAI:
435 case MCU_TNZS:
436 coin = (((~tnzs_mcu_inputs[2] & 0x30) >> 4) | ((~tnzs_mcu_inputs[2] & 0x03) << 2));
437 coin &= mcu_coin_lockout;
438 mcu_handle_coins(coin);
439 break;
440
441 case MCU_NONE:
442 break;
443 }
444 }
445
tnzs_mcu_type()446 INT32 tnzs_mcu_type()
447 {
448 return mcu_type;
449 }
450
tnzs_mcu_scan()451 void tnzs_mcu_scan()
452 {
453 SCAN_VAR(mcu_initializing);
454 SCAN_VAR(mcu_coinage_init);
455 SCAN_VAR(mcu_coinage[0]);
456 SCAN_VAR(mcu_coinage[1]);
457 SCAN_VAR(mcu_coinage[2]);
458 SCAN_VAR(mcu_coinage[3]);
459 SCAN_VAR(mcu_coinsA);
460 SCAN_VAR(mcu_coinsB);
461 SCAN_VAR(mcu_credits);
462 SCAN_VAR(mcu_reportcoin);
463 SCAN_VAR(mcu_command);
464 SCAN_VAR(mcu_coin_lockout);
465 }
466