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] & 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