1 /***********************************************************************
2 
3 	DECO Cassette System machine
4 
5  ***********************************************************************/
6 
7 #include "driver.h"
8 #include "cpu/m6502/m6502.h"
9 #include "cpu/i8x41/i8x41.h"
10 #include "machine/decocass.h"
11 #include "state.h"
12 
13 /* tape direction, speed and timing (used also in vidhrdw/decocass.c) */
14 int tape_dir;
15 int tape_speed;
16 double tape_time0;
17 void *tape_timer;
18 
19 static int firsttime = 1;
20 static int tape_present;
21 static int tape_blocks;
22 static int tape_length;
23 static int tape_bot_eot;
24 static UINT8 crc16_lsb;
25 static UINT8 crc16_msb;
26 
27 /* pre-calculated crc16 of the tape blocks */
28 static UINT8 tape_crc16_lsb[256];
29 static UINT8 tape_crc16_msb[256];
30 
31 static data8_t (*decocass_dongle_r)(offs_t offset);
32 static void (*decocass_dongle_w)(offs_t offset, data8_t data);
33 
34 static data8_t decocass_reset;
35 static data8_t i8041_p1;
36 static data8_t i8041_p2;
37 
38 /* dongle type #1: jumpers C and D assignments */
39 #define MAKE_MAP(m0,m1,m2,m3,m4,m5,m6,m7)		\
40 	((m0)<<0)|((m1)<<4)|((m2)<<8)|((m3)<<12)|	\
41 	((m4)<<16)|((m5)<<20)|((m6)<<24)|((m7)<<28)
42 #define MAP0(m) ((m>>0)&15)
43 #define MAP1(m) ((m>>4)&15)
44 #define MAP2(m) ((m>>8)&15)
45 #define MAP3(m) ((m>>12)&15)
46 #define MAP4(m) ((m>>16)&15)
47 #define MAP5(m) ((m>>20)&15)
48 #define MAP6(m) ((m>>24)&15)
49 #define MAP7(m) ((m>>28)&15)
50 static UINT32 type1_inmap;
51 static UINT32 type1_outmap;
52 
53 /* dongle type #2: status of the latches */
54 static int type2_d2_latch;	/* latched 8041-STATUS D2 value */
55 static int type2_xx_latch;	/* latched value (D7-4 == 0xc0) ? 1 : 0 */
56 static int type2_promaddr;	/* latched PROM address A0-A7 */
57 
58 /* dongle type #3: status and patches */
59 static int type3_ctrs;			/* 12 bit counter stage */
60 static int type3_d0_latch;		/* latched 8041-D0 value */
61 static int type3_pal_19;		/* latched 1 for PAL input pin-19 */
62 static int type3_swap;
63 enum {
64 	TYPE3_SWAP_01,
65 	TYPE3_SWAP_12,
66 	TYPE3_SWAP_13,
67 	TYPE3_SWAP_24,
68 	TYPE3_SWAP_25,
69 	TYPE3_SWAP_34_0,
70 	TYPE3_SWAP_34_7,
71 	TYPE3_SWAP_56,
72 	TYPE3_SWAP_67
73 };
74 
75 /* dongle type #4: status */
76 static int type4_ctrs;			/* latched PROM address (E5x0 LSB, E5x1 MSB) */
77 static int type4_latch; 		/* latched enable PROM (1100xxxx written to E5x1) */
78 
79 /* dongle type #5: status */
80 static int type5_latch; 		/* latched enable PROM (1100xxxx written to E5x1) */
81 
82 /* four inputs from the quadrature decoder (H1, V1, H2, V2) */
83 static data8_t decocass_quadrature_decoder[4];
84 
85 /* sound latches, ACK status bits and NMI timer */
86 static data8_t decocass_sound_ack;
87 static void *decocass_sound_timer;
88 
WRITE_HANDLER(decocass_coin_counter_w)89 WRITE_HANDLER( decocass_coin_counter_w )
90 {
91 }
92 
WRITE_HANDLER(decocass_sound_command_w)93 WRITE_HANDLER( decocass_sound_command_w )
94 {
95 	LOG(2,("CPU #%d sound command -> $%02x\n", cpu_getactivecpu(), data));
96 	soundlatch_w(0,data);
97 	decocass_sound_ack |= 0x80;
98 	/* remove snd cpu data ack bit. i don't see it in the schems, but... */
99 	decocass_sound_ack &= ~0x40;
100 	cpu_set_irq_line(1, M6502_IRQ_LINE, ASSERT_LINE);
101 }
102 
READ_HANDLER(decocass_sound_data_r)103 READ_HANDLER( decocass_sound_data_r )
104 {
105 	data8_t data = soundlatch2_r(0);
106 	LOG(2,("CPU #%d sound data    <- $%02x\n", cpu_getactivecpu(), data));
107 	return data;
108 }
109 
READ_HANDLER(decocass_sound_ack_r)110 READ_HANDLER( decocass_sound_ack_r )
111 {
112 	data8_t data = decocass_sound_ack;	/* D6+D7 */
113 	LOG(2,("CPU #%d sound ack     <- $%02x\n", cpu_getactivecpu(), data));
114 	return data;
115 }
116 
WRITE_HANDLER(decocass_sound_data_w)117 WRITE_HANDLER( decocass_sound_data_w )
118 {
119 	LOG(2,("CPU #%d sound data    -> $%02x\n", cpu_getactivecpu(), data));
120 	soundlatch2_w(0, data);
121 	decocass_sound_ack |= 0x40;
122 }
123 
READ_HANDLER(decocass_sound_command_r)124 READ_HANDLER( decocass_sound_command_r )
125 {
126 	data8_t data = soundlatch_r(0);
127 	LOG(2,("CPU #%d sound command <- $%02x\n", cpu_getactivecpu(), data));
128 	cpu_set_irq_line(1, M6502_IRQ_LINE, CLEAR_LINE);
129 	decocass_sound_ack &= ~0x80;
130 	return data;
131 }
132 
decocass_sound_nmi_pulse(int param)133 static void decocass_sound_nmi_pulse( int param )
134 {
135 	cpu_set_nmi_line(1, PULSE_LINE);
136 }
137 
WRITE_HANDLER(decocass_sound_nmi_enable_w)138 WRITE_HANDLER( decocass_sound_nmi_enable_w )
139 {
140 	LOG(2,("CPU #%d sound NMI enb -> $%02x\n", cpu_getactivecpu(), data));
141 	timer_adjust(decocass_sound_timer, TIME_IN_HZ(256 * 57 / 8 / 2), 0, TIME_IN_HZ(256 * 57 / 8 / 2));
142 }
143 
READ_HANDLER(decocass_sound_nmi_enable_r)144 READ_HANDLER( decocass_sound_nmi_enable_r )
145 {
146 	data8_t data = 0xff;
147 	LOG(2,("CPU #%d sound NMI enb <- $%02x\n", cpu_getactivecpu(), data));
148 	timer_adjust(decocass_sound_timer, TIME_IN_HZ(256 * 57 / 8 / 2), 0, TIME_IN_HZ(256 * 57 / 8 / 2));
149 	return data;
150 }
151 
READ_HANDLER(decocass_sound_data_ack_reset_r)152 READ_HANDLER( decocass_sound_data_ack_reset_r )
153 {
154 	data8_t data = 0xff;
155 	LOG(2,("CPU #%d sound ack rst <- $%02x\n", cpu_getactivecpu(), data));
156 	decocass_sound_ack &= ~0x40;
157 	return data;
158 }
159 
WRITE_HANDLER(decocass_sound_data_ack_reset_w)160 WRITE_HANDLER( decocass_sound_data_ack_reset_w )
161 {
162 	LOG(2,("CPU #%d sound ack rst -> $%02x\n", cpu_getactivecpu(), data));
163 	decocass_sound_ack &= ~0x40;
164 }
165 
WRITE_HANDLER(decocass_nmi_reset_w)166 WRITE_HANDLER( decocass_nmi_reset_w )
167 {
168 	cpu_set_nmi_line( 0, CLEAR_LINE );
169 }
170 
WRITE_HANDLER(decocass_quadrature_decoder_reset_w)171 WRITE_HANDLER( decocass_quadrature_decoder_reset_w )
172 {
173 	/* just latch the analog controls here */
174 	decocass_quadrature_decoder[0] = input_port_3_r(0);
175 	decocass_quadrature_decoder[1] = input_port_4_r(0);
176 	decocass_quadrature_decoder[2] = input_port_5_r(0);
177 	decocass_quadrature_decoder[3] = input_port_6_r(0);
178 }
179 
WRITE_HANDLER(decocass_adc_w)180 WRITE_HANDLER( decocass_adc_w )
181 {
182 }
183 
184 /*
185  * E6x0    inputs
186  * E6x1    inputs
187  * E6x2    coin inp
188  * E6x3    quadrature decoder read
189  * E6x4    ""
190  * E6x5    ""
191  * E6x6    ""
192  * E6x7    a/d converter read
193  */
READ_HANDLER(decocass_input_r)194 READ_HANDLER( decocass_input_r )
195 {
196 	data8_t data = 0xff;
197 	switch (offset & 7)
198 	{
199 	case 0: case 1: case 2:
200 		data = readinputport(offset & 7);
201 		break;
202 	case 3: case 4: case 5: case 6:
203 		data = decocass_quadrature_decoder[(offset & 7) - 3];
204 		break;
205 	default:
206 		break;
207 	}
208 
209 	return data;
210 }
211 
212 /*
213  * D0 - REQ/ data request	  (8041 pin 34 port 1.7)
214  * D1 - FNO/ function number  (8041 pin 21 port 2.0)
215  * D2 - EOT/ end-of-tape	  (8041 pin 22 port 2.1)
216  * D3 - ERR/ error condition  (8041 pin 23 port 2.2)
217  * D4 - BOT-EOT from tape
218  * D5 -
219  * D6 -
220  * D7 - cassette present
221  */
222 /* Note on a tapes leader-BOT-data-EOT-trailer format:
223  * A cassette has a transparent piece of tape on both ends,
224  * leader and trailer. And data tapes also have BOT and EOT
225  * holes, shortly before the the leader and trailer.
226  * The holes and clear tape are detected using a photo-resitor.
227  * When rewinding, the BOT/EOT signal will show a short
228  * pulse and if rewind continues a constant high signal later.
229  * The specs say the holes are "> 2ms" in length.
230  */
231 
232 #define TAPE_CLOCKRATE	4800	/* clock pulses per second */
233 
234 /* duration of the clear LEADER (and trailer) of the tape */
235 #define TAPE_LEADER 	TAPE_CLOCKRATE		/* 1s */
236 /* duration of the GAP between leader and BOT/EOT */
237 #define TAPE_GAP		TAPE_CLOCKRATE*3/2	/* 1.5s */
238 /* duration of BOT/EOT holes */
239 #define TAPE_HOLE		TAPE_CLOCKRATE/400	/* 0.0025s */
240 
241 /* byte offset of the tape chunks (8 clocks per byte = 16 samples) */
242 /* 300 ms GAP between BOT and first data block (doesn't work.. thus /2) */
243 #define TAPE_PRE_GAP	34
244 #define TAPE_LEADIN 	(TAPE_PRE_GAP + 1)
245 #define TAPE_HEADER 	(TAPE_LEADIN + 1)
246 #define TAPE_BLOCK		(TAPE_HEADER + 256)
247 #define TAPE_CRC16_MSB	(TAPE_BLOCK + 1)
248 #define TAPE_CRC16_LSB	(TAPE_CRC16_MSB + 1)
249 #define TAPE_TRAILER	(TAPE_CRC16_LSB + 1)
250 #define TAPE_LEADOUT	(TAPE_TRAILER + 1)
251 #define TAPE_LONGCLOCK	(TAPE_LEADOUT + 1)
252 #define TAPE_POST_GAP	(TAPE_LONGCLOCK + 34)
253 
254 /* size of a tape chunk (block) including gaps */
255 #define TAPE_CHUNK		TAPE_POST_GAP
256 
257 #define E5XX_MASK	0x02	/* use 0x0e for old style board */
258 
259 #define BIT0(x) ((x)&1)
260 #define BIT1(x) (((x)>>1)&1)
261 #define BIT2(x) (((x)>>2)&1)
262 #define BIT3(x) (((x)>>3)&1)
263 #define BIT4(x) (((x)>>4)&1)
264 #define BIT5(x) (((x)>>5)&1)
265 #define BIT6(x) (((x)>>6)&1)
266 #define BIT7(x) (((x)>>7)&1)
267 
WRITE_HANDLER(decocass_reset_w)268 WRITE_HANDLER( decocass_reset_w )
269 {
270 	LOG(1,("%9.7f 6502-PC: %04x decocass_reset_w(%02x): $%02x\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
271 	decocass_reset = data;
272 
273 	/* CPU #1 active hight reset */
274 	cpu_set_reset_line( 1, data & 0x01 );
275 
276 	/* on reset also remove the sound timer */
277 	if (data & 1)
278 		timer_adjust(decocass_sound_timer, TIME_NEVER, 0, 0);
279 
280 	/* 8041 active low reset */
281 	cpu_set_reset_line( 2, (data & 0x08) ^ 0x08 );
282 }
283 
284 #ifdef MAME_DEBUG
dirnm(int speed)285 static const char *dirnm(int speed)
286 {
287 	if (speed <  -1) return "fast rewind";
288 	if (speed == -1) return "rewind";
289 	if (speed ==  0) return "stop";
290 	if (speed ==  1) return "forward";
291 	return "fast forward";
292 }
293 #endif
294 
tape_crc16(UINT8 data)295 static void tape_crc16(UINT8 data)
296 {
297 	UINT8 c0, c1;
298 	UINT8 old_lsb = crc16_lsb;
299 	UINT8 old_msb = crc16_msb;
300 	UINT8 feedback;
301 
302 	feedback = ((data >> 7) ^ crc16_msb) & 1;
303 
304 	/* rotate 16 bits */
305 	c0 = crc16_lsb & 1;
306 	c1 = crc16_msb & 1;
307 	crc16_msb = (crc16_msb >> 1) | (c0 << 7);
308 	crc16_lsb = (crc16_lsb >> 1) | (c1 << 7);
309 
310 	/* feedback into bit 7 */
311 	if (feedback)
312 		crc16_lsb |= 0x80;
313 	else
314 		crc16_lsb &= ~0x80;
315 
316 	/* feedback to bit 6 into bit 5 */
317 	if (((old_lsb >> 6) ^ feedback) & 1)
318 		crc16_lsb |= 0x20;
319 	else
320 		crc16_lsb &= ~0x20;
321 
322 	/* feedback to bit 1 into bit 0 */
323 	if (((old_msb >> 1) ^ feedback) & 1)
324 		crc16_msb |= 0x01;
325 	else
326 		crc16_msb &= ~0x01;
327 }
328 
tape_update(void)329 static void tape_update(void)
330 {
331 	static int last_byte;
332 	double tape_time = tape_time0;
333 	int offset, rclk, rdata, tape_bit, tape_byte, tape_block;
334 
335 	if (tape_timer)
336 		tape_time += tape_dir * timer_timeelapsed(tape_timer);
337 
338 	if (tape_time < 0.0)
339 		tape_time = 0.0;
340 	else if (tape_time > 999.9)
341 		tape_time = 999.9;
342 
343 	offset = (int)(tape_time * TAPE_CLOCKRATE + 0.499995);
344 
345 	/* reset RCLK and RDATA inputs */
346 	rclk = 0;
347 	rdata = 0;
348 
349 	if (offset < TAPE_LEADER)
350 	{
351 		if (offset < 0)
352 			offset = 0;
353 		/* LEADER area */
354 		if (0 == tape_bot_eot)
355 		{
356 			tape_bot_eot = 1;
357 			set_led_status(1, 1);
358 			LOG(5,("tape %5.4fs: %s found LEADER\n", tape_time, dirnm(tape_dir)));
359 		}
360 	}
361 	else
362 	if (offset < TAPE_LEADER + TAPE_GAP)
363 	{
364 		/* GAP between LEADER and BOT hole */
365 		if (1 == tape_bot_eot)
366 		{
367 			tape_bot_eot = 0;
368 			set_led_status(1, 0);
369 			LOG(5,("tape %5.4fs: %s between BOT + LEADER\n", tape_time, dirnm(tape_dir)));
370 		}
371 	}
372 	else
373 	if (offset < TAPE_LEADER + TAPE_GAP + TAPE_HOLE)
374 	{
375 		/* during BOT hole */
376 		if (0 == tape_bot_eot)
377 		{
378 			tape_bot_eot = 1;
379 			set_led_status(1, 1);
380 			LOG(5,("tape %5.4fs: %s found BOT\n", tape_time, dirnm(tape_dir)));
381 		}
382 	}
383 	else
384 	if (offset < tape_length - TAPE_LEADER - TAPE_GAP - TAPE_HOLE)
385 	{
386 		offset -= TAPE_LEADER + TAPE_GAP + TAPE_HOLE;
387 
388 		/* data area */
389 		if (1 == tape_bot_eot)
390 		{
391 			tape_bot_eot = 0;
392 			set_led_status(1, 0);
393 			LOG(5,("tape %5.4fs: %s data area\n", tape_time, dirnm(tape_dir)));
394 		}
395 		rclk = (offset ^ 1) & 1;
396 		tape_bit = (offset / 2) % 8;
397 		tape_byte = (offset / 16) % TAPE_CHUNK;
398 		tape_block = offset / 16 / TAPE_CHUNK;
399 
400 		if (tape_byte < TAPE_PRE_GAP)
401 		{
402 			rclk = 0;
403 			rdata = 0;
404 		}
405 		else
406 		if (tape_byte < TAPE_LEADIN)
407 		{
408 			rdata = (0x00 >> tape_bit) & 1;
409 			if (tape_byte != last_byte)
410 			{
411 				LOG(5,("tape %5.4fs: LEADIN $00\n", tape_time));
412 				set_led_status(2, 1);
413 			}
414 		}
415 		else
416 		if (tape_byte < TAPE_HEADER)
417 		{
418 			rdata = (0xaa >> tape_bit) & 1;
419 			if (tape_byte != last_byte)
420 				LOG(5,("tape %5.4fs: HEADER $aa\n", tape_time));
421 		}
422 		else
423 		if (tape_byte < TAPE_BLOCK)
424 		{
425 			data8_t *ptr = memory_region(REGION_USER2) + tape_block * 256 + tape_byte - TAPE_HEADER;
426 			rdata = (*ptr >> tape_bit) & 1;
427 			if (tape_byte != last_byte)
428 				LOG(4,("tape %5.4fs: DATA(%02x) $%02x\n", tape_time, tape_byte - TAPE_HEADER, *ptr));
429 		}
430 		else
431 		if (tape_byte < TAPE_CRC16_MSB)
432 		{
433 			rdata = (tape_crc16_msb[tape_block] >> tape_bit) & 1;
434 			if (tape_byte != last_byte)
435 				LOG(4,("tape %5.4fs: CRC16 MSB $%02x\n", tape_time, tape_crc16_msb[tape_block]));
436 		}
437 		else
438 		if (tape_byte < TAPE_CRC16_LSB)
439 		{
440 			rdata = (tape_crc16_lsb[tape_block] >> tape_bit) & 1;
441 			if (tape_byte != last_byte)
442 				LOG(4,("tape %5.4fs: CRC16 LSB $%02x\n", tape_time, tape_crc16_lsb[tape_block]));
443 		}
444 		else
445 		if (tape_byte < TAPE_TRAILER)
446 		{
447 			rdata = (0xaa >> tape_bit) & 1;
448 			if (tape_byte != last_byte)
449 				LOG(4,("tape %5.4fs: TRAILER $aa\n", tape_time));
450 		}
451 		else
452 		if (tape_byte < TAPE_LEADOUT)
453 		{
454 			rdata = (0x00 >> tape_bit) & 1;
455 			if (tape_byte != last_byte)
456 				LOG(4,("tape %5.4fs: LEADOUT $00\n", tape_time));
457 		}
458 		else
459 		if (tape_byte < TAPE_LONGCLOCK)
460 		{
461 			if (tape_byte != last_byte)
462 			{
463 				LOG(4,("tape %5.4fs: LONG CLOCK\n", tape_time));
464 				set_led_status(2, 0);
465 			}
466 			rclk = 1;
467 			rdata = 0;
468 		}
469 		last_byte = tape_byte;
470 	}
471 	else
472 	if (offset < tape_length - TAPE_LEADER - TAPE_GAP)
473 	{
474 		/* during EOT hole */
475 		if (0 == tape_bot_eot)
476 		{
477 			tape_bot_eot = 1;
478 			set_led_status(1, 1);
479 			LOG(5,("tape %5.4fs: %s found EOT\n", tape_time, dirnm(tape_dir)));
480 		}
481 	}
482 	else
483 	if (offset < tape_length - TAPE_LEADER)
484 	{
485 		/* GAP between EOT and trailer */
486 		if (1 == tape_bot_eot)
487 		{
488 			tape_bot_eot = 0;
489 			set_led_status(1, 0);
490 			LOG(5,("tape %5.4fs: %s EOT and TRAILER\n", tape_time, dirnm(tape_dir)));
491 		}
492 	}
493 	else
494 	{
495 		/* TRAILER area */
496 		if (0 == tape_bot_eot)
497 		{
498 			tape_bot_eot = 1;
499 			set_led_status(1, 1);
500 			LOG(5,("tape %5.4fs: %s found TRAILER\n", tape_time, dirnm(tape_dir)));
501 		}
502 		offset = tape_length - 1;
503 	}
504 
505 	i8041_p2 = (i8041_p2 & ~0xe0) | (tape_bot_eot << 5) | (rclk << 6) | (rdata << 7);
506 }
507 
508 #ifdef MAME_DEBUG
decocass_fno(offs_t offset,data8_t data)509 static void decocass_fno(offs_t offset, data8_t data)
510 {
511 		/* 8041ENA/ and is this a FNO write (function number)? */
512 		if (0 == (i8041_p2 & 0x01))
513 		{
514 			switch (data)
515 			{
516 			case 0x25: logerror("8041 FNO 25: write_block\n"); break;
517 			case 0x26: logerror("8041 FNO 26: rewind_block\n"); break;
518 			case 0x27: logerror("8041 FNO 27: read_block_a\n"); break;
519 			case 0x28: logerror("8041 FNO 28: read_block_b\n"); break;
520 			case 0x29: logerror("8041 FNO 29: tape_rewind_fast\n"); break;
521 			case 0x2a: logerror("8041 FNO 2a: tape_forward\n"); break;
522 			case 0x2b: logerror("8041 FNO 2b: tape_rewind\n"); break;
523 			case 0x2c: logerror("8041 FNO 2c: force_abort\n"); break;
524 			case 0x2d: logerror("8041 FNO 2d: tape_erase\n"); break;
525 			case 0x2e: logerror("8041 FNO 2e: search_tape_mark\n"); break;
526 			case 0x2f: logerror("8041 FNO 2f: search_eot\n"); break;
527 			case 0x30: logerror("8041 FNO 30: advance_block\n"); break;
528 			case 0x31: logerror("8041 FNO 31: write_tape_mark\n"); break;
529 			case 0x32: logerror("8041 FNO 32: reset_error\n"); break;
530 			case 0x33: logerror("8041 FNO 33: flag_status_report\n"); break;
531 			case 0x34: logerror("8041 FNO 34: report_status_to_main\n"); break;
532 			default:   logerror("8041 FNO %02x: invalid\n", data);
533 			}
534 		}
535 }
536 #endif
537 
538 /***************************************************************************
539  *
540  *	TYPE1 DONGLE (DE-0061)
541  *	- Test Tape
542  *	- Lock 'n Chase
543  *	- Treasure Island
544  *	- Super Astro Fighter
545  *	- Lucky Poker
546  *	- Terranian
547  *	- Explorer
548  *	- Pro Golf
549  *
550  ***************************************************************************/
551 
READ_HANDLER(decocass_type1_r)552 READ_HANDLER( decocass_type1_r )
553 {
554 	static data8_t latch1;
555 	data8_t data;
556 
557 	if (1 == (offset & 1))
558 	{
559 		if (0 == (offset & E5XX_MASK))
560 			data = cpunum_get_reg(2, I8X41_STAT);
561 		else
562 			data = 0xff;
563 
564 		data =
565 			(BIT0(data) << 0) |
566 			(BIT1(data) << 1) |
567 			(1			<< 2) |
568 			(1			<< 3) |
569 			(1			<< 4) |
570 			(1			<< 5) |
571 			(1			<< 6) |
572 			(0			<< 7);
573 		LOG(4,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x <- (%s %s)\n",
574 			timer_get_time(), activecpu_get_previouspc(), offset, data,
575 			(data & 1) ? "OBF" : "-",
576 			(data & 2) ? "IBF" : "-"));
577 	}
578 	else
579 	{
580 		offs_t promaddr;
581 		data8_t save;
582 		UINT8 *prom = memory_region(REGION_USER1);
583 
584 		if (firsttime)
585 		{
586 			LOG(4,("prom data:\n"));
587 			for (promaddr = 0; promaddr < 32; promaddr++)
588 			{
589 				if (promaddr % 8 == 0)
590 					LOG(4,("%04x:", promaddr));
591 				LOG(4,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
592 			}
593 			firsttime = 0;
594 			latch1 = 0; 	 /* reset latch (??) */
595 		}
596 
597 		if (0 == (offset & E5XX_MASK))
598 			data = cpunum_get_reg(2, I8X41_DATA);
599 		else
600 			data = 0xff;
601 
602 		save = data;	/* save the unmodifed data for the latch */
603 
604 		promaddr =
605 			(((data >> MAP0(type1_inmap)) & 1) << 0) |
606 			(((data >> MAP1(type1_inmap)) & 1) << 1) |
607 			(((data >> MAP4(type1_inmap)) & 1) << 2) |
608 			(((data >> MAP5(type1_inmap)) & 1) << 3) |
609 			(((data >> MAP7(type1_inmap)) & 1) << 4);
610 
611 		data =
612 			(((prom[promaddr] >> 0) & 1)			   << MAP0(type1_outmap)) |
613 			(((prom[promaddr] >> 1) & 1)			   << MAP1(type1_outmap)) |
614 			((1 - ((latch1 >> MAP2(type1_inmap)) & 1)) << MAP2(type1_outmap)) |
615 			(((data >> MAP3(type1_inmap)) & 1)		   << MAP3(type1_outmap)) |
616 			(((prom[promaddr] >> 2) & 1)			   << MAP4(type1_outmap)) |
617 			(((prom[promaddr] >> 3) & 1)			   << MAP5(type1_outmap)) |
618 			(((latch1 >> MAP6(type1_inmap)) & 1)	   << MAP6(type1_outmap)) |
619 			(((prom[promaddr] >> 4) & 1)			   << MAP7(type1_outmap));
620 
621 		LOG(3,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x <- (%s $%02x mangled with PROM[$%02x])\n", timer_get_time(), activecpu_get_previouspc(), offset, data, 0 == (offset & E5XX_MASK) ? "8041-DATA" : "open bus", save, promaddr));
622 
623 		latch1 = save;		/* latch the data for the next A0 == 0 read */
624 	}
625 	return data;
626 }
627 
628 /*
629  * special handler for the test tape, because we cannot
630  * look inside the dongle :-/
631  * There seem to be lines 1, 3 and 6 straight through.
632  * The rest could be translated with the standard Type1 dongle
633  * PROM, but I don't know. For now we have found this lookup
634  * table by applying data to the dongle and logging the outputs.
635  */
636 
READ_HANDLER(decocass_type1_map1_r)637 READ_HANDLER( decocass_type1_map1_r )
638 {
639 	static data8_t map[] = {
640 		0x01,0x34,0x03,0x36,0xa4,0x15,0xa6,0x17,
641 		0x09,0x3c,0x0b,0x3e,0xac,0x1d,0xae,0x1f,
642 		0x90,0x14,0x92,0x16,0x85,0x00,0x87,0x02,
643 		0x98,0x1c,0x9a,0x1e,0x8d,0x08,0x8f,0x0a,
644 		0x31,0x30,0x33,0x32,0xa1,0x11,0xa3,0x13,
645 		0x39,0x38,0x3b,0x3a,0xa9,0x19,0xab,0x1b,
646 		0x84,0xb5,0x86,0xb7,0x81,0xb4,0x83,0xb6,
647 		0x8c,0xbd,0x8e,0xbf,0x89,0xbc,0x8b,0xbe,
648 		0x41,0x74,0x43,0x76,0xe4,0x55,0xe6,0x57,
649 		0x49,0x7c,0x4b,0x7e,0xec,0x5d,0xee,0x5f,
650 		0xd0,0x54,0xd2,0x56,0xc5,0x40,0xc7,0x42,
651 		0xd8,0x5c,0xda,0x5e,0xcd,0x48,0xcf,0x4a,
652 		0x71,0x70,0x73,0x72,0xe1,0x51,0xe3,0x53,
653 		0x79,0x78,0x7b,0x7a,0xe9,0x59,0xeb,0x5b,
654 		0xc4,0xf5,0xc6,0xf7,0xc1,0xf4,0xc3,0xf6,
655 		0xcc,0xfd,0xce,0xff,0xc9,0xfc,0xcb,0xfe,
656 		0x25,0xa0,0x27,0xa2,0x95,0x10,0x97,0x12,
657 		0x2d,0xa8,0x2f,0xaa,0x9d,0x18,0x9f,0x1a,
658 		0x80,0xb1,0x82,0xb3,0x24,0xb0,0x26,0xb2,
659 		0x88,0xb9,0x8a,0xbb,0x2c,0xb8,0x2e,0xba,
660 		0x21,0x94,0x23,0x96,0x05,0x04,0x07,0x06,
661 		0x29,0x9c,0x2b,0x9e,0x0d,0x0c,0x0f,0x0e,
662 		0x35,0xa5,0x37,0xa7,0x20,0x91,0x22,0x93,
663 		0x3d,0xad,0x3f,0xaf,0x28,0x99,0x2a,0x9b,
664 		0x65,0xe0,0x67,0xe2,0xd5,0x50,0xd7,0x52,
665 		0x6d,0xe8,0x6f,0xea,0xdd,0x58,0xdf,0x5a,
666 		0xc0,0xf1,0xc2,0xf3,0x64,0xf0,0x66,0xf2,
667 		0xc8,0xf9,0xca,0xfb,0x6c,0xf8,0x6e,0xfa,
668 		0x61,0xd4,0x63,0xd6,0x45,0x44,0x47,0x46,
669 		0x69,0xdc,0x6b,0xde,0x4d,0x4c,0x4f,0x4e,
670 		0x75,0xe5,0x77,0xe7,0x60,0xd1,0x62,0xd3,
671 		0x7d,0xed,0x7f,0xef,0x68,0xd9,0x6a,0xdb
672 	};
673 	data8_t save, data;
674 
675 	if (1 == (offset & 1))
676 	{
677 		if (0 == (offset & E5XX_MASK))
678 			data = cpunum_get_reg(2, I8X41_STAT);
679 		else
680 			data = 0xff;
681 
682 		data =
683 			(BIT0(data) << 0) |
684 			(BIT1(data) << 1) |
685 			(1			<< 2) |
686 			(1			<< 3) |
687 			(1			<< 4) |
688 			(1			<< 5) |
689 			(1			<< 6) |
690 			(0			<< 7);
691 		LOG(4,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x <- (%s %s)\n",
692 			timer_get_time(), activecpu_get_previouspc(), offset, data,
693 			(data & 1) ? "OBF" : "-",
694 			(data & 2) ? "IBF" : "-"));
695 	}
696 	else
697 	{
698 		if (0 == (offset & E5XX_MASK))
699 			save = cpunum_get_reg(2, I8X41_DATA);
700 		else
701 			save = 0xff;
702 
703 		data = map[save];
704 
705 		LOG(3,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x '%c' <- map[%02x] (%s)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.', save, 0 == (offset & E5XX_MASK) ? "8041-DATA" : "open bus"));
706 	}
707 	return data;
708 }
709 
READ_HANDLER(decocass_type1_map2_r)710 READ_HANDLER( decocass_type1_map2_r )
711 {
712 	static data8_t map[] = {
713 /* 00 */0x06,0x1f,0x8f,0x0c,0x02,0x1b,0x8b,0x08,
714 		0x1e,0x1d,0x8e,0x16,0x1a,0x19,0x8a,0x12,
715 		0x95,0x17,0x94,0x05,0x91,0x13,0x90,0x01,
716 		0x87,0x04,0x86,0x9f,0x83,0x00,0x82,0x9b,
717 /* 20 */0x26,0x3f,0xaf,0x2c,0x22,0x3b,0xab,0x28,
718 		0x3e,0x3d,0xae,0x36,0x3a,0x39,0xaa,0x32,
719 		0xb5,0x37,0xb4,0x25,0xb1,0x33,0xb0,0x21,
720 		0xa7,0x24,0xa6,0xbf,0xa3,0x20,0xa2,0xbb,
721 /* 40 */0x46,0x5f,0xcf,0x4c,0x42,0x5b,0xcb,0x48,
722 		0x5e,0x5d,0xce,0x56,0x5a,0x59,0xca,0x52,
723 		0xd5,0x57,0xd4,0x45,0xd1,0x53,0xd0,0x41,
724 		0xc7,0x44,0xc6,0xdf,0xc3,0x40,0xc2,0xdb,
725 /* 60 */0x66,0x7f,0xef,0x6c,0x62,0x7b,0xeb,0x68,
726 		0x7e,0x7d,0xee,0x76,0x7a,0x79,0xea,0x72,
727 		0xf5,0x77,0xf4,0x65,0xf1,0x73,0xf0,0x61,
728 		0xe7,0x64,0xe6,0xff,0xe3,0x60,0xe2,0xfb,
729 /* 80 */0x1c,0x8d,0x8c,0x15,0x18,0x89,0x88,0x11,
730 		0x0e,0x97,0x14,0x07,0x0a,0x93,0x10,0x03,
731 		0x85,0x9e,0x0f,0x9d,0x81,0x9a,0x0b,0x99,
732 		0x84,0x9c,0x0d,0x96,0x80,0x98,0x09,0x92,
733 /* a0 */0x3c,0xad,0xac,0x35,0x38,0xa9,0xa8,0x31,
734 		0x2e,0xb7,0x34,0x27,0x2a,0xb3,0x30,0x23,
735 		0xa5,0xbe,0x2f,0xbd,0xa1,0xba,0x2b,0xb9,
736 		0xa4,0xbc,0x2d,0xb6,0xa0,0xb8,0x29,0xb2,
737 /* c0 */0x5c,0xcd,0xcc,0x55,0x58,0xc9,0xc8,0x51,
738 		0x4e,0xd7,0x54,0x47,0x4a,0xd3,0x50,0x43,
739 		0xc5,0xde,0x4f,0xdd,0xc1,0xda,0x4b,0xd9,
740 		0xc4,0xdc,0x4d,0xd6,0xc0,0xd8,0x49,0xd2,
741 /* e0 */0x7c,0xed,0xec,0x75,0x78,0xe9,0xe8,0x71,
742 		0x6e,0xf7,0x74,0x67,0x6a,0xf3,0x70,0x63,
743 		0xe5,0xfe,0x6f,0xfd,0xe1,0xfa,0x6b,0xf9,
744 		0xe4,0xfc,0x6d,0xf6,0xe0,0xf8,0x69,0xf2
745 	};
746 	static data8_t latch2;
747 	data8_t save, addr, data;
748 
749 	/* read from tape:
750 	 *	7d 43 5d 4f 04 ae e3 59 57 cb d6 55 4d 15
751 	 * should become:
752 	 *	?? 48 44 52 42 30 31 44 45 43 4f 53 59 53
753 	 * lookup entries with above values:
754 	 *	?? 47 59 4f 44 ae a7 59 53 cf d2 55 4d 55
755 	 * difference:
756 	 *	   04 04 00 40 00 44 00 04 04 04 00 00 40
757 	 */
758 
759 	if (1 == (offset & 1))
760 	{
761 		if (0 == (offset & E5XX_MASK))
762 			data = cpunum_get_reg(2, I8X41_STAT);
763 		else
764 			data = 0xff;
765 
766 		data =
767 			(BIT0(data) << 0) |
768 			(BIT1(data) << 1) |
769 			(1			<< 2) |
770 			(1			<< 3) |
771 			(1			<< 4) |
772 			(1			<< 5) |
773 			(1			<< 6) |
774 			(0			<< 7);
775 		LOG(4,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x <- (%s %s)\n",
776 			timer_get_time(), activecpu_get_previouspc(), offset, data,
777 			(data & 1) ? "OBF" : "-",
778 			(data & 2) ? "IBF" : "-"));
779 	}
780 	else
781 	{
782 		if (0 == (offset & E5XX_MASK))
783 			save = cpunum_get_reg(2, I8X41_DATA);
784 		else
785 			save = 0xff;
786 
787 		addr = (save & ~0x44) | (latch2 & 0x44);
788 		data = map[addr];
789 
790 		LOG(3,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x '%c' <- map[%02x = %02x^((%02x^%02x)&%02x)] (%s)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.', addr, save, latch2, save, 0x44, 0 == (offset & E5XX_MASK) ? "8041-DATA" : "open bus"));
791 		latch2 = save;
792 	}
793 	return data;
794 }
795 
READ_HANDLER(decocass_type1_map3_r)796 READ_HANDLER( decocass_type1_map3_r )
797 {
798 	static data8_t map[] = {
799 /* 00 */0x03,0x36,0x01,0x34,0xa6,0x17,0xa4,0x15,
800 		0x0b,0x3e,0x09,0x3c,0xae,0x1f,0xac,0x1d,
801 		0x92,0x16,0x90,0x14,0x87,0x02,0x85,0x00,
802 		0x9a,0x1e,0x98,0x1c,0x8f,0x0a,0x8d,0x08,
803 /* 20 */0x33,0x32,0x31,0x30,0xa3,0x13,0xa1,0x11,
804 		0x3b,0x3a,0x39,0x38,0xab,0x1b,0xa9,0x19,
805 		0x86,0xb7,0x84,0xb5,0x83,0xb6,0x81,0xb4,
806 		0x8e,0xbf,0x8c,0xbd,0x8b,0xbe,0x89,0xbc,
807 /* 40 */0x43,0x76,0x41,0x74,0xe6,0x57,0xe4,0x55,
808 		0x4b,0x7e,0x49,0x7c,0xee,0x5f,0xec,0x5d,
809 		0xd2,0x56,0xd0,0x54,0xc7,0x42,0xc5,0x40,
810 		0xda,0x5e,0xd8,0x5c,0xcf,0x4a,0xcd,0x48,
811 /* 60 */0x73,0x72,0x71,0x70,0xe3,0x53,0xe1,0x51,
812 		0x7b,0x7a,0x79,0x78,0xeb,0x5b,0xe9,0x59,
813 		0xc6,0xf7,0xc4,0xf5,0xc3,0xf6,0xc1,0xf4,
814 		0xce,0xff,0xcc,0xfd,0xcb,0xfe,0xc9,0xfc,
815 /* 80 */0x27,0xa2,0x25,0xa0,0x97,0x12,0x95,0x10,
816 		0x2f,0xaa,0x2d,0xa8,0x9f,0x1a,0x9d,0x18,
817 		0x82,0xb3,0x80,0xb1,0x26,0xb2,0x24,0xb0,
818 		0x8a,0xbb,0x88,0xb9,0x2e,0xba,0x2c,0xb8,
819 /* a0 */0x23,0x96,0x21,0x94,0x07,0x06,0x05,0x04,
820 		0x2b,0x9e,0x29,0x9c,0x0f,0x0e,0x0d,0x0c,
821 		0x37,0xa7,0x35,0xa5,0x22,0x93,0x20,0x91,
822 		0x3f,0xaf,0x3d,0xad,0x2a,0x9b,0x28,0x99,
823 /* c0 */0x67,0xe2,0x65,0xe0,0xd7,0x52,0xd5,0x50,
824 		0x6f,0xea,0x6d,0xe8,0xdf,0x5a,0xdd,0x58,
825 		0xc2,0xf3,0xc0,0xf1,0x66,0xf2,0x64,0xf0,
826 		0xca,0xfb,0xc8,0xf9,0x6e,0xfa,0x6c,0xf8,
827 /* e0 */0x63,0xd6,0x61,0xd4,0x47,0x46,0x45,0x44,
828 		0x6b,0xde,0x69,0xdc,0x4f,0x4e,0x4d,0x4c,
829 		0x77,0xe7,0x75,0xe5,0x62,0xd3,0x60,0xd1,
830 		0x7f,0xef,0x7d,0xed,0x6a,0xdb,0x68,0xd9
831 	};
832 	static data8_t latch3;
833 	data8_t save, addr, data;
834 
835 	/* read from tape:
836 	 *	f6 5f e5 c5 17 23 62 40 67 51 c5 ee 85 23
837 	 * should become:
838 	 *	20 48 44 52 42 30 31 41 53 54 52 4f 50 32
839 	 * lookup entries with above values:
840 	 *	b6 5f e7 c5 55 23 22 42 65 53 c5 ec c7 21
841 	 * difference:
842 	 *	40 00 02 00 40 00 40 02 02 02 00 02 42 02
843 	 */
844 
845 	if (1 == (offset & 1))
846 	{
847 		if (0 == (offset & E5XX_MASK))
848 			data = cpunum_get_reg(2, I8X41_STAT);
849 		else
850 			data = 0xff;
851 
852 		data =
853 			(BIT0(data) << 0) |
854 			(BIT1(data) << 1) |
855 			(1			<< 2) |
856 			(1			<< 3) |
857 			(1			<< 4) |
858 			(1			<< 5) |
859 			(1			<< 6) |
860 			(0			<< 7);
861 		LOG(4,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x <- (%s %s)\n",
862 			timer_get_time(), activecpu_get_previouspc(), offset, data,
863 			(data & 1) ? "OBF" : "-",
864 			(data & 2) ? "IBF" : "-"));
865 	}
866 	else
867 	{
868 
869 		if (0 == (offset & E5XX_MASK))
870 			save = cpunum_get_reg(2, I8X41_DATA);
871 		else
872 			save = 0xff;
873 
874 		addr = (save & ~0x42) | (latch3 & 0x42);
875 		data = map[addr];
876 
877 		LOG(3,("%9.7f 6502-PC: %04x decocass_type1_r(%02x): $%02x '%c' <- map[%02x = %02x^((%02x^%02x)&%02x)] (%s)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, data >= 0x20 ? data : '.', addr, save, latch3, save, 0x42, 0 == (offset & E5XX_MASK) ? "8041-DATA" : "open bus"));
878 		latch3 = save;
879 	}
880 	return data;
881 }
882 
883 /***************************************************************************
884  *
885  *	TYPE2 DONGLE (CS82-007)
886  *	- Mission X
887  *	- Disco No 1
888  *	- Pro Tennis
889  *	- Tornado
890  *
891  ***************************************************************************/
READ_HANDLER(decocass_type2_r)892 READ_HANDLER( decocass_type2_r )
893 {
894 	data8_t data;
895 
896 	if (1 == type2_xx_latch)
897 	{
898 		if (1 == (offset & 1))
899 		{
900 			data8_t *prom = memory_region(REGION_USER1);
901 			data = prom[256 * type2_d2_latch + type2_promaddr];
902 			LOG(3,("%9.7f 6502-PC: %04x decocass_type2_r(%02x): $%02x <- prom[%03x]\n", timer_get_time(), activecpu_get_previouspc(), offset, data, 256 * type2_d2_latch + type2_promaddr));
903 		}
904 		else
905 		{
906 			data = 0xff;	/* floating input? */
907 		}
908 	}
909 	else
910 	{
911 		if (0 == (offset & E5XX_MASK))
912 			data = cpunum_get_reg(2, offset & 1 ? I8X41_STAT : I8X41_DATA);
913 		else
914 			data = offset & 0xff;
915 
916 		LOG(3,("%9.7f 6502-PC: %04x decocass_type2_r(%02x): $%02x <- 8041-%s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, offset & 1 ? "STATUS" : "DATA"));
917 	}
918 	return data;
919 }
920 
WRITE_HANDLER(decocass_type2_w)921 WRITE_HANDLER( decocass_type2_w )
922 {
923 	if (1 == type2_xx_latch)
924 	{
925 		if (1 == (offset & 1))
926 		{
927 			LOG(4,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> set PROM+D2 latch", timer_get_time(), activecpu_get_previouspc(), offset, data));
928 		}
929 		else
930 		{
931 			type2_promaddr = data;
932 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> set PROM addr $%02x\n", timer_get_time(), activecpu_get_previouspc(), offset, data, type2_promaddr));
933 			return;
934 		}
935 	}
936 	else
937 	{
938 		LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s ", timer_get_time(), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041 DATA"));
939 	}
940 	if (1 == (offset & 1))
941 	{
942 		if (0xc0 == (data & 0xf0))
943 		{
944 			type2_xx_latch = 1;
945 			type2_d2_latch = (data & 0x04) ? 1 : 0;
946 			LOG(3,("PROM:%s D2:%d", type2_xx_latch ? "on" : "off", type2_d2_latch));
947 		}
948 	}
949 	cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
950 
951 #ifdef MAME_DEBUG
952 	decocass_fno(offset, data);
953 #endif
954 }
955 
956 /***************************************************************************
957  *
958  *	TYPE3 DONGLE
959  *	- Bump 'n Jump
960  *	- Burnin' Rubber
961  *	- Burger Time
962  *	- Graplop
963  *	- Cluster Buster
964  *	- LaPaPa
965  *	- Fighting Ice Hockey
966  *	- Pro Bowling
967  *	- Night Star
968  *	- Pro Soccer
969  *	- Peter Pepper's Ice Cream Factory
970  *
971  ***************************************************************************/
READ_HANDLER(decocass_type3_r)972 READ_HANDLER( decocass_type3_r )
973 {
974 	data8_t data, save;
975 
976 	if (1 == (offset & 1))
977 	{
978 		if (1 == type3_pal_19)
979 		{
980 			data8_t *prom = memory_region(REGION_USER1);
981 			data = prom[type3_ctrs];
982 			LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- prom[$%03x]\n", timer_get_time(), activecpu_get_previouspc(), offset, data, type3_ctrs));
983 			if (++type3_ctrs == 4096)
984 				type3_ctrs = 0;
985 		}
986 		else
987 		{
988 			if (0 == (offset & E5XX_MASK))
989 			{
990 				data = cpunum_get_reg(2, I8X41_STAT);
991 				LOG(4,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- 8041 STATUS\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
992 			}
993 			else
994 			{
995 				data = 0xff;	/* open data bus? */
996 				LOG(4,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- open bus\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
997 			}
998 		}
999 	}
1000 	else
1001 	{
1002 		if (1 == type3_pal_19)
1003 		{
1004 			save = data = 0xff;    /* open data bus? */
1005 			LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- open bus", timer_get_time(), activecpu_get_previouspc(), offset, data));
1006 		}
1007 		else
1008 		{
1009 			if (0 == (offset & E5XX_MASK))
1010 			{
1011 				save = cpunum_get_reg(2, I8X41_DATA);
1012 				if (type3_swap == TYPE3_SWAP_01)
1013 				{
1014 					data =
1015 						(BIT1(save) << 0) |
1016 						(type3_d0_latch << 1) |
1017 						(BIT2(save) << 2) |
1018 						(BIT3(save) << 3) |
1019 						(BIT4(save) << 4) |
1020 						(BIT5(save) << 5) |
1021 						(BIT6(save) << 6) |
1022 						(BIT7(save) << 7);
1023 					type3_d0_latch = save & 1;
1024 				}
1025 				else
1026 				if (type3_swap == TYPE3_SWAP_12)
1027 				{
1028 					data =
1029 						(type3_d0_latch << 0) |
1030 						(BIT2(save) << 1) |
1031 						(BIT1(save) << 2) |
1032 						(BIT3(save) << 3) |
1033 						(BIT4(save) << 4) |
1034 						(BIT5(save) << 5) |
1035 						(BIT6(save) << 6) |
1036 						(BIT7(save) << 7);
1037 					type3_d0_latch = save & 1;
1038 				}
1039 				else
1040 				if (type3_swap == TYPE3_SWAP_13)
1041 				{
1042 					data =
1043 						(type3_d0_latch << 0) |
1044 						(BIT3(save) << 1) |
1045 						(BIT2(save) << 2) |
1046 						(BIT1(save) << 3) |
1047 						(BIT4(save) << 4) |
1048 						(BIT5(save) << 5) |
1049 						(BIT6(save) << 6) |
1050 						(BIT7(save) << 7);
1051 					type3_d0_latch = save & 1;
1052 				}
1053 				else
1054 				if (type3_swap == TYPE3_SWAP_24)
1055 				{
1056 					data =
1057 						(type3_d0_latch << 0) |
1058 						(BIT1(save) << 1) |
1059 						(BIT4(save) << 2) |
1060 						(BIT3(save) << 3) |
1061 						(BIT2(save) << 4) |
1062 						(BIT5(save) << 5) |
1063 						(BIT6(save) << 6) |
1064 						(BIT7(save) << 7);
1065 					type3_d0_latch = save & 1;
1066 				}
1067 				else
1068 				if (type3_swap == TYPE3_SWAP_25)
1069 				{
1070 					data =
1071 						(type3_d0_latch << 0) |
1072 						(BIT1(save) << 1) |
1073 						(BIT5(save) << 2) |
1074 						(BIT3(save) << 3) |
1075 						(BIT4(save) << 4) |
1076 						(BIT2(save) << 5) |
1077 						(BIT6(save) << 6) |
1078 						(BIT7(save) << 7);
1079 					type3_d0_latch = save & 1;
1080 				}
1081 				else
1082 				if (type3_swap == TYPE3_SWAP_34_0)
1083 				{
1084 					data =
1085 						(type3_d0_latch << 0) |
1086 						(BIT1(save) << 1) |
1087 						(BIT2(save) << 2) |
1088 						(BIT3(save) << 4) |
1089 						(BIT4(save) << 3) |
1090 						(BIT5(save) << 5) |
1091 						(BIT6(save) << 6) |
1092 						(BIT7(save) << 7);
1093 					type3_d0_latch = save & 1;
1094 				}
1095 				else
1096 				if (type3_swap == TYPE3_SWAP_34_7)
1097 				{
1098 					data =
1099 						(BIT7(save) << 0) |
1100 						(BIT1(save) << 1) |
1101 						(BIT2(save) << 2) |
1102 						(BIT4(save) << 3) |
1103 						(BIT3(save) << 4) |
1104 						(BIT5(save) << 5) |
1105 						(BIT6(save) << 6) |
1106 						(type3_d0_latch << 7);
1107 					type3_d0_latch = save & 1;
1108 				}
1109 				else
1110 				if (type3_swap == TYPE3_SWAP_56)
1111 				{
1112 					data =
1113 						type3_d0_latch |
1114 						(BIT1(save) << 1) |
1115 						(BIT2(save) << 2) |
1116 						(BIT3(save) << 3) |
1117 						(BIT4(save) << 4) |
1118 						(BIT6(save) << 5) |
1119 						(BIT5(save) << 6) |
1120 						(BIT7(save) << 7);
1121 					type3_d0_latch = save & 1;
1122 				}
1123 				else
1124 				if (type3_swap == TYPE3_SWAP_67)
1125 				{
1126 					data =
1127 						type3_d0_latch |
1128 						(BIT1(save) << 1) |
1129 						(BIT2(save) << 2) |
1130 						(BIT3(save) << 3) |
1131 						(BIT4(save) << 4) |
1132 						(BIT5(save) << 5) |
1133 						(BIT7(save) << 6) |
1134 						(BIT6(save) << 7);
1135 					type3_d0_latch = save & 1;
1136 				}
1137 				else
1138 				{
1139 					data =
1140 						type3_d0_latch |
1141 						(BIT1(save) << 1) |
1142 						(BIT2(save) << 2) |
1143 						(BIT3(save) << 3) |
1144 						(BIT4(save) << 4) |
1145 						(BIT5(save) << 5) |
1146 						(BIT6(save) << 6) |
1147 						(BIT7(save) << 7);
1148 					type3_d0_latch = save & 1;
1149 				}
1150 				LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x '%c' <- 8041-DATA\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
1151 			}
1152 			else
1153 			{
1154 				save = 0xff;	/* open data bus? */
1155 				data =
1156 					type3_d0_latch |
1157 					(BIT1(save) << 1) |
1158 					(BIT2(save) << 2) |
1159 					(BIT3(save) << 3) |
1160 					(BIT4(save) << 4) |
1161 					(BIT5(save) << 5) |
1162 					(BIT6(save) << 7) |
1163 					(BIT7(save) << 6);
1164 				LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
1165 				type3_d0_latch = save & 1;
1166 			}
1167 		}
1168 	}
1169 
1170 	return data;
1171 }
1172 
WRITE_HANDLER(decocass_type3_w)1173 WRITE_HANDLER( decocass_type3_w )
1174 {
1175 	if (1 == (offset & 1))
1176 	{
1177 		if (1 == type3_pal_19)
1178 		{
1179 			type3_ctrs = data << 4;
1180 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, "LDCTRS"));
1181 			return;
1182 		}
1183 		else
1184 		if (0xc0 == (data & 0xf0))
1185 			type3_pal_19 = 1;
1186 	}
1187 	else
1188 	{
1189 		if (1 == type3_pal_19)
1190 		{
1191 			/* write nowhere?? */
1192 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, "nowhere?"));
1193 			return;
1194 		}
1195 	}
1196 	LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
1197 	cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
1198 }
1199 
1200 /***************************************************************************
1201  *
1202  *	TYPE4 DONGLE
1203  *	- Scrum Try
1204  *	Contains a 32K (EP)ROM that can be read from any byte
1205  *	boundary sequentially. The EPROM is enable after writing
1206  *	1100xxxx to E5x1 once. Then an address is written LSB
1207  *	to E5x0 MSB to E5x1 and every read from E5x1 returns the
1208  *	next byte of the contents.
1209  *
1210  ***************************************************************************/
1211 
READ_HANDLER(decocass_type4_r)1212 READ_HANDLER( decocass_type4_r )
1213 {
1214 	data8_t data;
1215 
1216 	if (1 == (offset & 1))
1217 	{
1218 		if (0 == (offset & E5XX_MASK))
1219 		{
1220 			data = cpunum_get_reg(2, I8X41_STAT);
1221 			LOG(4,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x <- 8041 STATUS\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1222 		}
1223 		else
1224 		{
1225 			data = 0xff;	/* open data bus? */
1226 			LOG(4,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x <- open bus\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1227 		}
1228 	}
1229 	else
1230 	{
1231 		if (type4_latch)
1232 		{
1233 			UINT8 *prom = memory_region(REGION_USER1);
1234 
1235 			data = prom[type4_ctrs];
1236 			LOG(3,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- PROM[%04x]\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.', type4_ctrs));
1237 			type4_ctrs = (type4_ctrs+1) & 0x7fff;
1238 		}
1239 		else
1240 		{
1241 			if (0 == (offset & E5XX_MASK))
1242 			{
1243 				data = cpunum_get_reg(2, I8X41_DATA);
1244 				LOG(3,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
1245 			}
1246 			else
1247 			{
1248 				data = 0xff;	/* open data bus? */
1249 				LOG(4,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x <- open bus\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1250 			}
1251 		}
1252 	}
1253 
1254 	return data;
1255 }
1256 
WRITE_HANDLER(decocass_type4_w)1257 WRITE_HANDLER( decocass_type4_w )
1258 {
1259 	if (1 == (offset & 1))
1260 	{
1261 		if (1 == type4_latch)
1262 		{
1263 			type4_ctrs = (type4_ctrs & 0x00ff) | ((data & 0x7f) << 8);
1264 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS MSB (%04x)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, type4_ctrs));
1265 			return;
1266 		}
1267 		else
1268 		if (0xc0 == (data & 0xf0))
1269 		{
1270 			type4_latch = 1;
1271 		}
1272 	}
1273 	else
1274 	{
1275 		if (type4_latch)
1276 		{
1277 			type4_ctrs = (type4_ctrs & 0xff00) | data;
1278 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS LSB (%04x)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, type4_ctrs));
1279 			return;
1280 		}
1281 	}
1282 	LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
1283 	cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
1284 }
1285 
1286 /***************************************************************************
1287  *
1288  *	TYPE5 DONGLE
1289  *	- Boulder Dash
1290  *	Actually a NOP dongle returning 0x55 after triggering a latch
1291  *	by writing 1100xxxx to E5x1
1292  *
1293  ***************************************************************************/
1294 
READ_HANDLER(decocass_type5_r)1295 READ_HANDLER( decocass_type5_r )
1296 {
1297 	data8_t data;
1298 
1299 	if (1 == (offset & 1))
1300 	{
1301 		if (0 == (offset & E5XX_MASK))
1302 		{
1303 			data = cpunum_get_reg(2, I8X41_STAT);
1304 			LOG(4,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x <- 8041 STATUS\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1305 		}
1306 		else
1307 		{
1308 			data = 0xff;	/* open data bus? */
1309 			LOG(4,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x <- open bus\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1310 		}
1311 	}
1312 	else
1313 	{
1314 		if (type5_latch)
1315 		{
1316 			data = 0x55;	/* Only a fixed value? It looks like this is all we need to do */
1317 			LOG(3,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- fixed value???\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
1318 		}
1319 		else
1320 		{
1321 			if (0 == (offset & E5XX_MASK))
1322 			{
1323 				data = cpunum_get_reg(2, I8X41_DATA);
1324 				LOG(3,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", timer_get_time(), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
1325 			}
1326 			else
1327 			{
1328 				data = 0xff;	/* open data bus? */
1329 				LOG(4,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x <- open bus\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1330 			}
1331 		}
1332 	}
1333 
1334 	return data;
1335 }
1336 
WRITE_HANDLER(decocass_type5_w)1337 WRITE_HANDLER( decocass_type5_w )
1338 {
1339 	if (1 == (offset & 1))
1340 	{
1341 		if (1 == type5_latch)
1342 		{
1343 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, "latch #2??"));
1344 			return;
1345 		}
1346 		else
1347 		if (0xc0 == (data & 0xf0))
1348 			type5_latch = 1;
1349 	}
1350 	else
1351 	{
1352 		if (type5_latch)
1353 		{
1354 			/* write nowhere?? */
1355 			LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, "nowhere?"));
1356 			return;
1357 		}
1358 	}
1359 	LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
1360 	cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
1361 }
1362 
1363 /***************************************************************************
1364  *
1365  *	Main dongle and 8041 interface
1366  *
1367  ***************************************************************************/
1368 
READ_HANDLER(decocass_e5xx_r)1369 READ_HANDLER( decocass_e5xx_r )
1370 {
1371 	data8_t data;
1372 
1373 	/* E5x2-E5x3 and mirrors */
1374 	if (2 == (offset & E5XX_MASK))
1375 	{
1376 		data =
1377 			(BIT7(i8041_p1) 	  << 0) |	/* D0 = P17 - REQ/ */
1378 			(BIT0(i8041_p2) 	  << 1) |	/* D1 = P20 - FNO/ */
1379 			(BIT1(i8041_p2) 	  << 2) |	/* D2 = P21 - EOT/ */
1380 			(BIT2(i8041_p2) 	  << 3) |	/* D3 = P22 - ERR/ */
1381 			((tape_bot_eot) 	  << 4) |	/* D4 = BOT/EOT (direct from drive) */
1382 			(1					  << 5) |	/* D5 floating input */
1383 			(1					  << 6) |	/* D6 floating input */
1384 			((1 - tape_present)   << 7);	/* D7 = cassette present */
1385 
1386 		LOG(4,("%9.7f 6502-PC: %04x decocass_e5xx_r(%02x): $%02x <- STATUS (%s%s%s%s%s%s%s%s)\n",
1387 			timer_get_time(),
1388 			activecpu_get_previouspc(),
1389 			offset, data,
1390 			data & 0x01 ? "" : "REQ/",
1391 			data & 0x02 ? "" : " FNO/",
1392 			data & 0x04 ? "" : " EOT/",
1393 			data & 0x08 ? "" : " ERR/",
1394 			data & 0x10 ? " [BOT-EOT]" : "",
1395 			data & 0x20 ? " [BIT5?]" : "",
1396 			data & 0x40 ? " [BIT6?]" : "",
1397 			data & 0x80 ? "" : " [CASS-PRESENT/]"));
1398 	}
1399 	else
1400 	{
1401 		if (decocass_dongle_r)
1402 			data = (*decocass_dongle_r)(offset);
1403 		else
1404 			data = 0xff;
1405 	}
1406 	return data;
1407 }
1408 
WRITE_HANDLER(decocass_e5xx_w)1409 WRITE_HANDLER( decocass_e5xx_w )
1410 {
1411 	if (decocass_dongle_w)
1412 	{
1413 		(*decocass_dongle_w)(offset, data);
1414 		return;
1415 	}
1416 
1417 	if (0 == (offset & E5XX_MASK))
1418 	{
1419 		LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", timer_get_time(), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
1420 		cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
1421 #ifdef MAME_DEBUG
1422 		decocass_fno(offset, data);
1423 #endif
1424 	}
1425 	else
1426 	{
1427 		LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> dongle\n", timer_get_time(), activecpu_get_previouspc(), offset, data));
1428 	}
1429 }
1430 
1431 /***************************************************************************
1432  *
1433  *	init machine functions (select dongle and determine tape image size)
1434  *
1435  ***************************************************************************/
decocass_state_save_postload(void)1436 static void decocass_state_save_postload(void)
1437 {
1438 	int A;
1439 	unsigned char *mem = memory_region(REGION_CPU1);
1440 	int diff = memory_region_length(REGION_CPU1) / 2;
1441 
1442 	memory_set_opcode_base(0, mem + diff);
1443 
1444 	for (A = 0;A < 0x10000; A++)
1445 		decocass_w(A, mem[A]);
1446 	/* restart the timer if the tape was playing */
1447 	if (0 != tape_dir)
1448 		timer_adjust(tape_timer, TIME_NEVER, 0, 0);
1449 }
1450 
decocass_init_common(void)1451 void decocass_init_common(void)
1452 {
1453 	UINT8 *image = memory_region(REGION_USER2);
1454 	int i, offs;
1455 
1456 	tape_dir = 0;
1457 	tape_speed = 0;
1458 	tape_timer = timer_alloc(NULL);
1459 
1460 	firsttime = 1;
1461 	tape_present = 1;
1462 	tape_blocks = 0;
1463 	for (i = memory_region_length(REGION_USER2) / 256 - 1; !tape_blocks && i > 0; i--)
1464 		for (offs = 256 * i; !tape_blocks && offs < 256 * i + 256; offs++)
1465 			if (image[offs])
1466 				tape_blocks = i+1;
1467 	for (i = 0; i < tape_blocks; i++)
1468 	{
1469 		crc16_lsb = 0;
1470 		crc16_msb = 0;
1471 		for (offs = 256 * i; offs < 256 * i + 256; offs++)
1472 		{
1473 			tape_crc16(image[offs] << 7);
1474 			tape_crc16(image[offs] << 6);
1475 			tape_crc16(image[offs] << 5);
1476 			tape_crc16(image[offs] << 4);
1477 			tape_crc16(image[offs] << 3);
1478 			tape_crc16(image[offs] << 2);
1479 			tape_crc16(image[offs] << 1);
1480 			tape_crc16(image[offs] << 0);
1481 		}
1482 		tape_crc16_lsb[i] = crc16_lsb;
1483 		tape_crc16_msb[i] = crc16_msb;
1484 	}
1485 
1486 	tape_length = tape_blocks * TAPE_CHUNK * 8 * 2 + 2 * (TAPE_LEADER + TAPE_GAP + TAPE_HOLE);
1487 	tape_time0 = (double)(TAPE_LEADER + TAPE_GAP - TAPE_HOLE) / TAPE_CLOCKRATE;
1488 	LOG(0,("tape: %d blocks\n", tape_blocks));
1489 	tape_bot_eot = 0;
1490 
1491 	decocass_dongle_r = NULL;
1492 	decocass_dongle_w = NULL;
1493 
1494 	decocass_reset = 0;
1495 	i8041_p1 = 0xff;
1496 	i8041_p2 = 0xff;
1497 
1498 	type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
1499 	type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
1500 
1501 	type2_d2_latch = 0;
1502 	type2_xx_latch = 0;
1503 	type2_promaddr = 0;
1504 
1505 	type3_ctrs = 0;
1506 	type3_d0_latch = 0;
1507 	type3_pal_19 = 0;
1508 	type3_swap = 0;
1509 
1510 	memset(decocass_quadrature_decoder, 0, sizeof(decocass_quadrature_decoder));
1511 	decocass_sound_ack = 0;
1512 	decocass_sound_timer = timer_alloc(decocass_sound_nmi_pulse);
1513 
1514 	/* state saving code */
1515 	state_save_register_func_postload(decocass_state_save_postload);
1516 	state_save_register_int 	("decocass", 0, "tape_dir", &tape_dir);
1517 	state_save_register_int 	("decocass", 0, "tape_speed", &tape_speed);
1518 	state_save_register_double	("decocass", 0, "tape_time0", &tape_time0, 1);
1519 	state_save_register_int 	("decocass", 0, "firsttime", &firsttime);
1520 	state_save_register_int 	("decocass", 0, "tape_present", &tape_present);
1521 	state_save_register_int 	("decocass", 0, "tape_blocks", &tape_blocks);
1522 	state_save_register_int 	("decocass", 0, "tape_length", &tape_length);
1523 	state_save_register_int 	("decocass", 0, "tape_bot_eot", &tape_bot_eot);
1524 	state_save_register_UINT8	("decocass", 0, "crc16_lsb", &crc16_lsb, 1);
1525 	state_save_register_UINT8	("decocass", 0, "crc16_msb", &crc16_msb, 1);
1526 	state_save_register_UINT8	("decocass", 0, "tape_crc16_lsb", tape_crc16_lsb, 256);
1527 	state_save_register_UINT8	("decocass", 0, "tape_crc16_msb", tape_crc16_msb, 256);
1528 	state_save_register_UINT8	("decocass", 0, "decocass_reset", &decocass_reset, 1);
1529 	state_save_register_UINT8	("decocass", 0, "i8041_p1", &i8041_p1, 1);
1530 	state_save_register_UINT8	("decocass", 0, "i8041_p2", &i8041_p2, 1);
1531 	state_save_register_UINT32	("decocass", 0, "type1_inmap", &type1_inmap, 1);
1532 	state_save_register_UINT32	("decocass", 0, "type1_outmap", &type1_outmap, 1);
1533 	state_save_register_int 	("decocass", 0, "type2_d2_latch", &type2_d2_latch);
1534 	state_save_register_int 	("decocass", 0, "type2_xx_latch", &type2_xx_latch);
1535 	state_save_register_int 	("decocass", 0, "type2_promaddr", &type2_promaddr);
1536 	state_save_register_int 	("decocass", 0, "type3_ctrs", &type3_ctrs);
1537 	state_save_register_int 	("decocass", 0, "type3_d0_latch", &type3_d0_latch);
1538 	state_save_register_int 	("decocass", 0, "type3_pal_19", &type3_pal_19);
1539 	state_save_register_int 	("decocass", 0, "type3_swap", &type3_swap);
1540 	state_save_register_int 	("decocass", 0, "type4_ctrs", &type4_ctrs);
1541 	state_save_register_int 	("decocass", 0, "type4_latch", &type4_latch);
1542 	state_save_register_int 	("decocass", 0, "type5_latch", &type5_latch);
1543 	state_save_register_UINT8	("decocass", 0, "decocass_sound_ack", &decocass_sound_ack, 1);
1544 }
1545 
MACHINE_INIT(decocass)1546 MACHINE_INIT( decocass )
1547 {
1548 	decocass_init_common();
1549 }
1550 
MACHINE_INIT(ctsttape)1551 MACHINE_INIT( ctsttape )
1552 {
1553 	decocass_init_common();
1554 	LOG(0,("dongle type #1 (DE-0061)\n"));
1555 	decocass_dongle_r = decocass_type1_map1_r;
1556 }
1557 
MACHINE_INIT(clocknch)1558 MACHINE_INIT( clocknch )
1559 {
1560 	decocass_init_common();
1561 	LOG(0,("dongle type #1 (DE-0061 flip 2-3)\n"));
1562 	decocass_dongle_r = decocass_type1_r;
1563 	type1_inmap = MAKE_MAP(0,1,3,2,4,5,6,7);
1564 	type1_outmap = MAKE_MAP(0,1,3,2,4,5,6,7);
1565 }
1566 
MACHINE_INIT(ctisland)1567 MACHINE_INIT( ctisland )
1568 {
1569 	decocass_init_common();
1570 	LOG(0,("dongle type #1 (DE-0061 flip 0-2)\n"));
1571 	decocass_dongle_r = decocass_type1_r;
1572 	type1_inmap = MAKE_MAP(2,1,0,3,4,5,6,7);
1573 	type1_outmap = MAKE_MAP(2,1,0,3,4,5,6,7);
1574 }
1575 
MACHINE_INIT(csuperas)1576 MACHINE_INIT( csuperas )
1577 {
1578 	decocass_init_common();
1579 	LOG(0,("dongle type #1 (DE-0061 flip 4-5)\n"));
1580 	decocass_dongle_r = decocass_type1_r;
1581 	type1_inmap = MAKE_MAP(0,1,2,3,5,4,6,7);
1582 	type1_outmap = MAKE_MAP(0,1,2,3,5,4,6,7);
1583 }
1584 
MACHINE_INIT(castfant)1585 MACHINE_INIT( castfant )
1586 {
1587 	decocass_init_common();
1588 	LOG(0,("dongle type #1 (DE-0061 flip 1-2)\n"));
1589 	decocass_dongle_r = decocass_type1_map3_r;
1590 }
1591 
MACHINE_INIT(cluckypo)1592 MACHINE_INIT( cluckypo )
1593 {
1594 	decocass_init_common();
1595 	LOG(0,("dongle type #1 (DE-0061 flip 1-3)\n"));
1596 	decocass_dongle_r = decocass_type1_r;
1597 	type1_inmap = MAKE_MAP(0,3,2,1,4,5,6,7);
1598 	type1_outmap = MAKE_MAP(0,3,2,1,4,5,6,7);
1599 }
1600 
MACHINE_INIT(cterrani)1601 MACHINE_INIT( cterrani )
1602 {
1603 	decocass_init_common();
1604 	LOG(0,("dongle type #1 (DE-0061 straight)\n"));
1605 	decocass_dongle_r = decocass_type1_r;
1606 	type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
1607 	type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
1608 }
1609 
MACHINE_INIT(cexplore)1610 MACHINE_INIT( cexplore )
1611 {
1612 	decocass_init_common();
1613 	LOG(0,("dongle type #1 (DE-0061)\n"));
1614 	decocass_dongle_r = decocass_type1_map2_r;
1615 }
1616 
MACHINE_INIT(cprogolf)1617 MACHINE_INIT( cprogolf )
1618 {
1619 	decocass_init_common();
1620 	LOG(0,("dongle type #1 (DE-0061 flip 0-1)\n"));
1621 	decocass_dongle_r = decocass_type1_r;
1622 	type1_inmap = MAKE_MAP(1,0,2,3,4,5,6,7);
1623 	type1_outmap = MAKE_MAP(1,0,2,3,4,5,6,7);
1624 }
1625 
MACHINE_INIT(cmissnx)1626 MACHINE_INIT( cmissnx )
1627 {
1628 	decocass_init_common();
1629 	LOG(0,("dongle type #2 (CS82-007)\n"));
1630 	decocass_dongle_r = decocass_type2_r;
1631 	decocass_dongle_w = decocass_type2_w;
1632 }
1633 
MACHINE_INIT(cdiscon1)1634 MACHINE_INIT( cdiscon1 )
1635 {
1636 	decocass_init_common();
1637 	LOG(0,("dongle type #2 (CS82-007)\n"));
1638 	decocass_dongle_r = decocass_type2_r;
1639 	decocass_dongle_w = decocass_type2_w;
1640 }
1641 
MACHINE_INIT(cptennis)1642 MACHINE_INIT( cptennis )
1643 {
1644 	decocass_init_common();
1645 	LOG(0,("dongle type #2 (CS82-007)\n"));
1646 	decocass_dongle_r = decocass_type2_r;
1647 	decocass_dongle_w = decocass_type2_w;
1648 }
1649 
MACHINE_INIT(ctornado)1650 MACHINE_INIT( ctornado )
1651 {
1652 	decocass_init_common();
1653 	LOG(0,("dongle type #2 (CS82-007)\n"));
1654 	decocass_dongle_r = decocass_type2_r;
1655 	decocass_dongle_w = decocass_type2_w;
1656 }
1657 
MACHINE_INIT(cbnj)1658 MACHINE_INIT( cbnj )
1659 {
1660 	decocass_init_common();
1661 	LOG(0,("dongle type #3 (PAL)\n"));
1662 	decocass_dongle_r = decocass_type3_r;
1663 	decocass_dongle_w = decocass_type3_w;
1664 	type3_swap = TYPE3_SWAP_67;
1665 }
1666 
MACHINE_INIT(cburnrub)1667 MACHINE_INIT( cburnrub )
1668 {
1669 	decocass_init_common();
1670 	LOG(0,("dongle type #3 (PAL)\n"));
1671 	decocass_dongle_r = decocass_type3_r;
1672 	decocass_dongle_w = decocass_type3_w;
1673 	type3_swap = TYPE3_SWAP_67;
1674 }
1675 
MACHINE_INIT(cbtime)1676 MACHINE_INIT( cbtime )
1677 {
1678 	decocass_init_common();
1679 	LOG(0,("dongle type #3 (PAL)\n"));
1680 	decocass_dongle_r = decocass_type3_r;
1681 	decocass_dongle_w = decocass_type3_w;
1682 	type3_swap = TYPE3_SWAP_12;
1683 }
1684 
MACHINE_INIT(cgraplop)1685 MACHINE_INIT( cgraplop )
1686 {
1687 	decocass_init_common();
1688 	LOG(0,("dongle type #3 (PAL)\n"));
1689 	decocass_dongle_r = decocass_type3_r;
1690 	decocass_dongle_w = decocass_type3_w;
1691 	type3_swap = TYPE3_SWAP_56;
1692 }
1693 
MACHINE_INIT(clapapa)1694 MACHINE_INIT( clapapa )
1695 {
1696 	decocass_init_common();
1697 	LOG(0,("dongle type #3 (PAL)\n"));
1698 	decocass_dongle_r = decocass_type3_r;
1699 	decocass_dongle_w = decocass_type3_w;
1700 	type3_swap = TYPE3_SWAP_34_7;
1701 }
1702 
MACHINE_INIT(cfghtice)1703 MACHINE_INIT( cfghtice )
1704 {
1705 	decocass_init_common();
1706 	LOG(0,("dongle type #3 (PAL)\n"));
1707 	decocass_dongle_r = decocass_type3_r;
1708 	decocass_dongle_w = decocass_type3_w;
1709 	type3_swap = TYPE3_SWAP_25;
1710 }
1711 
MACHINE_INIT(cprobowl)1712 MACHINE_INIT( cprobowl )
1713 {
1714 	decocass_init_common();
1715 	LOG(0,("dongle type #3 (PAL)\n"));
1716 	decocass_dongle_r = decocass_type3_r;
1717 	decocass_dongle_w = decocass_type3_w;
1718 	type3_swap = TYPE3_SWAP_34_0;
1719 }
1720 
MACHINE_INIT(cnightst)1721 MACHINE_INIT( cnightst )
1722 {
1723 	decocass_init_common();
1724 	LOG(0,("dongle type #3 (PAL)\n"));
1725 	decocass_dongle_r = decocass_type3_r;
1726 	decocass_dongle_w = decocass_type3_w;
1727 	type3_swap = TYPE3_SWAP_13;
1728 }
1729 
MACHINE_INIT(cprosocc)1730 MACHINE_INIT( cprosocc )
1731 {
1732 	decocass_init_common();
1733 	LOG(0,("dongle type #3 (PAL)\n"));
1734 	decocass_dongle_r = decocass_type3_r;
1735 	decocass_dongle_w = decocass_type3_w;
1736 	type3_swap = TYPE3_SWAP_24;
1737 }
1738 
MACHINE_INIT(cppicf)1739 MACHINE_INIT( cppicf )
1740 {
1741 	decocass_init_common();
1742 	LOG(0,("dongle type #3 (PAL)\n"));
1743 	decocass_dongle_r = decocass_type3_r;
1744 	decocass_dongle_w = decocass_type3_w;
1745 	type3_swap = TYPE3_SWAP_01;
1746 }
1747 
MACHINE_INIT(cscrtry)1748 MACHINE_INIT( cscrtry )
1749 {
1750 	decocass_init_common();
1751 	LOG(0,("dongle type #4 (32K ROM)\n"));
1752 	decocass_dongle_r = decocass_type4_r;
1753 	decocass_dongle_w = decocass_type4_w;
1754 }
1755 
MACHINE_INIT(cbdash)1756 MACHINE_INIT( cbdash )
1757 {
1758 	decocass_init_common();
1759 	LOG(0,("dongle type #5 (NOP)\n"));
1760 	decocass_dongle_r = decocass_type5_r;
1761 	decocass_dongle_w = decocass_type5_w;
1762 }
1763 
1764 /***************************************************************************
1765  *
1766  *	8041 port handlers
1767  *
1768  ***************************************************************************/
1769 
tape_stop(void)1770 static void tape_stop(void)
1771 {
1772 	/* remember time */
1773 	tape_time0 += tape_dir * timer_timeelapsed(tape_timer);
1774 	timer_adjust(tape_timer, TIME_NEVER, 0, 0);
1775 }
1776 
1777 
WRITE_HANDLER(i8041_p1_w)1778 WRITE_HANDLER( i8041_p1_w )
1779 {
1780 	static int i8041_p1_old;
1781 
1782 	if (data != i8041_p1_old)
1783 	{
1784 		LOG(4,("%9.7f 8041-PC: %03x i8041_p1_w: $%02x (%s%s%s%s%s%s%s%s)\n",
1785 			timer_get_time(),
1786 			activecpu_get_previouspc(),
1787 			data,
1788 			data & 0x01 ? "" : "DATA-WRT",
1789 			data & 0x02 ? "" : " DATA-CLK",
1790 			data & 0x04 ? "" : " FAST",
1791 			data & 0x08 ? "" : " BIT3",
1792 			data & 0x10 ? "" : " REW",
1793 			data & 0x20 ? "" : " FWD",
1794 			data & 0x40 ? "" : " WREN",
1795 			data & 0x80 ? "" : " REQ"));
1796 		i8041_p1_old = data;
1797 	}
1798 
1799 	/* change in REW signal ? */
1800 	if ((data ^ i8041_p1) & 0x10)
1801 	{
1802 		tape_stop();
1803 		if (0 == (data & 0x10))
1804 		{
1805 			LOG(2,("tape %5.4fs: rewind\n", tape_time0));
1806 			tape_dir = -1;
1807 			timer_adjust(tape_timer, TIME_NEVER, 0, 0);
1808 			set_led_status(0, 1);
1809 		}
1810 		else
1811 		{
1812 			tape_dir = 0;
1813 			tape_speed = 0;
1814 			LOG(2,("tape %5.4fs: stopped\n", tape_time0));
1815 #if TAPE_UI_DISPLAY
1816 			usrintf_showmessage("   [%05.1fs]   ", tape_time0);
1817 #endif
1818 			set_led_status(0, 0);
1819 		}
1820 	}
1821 
1822 	/* change in FWD signal ? */
1823 	if ((data ^ i8041_p1) & 0x20)
1824 	{
1825 		tape_stop();
1826 		if (0 == (data & 0x20))
1827 		{
1828 			LOG(2,("tape %5.4fs: forward\n", tape_time0));
1829 			tape_dir = +1;
1830 			timer_adjust(tape_timer, TIME_NEVER, 0, 0);
1831 			set_led_status(0, 1);
1832 		}
1833 		else
1834 		{
1835 			tape_dir = 0;
1836 			tape_speed = 0;
1837 			LOG(2,("tape %5.4fs: stopped\n", tape_time0));
1838 #if TAPE_UI_DISPLAY
1839 			usrintf_showmessage("   [%05.1fs]   ", tape_time0);
1840 #endif
1841 			set_led_status(0, 0);
1842 		}
1843 	}
1844 
1845 	/* change in FAST signal ? */
1846 	if (tape_timer && (data ^ i8041_p1) & 0x04)
1847 	{
1848 		tape_stop();
1849 		tape_speed = (0 == (data & 0x04)) ? 1 : 0;
1850 
1851 		if (tape_dir < 0)
1852 		{
1853 			LOG(2,("tape: fast rewind %s\n", (0 == (data & 0x04)) ? "on" : "off"));
1854 			tape_dir = (tape_speed) ? -7 : -1;
1855 			timer_adjust(tape_timer, TIME_NEVER, 0, 0);
1856 		}
1857 		else
1858 		if (tape_dir > 0)
1859 		{
1860 			LOG(2,("tape: fast forward %s\n", (0 == (data & 0x04)) ? "on" : "off"));
1861 			tape_dir = (tape_speed) ? +7 : +1;
1862 			timer_adjust(tape_timer, TIME_NEVER, 0, 0);
1863 		}
1864 	}
1865 
1866 	i8041_p1 = data;
1867 }
1868 
READ_HANDLER(i8041_p1_r)1869 READ_HANDLER( i8041_p1_r )
1870 {
1871 	data8_t data = i8041_p1;
1872 	static int i8041_p1_old;
1873 
1874 	if (data != i8041_p1_old)
1875 	{
1876 		LOG(4,("%9.7f 8041-PC: %03x i8041_p1_r: $%02x (%s%s%s%s%s%s%s%s)\n",
1877 			timer_get_time(),
1878 			activecpu_get_previouspc(),
1879 			data,
1880 			data & 0x01 ? "" : "DATA-WRT",
1881 			data & 0x02 ? "" : " DATA-CLK",
1882 			data & 0x04 ? "" : " FAST",
1883 			data & 0x08 ? "" : " BIT3",
1884 			data & 0x10 ? "" : " REW",
1885 			data & 0x20 ? "" : " FWD",
1886 			data & 0x40 ? "" : " WREN",
1887 			data & 0x80 ? "" : " REQ"));
1888 		i8041_p1_old = data;
1889 	}
1890 	return data;
1891 }
1892 
WRITE_HANDLER(i8041_p2_w)1893 WRITE_HANDLER( i8041_p2_w )
1894 {
1895 	static int i8041_p2_old;
1896 
1897 	if (data != i8041_p2_old)
1898 	{
1899 		LOG(4,("%9.7f 8041-PC: %03x i8041_p2_w: $%02x (%s%s%s%s%s%s%s%s)\n",
1900 			timer_get_time(),
1901 			activecpu_get_previouspc(),
1902 			data,
1903 			data & 0x01 ? "" : "FNO/",
1904 			data & 0x02 ? "" : " EOT/",
1905 			data & 0x04 ? "" : " ERR/",
1906 			data & 0x08 ? "" : " OUT3?/",
1907 			data & 0x10 ? " [IN4]" : "",
1908 			data & 0x20 ? " [BOT-EOT]" : "",
1909 			data & 0x40 ? " [RCLK]" : "",
1910 			data & 0x80 ? " [RDATA]" : ""));
1911 		i8041_p2_old = data;
1912 	}
1913 	i8041_p2 = data;
1914 }
1915 
READ_HANDLER(i8041_p2_r)1916 READ_HANDLER( i8041_p2_r )
1917 {
1918 	data8_t data;
1919 	static int i8041_p2_old;
1920 
1921 	tape_update();
1922 
1923 	data = i8041_p2;
1924 
1925 	if (data != i8041_p2_old)
1926 	{
1927 		LOG(4,("%9.7f 8041-PC: %03x i8041_p2_r: $%02x (%s%s%s%s%s%s%s%s)\n",
1928 			timer_get_time(),
1929 			activecpu_get_previouspc(),
1930 			data,
1931 			data & 0x01 ? "" : "FNO/",
1932 			data & 0x02 ? "" : " EOT/",
1933 			data & 0x04 ? "" : " ERR/",
1934 			data & 0x08 ? "" : " OUT3?/",
1935 			data & 0x10 ? " [IN4]" : "",
1936 			data & 0x20 ? " [BOT-EOT]" : "",
1937 			data & 0x40 ? " [RCLK]" : "",
1938 			data & 0x80 ? " [RDATA]" : ""));
1939 		i8041_p2_old = data;
1940 	}
1941 	return data;
1942 }
1943 
1944 
1945