saturn.cpp: SMPC device-ification part 1 (nw)

This commit is contained in:
angelosa 2017-10-04 04:00:59 +02:00
parent a5c860a5cf
commit e09bcca8ae
6 changed files with 603 additions and 233 deletions

View File

@ -161,26 +161,224 @@ TODO:
#define LOG_SMPC 0
#define LOG_PAD_CMD 0
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
/********************************************
*
* Bankswitch code for ST-V Multi Cart mode
*
*******************************************/
// device type definition
DEFINE_DEVICE_TYPE(SMPC_HLE, smpc_hle_device, "smpc_hle", "Sega Saturn SMPC HLE (HD404920FS)")
void saturn_state::stv_select_game(int gameno)
// TODO: this is actually a DEVICE_ADDRESS_MAP, fix once everything is merged
static ADDRESS_MAP_START( smpc_regs, 0, 8, smpc_hle_device )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x61, 0x61) AM_READ(status_register_r)
AM_RANGE(0x63, 0x63) AM_READWRITE(status_flag_r, status_flag_w)
AM_RANGE(0x75, 0x75) AM_READWRITE(pdr1_r, pdr1_w)
AM_RANGE(0x77, 0x77) AM_READWRITE(pdr2_r, pdr2_w)
AM_RANGE(0x79, 0x79) AM_WRITE(ddr1_w)
AM_RANGE(0x7b, 0x7b) AM_WRITE(ddr2_w)
AM_RANGE(0x7d, 0x7d) AM_WRITE(iosel_w)
AM_RANGE(0x7f, 0x7f) AM_WRITE(exle_w)
ADDRESS_MAP_END
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// smpc_hle_device - constructor
//-------------------------------------------------
smpc_hle_device::smpc_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SMPC_HLE, tag, owner, clock),
device_memory_interface(mconfig, *this),
m_space_config("regs", ENDIANNESS_LITTLE, 8, 7, 0, nullptr, *ADDRESS_MAP_NAME(smpc_regs)),
m_pdr1_read(*this),
m_pdr2_read(*this),
m_pdr1_write(*this),
m_pdr2_write(*this)
{
if (m_prev_bankswitch != gameno)
{
if (m_cart_reg[gameno] && m_cart_reg[gameno]->base())
memcpy(memregion("abus")->base(), m_cart_reg[gameno]->base(), 0x3000000);
else
memset(memregion("abus")->base(), 0x00, 0x3000000); // TODO: 1-filled?
m_prev_bankswitch = gameno;
}
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void smpc_hle_device::device_start()
{
m_pdr1_read.resolve_safe(0xff);
m_pdr2_read.resolve_safe(0xff);
m_pdr1_write.resolve_safe();
m_pdr2_write.resolve_safe();
save_item(NAME(m_sf));
save_item(NAME(m_sr));
save_item(NAME(m_ddr1));
save_item(NAME(m_ddr2));
save_item(NAME(m_pdr1_readback));
save_item(NAME(m_pdr2_readback));
save_item(NAME(m_iosel1));
save_item(NAME(m_iosel2));
save_item(NAME(m_exle1));
save_item(NAME(m_exle2));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void smpc_hle_device::device_reset()
{
m_sr = 0x40; // this bit is always on according to docs (?)
m_sf = false;
m_cd_sf = false;
m_ddr1 = 0;
m_ddr2 = 0;
m_pdr1_readback = 0;
m_pdr2_readback = 0;
}
//-------------------------------------------------
// memory_space_config - return a description of
// any address spaces owned by this device
//-------------------------------------------------
device_memory_interface::space_config_vector smpc_hle_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(0, &m_space_config)
};
}
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
READ8_MEMBER( smpc_hle_device::status_register_r )
{
return m_sr;
}
READ8_MEMBER( smpc_hle_device::status_flag_r )
{
// bit 3: CD enable related?
return (m_sf<<0) | (m_cd_sf<<3);
}
WRITE8_MEMBER( smpc_hle_device::status_flag_w )
{
m_sf = BIT(data,0);
m_cd_sf = false;
}
READ8_MEMBER( smpc_hle_device::pdr1_r )
{
uint8_t res = (m_pdr1_read() & ~m_ddr1) | m_pdr1_readback;
return res;
}
READ8_MEMBER( smpc_hle_device::pdr2_r )
{
uint8_t res = (m_pdr2_read() & ~m_ddr2) | m_pdr2_readback;
return res;
}
WRITE8_MEMBER( smpc_hle_device::pdr1_w )
{
// pins defined as output returns in input
m_pdr1_readback = (data & m_ddr1);
m_pdr1_readback &= 0x7f;
m_pdr1_write(m_pdr1_readback);
// bit 7 can be read back apparently
m_pdr1_readback |= data & 0x80;
}
WRITE8_MEMBER( smpc_hle_device::pdr2_w )
{
// pins defined as output returns in input
m_pdr2_readback = (data & m_ddr2);
m_pdr2_readback &= 0x7f;
m_pdr2_write(m_pdr2_readback);
// bit 7 can be read back apparently
m_pdr2_readback |= data & 0x80;
}
WRITE8_MEMBER( smpc_hle_device::ddr1_w )
{
m_ddr1 = data & 0x7f;
}
WRITE8_MEMBER( smpc_hle_device::ddr2_w )
{
m_ddr2 = data & 0x7f;
}
WRITE8_MEMBER( smpc_hle_device::iosel_w )
{
m_iosel1 = BIT(data,0);
m_iosel2 = BIT(data,1);
}
WRITE8_MEMBER( smpc_hle_device::exle_w )
{
m_exle1 = BIT(data,0);
m_exle2 = BIT(data,1);
}
inline void smpc_hle_device::sr_ack()
{
m_sr &= 0x0f;
}
inline void smpc_hle_device::sr_set(uint8_t data)
{
m_sr = data;
}
inline void smpc_hle_device::sf_ack(bool cd_enable)
{
m_sf = false;
m_cd_sf = cd_enable;
}
inline void smpc_hle_device::sf_set()
{
m_sf = true;
}
// Saturn Direct Mode polling check for delegate
bool smpc_hle_device::get_iosel(bool which)
{
return which == true ? m_iosel2 : m_iosel1;
}
uint8_t smpc_hle_device::get_ddr(bool which)
{
return which == true ? m_ddr2 : m_ddr1;
}
// TODO: trampolines that needs to go away
READ8_MEMBER( smpc_hle_device::read )
{
return this->space().read_byte(offset);
}
WRITE8_MEMBER( smpc_hle_device::write )
{
this->space().write_byte(offset,data);
}
/********************************************
*
* Command functions
@ -196,7 +394,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::smpc_slave_enable )
{
m_slave->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
m_smpc.OREG[31] = param + 0x02; //read-back for last command issued
m_smpc.SF = 0x00; //clear hand-shake flag
m_smpc_hle->sf_ack(false);
m_smpc.slave_on = param;
// printf("%d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos());
}
@ -206,13 +404,13 @@ TIMER_CALLBACK_MEMBER( saturn_state::smpc_sound_enable )
m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
m_en_68k = param ^ 1;
m_smpc.OREG[31] = param + 0x06; //read-back for last command issued
m_smpc.SF = 0x00; //clear hand-shake flag
m_smpc_hle->sf_ack(false);
}
TIMER_CALLBACK_MEMBER( saturn_state::smpc_cd_enable )
{
m_smpc.OREG[31] = param + 0x08; //read-back for last command issued
m_smpc.SF = 0x08; //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high)
m_smpc_hle->sf_ack(true); //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high)
}
void saturn_state::smpc_system_reset()
@ -256,21 +454,20 @@ TIMER_CALLBACK_MEMBER( saturn_state::smpc_change_clock )
/* put issued command in OREG31 */
m_smpc.OREG[31] = 0x0e + param;
/* clear hand-shake flag */
m_smpc.SF = 0x00;
m_smpc_hle->sf_ack(false);
/* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values? */
}
TIMER_CALLBACK_MEMBER( saturn_state::stv_intback_peripheral )
{
if (m_smpc.intback_stage == 2)
{
m_smpc.SR = (0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
{
m_smpc_hle->sr_set(0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
m_smpc.intback_stage = 0;
}
else
{
m_smpc.SR = (0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
m_smpc_hle->sr_set(0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
m_smpc.intback_stage ++;
}
@ -280,7 +477,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::stv_intback_peripheral )
m_scu.ist |= (IRQ_SMPC);
m_smpc.OREG[31] = 0x10; /* callback for last command issued */
m_smpc.SF = 0x00; /* clear hand-shake flag */
m_smpc_hle->sf_ack(false);
}
@ -318,7 +515,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::stv_smpc_intback )
m_smpc.OREG[16+i]=0xff; // undefined
m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
m_smpc.SR = 0x40 | m_smpc.intback_stage << 5;
m_smpc_hle->sr_set(0x40 | (m_smpc.intback_stage << 5));
m_smpc.pmode = m_smpc.intback_buf[0]>>4;
// /*This is for RTC,cartridge code and similar stuff...*/
@ -331,12 +528,12 @@ TIMER_CALLBACK_MEMBER( saturn_state::stv_smpc_intback )
/* put issued command in OREG31 */
m_smpc.OREG[31] = 0x10; // TODO: doc says 0?
/* clear hand-shake flag */
m_smpc.SF = 0x00;
m_smpc_hle->sf_ack(false);
}
else if(m_smpc.intback_buf[1] & 8)
{
m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
m_smpc.SR = 0x40;
m_smpc_hle->sr_set(0x40);
m_smpc.OREG[31] = 0x10;
machine().scheduler().timer_set(attotime::from_usec(0), timer_expired_delegate(FUNC(saturn_state::stv_intback_peripheral),this),0);
}
@ -344,7 +541,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::stv_smpc_intback )
{
/* Shienryu calls this, it would be plainly illegal on Saturn, I'll just return the command and clear the hs flag for now. */
m_smpc.OREG[31] = 0x10;
m_smpc.SF = 0x00;
m_smpc_hle->sf_ack(false);
}
}
@ -416,12 +613,12 @@ TIMER_CALLBACK_MEMBER( saturn_state::intback_peripheral )
if (m_smpc.intback_stage == 2)
{
m_smpc.SR = (0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
m_smpc_hle->sr_set(0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
m_smpc.intback_stage = 0;
}
else
{
m_smpc.SR = (0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
m_smpc_hle->sr_set(0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
m_smpc.intback_stage ++;
}
@ -431,7 +628,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::intback_peripheral )
m_scu.ist |= (IRQ_SMPC);
m_smpc.OREG[31] = 0x10; /* callback for last command issued */
m_smpc.SF = 0x00; /* clear hand-shake flag */
m_smpc_hle->sf_ack(false);
}
TIMER_CALLBACK_MEMBER( saturn_state::saturn_smpc_intback )
@ -468,7 +665,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::saturn_smpc_intback )
}
m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
m_smpc.SR = 0x40 | m_smpc.intback_stage << 5;
m_smpc_hle->sr_set(0x40 | (m_smpc.intback_stage << 5));
m_smpc.pmode = m_smpc.intback_buf[0]>>4;
if(!(m_scu.ism & IRQ_SMPC))
@ -479,12 +676,12 @@ TIMER_CALLBACK_MEMBER( saturn_state::saturn_smpc_intback )
/* put issued command in OREG31 */
m_smpc.OREG[31] = 0x10;
/* clear hand-shake flag */
m_smpc.SF = 0x00;
m_smpc_hle->sf_ack(false);
}
else if(m_smpc.intback_buf[1] & 8)
{
m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
m_smpc.SR = 0x40;
m_smpc_hle->sr_set(0x40);
m_smpc.OREG[31] = 0x10;
machine().scheduler().timer_set(attotime::from_usec(0), timer_expired_delegate(FUNC(saturn_state::intback_peripheral),this),0);
}
@ -525,7 +722,7 @@ TIMER_CALLBACK_MEMBER( saturn_state::smpc_nmi_set )
/* put issued command in OREG31 */
m_smpc.OREG[31] = 0x19 + param;
/* clear hand-shake flag */
m_smpc.SF = 0x00;
m_smpc_hle->sf_ack(false);
//m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6);
}
@ -663,7 +860,7 @@ void saturn_state::smpc_comreg_exec(address_space &space, uint8_t data, uint8_t
READ8_MEMBER( saturn_state::stv_SMPC_r )
{
int return_data = 0;
if(!(offset & 1))
return 0;
@ -671,22 +868,22 @@ READ8_MEMBER( saturn_state::stv_SMPC_r )
return_data = m_smpc.OREG[(offset-0x21) >> 1];
if (offset == 0x61) // TODO: SR
return_data = m_smpc.SR;
return_data = m_smpc_hle->read(space,offset);
if (offset == 0x63)
return_data = m_smpc.SF;
return_data = m_smpc_hle->read(space,offset);
if (offset == 0x75)//PDR1 read
return_data = ioport("DSW1")->read();
return_data = m_smpc_hle->read(space,offset); //ioport("DSW1")->read();
if (offset == 0x77)//PDR2 read
return_data = (0xfe | m_eeprom->do_read());
return_data = m_smpc_hle->read(space,offset); //(0xfe | m_eeprom->do_read());
return return_data;
}
WRITE8_MEMBER( saturn_state::stv_SMPC_w )
{
{
if (!(offset & 1)) // avoid writing to even bytes
return;
@ -702,7 +899,7 @@ WRITE8_MEMBER( saturn_state::stv_SMPC_w )
if(data & 0x40)
{
if(LOG_PAD_CMD) printf("SMPC: BREAK request\n");
m_smpc.SR &= 0x0f;
m_smpc_hle->sr_ack();
m_smpc.intback_stage = 0;
}
else if(data & 0x80)
@ -710,7 +907,7 @@ WRITE8_MEMBER( saturn_state::stv_SMPC_w )
if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n");
machine().scheduler().timer_set(attotime::from_usec(700), timer_expired_delegate(FUNC(saturn_state::stv_intback_peripheral),this),0); /* TODO: is timing correct? */
m_smpc.OREG[31] = 0x10;
m_smpc.SF = 0x01; //TODO: set hand-shake flag?
m_smpc_hle->sf_set();
}
}
}
@ -723,65 +920,36 @@ WRITE8_MEMBER( saturn_state::stv_SMPC_w )
if(data != 0x10 && data != 0x02 && data != 0x03 && data != 0x08 && data != 0x09 && data != 0xe && data != 0xf && data != 0x19 && data != 0x1a)
{
m_smpc.OREG[31] = data; //read-back command
m_smpc.SF = 0x00;
m_smpc_hle->sf_ack(false);
}
/*TODO:emulate the timing of each command...*/
}
if(offset == 0x63)
m_smpc.SF = data & 1;
m_smpc_hle->write(space,offset,data);
// PDR1
if(offset == 0x75)
{
/*
-xx- ---- PDR1
---x ---- EEPROM write bit
---- x--- EEPROM CLOCK line
---- -x-- EEPROM CS line
---- --xx A-Bus bank bits
*/
m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
m_eeprom->di_write((data >> 4) & 1);
m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE);
m_stv_multi_bank = data & 3;
stv_select_game(m_stv_multi_bank);
m_smpc.PDR1 = (data & 0x60);
}
m_smpc_hle->write(space,offset,data);
// PDR2
if(offset == 0x77)
{
/*
-xx- ---- PDR2
---x ---- Enable Sound System (ACTIVE LOW)
*/
//popmessage("PDR2 = %02x",m_smpc_ram[0x77]);
m_smpc_hle->write(space,offset,data);
if(LOG_SMPC) printf("SMPC: M68k %s\n",(data & 0x10) ? "off" : "on");
//machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_sound_enable),this),(m_smpc_ram[0x77] & 0x10) >> 4);
m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
m_en_68k = ((data & 0x10) >> 4) ^ 1;
//if(LOG_SMPC) printf("SMPC: ram [0x77] = %02x\n",data);
m_smpc.PDR2 = (data & 0x60);
}
if(offset == 0x79)
m_smpc_hle->write(space,offset,data);
if(offset == 0x7b)
m_smpc_hle->write(space,offset,data);
if(offset == 0x7d)
{
/*
---- --x- IOSEL2 direct (1) / control mode (0) port select
---- ---x IOSEL1 direct (1) / control mode (0) port select
*/
m_smpc.IOSEL1 = (data & 1) >> 0;
m_smpc.IOSEL2 = (data & 2) >> 1;
m_smpc_hle->write(space,offset,data);
}
if(offset == 0x7f)
{
//enable PAD irq & VDP2 external latch for port 1/2
m_smpc.EXLE1 = (data & 1) >> 0;
m_smpc.EXLE2 = (data & 2) >> 1;
m_smpc_hle->write(space,offset,data);
}
}
@ -791,67 +959,8 @@ WRITE8_MEMBER( saturn_state::stv_SMPC_w )
*
*******************************************/
uint8_t saturn_state::smpc_th_control_mode(uint8_t pad_n)
{
uint8_t res = 0;
int th = (pad_n == 0) ? ((m_smpc.PDR1 >> 5) & 3) : ((m_smpc.PDR2 >> 5) & 3);
uint16_t ctrl_read = 0;
if (m_ctrl1 && pad_n == 0)
ctrl_read = m_ctrl1->read_direct();
if (m_ctrl2 && pad_n == 1)
ctrl_read = m_ctrl2->read_direct();
if (LOG_SMPC) printf("SMPC: SH-2 TH control mode, returning pad data %d for phase %d\n", pad_n + 1, th);
switch (th)
{
/* TODO: 3D Lemmings bogusly enables TH Control mode, wants this to return the ID, needs HW tests. */
case 3:
res = th << 6;
res |= 0x14;
res |= (ctrl_read & 8); // L
break;
case 2:
res = th << 6;
// 1 C B Right Left Down Up
// WHP actually has a very specific code at 0x6015f30, doesn't like bits 0-1 active here ...
res|= ((ctrl_read >> 4) & 0x30); // C & B
res|= ((ctrl_read >> 12) & 0xc);
break;
case 1:
res = th << 6;
res |= 0x10;
res |= ((ctrl_read >> 4) & 0xf); // R, X, Y, Z
break;
case 0:
res = th << 6;
// 0 Start A 0 0 Down Up
res |= ((ctrl_read >> 6) & 0x30); // Start & A
res |= ((ctrl_read >> 12) & 0x03);
// ... and it actually wants bits 2 - 3 active here.
res |= 0xc;
break;
}
return res;
}
uint8_t saturn_state::smpc_direct_mode(uint8_t pad_n)
{
int hshake = (pad_n == 0) ? ((m_smpc.PDR1 >> 5) & 3) : ((m_smpc.PDR2 >> 5) & 3);
const int shift_bit[4] = { 4, 12, 8, 0 };
uint16_t ctrl_read = 0;
if (m_ctrl1 && pad_n == 0)
ctrl_read = m_ctrl1->read_direct();
if (m_ctrl2 && pad_n == 1)
ctrl_read = m_ctrl2->read_direct();
if (LOG_SMPC) logerror("SMPC: SH-2 direct mode, returning data for phase %d\n", hshake);
return 0x80 | 0x10 | ((ctrl_read >> shift_bit[hshake]) & 0xf);
}
READ8_MEMBER( saturn_state::saturn_SMPC_r )
{
@ -864,16 +973,18 @@ READ8_MEMBER( saturn_state::saturn_SMPC_r )
return_data = m_smpc.OREG[(offset-0x21) >> 1];
if (offset == 0x61)
return_data = m_smpc.SR;
return_data = m_smpc_hle->read(space,offset);
if (offset == 0x63)
{
//printf("SF %d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos());
return_data = m_smpc.SF;
return_data = m_smpc_hle->read(space,offset);
}
if (offset == 0x75 || offset == 0x77)//PDR1/2 read
{
return_data = m_smpc_hle->read(space,offset);
#if 0
if ((m_smpc.IOSEL1 && offset == 0x75) || (m_smpc.IOSEL2 && offset == 0x77))
{
uint8_t cur_ddr;
@ -897,6 +1008,7 @@ READ8_MEMBER( saturn_state::saturn_SMPC_r )
break;
}
}
#endif
}
if (LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x (%d) Returns %02x\n", space.device().tag(), space.device().safe_pc(), offset, offset>>1, return_data);
@ -921,7 +1033,7 @@ WRITE8_MEMBER( saturn_state::saturn_SMPC_w )
if(data & 0x40)
{
if(LOG_PAD_CMD) printf("SMPC: BREAK request %02x\n",data);
m_smpc.SR &= 0x0f;
m_smpc_hle->sr_ack();
m_smpc.intback_stage = 0;
}
else if(data & 0x80)
@ -929,7 +1041,7 @@ WRITE8_MEMBER( saturn_state::saturn_SMPC_w )
if(LOG_PAD_CMD) printf("SMPC: CONTINUE request %02x\n",data);
machine().scheduler().timer_set(attotime::from_usec(700), timer_expired_delegate(FUNC(saturn_state::intback_peripheral),this),0); /* TODO: is timing correct? */
m_smpc.OREG[31] = 0x10;
m_smpc.SF = 0x01; //TODO: set hand-shake flag?
m_smpc_hle->sf_set(); //TODO: set hand-shake flag?
}
}
}
@ -942,36 +1054,48 @@ WRITE8_MEMBER( saturn_state::saturn_SMPC_w )
if(data != 0x10 && data != 2 && data != 3 && data != 6 && data != 7 && data != 0x08 && data != 0x09 && data != 0x0e && data != 0x0f && data != 0x19 && data != 0x1a)
{
m_smpc.OREG[31] = data; //read-back for last command issued
m_smpc.SF = 0x00; //clear hand-shake flag
m_smpc_hle->sf_ack(false); //clear hand-shake flag
}
/*TODO:emulate the timing of each command...*/
// TODO: emulate the timing of each command...
}
if (offset == 0x63)
m_smpc.SF = data & 1; // hand-shake flag
m_smpc_hle->write(space,offset,data);
if(offset == 0x75) // PDR1
m_smpc.PDR1 = data & 0x7f;
m_smpc_hle->write(space,offset,data);
//m_smpc.PDR1 = data & 0x7f;
if(offset == 0x77) // PDR2
m_smpc.PDR2 = data & 0x7f;
m_smpc_hle->write(space,offset,data);
//m_smpc.PDR2 = data & 0x7f;
if(offset == 0x79)
m_smpc.DDR1 = data & 0x7f;
m_smpc_hle->write(space,offset,data);
// m_smpc.DDR1 = data & 0x7f;
if(offset == 0x7b)
m_smpc.DDR2 = data & 0x7f;
m_smpc_hle->write(space,offset,data);
// m_smpc.DDR2 = data & 0x7f;
if(offset == 0x7d)
{
m_smpc.IOSEL1 = data & 1;
m_smpc.IOSEL2 = (data & 2) >> 1;
m_smpc_hle->write(space,offset,data);
// m_smpc.IOSEL1 = data & 1;
// m_smpc.IOSEL2 = (data & 2) >> 1;
}
if(offset == 0x7f)
{
m_smpc_hle->write(space,offset,data);
//enable PAD irq & VDP2 external latch for port 1/2
m_smpc.EXLE1 = (data & 1) >> 0;
m_smpc.EXLE2 = (data & 2) >> 1;
// m_smpc.EXLE1 = (data & 1) >> 0;
// m_smpc.EXLE2 = (data & 2) >> 1;
}
}

