BFM Scorpion 4 Hardware: [David Haywood]

- General update which fleshes out some of the 68307 code (not 100% correct hookups, just improved logging and enough to get us somewhere).

- Added various devices to the SC4 emulation, added a default layout showing the VFD, to which most of the earlier games will now write 'Initializing'.  Timers and other devices still need to be implemented properly before they actually initialize. 

- Put the actual SC4 hardware emulation in drivers/bfm_sc4h.c so that it doesn't get lost in the swamp of sets (scrolling through a file is quite hard when it's almost entirely set definitions)
This commit is contained in:
Scott Stone 2012-04-03 17:21:33 +00:00
parent 5f26aaac79
commit 2b6903b343
14 changed files with 919 additions and 220 deletions

2
.gitattributes vendored
View File

@ -2137,6 +2137,7 @@ src/mame/drivers/bfcobra.c svneol=native#text/plain
src/mame/drivers/bfm_sc1.c svneol=native#text/plain
src/mame/drivers/bfm_sc2.c svneol=native#text/plain
src/mame/drivers/bfm_sc4.c svneol=native#text/plain
src/mame/drivers/bfm_sc4h.c svneol=native#text/plain
src/mame/drivers/bfm_sc5.c svneol=native#text/plain
src/mame/drivers/bfm_swp.c svneol=native#text/plain
src/mame/drivers/bfmsys83.c svneol=native#text/plain
@ -3972,6 +3973,7 @@ src/mame/layout/babypkr.lay svneol=native#text/plain
src/mame/layout/beaminv.lay svneol=native#text/plain
src/mame/layout/bfm_sc1.lay svneol=native#text/plain
src/mame/layout/bfm_sc2.lay svneol=native#text/plain
src/mame/layout/bfm_sc4.lay svneol=native#text/native
src/mame/layout/bigdeal.lay svneol=native#text/plain
src/mame/layout/bingowng.lay svneol=native#text/plain
src/mame/layout/blckjack.lay svneol=native#text/plain

View File

