// license:BSD-3-Clause // copyright-holders:David Haywood, James Wallace // thanks-to:Chris Wren, Tony Friery, MFME /* mpu4.cpp - MPU4 hardware emulation this file contains emulation of the hardware only */ /* --- Board Setup --- The MPU4 BOARD is the driver board, originally designed to run Fruit Machines made by the Barcrest Group, but later licensed to other firms as a general purpose unit (even some old Photo-Me booths used the unit). This board uses a ~1.72 Mhz 6809B CPU, and a number of PIA6821 chips for multiplexing inputs and the like. To some extent, the hardware feels like a revision of the MPU3 design, integrating into the base unit features that were previously added through expansion ports. However, there is no backwards compatibility, and the entire memory map has been reworked. Like MPU3, a 6840PTM is used for internal timing, and other miscellaneous control functions, including as a crude analogue sound device (a square wave from the PTM being used as the alarm sound generator). However, the main sound functionality is provided by dedicated hardware (an AY8913). A MPU4 GAME CARD (cartridge) plugs into the MPU4 board containing the game, and a protection PAL (the 'characteriser'). This PAL, as well as protecting the games, also controlled some of the lamp address matrix for many games, and acted as an anti-tampering device which helped to prevent the hacking of certain titles in a manner which broke UK gaming laws. Like MPU3, over the years developers have added more capabilities through the spare inputs and outputs provided. These provided support for more reels, lamps and LEDs through daughtercards. Several solutions were released depending on the manufacturer of the machine, all are emulated here. In later revisions of the main board (MOD4 onwards), the AY8913 was removed entirely, as two official alternatives for sound had been produced. In one, a YM2413 is built into the gameboard, and in the other an OKI MSM6376 is interfaced with a PIA and PTM to allow sophisticated sampled sound. The lamping and input handling side of the machine rely entirely on a column by column 'strobe' system, with lights and LEDs selected in turn. In the inputs there are two orange connectors (sampled every 8ms) and two black ones (sampled every 16ms), giving 32 multiplexed inputs. In addition there are two auxiliary ports that can be accessed separately to these and are bidirectional --- Preliminary MPU4 Memorymap --- (NV) indicates an item which is not present on the video version, which has a Comms card instead. hex |r/w| D D D D D D D D | location | | 7 6 5 4 3 2 1 0 | function -----------+---+-----------------+-------------------------------------------------------------------------- 0000-07FF |R/W| D D D D D D D D | 2k RAM -----------+---+-----------------+-------------------------------------------------------------------------- 0800 |R/W| | Characteriser (Security PAL) (NV) -----------+---+-----------------+-------------------------------------------------------------------------- 0850 ? | W | ??????????????? | page latch (NV) -----------+---+-----------------+-------------------------------------------------------------------------- 0880 |R/W| D D D D D D D D | PIA6821 on soundboard (Oki MSM6376 clocked by 6840 (8C0)) | | | port A = ?? | | | port B (882) | | | b7 = NAR | | | b6 = 0 if OKI busy, 1 if OKI ready | | | b5 = volume control clock | | | b4 = volume control direction (0= up, 1 = down) | | | b3 = ?? | | | b2 = ?? | | | b1 = 2ch | | | b0 = ST -----------+---+-----------------+-------------------------------------------------------------------------- 08C0 | | | MC6840 on sound board -----------+---+-----------------+-------------------------------------------------------------------------- 0900- |R/W| D D D D D D D D | MC6840 PTM IC2 Clock1 <-------------------------------------- | | V | Output1 ---> Clock2 | | Output2 --+-> Clock3 | | | | Output3 ---> 'to audio amp' ?? | +--------> CA1 IC3 ( IRQ line connected to CPU -----------+---+-----------------+-------------------------------------------------------------------------- 0A00-0A03 |R/W| D D D D D D D D | PIA6821 IC3 port A Lamp Drives 1,2,3,4,6,7,8,9 (sic)(IC14) | | | | | | CA1 <= output2 from PTM6840 (IC2) | | | CA2 => alpha data | | | | | | port B Lamp Drives 10,11,12,13,14,15,16,17 (sic)(IC13) | | | | | | CB2 => alpha reset (clock on Dutch systems) | | | -----------+---+-----------------+-------------------------------------------------------------------------- 0B00-0B03 |R/W| D D D D D D D D | PIA6821 IC4 port A = data for 7seg leds (pins 10 - 17, via IC32) | | | | | | CA1 INPUT, 50 Hz input (used to generate IRQ) | | | CA2 OUTPUT, connected to pin2 74LS138 CE for multiplexer | | | (B on LED strobe multiplexer) | | | IRQA connected to IRQ of CPU | | | port B | | | PB7 = INPUT, serial port Receive data (Rx) | | | PB6 = INPUT, reel A sensor | | | PB5 = INPUT, reel B sensor | | | PB4 = INPUT, reel C sensor | | | PB3 = INPUT, reel D sensor | | | PB2 = INPUT, Connected to CA1 (50Hz signal) | | | PB1 = INPUT, undercurrent sense | | | PB0 = INPUT, overcurrent sense | | | | | | CB1 INPUT, used to generate IRQ on edge of serial input line | | | CB2 OUTPUT, enable signal for reel optics | | | IRQB connected to IRQ of CPU | | | -----------+---+-----------------+-------------------------------------------------------------------------- 0C00-0C03 |R/W| D D D D D D D D | PIA6821 IC5 port A | | | | | | PA0-PA7, INPUT AUX1 connector | | | | | | CA2 OUTPUT, serial port Transmit line (Tx) | | | CA1 not connected | | | IRQA connected to IRQ of CPU | | | | | | port B | | | | | | PB0-PB7 INPUT, AUX2 connector | | | | | | CB1 INPUT, connected to PB7 (Aux2 connector pin 4) | | | | | | CB2 OUTPUT, AY8913 chip select line | | | IRQB connected to IRQ of CPU | | | -----------+---+-----------------+-------------------------------------------------------------------------- 0D00-0D03 |R/W| D D D D D D D D | PIA6821 IC6 | | | | | | port A | | | | | | PA0 - PA7 (INPUT/OUTPUT) data port AY8913 sound chip | | | | | | CA1 INPUT, not connected | | | CA2 OUTPUT, BC1 pin AY8913 sound chip | | | IRQA , connected to IRQ CPU | | | | | | port B | | | | | | PB0-PB3 OUTPUT, reel A | | | PB4-PB7 OUTPUT, reel B | | | | | | CB1 INPUT, not connected | | | CB2 OUTPUT, B01R pin AY8913 sound chip | | | IRQB , connected to IRQ CPU | | | -----------+---+-----------------+-------------------------------------------------------------------------- 0E00-0E03 |R/W| D D D D D D D D | PIA6821 IC7 | | | | | | port A | | | | | | PA0-PA3 OUTPUT, reel C | | | PA4-PA7 OUTPUT, reel D | | | CA1 INPUT, not connected | | | CA2 OUTPUT, A on LED strobe multiplexer | | | IRQA , connected to IRQ CPU | | | | | | port B | | | | | | PB0-PB6 OUTPUT mech meter 1-7 or reel E + F | | | PB7 Voltage drop sensor | | | CB1 INPUT, not connected | | | CB2 OUTPUT,mech meter 8 | | | IRQB , connected to IRQ CPU | | | -----------+---+-----------------+-------------------------------------------------------------------------- 0F00-0F03 |R/W| D D D D D D D D | PIA6821 IC8 | | | | | | port A | | | | | | PA0-PA7 INPUT multiplexed inputs data | | | | | | CA1 INPUT, not connected | | | CA2 OUTPUT, C on LED strobe multiplexer | | | IRQA connected to IRQ CPU | | | | | | port B | | | | | | PB0-PB7 OUTPUT triacs outputs connector PL6 | | | used for slides / hoppers | | | | | | CB1 INPUT, not connected | | | CB2 OUTPUT, pin1 alpha display PL7 (clock signal) | | | IRQB connected to IRQ CPU | | | -----------+---+-----------------+-------------------------------------------------------------------------- 1000-FFFF | R | D D D D D D D D | ROM (can be bank switched by 0x850 in 8 banks of 64 k ) (NV) -----------+---+-----------------+-------------------------------------------------------------------------- Additional Notes: Games from around the era of Road Hog and Chase Invaders had sufficient additional space to store three sets of reel start/stop sounds. To change between them, follow these instructions: 1) Load the game. 2) Open the cashbox door and insert the refill key. 3) Use Hi/Lo to adjust volume 4) Use Hold 1/2/3 to choose between "Default", "Standard" and "Alternative" sound sets 5) Use Cancel/collect to test the sounds. 6) To return to the game, remove the refill key and close the door ***********************************************************************************************************/ #include "emu.h" #include "includes/mpu4.h" #include "video/awpvid.h" //Fruit Machines Only #include "machine/rescap.h" #include "speaker.h" #include "mpu4.lh" #include "mpu4ext.lh" /* LED Segments related to pins (5 is not connected): Unlike the controllers emulated in the layout code, each segment of an MPU4 LED can be set individually, even being used as individual lamps. However, we can get away with settings like this in the majority of cases. _9_ | | 3 8 | | _2_ | | 4 7 |_ _| 6 1 8 display enables (pins 10 - 17) */ void mpu4_state::lamp_extend_small(int data) { int lamp_ext_data,column,i; column = data & 0x07; lamp_ext_data = 0x1f - ((data & 0xf8) >> 3);//remove the mux lines from the data if (m_lamp_strobe_ext_persistence == 0) { //One write to reset the drive lines, one with the data, one to clear the lines, so only the 2nd write does anything //TODO: PWM for (i = 0; i < 5; i++) { m_lamps[(8*column)+i+128] = BIT(lamp_ext_data, i); } } m_lamp_strobe_ext_persistence ++; if ((m_lamp_strobe_ext_persistence == 3)||(m_lamp_strobe_ext!=column)) { m_lamp_strobe_ext_persistence = 0; m_lamp_strobe_ext=column; } } void mpu4_state::lamp_extend_large(int data,int column,int active) { int lampbase,i,bit7; m_lamp_sense = 0; bit7 = data & 0x80; if ( bit7 != m_last_b7 ) { m_card_live = 1; //depending on bit 7, we can access one of two 'blocks' of 64 lamps lampbase = bit7 ? 64 : 0; if ( data & 0x3f ) { m_lamp_sense = 1; } if ( active ) { if (m_lamp_strobe_ext != column) { for (i = 0; i < 8; i++) {//CHECK, this includes bit 7, which seems wrong m_lamps[(8*column)+i+128+lampbase] = BIT(data, i); } m_lamp_strobe_ext = column; } } m_last_b7 = bit7; } else { m_card_live = 0; } } void mpu4_state::led_write_extender(int latch, int data, int starting_column) { int diff,i,j, ext_strobe; diff = (latch ^ m_last_latch) & latch; ext_strobe = (7 - starting_column) * 8; data = ~data;//invert drive lines for (i=0; i<5; i++) { if (diff & (1<update(((data >> 4) & 0x0f)); data = (data & 0x0F); //Strip reel data from meter drives, leaving active elements awp_draw_reel(machine(),"reel5", *m_reel[4]); break; case FIVE_REEL_8TO5: m_reel[4]->update((((data & 0x01) + ((data & 0x08) >> 2) + ((data & 0x20) >> 3) + ((data & 0x80) >> 4)) & 0x0f)) ; data = 0x00; //Strip all reel data from meter drives, nothing is connected awp_draw_reel(machine(),"reel5", *m_reel[4]); break; case FIVE_REEL_3TO6: m_reel[4]->update(((data >> 2) & 0x0f)); data = 0x00; //Strip all reel data from meter drives awp_draw_reel(machine(),"reel5", *m_reel[4]); break; case SIX_REEL_1TO8: m_reel[4]->update( data & 0x0f); m_reel[5]->update((data >> 4) & 0x0f); data = 0x00; //Strip all reel data from meter drives awp_draw_reel(machine(),"reel5", *m_reel[4]); awp_draw_reel(machine(),"reel6", *m_reel[5]); break; case SIX_REEL_5TO8: m_reel[4]->update(((data >> 4) & 0x0f)); data = 0x00; //Strip all reel data from meter drives awp_draw_reel(machine(),"reel5", *m_reel[4]); break; case SEVEN_REEL: m_reel[0]->update((((data & 0x01) + ((data & 0x08) >> 2) + ((data & 0x20) >> 3) + ((data & 0x80) >> 4)) & 0x0f)) ; data = 0x00; //Strip all reel data from meter drives awp_draw_reel(machine(),"reel1", *m_reel[0]); break; case FLUTTERBOX: //The backbox fan assembly fits in a reel unit sized box, wired to the remote meter pin, so we can handle it here output().set_value("flutterbox", data & 0x80); data &= ~0x80; //Strip flutterbox data from meter drives break; } m_meters->update(7, (data & 0x80)); for (meter = 0; meter < 4; meter ++) { m_meters->update(meter, (data & (1 << meter))); } if (m_reel_mux == STANDARD_REEL) { for (meter = 4; meter < 7; meter ++) { m_meters->update(meter, (data & (1 << meter))); } } } /* called if board is reset */ MACHINE_RESET_MEMBER(mpu4_state,mpu4) { m_vfd->reset(); m_lamp_strobe = 0; m_lamp_strobe2 = 0; m_led_strobe = 0; m_mmtr_data = 0; m_remote_meter = 0; m_IC23GC = 0; m_IC23GB = 0; m_IC23GA = 0; m_IC23G1 = 1; m_IC23G2A = 0; m_IC23G2B = 0; // Bwb Orlando, which uses the bwb_bank address for banking requires the default bank to be 0! if (m_numbanks) m_bank1->set_entry(m_default_to_low_bank ? 0 : m_numbanks); m_maincpu->reset(); } /* 6809 IRQ handler */ WRITE_LINE_MEMBER(mpu4_state::cpu0_irq) { /* The PIA and PTM IRQ lines are all connected to a common PCB track, leading directly to the 6809 IRQ line. */ int combined_state = m_pia3->irq_a_state() | m_pia3->irq_b_state() | m_pia4->irq_a_state() | m_pia4->irq_b_state() | m_pia5->irq_a_state() | m_pia5->irq_b_state() | m_pia6->irq_a_state() | m_pia6->irq_b_state() | m_pia7->irq_a_state() | m_pia7->irq_b_state() | m_pia8->irq_a_state() | m_pia8->irq_b_state() | m_6840ptm->irq_state(); if (!m_link7a_connected) //7B = IRQ, 7A = FIRQ, both = NMI { m_maincpu->set_input_line(M6809_IRQ_LINE, combined_state ? ASSERT_LINE : CLEAR_LINE); LOG(("6809 int%d \n", combined_state)); } else { m_maincpu->set_input_line(M6809_FIRQ_LINE, combined_state ? ASSERT_LINE : CLEAR_LINE); LOG(("6809 fint%d \n", combined_state)); } } /* Bankswitching The MOD 4 ROM cards are set up to handle 8 separate ROM pages, arranged as 2 sets of 4. The bankswitch selects which of the 4 pages in the set is active, while the bankset switches between the sets. It appears that the cards were originally intended to be used in a 'half' page setup, where the two halves of the ROM space could be mixed and matched as appropriate. However, there is no evidence to suggest this was ever implemented. The controls for it exist however, in the form of the Soundboard PIA CB2 pin, which is used in some cabinets instead of the main control. */ void mpu4_state::bankswitch_w(uint8_t data) { m_pageval = (data & 0x03); m_bank1->set_entry((m_pageval + (m_pageset ? 4 : 0)) & m_numbanks); } uint8_t mpu4_state::bankswitch_r() { return m_bank1->entry(); } void mpu4_state::bankset_w(uint8_t data) { //logerror("bankset_w %02x\n", data); m_pageval = (data - 2);//writes 2 and 3, to represent 0 and 1 - a hangover from the half page design? m_bank1->set_entry((m_pageval + (m_pageset ? 4 : 0)) & m_numbanks); } /* IC2 6840 PTM handler */ WRITE_LINE_MEMBER(mpu4_state::ic2_o1_callback) { m_6840ptm->set_c2(state); /* copy output value to IC2 c2 this output is the clock for timer2 */ /* 1200Hz System interrupt timer */ } WRITE_LINE_MEMBER(mpu4_state::ic2_o2_callback) { m_pia3->ca1_w(state); /* copy output value to IC3 ca1 */ /* the output from timer2 is the input clock for timer3 */ /* miscellaneous interrupts generated here */ m_6840ptm->set_c3(state); } WRITE_LINE_MEMBER(mpu4_state::ic2_o3_callback) { /* the output from timer3 is used as a square wave for the alarm output and as an external clock source for timer 1! */ /* also runs lamp fade */ m_6840ptm->set_c1(state); } /* 6821 PIA handlers */ /* IC3, lamp data lines + alpha numeric display */ void mpu4_state::pia_ic3_porta_w(uint8_t data) { int i; LOG_IC3(("%s: IC3 PIA Port A Set to %2x (lamp strobes 1 - 9)\n", machine().describe_context(),data)); if(m_ic23_active) { if (m_lamp_strobe != m_input_strobe) { // Because of the nature of the lamping circuit, there is an element of persistance // As a consequence, the lamp column data can change before the input strobe without // causing the relevant lamps to black out. for (i = 0; i < 8; i++) { m_lamps[(8*m_input_strobe)+i] = BIT(data, i); } m_lamp_strobe = m_input_strobe; } } } void mpu4_state::pia_ic3_portb_w(uint8_t data) { int i; LOG_IC3(("%s: IC3 PIA Port B Set to %2x (lamp strobes 10 - 17)\n", machine().describe_context(),data)); if(m_ic23_active) { if (m_lamp_strobe2 != m_input_strobe) { for (i = 0; i < 8; i++) { m_lamps[(8*m_input_strobe)+i+64] = BIT(data, i); } m_lamp_strobe2 = m_input_strobe; } if (m_led_lamp) { /* Some games (like Connect 4) use 'programmable' LED displays, built from light display lines in section 2. */ /* These are mostly low-tech machines, where such wiring proved cheaper than an extender card */ uint8_t pled_segs[2] = {0,0}; static const int lamps1[8] = { 106, 107, 108, 109, 104, 105, 110, 111 }; static const int lamps2[8] = { 114, 115, 116, 117, 112, 113, 118, 119 }; for (i = 0; i < 8; i++) { if (m_lamps[lamps1[i]]) pled_segs[0] |= (1 << i); if (m_lamps[lamps2[i]]) pled_segs[1] |= (1 << i); } m_digits[8] = pled_segs[0]; m_digits[9] = pled_segs[1]; } } } WRITE_LINE_MEMBER(mpu4_state::pia_ic3_ca2_w) { LOG_IC3(("%s: IC3 PIA Write CA2 (alpha data), %02X\n", machine().describe_context(),state)); m_vfd->data(state); } WRITE_LINE_MEMBER(mpu4_state::pia_ic3_cb2_w) { LOG_IC3(("%s: IC3 PIA Write CB (alpha reset), %02X\n",machine().describe_context(),state)); // DM Data pin A m_vfd->por(state); } /* IC23 emulation IC23 is a 74LS138 1-of-8 Decoder It is used as a multiplexer for the LEDs, lamp selects and inputs.*/ void mpu4_state::ic23_update() { if (!m_IC23G2A) { if (!m_IC23G2B) { if (m_IC23G1) { if ( m_IC23GA ) m_input_strobe |= 0x01; else m_input_strobe &= ~0x01; if ( m_IC23GB ) m_input_strobe |= 0x02; else m_input_strobe &= ~0x02; if ( m_IC23GC ) m_input_strobe |= 0x04; else m_input_strobe &= ~0x04; } } } else if ((m_IC23G2A)||(m_IC23G2B)) { m_input_strobe = 0x00; } } /* IC24 emulation IC24 is a 74LS122 pulse generator CLEAR and B2 are tied high and A1 and A2 tied low, meaning any pulse on B1 will give a low pulse on the output pin. */ void mpu4_state::ic24_output(int data) { m_IC23G2A = data; ic23_update(); } void mpu4_state::ic24_setup() { if (m_IC23GA) { double duration = TIME_OF_74LS123((220*1000),(0.1*0.000001)); { m_ic23_active=1; ic24_output(0); m_ic24_timer->adjust(attotime::from_double(duration)); } } } TIMER_CALLBACK_MEMBER(mpu4_state::update_ic24) { m_ic23_active=0; ic24_output(1); } WRITE_LINE_MEMBER(mpu4_state::dataport_rxd) { m_serial_data = state; m_pia4->cb1_w(state); LOG_IC3(("Dataport RX %x\n",state)); } /* IC4, 7 seg leds, 50Hz timer reel sensors, current sensors */ void mpu4_state::pia_ic4_porta_w(uint8_t data) { if(m_ic23_active) { if (((m_lamp_extender == NO_EXTENDER) || (m_lamp_extender == SMALL_CARD) || (m_lamp_extender == LARGE_CARD_C)) && (m_led_extender == NO_EXTENDER)) { if(m_led_strobe != m_input_strobe) { for(int i=0; i<8; i++) { m_mpu4leds[((7 - m_input_strobe) << 3) | i] = BIT(data, i); } m_digits[7 - m_input_strobe] = data; } m_led_strobe = m_input_strobe; } } } void mpu4_state::pia_ic4_portb_w(uint8_t data) { if (m_reel_mux) { /* A write here connects one reel (and only one) to the optic test circuit. This allows 8 reels to be supported instead of 4. */ if (m_reel_mux == SEVEN_REEL) { m_active_reel = reel_mux_table7[(data >> 4) & 0x07]; } else { m_active_reel = reel_mux_table[(data >> 4) & 0x07]; } } } uint8_t mpu4_state::pia_ic4_portb_r() { if ( m_serial_data ) { m_ic4_input_b |= 0x80; } else { m_ic4_input_b &= ~0x80; } if (!m_reel_mux) { if ( m_optic_pattern & 0x01 ) m_ic4_input_b |= 0x40; /* reel A tab */ else m_ic4_input_b &= ~0x40; if ( m_optic_pattern & 0x02 ) m_ic4_input_b |= 0x20; /* reel B tab */ else m_ic4_input_b &= ~0x20; if ( m_optic_pattern & 0x04 ) m_ic4_input_b |= 0x10; /* reel C tab */ else m_ic4_input_b &= ~0x10; if ( m_optic_pattern & 0x08 ) m_ic4_input_b |= 0x08; /* reel D tab */ else m_ic4_input_b &= ~0x08; } else { if (m_optic_pattern & (1<read() | m_aux1_input; return tempinput; } void mpu4_state::pia_ic5_porta_w(uint8_t data) { int i; if (m_hopper == HOPPER_NONDUART_A) { //opto line //hopper1_drive_sensor(data&0x10); } switch (m_lamp_extender) { case NO_EXTENDER: if (m_led_extender == CARD_B) { led_write_extender(data & 0x1f, m_pia4->a_output(),m_input_strobe); } else if ((m_led_extender != CARD_A) && (m_led_extender != NO_EXTENDER)) { for(i=0; i<8; i++) { m_mpu4leds[((m_input_strobe | 8) << 3) | i] = BIT(data, i); } m_digits[m_input_strobe | 8] = data; } break; case SMALL_CARD: if(m_ic23_active) { lamp_extend_small(data); } break; case LARGE_CARD_A: lamp_extend_large(data,m_input_strobe,m_ic23_active); break; case LARGE_CARD_B: lamp_extend_large(data,m_input_strobe,m_ic23_active); if ((m_ic23_active) && m_card_live) { for(i=0; i<8; i++) { m_mpu4leds[((m_last_b7 >> 7) << 6) | (m_input_strobe << 3) | i] = BIT(~data, i); } m_digits[((m_last_b7 >> 7) << 3) | m_input_strobe] = ~data; } break; case LARGE_CARD_C: lamp_extend_large(data,m_input_strobe,m_ic23_active); break; } if (m_reel_mux == SIX_REEL_5TO8) { m_reel[4]->update( data &0x0F); m_reel[5]->update((data >> 4)&0x0F); awp_draw_reel(machine(),"reel5", *m_reel[4]); awp_draw_reel(machine(),"reel6", *m_reel[5]); } else if (m_reel_mux == SEVEN_REEL) { m_reel[1]->update( data &0x0F); m_reel[2]->update((data >> 4)&0x0F); awp_draw_reel(machine(),"reel2", *m_reel[1]); awp_draw_reel(machine(),"reel3", *m_reel[2]); } } void mpu4_state::pia_ic5_portb_w(uint8_t data) { if (m_hopper == HOPPER_NONDUART_B) { //hopper1_drive_motor(data &0x01) motor //hopper1_drive_sensor(data &0x08) opto } if (m_led_extender == CARD_A) { led_write_extender(data & 0x07, m_pia4->a_output(),m_input_strobe); } else if (m_led_extender == SIMPLE_CARD) { if(m_led_strobe != m_input_strobe) { for(int i=0; i<8; i++) { m_mpu4leds[( ( (7 - m_input_strobe) + 8) << 3) | i] = BIT(m_pia4->a_output(), i); } m_digits[(7 - m_input_strobe) + 8] = m_pia4->a_output(); } m_led_strobe = m_input_strobe; } } uint8_t mpu4_state::pia_ic5_portb_r() { if (m_hopper == HOPPER_NONDUART_B) {/* if (hopper1_active) { m_aux2_input |= 0x08; } else { m_aux2_input &= ~0x08; }*/ } LOG(("%s: IC5 PIA Read of Port B (coin input AUX2)\n",machine().describe_context())); machine().bookkeeping().coin_lockout_w(0, (m_pia5->b_output() & 0x01) ); machine().bookkeeping().coin_lockout_w(1, (m_pia5->b_output() & 0x02) ); machine().bookkeeping().coin_lockout_w(2, (m_pia5->b_output() & 0x04) ); machine().bookkeeping().coin_lockout_w(3, (m_pia5->b_output() & 0x08) ); uint8_t tempinput = m_aux2_port->read() | m_aux2_input; return tempinput; } WRITE_LINE_MEMBER(mpu4_state::pia_ic5_ca2_w) { LOG(("%s: IC5 PIA Write CA2 (Serial Tx) %2x\n",machine().describe_context(),state)); m_dataport->write_txd(state); } /* --------------------------------------- AY Chip sound function selection - --------------------------------------- The databus of the AY sound chip is connected to IC6 Port A. Data is read from/written to the AY chip through this port. If this sounds familiar, Amstrad did something very similar with their home computers. The PSG function, defined by the BC1,BC2 and BDIR signals, is controlled by CA2 and CB2 of IC6. PSG function selection: ----------------------- BDIR = IC6 CB2 and BC1 = IC6 CA2 Pin | PSG Function BDIR BC1 | 0 0 | Inactive 0 1 | Read from selected PSG register. When function is set, the PSG will make the register data available to Port A. 1 0 | Write to selected PSG register. When set, the PSG will take the data at Port A and write it into the selected PSG register. 1 1 | Select PSG register. When set, the PSG will take the data at Port A and select a register. */ /* PSG function selected */ void mpu4_state::update_ay(device_t *device) { if (!m_ay8913) return; pia6821_device *pia = downcast(device); if (!pia->cb2_output()) { switch (m_ay8913_address) { case 0x00: /* Inactive */ break; case 0x01: /* CA2 = 1 CB2 = 0? : Read from selected PSG register and make the register data available to Port A */ LOG(("AY8913 address = %d \n",m_pia6->a_output()&0x0f)); break; case 0x02: /* CA2 = 0 CB2 = 1? : Write to selected PSG register and write data to Port A */ m_ay8913->data_w(m_pia6->a_output()); LOG(("AY Chip Write \n")); break; case 0x03: /* CA2 = 1 CB2 = 1? : The register will now be selected and the user can read from or write to it. The register will remain selected until another is chosen.*/ m_ay8913->address_w(m_pia6->a_output()); LOG(("AY Chip Select \n")); break; default: LOG(("AY Chip error \n")); break; } } } WRITE_LINE_MEMBER(mpu4_state::pia_ic5_cb2_w) { update_ay(m_pia5); } /* IC6, Reel A and B and AY registers (MODs below 4 only) */ void mpu4_state::pia_ic6_portb_w(uint8_t data) { LOG(("%s: IC6 PIA Port B Set to %2x (Reel A and B)\n", machine().describe_context(),data)); if (m_reel_mux == SEVEN_REEL) { m_reel[3]->update( data &0x0F); m_reel[4]->update((data >> 4)&0x0F); awp_draw_reel(machine(),"reel4", *m_reel[3]); awp_draw_reel(machine(),"reel5", *m_reel[4]); } else if (m_reels) { m_reel[0]->update( data &0x0F); m_reel[1]->update((data >> 4)&0x0F); awp_draw_reel(machine(),"reel1", *m_reel[0]); awp_draw_reel(machine(),"reel2", *m_reel[1]); } } void mpu4_state::pia_ic6_porta_w(uint8_t data) { LOG(("%s: IC6 PIA Write A %2x\n", machine().describe_context(),data)); if (m_mod_number <4) { m_ay_data = data; update_ay(m_pia6); } } WRITE_LINE_MEMBER(mpu4_state::pia_ic6_ca2_w) { LOG(("%s: IC6 PIA write CA2 %2x (AY8913 BC1)\n", machine().describe_context(),state)); if (m_mod_number <4) { if ( state ) m_ay8913_address |= 0x01; else m_ay8913_address &= ~0x01; update_ay(m_pia6); } } WRITE_LINE_MEMBER(mpu4_state::pia_ic6_cb2_w) { LOG(("%s: IC6 PIA write CB2 %2x (AY8913 BCDIR)\n", machine().describe_context(),state)); if (m_mod_number <4) { if ( state ) m_ay8913_address |= 0x02; else m_ay8913_address &= ~0x02; update_ay(m_pia5); // using m_pia5 here allows m4fourmr to have sound } } /* IC7 Reel C and D, mechanical meters/Reel E and F, input strobe bit A */ void mpu4_state::pia_ic7_porta_w(uint8_t data) { LOG(("%s: IC7 PIA Port A Set to %2x (Reel C and D)\n", machine().describe_context(),data)); if (m_reel_mux == SEVEN_REEL) { m_reel[5]->update( data &0x0F); m_reel[6]->update((data >> 4)&0x0F); awp_draw_reel(machine(),"reel6", *m_reel[5]); awp_draw_reel(machine(),"reel7", *m_reel[6]); } else if (m_reels) { m_reel[2]->update( data &0x0F); m_reel[3]->update((data >> 4)&0x0F); awp_draw_reel(machine(),"reel3", *m_reel[2]); awp_draw_reel(machine(),"reel4", *m_reel[3]); } } void mpu4_state::pia_ic7_portb_w(uint8_t data) { if (m_hopper == HOPPER_DUART_A) { //duart write data } else if (m_hopper == HOPPER_NONDUART_A) { //hoppr1_drive_motor(data & 0x10); } m_mmtr_data = data; } uint8_t mpu4_state::pia_ic7_portb_r() { /* The meters are connected to a voltage drop sensor, where current flowing through them also passes through pin B7, meaning that when any meter is activated, pin B7 goes high. As for why they connected this to an output port rather than using CB1, no idea, although it proved of benefit when the reel multiplexer was designed as it allows a separate meter to be used when the rest of the port is blocked. This appears to have confounded the schematic drawer, who has assumed that all eight meters are driven from this port, giving the 8 line driver chip 9 connections in total. */ //This may be overkill, but the meter sensing is VERY picky int combined_meter = m_meters->get_activity(0) | m_meters->get_activity(1) | m_meters->get_activity(2) | m_meters->get_activity(3) | m_meters->get_activity(4) | m_meters->get_activity(5) | m_meters->get_activity(6) | m_meters->get_activity(7); if(combined_meter) { return 0x80; } else { return 0x00; } } WRITE_LINE_MEMBER(mpu4_state::pia_ic7_ca2_w) { LOG(("%s: IC7 PIA write CA2 %2x (input strobe bit 0 / LED A)\n", machine().describe_context(),state)); m_IC23GA = state; ic24_setup(); ic23_update(); } WRITE_LINE_MEMBER(mpu4_state::pia_ic7_cb2_w) { m_remote_meter = state?0x80:0x00; } /* IC8, Inputs, TRIACS, alpha clock */ uint8_t mpu4_state::pia_ic8_porta_r() { LOG_IC8(("%s: IC8 PIA Read of Port A (MUX input data)\n", machine().describe_context())); /* The orange inputs are polled twice as often as the black ones, for reasons of efficiency. This is achieved via connecting every input line to an AND gate, thus allowing two strobes to represent each orange input bank (strobes are active low). */ m_pia5->cb1_w(m_aux2_port->read() & 0x80); return (m_port_mux[m_input_strobe])->read(); } void mpu4_state::pia_ic8_portb_w(uint8_t data) { if (m_hopper == HOPPER_DUART_B) { // duart.drive_sensor(data & 0x04, data & 0x01, 0, 0); } else if (m_hopper == HOPPER_DUART_C) { // duart.drive_sensor(data & 0x04, data & 0x01, data & 0x04, data & 0x02); } LOG_IC8(("%s: IC8 PIA Port B Set to %2x (OUTPUT PORT, TRIACS)\n", machine().describe_context(),data)); for (int i = 0; i < 8; i++) { m_triacs[i] = BIT(data, i); } } WRITE_LINE_MEMBER(mpu4_state::pia_ic8_ca2_w) { LOG_IC8(("%s: IC8 PIA write CA2 (input_strobe bit 2 / LED C) %02X\n", machine().describe_context(), state & 0xFF)); m_IC23GC = state; ic23_update(); } WRITE_LINE_MEMBER(mpu4_state::pia_ic8_cb2_w) { LOG_IC8(("%s: IC8 PIA write CB2 (alpha clock) %02X\n", machine().describe_context(), state & 0xFF)); // DM Data pin B m_vfd->sclk(!state); } // universal sampled sound program card PCB 683077 // Sampled sound card, using a PIA and PTM for timing and data handling void mpu4_state::pia_gb_porta_w(uint8_t data) { LOG_SS(("%s: GAMEBOARD: PIA Port A Set to %2x\n", machine().describe_context(),data)); m_msm6376->write(data); } void mpu4_state::pia_gb_portb_w(uint8_t data) { int changed = m_expansion_latch^data; LOG_SS(("%s: GAMEBOARD: PIA Port B Set to %2x\n", machine().describe_context(),data)); if ( changed & 0x20) { // digital volume clock line changed if ( !(data & 0x20) ) { // changed from high to low, if ( !(data & 0x10) )//down { if ( m_global_volume < 32 ) m_global_volume++; //steps unknown } else {//up if ( m_global_volume > 0 ) m_global_volume--; } { LOG_SS(("%s: GAMEBOARD: Volume Set to %2x\n", machine().describe_context(),data)); float percent = (32-m_global_volume)/32.0; m_msm6376->set_output_gain(0, percent); m_msm6376->set_output_gain(1, percent); } } } m_msm6376->ch2_w(data&0x02); m_msm6376->st_w(data&0x01); } uint8_t mpu4_state::pia_gb_portb_r() { LOG_SS(("%s: GAMEBOARD: PIA Read of Port B\n",machine().describe_context())); int data=0; // b7 NAR - we can load another address into Channel 1 // b6, 1 = OKI ready, 0 = OKI busy // b5, vol clock // b4, 1 = Vol down, 0 = Vol up // if ( m_msm6376->nar_r() ) data |= 0x80; else data &= ~0x80; if ( m_msm6376->busy_r() ) data |= 0x40; else data &= ~0x40; return ( data | m_expansion_latch ); } WRITE_LINE_MEMBER(mpu4_state::pia_gb_ca2_w) { LOG_SS(("%s: GAMEBOARD: OKI RESET data = %02X\n", machine().describe_context(), state)); // reset line } WRITE_LINE_MEMBER(mpu4_state::pia_gb_cb2_w) { // Some BWB games use this to drive the bankswitching // should the regular bankswitch still work in these cases? if (m_bwb_bank) { m_pageval = state; m_bank1->set_entry((m_pageval + (m_pageset ? 4 : 0)) & m_numbanks); } } //Sampled sound timer /* The MSM6376 sound chip is configured in a slightly strange way, to enable dynamic sample rate changes (8Khz, 10.6 Khz, 16 KHz) by varying the clock. According to the BwB programmer's guide, the formula is: MSM6376 clock frequency:- freq = (1720000/((t3L+1)(t3H+1)))*[(t3H(T3L+1)+1)/(2(t1+1))] where [] means rounded up integer, t3L is the LSB of Clock 3, t3H is the MSB of Clock 3, and t1 is the initial value in clock 1. */ //O3 -> G1 O1 -> c2 o2 -> c1 /* This is a bit of a cheat - since we don't clock into the OKI chip directly, we need to calculate the oscillation frequency in advance. We're running the timer for interrupt purposes, but the frequency calculation is done by plucking the values out as they are written.*/ void mpu4_state::ic3ss_w(offs_t offset, uint8_t data) { m_ptm_ic3ss->write(offset,data); if (offset == 3) { m_t1 = data; } if (offset == 6) { m_t3h = data; } if (offset == 7) { m_t3l = data; } float num = (1720000/((m_t3l + 1)*(m_t3h + 1))); float denom1 = ((m_t3h *(m_t3l + 1)+ 1)/(2*(m_t1 + 1))); int denom2 = denom1 + 0.5f;//need to round up, this gives same precision as chip int freq=num*denom2; if (freq) { m_msm6376->set_unscaled_clock(freq); } } /* input ports for MPU4 board */ INPUT_PORTS_START( mpu4 ) PORT_START("ORANGE1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("00")// 20p level PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("01")// 100p level PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("02")// Token 1 level PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("03")// Token 2 level PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("04") PORT_CONFNAME( 0xe0, 0x00, "Stake Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 5p" ) PORT_CONFSETTING( 0x20, "10p" ) PORT_CONFSETTING( 0x40, "20p" ) PORT_CONFSETTING( 0x60, "25p" ) PORT_CONFSETTING( 0x80, "30p" ) PORT_CONFSETTING( 0xa0, "40p" ) PORT_CONFSETTING( 0xc0, "50p" ) PORT_CONFSETTING( 0xe0, "1 GBP" ) PORT_START("ORANGE2") PORT_CONFNAME( 0x0f, 0x00, "Jackpot / Prize Key" ) PORT_CONFSETTING( 0x00, "Not fitted" ) PORT_CONFSETTING( 0x01, "3 GBP" ) PORT_CONFSETTING( 0x02, "4 GBP" ) PORT_CONFSETTING( 0x08, "5 GBP" ) PORT_CONFSETTING( 0x03, "6 GBP" ) PORT_CONFSETTING( 0x04, "6 GBP Token" ) PORT_CONFSETTING( 0x05, "8 GBP" ) PORT_CONFSETTING( 0x06, "8 GBP Token" ) PORT_CONFSETTING( 0x07, "10 GBP" ) PORT_CONFSETTING( 0x09, "15 GBP" ) PORT_CONFSETTING( 0x0a, "25 GBP" ) PORT_CONFSETTING( 0x0b, "25 GBP (Licensed Betting Office Profile)" ) PORT_CONFSETTING( 0x0c, "35 GBP" ) PORT_CONFSETTING( 0x0d, "70 GBP" ) PORT_CONFSETTING( 0x0e, "Reserved" ) PORT_CONFSETTING( 0x0f, "Reserved" ) PORT_CONFNAME( 0xf0, 0x00, "Percentage Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 68% (Invalid for UK Games)" ) PORT_CONFSETTING( 0x10, "70" ) PORT_CONFSETTING( 0x20, "72" ) PORT_CONFSETTING( 0x30, "74" ) PORT_CONFSETTING( 0x40, "76" ) PORT_CONFSETTING( 0x50, "78" ) PORT_CONFSETTING( 0x60, "80" ) PORT_CONFSETTING( 0x70, "82" ) PORT_CONFSETTING( 0x80, "84" ) PORT_CONFSETTING( 0x90, "86" ) PORT_CONFSETTING( 0xa0, "88" ) PORT_CONFSETTING( 0xb0, "90" ) PORT_CONFSETTING( 0xc0, "92" ) PORT_CONFSETTING( 0xd0, "94" ) PORT_CONFSETTING( 0xe0, "96" ) PORT_CONFSETTING( 0xf0, "98" ) PORT_START("BLACK1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Hi") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Lo") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("18") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("19") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("20") PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_SERVICE) PORT_NAME("Test Button") PORT_CODE(KEYCODE_W) PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_SERVICE) PORT_NAME("Refill Key") PORT_CODE(KEYCODE_R) PORT_TOGGLE PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_INTERLOCK) PORT_NAME("Cashbox (Back) Door") PORT_CODE(KEYCODE_Q) PORT_TOGGLE PORT_START("BLACK2") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("24") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("25") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Cancel") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_NAME("Hold 1") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_NAME("Hold 2") PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_NAME("Hold 3") PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_NAME("Hold 4") PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_START1) PORT_START("DIL1") PORT_DIPNAME( 0x01, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:04") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_DIPNAME( 0xf0, 0x00, "Target Percentage (if key not fitted)" )PORT_DIPLOCATION("DIL1:05,06,07,08") PORT_DIPSETTING( 0x00, "Unset (Program Optimum)" ) PORT_DIPSETTING( 0x10, "70" ) PORT_DIPSETTING( 0x20, "72" ) PORT_DIPSETTING( 0x30, "74" ) PORT_DIPSETTING( 0x40, "76" ) PORT_DIPSETTING( 0x50, "78" ) PORT_DIPSETTING( 0x60, "80" ) PORT_DIPSETTING( 0x70, "82" ) PORT_DIPSETTING( 0x80, "84" ) PORT_DIPSETTING( 0x90, "86" ) PORT_DIPSETTING( 0xa0, "88" ) PORT_DIPSETTING( 0xb0, "90" ) PORT_DIPSETTING( 0xc0, "92" ) PORT_DIPSETTING( 0xd0, "94" ) PORT_DIPSETTING( 0xe0, "96" ) PORT_DIPSETTING( 0xf0, "98" ) PORT_START("DIL2") PORT_DIPNAME( 0x01, 0x00, "Token Lockout when full" ) PORT_DIPLOCATION("DIL2:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unused )) PORT_DIPLOCATION("DIL2:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_DIPNAME( 0x04, 0x00, "Scottish Coin Handling" ) PORT_DIPLOCATION("DIL2:03")//20p payout PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPNAME( 0x08, 0x00, "Out of Credit Display Inhibit" ) PORT_DIPLOCATION("DIL2:04") // many games need this 'OFF' to display attract cycles PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_DIPNAME( 0x10, 0x00, "OCD Audio Enable" ) PORT_DIPLOCATION("DIL2:05") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x10, DEF_STR( On ) ) PORT_DIPNAME( 0x20, 0x00, "Coin Alarm Inhibit" ) PORT_DIPLOCATION("DIL2:06") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x20, DEF_STR( On ) ) PORT_DIPNAME( 0x40, 0x00, "Token Refill Level Inhibit" ) PORT_DIPLOCATION("DIL2:07") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x00, "Single Credit Entry" ) PORT_DIPLOCATION("DIL2:08") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x80, DEF_STR( On ) ) PORT_START("AUX1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_0") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_1") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_2") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_3") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_4") PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_5") PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_6") PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("A1_7") PORT_START("AUX2") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_CUSTOM) //Lockouts, in same order as below PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_COIN1) PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_COIN2) PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_COIN3) PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_COIN4) INPUT_PORTS_END INPUT_PORTS_START( mpu4_impcoin ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("AUX2") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_COIN1) PORT_IMPULSE(4) PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_COIN2) PORT_IMPULSE(4) PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_COIN3) PORT_IMPULSE(4) PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_COIN4) PORT_IMPULSE(4) INPUT_PORTS_END INPUT_PORTS_START( mpu4_invcoin ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("AUX2") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_COIN1) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_COIN2) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_COIN3) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_COIN4) INPUT_PORTS_END INPUT_PORTS_START( mpu4_invimpcoin ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("AUX2") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_COIN1) PORT_IMPULSE(5) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_COIN2) PORT_IMPULSE(5) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_COIN3) PORT_IMPULSE(5) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_COIN4) PORT_IMPULSE(5) INPUT_PORTS_END INPUT_PORTS_START( mpu4_cw ) //Inputs for CoinWorld games PORT_INCLUDE( mpu4 ) PORT_MODIFY("DIL1") PORT_DIPNAME( 0x01, 0x00, "Profile Type" ) PORT_DIPLOCATION("DIL1:01") PORT_DIPSETTING( 0x00, "Bingo Profile" ) PORT_DIPSETTING( 0x01, "Arcade" ) PORT_DIPNAME( 0x02, 0x00, "Accept 2 GBP Coin?" ) PORT_DIPLOCATION("DIL1:02") PORT_DIPSETTING( 0x00, DEF_STR( No ) ) PORT_DIPSETTING( 0x02, DEF_STR( Yes ) ) PORT_DIPNAME( 0x0C, 0x00, "Jackpot" ) PORT_DIPLOCATION("DIL1:03,04") PORT_DIPSETTING( 0x04, "15 GBP" ) PORT_DIPSETTING( 0x00, "10 GBP" ) PORT_DIPSETTING( 0x08, "5 GBP" ) PORT_DIPNAME( 0x10, 0x00, "Hold Mode" ) PORT_DIPLOCATION("DIL1:05") PORT_DIPSETTING( 0x00, "Show Hints" ) PORT_DIPSETTING( 0x10, "Auto Hold" ) PORT_DIPNAME( 0x20, 0x00, "Coin Mech Type" ) PORT_DIPLOCATION("DIL1:05") PORT_DIPSETTING( 0x00, "6 Coin" ) PORT_DIPSETTING( 0x20, "5 Coin" ) PORT_DIPNAME( 0x40, 0x00, "Reel Motor Type" ) PORT_DIPLOCATION("DIL1:05") PORT_DIPSETTING( 0x00, "Slim motor" ) PORT_DIPSETTING( 0x40, "Fat motor" ) PORT_DIPNAME( 0x80, 0x00, "Payout Tube" ) PORT_DIPLOCATION("DIL1:05") PORT_DIPSETTING( 0x00, "20p" ) PORT_DIPSETTING( 0x80, "10p" ) PORT_MODIFY("DIL2") PORT_DIPNAME( 0x07, 0x00, "Stake Setting" ) PORT_DIPSETTING( 0x00, "Not fitted / 5p" ) PORT_DIPSETTING( 0x01, "10p" ) PORT_DIPSETTING( 0x02, "20p" ) PORT_DIPSETTING( 0x03, "25p" ) PORT_DIPSETTING( 0x04, "30p" ) PORT_BIT(0xE0, IP_ACTIVE_HIGH, IPT_UNUSED) INPUT_PORTS_END INPUT_PORTS_START( mpu420p ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("ORANGE1") PORT_CONFNAME( 0xe0, 0x40, "Stake Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 5p" ) PORT_CONFSETTING( 0x20, "10p" ) PORT_CONFSETTING( 0x40, "20p" ) PORT_CONFSETTING( 0x60, "25p" ) PORT_CONFSETTING( 0x80, "30p" ) PORT_CONFSETTING( 0xa0, "40p" ) PORT_CONFSETTING( 0xc0, "50p" ) PORT_CONFSETTING( 0xe0, "1 GBP" ) INPUT_PORTS_END INPUT_PORTS_START( mpu4jackpot8tkn ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("ORANGE2") PORT_CONFNAME( 0x0F, 0x06, "Jackpot / Prize Key" ) PORT_CONFSETTING( 0x00, "Not fitted" ) PORT_CONFSETTING( 0x01, "3 GBP" ) PORT_CONFSETTING( 0x02, "4 GBP" ) PORT_CONFSETTING( 0x08, "5 GBP" ) PORT_CONFSETTING( 0x03, "6 GBP" ) PORT_CONFSETTING( 0x04, "6 GBP Token" ) PORT_CONFSETTING( 0x05, "8 GBP" ) PORT_CONFSETTING( 0x06, "8 GBP Token" ) PORT_CONFSETTING( 0x07, "10 GBP" ) PORT_CONFSETTING( 0x09, "15 GBP" ) PORT_CONFSETTING( 0x0A, "25 GBP" ) PORT_CONFSETTING( 0x0B, "25 GBP (Licensed Betting Office Profile)" ) PORT_CONFSETTING( 0x0C, "35 GBP" ) PORT_CONFSETTING( 0x0D, "70 GBP" ) PORT_CONFSETTING( 0x0E, "Reserved" ) PORT_CONFSETTING( 0x0F, "Reserved" ) INPUT_PORTS_END INPUT_PORTS_START( mpu4jackpot8tkn20p ) PORT_INCLUDE( mpu4jackpot8tkn ) PORT_MODIFY("ORANGE1") PORT_CONFNAME( 0xe0, 0x40, "Stake Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 5p" ) PORT_CONFSETTING( 0x20, "10p" ) PORT_CONFSETTING( 0x40, "20p" ) PORT_CONFSETTING( 0x60, "25p" ) PORT_CONFSETTING( 0x80, "30p" ) PORT_CONFSETTING( 0xa0, "40p" ) PORT_CONFSETTING( 0xc0, "50p" ) PORT_CONFSETTING( 0xe0, "1 GBP" ) INPUT_PORTS_END INPUT_PORTS_START( mpu4jackpot8tkn20p90pc ) PORT_INCLUDE( mpu4jackpot8tkn20p ) PORT_MODIFY("ORANGE2") PORT_CONFNAME( 0xf0, 0xb0, "Percentage Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 68% (Invalid for UK Games)" ) PORT_CONFSETTING( 0x10, "70" ) PORT_CONFSETTING( 0x20, "72" ) PORT_CONFSETTING( 0x30, "74" ) PORT_CONFSETTING( 0x40, "76" ) PORT_CONFSETTING( 0x50, "78" ) PORT_CONFSETTING( 0x60, "80" ) PORT_CONFSETTING( 0x70, "82" ) PORT_CONFSETTING( 0x80, "84" ) PORT_CONFSETTING( 0x90, "86" ) PORT_CONFSETTING( 0xa0, "88" ) PORT_CONFSETTING( 0xb0, "90" ) PORT_CONFSETTING( 0xc0, "92" ) PORT_CONFSETTING( 0xd0, "94" ) PORT_CONFSETTING( 0xe0, "96" ) PORT_CONFSETTING( 0xf0, "98" ) INPUT_PORTS_END INPUT_PORTS_START( mpu4jackpot8per ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("ORANGE2") PORT_CONFNAME( 0x0f, 0x06, "Jackpot / Prize Key" ) PORT_CONFSETTING( 0x00, "Not fitted" ) PORT_CONFSETTING( 0x01, "3 GBP" ) PORT_CONFSETTING( 0x02, "4 GBP" ) PORT_CONFSETTING( 0x08, "5 GBP" ) PORT_CONFSETTING( 0x03, "6 GBP" ) PORT_CONFSETTING( 0x04, "6 GBP Token" ) PORT_CONFSETTING( 0x05, "8 GBP" ) PORT_CONFSETTING( 0x06, "8 GBP Token" ) PORT_CONFSETTING( 0x07, "10 GBP" ) PORT_CONFSETTING( 0x09, "15 GBP" ) PORT_CONFSETTING( 0x0a, "25 GBP" ) PORT_CONFSETTING( 0x0b, "25 GBP (Licensed Betting Office Profile)" ) PORT_CONFSETTING( 0x0c, "35 GBP" ) PORT_CONFSETTING( 0x0d, "70 GBP" ) PORT_CONFSETTING( 0x0e, "Reserved" ) PORT_CONFSETTING( 0x0f, "Reserved" ) PORT_CONFNAME( 0xf0, 0x10, "Percentage Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 68% (Invalid for UK Games)" ) PORT_CONFSETTING( 0x10, "70" ) PORT_CONFSETTING( 0x20, "72" ) PORT_CONFSETTING( 0x30, "74" ) PORT_CONFSETTING( 0x40, "76" ) PORT_CONFSETTING( 0x50, "78" ) PORT_CONFSETTING( 0x60, "80" ) PORT_CONFSETTING( 0x70, "82" ) PORT_CONFSETTING( 0x80, "84" ) PORT_CONFSETTING( 0x90, "86" ) PORT_CONFSETTING( 0xa0, "88" ) PORT_CONFSETTING( 0xb0, "90" ) PORT_CONFSETTING( 0xc0, "92" ) PORT_CONFSETTING( 0xd0, "94" ) PORT_CONFSETTING( 0xe0, "96" ) PORT_CONFSETTING( 0xf0, "98" ) INPUT_PORTS_END INPUT_PORTS_START( mpu4_70pc ) PORT_INCLUDE( mpu4 ) PORT_MODIFY("ORANGE2") PORT_CONFNAME( 0xf0, 0x10, "Percentage Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 68% (Invalid for UK Games)" ) PORT_CONFSETTING( 0x10, "70" ) PORT_CONFSETTING( 0x20, "72" ) PORT_CONFSETTING( 0x30, "74" ) PORT_CONFSETTING( 0x40, "76" ) PORT_CONFSETTING( 0x50, "78" ) PORT_CONFSETTING( 0x60, "80" ) PORT_CONFSETTING( 0x70, "82" ) PORT_CONFSETTING( 0x80, "84" ) PORT_CONFSETTING( 0x90, "86" ) PORT_CONFSETTING( 0xa0, "88" ) PORT_CONFSETTING( 0xb0, "90" ) PORT_CONFSETTING( 0xc0, "92" ) PORT_CONFSETTING( 0xd0, "94" ) PORT_CONFSETTING( 0xe0, "96" ) PORT_CONFSETTING( 0xf0, "98" ) INPUT_PORTS_END INPUT_PORTS_START( grtecp ) PORT_START("ORANGE1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("00")// 20p level PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("01")// 100p level PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("02")// Token 1 level PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("03")// Token 2 level PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("04") PORT_CONFNAME( 0xe0, 0x00, "Stake Key" ) PORT_CONFSETTING( 0x00, "Not fitted / 5p" ) PORT_CONFSETTING( 0x20, "10p" ) PORT_CONFSETTING( 0x40, "20p" ) PORT_CONFSETTING( 0x60, "25p" ) PORT_CONFSETTING( 0x80, "30p" ) PORT_CONFSETTING( 0xa0, "40p" ) PORT_CONFSETTING( 0xc0, "50p" ) PORT_CONFSETTING( 0xe0, "1 GBP" ) PORT_START("ORANGE2") PORT_CONFNAME( 0x0f, 0x00, "Jackpot / Prize Key" ) PORT_CONFSETTING( 0x00, "Not fitted" ) PORT_CONFSETTING( 0x01, "3 GBP" ) PORT_CONFSETTING( 0x02, "4 GBP" ) PORT_CONFSETTING( 0x08, "5 GBP" ) PORT_CONFSETTING( 0x03, "6 GBP" ) PORT_CONFSETTING( 0x04, "6 GBP Token" ) PORT_CONFSETTING( 0x05, "8 GBP" ) PORT_CONFSETTING( 0x06, "8 GBP Token" ) PORT_CONFSETTING( 0x07, "10 GBP" ) PORT_CONFSETTING( 0x09, "15 GBP" ) PORT_CONFSETTING( 0x0a, "25 GBP" ) PORT_CONFSETTING( 0x0b, "25 GBP (Licensed Betting Office Profile)" ) PORT_CONFSETTING( 0x0c, "35 GBP" ) PORT_CONFSETTING( 0x0d, "70 GBP" ) PORT_CONFSETTING( 0x0e, "Reserved" ) PORT_CONFSETTING( 0x0f, "Reserved" ) PORT_CONFNAME( 0xf0, 0x00, "Percentage Key" ) PORT_CONFSETTING( 0x00, "As Option Switches" ) PORT_CONFSETTING( 0x10, "70" ) PORT_CONFSETTING( 0x20, "72" ) PORT_CONFSETTING( 0x30, "74" ) PORT_CONFSETTING( 0x40, "76" ) PORT_CONFSETTING( 0x50, "78" ) PORT_CONFSETTING( 0x60, "80" ) PORT_CONFSETTING( 0x70, "82" ) PORT_CONFSETTING( 0x80, "84" ) PORT_CONFSETTING( 0x90, "86" ) PORT_CONFSETTING( 0xa0, "88" ) PORT_CONFSETTING( 0xb0, "90" ) PORT_CONFSETTING( 0xc0, "92" ) PORT_CONFSETTING( 0xd0, "94" ) PORT_CONFSETTING( 0xe0, "96" ) PORT_CONFSETTING( 0xf0, "98" ) PORT_START("BLACK1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_SERVICE) PORT_NAME("Test Button") PORT_CODE(KEYCODE_W) PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_SERVICE) PORT_NAME("Refill Key") PORT_CODE(KEYCODE_R) PORT_TOGGLE PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_INTERLOCK) PORT_NAME("Cashbox (Back) Door") PORT_CODE(KEYCODE_Q) PORT_TOGGLE PORT_START("BLACK2") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Collect/Cancel") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Hold 1") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Hold 2") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_NAME("Hold 3") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_NAME("Hi") PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_NAME("Lo") PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_NAME("Exchange") PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_START1) PORT_START("DIL1") PORT_DIPNAME( 0x01, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("DIL1:04") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_DIPNAME( 0xf0, 0x00, "Target Percentage (if key not fitted)" )PORT_DIPLOCATION("DIL1:05,06,07,08") PORT_DIPSETTING( 0x00, "Unset (Program Optimum)" ) PORT_DIPSETTING( 0x10, "70" ) PORT_DIPSETTING( 0x20, "72" ) PORT_DIPSETTING( 0x30, "74" ) PORT_DIPSETTING( 0x40, "76" ) PORT_DIPSETTING( 0x50, "78" ) PORT_DIPSETTING( 0x60, "80" ) PORT_DIPSETTING( 0x70, "82" ) PORT_DIPSETTING( 0x80, "84" ) PORT_DIPSETTING( 0x90, "86" ) PORT_DIPSETTING( 0xa0, "88" ) PORT_DIPSETTING( 0xb0, "90" ) PORT_DIPSETTING( 0xc0, "92" ) PORT_DIPSETTING( 0xd0, "94" ) PORT_DIPSETTING( 0xe0, "96" ) PORT_DIPSETTING( 0xf0, "98" ) PORT_START("DIL2") PORT_DIPNAME( 0x01, 0x00, "Token Lockout when full" ) PORT_DIPLOCATION("DIL2:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unused )) PORT_DIPLOCATION("DIL2:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_DIPNAME( 0x04, 0x00, "Scottish Coin Handling" ) PORT_DIPLOCATION("DIL2:03")//20p payout PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPNAME( 0x08, 0x00, "Out of Credit Display Inhibit" ) PORT_DIPLOCATION("DIL2:04") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_DIPNAME( 0x10, 0x00, "OCD Audio Enable" ) PORT_DIPLOCATION("DIL2:05") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x10, DEF_STR( On ) ) PORT_DIPNAME( 0x20, 0x00, "Coin Alarm Inhibit" ) PORT_DIPLOCATION("DIL2:06") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x20, DEF_STR( On ) ) PORT_DIPNAME( 0x40, 0x00, "Token Refill Level Inhibit" ) PORT_DIPLOCATION("DIL2:07") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x00, "Single Credit Entry" ) PORT_DIPLOCATION("DIL2:08") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x80, DEF_STR( On ) ) PORT_START("AUX1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("0") PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("1") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("2") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("3") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("4") PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("5") PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("6") PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("7") PORT_START("AUX2") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_COIN1) PORT_NAME("10p")//PORT_IMPULSE(5) PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_COIN2) PORT_NAME("20p")//PORT_IMPULSE(5) PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_COIN3) PORT_NAME("50p")//PORT_IMPULSE(5) PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_COIN4) PORT_NAME("100p")//PORT_IMPULSE(5) INPUT_PORTS_END /* Common configurations */ void mpu4_state::mpu4_ym2413_w(offs_t offset, uint8_t data) { if (m_ym2413) m_ym2413->write(offset,data); } uint8_t mpu4_state::mpu4_ym2413_r(offs_t offset) { // if (m_ym2413) return m_ym2413->read(offset); return 0xff; } void mpu4_state::mpu4_install_mod4yam_space(address_space &space) { space.install_read_handler(0x0880, 0x0882, read8sm_delegate(*this, FUNC(mpu4_state::mpu4_ym2413_r))); space.install_write_handler(0x0880, 0x0881, write8sm_delegate(*this, FUNC(mpu4_state::mpu4_ym2413_w))); } void mpu4_state::mpu4_install_mod4oki_space(address_space &space) { pia6821_device *const pia_ic4ss = subdevice("pia_ic4ss"); space.install_readwrite_handler(0x0880, 0x0883, read8sm_delegate(*pia_ic4ss, FUNC(pia6821_device::read)), write8sm_delegate(*pia_ic4ss, FUNC(pia6821_device::write))); space.install_read_handler(0x08c0, 0x08c7, read8sm_delegate(*m_ptm_ic3ss, FUNC(ptm6840_device::read))); space.install_write_handler(0x08c0, 0x08c7, write8sm_delegate(*this, FUNC(mpu4_state::ic3ss_w))); } void mpu4_state::mpu4_config_common() { m_lamps.resolve(); m_mpu4leds.resolve(); m_digits.resolve(); m_triacs.resolve(); m_ic24_timer = timer_alloc(FUNC(mpu4_state::update_ic24), this); m_lamp_strobe_ext_persistence = 0; } MACHINE_START_MEMBER(mpu4_state,mod2) { mpu4_config_common(); m_link7a_connected=0; m_mod_number=2; } MACHINE_START_MEMBER(mpu4_state,mpu4yam) { address_space &space = m_maincpu->space(AS_PROGRAM); mpu4_config_common(); m_link7a_connected=0; m_mod_number=4; mpu4_install_mod4yam_space(space); } MACHINE_START_MEMBER(mpu4_state,mpu4oki) { address_space &space = m_maincpu->space(AS_PROGRAM); mpu4_config_common(); m_link7a_connected=0; m_mod_number=4; mpu4_install_mod4oki_space(space); } //TODO: Replace with standard six reels once sets are sorted out - is really six_reel_std void mpu4_state::init_m4altreels() { m_reel_mux = SIX_REEL_1TO8; m_reels = 6; setup_rom_banks(); } void mpu4_state::init_m4altreels_big() { init_m4default_big(); m_reel_mux = SIX_REEL_1TO8; m_reels = 6; } void mpu4_state::init_m4_andycp10c() { init_m4default(); use_m4_small_extender(); } void mpu4_state::init_m4default_big_five_std() { init_m4default_big(); use_m4_five_reel_std(); } void mpu4_state::init_m4default_big_five_rev() { init_m4default_big(); use_m4_five_reel_rev(); } void mpu4_state::init_m4default_big_six() { init_m4default_big(); use_m4_six_reel_std(); } void mpu4_state::init_m4default_big_six_alt() { init_m4default_big(); use_m4_six_reel_alt(); } void mpu4_state::init_m4default_five_std() { init_m4default(); use_m4_five_reel_std(); } void mpu4_state::init_m4default_five_rev() { init_m4default(); use_m4_five_reel_rev(); } void mpu4_state::init_m4default_five_alt() { init_m4default(); use_m4_five_reel_alt(); } void mpu4_state::init_m4default_six() { init_m4default(); use_m4_six_reel_std(); } void mpu4_state::init_m4default_six_alt() { init_m4default(); use_m4_six_reel_alt(); } void mpu4_state::init_m4default_seven() { init_m4default(); use_m4_seven_reel(); } void mpu4_state::init_big_extenda() { init_m4default_big(); m_lamp_extender = LARGE_CARD_A; } void mpu4_state::init_m4default_big_low() { init_m4default_big(); m_default_to_low_bank = true; } void mpu4_state::init_m4default_alt() { m_reel_mux = STANDARD_REEL; m_reels = 8; setup_rom_banks(); m_bwb_bank=0; } void mpu4_state::init_m4default() { use_m4_standard_reels(); m_bwb_bank = 0; setup_rom_banks(); } void mpu4_state::init_m4default_big() { use_m4_standard_reels(); int size = memregion("maincpu")->bytes(); if (size <= 0x10000) { fatalerror("Error: Extended banking selected on set <=0x10000 in size\n"); } address_space &space = m_maincpu->space(AS_PROGRAM); m_bwb_bank = 1; space.install_write_handler(0x0858, 0x0858, write8smo_delegate(*this, FUNC(mpu4_state::bankswitch_w))); space.install_write_handler(0x0878, 0x0878, write8smo_delegate(*this, FUNC(mpu4_state::bankset_w))); uint8_t *rom = memregion("maincpu")->base(); m_numbanks = size / 0x10000; m_bank1->configure_entries(0, m_numbanks, &rom[0x01000], 0x10000); m_numbanks--; // some Bwb games must default to the last bank, does anything not like this // behavior? // some Bwb games don't work anyway tho, they seem to dislike something else // about the way the regular banking behaves, not related to the CB2 stuff m_bank1->set_entry(m_numbanks); } // these are not 'init' functions in their own right, they can be called from init functions void mpu4_state::use_m4_standard_reels() { m_reel_mux = STANDARD_REEL; m_reels = 4; } void mpu4_state::use_m4_five_reel_std() { m_reel_mux = FIVE_REEL_5TO8; m_reels = 5; } void mpu4_state::use_m4_five_reel_rev() { m_reel_mux = FIVE_REEL_8TO5; m_reels = 5; } void mpu4_state::use_m4_five_reel_alt() { m_reel_mux = FIVE_REEL_3TO6; m_reels = 5; } void mpu4_state::use_m4_six_reel_std() { m_reel_mux = SIX_REEL_1TO8; m_reels = 6; } void mpu4_state::use_m4_six_reel_alt() { m_reel_mux = SIX_REEL_5TO8; m_reels = 6; } void mpu4_state::use_m4_seven_reel() { m_reel_mux = SEVEN_REEL; m_reels = 7; } void mpu4_state::use_m4_low_volt_alt() { //Some games can't use the 50Hz circuit to check voltage issues, handle it here m_low_volt_detect_disable = 1; } void mpu4_state::use_m4_small_extender() { m_lamp_extender = SMALL_CARD; } void mpu4_state::use_m4_large_extender_b() { m_lamp_extender = LARGE_CARD_B; } void mpu4_state::use_m4_large_extender_c() { m_lamp_extender = LARGE_CARD_C; } void mpu4_state::use_m4_hopper_tubes() { m_hopper = TUBES; } void mpu4_state::use_m4_hopper_duart_a() { m_hopper = HOPPER_DUART_A; } void mpu4_state::use_m4_hopper_duart_b() { m_hopper = HOPPER_DUART_B; } void mpu4_state::use_m4_hopper_duart_c() { m_hopper = HOPPER_DUART_C; } void mpu4_state::use_m4_hopper_nonduart_a() { m_hopper = HOPPER_NONDUART_A; } void mpu4_state::use_m4_hopper_nonduart_b() { m_hopper = HOPPER_NONDUART_B; } void mpu4_state::use_m4_led_a() { m_led_extender = CARD_A; } void mpu4_state::use_m4_led_b() { m_led_extender = CARD_B; } void mpu4_state::use_m4_led_c() { m_led_extender = CARD_C; } void mpu4_state::use_m4_led_simple() { m_led_extender = SIMPLE_CARD; } void mpu4_state::setup_rom_banks() { //Initialise paging for non-extended ROM space uint8_t *rom = memregion("maincpu")->base(); membank("bank1")->configure_entries(0, 4, &rom[0x01000], 0x10000); membank("bank1")->set_entry(0); } /* generate a 50 Hz signal (based on an RC time) */ TIMER_DEVICE_CALLBACK_MEMBER(mpu4_state::gen_50hz) { if (!m_low_volt_detect_disable) { /* Although reported as a '50Hz' signal, the fact that both rising and falling edges of the pulse are used means the timer actually gives a 100Hz oscillating signal.*/ m_signal_50hz = m_signal_50hz?0:1; m_pia4->ca1_w(m_signal_50hz); /* signal is connected to IC4 CA1 */ } update_meters();//run at 100Hz to sync with PIAs } void mpu4_state::mpu4_memmap(address_map &map) { map(0x0000, 0x07ff).ram().share("nvram"); // map(0x0800, 0x081f) // optional protection device lives here, see other maps map(0x0850, 0x0850).rw(FUNC(mpu4_state::bankswitch_r), FUNC(mpu4_state::bankswitch_w)); /* write bank (rom page select) */ map(0x08e0, 0x08ef).rw(m_duart68681, FUNC(mc68681_device::read), FUNC(mc68681_device::write)); //Runs hoppers map(0x08ed, 0x08ed).r(FUNC(mpu4_state::hack_duart_r)); // hack until the hopper is hooked up to the duart in games wanting that setup (eg m4ready) map(0x0900, 0x0907).rw(m_6840ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write));/* PTM6840 IC2 */ map(0x0a00, 0x0a03).rw(m_pia3, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); /* PIA6821 IC3 */ map(0x0b00, 0x0b03).rw(m_pia4, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); /* PIA6821 IC4 */ map(0x0c00, 0x0c03).rw(m_pia5, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); /* PIA6821 IC5 */ map(0x0d00, 0x0d03).rw(m_pia6, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); /* PIA6821 IC6 */ map(0x0e00, 0x0e03).rw(m_pia7, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); /* PIA6821 IC7 */ map(0x0f00, 0x0f03).rw(m_pia8, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); /* PIA6821 IC8 */ map(0x1000, 0xffff).bankr("bank1"); /* 64k paged ROM (4 pages) */ } void mpu4_state::mpu4_memmap_characteriser(address_map &map) { mpu4_memmap(map); map(0x0800, 0x0810).rw(m_characteriser, FUNC(mpu4_characteriser_pal::read), FUNC(mpu4_characteriser_pal::write)); } void mpu4_state::mpu4_memmap_bootleg_characteriser(address_map &map) { mpu4_memmap(map); // a few sets use 0x840 for protection, 0x850 is where banking maps, so map up to that point map(0x0800, 0x084f).rw(m_characteriser_bl, FUNC(mpu4_characteriser_bl::read), FUNC(mpu4_characteriser_bl::write)); } void mpu4_state::mpu4_memmap_bl_characteriser_blastbank(address_map &map) { mpu4_memmap(map); map(0x0800, 0x081f).rw(m_characteriser_blastbank, FUNC(mpu4_characteriser_bl_blastbank::read), FUNC(mpu4_characteriser_bl_blastbank::write)); } void mpu4_state::mpu4_common(machine_config &config) { TIMER(config, "50hz").configure_periodic(FUNC(mpu4_state::gen_50hz), attotime::from_hz(100)); MSC1937(config, m_vfd); /* 6840 PTM */ PTM6840(config, m_6840ptm, MPU4_MASTER_CLOCK / 4); m_6840ptm->set_external_clocks(0, 0, 0); m_6840ptm->o1_callback().set(FUNC(mpu4_state::ic2_o1_callback)); m_6840ptm->o2_callback().set(FUNC(mpu4_state::ic2_o2_callback)); m_6840ptm->o3_callback().set(FUNC(mpu4_state::ic2_o3_callback)); m_6840ptm->irq_callback().set(FUNC(mpu4_state::cpu0_irq)); PIA6821(config, m_pia3, 0); m_pia3->writepa_handler().set(FUNC(mpu4_state::pia_ic3_porta_w)); m_pia3->writepb_handler().set(FUNC(mpu4_state::pia_ic3_portb_w)); m_pia3->ca2_handler().set(FUNC(mpu4_state::pia_ic3_ca2_w)); m_pia3->cb2_handler().set(FUNC(mpu4_state::pia_ic3_cb2_w)); m_pia3->irqa_handler().set(FUNC(mpu4_state::cpu0_irq)); m_pia3->irqb_handler().set(FUNC(mpu4_state::cpu0_irq)); PIA6821(config, m_pia4, 0); m_pia4->readpb_handler().set(FUNC(mpu4_state::pia_ic4_portb_r)); m_pia4->writepa_handler().set(FUNC(mpu4_state::pia_ic4_porta_w)); m_pia4->writepb_handler().set(FUNC(mpu4_state::pia_ic4_portb_w)); m_pia4->ca2_handler().set(FUNC(mpu4_state::pia_ic4_ca2_w)); m_pia4->cb2_handler().set(FUNC(mpu4_state::pia_ic4_cb2_w)); m_pia4->irqa_handler().set(FUNC(mpu4_state::cpu0_irq)); m_pia4->irqb_handler().set(FUNC(mpu4_state::cpu0_irq)); PIA6821(config, m_pia5, 0); m_pia5->readpa_handler().set(FUNC(mpu4_state::pia_ic5_porta_r)); m_pia5->readpb_handler().set(FUNC(mpu4_state::pia_ic5_portb_r)); m_pia5->writepa_handler().set(FUNC(mpu4_state::pia_ic5_porta_w)); m_pia5->writepb_handler().set(FUNC(mpu4_state::pia_ic5_portb_w)); m_pia5->ca2_handler().set(FUNC(mpu4_state::pia_ic5_ca2_w)); m_pia5->cb2_handler().set(FUNC(mpu4_state::pia_ic5_cb2_w)); m_pia5->irqa_handler().set(FUNC(mpu4_state::cpu0_irq)); m_pia5->irqb_handler().set(FUNC(mpu4_state::cpu0_irq)); PIA6821(config, m_pia6, 0); m_pia6->writepa_handler().set(FUNC(mpu4_state::pia_ic6_porta_w)); m_pia6->writepb_handler().set(FUNC(mpu4_state::pia_ic6_portb_w)); m_pia6->ca2_handler().set(FUNC(mpu4_state::pia_ic6_ca2_w)); m_pia6->cb2_handler().set(FUNC(mpu4_state::pia_ic6_cb2_w)); m_pia6->irqa_handler().set(FUNC(mpu4_state::cpu0_irq)); m_pia6->irqb_handler().set(FUNC(mpu4_state::cpu0_irq)); PIA6821(config, m_pia7, 0); m_pia7->readpb_handler().set(FUNC(mpu4_state::pia_ic7_portb_r)); m_pia7->writepa_handler().set(FUNC(mpu4_state::pia_ic7_porta_w)); m_pia7->writepb_handler().set(FUNC(mpu4_state::pia_ic7_portb_w)); m_pia7->ca2_handler().set(FUNC(mpu4_state::pia_ic7_ca2_w)); m_pia7->cb2_handler().set(FUNC(mpu4_state::pia_ic7_cb2_w)); m_pia7->irqa_handler().set(FUNC(mpu4_state::cpu0_irq)); m_pia7->irqb_handler().set(FUNC(mpu4_state::cpu0_irq)); PIA6821(config, m_pia8, 0); m_pia8->readpa_handler().set(FUNC(mpu4_state::pia_ic8_porta_r)); m_pia8->writepb_handler().set(FUNC(mpu4_state::pia_ic8_portb_w)); m_pia8->ca2_handler().set(FUNC(mpu4_state::pia_ic8_ca2_w)); m_pia8->cb2_handler().set(FUNC(mpu4_state::pia_ic8_cb2_w)); m_pia8->irqa_handler().set(FUNC(mpu4_state::cpu0_irq)); m_pia8->irqb_handler().set(FUNC(mpu4_state::cpu0_irq)); METERS(config, m_meters, 0).set_number(8); BACTA_DATALOGGER(config, m_dataport, 0); m_dataport->rxd_handler().set(FUNC(mpu4_state::dataport_rxd)); } void mpu4_state::mpu4_common2(machine_config &config) { PTM6840(config, m_ptm_ic3ss, MPU4_MASTER_CLOCK / 4); m_ptm_ic3ss->set_external_clocks(0, 0, 0); m_ptm_ic3ss->o1_callback().set("ptm_ic3ss", FUNC(ptm6840_device::set_c2)); m_ptm_ic3ss->o2_callback().set("ptm_ic3ss", FUNC(ptm6840_device::set_c1)); m_ptm_ic3ss->o3_callback().set("ptm_ic3ss", FUNC(ptm6840_device::set_g1)); PIA6821(config, m_pia_ic4ss, 0); m_pia_ic4ss->readpb_handler().set(FUNC(mpu4_state::pia_gb_portb_r)); m_pia_ic4ss->writepa_handler().set(FUNC(mpu4_state::pia_gb_porta_w)); m_pia_ic4ss->writepb_handler().set(FUNC(mpu4_state::pia_gb_portb_w)); m_pia_ic4ss->ca2_handler().set(FUNC(mpu4_state::pia_gb_ca2_w)); m_pia_ic4ss->cb2_handler().set(FUNC(mpu4_state::pia_gb_cb2_w)); } /*********************************************************************************************** Base config with no sound ***********************************************************************************************/ void mpu4_state::mpu4base(machine_config &config) { MCFG_MACHINE_START_OVERRIDE(mpu4_state,mod2) MCFG_MACHINE_RESET_OVERRIDE(mpu4_state,mpu4) MC6809(config, m_maincpu, MPU4_MASTER_CLOCK); // MC68B09P m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap); mpu4_common(config); SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); MC68681(config, m_duart68681, MPU4_MASTER_CLOCK); // ? config.set_default_layout(layout_mpu4); } /*********************************************************************************************** Configs for Mod2 TODO: mod2 should eventually become a subclass ***********************************************************************************************/ void mpu4_state::mod2(machine_config &config) { mpu4base(config); AY8913(config, m_ay8913, MPU4_MASTER_CLOCK/4); m_ay8913->set_flags(AY8910_SINGLE_OUTPUT); m_ay8913->set_resistors_load(820, 0, 0); m_ay8913->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_ay8913->add_route(ALL_OUTPUTS, "rspeaker", 1.0); mpu4_reels<0, 6>(config); } void mpu4_state::mod2_7reel(machine_config &config) { mpu4base(config); AY8913(config, m_ay8913, MPU4_MASTER_CLOCK/4); m_ay8913->set_flags(AY8910_SINGLE_OUTPUT); m_ay8913->set_resistors_load(820, 0, 0); m_ay8913->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_ay8913->add_route(ALL_OUTPUTS, "rspeaker", 1.0); mpu4_reels<0, 7>(config); } void mpu4_state::mod2_cheatchr_table(machine_config &config, const uint8_t* table) { mod2(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); m_characteriser->set_cpu_tag("maincpu"); m_characteriser->set_allow_6809_cheat(true); m_characteriser->set_lamp_table(table); } void mpu4_state::mod2_chr(machine_config &config) { mod2(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); } void mpu4_state::mod2_cheatchr(machine_config &config) { mod2_cheatchr_table(config, nullptr); } void mpu4_state::mod2_chr_blastbnk(machine_config &config) { mod2(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_bl_characteriser_blastbank); MPU4_CHARACTERISER_BL_BLASTBANK(config, m_characteriser_blastbank, 0); } void mpu4_state::mod2_chr_copcash(machine_config &config) { mod2(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_bl_characteriser_blastbank); MPU4_CHARACTERISER_BL_BLASTBANK(config, m_characteriser_blastbank, 0); m_characteriser_blastbank->set_retxor(0x03); } // alt reel setup void mpu4_state::mod2_alt(machine_config &config) { mpu4base(config); AY8913(config, m_ay8913, MPU4_MASTER_CLOCK/4); m_ay8913->set_flags(AY8910_SINGLE_OUTPUT); m_ay8913->set_resistors_load(820, 0, 0); m_ay8913->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_ay8913->add_route(ALL_OUTPUTS, "rspeaker", 1.0); mpu4_reels<1, 6>(config); } void mpu4_state::mod2_alt_cheatchr_table(machine_config &config, const uint8_t* table) { mod2_alt(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); m_characteriser->set_cpu_tag("maincpu"); m_characteriser->set_allow_6809_cheat(true); m_characteriser->set_lamp_table(table); } void mpu4_state::mod2_alt_cheatchr(machine_config &config) { mod2_alt_cheatchr_table(config, nullptr); } /*********************************************************************************************** Configs for Mod4 with YM TODO: mod4yam should eventually become a subclass ***********************************************************************************************/ void mpu4_state::mod4yam(machine_config &config) { mpu4base(config); MCFG_MACHINE_START_OVERRIDE(mpu4_state,mpu4yam) mpu4_reels<0, 6>(config); YM2413(config, m_ym2413, MPU4_MASTER_CLOCK/4); m_ym2413->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_ym2413->add_route(ALL_OUTPUTS, "rspeaker", 1.0); } void mpu4_state::mod4yam_chr(machine_config &config) { mod4yam(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); } void mpu4_state::mod4yam_cheatchr_table(machine_config& config, const uint8_t* table) { mod4yam(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); m_characteriser->set_cpu_tag("maincpu"); m_characteriser->set_allow_6809_cheat(true); m_characteriser->set_lamp_table(table); } void mpu4_state::mod4yam_cheatchr(machine_config &config) { mod4yam_cheatchr_table(config, nullptr); } void mpu4_state::mod4yam_alt(machine_config &config) { mpu4base(config); MCFG_MACHINE_START_OVERRIDE(mpu4_state,mpu4yam) mpu4_reels<1, 6>(config); YM2413(config, m_ym2413, MPU4_MASTER_CLOCK/4); m_ym2413->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_ym2413->add_route(ALL_OUTPUTS, "rspeaker", 1.0); } /*********************************************************************************************** Configs for Mod4 with OKI TODO: mod4oki should eventually become a subclass ***********************************************************************************************/ // standard reel setup void mpu4_state::mod4oki(machine_config &config) { mpu4base(config); MCFG_MACHINE_START_OVERRIDE(mpu4_state,mpu4oki) mpu4_common2(config); mpu4_reels<0, 6>(config); OKIM6376(config, m_msm6376, 128000); //Adjusted by IC3, default to 16KHz sample. Can also be 85430 at 10.5KHz and 64000 at 8KHz m_msm6376->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_msm6376->add_route(ALL_OUTPUTS, "rspeaker", 1.0); } void mpu4_state::mod4oki_7reel(machine_config &config) { mpu4base(config); MCFG_MACHINE_START_OVERRIDE(mpu4_state,mpu4oki) mpu4_common2(config); mpu4_reels<0, 7>(config); OKIM6376(config, m_msm6376, 128000); //Adjusted by IC3, default to 16KHz sample. Can also be 85430 at 10.5KHz and 64000 at 8KHz m_msm6376->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_msm6376->add_route(ALL_OUTPUTS, "rspeaker", 1.0); } void mpu4_state::mod4oki_chr(machine_config &config) { mod4oki(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); } void mpu4_state::mod4oki_cheatchr_table(machine_config &config, const uint8_t* table) { mod4oki(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); m_characteriser->set_cpu_tag("maincpu"); m_characteriser->set_allow_6809_cheat(true); m_characteriser->set_lamp_table(table); } void mpu4_state::mod4oki_cheatchr(machine_config &config) { mod4oki_cheatchr_table(config, nullptr); } // alt reel setup void mpu4_state::mod4oki_alt(machine_config &config) { mpu4base(config); MCFG_MACHINE_START_OVERRIDE(mpu4_state,mpu4oki) mpu4_common2(config); mpu4_reels<1, 6>(config); OKIM6376(config, m_msm6376, 128000); //Adjusted by IC3, default to 16KHz sample. Can also be 85430 at 10.5KHz and 64000 at 8KHz m_msm6376->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_msm6376->add_route(ALL_OUTPUTS, "rspeaker", 1.0); } void mpu4_state::mod4oki_alt_cheatchr_table(machine_config& config, const uint8_t* table) { mod4oki_alt(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); m_characteriser->set_cpu_tag("maincpu"); m_characteriser->set_allow_6809_cheat(true); m_characteriser->set_lamp_table(table); } void mpu4_state::mod4oki_alt_cheatchr(machine_config &config) { mod4oki_alt_cheatchr_table(config, nullptr); } // 5 reel setup void mpu4_state::mod4oki_5r(machine_config &config) { mpu4base(config); MCFG_MACHINE_START_OVERRIDE(mpu4_state,mpu4oki) mpu4_common2(config); mpu4_reels<0, 5>(config); OKIM6376(config, m_msm6376, 128000); //Adjusted by IC3, default to 16KHz sample. Can also be 85430 at 10.5KHz and 64000 at 8KHz m_msm6376->add_route(ALL_OUTPUTS, "lspeaker", 1.0); m_msm6376->add_route(ALL_OUTPUTS, "rspeaker", 1.0); } void mpu4_state::mod4oki_5r_chr(machine_config &config) { mod4oki_5r(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); } void mpu4_state::mod4oki_5r_cheatchr_table(machine_config &config, const uint8_t* table) { mod4oki_5r(config); m_maincpu->set_addrmap(AS_PROGRAM, &mpu4_state::mpu4_memmap_characteriser); MPU4_CHARACTERISER_PAL(config, m_characteriser, 0); m_characteriser->set_cpu_tag("maincpu"); m_characteriser->set_allow_6809_cheat(true); m_characteriser->set_lamp_table(table); } void mpu4_state::mod4oki_5r_cheatchr(machine_config &config) { mod4oki_5r_cheatchr_table(config, nullptr); } /*********************************************************************************************** Inits ***********************************************************************************************/ // TODO: move this to mpu4_characteriser_bootleg.cpp, it's for a single game that requires // a different 'fixed' value depending on the address uint8_t mpu4_state::bootleg806_r(address_space &space, offs_t offset) { return 0x6a; } void mpu4_state::init_m4default_806prot() { init_m4default(); m_maincpu->space(AS_PROGRAM).install_read_handler(0x0806, 0x0806, read8m_delegate(*this, FUNC(mpu4_state::bootleg806_r))); }