View File

@ -5,3 +5,112 @@
//DECLARE_READ8_MEMBER( stv_SMPC_r );
//DECLARE_WRITE8_MEMBER( saturn_SMPC_w );
//DECLARE_READ8_MEMBER( saturn_SMPC_r );
#ifndef MAME_MACHINE_SMPC_HLE_H
#define MAME_MACHINE_SMPC_HLE_H
#pragma once
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_SMPC_HLE_ADD(tag) \
MCFG_DEVICE_ADD((tag), SMPC_HLE, (0))
#define MCFG_SMPC_HLE_PDR1_IN_CB(_devcb) \
devcb = &smpc_hle_device::set_pdr1_in_handler(*device, DEVCB_##_devcb);
#define MCFG_SMPC_HLE_PDR2_IN_CB(_devcb) \
devcb = &smpc_hle_device::set_pdr2_in_handler(*device, DEVCB_##_devcb);
#define MCFG_SMPC_HLE_PDR1_OUT_CB(_devcb) \
devcb = &smpc_hle_device::set_pdr1_out_handler(*device, DEVCB_##_devcb);
#define MCFG_SMPC_HLE_PDR2_OUT_CB(_devcb) \
devcb = &smpc_hle_device::set_pdr2_out_handler(*device, DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> smpc_hle_device
class smpc_hle_device : public device_t,
public device_memory_interface
{
public:
// construction/destruction
smpc_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual space_config_vector memory_space_config() const override;
// I/O operations
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( read );
// TODO: public stuff that should be internal to the device
void sr_set(uint8_t data);
void sr_ack();
void sf_ack(bool cd_enable);
void sf_set();
bool get_iosel(bool which);
uint8_t get_ddr(bool which);
DECLARE_READ8_MEMBER( status_register_r );
DECLARE_WRITE8_MEMBER( status_flag_w );
DECLARE_READ8_MEMBER( status_flag_r );
DECLARE_READ8_MEMBER( pdr1_r );
DECLARE_READ8_MEMBER( pdr2_r );
DECLARE_WRITE8_MEMBER( pdr1_w );
DECLARE_WRITE8_MEMBER( pdr2_w );
DECLARE_WRITE8_MEMBER( ddr1_w );
DECLARE_WRITE8_MEMBER( ddr2_w );
DECLARE_WRITE8_MEMBER( iosel_w );
DECLARE_WRITE8_MEMBER( exle_w );
template <class Object> static devcb_base &set_pdr1_in_handler(device_t &device, Object &&cb) { return downcast<smpc_hle_device &>(device).m_pdr1_read.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_pdr2_in_handler(device_t &device, Object &&cb) { return downcast<smpc_hle_device &>(device).m_pdr2_read.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_pdr1_out_handler(device_t &device, Object &&cb) { return downcast<smpc_hle_device &>(device).m_pdr1_write.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_pdr2_out_handler(device_t &device, Object &&cb) { return downcast<smpc_hle_device &>(device).m_pdr2_write.set_callback(std::forward<Object>(cb)); }
protected:
// device-level overrides
// virtual void device_validity_check(validity_checker &valid) const override;
// virtual void device_add_mconfig() override;
virtual void device_start() override;
virtual void device_reset() override;
private:
const address_space_config m_space_config;
bool m_sf;
bool m_cd_sf;
uint8_t m_sr;
uint8_t m_ddr1, m_ddr2;
uint8_t m_pdr1_readback, m_pdr2_readback;
bool m_iosel1, m_iosel2;
bool m_exle1, m_exle2;
devcb_read8 m_pdr1_read;
devcb_read8 m_pdr2_read;
devcb_write8 m_pdr1_write;
devcb_write8 m_pdr2_write;
};
// device type definition
DECLARE_DEVICE_TYPE(SMPC_HLE, smpc_hle_device)
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
#endif // MAME_MACHINE_SMPC_HLE_H

View File

@ -719,18 +719,18 @@ MACHINE_START_MEMBER(sat_console_state, saturn)
save_pointer(NAME(m_scsp_regs.get()), 0x1000/2);
save_item(NAME(m_NMI_reset));
save_item(NAME(m_en_68k));
save_item(NAME(m_smpc.IOSEL1));
save_item(NAME(m_smpc.IOSEL2));
save_item(NAME(m_smpc.EXLE1));
save_item(NAME(m_smpc.EXLE2));
save_item(NAME(m_smpc.PDR1));
save_item(NAME(m_smpc.PDR2));
// save_item(NAME(m_smpc.IOSEL1));
// save_item(NAME(m_smpc.IOSEL2));
// save_item(NAME(m_smpc.EXLE1));
// save_item(NAME(m_smpc.EXLE2));
// save_item(NAME(m_smpc.PDR1));
// save_item(NAME(m_smpc.PDR2));
// save_item(NAME(m_port_sel));
// save_item(NAME(mux_data));
save_item(NAME(m_scsp_last_line));
save_item(NAME(m_smpc.intback_stage));
save_item(NAME(m_smpc.pmode));
save_item(NAME(m_smpc.SR));
// save_item(NAME(m_smpc.SR));
save_item(NAME(m_smpc.SMEM));
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&sat_console_state::stvcd_exit, this));
@ -767,7 +767,7 @@ MACHINE_RESET_MEMBER(sat_console_state,saturn)
m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_scudsp->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_smpc.SR = 0x40; // this bit is always on according to docs
// m_smpc.SR = 0x40; // this bit is always on according to docs
scu_reset();
@ -789,6 +789,97 @@ MACHINE_RESET_MEMBER(sat_console_state,saturn)
m_stv_rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
}
READ8_MEMBER( saturn_state::saturn_pdr1_direct_r )
{
return saturn_direct_port_read(false);
}
READ8_MEMBER( saturn_state::saturn_pdr2_direct_r )
{
return saturn_direct_port_read(true);
}
WRITE8_MEMBER( saturn_state::saturn_pdr1_direct_w )
{
m_direct_mux[0] = data;
}
WRITE8_MEMBER( saturn_state::saturn_pdr2_direct_w )
{
m_direct_mux[1] = data;
}
inline uint8_t saturn_state::saturn_direct_port_read(bool which)
{
// bail out if direct mode is disabled
if(m_smpc_hle->get_iosel(which) == false)
return 0xff;
saturn_control_port_device *port = which == true ? m_ctrl2 : m_ctrl1;
uint8_t cur_mode = m_smpc_hle->get_ddr(which);
uint8_t res = 0;
uint16_t ctrl_read = port->read_direct();
// check for control method
switch(cur_mode & 0x60)
{
case 0: break;
case 0x40: res = smpc_th_control_mode(ctrl_read,which); break;
case 0x60: res = smpc_direct_mode(ctrl_read,which); break;
default:
popmessage("SMPC: unemulated control method %02x, contact MAMEdev",cur_mode & 0x60);
break;
}
return res;
}
uint8_t saturn_state::smpc_th_control_mode(uint16_t in_value, bool which)
{
uint8_t res = 0;
uint8_t th = (m_direct_mux[which] >> 5) & 3;
switch (th)
{
/* TODO: 3D Lemmings bogusly enables TH Control mode, wants this to return the ID, needs HW tests. */
case 3:
res = th << 6;
res |= 0x14;
res |= (in_value & 8); // L
break;
case 2:
res = th << 6;
// 1 C B Right Left Down Up
// WHP actually has a very specific code at 0x6015f30, doesn't like bits 0-1 active here ...
res|= ((in_value >> 4) & 0x30); // C & B
res|= ((in_value >> 12) & 0xc);
break;
case 1:
res = th << 6;
res |= 0x10;
res |= ((in_value >> 4) & 0xf); // R, X, Y, Z
break;
case 0:
res = th << 6;
// 0 Start A 0 0 Down Up
res |= ((in_value >> 6) & 0x30); // Start & A
res |= ((in_value >> 12) & 0x03);
// ... and it actually wants bits 2 - 3 active here.
res |= 0xc;
break;
}
return res;
}
uint8_t saturn_state::smpc_direct_mode(uint16_t in_value,bool which)
{
uint8_t hshake = (m_direct_mux[which] >> 5) & 3;
const int shift_bit[4] = { 4, 12, 8, 0 };
return 0x80 | 0x10 | ((in_value >> shift_bit[hshake]) & 0xf);
}
static MACHINE_CONFIG_START( saturn )
@ -815,6 +906,11 @@ static MACHINE_CONFIG_START( saturn )
// SH-1
MCFG_SMPC_HLE_ADD("smpc")
MCFG_SMPC_HLE_PDR1_IN_CB(READ8(saturn_state, saturn_pdr1_direct_r))
MCFG_SMPC_HLE_PDR2_IN_CB(READ8(saturn_state, saturn_pdr2_direct_r))
MCFG_SMPC_HLE_PDR1_OUT_CB(WRITE8(saturn_state, saturn_pdr1_direct_w))
MCFG_SMPC_HLE_PDR2_OUT_CB(WRITE8(saturn_state, saturn_pdr2_direct_w))
// SMPC MCU, running at 4 MHz (+ custom RTC device that runs at 32.768 KHz)
MCFG_MACHINE_START_OVERRIDE(sat_console_state,saturn)

View File

@ -1021,6 +1021,57 @@ static ADDRESS_MAP_START( scudsp_data, AS_DATA, 32, stv_state )
ADDRESS_MAP_END
/********************************************
*
* SMPC outputs
*
*******************************************/
void stv_state::stv_select_game(int gameno)
{
if (m_prev_gamebank_select != gameno)
{
if (m_cart_reg[gameno] && m_cart_reg[gameno]->base())
memcpy(memregion("abus")->base(), m_cart_reg[gameno]->base(), 0x3000000);
else
memset(memregion("abus")->base(), 0x00, 0x3000000); // TODO: 1-filled?
m_prev_gamebank_select = gameno;
}
}
READ8_MEMBER( stv_state::pdr1_input_r )
{
return (ioport("PDR1")->read() & 0x40) | 0x3f;
}
READ8_MEMBER( stv_state::pdr2_input_r )
{
return (ioport("PDR2")->read() & ~0x19) | 0x18 | (m_eeprom->do_read()<<0);
}
WRITE8_MEMBER( stv_state::pdr1_output_w )
{
m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
m_eeprom->di_write((data >> 4) & 1);
m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE);
stv_select_game(data & 3);
}
WRITE8_MEMBER( stv_state::pdr2_output_w )
{
m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
m_en_68k = ((data & 0x10) >> 4) ^ 1;
if(data & 8)
logerror("PDR2: data 0x8 active!\n");
}
static MACHINE_CONFIG_START( stv )
/* basic machine hardware */
@ -1044,6 +1095,12 @@ static MACHINE_CONFIG_START( stv )
MCFG_SCUDSP_IN_DMA_CB(READ16(saturn_state, scudsp_dma_r))
MCFG_SCUDSP_OUT_DMA_CB(WRITE16(saturn_state, scudsp_dma_w))
MCFG_SMPC_HLE_ADD("smpc")
MCFG_SMPC_HLE_PDR1_IN_CB(READ8(stv_state, pdr1_input_r))
MCFG_SMPC_HLE_PDR2_IN_CB(READ8(stv_state, pdr2_input_r))
MCFG_SMPC_HLE_PDR1_OUT_CB(WRITE8(stv_state, pdr1_output_w))
MCFG_SMPC_HLE_PDR2_OUT_CB(WRITE8(stv_state, pdr2_output_w))
MCFG_MACHINE_START_OVERRIDE(stv_state,stv)
MCFG_MACHINE_RESET_OVERRIDE(stv_state,stv)
@ -1181,7 +1238,7 @@ MACHINE_RESET_MEMBER(stv_state,stv)
stvcd_reset();
m_stv_rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
m_prev_bankswitch = 0xff;
m_prev_gamebank_select = 0xff;
scu_reset();
@ -1234,13 +1291,14 @@ MACHINE_START_MEMBER(stv_state,stv)
save_pointer(NAME(m_scsp_regs.get()), 0x1000/2);
save_item(NAME(m_NMI_reset));
save_item(NAME(m_en_68k));
save_item(NAME(m_prev_gamebank_select));
// save_item(NAME(scanline));
save_item(NAME(m_smpc.IOSEL1));
save_item(NAME(m_smpc.IOSEL2));
save_item(NAME(m_smpc.EXLE1));
save_item(NAME(m_smpc.EXLE2));
save_item(NAME(m_smpc.PDR1));
save_item(NAME(m_smpc.PDR2));
// save_item(NAME(m_smpc.IOSEL1));
// save_item(NAME(m_smpc.IOSEL2));
// save_item(NAME(m_smpc.EXLE1));
// save_item(NAME(m_smpc.EXLE2));
// save_item(NAME(m_smpc.PDR1));
// save_item(NAME(m_smpc.PDR2));
save_item(NAME(m_port_sel));
save_item(NAME(m_mux_data));
save_item(NAME(m_scsp_last_line));
@ -1274,57 +1332,27 @@ MACHINE_START_MEMBER(stv_state,stv)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(_n_)
static INPUT_PORTS_START( stv )
PORT_START("DSW1")
PORT_DIPNAME( 0x01, 0x01, "PDR1" )
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
PORT_START("PDR1")
PORT_DIPNAME( 0x40, 0x40, "PDR1" ) // P1 Gun Trigger
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("DSW2")
PORT_DIPNAME( 0x01, 0x01, "PDR2" )
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) // test mode mirror
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) // service button mirror
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) // P2 Gun Trigger
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("PORTA")
STV_PLAYER_INPUTS(1, BUTTON1, BUTTON2, BUTTON3, BUTTON4)