@ -32,6 +32,11 @@ READ16_HANDLER( m68307_internal_sim_r )
return 0x0000;
}
m68307_porta_read_callback m_m68307_porta_r;
m68307_porta_write_callback m_m68307_porta_w;
m68307_portb_read_callback m_m68307_portb_r;
m68307_portb_write_callback m_m68307_portb_w;
WRITE16_HANDLER( m68307_internal_sim_w )
{
m68ki_cpu_core *m68k = m68k_get_safe_token(&space->device());
@ -39,13 +44,61 @@ WRITE16_HANDLER( m68307_internal_sim_w )
assert(sim != NULL);
int pc = cpu_get_pc(&space->device());
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x)\n", pc, offset*2,data,mem_mask);
if (sim)
{
switch (offset<<1)
{
case m68307SIM_PACNT:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port A (8-bit) Control Register - PACNT)\n", pc, offset*2,data,mem_mask);
sim->write_pacnt(data,mem_mask);
break;
case m68307SIM_PADDR:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port A (8-bit) Direction Register - PADDR)\n", pc, offset*2,data,mem_mask);
sim->write_paddr(data,mem_mask);
break;
case m68307SIM_PADAT:
sim->write_padat(space, data,mem_mask);
break;
case m68307SIM_PBCNT:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port B (16-bit) Control Register - PBCNT)\n", pc, offset*2,data,mem_mask);
sim->write_pbcnt(data,mem_mask);
break;
case m68307SIM_PBDDR:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port B (16-bit) Direction Register - PBDDR)\n", pc, offset*2,data,mem_mask);
sim->write_pbddr(data,mem_mask);
break;
case m68307SIM_PBDAT:
sim->write_pbdat(space, data,mem_mask);
break;
case m68307SIM_LICR1:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Latched Interrupt Control Register 1 - LICR1)\n", pc, offset*2,data,mem_mask);
sim->write_licr1(data,mem_mask);
break;
case m68307SIM_LICR2:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Latched Interrupt Control Register 2 - LICR2)\n", pc, offset*2,data,mem_mask);
sim->write_licr2(data,mem_mask);
break;
case m68307SIM_PICR:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Peripheral Interrupt Control Register - PICR)\n", pc, offset*2,data,mem_mask);
sim->write_picr(data,mem_mask);
break;
case m68307SIM_PIVR:
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Peripheral Interrupt Vector Register - PIVR)\n", pc, offset*2,data,mem_mask);
sim->write_pivr(data,mem_mask);
break;
case m68307SIM_BR0:
COMBINE_DATA(&sim->m_br[0]);
break;
@ -70,11 +123,124 @@ WRITE16_HANDLER( m68307_internal_sim_w )
case m68307SIM_OR3:
COMBINE_DATA(&sim->m_or[3]);
break;
default :
logerror("%08x m68307_internal_sim_w %08x, %04x (%04x)\n", pc, offset*2,data,mem_mask);
break;
}
}
}
void m68307_sim::write_pacnt(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_pacnt);
}
void m68307_sim::write_paddr(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_paddr);
}
void m68307_sim::write_padat(address_space *space, UINT16 data, UINT16 mem_mask)
{
int pc = cpu_get_pc(&space->device());
m68ki_cpu_core *m68k = m68k_get_safe_token(&space->device());
COMBINE_DATA(&m_padat);
if (m68k->m_m68307_porta_w)
{
m68k->m_m68307_porta_w(space, 0, data);
}
else
{
logerror("%08x m68307_internal_sim_w %04x (%04x) (Port A (8-bit) Data Register - PADAT)\n", pc, data,mem_mask);
}
}
void m68307_sim::write_pbcnt(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_pbcnt);
}
void m68307_sim::write_pbddr(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_pbddr);
}
void m68307_sim::write_pbdat(address_space *space, UINT16 data, UINT16 mem_mask)
{
int pc = cpu_get_pc(&space->device());
m68ki_cpu_core *m68k = m68k_get_safe_token(&space->device());
COMBINE_DATA(&m_pbdat);
if (m68k->m_m68307_portb_w)
{
m68k->m_m68307_portb_w(space, 0, data, mem_mask);
}
else
{
logerror("%08x m68307_internal_sim_w %04x (%04x) (Port B (16-bit) Data Register - PBDAT)\n", pc, data,mem_mask);
}
}
void m68307_sim::write_licr1(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_licr1);
data = m_licr1;
logerror("m_licr1 value %04x : Details :\n", data);
logerror("int4ipl %01x\n", (data>>0)&7);
logerror("pir4 %01x\n", (data>>3)&1);
logerror("int3ipl %01x\n", (data>>4)&7);
logerror("pir3 %01x\n", (data>>7)&1);
logerror("int2ipl %01x\n", (data>>8)&7);
logerror("pir2 %01x\n", (data>>11)&1);
logerror("int1ipl %01x\n", (data>>12)&7);
logerror("pir1 %01x\n", (data>>15)&1);
logerror("\n");
}
void m68307_sim::write_licr2(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_licr2);
data = m_licr2;
logerror("m_licr2 value %04x : Details :\n", data);
logerror("int8ipl %01x\n", (data>>0)&7);
logerror("pir8 %01x\n", (data>>3)&1);
logerror("int7ipl %01x\n", (data>>4)&7);
logerror("pir7 %01x\n", (data>>7)&1);
logerror("int6ipl %01x\n", (data>>8)&7);
logerror("pir6 %01x\n", (data>>11)&1);
logerror("int5ipl %01x\n", (data>>12)&7);
logerror("pir5 %01x\n", (data>>15)&1);
logerror("\n");
}
void m68307_sim::write_picr(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_picr);
data = m_picr;
logerror("picr value %04x : Details :\n", data);
logerror("mbipl %01x\n", (data>>0)&7);
logerror("uaipl %01x\n", (data>>4)&7);
logerror("t2ipl %01x\n", (data>>8)&7);
logerror("t1ipl %01x\n", (data>>12)&7);
logerror("\n");
}
void m68307_sim::write_pivr(UINT16 data, UINT16 mem_mask)
{
COMBINE_DATA(&m_pivr);
data = m_pivr;
logerror("pivr value %04x : Details :\n", data);
logerror("unused %01x\n", (data>>0)&0xf);
logerror("high vector %01x\n", (data>>4)&0xf);
}
void m68307_sim::reset(void)
{
for (int i=0;i<4;i++)

View File

@ -3,6 +3,21 @@
READ16_HANDLER( m68307_internal_sim_r );
WRITE16_HANDLER( m68307_internal_sim_w );
/* ports */
#define m68307SIM_PACNT (0x10)
#define m68307SIM_PADDR (0x12)
#define m68307SIM_PADAT (0x14)
#define m68307SIM_PBCNT (0x16)
#define m68307SIM_PBDDR (0x18)
#define m68307SIM_PBDAT (0x1a)
/* interrupt logic */
#define m68307SIM_LICR1 (0x20)
#define m68307SIM_LICR2 (0x22)
#define m68307SIM_PICR (0x24)
#define m68307SIM_PIVR (0x26)
/* used for the CS logic */
#define m68307SIM_BR0 (0x40)
#define m68307SIM_OR0 (0x42)
@ -17,8 +32,37 @@ class m68307_sim
{
public:
UINT16 m_pacnt; // 8-bit
UINT16 m_paddr; // 8-bit
UINT16 m_padat; // 8-bit
UINT16 m_pbcnt;
UINT16 m_pbddr;
UINT16 m_pbdat;
UINT16 m_pivr; // 8-bit
UINT16 m_br[4];
UINT16 m_or[4];
UINT16 m_picr;
UINT16 m_licr1;
UINT16 m_licr2;
void write_pacnt(UINT16 data, UINT16 mem_mask);
void write_paddr(UINT16 data, UINT16 mem_mask);
void write_padat(address_space *space, UINT16 data, UINT16 mem_mask);
void write_pbcnt(UINT16 data, UINT16 mem_mask);
void write_pbddr(UINT16 data, UINT16 mem_mask);
void write_pbdat(address_space *space, UINT16 data, UINT16 mem_mask);
void write_licr1(UINT16 data, UINT16 mem_mask);
void write_licr2(UINT16 data, UINT16 mem_mask);
void write_picr(UINT16 data, UINT16 mem_mask);
void write_pivr(UINT16 data, UINT16 mem_mask);
void reset(void);
};

View File

@ -13,7 +13,20 @@ READ16_HANDLER( m68307_internal_timer_r )
if (timer)
{
int pc = cpu_get_pc(&space->device());
logerror("%08x m68307_internal_timer_r %08x, (%04x)\n", pc, offset*2,mem_mask);
int which = offset & 0x8;
switch (offset&0x7)
{
case m68307TIMER_TCN: /* 0x3 (0x126 / 0x136) */
//if (pc!=0x2182e) logerror("%08x m68307_internal_timer_r %08x (%04x) (TCN - Timer Counter for timer %d)\n", pc, offset*2,mem_mask, which);
return timer->read_tcn(mem_mask, which);
break;
default:
logerror("%08x m68307_internal_timer_r %08x, (%04x)\n", pc, offset*2,mem_mask);
break;
}
}
return 0x0000;
@ -28,15 +41,209 @@ WRITE16_HANDLER( m68307_internal_timer_w )
if (timer)
{
int pc = cpu_get_pc(&space->device());
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x)\n", pc, offset*2,data,mem_mask);
int which = offset & 0x8;
switch (offset&0x7)
{
case m68307TIMER_TMR: /* 0x0 (0x120 / 0x130) */
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TMR - Timer Mode Register for timer %d)\n", pc, offset*2,data,mem_mask, which);
timer->write_tmr(data, mem_mask, which);
break;
case m68307TIMER_TRR: /* 0x1 (0x122 / 0x132) */
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TRR - Timer Reference Register for timer %d)\n", pc, offset*2,data,mem_mask, which);
timer->write_trr(data, mem_mask, which);
break;
case m68307TIMER_TCR: /* 0x2 (0x124 / 0x134) */
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TCR - Timer Capture Register for timer %d) (illegal, read-only)\n", pc, offset*2,data,mem_mask, which);
break;
case m68307TIMER_TCN: /* 0x3 (0x126 / 0x136) */
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TCN - Timer Counter for timer %d)\n", pc, offset*2,data,mem_mask, which);
break;
case m68307TIMER_TER: /* 0x4 (0x128 / 0x138) */
/* 8-bit only!! */
//logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TER - Timer Event Register for timer %d)\n", pc, offset*2,data,mem_mask, which);
timer->write_ter(data, mem_mask, which);
break;
case m68307TIMER_WRR: /* 0x5 (0x12a / 0x13a) */
if (which==0)
{
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (WRR - Watchdog Reference Register)\n", pc, offset*2,data,mem_mask);
}
else
{
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", pc, offset*2,data,mem_mask);
}
break;
case m68307TIMER_WCR: /* 0x6 (0x12c / 0x13c) */
if (which==0)
{
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (WRR - Watchdog Counter Register)\n", pc, offset*2,data,mem_mask);
}
else
{
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", pc, offset*2,data,mem_mask);
}
break;
case m68307TIMER_XXX: /* 0x7 (0x12e / 0x13e) */
logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", pc, offset*2,data,mem_mask);
break;
}
}
// printf("%d\n", (UINT32)m68k->device->total_cycles());
}
static TIMER_CALLBACK( m68307_timer0_callback )
{
// printf("timer0\n");
legacy_cpu_device *dev = (legacy_cpu_device *)ptr;
m68ki_cpu_core* m68k = m68k_get_safe_token(dev);
int prioritylevel = (m68k->m68307SIM->m_picr & 0x7000)>>12;
int vector = (m68k->m68307SIM->m_pivr & 0x00f0) | 0xa;
m68307_single_timer* tptr = &m68k->m68307TIMER->singletimer[0];
tptr->regs[m68307TIMER_TMR] |= 0x2;
m68307_set_interrupt(dev, prioritylevel, vector);
tptr->mametimer->adjust(m68k->device->cycles_to_attotime(100000));
}
static TIMER_CALLBACK( m68307_timer1_callback )
{
// int prioritylevel = (m68k->m68307SIM->m_picr & 0x0700)>>8;
// int vector = (m68k->m68307SIM->m_pivr & 0x00f0) | 0xb;
printf("timer1\n");
}
static TIMER_CALLBACK( m68307_wd_timer_callback )
{
printf("wd timer\n");
}
void m68307_timer::init(legacy_cpu_device *device)
{
m68ki_cpu_core *m68k;
m68k = m68k_get_safe_token(device);
m68307_single_timer* tptr;
tptr = &singletimer[0];
tptr->mametimer = device->machine().scheduler().timer_alloc(FUNC(m68307_timer0_callback), device);
tptr = &singletimer[1];
tptr->mametimer = device->machine().scheduler().timer_alloc(FUNC(m68307_timer1_callback), device);
parent = device;
wd_mametimer = device->machine().scheduler().timer_alloc(FUNC(m68307_wd_timer_callback), device);
}
UINT16 m68307_timer::read_tcn(UINT16 mem_mask, int which)
{
// return 0;
return 0x411d;
// return 0x3a98;
}
void m68307_timer::write_ter(UINT16 data, UINT16 mem_mask, int which)
{
// m68ki_cpu_core* m68k = m68k_get_safe_token(parent);
m68307_single_timer* tptr = &singletimer[which];
// UINT16 ter = tptr->regs[m68307TIMER_TMR;
if (data & 0x2) tptr->regs[m68307TIMER_TMR] &= ~0x2;
// COMBINE_DATA(&tptr->regs[m68307TIMER_TMR]);
}
void m68307_timer::write_tmr(UINT16 data, UINT16 mem_mask, int which)
{
m68ki_cpu_core* m68k = m68k_get_safe_token(parent);
m68307_single_timer* tptr = &singletimer[which];
COMBINE_DATA(&tptr->regs[m68307TIMER_TMR]);
data = tptr->regs[m68307TIMER_TMR];
int ps = data & (0xff00)>>8;
int ce = data & (0x00c0)>>6;
int om = data & (0x0020)>>5;
int ori = data & (0x0010)>>4;
int frr = data & (0x0008)>>3;
int iclk = data & (0x0006)>>1;
int rst = data & (0x0001)>>0;
logerror("tmr value %04x : Details :\n", data);
logerror("prescale %d\n", ps);
logerror("(clock divided by %d)\n", ps+1);
logerror("capture edge / enable interrupt %d\n", ce);
if (ce==0x0) logerror("(disable interrupt on capture event)\n");
if (ce==0x1) logerror("(capture on rising edge only + enable capture interrupt)\n");
if (ce==0x2) logerror("(capture on falling edge only + enable capture interrupt)\n");
if (ce==0x3) logerror("(capture on any edge + enable capture interrupt)\n");
logerror("output mode %d\n", om);
if (om==0x0) logerror("(active-low pulse for one cycle))\n");
if (om==0x1) logerror("(toggle output)\n");
logerror("output reference interrupt %d\n", ori);
if (ori==0x0) logerror("(disable reference interrupt)\n");
if (ori==0x1) logerror("(enable interrupt on reaching reference value))\n");
logerror("free running %d\n", frr);
if (frr==0x0) logerror("(free running mode, counter continues after value reached)\n");
if (frr==0x1) logerror("(restart mode, counter resets after value reached)\n");
logerror("interrupt clock source %d\n", iclk);
if (iclk==0x0) logerror("(stop count)\n");
if (iclk==0x1) logerror("(master system clock)\n");
if (iclk==0x2) logerror("(master system clock divided by 16)\n");
if (iclk==0x3) logerror("(TIN Pin)\n");
logerror("reset %d\n", rst);
if (rst==0x0) logerror("(timer is reset)\n");
if (rst==0x1) logerror("(timer is running)\n");
tptr->mametimer->adjust(m68k->device->cycles_to_attotime(100000));
logerror("\n");
}
void m68307_timer::write_trr(UINT16 data, UINT16 mem_mask, int which)
{
m68307_single_timer* tptr = &singletimer[which];
COMBINE_DATA(&tptr->regs[m68307TIMER_TRR]);
}
void m68307_timer::reset(void)
{
for (int i=0;i<2;i++)
{
m68307_single_timer* tptr = &timer[i];
m68307_single_timer* tptr = &singletimer[i];
tptr->regs[m68307TIMER_TMR] = 0x0000;
tptr->regs[m68307TIMER_TRR] = 0xffff;
@ -47,6 +254,11 @@ void m68307_timer::reset(void)
tptr->regs[m68307TIMER_WCR] = 0xffff;
tptr->regs[m68307TIMER_XXX] = 0;
tptr->enabled = false;
tptr->mametimer->adjust(attotime::never);
}
wd_mametimer->adjust(attotime::never);
}

