1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     Emulation of various Midway ICs
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "debugger.h"
11 #include "midwayic.h"
12 
13 
14 #define LOG_NVRAM           (0)
15 
16 #define PRINTF_DEBUG        (0)
17 #define LOG_IOASIC          (0)
18 #define LOG_FIFO            (0)
19 
20 
21 /*************************************
22  *
23  *  Constants
24  *
25  *************************************/
26 
27 #define FIFO_SIZE           512
28 
29 /*************************************
30  *
31  *  Serial number input kludge
32  *
33  *************************************/
34 
35 static INPUT_PORTS_START( pic_serial_adjust )
36 	PORT_START("SERIAL_DIGIT")
37 	PORT_DIPNAME( 0x0f, 0x06, "Serial Low Digit")
38 	PORT_DIPSETTING(    0x00, "0")
39 	PORT_DIPSETTING(    0x01, "1")
40 	PORT_DIPSETTING(    0x02, "2")
41 	PORT_DIPSETTING(    0x03, "3")
42 	PORT_DIPSETTING(    0x04, "4")
43 	PORT_DIPSETTING(    0x05, "5")
44 	PORT_DIPSETTING(    0x06, "6")
45 	PORT_DIPSETTING(    0x07, "7")
46 	PORT_DIPSETTING(    0x08, "8")
47 	PORT_DIPSETTING(    0x09, "9")
48 	PORT_BIT( 0xf0, 0x00, IPT_UNUSED )
49 INPUT_PORTS_END
50 
device_input_ports() const51 ioport_constructor midway_serial_pic_device::device_input_ports() const
52 {
53 	return INPUT_PORTS_NAME(pic_serial_adjust);
54 }
55 
56 /*************************************
57  *
58  *  Serial number encoding
59  *
60  *************************************/
61 
generate_serial_data(int upper)62 void midway_serial_pic_device::generate_serial_data(int upper)
63 {
64 	int year = atoi(machine().system().year), month = 12, day = 11;
65 	uint32_t serial_number, temp;
66 	uint8_t serial_digit[9];
67 
68 	serial_number = 123450;
69 	serial_number += upper * 1000000;
70 	serial_number += m_io_serial_digit->read() & 0x0f;
71 
72 	serial_digit[0] = (serial_number / 100000000) % 10;
73 	serial_digit[1] = (serial_number / 10000000) % 10;
74 	serial_digit[2] = (serial_number / 1000000) % 10;
75 	serial_digit[3] = (serial_number / 100000) % 10;
76 	serial_digit[4] = (serial_number / 10000) % 10;
77 	serial_digit[5] = (serial_number / 1000) % 10;
78 	serial_digit[6] = (serial_number / 100) % 10;
79 	serial_digit[7] = (serial_number / 10) % 10;
80 	serial_digit[8] = (serial_number / 1) % 10;
81 
82 	m_data[12] = machine().rand() & 0xff;
83 	m_data[13] = machine().rand() & 0xff;
84 
85 	m_data[14] = 0; /* ??? */
86 	m_data[15] = 0; /* ??? */
87 
88 	temp = 0x174 * (year - 1980) + 0x1f * (month - 1) + day;
89 	m_data[10] = (temp >> 8) & 0xff;
90 	m_data[11] = temp & 0xff;
91 
92 	temp = serial_digit[4] + serial_digit[7] * 10 + serial_digit[1] * 100;
93 	temp = (temp + 5 * m_data[13]) * 0x1bcd + 0x1f3f0;
94 	m_data[7] = temp & 0xff;
95 	m_data[8] = (temp >> 8) & 0xff;
96 	m_data[9] = (temp >> 16) & 0xff;
97 
98 	temp = serial_digit[6] + serial_digit[8] * 10 + serial_digit[0] * 100 + serial_digit[2] * 10000;
99 	temp = (temp + 2 * m_data[13] + m_data[12]) * 0x107f + 0x71e259;
100 	m_data[3] = temp & 0xff;
101 	m_data[4] = (temp >> 8) & 0xff;
102 	m_data[5] = (temp >> 16) & 0xff;
103 	m_data[6] = (temp >> 24) & 0xff;
104 
105 	temp = serial_digit[5] * 10 + serial_digit[3] * 100;
106 	temp = (temp + m_data[12]) * 0x245 + 0x3d74;
107 	m_data[0] = temp & 0xff;
108 	m_data[1] = (temp >> 8) & 0xff;
109 	m_data[2] = (temp >> 16) & 0xff;
110 }
111 
112 
113 
114 /*************************************
115  *
116  *  Original serial number PIC
117  *  interface - simulation
118  *
119  *************************************/
120 
serial_register_state()121 void midway_serial_pic_device::serial_register_state()
122 {
123 	save_item(NAME(m_data));
124 	save_item(NAME(m_buff));
125 	save_item(NAME(m_idx));
126 	save_item(NAME(m_status));
127 	save_item(NAME(m_bits));
128 }
129 
130 DEFINE_DEVICE_TYPE(MIDWAY_SERIAL_PIC, midway_serial_pic_device, "midway_serial_pic_sim", "Midway Serial PIC Simulation")
131 
132 
133 //-------------------------------------------------
134 //  midway_serial_pic_device - constructor
135 //-------------------------------------------------
136 
midway_serial_pic_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)137 midway_serial_pic_device::midway_serial_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
138 	midway_serial_pic_device(mconfig, MIDWAY_SERIAL_PIC, tag, owner, clock)
139 {
140 }
141 
midway_serial_pic_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)142 midway_serial_pic_device::midway_serial_pic_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
143 	device_t(mconfig, type, tag, owner, clock),
144 	m_io_serial_digit(*this, "SERIAL_DIGIT"),
145 	m_upper(0),
146 	m_buff(0),
147 	m_idx(0),
148 	m_status(0),
149 	m_bits(0)
150 {
151 	memset(m_data,0,sizeof(m_data));
152 }
153 
154 //-------------------------------------------------
155 //  device_start - device-specific startup
156 //-------------------------------------------------
157 
device_start()158 void midway_serial_pic_device::device_start()
159 {
160 	serial_register_state();
161 }
162 
device_reset()163 void midway_serial_pic_device::device_reset()
164 {
165 	generate_serial_data(m_upper);
166 }
167 
WRITE_LINE_MEMBER(midway_serial_pic_device::reset_w)168 WRITE_LINE_MEMBER(midway_serial_pic_device::reset_w)
169 {
170 	if (state)
171 	{
172 		m_idx = 0;
173 		m_status = 0;
174 		m_buff = 0;
175 	}
176 }
177 
178 
status_r()179 u8 midway_serial_pic_device::status_r()
180 {
181 	return m_status;
182 }
183 
184 
read()185 u8 midway_serial_pic_device::read()
186 {
187 	if (!machine().side_effects_disabled())
188 	{
189 		logerror("%s:security R = %04X\n", machine().describe_context(), m_buff);
190 		m_status = 1;
191 	}
192 	return m_buff;
193 }
194 
195 
write(u8 data)196 void midway_serial_pic_device::write(u8 data)
197 {
198 	logerror("%s:security W = %04X\n", machine().describe_context(), data);
199 
200 	/* status seems to reflect the clock bit */
201 	m_status = (data >> 4) & 1;
202 
203 	/* on the falling edge, clock the next data byte through */
204 	if (!m_status)
205 	{
206 		/* the self-test writes 1F, 0F, and expects to read an F in the low 4 bits */
207 		if (data & 0x0f)
208 			m_buff = data & 0xf;
209 		else
210 			m_buff = m_data[m_idx++ % sizeof(m_data)];
211 	}
212 }
213 
214 
215 /*************************************
216  *
217  *  Original serial number PIC
218  *  interface - emulation
219  *
220  *  PIC16C57 wiring notes:
221  *  PORTA - 4bit command in (usually 0 = read SN#)
222  *  PORTB - 8bit data out
223  *  PORTC bit 7 - access clock in
224  *  PORTC bit 6 - status out
225  *  PORTC bit 2 - in/out (optional) MK41T56N RTC/NVRAM Data
226  *  PORTC bit 1 - out (optional) MK41T56N RTC/NVRAM Clock
227  *
228  *************************************/
229 
230 
231 DEFINE_DEVICE_TYPE(MIDWAY_SERIAL_PIC_EMU, midway_serial_pic_emu_device, "midway_serial_pic_emu", "Midway Serial PIC Emulation")
232 
233 
234 //-------------------------------------------------
235 //  midway_serial_pic_emu_device - constructor
236 //-------------------------------------------------
237 
midway_serial_pic_emu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)238 midway_serial_pic_emu_device::midway_serial_pic_emu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
239 	device_t(mconfig, MIDWAY_SERIAL_PIC_EMU, tag, owner, clock)
240 	, m_pic(*this, "pic")
241 {
242 }
243 
244 //-------------------------------------------------
245 //  device_start - device-specific startup
246 //-------------------------------------------------
247 
device_start()248 void midway_serial_pic_emu_device::device_start()
249 {
250 	save_item(NAME(m_command));
251 	save_item(NAME(m_data_out));
252 	save_item(NAME(m_clk));
253 	save_item(NAME(m_status));
254 
255 	m_command = 0;
256 	m_data_out = 0;
257 	m_clk = 0;
258 	m_status = 0;
259 }
260 
WRITE_LINE_MEMBER(midway_serial_pic_emu_device::reset_w)261 WRITE_LINE_MEMBER(midway_serial_pic_emu_device::reset_w)
262 {
263 	if (!state) // fixme, PIC should be stopped while 0 and start running at 0->1 transition
264 		m_pic->reset();
265 }
266 
status_r()267 u8 midway_serial_pic_emu_device::status_r()
268 {
269 	return m_status;
270 }
271 
read()272 u8 midway_serial_pic_emu_device::read()
273 {
274 	return m_data_out;
275 }
276 
write(u8 data)277 void midway_serial_pic_emu_device::write(u8 data)
278 {
279 	// perhaps this should be split in 2 handlers ?
280 	m_command = data & 0x0f;
281 	m_clk = BIT(data, 4);
282 }
283 
read_c()284 u8 midway_serial_pic_emu_device::read_c()
285 {
286 	u8 data = 0;
287 	data |= m_clk << 7;
288 	// bit 2 RTC Data
289 	return data;
290 }
291 
write_c(u8 data)292 void midway_serial_pic_emu_device::write_c(u8 data)
293 {
294 	m_status = BIT(data, 6);
295 	// bits 1 and 2 is RTC Clock and Data
296 //  printf("%s: write_c %02x\n", machine().describe_context().c_str(), data);
297 }
298 
device_add_mconfig(machine_config & config)299 void midway_serial_pic_emu_device::device_add_mconfig(machine_config &config)
300 {
301 	PIC16C57(config, m_pic, 4000000);    /* ? Mhz */
302 	m_pic->read_a().set([this]() { return m_command; });
303 	m_pic->write_b().set([this](u8 data) { m_data_out = data; });
304 	m_pic->read_c().set(FUNC(midway_serial_pic_emu_device::read_c));
305 	m_pic->write_c().set(FUNC(midway_serial_pic_emu_device::write_c));
306 }
307 
308 
309 /*************************************
310  *
311  *  Second generation serial number
312  *  PIC interface; this version also
313  *  contained some NVRAM and a real
314  *  time clock
315  *
316  *************************************/
317 
make_bcd(uint8_t data)318 static inline uint8_t make_bcd(uint8_t data)
319 {
320 	return ((data / 10) << 4) | (data % 10);
321 }
322 
323 DEFINE_DEVICE_TYPE(MIDWAY_SERIAL_PIC2, midway_serial_pic2_device, "midway_serial_pic2", "Midway Serial PIC 2")
324 
325 
326 //-------------------------------------------------
327 //  midway_serial_pic2_device - constructor
328 //-------------------------------------------------
329 
midway_serial_pic2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)330 midway_serial_pic2_device::midway_serial_pic2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
331 	midway_serial_pic2_device(mconfig, MIDWAY_SERIAL_PIC2, tag, owner, clock)
332 {
333 }
334 
midway_serial_pic2_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)335 midway_serial_pic2_device::midway_serial_pic2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
336 	midway_serial_pic_device(mconfig, type, tag, owner, clock),
337 	device_nvram_interface(mconfig, *this),
338 	m_latch(0),
339 	m_state(0),
340 	m_index(0),
341 	m_total(0),
342 	m_nvram_addr(0),
343 	m_time_index(0),
344 	m_time_just_written(0),
345 	m_yearoffs(0),
346 	m_time_write_timer(nullptr)
347 {
348 	memset(m_buffer,0,sizeof(m_buffer));
349 	memset(m_time_buf,0,sizeof(m_time_buf));
350 	memset(m_nvram,0,sizeof(m_nvram));
351 	memset(m_default_nvram,0,sizeof(m_default_nvram));
352 }
353 
354 
355 //-------------------------------------------------
356 //  device_start - device-specific startup
357 //-------------------------------------------------
358 
device_start()359 void midway_serial_pic2_device::device_start()
360 {
361 	midway_serial_pic_device::device_start();
362 	//void midway_serial_pic2_init(running_machine &machine, int upper, int yearoffs)
363 	pic_register_state();
364 
365 	//m_yearoffs = yearoffs;
366 	m_time_just_written = 0;
367 	m_time_write_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midway_serial_pic2_device::reset_timer),this));
368 	memset(m_default_nvram, 0xff, sizeof(m_default_nvram));
369 }
370 
371 
TIMER_CALLBACK_MEMBER(midway_serial_pic2_device::reset_timer)372 TIMER_CALLBACK_MEMBER( midway_serial_pic2_device::reset_timer )
373 {
374 	m_time_just_written = 0;
375 }
376 
377 
pic_register_state()378 void midway_serial_pic2_device::pic_register_state()
379 {
380 	save_item(NAME(m_latch));
381 	save_item(NAME(m_latch_expire_time));
382 	save_item(NAME(m_state));
383 	save_item(NAME(m_index));
384 	save_item(NAME(m_total));
385 	save_item(NAME(m_nvram_addr));
386 	save_item(NAME(m_buffer));
387 	save_item(NAME(m_nvram));
388 	save_item(NAME(m_default_nvram));
389 	save_item(NAME(m_time_buf));
390 	save_item(NAME(m_time_index));
391 	save_item(NAME(m_time_just_written));
392 	save_item(NAME(m_yearoffs));
393 }
394 
395 
396 
set_default_nvram(const uint8_t * nvram)397 void midway_serial_pic2_device::set_default_nvram(const uint8_t *nvram)
398 {
399 	memcpy(m_default_nvram, nvram, sizeof(m_default_nvram));
400 }
401 
402 
status_r()403 u8 midway_serial_pic2_device::status_r()
404 {
405 	uint8_t result = 0;
406 
407 	if (!machine().side_effects_disabled())
408 	{
409 		/* if we're still holding the data ready bit high, do it */
410 		if (m_latch & 0xf00)
411 		{
412 			if (machine().time() > m_latch_expire_time)
413 				m_latch &= 0xff;
414 			else
415 				m_latch -= 0x100;
416 			result = 1;
417 		}
418 
419 		logerror("%s:PIC status %d\n", machine().describe_context(), result);
420 	}
421 	return result;
422 }
423 
424 
read()425 u8 midway_serial_pic2_device::read()
426 {
427 	uint8_t result = 0;
428 
429 	/* PIC data register */
430 	if (!machine().side_effects_disabled())
431 		logerror("%s:PIC data read (index=%d total=%d latch=%03X) =", machine().describe_context(), m_index, m_total, m_latch);
432 
433 	/* return the current result */
434 	if (m_latch & 0xf00)
435 		result = m_latch & 0xff;
436 
437 	/* otherwise, return 0xff if we have data ready */
438 	else if (m_index < m_total)
439 		result = 0xff;
440 
441 	if (!machine().side_effects_disabled())
442 		logerror("%02X\n", result);
443 	return result;
444 }
445 
446 
write(u8 data)447 void midway_serial_pic2_device::write(u8 data)
448 {
449 	static FILE *nvramlog;
450 	if (LOG_NVRAM && !nvramlog)
451 		nvramlog = fopen("nvram.log", "w");
452 
453 	/* PIC command register */
454 	if (m_state == 0)
455 		logerror("%s:PIC command %02X\n", machine().describe_context(), data);
456 	else
457 		logerror("%s:PIC data %02X\n", machine().describe_context(), data);
458 
459 	/* store in the latch, along with a bit to indicate we have data */
460 	m_latch = (data & 0x00f) | 0x480;
461 	m_latch_expire_time = machine().time() + attotime::from_msec(1);
462 	if (data & 0x10)
463 	{
464 		int cmd = m_state ? (m_state & 0x0f) : (m_latch & 0x0f);
465 		switch (cmd)
466 		{
467 			/* written to latch the next byte of data */
468 			case 0:
469 				if (m_index < m_total)
470 					m_latch = 0x400 | m_buffer[m_index++];
471 				break;
472 
473 			/* fetch the serial number */
474 			case 1:
475 				/* note: Biofreaks assumes that it can latch the next byte this way */
476 				if (m_index < m_total)
477 					m_latch = 0x400 | m_buffer[m_index++];
478 				else
479 				{
480 					memcpy(m_buffer, m_data, 16);
481 					m_total = 16;
482 					m_index = 0;
483 					machine().debug_break();
484 				}
485 				break;
486 
487 			/* read the clock */
488 			case 3:
489 			{
490 				/* stuff it into the data bytes */
491 				m_index = 0;
492 				m_total = 0;
493 
494 				/* if we haven't written a new time recently, use the real live time */
495 				if (!m_time_just_written)
496 				{
497 					system_time systime;
498 					machine().base_datetime(systime);
499 
500 					m_buffer[m_total++] = make_bcd(systime.local_time.second);
501 					m_buffer[m_total++] = make_bcd(systime.local_time.minute);
502 					m_buffer[m_total++] = make_bcd(systime.local_time.hour);
503 					m_buffer[m_total++] = make_bcd(systime.local_time.weekday + 1);
504 					m_buffer[m_total++] = make_bcd(systime.local_time.mday);
505 					m_buffer[m_total++] = make_bcd(systime.local_time.month + 1);
506 					m_buffer[m_total++] = make_bcd(systime.local_time.year - 1900 - m_yearoffs);
507 				}
508 
509 				/* otherwise, just parrot back what was written to pass self tests */
510 				else
511 				{
512 					m_buffer[m_total++] = m_time_buf[0];
513 					m_buffer[m_total++] = m_time_buf[1];
514 					m_buffer[m_total++] = m_time_buf[2];
515 					m_buffer[m_total++] = m_time_buf[3];
516 					m_buffer[m_total++] = m_time_buf[4];
517 					m_buffer[m_total++] = m_time_buf[5];
518 					m_buffer[m_total++] = m_time_buf[6];
519 				}
520 				break;
521 			}
522 
523 			/* write the clock */
524 			case 4:
525 
526 				/* if coming from state 0, go to state 1 (this is just the command byte) */
527 				if (m_state == 0)
528 				{
529 					m_state = 0x14;
530 					m_time_index = 0;
531 				}
532 
533 				/* if in states 1-2 put data in the buffer until it's full */
534 				else if (m_state == 0x14)
535 				{
536 					m_time_buf[m_time_index] = m_latch & 0x0f;
537 					m_state = 0x24;
538 				}
539 				else if (m_state == 0x24)
540 				{
541 					m_time_buf[m_time_index++] |= m_latch << 4;
542 
543 					/* if less than 7 bytes accumulated, go back to state 1 */
544 					if (m_time_index < 7)
545 						m_state = 0x14;
546 
547 					/* otherwise, flag the time as having just been written for 1/2 second */
548 					else
549 					{
550 						m_time_write_timer->adjust(attotime::from_msec(500));
551 						m_time_just_written = 1;
552 						m_state = 0;
553 					}
554 				}
555 				break;
556 
557 			/* write to NVRAM */
558 			case 5:
559 
560 				/* if coming from state 0, go to state 1 (this is just the command byte) */
561 				if (m_state == 0)
562 					m_state = 0x15;
563 
564 				/* coming from state 1, go to state 2 and latch the low 4 address bits */
565 				else if (m_state == 0x15)
566 				{
567 					m_nvram_addr = m_latch & 0x0f;
568 					m_state = 0x25;
569 				}
570 
571 				/* coming from state 2, go to state 3 and latch the high 4 address bits */
572 				else if (m_state == 0x25)
573 				{
574 					m_state = 0x35;
575 					m_nvram_addr |= m_latch << 4;
576 				}
577 
578 				/* coming from state 3, go to state 4 and write the low 4 bits */
579 				else if (m_state == 0x35)
580 				{
581 					m_state = 0x45;
582 					m_nvram[m_nvram_addr] = m_latch & 0x0f;
583 				}
584 
585 				/* coming from state 4, reset the states and write the upper 4 bits */
586 				else if (m_state == 0x45)
587 				{
588 					m_state = 0;
589 					m_nvram[m_nvram_addr] |= m_latch << 4;
590 					if (nvramlog)
591 						fprintf(nvramlog, "Write byte %02X = %02X\n", m_nvram_addr, m_nvram[m_nvram_addr]);
592 				}
593 				break;
594 
595 			/* read from NVRAM */
596 			case 6:
597 
598 				/* if coming from state 0, go to state 1 (this is just the command byte) */
599 				if (m_state == 0)
600 					m_state = 0x16;
601 
602 				/* coming from state 1, go to state 2 and latch the low 4 address bits */
603 				else if (m_state == 0x16)
604 				{
605 					m_nvram_addr = m_latch & 0x0f;
606 					m_state = 0x26;
607 				}
608 
609 				/* coming from state 2, reset the states and make the data available */
610 				else if (m_state == 0x26)
611 				{
612 					m_state = 0;
613 					m_nvram_addr |= m_latch << 4;
614 
615 					m_total = 0;
616 					m_index = 0;
617 					m_buffer[m_total++] = m_nvram[m_nvram_addr];
618 					if (nvramlog)
619 						fprintf(nvramlog, "Read byte %02X = %02X\n", m_nvram_addr, m_nvram[m_nvram_addr]);
620 				}
621 				break;
622 
623 			/* reflect inverted? (Cruisin' Exotica) */
624 			case 8:
625 				m_latch = 0x400 | (~cmd & 0xff);
626 				break;
627 		}
628 	}
629 }
630 
nvram_default()631 void midway_serial_pic2_device::nvram_default()
632 {
633 	memcpy(m_nvram, m_default_nvram, sizeof(m_nvram));
634 }
635 
nvram_read(emu_file & file)636 void midway_serial_pic2_device::nvram_read(emu_file &file)
637 {
638 	file.read(m_nvram, sizeof(m_nvram));
639 }
640 
nvram_write(emu_file & file)641 void midway_serial_pic2_device::nvram_write(emu_file &file)
642 {
643 	file.write(m_nvram, sizeof(m_nvram));
644 }
645 
646 
647 /*************************************
648  *
649  *  The I/O ASIC was first introduced
650  *  in War Gods, then later used on
651  *  the Seattle hardware
652  *
653  *************************************/
654 
655 enum
656 {
657 	IOASIC_PORT0,       /* 0: input port 0 */
658 	IOASIC_PORT1,       /* 1: input port 1 */
659 	IOASIC_PORT2,       /* 2: input port 2 */
660 	IOASIC_PORT3,       /* 3: input port 3 */
661 	IOASIC_UARTCONTROL, /* 4: controls some UART behavior */
662 	IOASIC_UARTOUT,     /* 5: UART output */
663 	IOASIC_UARTIN,      /* 6: UART input */
664 	IOASIC_COIN,        /* 7: triggered on coin insertion */
665 	IOASIC_SOUNDCTL,    /* 8: sound communications control */
666 	IOASIC_SOUNDOUT,    /* 9: sound output port */
667 	IOASIC_SOUNDSTAT,   /* a: sound status port */
668 	IOASIC_SOUNDIN,     /* b: sound input port */
669 	IOASIC_PICOUT,      /* c: PIC output port */
670 	IOASIC_PICIN,       /* d: PIC input port */
671 	IOASIC_INTSTAT,     /* e: interrupt status */
672 	IOASIC_INTCTL       /* f: interrupt control */
673 };
674 
ioasic_register_state()675 void midway_ioasic_device::ioasic_register_state()
676 {
677 	save_item(NAME(m_reg));
678 	save_item(NAME(m_shuffle_active));
679 	save_item(NAME(m_irq_state));
680 	save_item(NAME(m_sound_irq_state));
681 	save_item(NAME(m_auto_ack));
682 	save_item(NAME(m_force_fifo_full));
683 	save_item(NAME(m_fifo));
684 	save_item(NAME(m_fifo_in));
685 	save_item(NAME(m_fifo_out));
686 	save_item(NAME(m_fifo_bytes));
687 	save_item(NAME(m_fifo_force_buffer_empty_pc));
688 }
689 
690 DEFINE_DEVICE_TYPE(MIDWAY_IOASIC, midway_ioasic_device, "midway_ioasic", "Midway IOASIC")
691 
692 
693 //-------------------------------------------------
694 //  midway_serial_pic2_device - constructor
695 //-------------------------------------------------
696 
midway_ioasic_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)697 midway_ioasic_device::midway_ioasic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
698 	midway_serial_pic2_device(mconfig, MIDWAY_IOASIC, tag, owner, clock),
699 	m_io_dips(*this, ":DIPS"),
700 	m_io_system(*this, ":SYSTEM"),
701 	m_io_in1(*this, ":IN1"),
702 	m_io_in2(*this, ":IN2"),
703 	m_serial_tx_cb(*this),
704 	m_aux_output_cb(*this),
705 	m_has_dcs(0),
706 	m_has_cage(0),
707 	m_dcs_cpu(nullptr),
708 	m_shuffle_type(0),
709 	m_shuffle_default(0),
710 	m_shuffle_active(0),
711 	m_shuffle_map(nullptr),
712 	m_irq_callback(*this),
713 	m_irq_state(0),
714 	m_sound_irq_state(0),
715 	m_auto_ack(0),
716 	m_force_fifo_full(0),
717 	m_fifo_in(0),
718 	m_fifo_out(0),
719 	m_fifo_bytes(0),
720 	m_fifo_force_buffer_empty_pc(0),
721 	m_cage(*this, ":cage"),
722 	m_dcs(*this, ":dcs")
723 {
724 	memset(m_fifo,0,sizeof(m_fifo));
725 	memset(m_reg,0,sizeof(m_reg));
726 }
727 
728 
729 //-------------------------------------------------
730 //  device_start - device-specific startup
731 //-------------------------------------------------
732 
device_start()733 void midway_ioasic_device::device_start()
734 //void midway_ioasic_init(running_machine &machine, int shuffle, int upper, int yearoffs, void (*irq_callback)(running_machine &, int))
735 {
736 	static const uint8_t shuffle_maps[][16] =
737 	{
738 		{ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf },    /* WarGods, WG3DH, SFRush, MK4 */
739 		{ 0x4,0x5,0x6,0x7,0xb,0xa,0x9,0x8,0x3,0x2,0x1,0x0,0xf,0xe,0xd,0xc },    /* Blitz, Blitz99 */
740 		{ 0x7,0x3,0x2,0x0,0x1,0xc,0xd,0xe,0xf,0x4,0x5,0x6,0x8,0x9,0xa,0xb },    /* Carnevil */
741 		{ 0x8,0x9,0xa,0xb,0x0,0x1,0x2,0x3,0xf,0xe,0xc,0xd,0x4,0x5,0x6,0x7 },    /* Calspeed, Gauntlet Legends */
742 		{ 0xf,0xe,0xd,0xc,0x4,0x5,0x6,0x7,0x9,0x8,0xa,0xb,0x2,0x3,0x1,0x0 },    /* Mace */
743 		{ 0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x7,0x8,0x9,0xb,0xa,0x5,0x6,0x4 },    /* Gauntlet Dark Legacy */
744 		{ 0x7,0x4,0x5,0x6,0x2,0x0,0x1,0x3,0x8,0x9,0xa,0xb,0xd,0xc,0xe,0xf },    /* Vapor TRX */
745 		{ 0x7,0x4,0x5,0x6,0x2,0x0,0x1,0x3,0x8,0x9,0xa,0xb,0xd,0xc,0xe,0xf },    /* San Francisco Rush: The Rock */
746 		{ 0x1,0x2,0x3,0x0,0x4,0x5,0x6,0x7,0xa,0xb,0x8,0x9,0xc,0xd,0xe,0xf },    /* Hyperdrive */
747 	};
748 
749 	ioasic_register_state();
750 
751 	/* do we have a DCS2 sound chip connected? */
752 	m_has_dcs = (m_dcs != nullptr);
753 	m_has_cage = (m_cage != nullptr);
754 
755 	if (m_has_dcs)
756 	{
757 		m_dcs_cpu = m_dcs->get_cpu();
758 	}
759 
760 	m_shuffle_map = &shuffle_maps[m_shuffle_type][0];
761 	// resolve callbacks
762 	m_irq_callback.resolve_safe();
763 	m_serial_tx_cb.resolve_safe();
764 	m_aux_output_cb.resolve();
765 
766 	/* initialize the PIC */
767 	midway_serial_pic2_device::device_start();
768 
769 	/* reset the chip */
770 	ioasic_reset();
771 
772 	m_reg[IOASIC_SOUNDCTL] = 0x0001;
773 
774 
775 	/* configure the fifo */
776 	if (m_has_dcs)
777 	{
778 		m_dcs->set_fifo_callbacks(
779 				read16smo_delegate(*this, FUNC(midway_ioasic_device::fifo_r)),
780 				read16mo_delegate(*this, FUNC(midway_ioasic_device::fifo_status_r)),
781 				write_line_delegate(*this, FUNC(midway_ioasic_device::fifo_reset_w)));
782 		m_dcs->set_io_callbacks(
783 				write_line_delegate(*this, FUNC(midway_ioasic_device::ioasic_output_full)),
784 				write_line_delegate(*this, FUNC(midway_ioasic_device::ioasic_input_empty)));
785 	}
786 
787 	fifo_reset_w(1);
788 }
789 
set_shuffle_state(int state)790 void midway_ioasic_device::set_shuffle_state(int state)
791 {
792 	m_shuffle_active = state;
793 }
794 
795 
ioasic_reset()796 void midway_ioasic_device::ioasic_reset()
797 {
798 	m_shuffle_active = m_shuffle_default;
799 	m_sound_irq_state = 0x0080;
800 	m_reg[IOASIC_INTCTL] = 0;
801 	if (m_has_dcs)
802 		fifo_reset_w(1);
803 	update_ioasic_irq();
804 	midway_serial_pic_device::reset_w(1);
805 }
806 
807 
update_ioasic_irq()808 void midway_ioasic_device::update_ioasic_irq()
809 {
810 	uint16_t fifo_state = fifo_status_r(machine().dummy_space());
811 	uint16_t irqbits = 0x2000;
812 	uint8_t new_state;
813 
814 	irqbits |= m_sound_irq_state & 0xff;
815 	irqbits |= m_reg[IOASIC_UARTIN] & 0x3f00;
816 	if (fifo_state & 8)
817 		irqbits |= 0x0008;
818 	if (irqbits)
819 		irqbits |= 0x0001;
820 
821 	m_reg[IOASIC_INTSTAT] = irqbits;
822 
823 	new_state = ((m_reg[IOASIC_INTCTL] & 0x0001) != 0) && ((m_reg[IOASIC_INTSTAT] & m_reg[IOASIC_INTCTL] & 0x3ffe) != 0);
824 	if (new_state != m_irq_state)
825 	{
826 		m_irq_state = new_state;
827 		if (!m_irq_callback.isnull())
828 			m_irq_callback(m_irq_state ? ASSERT_LINE : CLEAR_LINE);
829 		if (m_irq_state && (m_reg[IOASIC_UARTIN] & 0x1000))
830 			logerror("IOASIC: Asserting IRQ INTCTRL=%04x INTSTAT=%04X\n", m_reg[IOASIC_INTCTL], m_reg[IOASIC_INTSTAT]);
831 	}
832 }
833 
834 
cage_irq_handler(uint8_t data)835 void midway_ioasic_device::cage_irq_handler(uint8_t data)
836 {
837 	logerror("CAGE irq handler: %d\n", data);
838 	m_sound_irq_state = 0;
839 	if (data & atari_cage_device::CAGE_IRQ_REASON_DATA_READY)
840 		m_sound_irq_state |= 0x0040;
841 	if (data & atari_cage_device::CAGE_IRQ_REASON_BUFFER_EMPTY)
842 		m_sound_irq_state |= 0x0080;
843 	update_ioasic_irq();
844 }
845 
846 
WRITE_LINE_MEMBER(midway_ioasic_device::ioasic_input_empty)847 WRITE_LINE_MEMBER(midway_ioasic_device::ioasic_input_empty)
848 {
849 //  logerror("ioasic_input_empty(%d)\n", state);
850 	if (state)
851 		m_sound_irq_state |= 0x0080;
852 	else
853 		m_sound_irq_state &= ~0x0080;
854 	update_ioasic_irq();
855 }
856 
857 
WRITE_LINE_MEMBER(midway_ioasic_device::ioasic_output_full)858 WRITE_LINE_MEMBER(midway_ioasic_device::ioasic_output_full)
859 {
860 //  logerror("ioasic_output_full(%d)\n", state);
861 	if (state)
862 		m_sound_irq_state |= 0x0040;
863 	else
864 		m_sound_irq_state &= ~0x0040;
865 	update_ioasic_irq();
866 }
867 
868 
869 
870 /*************************************
871  *
872  *  ASIC sound FIFO; used by CarnEvil
873  *
874  *************************************/
875 
fifo_r()876 uint16_t midway_ioasic_device::fifo_r()
877 {
878 	uint16_t result = 0;
879 
880 	/* we can only read data if there's some to read! */
881 	if (m_fifo_bytes != 0)
882 	{
883 		/* fetch the data from the buffer and update the IOASIC state */
884 		result = m_fifo[m_fifo_out++ % FIFO_SIZE];
885 		m_fifo_bytes--;
886 		update_ioasic_irq();
887 
888 		if (LOG_FIFO && (m_fifo_bytes < 4 || m_fifo_bytes >= FIFO_SIZE - 4))
889 			logerror("fifo_r(%04X): FIFO bytes = %d!\n", result, m_fifo_bytes);
890 
891 		/* if we just cleared the buffer, this may generate an IRQ on the master CPU */
892 		/* because of the way the streaming code works, we need to make sure that the */
893 		/* next status read indicates an empty buffer, even if we've timesliced and the */
894 		/* main CPU is handling the I/O ASIC interrupt */
895 		if (m_fifo_bytes == 0 && m_has_dcs)
896 		{
897 			m_fifo_force_buffer_empty_pc = m_dcs_cpu->pc();
898 			if (LOG_FIFO)
899 				logerror("fifo_r(%04X): FIFO empty, PC = %04X\n", result, m_fifo_force_buffer_empty_pc);
900 		}
901 	}
902 	else
903 	{
904 		if (LOG_FIFO)
905 			logerror("fifo_r(): nothing to read!\n");
906 	}
907 	return result;
908 }
909 
910 
fifo_status_r(address_space & space)911 uint16_t midway_ioasic_device::fifo_status_r(address_space &space)
912 {
913 	uint16_t result = 0;
914 
915 	if (m_fifo_bytes == 0 && !m_force_fifo_full)
916 		result |= 0x08;
917 	if (m_fifo_bytes >= FIFO_SIZE/2)
918 		result |= 0x10;
919 	if (m_fifo_bytes >= FIFO_SIZE || m_force_fifo_full)
920 		result |= 0x20;
921 
922 	/* kludge alert: if we're reading this from the DCS CPU itself, and we recently cleared */
923 	/* the FIFO, and we're within 16 instructions of the read that cleared the FIFO, make */
924 	/* sure the FIFO clear bit is set */
925 	if (m_fifo_force_buffer_empty_pc && &space.device() == m_dcs_cpu)
926 	{
927 		offs_t currpc = m_dcs_cpu->pc();
928 		if (currpc >= m_fifo_force_buffer_empty_pc && currpc < m_fifo_force_buffer_empty_pc + 0x10)
929 		{
930 			m_fifo_force_buffer_empty_pc = 0;
931 			result |= 0x08;
932 			if (LOG_FIFO)
933 				logerror("ioasic_fifo_status_r(%04X): force empty, PC = %04X\n", result, currpc);
934 		}
935 	}
936 
937 	return result;
938 }
939 
940 
WRITE_LINE_MEMBER(midway_ioasic_device::fifo_reset_w)941 WRITE_LINE_MEMBER(midway_ioasic_device::fifo_reset_w)
942 {
943 	/* on the high state, reset the FIFO data */
944 	if (state)
945 	{
946 		m_fifo_in = 0;
947 		m_fifo_out = 0;
948 		m_fifo_bytes = 0;
949 		m_force_fifo_full = 0;
950 		update_ioasic_irq();
951 	}
952 	if (LOG_FIFO)
953 		logerror("%s:fifo_reset(%d)\n", machine().describe_context(), state);
954 }
955 
956 
fifo_w(uint16_t data)957 void midway_ioasic_device::fifo_w(uint16_t data)
958 {
959 	/* if we have room, add it to the FIFO buffer */
960 	if (m_fifo_bytes < FIFO_SIZE)
961 	{
962 		m_fifo[m_fifo_in++ % FIFO_SIZE] = data;
963 		m_fifo_bytes++;
964 		update_ioasic_irq();
965 		if (LOG_FIFO && (m_fifo_bytes < 4 || m_fifo_bytes >= FIFO_SIZE - 4))
966 			logerror("fifo_w(%04X): FIFO bytes = %d!\n", data, m_fifo_bytes);
967 	}
968 	else
969 	{
970 		if (LOG_FIFO)
971 			logerror("fifo_w(%04X): out of space!\n", data);
972 	}
973 	m_dcs->fifo_notify(m_fifo_bytes, FIFO_SIZE);
974 }
975 
976 
fifo_full_w(uint16_t data)977 void midway_ioasic_device::fifo_full_w(uint16_t data)
978 {
979 	if (LOG_FIFO)
980 		logerror("fifo_full_w(%04X)\n", data);
981 	m_force_fifo_full = 1;
982 	update_ioasic_irq();
983 	m_dcs->fifo_notify(m_fifo_bytes, FIFO_SIZE);
984 }
985 
986 
987 
988 /*************************************
989  *
990  *  I/O ASIC master read/write
991  *
992  *************************************/
993 
packed_r(address_space & space,offs_t offset,uint32_t mem_mask)994 uint32_t midway_ioasic_device::packed_r(address_space &space, offs_t offset, uint32_t mem_mask)
995 {
996 	uint32_t result = 0;
997 	if (ACCESSING_BITS_0_15)
998 		result |= read(space, offset*2) & 0xffff;
999 	if (ACCESSING_BITS_16_31)
1000 		result |= (read(space, offset*2+1) & 0xffff) << 16;
1001 	return result;
1002 }
1003 
1004 
read(address_space & space,offs_t offset)1005 uint32_t midway_ioasic_device::read(address_space &space, offs_t offset)
1006 {
1007 	uint32_t result;
1008 
1009 	offset = m_shuffle_active ? m_shuffle_map[offset & 15] : offset;
1010 	result = m_reg[offset];
1011 
1012 	switch (offset)
1013 	{
1014 		case IOASIC_PORT0:
1015 			// bit 0 is PIC ready flag before shuffling happens
1016 			// bits 15:13 == 001
1017 			if (!m_shuffle_active)
1018 			{
1019 				/* blitz99 wants bit bits 13-15 to be 1 */
1020 				result = 0x2001;
1021 			}
1022 			else {
1023 				result = m_io_dips->read();
1024 			}
1025 			break;
1026 
1027 		case IOASIC_PORT1:
1028 			result = m_io_system->read();
1029 			break;
1030 
1031 		case IOASIC_PORT2:
1032 			result = m_io_in1->read();
1033 			break;
1034 
1035 		case IOASIC_PORT3:
1036 			result = m_io_in2->read();
1037 			break;
1038 
1039 		case IOASIC_UARTIN:
1040 			m_reg[offset] &= ~0x1000;
1041 			if (result & 0x1000)
1042 				logerror("%s: ioasic_r(%d) = %08X\n", machine().describe_context(), offset, result);
1043 			// Add lf
1044 			if ((result & 0xff)==0x0d)
1045 				m_reg[offset] = 0x300a;
1046 			update_ioasic_irq();
1047 			break;
1048 
1049 		case IOASIC_SOUNDSTAT:
1050 			/* status from sound CPU */
1051 			result = 0;
1052 			if (m_has_dcs)
1053 			{
1054 				result |= ((m_dcs->control_r() >> 4) ^ 0x40) & 0x00c0;
1055 				result |= fifo_status_r(space) & 0x0038;
1056 				result |= m_dcs->data2_r() & 0xff00;
1057 			}
1058 			else if (m_has_cage)
1059 			{
1060 				result |= (m_cage->control_r() << 6) ^ 0x80;
1061 			}
1062 			else
1063 				result |= 0x48;
1064 			break;
1065 
1066 		case IOASIC_SOUNDIN:
1067 			result = 0;
1068 			if (m_has_dcs)
1069 			{
1070 				result = m_dcs->data_r();
1071 				if (m_auto_ack)
1072 					m_dcs->ack_w();
1073 			}
1074 			else if (m_has_cage)
1075 				result = m_cage->main_r();
1076 			else
1077 			{
1078 				static uint16_t val = 0;
1079 				result = val = ~val;
1080 			}
1081 			break;
1082 
1083 		case IOASIC_PICIN:
1084 			result = midway_serial_pic2_device::read() | (midway_serial_pic2_device::status_r() << 8);
1085 			break;
1086 
1087 		default:
1088 			break;
1089 	}
1090 
1091 	if (LOG_IOASIC && offset != IOASIC_SOUNDSTAT && offset != IOASIC_SOUNDIN)
1092 		logerror("%s:ioasic_r(%d) = %08X\n", machine().describe_context(), offset, result);
1093 
1094 	return result;
1095 }
1096 
1097 
packed_w(offs_t offset,uint32_t data,uint32_t mem_mask)1098 void midway_ioasic_device::packed_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1099 {
1100 	if (ACCESSING_BITS_0_15)
1101 		write(offset*2, data & 0xffff, 0x0000ffff);
1102 	if (ACCESSING_BITS_16_31)
1103 		write(offset*2+1, data >> 16, 0x0000ffff);
1104 }
1105 
serial_rx_w(u8 data)1106 void midway_ioasic_device::serial_rx_w(u8 data)
1107 {
1108 	// Break Detect        0x0100
1109 	// Frame Error         0x0200
1110 	// Overrun             0x0400
1111 	// Rx FIFO FULL        0x0800
1112 	// Rx Ready            0x1000
1113 	// Tx EMPTY            0x2000
1114 	// CTS IN              0x4000
1115 	// CTS OUT             0x8000
1116 	if (m_reg[IOASIC_UARTCONTROL] & 0x200) {
1117 		m_reg[IOASIC_UARTIN] = data | 0x3000;
1118 		update_ioasic_irq();
1119 	}
1120 
1121 }
1122 
write(offs_t offset,uint32_t data,uint32_t mem_mask)1123 void midway_ioasic_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
1124 {
1125 	uint32_t oldreg, newreg;
1126 
1127 	offset = m_shuffle_active ? m_shuffle_map[offset & 15] : offset;
1128 	oldreg = m_reg[offset];
1129 	// Block register updates until ioasic is unlocked
1130 	// mwskins and thegrid use this as test to see if the ioasic is unlocked
1131 	if (m_shuffle_active)
1132 		COMBINE_DATA(&m_reg[offset]);
1133 	newreg = m_reg[offset];
1134 
1135 	if (LOG_IOASIC && offset != IOASIC_SOUNDOUT)
1136 		logerror("%s ioasic_w(%d) = %08X\n", machine().describe_context(), offset, data);
1137 
1138 	switch (offset)
1139 	{
1140 		case IOASIC_PORT0:
1141 			/* the last write here seems to turn on shuffling */
1142 			if (data == 0xe2)
1143 			{
1144 				m_shuffle_active = 1;
1145 				logerror("*** I/O ASIC unlocked!\n");
1146 				m_reg[IOASIC_INTCTL] = 0;
1147 				m_reg[IOASIC_UARTCONTROL] = 0; /* bug in 10th Degree assumes this */
1148 			}
1149 			break;
1150 
1151 		case IOASIC_PORT2:
1152 		case IOASIC_PORT3:
1153 			/* ignore writes here if we're not shuffling yet */
1154 			if (!m_shuffle_active)
1155 				break;
1156 			break;
1157 
1158 		case IOASIC_UARTCONTROL:
1159 			logerror("%s: IOASIC uart control = %04X INTCTRL=%04x\n", machine().describe_context(), data, m_reg[IOASIC_INTCTL]);
1160 			break;
1161 
1162 		case IOASIC_UARTOUT:
1163 			if (m_reg[IOASIC_UARTCONTROL] & 0x800)
1164 			{
1165 				/* we're in loopback mode -- copy to the input */
1166 				m_reg[IOASIC_UARTIN] = (newreg & 0x00ff) | 0x3000;
1167 				update_ioasic_irq();
1168 			}
1169 			else {
1170 				m_serial_tx_cb(data);
1171 				m_reg[IOASIC_UARTIN] |= 0x2000;
1172 				update_ioasic_irq();
1173 				if (PRINTF_DEBUG) {
1174 					osd_printf_info("%c", data & 0xff);
1175 					logerror("%c", data & 0xff);
1176 				}
1177 			}
1178 			//logerror("IOASIC uart tx data = %04X\n", data);
1179 			break;
1180 
1181 		case IOASIC_SOUNDCTL:
1182 			if (LOG_IOASIC)
1183 				logerror("%s: write IOASIC_SOUNDCTL=%04x\n", machine().describe_context(), data);
1184 			/* sound reset? */
1185 			if (m_has_dcs)
1186 			{
1187 				m_dcs->reset_w(newreg & 1);
1188 			}
1189 			else if (m_has_cage)
1190 			{
1191 				if ((oldreg ^ newreg) & 1)
1192 				{
1193 					m_cage->control_w(0);
1194 					if (!(~newreg & 1))
1195 						m_cage->control_w(3);
1196 				}
1197 			}
1198 
1199 			/* FIFO reset? */
1200 			fifo_reset_w(~newreg & 4);
1201 			break;
1202 
1203 		case IOASIC_SOUNDOUT:
1204 			if (m_has_dcs)
1205 				m_dcs->data_w(newreg);
1206 			else if (m_has_cage)
1207 				m_cage->main_w(newreg);
1208 			break;
1209 
1210 		case IOASIC_SOUNDIN:
1211 			m_dcs->ack_w();
1212 			/* acknowledge data read */
1213 			break;
1214 
1215 		case IOASIC_PICOUT:
1216 			if (m_shuffle_type == MIDWAY_IOASIC_VAPORTRX)
1217 				midway_serial_pic2_device::write(newreg ^ 0x0a);
1218 			else if (m_shuffle_type == MIDWAY_IOASIC_SFRUSHRK)
1219 				midway_serial_pic2_device::write(newreg ^ 0x05);
1220 			else
1221 				midway_serial_pic2_device::write(newreg);
1222 			break;
1223 
1224 		case IOASIC_PICIN:
1225 			/* This is P15 on vegas boards */
1226 			if (!m_aux_output_cb.isnull())
1227 				m_aux_output_cb(data);
1228 			break;
1229 
1230 		case IOASIC_INTCTL:
1231 			/* interrupt enables */
1232 			/* bit  0 = global interrupt enable */
1233 			/* bit  3 = FIFO empty */
1234 			/* bit  6 = sound input buffer full */
1235 			/* bit  7 = sound output buffer empty */
1236 			/* bit 14 = LED */
1237 			/* bit 15 = TI320Cx Mode Enable */
1238 			if (LOG_IOASIC && ((oldreg ^ newreg) & 0x3ff6))
1239 				logerror("IOASIC interrupt control = %04X\n", data);
1240 			update_ioasic_irq();
1241 			break;
1242 
1243 		default:
1244 			break;
1245 	}
1246 }
1247