View File

@ -7,6 +7,7 @@
#include "cpu/m68000/m68000.h"
#include "cpu/adsp2100/adsp2100.h"
#include "cpu/scudsp/scudsp.h"
#include "machine/smpc.h"
#include "cpu/sh/sh2.h"
#include "bus/sat_ctrl/ctrl.h"
@ -38,12 +39,9 @@ public:
m_maincpu(*this, "maincpu"),
m_slave(*this, "slave"),
m_audiocpu(*this, "audiocpu"),
m_smpc_hle(*this, "smpc"),
m_scudsp(*this, "scudsp"),
m_eeprom(*this, "eeprom"),
m_cart1(*this, "stv_slot1"),
m_cart2(*this, "stv_slot2"),
m_cart3(*this, "stv_slot3"),
m_cart4(*this, "stv_slot4"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_ctrl1(*this, "ctrl1"),
@ -130,16 +128,16 @@ public:
}m_vdp2;
struct {
uint8_t IOSEL1;
uint8_t IOSEL2;
uint8_t EXLE1;
uint8_t EXLE2;
uint8_t PDR1;
uint8_t PDR2;
uint8_t DDR1;
uint8_t DDR2;
uint8_t SF;
uint8_t SR;
// uint8_t IOSEL1;
// uint8_t IOSEL2;
// uint8_t EXLE1;
// uint8_t EXLE2;
// uint8_t PDR1;
// uint8_t PDR2;
// uint8_t DDR1;
// uint8_t DDR2;
// uint8_t SF;
// uint8_t SR;
uint8_t IREG[7];
uint8_t intback_buf[7];
uint8_t OREG[32];
@ -157,8 +155,6 @@ public:
uint32_t *m_cart_dram;
/* ST-V specific */
uint8_t m_stv_multi_bank;
uint8_t m_prev_bankswitch;
emu_timer *m_stv_rtc_timer;
uint8_t m_port_sel,m_mux_data;
uint8_t m_system_output;
@ -169,12 +165,9 @@ public:
required_device<sh2_device> m_maincpu;
required_device<sh2_device> m_slave;
required_device<m68000_base_device> m_audiocpu;
required_device<smpc_hle_device> m_smpc_hle;
required_device<scudsp_cpu_device> m_scudsp;
optional_device<eeprom_serial_93cxx_device> m_eeprom;
optional_device<generic_slot_device> m_cart1;
optional_device<generic_slot_device> m_cart2;
optional_device<generic_slot_device> m_cart3;
optional_device<generic_slot_device> m_cart4;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
optional_device<saturn_control_port_device> m_ctrl1;
@ -210,8 +203,6 @@ public:
DECLARE_WRITE8_MEMBER(scsp_irq);
int m_scsp_last_line;
uint8_t smpc_direct_mode(uint8_t pad_n);
uint8_t smpc_th_control_mode(uint8_t pad_n);
TIMER_CALLBACK_MEMBER( smpc_audio_reset_line_pulse );
DECLARE_READ8_MEMBER( saturn_SMPC_r );
DECLARE_WRITE8_MEMBER( saturn_SMPC_w );
@ -673,7 +664,6 @@ public:
DECLARE_WRITE16_MEMBER(scudsp_dma_w);
// FROM smpc.c
void stv_select_game(int gameno);
void smpc_master_on();
TIMER_CALLBACK_MEMBER( smpc_slave_enable );
TIMER_CALLBACK_MEMBER( smpc_sound_enable );
@ -692,11 +682,19 @@ public:
DECLARE_READ8_MEMBER( stv_SMPC_r );
DECLARE_WRITE8_MEMBER( stv_SMPC_w );
DECLARE_READ8_MEMBER(saturn_pdr1_direct_r);
DECLARE_READ8_MEMBER(saturn_pdr2_direct_r);
DECLARE_WRITE8_MEMBER(saturn_pdr1_direct_w);
DECLARE_WRITE8_MEMBER(saturn_pdr2_direct_w);
uint8_t m_direct_mux[2];
uint8_t saturn_direct_port_read(bool which);
uint8_t smpc_direct_mode(uint16_t in_value, bool which);
uint8_t smpc_th_control_mode(uint16_t in_value, bool which);
void debug_scudma_command(int ref, const std::vector<std::string> &params);
void debug_scuirq_command(int ref, const std::vector<std::string> &params);
void debug_help_command(int ref, const std::vector<std::string> &params);
void debug_commands(int ref, const std::vector<std::string> &params);
};