View File

@ -15,12 +15,24 @@ struct m68307_single_timer
{
UINT16 regs[0x8];
bool enabled;
emu_timer *mametimer;
};
class m68307_timer
{
public:
m68307_single_timer timer[2];
m68307_single_timer singletimer[2];
emu_timer *wd_mametimer;
legacy_cpu_device *parent;
void write_tmr(UINT16 data, UINT16 mem_mask, int which);
void write_trr(UINT16 data, UINT16 mem_mask, int which);
void write_ter(UINT16 data, UINT16 mem_mask, int which);
UINT16 read_tcn(UINT16 mem_mask, int which);
void init(legacy_cpu_device *device);
void reset(void);
};

View File

@ -101,6 +101,12 @@ typedef void (*m68k_cmpild_func)(device_t *device, UINT32 data, UINT8 reg);
typedef void (*m68k_rte_func)(device_t *device);
typedef int (*m68k_tas_func)(device_t *device);
typedef UINT8 (*m68307_porta_read_callback)(address_space *space, offs_t offset);
typedef void (*m68307_porta_write_callback)(address_space *space, offs_t offset, UINT8 data);
typedef UINT16 (*m68307_portb_read_callback)(address_space *space, offs_t offset, UINT16 mem_mask);
typedef void (*m68307_portb_write_callback)(address_space *space, offs_t offset, UINT16 data, UINT16 mem_mask);
DECLARE_LEGACY_CPU_DEVICE(M68000, m68000);
DECLARE_LEGACY_CPU_DEVICE(M68301, m68301);
@ -133,7 +139,10 @@ void m68k_set_cmpild_callback(device_t *device, m68k_cmpild_func callback);
void m68k_set_rte_callback(device_t *device, m68k_rte_func callback);
void m68k_set_tas_callback(device_t *device, m68k_tas_func callback);
UINT16 m68k_get_fc(device_t *device);
void m68307_set_port_callbacks(device_t *device, m68307_porta_read_callback porta_r, m68307_porta_write_callback m_m68307_porta_w, m68307_portb_read_callback portb_r, m68307_portb_write_callback m_m68307_portb_w);
UINT16 m68307_get_cs(device_t *device, offs_t address);
void m68307_set_interrupt(device_t *device, int level, int vector);
typedef int (*instruction_hook_t)(device_t *device, offs_t curpc);
void m68k_set_instruction_hook(device_t *device, instruction_hook_t ihook);

