diff --git a/.gitattributes b/.gitattributes index ead0eb2160f..c0f14d7f81e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2145,6 +2145,7 @@ src/mame/drivers/moo.c svneol=native#text/plain src/mame/drivers/mosaic.c svneol=native#text/plain src/mame/drivers/mouser.c svneol=native#text/plain src/mame/drivers/mpoker.c svneol=native#text/plain +src/mame/drivers/mpu3.c svneol=native#text/plain src/mame/drivers/mpu4.c svneol=native#text/plain src/mame/drivers/mpu4drvr.c svneol=native#text/plain src/mame/drivers/mpu5.c svneol=native#text/plain diff --git a/src/mame/drivers/bfm_sc1.c b/src/mame/drivers/bfm_sc1.c index 870c953d39a..726b3545fdc 100644 --- a/src/mame/drivers/bfm_sc1.c +++ b/src/mame/drivers/bfm_sc1.c @@ -207,7 +207,7 @@ static WRITE8_HANDLER( reel12_w ) { bfm_sc1_state *state = space->machine().driver_data(); if ( state->m_locked & 0x01 ) - { // hardware is still state->m_locked, + { // hardware is still locked, if ( data == 0x46 ) state->m_locked &= ~0x01; } else @@ -230,7 +230,7 @@ static WRITE8_HANDLER( reel34_w ) { bfm_sc1_state *state = space->machine().driver_data(); if ( state->m_locked & 0x02 ) - { // hardware is still state->m_locked, + { // hardware is still locked, if ( data == 0x42 ) state->m_locked &= ~0x02; } else @@ -272,7 +272,7 @@ static WRITE8_HANDLER( mmtr_w ) bfm_sc1_state *state = space->machine().driver_data(); int i; if ( state->m_locked & 0x04 ) - { // hardware is still state->m_locked, + { // hardware is still locked, state->m_locked &= ~0x04; } else @@ -745,7 +745,7 @@ static MACHINE_RESET( bfm_sc1 ) } state->m_acia_status = 0x02; // MC6850 transmit buffer empty !!! - state->m_locked = 0x07; // hardware is state->m_locked + state->m_locked = 0x07; // hardware is locked // init rom bank //////////////////////////////////////////////////////////////////// { @@ -797,7 +797,7 @@ static ADDRESS_MAP_START( memmap, AS_PROGRAM, 8 ) AM_RANGE(0x4000, 0x5FFF) AM_ROM // 8k ROM AM_RANGE(0x6000, 0x7FFF) AM_ROMBANK("bank1") // 8k paged ROM (4 pages) - AM_RANGE(0x8000, 0xFFFF) AM_RAM_WRITE(watchdog_w) // 32k ROM + AM_RANGE(0x8000, 0xFFFF) AM_ROM AM_WRITE (watchdog_w)//AM_RAM_WRITE(watchdog_w) // 32k ROM ADDRESS_MAP_END diff --git a/src/mame/drivers/mpu3.c b/src/mame/drivers/mpu3.c new file mode 100644 index 00000000000..9411b0447c8 --- /dev/null +++ b/src/mame/drivers/mpu3.c @@ -0,0 +1,938 @@ +/*********************************************************************************************************** + Barcrest MPU3 highly preliminary driver by J.Wallace, and Anonymous. + +--- Board Setup --- + +This original board uses a ~1.Mhz 6808 CPU, and a number of PIA6821 chips for multiplexing inputs and the like. + +A 6840PTM is used for internal timing +A GAME CARD (cartridge) plugs into the board containing the game, and a protection PAL (the 'characteriser'). + +--- Preliminary MPU3 Memorymap --- + + 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 +-----------+---+-----------------+-------------------------------------------------------------------------- + + 8800-881F |R/W| ???????????????? | MC6840 PTM IC2 (unusual bus setup, address shifted two bytes) + +Outputs hooked into IC 19 + + Clock1 <-------------------------------------- + | | + V | + Output1 ---> Clock2 | + | + Output2 --+-> Clock3 | + | | + | Output3 ---> 'to audio amp' ?? + | + +--------> CA1 IC3 ( + +IRQ line connected to CPU + +-----------+---+-----------------+-------------------------------------------------------------------------- +9000- |R/W| D D D D D D D D | PIA6821 IC3 + | | | PA2-PA7 INPUT multiplexed inputs data + | | | PA1, CB1 connected to IC2 C1 pin + | | | CA1 INPUT, not connected + | | | CA2 OUTPUT, A on strobe multiplexer + | | | IRQA Not connected + | | | + | | | CB2 IC19 Triac switch + | | | Port B triacs + +9800 |R/W| D D D D D D D D | PIA6821 IC4 + | | | PA0-PA6 INPUT Yellow 15 way data (7SEG LED or Meters) + | | | PA7 802 (Q) IC11 G1 + | | | PB0-PB7 INPUT IC24 + | | | CA2 OUTPUT, B on strobe multiplexer + | | | CB2 TRiac switch + +A000-A003 |R/W| D D D D D D D D | PIA6821 IC5 port A Reel drives + | | | port B Reel opto + | | | + | | | CA2 OUTPUT, C on strobe multiplexer + | | | CB2 TRiac switch +-----------+---+-----------------+-------------------------------------------------------------------------- +A800-A803 |R/W| D D D D D D D D | PIA6821 IC6 PA0-PA7, AUX1 connector (ALPHA) + | | | PB0-PB7, AUX2 connector + | | | + | | | + +-----------+---+-----------------+-------------------------------------------------------------------------- +??? B000-FFFF | R | D D D D D D D D | ROM +-----------+---+-----------------+-------------------------------------------------------------------------- + +TODO: - Distinguish door switches using manual + - Add discrete sound functionality (same as MPU4 alarm) + - Is pulse timer ic11 right? + - 12V meter alarm on hyper viper - how are meters sensed? + +***********************************************************************************************************/ +#include "emu.h" +#include "machine/6821pia.h" +#include "machine/6840ptm.h" +#include "machine/nvram.h" + +#include "cpu/m6800/m6800.h" +#include "machine/steppers.h" +#include "machine/roc10937.h" +#include "machine/meters.h" + +#ifdef MAME_DEBUG +#define MPU3VERBOSE 1 +#else +#define MPU3VERBOSE 0 +#endif + +#define LOG(x) do { if (MPU3VERBOSE) logerror x; } while (0) + +#include "video/awpvid.h" //Fruit Machines Only + +#define MPU3_MASTER_CLOCK (XTAL_4MHz) + +/* Lookup table for CHR data */ + +struct mpu3_chr_table +{ + UINT8 call; + UINT8 response; +}; + +class mpu3_state : public driver_device +{ +public: + mpu3_state(running_machine &machine, const driver_device_config_base &config) + : driver_device(machine, config) { } + + +int m_alpha_data_line; +int m_alpha_clock; +int m_triac_ic3; +int m_triac_ic4; +int m_triac_ic5; +int m_ic3_data; +int m_IC11G1; +int m_IC11G2A; +int m_IC11G2B; +int m_IC11GC; +int m_IC11GB; +int m_IC11GA; + +int m_ic10_output; +int m_ic11_active; +int m_ic11_output; +int m_disp_func; + +int m_ic4_input_a; +int m_aux1_input; +int m_aux2_input; +int m_input_strobe; /* IC11 74LS138 A = CA2 IC3, B = CA2 IC4, C = CA2 IC5 */ +UINT8 m_lamp_strobe; +UINT8 m_led_strobe; +int m_signal_50hz; + +const mpu3_chr_table* m_current_chr_table; +int m_prot_col; + +int m_optic_pattern; + +emu_timer *m_ic21_timer; +}; + +#define DISPLAY_PORT 0 +#define METER_PORT 1 +#define BWB_FUNCTIONALITY 2 +static TIMER_CALLBACK( ic21_timeout ); + +static void update_triacs(running_machine &machine) +{ + mpu3_state *state = machine.driver_data(); + int i,triacdata; + + triacdata=state->m_triac_ic3 + (state->m_triac_ic4 << 8) + (state->m_triac_ic5 << 9); + + for (i = 0; i < 8; i++) + { + output_set_indexed_value("triac", i, triacdata & (1 << i)); + } +} + +/* called if board is reset */ +static void mpu3_stepper_reset(running_machine &machine) +{ + mpu3_state *state = machine.driver_data(); + int pattern = 0,reel; + for (reel = 0; reel < 6; reel++) + { + stepper_reset_position(reel); + if (stepper_optic_state(reel)) pattern |= 1<m_optic_pattern = pattern; +} + +static MACHINE_RESET( mpu3 ) +{ + mpu3_state *state = machine.driver_data(); + ROC10937_reset(0); /* reset display1 */ + + mpu3_stepper_reset(machine); + + state->m_lamp_strobe = 0; + state->m_led_strobe = 0; + + state->m_IC11GC = 0; + state->m_IC11GB = 0; + state->m_IC11GA = 0; + state->m_IC11G1 = 1; + state->m_IC11G2A = 0; + state->m_IC11G2B = 0; +} + +/* 6808 IRQ handler */ +static WRITE_LINE_DEVICE_HANDLER( cpu0_irq ) +{ + device_t *pia3 = device->machine().device("pia_ic3"); + device_t *pia4 = device->machine().device("pia_ic4"); + device_t *pia5 = device->machine().device("pia_ic5"); + device_t *pia6 = device->machine().device("pia_ic6"); + device_t *ptm2 = device->machine().device("ptm_ic2"); + + /* The PIA and PTM IRQ lines are all connected to a common PCB track, leading directly to the 6809 IRQ line. */ + int combined_state = pia6821_get_irq_a(pia3) | pia6821_get_irq_b(pia3) | + pia6821_get_irq_a(pia4) | pia6821_get_irq_b(pia4) | + pia6821_get_irq_a(pia5) | pia6821_get_irq_b(pia5) | + pia6821_get_irq_a(pia6) | pia6821_get_irq_b(pia6) | + ptm6840_get_irq(ptm2); + + cputag_set_input_line(device->machine(), "maincpu", M6800_IRQ_LINE, combined_state ? ASSERT_LINE : CLEAR_LINE); + LOG(("6808 int%d \n", combined_state)); +} + + +/* IC2 6840 PTM handler probably clocked from elsewhere*/ +static WRITE8_DEVICE_HANDLER( ic2_o1_callback ) +{ +} + +//FIXME FROM HERE +static WRITE8_DEVICE_HANDLER( ic2_o2_callback ) +{ +} + + +static WRITE8_DEVICE_HANDLER( ic2_o3_callback ) +{ +} + + +static const ptm6840_interface ptm_ic2_intf = +{ + MPU3_MASTER_CLOCK,///4, + { 0, 0, 0 }, + { DEVCB_HANDLER(ic2_o1_callback), + DEVCB_HANDLER(ic2_o2_callback), + DEVCB_HANDLER(ic2_o3_callback) }, + DEVCB_LINE(cpu0_irq) +}; + +/* +IC23 emulation + +IC23 is a 74LS138 1-of-8 Decoder + +It is used as a multiplexer for the LEDs, lamp selects and inputs.*/ + +static void ic11_update(mpu3_state *state) +{ + if (!state->m_IC11G2A) + { + if (!state->m_IC11G2B) + { + if (state->m_IC11G1) + { + if ( state->m_IC11GA ) state->m_input_strobe |= 0x01; + else state->m_input_strobe &= ~0x01; + + if ( state->m_IC11GB ) state->m_input_strobe |= 0x02; + else state->m_input_strobe &= ~0x02; + + if ( state->m_IC11GC ) state->m_input_strobe |= 0x04; + else state->m_input_strobe &= ~0x04; + } + } + } + else + if ((state->m_IC11G2A)||(state->m_IC11G2B)||(!state->m_IC11G1)) + { + state->m_input_strobe = 0x00; + } +} + + +/* +IC21 emulation + +IC21 is an 8602 or equivalent pulse generator + +CLEAR and B2 are tied high, so a high to low transition on A2 +(tied to IC11 GA) will trigger operation. + +Cx = 2.2 uF + +Rx = 47k + +K = ~0.34 + +t/ns = .34 * 47 * 2.2e6 [ 1+ (1/47)] + + +This seems less stable than the revised version used in MPU4 +*/ +static void ic21_output(mpu3_state *state,int data) +{ + state->m_IC11G1 = data; + ic11_update(state); +} + +static void ic21_setup(mpu3_state *state) +{ + if (state->m_IC11GA) + { + { + state->m_ic11_active=1; + ic21_output(state,1); + state->m_ic21_timer->adjust(attotime::from_nsec( (0.34 * 47 * 2200000) *(1+(1/47)))); + } + } +} + +static TIMER_CALLBACK( ic21_timeout ) +{ + mpu3_state *state = machine.driver_data(); + state->m_ic11_active=0; + ic21_output(state,0); +} + +static READ8_DEVICE_HANDLER( pia_ic3_porta_r ) +{ + mpu3_state *state = device->machine().driver_data(); + static const char *const portnames[] = { "ORANGE1", "ORANGE2", "BLACK1", "BLACK2", "DIL1", "DIL1", "DIL2", "DIL2" }; + int data=0,swizzle; + LOG(("%s: IC3 PIA Read of Port A (MUX input data)\n", device->machine().describe_context())); + popmessage("%x",state->m_input_strobe); + switch (state->m_input_strobe) + { + case 0: + case 1: + case 2: + case 3: + { + data = (input_port_read(device->machine(), portnames[state->m_input_strobe])<<2); + break; + } + case 4://DIL1 + case 6://DIL2 + { + swizzle = (input_port_read(device->machine(), portnames[state->m_input_strobe])); + data = (((swizzle & 0x01) << 7) + ((swizzle & 0x02) << 5) + ((swizzle & 0x04) << 3) + + ((swizzle & 0x08) << 1) +((swizzle & 0x10) >> 1) + ((swizzle & 0x20) >> 3)); + break; + } + case 5://DIL1 + case 7://DIL2 + { + swizzle = (input_port_read(device->machine(), portnames[state->m_input_strobe])); + data = (((swizzle & 0x80) >> 1) + ((swizzle & 0x40) << 1)); + break; + } + } + if (state->m_signal_50hz) + { + data |= 0x02; + } + else + { + data &= ~0x02; + } + return data; +} + +static WRITE8_DEVICE_HANDLER( pia_ic3_portb_w ) +{ + mpu3_state *state = device->machine().driver_data(); + LOG(("%s: IC3 PIA Port B Set to %2x (Triac)\n", device->machine().describe_context(),data)); + state->m_triac_ic3 =data; +} + + +static WRITE_LINE_DEVICE_HANDLER( pia_ic3_ca2_w ) +{ + mpu3_state *mstate = device->machine().driver_data(); + LOG(("%s: IC3 PIA Port CA2 Set to %2x (input A)\n", device->machine().describe_context(),state)); + mstate->m_IC11GA = state; + ic21_setup(mstate); + ic11_update(mstate); +} + +static const pia6821_interface pia_ic3_intf = +{ + DEVCB_HANDLER(pia_ic3_porta_r), /* port A in */ + DEVCB_NULL, /* port B in */ + DEVCB_NULL, /* line CA1 in */ + DEVCB_NULL, /* line CB1 in */ + DEVCB_NULL, /* line CA2 in */ + DEVCB_NULL, /* line CB2 in */ + DEVCB_NULL, /* port A out */ + DEVCB_HANDLER(pia_ic3_portb_w), /* port B out */ + DEVCB_LINE(pia_ic3_ca2_w), /* line CA2 out */ + DEVCB_NULL, /* port CB2 out */ + DEVCB_NULL, /* IRQA */ + DEVCB_LINE(cpu0_irq) /* IRQB */ +}; + +static READ8_DEVICE_HANDLER( pia_ic4_porta_r ) +{ + mpu3_state *state = device->machine().driver_data(); + if (state->m_ic11_active) + { + state->m_ic4_input_a|=0x80; + } + else + { + state->m_ic4_input_a&=~0x80; + } + return state->m_ic4_input_a; +} + +/* IC4, 7 seg leds */ +static WRITE8_DEVICE_HANDLER( pia_ic4_porta_w ) +{ + mpu3_state *state = device->machine().driver_data(); + int meter,swizzle; + LOG(("%s: IC4 PIA Port A Set to %2x (DISPLAY PORT)\n", device->machine().describe_context(),data)); + state->m_ic4_input_a=data; + switch (state->m_disp_func) + { + case DISPLAY_PORT: + if(state->m_ic11_active) + { + if(state->m_led_strobe != state->m_input_strobe) + { + swizzle = ((state->m_ic4_input_a & 0x01) << 2)+(state->m_ic4_input_a & 0x02)+((state->m_ic4_input_a & 0x4) >> 2)+(state->m_ic4_input_a & 0x08)+((state->m_ic4_input_a & 0x10) << 2)+(state->m_ic4_input_a & 0x20)+((state->m_ic4_input_a & 0x40) >> 2); + output_set_digit_value(7 - state->m_input_strobe,swizzle); + } + state->m_led_strobe = state->m_input_strobe; + } + break; + + case METER_PORT: + for (meter = 0; meter < 6; meter ++) + { + swizzle = ((state->m_ic4_input_a ^ 0xff) & 0x3f); + MechMtr_update(meter, (swizzle & (1 << meter))); + } + break; + + case BWB_FUNCTIONALITY: + //Need to find a game to work this out, MFME has a specific option for it, but I see no activity there. + break; + + } +} + +static WRITE8_DEVICE_HANDLER( pia_ic4_portb_w ) +{ + mpu3_state *state = device->machine().driver_data(); + LOG(("%s: IC4 PIA Port B Set to %2x (Lamp)\n", device->machine().describe_context(),data)); + int i; + if(state->m_ic11_active) + { + if (state->m_lamp_strobe != state->m_input_strobe) + { + // Because of the nature of the lamping circuit, there is an element of persistance where the lamp retains residual charge + // As a consequence, the lamp column data can change before the input strobe (effectively writing 0 to the previous strobe) + // without causing the relevant lamps to black out. + + for (i = 0; i < 8; i++) + { + output_set_lamp_value((8*state->m_input_strobe)+i, ((data & (1 << i)) !=0)); + } + state->m_lamp_strobe = state->m_input_strobe; + } + } +} + +static WRITE_LINE_DEVICE_HANDLER( pia_ic4_ca2_w ) +{ + mpu3_state *mstate = device->machine().driver_data(); + LOG(("%s: IC4 PIA Port CA2 Set to %2x (Input B)\n", device->machine().describe_context(),state)); + mstate->m_IC11GB = state; + ic11_update(mstate); +} + +static WRITE_LINE_DEVICE_HANDLER( pia_ic4_cb2_w ) +{ + mpu3_state *mstate = device->machine().driver_data(); + LOG(("%s: IC4 PIA Port CA2 Set to %2x (Triac)\n", device->machine().describe_context(),state)); + mstate->m_triac_ic4=state; +} + +static const pia6821_interface pia_ic4_intf = +{ + DEVCB_HANDLER(pia_ic4_porta_r), /* port A in */ + DEVCB_NULL, /* port B in */ + DEVCB_NULL, /* line CA1 in */ + DEVCB_NULL, /* line CB1 in */ + DEVCB_NULL, /* line CA2 in */ + DEVCB_NULL, /* line CB2 in */ + DEVCB_HANDLER(pia_ic4_porta_w), /* port A out */ + DEVCB_HANDLER(pia_ic4_portb_w), /* port B out */ + DEVCB_LINE(pia_ic4_ca2_w), /* line CA2 out */ + DEVCB_LINE(pia_ic4_cb2_w), /* line CB2 out */ + DEVCB_LINE(cpu0_irq), /* IRQA */ + DEVCB_NULL /* IRQB */ +}; + +/* IC5, AUX ports, coin lockouts and AY sound chip select (MODs below 4 only) */ +static WRITE8_DEVICE_HANDLER( pia_ic5_porta_w ) +{ + mpu3_state *state = device->machine().driver_data(); + + LOG(("%s: IC5 PIA Port A Set to %2x (Reel)\n", device->machine().describe_context(),data)); + stepper_update(0, data & 0x03 ); + stepper_update(1, (data>>2) & 0x03 ); + stepper_update(2, (data>>4) & 0x03 ); + stepper_update(3, (data>>6) & 0x03 ); + awp_draw_reel(0); + awp_draw_reel(1); + awp_draw_reel(2); + awp_draw_reel(3); + + { + if ( stepper_optic_state(0) ) state->m_optic_pattern |= 0x01; + else state->m_optic_pattern &= ~0x01; + + if ( stepper_optic_state(1) ) state->m_optic_pattern |= 0x02; + else state->m_optic_pattern &= ~0x02; + if ( stepper_optic_state(2) ) state->m_optic_pattern |= 0x04; + else state->m_optic_pattern &= ~0x04; + + if ( stepper_optic_state(3) ) state->m_optic_pattern |= 0x08; + else state->m_optic_pattern &= ~0x08; + + } + +} + +static READ8_DEVICE_HANDLER( pia_ic5_portb_r ) +{ + mpu3_state *state = device->machine().driver_data(); + if (state->m_ic3_data & 0x80 ) + { + return state->m_optic_pattern; + } + else + { + return state->m_ic3_data; + } +} + + + +static WRITE8_DEVICE_HANDLER( pia_ic5_portb_w ) +{ + mpu3_state *state = device->machine().driver_data(); + state->m_ic3_data = data; +} + +static WRITE_LINE_DEVICE_HANDLER( pia_ic5_ca2_w ) +{ + mpu3_state *mstate = device->machine().driver_data(); + LOG(("%s: IC5 PIA Port CA2 Set to %2x (C)\n", device->machine().describe_context(),state)); + mstate->m_IC11GC = state; + ic11_update(mstate); +} + +static WRITE_LINE_DEVICE_HANDLER( pia_ic5_cb2_w ) +{ + mpu3_state *mstate = device->machine().driver_data(); + LOG(("%s: IC5 PIA Port CB2 Set to %2x (Triac)\n", device->machine().describe_context(),state)); + mstate->m_triac_ic5 = state; +} + +static const pia6821_interface pia_ic5_intf = +{ + DEVCB_NULL, /* port A in */ + DEVCB_HANDLER(pia_ic5_portb_r), /* port B in */ + DEVCB_NULL, /* line CA1 in */ + DEVCB_NULL, /* line CB1 in */ + DEVCB_NULL, /* line CA2 in */ + DEVCB_NULL, /* line CB2 in */ + DEVCB_HANDLER(pia_ic5_porta_w), /* port A out */ + DEVCB_HANDLER(pia_ic5_portb_w), /* port B out */ + DEVCB_LINE(pia_ic5_ca2_w), /* line CA2 out */ + DEVCB_LINE(pia_ic5_cb2_w), /* port CB2 out */ + DEVCB_NULL, /* IRQA */ + DEVCB_NULL /* IRQB */ +}; + + +/* IC6, AUX ports*/ +static READ8_DEVICE_HANDLER( pia_ic6_porta_r ) +{ + mpu3_state *state = device->machine().driver_data(); + return (input_port_read(device->machine(), "AUX1"))|state->m_aux1_input; +} + + +static READ8_DEVICE_HANDLER( pia_ic6_portb_r ) +{ + mpu3_state *state = device->machine().driver_data(); + return (input_port_read(device->machine(), "AUX2"))|state->m_aux2_input; +} + +static WRITE8_DEVICE_HANDLER( pia_ic6_porta_w ) +{ + mpu3_state *state = device->machine().driver_data(); + LOG(("%s: IC6 PIA Port A Set to %2x (Alpha)\n", device->machine().describe_context(),data)); + if ( data & 0x08 ) ROC10937_reset(0); + + state->m_alpha_data_line = ((data & 0x20) >> 5); + if ( !state->m_alpha_clock && (data & 0x10) ) + { + ROC10937_shift_data(0, state->m_alpha_data_line&0x01?0:1); + } + state->m_alpha_clock = (data & 0x10); + + ROC10937_draw_16seg(0); +} + +static WRITE8_DEVICE_HANDLER( pia_ic6_portb_w ) +{ + mpu3_state *state = device->machine().driver_data(); + LOG(("%s: IC6 PIA Port B Set to %2x (AUX2)\n", device->machine().describe_context(),data)); + state->m_aux2_input = data; +} + +static const pia6821_interface pia_ic6_intf = +{ + DEVCB_HANDLER(pia_ic6_porta_r), /* port A in */ + DEVCB_HANDLER(pia_ic6_portb_r), /* port B in */ + DEVCB_NULL, /* line CA1 in */ + DEVCB_NULL, /* line CB1 in */ + DEVCB_NULL, /* line CA2 in */ + DEVCB_NULL, /* line CB2 in */ + DEVCB_HANDLER(pia_ic6_porta_w), /* port A out */ + DEVCB_HANDLER(pia_ic6_portb_w), /* port B out */ + DEVCB_NULL, /* line CA2 out */ + DEVCB_NULL, /* port CB2 out */ + DEVCB_LINE(cpu0_irq), /* IRQA */ + DEVCB_LINE(cpu0_irq) /* IRQB */ +}; + +static INPUT_PORTS_START( mpu3 ) + PORT_START("ORANGE1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Cancel") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("01") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("02") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("03") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("04") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("05") + + + PORT_START("ORANGE2") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("08") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("09") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Exchange") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("11") + PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("12") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("13") + + 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(0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Auto Nudge") + 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 Door") PORT_CODE(KEYCODE_Q) PORT_TOGGLE + + PORT_START("BLACK2") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("20p") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("10p") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Token") + 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_START("DIL1") + PORT_DIPNAME( 0x80, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL108" ) PORT_DIPLOCATION("DIL1:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + + PORT_START("DIL2") + PORT_DIPNAME( 0x80, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, 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_SPECIAL) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_SPECIAL) + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_SPECIAL) + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_SPECIAL) + 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 + +static const stepper_interface mpu3_reel_interface = +{ + MPU3_48STEP_REEL, + 92, + 2, + 0x00 +}; + +/* Common configurations */ +static void mpu3_config_common(running_machine &machine) +{ + mpu3_state *state = machine.driver_data(); + state->m_ic21_timer = machine.scheduler().timer_alloc(FUNC(ic21_timeout)); +} + +static MACHINE_START( mpu3 ) +{ + mpu3_config_common(machine); + + /* setup 8 mechanical meters */ + MechMtr_config(machine,8); + + /* setup 4 reels */ + stepper_config(machine, 0, &mpu3_reel_interface); + stepper_config(machine, 1, &mpu3_reel_interface); + stepper_config(machine, 2, &mpu3_reel_interface); + stepper_config(machine, 3, &mpu3_reel_interface); + + /* setup the standard oki MSC1937 display */ + ROC10937_init(0, MSC1937,0); +} +/* +Characteriser (CHR) + +The MPU3 characteriser is surprisingly simple to simulate, as it operates a call, response pairing. The only factor that provides a challenge is that the +address of the PAL in memory varies between games. Once found, the memory location of the data table is easily found from the X register of the CPU. +*/ + +static WRITE8_HANDLER( characteriser_w ) +{ + mpu3_state *state = space->machine().driver_data(); + int x; + int call=data; + if (!state->m_current_chr_table) + fatalerror("No Characteriser Table @ %04x\n", cpu_get_previouspc(&space->device())); + + if (offset == 0) + { + { + if (call == 0) + { + state->m_prot_col = 0; + } + else + { + for (x = state->m_prot_col; x < 64; x++) + { + if (state->m_current_chr_table[(x)].call == call) + { + state->m_prot_col = x; + break; + } + } + } + } + } +} + + +static READ8_HANDLER( characteriser_r ) +{ + mpu3_state *state = space->machine().driver_data(); + if (!state->m_current_chr_table) + fatalerror("No Characteriser Table @ %04x\n", cpu_get_previouspc(&space->device())); + + if (offset == 0) + { + return state->m_current_chr_table[state->m_prot_col].response; + } + return 0; +} + +/* generate a 50 Hz signal (some components rely on this for external sync) */ +static TIMER_DEVICE_CALLBACK( gen_50hz ) +{ + mpu3_state *state = timer.machine().driver_data(); + /* 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.*/ + state->m_signal_50hz = state->m_signal_50hz?0:1; + ptm6840_set_c1(timer.machine().device("ptm_ic2"), 0, state->m_signal_50hz); + pia6821_cb1_w(timer.machine().device("pia_ic3"), ~state->m_signal_50hz); + update_triacs(timer.machine()); +} + +static TIMER_DEVICE_CALLBACK( ic10_callback ) +{ + mpu3_state *state = timer.machine().driver_data(); + // TODO: Use discrete handler for 555, this is far too simplistic + + state->m_ic10_output = state->m_ic10_output?0:1; + ptm6840_set_c2(timer.machine().device("ptm_ic2"), 0, state->m_ic10_output); + pia6821_ca1_w(timer.machine().device("pia_ic4"), state->m_ic10_output); + +} +static WRITE8_HANDLER( mpu3ptm_w ) +{ + device_t *ptm2 = space->machine().device("ptm_ic2"); + + ptm6840_write(ptm2,offset >>2,data);//((offset & 0x1f) >>2),data); +} + +static READ8_HANDLER( mpu3ptm_r ) +{ + device_t *ptm2 = space->machine().device("ptm_ic2"); + + return ptm6840_read(ptm2,offset >>2); +} + +static ADDRESS_MAP_START( mpu3_basemap, AS_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x07ff) AM_RAM AM_SHARE("nvram") + AM_RANGE(0x8800, 0x881f) AM_READWRITE(mpu3ptm_r, mpu3ptm_w)/* PTM6840 IC2 */ + AM_RANGE(0x9000, 0x9003) AM_DEVREADWRITE("pia_ic3", pia6821_r, pia6821_w) /* PIA6821 IC3 */ + AM_RANGE(0x9800, 0x9803) AM_DEVREADWRITE("pia_ic4", pia6821_r, pia6821_w) /* PIA6821 IC4 */ + AM_RANGE(0xa000, 0xa003) AM_DEVREADWRITE("pia_ic5", pia6821_r, pia6821_w) /* PIA6821 IC5 */ + AM_RANGE(0xa800, 0xa803) AM_DEVREADWRITE("pia_ic6", pia6821_r, pia6821_w) /* PIA6821 IC6 */ + + AM_RANGE(0x1000, 0xffff) AM_ROM +ADDRESS_MAP_END + +static MACHINE_CONFIG_START( mpu3base, mpu3_state ) + MCFG_MACHINE_START(mpu3) + MCFG_MACHINE_RESET(mpu3) + MCFG_CPU_ADD("maincpu", M6808, MPU3_MASTER_CLOCK)///4) + MCFG_CPU_PROGRAM_MAP(mpu3_basemap) + + MCFG_TIMER_ADD_PERIODIC("50hz",gen_50hz, attotime::from_hz(100)) + MCFG_TIMER_ADD_PERIODIC("555_ic10",ic10_callback, PERIOD_OF_555_ASTABLE(10000,1000,0.0000001)) + + /* 6840 PTM */ + MCFG_PTM6840_ADD("ptm_ic2", ptm_ic2_intf) + + MCFG_PIA6821_ADD("pia_ic3", pia_ic3_intf) + MCFG_PIA6821_ADD("pia_ic4", pia_ic4_intf) + MCFG_PIA6821_ADD("pia_ic5", pia_ic5_intf) + MCFG_PIA6821_ADD("pia_ic6", pia_ic6_intf) + + MCFG_NVRAM_ADD_0FILL("nvram") + + MCFG_DEFAULT_LAYOUT(layout_awpvid16) +MACHINE_CONFIG_END + + +static const mpu3_chr_table hprvpr_data[64] = { +{0x00, 0x00},{0x1a, 0x80},{0x04, 0xec},{0x10, 0x1c},{0x18, 0xf0},{0x0f, 0x28},{0x13, 0x54},{0x1b, 0x04}, +{0x03, 0xa4},{0x07, 0xac},{0x17, 0x3c},{0x1d, 0xf4},{0x16, 0x48},{0x15, 0x54},{0x0b, 0x00},{0x08, 0xc4}, +{0x19, 0x88},{0x01, 0x7c},{0x02, 0xf4},{0x05, 0x48},{0x0c, 0x54},{0x09, 0x04},{0x11, 0xc0},{0x14, 0xc8}, +{0x0a, 0x7c},{0x1f, 0xf4},{0x06, 0x6c},{0x0e, 0x70},{0x1c, 0x00},{0x12, 0xa4},{0x1e, 0x8c},{0x0d, 0x5c}, +{0x14, 0xf0},{0x0a, 0x28},{0x19, 0x30},{0x15, 0x40},{0x06, 0xe4},{0x0f, 0x88},{0x08, 0x5c},{0x1b, 0x94}, +{0x1e, 0x0c},{0x04, 0x74},{0x01, 0x40},{0x0c, 0xc4},{0x18, 0x8c},{0x1a, 0x7c},{0x11, 0xd4},{0x0b, 0x08}, +{0x03, 0x34},{0x17, 0x40},{0x10, 0xa4},{0x1d, 0xe8},{0x0e, 0x78},{0x07, 0x90},{0x12, 0x0c},{0x09, 0x54}, +{0x0d, 0x04},{0x1f, 0xc0},{0x16, 0xc8},{0x05, 0x78},{0x13, 0xd4},{0x1c, 0x0c},{0x02, 0x74},{0x00, 0x00}, +}; + +static DRIVER_INIT (m_hprvpr) +{ + mpu3_state *state = machine.driver_data(); + address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM); + + state->m_disp_func=METER_PORT; + state->m_current_chr_table = hprvpr_data; + space->install_legacy_readwrite_handler(0xc000, 0xc000 , FUNC(characteriser_r),FUNC(characteriser_w)); + +} + +ROM_START( mpu3utst ) + ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) + ROM_LOAD( "ut5.bin", 0x7800, 0x0800, CRC(89994adb) SHA1(03e38a860b6ba9d7ae2dbfa7845e85bcf67a6f4d)) + ROM_RELOAD(0xF800, 0x0800) +ROM_END + +ROM_START( m_hprvpr ) + ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) + ROM_LOAD( "hv.p3", 0x2000, 0x2000, CRC(63f8e04f) SHA1(9bfe06a6ea8c308e4a7035752722babbfd792160)) + ROM_RELOAD(0xc000, 0x2000) + ROM_LOAD( "hv.p2", 0x4000, 0x2000, CRC(b3b6f19e) SHA1(b2251dbe632b04ea7b5952b8a6217605b0df904c)) + ROM_RELOAD(0xc000, 0x2000) + ROM_LOAD( "hv.p1", 0x6000, 0x2000, CRC(05c0cf97) SHA1(085f432b608cec6054f1e03cf24ca80d3949a0de)) + ROM_RELOAD(0xe000, 0x2000) +ROM_END + +// year, name, parent, machine, input, init, monitor, company, fullname, flags +//Diagnostic ROMs +GAME( 198?, mpu3utst, 0, mpu3base, mpu3, 0, ROT0, "Barcrest", "MPU3 Unit Test (Program 5)", GAME_NO_SOUND ) +GAME( 198?, m_hprvpr, 0, mpu3base, mpu3, m_hprvpr, ROT0, "Barcrest", "Hyper Viper", GAME_NO_SOUND|GAME_UNEMULATED_PROTECTION ) \ No newline at end of file diff --git a/src/mame/drivers/mpu4.c b/src/mame/drivers/mpu4.c index fa6a06eed59..183287cc314 100644 --- a/src/mame/drivers/mpu4.c +++ b/src/mame/drivers/mpu4.c @@ -4,16 +4,16 @@ This is the core driver, no video specific stuff should go in here. This driver holds all the mechanical games. - 01-2011: Adding the missing 'OKI' sound card, and documented it. - 05-2009: Miscellaneous lamp fixes, based on data from FME Forever. + 04-2011: More accurate gamball code, fixed ROM banking (Project Amber), added BwB CHR simulator (Amber) + This is still a hard coded system, but significantly different to Barcrest's version. + 03-2011: Lamp timing fixes, support for all known expansion cards added. + 01-2011: Adding the missing 'OKI' sound card, and documented it, but needs 6376 rewrite. 09-2007: Haze: Added Deal 'Em video support. 03-08-2007: J Wallace: Removed audio filter for now, since sound is more accurate without them. Connect 4 now has the right sound. 03-07-2007: J Wallace: Several major changes, including input relabelling, and system timer improvements. 06-2007: Atari Ace, many cleanups and optimizations of I/O routines 09-06-2007: J Wallace: Fixed 50Hz detection circuit. - 09-04-2007: J Wallace: Corrected a lot of out of date info in this revision history. - Revisionism, if you will. 17-02-2007: J Wallace: Added Deal 'Em - still needs some work. 10-02-2007: J Wallace: Improved input timing. 30-01-2007: J Wallace: Characteriser rewritten to run the 'extra' data needed by some games. @@ -256,9 +256,11 @@ TODO: - Distinguish door switches using manual static TIMER_CALLBACK( ic24_timeout ); -static const UINT8 reel_mux_table[8]= {0,4,2,6,1,5,3,7};//include 7, although I don't think it's used +static const UINT8 reel_mux_table[8]= {0,4,2,6,1,5,3,7};//include 7, although I don't think it's used, this is basically a wire swap static const UINT8 reel_mux_table7[8]= {3,1,5,6,4,2,0,7}; +static const UINT8 bwb_chr_table_common[10]= {0x00,0x04,0x04,0x0c,0x0c,0x1c,0x14,0x2c,0x5c,0x2c}; + #define STANDARD_REEL 0 /* As originally designed 3/4 reels*/ #define FIVE_REEL_5TO8 1 /* Interfaces to meter port, allows some mechanical metering, but there is significant 'bounce' in the extra reel*/ #define FIVE_REEL_8TO5 2 /* Mounted backwards for space reasons, but different board*/ @@ -293,6 +295,11 @@ struct mpu4_chr_table UINT8 response; }; +struct bwb_chr_table//dynamic populated table +{ + UINT8 response; +}; + /* Video stuff */ struct ef9369_t { @@ -358,9 +365,15 @@ public: int m_card_live; int m_led_extender; int m_bwb_bank; + int m_chr_state; + int m_chr_counter; + int m_chr_value; + int m_bwb_return; + int m_pageval; + int m_pageset; int m_hopper; const mpu4_chr_table* m_current_chr_table; - + const bwb_chr_table* m_bwb_chr_table1; //Video UINT8 m_m6840_irq_state; UINT8 m_m6850_irq_state; @@ -608,7 +621,10 @@ static void mpu4_stepper_reset(mpu4_state *state) for (reel = 0; reel < 6; reel++) { stepper_reset_position(reel); - if (stepper_optic_state(reel)) pattern |= 1<m_reel_mux) + { + if (stepper_optic_state(reel)) pattern |= 1<m_optic_pattern = pattern; } @@ -633,8 +649,10 @@ static MACHINE_RESET( mpu4 ) state->m_IC23G2B = 0; state->m_prot_col = 0; + state->m_chr_counter = 0; + state->m_chr_value = 0; -/* init rom bank, some games don't set this */ + /* init rom bank, some games don't set this, and will assume bank 0,set 0 */ { UINT8 *rom = machine.region("maincpu")->base(); @@ -643,7 +661,6 @@ static MACHINE_RESET( mpu4 ) memory_set_bank(machine, "bank1",0); machine.device("maincpu")->reset(); } - } @@ -680,10 +697,21 @@ static WRITE_LINE_DEVICE_HANDLER( cpu0_irq ) } } -/* Bankswitching */ +/* 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. +*/ static WRITE8_HANDLER( bankswitch_w ) { - memory_set_bank(space->machine(), "bank1",data & 0x07); + mpu4_state *state = space->machine().driver_data(); + state->m_pageval=(data&0x03); + memory_set_bank(space->machine(), "bank1",state->m_pageval + (state->m_pageset?4:0)); } @@ -693,6 +721,14 @@ static READ8_HANDLER( bankswitch_r ) } +static WRITE8_HANDLER( bankset_w ) +{ + mpu4_state *state = space->machine().driver_data(); + state->m_pageval=(data - 2);//writes 2 and 3, to represent 0 and 1 - a hangover from the half page design? + memory_set_bank(space->machine(), "bank1",state->m_pageval + (state->m_pageset?4:0)); +} + + /* IC2 6840 PTM handler */ static WRITE8_DEVICE_HANDLER( ic2_o1_callback ) { @@ -810,7 +846,7 @@ static WRITE_LINE_DEVICE_HANDLER( pia_ic3_ca2_w ) static WRITE_LINE_DEVICE_HANDLER( pia_ic3_cb2_w ) { LOG_IC3(("%s: IC3 PIA Write CB (alpha reset), %02X\n",device->machine().describe_context(),state)); - +// DM Data pin A if ( state ) ROC10937_reset(0); ROC10937_draw_16seg(0); } @@ -1117,72 +1153,86 @@ static WRITE8_DEVICE_HANDLER( pia_ic5_porta_w ) } if (mame_stricmp(device->machine().system().name, "m_gmball") == 0) - { + { /* The 'Gamball' device is a unique piece of mechanical equipment, designed to provide a truly fair hi-lo gamble for an AWP machine. Functionally, it consists of a ping-pong ball or similar enclosed in the machine's backbox, on a platform with 12 holes. When the low 4 bytes of AUX1 are triggered, this fires the ball out from the - hole it's currently in, to land in another. Landing in the same hole cause the machine to + hole it's currently in, to land in another. Landing in the same hole causes the machine to refire the ball. The ball detection is done by the high 4 bytes of AUX1. - Here we call the MAME RNG, clamping it to 16 values, with the unused - values effectively asking the machine to 'roll again'. We then trigger the switches corresponding to - the correct number. This appears to be the best way of making the game fair, short of simulating - the physics of a bouncing ball ;)*/ + Here we call the MAME RNG, once to pick a row, once to pick from the four pockets within it. We + then trigger the switches corresponding to the correct number. This appears to be the best way + of making the game fair, short of simulating the physics of a bouncing ball ;)*/ if (data & 0x0f) { - switch (device->machine().rand() & 0xf) + switch (device->machine().rand() & 0x2) { - case 0x00: - default: - break;// stay where we are if we roll a zero, or roll more than 12 - case 0x01: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x50; - break; - case 0x02: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x90; - break; - case 0x03: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x20; - break; - case 0x04: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0xb0; - break; - case 0x05: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x00; - break; - case 0x06: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x30; - break; - case 0x07: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0xa0; - break; - case 0x08: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0xd0; - break; - case 0x09: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0xd0; - break; - case 0x0a: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x10; - break; - case 0xb: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x80; - break; - case 0xc: - state->m_aux1_input = (state->m_aux1_input & 0x0f); - state->m_aux1_input|= 0x40; - break; + case 0x00: //Top row + { + switch (device->machine().rand() & 0x3) + { + case 0x00: //7 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0xa0; + break; + case 0x01://4 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0xb0; + break; + case 0x02://9 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0xc0; + break; + case 0x03://8 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0xd0; + break; + } + } + case 0x01: //Middle row - note switches don't match pattern + { + switch (device->machine().rand() & 0x3) + { + case 0x00://12 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x40; + break; + case 0x01://1 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x50; + break; + case 0x02://11 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x80; + break; + case 0x03://2 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x90; + break; + } + } + case 0x02: //Bottom row + { + switch (device->machine().rand() & 0x3) + { + case 0x00://5 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x00; + break; + case 0x01://10 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x10; + break; + case 0x02://3 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x20; + break; + case 0x03://6 + state->m_aux1_input = (state->m_aux1_input & 0x0f); + state->m_aux1_input|= 0x30; + break; + } + } } } } @@ -1574,6 +1624,7 @@ static WRITE_LINE_DEVICE_HANDLER( pia_ic8_cb2_w ) mpu4_state *drvstate = device->machine().driver_data(); LOG_IC8(("%s: IC8 PIA write CB2 (alpha clock) %02X\n", device->machine().describe_context(), state & 0xFF)); + // DM Data pin B if ( !drvstate->m_alpha_clock && (state) ) { ROC10937_shift_data(0, drvstate->m_alpha_data_line&0x01?0:1); @@ -1663,7 +1714,9 @@ static WRITE_LINE_DEVICE_HANDLER( pia_gb_cb2_w ) //Some BWB games use this to drive the bankswitching if (mstate->m_bwb_bank) { - memory_set_bank(device->machine(), "bank1",state); + mstate->m_pageval=state; + + memory_set_bank(device->machine(), "bank1",mstate->m_pageval + (mstate->m_pageset?4:0)); } } @@ -1771,56 +1824,56 @@ static INPUT_PORTS_START( mpu4 ) PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_START1) PORT_START("DIL1") - PORT_DIPNAME( 0x01, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") + PORT_DIPNAME( 0x80, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "DIL108" ) PORT_DIPLOCATION("DIL1:08") + PORT_DIPNAME( 0x20, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL108" ) PORT_DIPLOCATION("DIL1:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_START("DIL2") - PORT_DIPNAME( 0x01, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") + PORT_DIPNAME( 0x80, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPNAME( 0x20, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_START("AUX1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("0") @@ -1886,56 +1939,56 @@ static INPUT_PORTS_START( connect4 ) PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Drop") PORT_START("DIL1") - PORT_DIPNAME( 0x01, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") + PORT_DIPNAME( 0x80, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "Invert Alpha?" ) PORT_DIPLOCATION("DIL1:08") - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x80, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x20, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL108" ) PORT_DIPLOCATION("DIL1:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_START("DIL2") - PORT_DIPNAME( 0x01, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") + PORT_DIPNAME( 0x80, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPNAME( 0x20, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_START("AUX1") PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("0") @@ -2000,56 +2053,56 @@ static INPUT_PORTS_START( gamball ) PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_START1) PORT_START("DIL1") - PORT_DIPNAME( 0x01, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") + PORT_DIPNAME( 0x80, 0x00, "DIL101" ) PORT_DIPLOCATION("DIL1:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL102" ) PORT_DIPLOCATION("DIL1:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "DIL108" ) PORT_DIPLOCATION("DIL1:08") + PORT_DIPNAME( 0x20, 0x00, "DIL103" ) PORT_DIPLOCATION("DIL1:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL104" ) PORT_DIPLOCATION("DIL1:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL105" ) PORT_DIPLOCATION("DIL1:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL106" ) PORT_DIPLOCATION("DIL1:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL107" ) PORT_DIPLOCATION("DIL1:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL108" ) PORT_DIPLOCATION("DIL1:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_START("DIL2") - PORT_DIPNAME( 0x01, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") + PORT_DIPNAME( 0x80, 0x00, "DIL201" ) PORT_DIPLOCATION("DIL2:01") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL202" ) PORT_DIPLOCATION("DIL2:02") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPNAME( 0x20, 0x00, "DIL203" ) PORT_DIPLOCATION("DIL2:03") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL204" ) PORT_DIPLOCATION("DIL2:04") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL205" ) PORT_DIPLOCATION("DIL2:05") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL206" ) PORT_DIPLOCATION("DIL2:06") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL207" ) PORT_DIPLOCATION("DIL2:07") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x01, 0x00, "DIL208" ) PORT_DIPLOCATION("DIL2:08") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_START("AUX1") PORT_BIT(0xFF, IP_ACTIVE_HIGH, IPT_SPECIAL)//Handled by Gamball unit @@ -2072,6 +2125,16 @@ static const stepper_interface barcrest_reel_interface = 4, 0x00 }; + +static const stepper_interface barcrest_reelrev_interface = +{ + BARCREST_48STEP_REEL, + 92, + 4, + 0x00, + 1 +}; + static const stepper_interface barcrest_opto1_interface = { BARCREST_48STEP_REEL, @@ -2181,7 +2244,8 @@ For most Barcrest games, the following method was used: The initial 'PALTEST' routine as found in the Barcrest programs simply writes the first 'call' to the CHR space, to read back the 'response'. There is no attempt to alter the order or anything else, just a simple runthrough of the entire data table. The only 'catch' in this is to note that the CHR chip always scans -through the table starting at the last accessed data value, unless 00 is used to reset to the beginning. +through the table starting at the last accessed data value, unless 00 is used to reset to the beginning. This is obviously +a simplification, in fact the PAL does bit manipulation with some latching. However, a final 8 byte row, that controls the lamp matrix is not tested - to date, no-one outside of Barcrest knows how this is generated, and currently trial and error is the only sensible method. It is noted that the default, @@ -2280,11 +2344,38 @@ static READ8_HANDLER( characteriser_r ) BwB Characteriser (CHR) The BwB method of protection is considerably different to the Barcrest one, with any -incorrect behaviour manifesting in ridiculously large payouts. +incorrect behaviour manifesting in ridiculously large payouts. The hardware is the +same, however the main weakness of the software has been eliminated. In fact, the software seems deliberately designed to mislead, but is (fortunately for us) prone to similar weaknesses that allow a per game solution. +Project Amber performed a source analysis (available on request) which appears to make things work. +Said weaknesses (A Cheats Guide according to Project Amber) + +The common initialisation sequence is "00 04 04 0C 0C 1C 14 2C 5C 2C" + 0 1 2 3 4 5 6 7 8 +Using debug search for the first read from said string (best to find it first). + +At this point, the X index on the CPU is at the magic number address. + +The subsequent calls for each can be found based on the magic address + + (0) = ( (BWBMagicAddress)) + (1) = ( (BWBMagicAddress + 1)) + (2) = ( (BWBMagicAddress + 2)) + (3) = ( (BWBMagicAddress + 4)) + + (4) = ( (BWBMagicAddress - 5)) + (5) = ( (BWBMagicAddress - 4)) + (6) = ( (BWBMagicAddress - 3)) + (7) = ( (BWBMagicAddress - 2)) + (8) = ( (BWBMagicAddress - 1)) + +These return the standard init sequence as above. + +For ease of understanding, we use three tables, one holding the common responses +and two holding the appropriate call and response pairs for the two stages of operation */ @@ -2297,38 +2388,35 @@ static WRITE8_HANDLER( bwb_characteriser_w ) if (!state->m_current_chr_table) fatalerror("No Characteriser Table @ %04x\n", cpu_get_previouspc(&space->device())); - if (offset == 0)//initialisation is always at 0x800 + if ((offset & 0x3f)== 0)//initialisation is always at 0x800 { + if (!state->m_chr_state) { - if (call == 0) - { - state->m_init_col =0; - } - else - { - for (x = state->m_init_col; x < 64; x++) - { - if (state->m_current_chr_table[(x)].call == call) - { - state->m_init_col = x; - LOG_CHR_FULL(("BwB Characteriser init column %02X\n",state->m_init_col)); - break; - } - } - } + state->m_chr_state=1; + state->m_chr_counter=0; + } + if (call == 0) + { + state->m_init_col ++; + } + else + { + state->m_init_col =0; } } - else + + state->m_chr_value = space->machine().rand(); + for (x = 0; x < 4; x++) { - for (x = state->m_prot_col; x < 64;) + if (state->m_current_chr_table[(x)].call == call) { - x++; - if (state->m_current_chr_table[(x)].call == call) + if (x == 0) // reinit { - state->m_prot_col = x; - LOG_CHR(("BwB Characteriser init column %02X\n",state->m_prot_col)); - break; + state->m_bwb_return = 0; } + state->m_chr_value = bwb_chr_table_common[(state->m_bwb_return)]; + state->m_bwb_return++; + break; } } } @@ -2336,21 +2424,38 @@ static WRITE8_HANDLER( bwb_characteriser_w ) static READ8_HANDLER( bwb_characteriser_r ) { mpu4_state *state = space->machine().driver_data(); - if (!state->m_current_chr_table) - fatalerror("No Characteriser Table @ %04x\n", cpu_get_previouspc(&space->device())); LOG_CHR(("Characteriser read offset %02X \n",offset)); if (offset ==0) { - LOG_CHR(("Characteriser read data %02X \n",state->m_current_chr_table[state->m_init_col].response)); - return state->m_current_chr_table[state->m_init_col].response; + switch (state->m_chr_counter) + { + case 6: + case 13: + case 20: + case 27: + case 34: + { + return state->m_bwb_chr_table1[(((state->m_chr_counter + 1) / 7) - 1)].response; + break; + } + default: + { + if (state->m_chr_counter > 34) + { + state->m_chr_counter = 35; + state->m_chr_state = 2; + } + state->m_chr_counter ++; + return state->m_chr_value; + } + } } - else + else { - LOG_CHR(("Characteriser read BwB data %02X \n",state->m_current_chr_table[state->m_prot_col].response)); - return state->m_current_chr_table[state->m_prot_col].response; + return state->m_chr_value; } } @@ -2402,18 +2507,19 @@ static const mpu4_chr_table oldtmr_data[72] = { {0x00, 0x00},{0x01, 0x00},{0x04, 0x00},{0x09, 0x00},{0x10, 0x00},{0x19, 0x10},{0x24, 0x00},{0x31, 0x00} }; -static const mpu4_chr_table blsbys_data[72] = { -{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x2e, 0x36},{0x20, 0x42}, -{0x0f, 0x27},{0x24, 0x42},{0x3c, 0x09},{0x2c, 0x01},{0x01, 0x1d},{0x1d, 0x40},{0x40, 0xd2},{0xd2, 0x01}, -{0x01, 0xf9},{0xb1, 0x41},{0x41, 0x1c},{0x1c, 0x01},{0x01, 0xf9},{0x04, 0x54},{0x54, 0x02},{0x02, 0x00}, -{0x00, 0x00},{0x00, 0x2e},{0x2e, 0x20},{0x20, 0x0f},{0x0f, 0x24},{0x24, 0x3c},{0x3c, 0x39},{0x3c, 0xc9}, -{0xc9, 0x05},{0x05, 0x04},{0x04, 0x54},{0x54, 0x02},{0x02, 0x00},{0x00, 0x00},{0x00, 0x2e},{0x2e, 0x20}, -{0x20, 0x0f},{0x0f, 0x24},{0x24, 0x3c},{0x3c, 0x39},{0x3c, 0x36},{0x36, 0x00},{0x42, 0x04},{0x27, 0x04}, -{0x42, 0x0c},{0x09, 0x0c},{0x42, 0x1c},{0x27, 0x14},{0x42, 0x2c},{0x42, 0x5c},{0x09, 0x2c}, -//All this may be garbage - it never gets called, but is in the ROM (?) -{0x0A, 0x00}, -{0x31, 0x20},{0x34, 0x90}, {0x1e, 0x40},{0x04, 0x90},{0x01, 0xe4},{0x0c, 0xf4},{0x18, 0x64},{0x19, 0x10}, -{0x00, 0x00},{0x01, 0x00},{0x04, 0x00},{0x09, 0x00},{0x10, 0x00},{0x19, 0x10},{0x24, 0x00},{0x31, 0x00} +static const bwb_chr_table blsbys_data1[5] = { +//Magic number 724A + +// PAL Codes +// 0 1 2 3 4 5 6 7 8 +// ?? ?? 20 0F 24 3C 36 27 09 + + {0x67},{0x17},{0x0f},{0x24},{0x3c}, +}; + +static const mpu4_chr_table blsbys_data[8] = { +{0xEF, 0x02},{0x81, 0x00},{0xCE, 0x00},{0x00, 0x2e}, +{0x06, 0x20},{0xC6, 0x0f},{0xF8, 0x24},{0x8E, 0x3c}, }; // set percentage and other options. 2e 20 0f @@ -2465,8 +2571,9 @@ static DRIVER_INIT (m_grtecp) mpu4_state *state = machine.driver_data(); state->m_reel_mux=FIVE_REEL_5TO8; state->m_lamp_extender=SMALL_CARD; - // setup 5 default 96 half step reels with the mux board - mpu4_config_common_reels(machine,5); + // setup 4 default 96 half step reels with the mux board + mpu4_config_common_reels(machine,4); + stepper_config(machine, 4, &barcrest_reelrev_interface); state->m_current_chr_table = grtecp_data; } @@ -2481,6 +2588,7 @@ static DRIVER_INIT (m_blsbys) stepper_config(machine, 2, &bwb_opto1_interface); stepper_config(machine, 3, &bwb_opto1_interface); stepper_config(machine, 4, &bwb_opto1_interface); + state->m_bwb_chr_table1 = blsbys_data1; state->m_current_chr_table = blsbys_data; } @@ -2517,10 +2625,7 @@ static TIMER_DEVICE_CALLBACK( gen_50hz ) state->m_signal_50hz = state->m_signal_50hz?0:1; pia6821_ca1_w(timer.machine().device("pia_ic4"), state->m_signal_50hz); /* signal is connected to IC4 CA1 */ - if (state->m_signal_50hz) - { - update_meters(state); - } + update_meters(state);//run at 100Hz to sync with PIAs } static ADDRESS_MAP_START( mod2_memmap, AS_PROGRAM, 8 ) @@ -2599,6 +2704,7 @@ static ADDRESS_MAP_START( mpu4_bwb_map, AS_PROGRAM, 8 ) AM_RANGE(0x0850, 0x0850) AM_WRITE(bankswitch_w) // write bank (rom page select) AM_RANGE(0x0858, 0x0858) AM_WRITE(bankswitch_w) // write bank (rom page select) + AM_RANGE(0x0878, 0x0878) AM_WRITE(bankset_w) // write bank (rom page select) AM_RANGE(0x0880, 0x0883) AM_DEVREADWRITE("pia_ic4ss", pia6821_r,pia6821_w) // PIA6821 on sampled sound board AM_RANGE(0x08c0, 0x08c7) AM_DEVREADWRITE("ptm_ic3ss", ptm6840_read, ptm6840_write) // 6840PTM on sampled sound board @@ -2771,8 +2877,9 @@ ROM_START( m_grtecp ) ROM_END ROM_START( m_blsbys ) - ROM_REGION( 0x40000, "maincpu", 0 ) + ROM_REGION( 0x80000, "maincpu", 0 ) ROM_LOAD("bbprog.bin", 0x00000, 0x20000, CRC(c262cfda) SHA1(f004895e0dd3f8420683927915554e19e41bd20b)) + ROM_RELOAD(0x40000,0x20000) ROM_REGION( 0x200000, "msm6376", 0 ) ROM_LOAD( "bbsnd.p1", 0x000000, 0x080000, CRC(715c9e95) SHA1(6a0c9c63e56cfc21bf77cf29c1b844b8e0844c1e) ) diff --git a/src/mame/drivers/mpu4drvr.c b/src/mame/drivers/mpu4drvr.c index c3619ebbde0..ea5c2e86c4a 100644 --- a/src/mame/drivers/mpu4drvr.c +++ b/src/mame/drivers/mpu4drvr.c @@ -1956,6 +1956,8 @@ static MACHINE_RESET( mpu4_vid ) state->m_IC23G2B = 0; state->m_prot_col = 0; + state->m_chr_counter = 0; + state->m_chr_value = 0; } static ADDRESS_MAP_START( mpu4_68k_map, AS_PROGRAM, 16 ) @@ -2058,7 +2060,7 @@ static ADDRESS_MAP_START( bwbvid5_68k_map, AS_PROGRAM, 16 ) AM_RANGE(0xe01000, 0xe0100f) AM_DEVREADWRITE8("6840ptm_68k", ptm6840_read, ptm6840_write, 0xff) AM_RANGE(0xe02000, 0xe02007) AM_DEVREADWRITE8("pia_ic4ss", pia6821_r, pia6821_w, 0xff) AM_RANGE(0xe03000, 0xe0300f) AM_DEVREADWRITE8("6840ptm_ic3ss", ptm6840_read, ptm6840_write, 0xff) - AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(bwb_characteriser16_r, bwb_characteriser16_w)//AM_READWRITE(adpcm_r, adpcm_w) CHR ? + AM_RANGE(0xe04000, 0xe0400f) AM_READWRITE(bwb_characteriser16_r, bwb_characteriser16_w)//AM_READWRITE(adpcm_r, adpcm_w) CHR ? ADDRESS_MAP_END /* Deal 'Em */ @@ -2561,6 +2563,10 @@ incorrect behaviour manifesting in ridiculously large payouts. In fact, the software seems deliberately designed to mislead, but is (fortunately for us) prone to similar weaknesses that allow a per game solution. +See MPU4.c for more info + +As BwB games aren't yet booting on the 16-bit board, we're duplicating the 8-bit program +Precedent suggests this is not that dangerous an assumption to make. */ @@ -2573,38 +2579,34 @@ static WRITE16_HANDLER( bwb_characteriser16_w ) if (!state->m_current_chr_table) fatalerror("No Characteriser Table @ %04x\n", cpu_get_previouspc(&space->device())); - if (offset == 0)//initialisation is always at 0x800 + if (offset == 0) { + if (!state->m_chr_state) { - if (call == 0) - { - state->m_init_col =0; - } - else - { - for (x = state->m_init_col; x < 64; x++) - { - if (state->m_current_chr_table[(x)].call == call) - { - state->m_init_col = x; - LOG_CHR_FULL(("BwB Characteriser init column %02X\n",state->m_init_col)); - break; - } - } - } + state->m_chr_state=1; + state->m_chr_counter=0; + } + if (call == 0) + { + state->m_init_col ++; + } + else + { + state->m_init_col =0; } } - else + state->m_chr_value = space->machine().rand(); + for (x = 0; x < 4; x++) { - for (x = state->m_prot_col; x < 64;) + if (state->m_current_chr_table[(x)].call == call) { - x++; - if (state->m_current_chr_table[(x)].call == call) + if (x == 0) // reinit { - state->m_prot_col = x; - LOG_CHR(("BwB Characteriser init column %02X\n",state->m_prot_col)); - break; + state->m_bwb_return = 0; } + state->m_chr_value = bwb_chr_table_common[(state->m_bwb_return)]; + state->m_bwb_return++; + break; } } } @@ -2612,21 +2614,38 @@ static WRITE16_HANDLER( bwb_characteriser16_w ) static READ16_HANDLER( bwb_characteriser16_r ) { mpu4_state *state = space->machine().driver_data(); - if (!state->m_current_chr_table) - fatalerror("No Characteriser Table @ %04x\n", cpu_get_previouspc(&space->device())); LOG_CHR(("Characteriser read offset %02X \n",offset)); if (offset ==0) { - LOG_CHR(("Characteriser read data %02X \n",state->m_current_chr_table[state->m_init_col].response)); - return state->m_current_chr_table[state->m_init_col].response; + switch (state->m_chr_counter) + { + case 6: + case 13: + case 20: + case 27: + case 34: + { + return state->m_bwb_chr_table1[(((state->m_chr_counter + 1) / 7) - 1)].response; + break; + } + default: + { + if (state->m_chr_counter > 34) + { + state->m_chr_counter = 35; + state->m_chr_state = 2; + } + state->m_chr_counter ++; + return state->m_chr_value; + } + } } - else + else { - LOG_CHR(("Characteriser read BwB data %02X \n",state->m_current_chr_table[state->m_prot_col].response)); - return state->m_current_chr_table[state->m_prot_col].response; + return state->m_chr_value; } } @@ -2773,18 +2792,16 @@ static const mpu4_chr_table quidgrid_data[64] = { {0x0D, 0x04}, {0x1F, 0x64}, {0x16, 0x24}, {0x05, 0x64}, {0x13, 0x24}, {0x1C, 0x64}, {0x02, 0x74}, {0x00, 0x00} }; -static const mpu4_chr_table prizeinv_data[72] = { -{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x00, 0x00},{0x2e, 0x36},{0x20, 0x42}, -{0x0f, 0x27},{0x24, 0x42},{0x3c, 0x09},{0x2c, 0x01},{0x01, 0x1d},{0x1d, 0x40},{0x40, 0xd2},{0xd2, 0x01}, -{0x01, 0xf9},{0xb1, 0x41},{0x41, 0x1c},{0x1c, 0x01},{0x01, 0xf9},{0x04, 0x54},{0x54, 0x02},{0x02, 0x00}, -{0x00, 0x00},{0x00, 0x2e},{0x2e, 0x20},{0x20, 0x0f},{0x0f, 0x24},{0x24, 0x3c},{0x3c, 0x39},{0x3c, 0xc9}, -{0xc9, 0x05},{0x05, 0x04},{0x04, 0x54},{0x54, 0x02},{0x02, 0x00},{0x00, 0x00},{0x00, 0x2e},{0x2e, 0x20}, -{0x20, 0x0f},{0x0f, 0x24},{0x24, 0x3c},{0x3c, 0x39},{0x3c, 0x36},{0x36, 0x00},{0x42, 0x04},{0x27, 0x04}, -{0x42, 0x0c},{0x09, 0x0c},{0x42, 0x1c},{0x27, 0x14},{0x42, 0x2c},{0x42, 0x5c},{0x09, 0x2c}, -//All this may be garbage - the ROM table seems endless -{0x0A, 0x00}, -{0x31, 0x20},{0x34, 0x90}, {0x1e, 0x40},{0x04, 0x90},{0x01, 0xe4},{0x0c, 0xf4},{0x18, 0x64},{0x19, 0x10}, -{0x00, 0x00},{0x01, 0x00},{0x04, 0x00},{0x09, 0x00},{0x10, 0x00},{0x19, 0x10},{0x24, 0x00},{0x31, 0x00} + +static const bwb_chr_table prizeinv_data1[5] = { +//This is all wrong, but without BwB Vid booting, +//I can't find the right values. These should be close though + {0x67},{0x17},{0x0f},{0x24},{0x3c}, +}; + +static const mpu4_chr_table prizeinv_data[8] = { +{0xEF, 0x02},{0x81, 0x00},{0xCE, 0x00},{0x00, 0x2e}, +{0x06, 0x20},{0xC6, 0x0f},{0xF8, 0x24},{0x8E, 0x3c}, }; static DRIVER_INIT (adders) @@ -3490,6 +3507,6 @@ GAME( 199?, vgpoker, 0, vgpoker, mpu4, 0, ROT0, "BwB", " GAME( 199?, prizeinv, 0, bwbvid, mpu4, prizeinv, ROT0, "BwB", "Prize Space Invaders (20\" v1.1)", GAME_NOT_WORKING ) GAME( 199?, blox, 0, bwbvid, mpu4, 0, ROT0, "BwB", "Blox (v2.0)", GAME_NOT_WORKING ) GAME( 199?, bloxd, blox, bwbvid, mpu4, 0, ROT0, "BwB", "Blox (v2.0, Datapak)", GAME_NOT_WORKING ) -GAME( 1996, renoreel, 0, bwbvid5, mpu4, 0, ROT0, "BwB", "Reno Reels (20p/10GBP Cash, release A)", GAME_NOT_WORKING ) +GAME( 1996, renoreel, 0, bwbvid5, mpu4, prizeinv, ROT0, "BwB", "Reno Reels (20p/10GBP Cash, release A)", GAME_NOT_WORKING ) GAME( 199?, redhtpkr, 0, bwbvid, mpu4, 0, ROT0, "BwB", "Red Hot Poker (20p/10GBP Cash, release 3)", GAME_NOT_WORKING ) GAME( 199?, bwbtetrs, 0, bwbvid, mpu4, 0, ROT0, "BwB", "BwB Tetris v 2.2", GAME_NOT_WORKING ) diff --git a/src/mame/layout/bfm_sc1.lay b/src/mame/layout/bfm_sc1.lay index 0f1f00a5c66..0fb2a1f35ae 100644 --- a/src/mame/layout/bfm_sc1.lay +++ b/src/mame/layout/bfm_sc1.lay @@ -2089,2096 +2089,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mame/machine/steppers.c b/src/mame/machine/steppers.c index 4f5f173e064..828f9a7e632 100644 --- a/src/mame/machine/steppers.c +++ b/src/mame/machine/steppers.c @@ -2,17 +2,20 @@ // // // steppers.c steppermotor emulation // // // -// Emulates : 48 step motors driven with full step or half step // +// Emulates : Stepper motors driven with full step or half step // // also emulates the index optic // // // +// 04-04-2011: J. Wallace - Added reverse spin (this is necessary for // +// accuracy, and improved wraparound logic // +// 03-2011: New 2D array to remove reel bounce and // +// make more realistic // // 26-01-2007: J. Wallace - Rewritten to make it more flexible // // and to allow indices to be set in drivers // // 29-12-2006: J. Wallace - Added state save support // // 05-03-2004: Re-Animator // // // -// TODO: add different types of stepper motors if needed // -// Convert the tables to something more like the real thing // -// someone who understands the device system may want to convert // +// TODO: add further different types of stepper motors if needed // +// Someone who understands the device system may want to convert // // this // /////////////////////////////////////////////////////////////////////////// @@ -31,7 +34,8 @@ typedef struct _stepper UINT8 pattern, /* coil pattern */ old_pattern, /* old coil pattern */ phase, /* motor phase */ - type; /* reel type */ + type, /* reel type */ + reverse; /* Does reel spin backwards (construction of unit, not wiring) */ INT16 step_pos, /* step position 0 - max_steps */ max_steps; /* maximum step position */ @@ -43,24 +47,25 @@ typedef struct _stepper } stepper; static stepper step[MAX_STEPPERS]; -/* step table, use active coils as row, phase as column */ +/* step table, use active coils as row, phase as column*/ static const int StarpointStepTab[8][16] = {// 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Phase - { 0, 0, 4, 0, 2, 1, 3, 0, -2, -1, -3, 0, 0, 0, 0, 0 },// 0 - { 0, -1, 3, 0, 1, 0, 2, 0, -3, -2, 4, 0, 0, 0, 0, 0 },// 1 - { 0, -2, 2, 0, 0, -1, 1, 0, 4, -3, 3, 0, 0, 0, 0, 0 },// 2 - { 0, -3, 1, 0, -1, -2, 0, 0, 3, 4, 2, 0, 0, 0, 0, 0 },// 3 - { 0, 4, 0, 0, -2, -3, -1, 0, 2, 3, 1, 0, 0, 0, 0, 0 },// 4 - { 0, 3, -1, 0, -3, -4, -2, 0, 1, 2, 0, 0, 0, 0, 0, 0 },// 5 - { 0, 2, -2, 0, 4, 3, -3, 0, 0, 1, -1, 0, 0, 0, 0, 0 },// 6 - { 0, 1, -3, 0, 3, 2, -4, 0, -1, 0, -2, 0, 0, 0, 0, 0 },// 7 + { 0, 2, 0, 0, 2, 1, 3, 0, -2, -1, -1, 0, 0, 0, 0, 0 },// 0 + { 0, -1, 3, 0, 1, 2, 2, 0, -3, -2, -2, 0, 0, 0, 0, 0 },// 1 + { 0, -2, 2, 0, 2, -1, 1, 0, 2, -3, 3, 0, 0, 0, 0, 0 },// 2 + { 0, -1, 1, 0, -1, -2, -2, 0, 3, 2, 2, 0, 0, 0, 0, 0 },// 3 + { 0, -2, 0, 0, -2, -3, -1, 0, 2, 3, 1, 0, 0, 0, 0, 0 },// 4 + { 0, 3, -1, 0, -1, -2, -2, 0, 1, 0, 2, 0, 0, 0, 0, 0 },// 5 + { 0, 2, -2, 0, -2, 3, -3, 0, -2, 1, -1, 0, 0, 0, 0, 0 },// 6 + { 0, 1, -3, 0, 3, 2, 2, 0, -1, -2, -2, 0, 0, 0, 0, 0 },// 7 }; + static const int MPU3StepTab[8][4] = {// 00 01 10 11 Phase { 2, 0, 0, -2, },// 0 { 0, 0, 0, 0, },// 1 - { 0, -2, -2, 0, },// 2 + { 0, -2, 2, 0, },// 2 { 0, 0, 0, 0, },// 3 {-2, 0, 0, 2, },// 4 { 0, 0, 0, 0, },// 5 @@ -80,7 +85,7 @@ static const int BarcrestStepTab[8][16] = { 0, 2, 0, 3, -2, 0, -3, 0, 0, 1, 0, 0, -1, 0, 0, 0 },// 7 }; -/* useful interfaces */ +/* useful interfaces (Starpoint is a very common setup)*/ const stepper_interface starpoint_interface_48step = { @@ -90,6 +95,15 @@ const stepper_interface starpoint_interface_48step = 0x09 }; +const stepper_interface starpoint_interface_48step_reverse = +{ + STARPOINT_48STEP_REEL, + 16, + 24, + 0x09, + 1 +}; + /////////////////////////////////////////////////////////////////////////// void stepper_config(running_machine &machine, int which, const stepper_interface *intf) { @@ -103,11 +117,13 @@ void stepper_config(running_machine &machine, int which, const stepper_interface step[which].index_start = intf->index_start;/* location of first index value in half steps */ step[which].index_end = intf->index_end; /* location of last index value in half steps */ step[which].index_patt = intf->index_patt; /* hex value of coil pattern (0 if not needed)*/ + step[which].reverse = intf->reverse; step[which].phase = 0; step[which].pattern = 0; step[which].old_pattern = 0; step[which].step_pos = 0; + switch ( step[which].type ) { default: case STARPOINT_48STEP_REEL: /* STARPOINT RMxxx */ @@ -129,6 +145,7 @@ void stepper_config(running_machine &machine, int which, const stepper_interface state_save_register_item(machine, "stepper", NULL, which, step[which].step_pos); state_save_register_item(machine, "stepper", NULL, which, step[which].max_steps); state_save_register_item(machine, "stepper", NULL, which, step[which].type); + state_save_register_item(machine, "stepper", NULL, which, step[which].reverse); } /////////////////////////////////////////////////////////////////////////// @@ -219,13 +236,12 @@ int stepper_update(int which, UINT8 pattern) step[which].phase = (step[which].step_pos % 8); step[which].pattern = pattern; -// index = (step[which].old_pattern << 4) | pattern; switch ( step[which].type ) { default: case STARPOINT_48STEP_REEL : /* STARPOINT RMxxx */ case STARPOINT_144STEPS_DICE : /* STARPOINT 1DCU DICE mechanism */ - steps = StarpointStepTab[step[which].phase][pattern]; + steps = StarpointStepTab[step[which].phase][pattern];//[(step[which].old_pattern << 4) | pattern];// break; case BARCREST_48STEP_REEL : /* Barcrest reel units have different windings */ steps = BarcrestStepTab[step[which].phase][pattern]; @@ -233,21 +249,26 @@ int stepper_update(int which, UINT8 pattern) case MPU3_48STEP_REEL : /* Same unit as above, but different interface (2 active lines, not 4)*/ steps = MPU3StepTab[step[which].phase][pattern]; } - #if 0 /* Assists with new index generation */ - if ( which ==3 )logerror("which %d Index %d Steps %d Phase %d Pattern Old %02X New %02X\n",which,index,steps,(step[which].step_pos % 8),step[which].old_pattern,step[which].pattern); + #if 1 /* Assists with new index generation */ + if ( which ==1 )logerror("which %d Steps %d Phase %d Pattern Old %02X New %02X\n",which,steps,(step[which].phase),step[which].old_pattern,step[which].pattern); #endif - if ( steps ) + if (step[which].reverse) { - pos = step[which].step_pos + steps; - if ( pos > step[which].max_steps ) pos -= step[which].max_steps; - if ( pos < 0 ) pos += step[which].max_steps; - - step[which].step_pos = pos; - update_optic(which); + pos = (step[which].step_pos - steps + step[which].max_steps) % step[which].max_steps; + } + else + { + pos = (step[which].step_pos + steps + step[which].max_steps) % step[which].max_steps; + } + if (pos != step[which].step_pos) + { changed++; } + + step[which].step_pos = pos; + update_optic(which); } return changed; } diff --git a/src/mame/machine/steppers.h b/src/mame/machine/steppers.h index 0e6250b3f7b..c5809eb5bd5 100644 --- a/src/mame/machine/steppers.h +++ b/src/mame/machine/steppers.h @@ -5,10 +5,6 @@ // Emulates : 48 step motors driven with full step or half step // // also emulates the index optic // // // -// 26-01-2007: J. Wallace - Rewritten to make it more flexible // -// and to allow indices to be set in drivers // -// 29-12-2006: J. Wallace - Added state save support // -// 05-03-2004: Re-Animator // // // // TODO: add different types of stepper motors if needed // // someone who understands the device system may want to convert // @@ -34,6 +30,7 @@ struct _stepper_interface INT16 index_start;/* start position of index (in half steps) */ INT16 index_end; /* end position of index (in half steps) */ INT16 index_patt; /* pattern needed on coils (0=don't care) */ + UINT8 reverse; /* Reel spins in reverse (symbols appear from the bottom) */ }; extern const stepper_interface starpoint_interface_48step; diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 4ddfca24b1e..e3c8cfb9c31 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -10669,6 +10669,10 @@ screenpl screenp1 screenp2 +// MPU3 +mpu3utst +m_hprvpr + // MPU4 m_oldtmr // Barcrest - highly prelim m_ccelbr diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 4eeb070289a..30e8ad5977f 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -483,6 +483,7 @@ $(MAMEOBJ)/atlus.a: \ $(DRIVERS)/powerins.o $(VIDEO)/powerins.o \ $(MAMEOBJ)/barcrest.a: \ + $(DRIVERS)/mpu3.o \ $(DRIVERS)/mpu4.o \ $(DRIVERS)/mpu5.o \ $(VIDEO)/awpvid.o \