Added reverse-spin support to the stepper motor simulator [James Wallace]

mpu4.c: Documented MOD 4 OKI program card ROM banking and improved the BwB characteriser emulation. [James Wallace]


New games added as GAME_NOT_WORKING:
------------------------------------

MPU3 Unit Test (Program 5)
Hyper Viper
This commit is contained in:
Phil Bennett 2011-04-15 11:59:49 +00:00
parent a8367e4f80
commit 4ab59dc7d1
10 changed files with 1411 additions and 2418 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -207,7 +207,7 @@ static WRITE8_HANDLER( reel12_w )
{
bfm_sc1_state *state = space->machine().driver_data<bfm_sc1_state>();
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<bfm_sc1_state>();
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<bfm_sc1_state>();
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

938
src/mame/drivers/mpu3.c Normal file
View File

@ -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<mpu3_state>();
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<mpu3_state>();
int pattern = 0,reel;
for (reel = 0; reel < 6; reel++)
{
stepper_reset_position(reel);
if (stepper_optic_state(reel)) pattern |= 1<<reel;
}
state->m_optic_pattern = pattern;
}
static MACHINE_RESET( mpu3 )
{
mpu3_state *state = machine.driver_data<mpu3_state>();
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<mpu3_state>();
state->m_ic11_active=0;
ic21_output(state,0);
}
static READ8_DEVICE_HANDLER( pia_ic3_porta_r )
{
mpu3_state *state = device->machine().driver_data<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
state->m_ic3_data = data;
}
static WRITE_LINE_DEVICE_HANDLER( pia_ic5_ca2_w )
{
mpu3_state *mstate = device->machine().driver_data<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
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<mpu3_state>();
/* 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<mpu3_state>();
// 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<mpu3_state>();
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 )

View File

@ -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<<reel;
if(!state->m_reel_mux)
{
if (stepper_optic_state(reel)) pattern |= 1<<reel;
}
}
state->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<mpu4_state>();
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<mpu4_state>();
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<mpu4_state>();
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<mpu4_state>();
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<mpu4_state>();
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) )

View File

@ -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<mpu4_state>();
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 )

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;

View File

@ -10669,6 +10669,10 @@ screenpl
screenp1
screenp2
// MPU3
mpu3utst
m_hprvpr
// MPU4
m_oldtmr // Barcrest - highly prelim
m_ccelbr

View File

@ -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 \