View File

@ -1781,6 +1781,16 @@ UINT16 m68k_get_fc(device_t *device)
return m68k->mmu_tmp_fc;
}
void m68307_set_port_callbacks(device_t *device, m68307_porta_read_callback porta_r, m68307_porta_write_callback porta_w, m68307_portb_read_callback portb_r, m68307_portb_write_callback portb_w)
{
m68ki_cpu_core *m68k = m68k_get_safe_token(device);
m68k->m_m68307_porta_r = porta_r;
m68k->m_m68307_porta_w = porta_w;
m68k->m_m68307_portb_r = portb_r;
m68k->m_m68307_portb_w = portb_w;
}
UINT16 m68307_get_cs(device_t *device, offs_t address)
{
m68ki_cpu_core *m68k = m68k_get_safe_token(device);
@ -1920,6 +1930,10 @@ CPU_GET_INFO( m68301 )
}
}
void m68307_set_interrupt(device_t *device, int level, int vector)
{
device_set_input_line_and_vector(device, level, HOLD_LINE, vector);
}
static CPU_INIT( m68307 )
{
@ -1938,6 +1952,8 @@ static CPU_INIT( m68307 )
m68k->m68307SERIAL = new m68307_serial();
m68k->m68307TIMER = new m68307_timer();
m68k->m68307TIMER->init(device);
m68k->m68307SIM->reset();
m68k->m68307MBUS->reset();
m68k->m68307SERIAL->reset();
@ -1947,6 +1963,8 @@ static CPU_INIT( m68307 )
m68k->m68307_base = 0xbfff;
m68k->m68307_scrhigh = 0x0007;
m68k->m68307_scrlow = 0xf010;
m68307_set_port_callbacks(device, 0,0,0,0);
}
static READ16_HANDLER( m68307_internal_base_r )
@ -2025,7 +2043,7 @@ CPU_GET_INFO( m68307 )
{
switch (state)
{
case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68307); break;

View File

@ -745,6 +745,13 @@ public:
/* 68308 / 68340 internal address map */
address_space *internal;
/* callbacks for internal ports */
m68307_porta_read_callback m_m68307_porta_r;
m68307_porta_write_callback m_m68307_porta_w;
m68307_portb_read_callback m_m68307_portb_r;
m68307_portb_write_callback m_m68307_portb_w;
/* external instruction hook (does not depend on debug mode) */
typedef int (*instruction_hook_t)(device_t *device, offs_t curpc);

View File

@ -4,226 +4,17 @@
Skeleton Driver
THIS DRIVER IS NONE FUNCTIONAL, THERE IS NO EMULATION CODE.
THIS DRIVER IS NOT WORKING
-----------------
what's the difference between this and Scorpion 5? Later revisons of many games appear
to be on the latter.
This file contains the set lists only, for the actual hardware
emulation see bfm_sc4h.c
Scorpion 4:::
Main CPU is a MC68307FG16, present on Motherboard
Configuration is SC4 motherboard + game card
The game card contains the program roms, sound rom and YMZ280B
Adder 4 video board adds an additional card with a MC68340PV25E (25.175Mhz)
-------------------------------
This is currently a mess of Scorpion 4, Scorpion 5 and Scorpion 5 Adder 5 games.
I think some games might use multiple boards of different techs linked up via
serial ports, but I'm not sure
THIS NEEDS SORTING OUT, TIDYING UP and PROPERLY DOCUMENTING
Sorting Tips:
Scorpion 5 sets seem to have SC5 as the first bytes (when interleaved)
Larger roms seem to be Adder 5 (and also have SC5 at the start)
Other roms are SC4? Some games are on both platforms - check..
even within many 'SC5' sets there are roms without SC5 in the header
these are either SC4 versions, or maybe some additional HW? - check...
SC5 stuff seems to use opcodes which don't exist in the 68020, are these
68340 based, or something else with additional opcodes (coldfire?)
-------------------------------
*/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "includes/bfm_sc45.h"
#include "sound/ymz280b.h"
class sc4_state : public driver_device
{
public:
sc4_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu")
{
}
UINT16* m_cpuregion;
UINT16* m_mainram;
// devices
required_device<cpu_device> m_maincpu;
DECLARE_READ16_MEMBER(sc4_mem_r);
DECLARE_WRITE16_MEMBER(sc4_mem_w);
};
class sc4_adder4_state : public sc4_state
{
public:
sc4_adder4_state(const machine_config &mconfig, device_type type, const char *tag)
: sc4_state(mconfig, type, tag),
m_adder4cpu(*this, "adder4")
{ }
// devices
required_device<cpu_device> m_adder4cpu;
};
READ16_MEMBER(sc4_state::sc4_mem_r)
{
int pc = cpu_get_pc(&space.device());
int cs = m68307_get_cs(m_maincpu, offset * 2);
int base = 0, end = 0;
// if (!(debugger_access())) printf("cs is %d\n", cs);
switch ( cs )
{
case 1:
if (offset<0x100000/2)
return m_cpuregion[offset];
else
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
break;
case 2:
base = 0x800000/2;
end = base + 0x100000 / 2;
if ((offset>=base) && (offset<end))
{
offset-=base;
return(m_mainram[offset]);
}
else
{
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
}
break;
case 3:
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
return 0x0000;
break;
case 4:
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
return 0x0000;
break;
default:
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d (invalid?)\n", pc, offset*2, mem_mask, cs);
}
return 0x0000;
}
WRITE16_MEMBER(sc4_state::sc4_mem_w)
{
int pc = cpu_get_pc(&space.device());
int cs = m68307_get_cs(m_maincpu, offset * 2);
int base = 0, end = 0;
switch ( cs )
{
case 1:
if (offset<0x100000/2)
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d (ROM WRITE?!)\n", pc, offset*2, data, mem_mask, cs);
else
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
break;
case 2:
base = 0x800000/2;
end = base + 0x100000 / 2;
if ((offset>=base) && (offset<end))
{
offset-=base;
COMBINE_DATA(&m_mainram[offset]);
}
else
{
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
}
break;
case 3:
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
break;
case 4:
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
break;
default:
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d (invalid?)\n", pc, offset*2, data, mem_mask, cs);
}
}
static ADDRESS_MAP_START( sc4_map, AS_PROGRAM, 16, sc4_state )
AM_RANGE(0x000000000, 0xffffffff) AM_READWRITE(sc4_mem_r, sc4_mem_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( sc4_adder4_map, AS_PROGRAM, 32, sc4_adder4_state )
AM_RANGE(0x000000, 0x2fffff) AM_ROM
ADDRESS_MAP_END
static INPUT_PORTS_START( sc4 )
INPUT_PORTS_END
static MACHINE_START( sc4 )
{
sc4_state *state = machine.driver_data<sc4_state>();
state->m_cpuregion = (UINT16*)machine.region( "maincpu" )->base();
state->m_mainram = (UINT16*)auto_alloc_array_clear(machine, UINT16, 0x100000);
}
static void bfm_sc4_irqhandler(device_t *device, int state)
{
logerror("YMZ280 is generating an interrupt. State=%08x\n",state);
}
static const ymz280b_interface ymz280b_config =
{
bfm_sc4_irqhandler
};
static MACHINE_CONFIG_START( sc4, sc4_state )
MCFG_CPU_ADD("maincpu", M68307, 16000000) // 68307! (EC000 core)
MCFG_CPU_PROGRAM_MAP(sc4_map)
MCFG_MACHINE_START( sc4 )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz)
MCFG_SOUND_CONFIG(ymz280b_config)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED_CLASS( sc4_adder4, sc4, sc4_adder4_state )
MCFG_CPU_ADD("adder4", M68340, 25175000) // 68340 (CPU32 core)
MCFG_CPU_PROGRAM_MAP(sc4_adder4_map)
MACHINE_CONFIG_END
ROM_START( sc4tst )

365
src/mame/drivers/bfm_sc4h.c Normal file
View File

@ -0,0 +1,365 @@
/*
Scorpion 4 Hardware Platform (c)1996 Bell Fruit Manufacturing
Skeleton Driver
THIS DRIVER IS NOT WORKING
-----------------
Scorpion 4:::
Main CPU is a MC68307FG16, present on Motherboard
Configuration is SC4 motherboard + game card
The game card contains the program roms, sound rom and YMZ280B
Adder 4 video board adds an additional card with a MC68340PV25E (25.175Mhz)
-------------------------------
This file contains the hardware emulation, for the supported sets
see bfm_sc4.c
*/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "includes/bfm_sc45.h"
#include "sound/ymz280b.h"
#include "machine/68681.h"
#include "bfm_sc4.lh"
#include "machine/bfm_bd1.h"
class sc4_state : public driver_device
{
public:
sc4_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu")
{
}
UINT16* m_cpuregion;
UINT16* m_mainram;
// devices
device_t* m_duart;
required_device<cpu_device> m_maincpu;
// serial vfd
int vfd_enabled;
bool vfd_old_clock;
UINT8 vfd_ser_value;
int vfd_ser_count;
};
class sc4_adder4_state : public sc4_state
{
public:
sc4_adder4_state(const machine_config &mconfig, device_type type, const char *tag)
: sc4_state(mconfig, type, tag),
m_adder4cpu(*this, "adder4")
{ }
// devices
required_device<cpu_device> m_adder4cpu;
};
static READ16_HANDLER( sc4_mem_r )
{
sc4_state *state = space->machine().driver_data<sc4_state>();
int pc = cpu_get_pc(&space->device());
int cs = m68307_get_cs(state->m_maincpu, offset * 2);
int base = 0, end = 0;
// if (!(space->debugger_access())) printf("cs is %d\n", cs);
switch ( cs )
{
case 1:
if (offset<0x100000/2)
return state->m_cpuregion[offset];
else
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
break;
case 2:
base = 0x800000/2;
end = base + 0x100000 / 2;
if ((offset>=base) && (offset<end))
{
offset-=base;
return(state->m_mainram[offset]);
}
else
{
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
}
break;
case 3:
base = 0xc00000/2;
end = base + 0x20 / 2;
if ((offset>=base) && (offset<end))
{
offset-=base;
return duart68681_r(state->m_duart,offset);
}
else
{
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
return 0x0000;
}
break;
case 4:
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d\n", pc, offset*2, mem_mask, cs);
return 0xffff;
break;
default:
logerror("%08x maincpu read access offset %08x mem_mask %04x cs %d (invalid?)\n", pc, offset*2, mem_mask, cs);
}
return 0x0000;
}
static WRITE16_HANDLER( sc4_mem_w )
{
sc4_state *state = space->machine().driver_data<sc4_state>();
int pc = cpu_get_pc(&space->device());
int cs = m68307_get_cs(state->m_maincpu, offset * 2);
int base = 0, end = 0;
switch ( cs )
{
case 1:
if (offset<0x100000/2)
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d (ROM WRITE?!)\n", pc, offset*2, data, mem_mask, cs);
else
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
break;
case 2:
base = 0x800000/2;
end = base + 0x100000 / 2;
if ((offset>=base) && (offset<end))
{
offset-=base;
COMBINE_DATA(&state->m_mainram[offset]);
}
else
{
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
}
break;
case 3:
base = 0xc00000/2;
end = base + 0x20 / 2;
if ((offset>=base) && (offset<end))
{
offset-=base;
duart68681_w(state->m_duart,offset,data&0x00ff);
}
else
{
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
}
break;
case 4:
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d\n", pc, offset*2, data, mem_mask, cs);
break;
default:
logerror("%08x maincpu write access offset %08x data %04x mem_mask %04x cs %d (invalid?)\n", pc, offset*2, data, mem_mask, cs);
}
}
static ADDRESS_MAP_START( sc4_map, AS_PROGRAM, 16, sc4_adder4_state )
AM_RANGE(0x0000000, 0xffffff) AM_READWRITE_LEGACY(sc4_mem_r, sc4_mem_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( sc4_adder4_map, AS_PROGRAM, 32, sc4_adder4_state )
AM_RANGE(0x000000, 0x2fffff) AM_ROM
ADDRESS_MAP_END
void bfm_sc4_reset_serial_vfd(running_machine &machine)
{
sc4_state *state = machine.driver_data<sc4_state>();
BFM_BD1_reset(0);
BFM_BD1_draw(0);
state->vfd_old_clock = false;
}
void bfm_sc4_write_serial_vfd(running_machine &machine, bool cs, bool clock, bool data)
{
sc4_state *state = machine.driver_data<sc4_state>();
// if we're turned on
if ( cs )
{
if ( !state->vfd_enabled )
{
bfm_sc4_reset_serial_vfd(machine);
state->vfd_old_clock = clock;
state->vfd_enabled = true;
}
else
{
// if the clock line changes
if ( clock != state->vfd_old_clock )
{
if ( !clock )
{
state->vfd_ser_value <<= 1;
if (data) state->vfd_ser_value |= 1;
state->vfd_ser_count++;
if ( state->vfd_ser_count == 8 )
{
state->vfd_ser_count = 0;
BFM_BD1_newdata(0, state->vfd_ser_value);
BFM_BD1_draw(0);
}
}
state->vfd_old_clock = clock;
}
}
}
else
{
state->vfd_enabled = false;
}
}
static WRITE16_HANDLER( bfm_sc4_68307_portb_w )
{
int pc = cpu_get_pc(&space->device());
//m68ki_cpu_core *m68k = m68k_get_safe_token(&space->device());
// serial output to the VFD at least..
logerror("%08x bfm_sc4_68307_portb_w %04x %04x\n", pc, data, mem_mask);
// this seems good for the earlier sets which use the VFD, but I think the later games use a generic DMD of some kind instead?
// we have game specific DMD roms in a couple of cases, is it possible ALL the later games are meant to have
// their own DMD roms rather than it being something generic? (if so we're missing a lot of DMD roms..)
bfm_sc4_write_serial_vfd(space->machine(), (data & 0x4000)?1:0, (data & 0x1000)?1:0, !(data & 0x2000)?1:0);
}
static MACHINE_START( sc4 )
{
sc4_state *state = machine.driver_data<sc4_state>();
state->m_cpuregion = (UINT16*)machine.region( "maincpu" )->base();
state->m_mainram = (UINT16*)auto_alloc_array_clear(machine, UINT16, 0x100000);
state->m_duart = machine.device("duart68681");
m68307_set_port_callbacks(machine.device("maincpu"), 0, 0, 0, bfm_sc4_68307_portb_w );
BFM_BD1_init(0);
}
static void bfm_sc4_irqhandler(device_t *device, int state)
{
logerror("YMZ280 is generating an interrupt. State=%08x\n",state);
}
static const ymz280b_interface ymz280b_config =
{
bfm_sc4_irqhandler
};
void bfm_sc4_duart_irq_handler(device_t *device, UINT8 vector)
{
logerror("bfm_sc4_duart_irq_handler\n");
};
void bfm_sc4_duart_tx(device_t *device, int channel, UINT8 data)
{
logerror("bfm_sc4_duart_irq_handler\n");
};
UINT8 bfm_sc4_duart_input_r(device_t *device)
{
logerror("bfm_sc4_duart_input_r\n");
return 0x2;
}
void bfm_sc4_duart_output_w(device_t *device, UINT8 data)
{
logerror("bfm_sc4_duart_output_w\n");
// cputag_set_input_line(device->machine(), "audiocpu", INPUT_LINE_RESET, data & 0x20 ? CLEAR_LINE : ASSERT_LINE);
}
static const duart68681_config bfm_sc4_duart68681_config =
{
bfm_sc4_duart_irq_handler,
bfm_sc4_duart_tx,
bfm_sc4_duart_input_r,
bfm_sc4_duart_output_w
};
MACHINE_CONFIG_START( sc4, sc4_state )
MCFG_CPU_ADD("maincpu", M68307, 16000000) // 68307! (EC000 core)
MCFG_CPU_PROGRAM_MAP(sc4_map)
MCFG_MACHINE_START( sc4 )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_DUART68681_ADD("duart68681", 16000000/4, bfm_sc4_duart68681_config) // ?? Mhz
MCFG_DEFAULT_LAYOUT(layout_bfm_sc4)
MCFG_SOUND_ADD("ymz", YMZ280B, 16000000) // ?? Mhz
MCFG_SOUND_CONFIG(ymz280b_config)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
MACHINE_CONFIG_END
MACHINE_CONFIG_DERIVED_CLASS( sc4_adder4, sc4, sc4_adder4_state )
MCFG_CPU_ADD("adder4", M68340, 25175000) // 68340 (CPU32 core)
MCFG_CPU_PROGRAM_MAP(sc4_adder4_map)
MACHINE_CONFIG_END
INPUT_PORTS_START( sc4 )
INPUT_PORTS_END

View File

@ -1,6 +1,11 @@
/* Scorpion 4 + 5 driver releated includes */
/* mainly used for stuff which is currently shared between sc4 / 5 sets to avoid duplication */
MACHINE_CONFIG_EXTERN( sc4 );
MACHINE_CONFIG_EXTERN( sc4_adder4 );
INPUT_PORTS_EXTERN( sc4 );
#define sc_ivply_others \
ROM_REGION( 0x400000, "ymz", ROMREGION_ERASE00 ) \
ROM_LOAD( "95004313.snd", 0x0000, 0x080000, CRC(28faed9e) SHA1(624d6cfcc97dd1950b5d908cde2e4d2eb6ea1dc6) ) \

View File

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<mamelayout version="2">
<element name="vfd0">
<led14segsc>
<color red="0" green="0.6" blue="1.0" />
</led14segsc>
</element>
<view name="VFD">
<backdrop name="vfd0" element="vfd0" state="0">
<bounds x="0" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd1" element="vfd0" state="0">
<bounds x="9" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd2" element="vfd0" state="0">
<bounds x="18" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd3" element="vfd0" state="0">
<bounds x="27" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd4" element="vfd0" state="0">
<bounds x="36" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd5" element="vfd0" state="0">
<bounds x="45" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd6" element="vfd0" state="0">
<bounds x="54" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd7" element="vfd0" state="0">
<bounds x="63" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd8" element="vfd0" state="0">
<bounds x="72" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd9" element="vfd0" state="0">
<bounds x="81" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd10" element="vfd0" state="0">
<bounds x="90" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd11" element="vfd0" state="0">
<bounds x="99" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd12" element="vfd0" state="0">
<bounds x="108" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd13" element="vfd0" state="0">
<bounds x="117" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd14" element="vfd0" state="0">
<bounds x="126" y="280" width="9" height="14"/>
</backdrop>
<backdrop name="vfd15" element="vfd0" state="0">
<bounds x="135" y="280" width="9" height="14"/>
</backdrop>
</view>
</mamelayout>

View File

@ -267,8 +267,8 @@ int BFM_BD1_newdata(int id, int data)
return 0;
}
data = '@';
change = BD1_setdata(id, bd1[id].user_def, data);
data = '@';
change = BD1_setdata(id, bd1[id].user_def, data);
}
else
{
@ -388,6 +388,9 @@ int BFM_BD1_newdata(int id, int data)
return change;
}
///////////////////////////////////////////////////////////////////////////
static void ScrollLeft(int id)

View File

@ -516,6 +516,7 @@ $(MAMEOBJ)/bfm.a: \
$(DRIVERS)/bfm_sc1.o \
$(DRIVERS)/bfm_sc2.o $(VIDEO)/bfm_adr2.o \
$(DRIVERS)/bfm_sc4.o \
$(DRIVERS)/bfm_sc4h.o \
$(DRIVERS)/bfm_sc5.o \
$(DRIVERS)/bfm_swp.o \
$(DRIVERS)/bfmsys83.o \
@ -1944,6 +1945,10 @@ $(DRIVERS)/bfm_sc2.o: $(LAYOUT)/bfm_sc2.lh \
$(LAYOUT)/sltblgpo.lh \
$(LAYOUT)/sltblgtk.lh
$(DRIVERS)/bfm_sc4.o: $(LAYOUT)/bfm_sc4.lh
$(DRIVERS)/bfm_sc4h.o: $(LAYOUT)/bfm_sc4.lh
$(DRIVERS)/blockade.o: $(LAYOUT)/blockade.lh
$(DRIVERS)/buggychl.o: $(LAYOUT)/buggychl.lh