View File

@ -10,6 +10,10 @@ class stv_state : public saturn_state
public:
stv_state(const machine_config &mconfig, device_type type, const char *tag)
: saturn_state(mconfig, type, tag),
m_cart1(*this, "stv_slot1"),
m_cart2(*this, "stv_slot2"),
m_cart3(*this, "stv_slot3"),
m_cart4(*this, "stv_slot4"),
m_rax(*this, "rax"),
m_cryptdevice(*this, "315_5881"),
m_5838crypt(*this, "315_5838"),
@ -88,6 +92,10 @@ public:
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( stv_cart2 ) { return load_cart(image, m_cart2); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( stv_cart3 ) { return load_cart(image, m_cart3); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( stv_cart4 ) { return load_cart(image, m_cart4); }
optional_device<generic_slot_device> m_cart1;
optional_device<generic_slot_device> m_cart2;
optional_device<generic_slot_device> m_cart3;
optional_device<generic_slot_device> m_cart4;
void install_stvbios_speedups( void );
@ -116,6 +124,13 @@ public:
uint16_t crypt_read_callback(uint32_t addr);
uint16_t crypt_read_callback_ch1(uint32_t addr);
uint16_t crypt_read_callback_ch2(uint32_t addr);
DECLARE_READ8_MEMBER(pdr1_input_r);
DECLARE_READ8_MEMBER(pdr2_input_r);
DECLARE_WRITE8_MEMBER(pdr1_output_w);
DECLARE_WRITE8_MEMBER(pdr2_output_w);
void stv_select_game(int gameno);
uint8_t m_prev_gamebank_select;
};