smpc moved to state, need to be device-fied in future (nw)

This commit is contained in:
Miodrag Milanovic 2014-04-03 08:08:38 +00:00
parent 1b5f24add6
commit 5e99f6e4c8
5 changed files with 294 additions and 301 deletions

View File

@ -164,28 +164,27 @@ TODO:
* *
*******************************************/ *******************************************/
static TIMER_CALLBACK( stv_bankswitch_state ) TIMER_CALLBACK_MEMBER( saturn_state::stv_bankswitch_state )
{ {
saturn_state *state = machine.driver_data<saturn_state>();
static const char *const banknames[] = { "game0", "game1", "game2", "game3" }; static const char *const banknames[] = { "game0", "game1", "game2", "game3" };
UINT8* game_region; UINT8* game_region;
if(state->m_prev_bankswitch != param) if(m_prev_bankswitch != param)
{ {
game_region = machine.root_device().memregion(banknames[param])->base(); game_region = memregion(banknames[param])->base();
if (game_region) if (game_region)
memcpy(machine.root_device().memregion("abus")->base(), game_region, 0x3000000); memcpy(memregion("abus")->base(), game_region, 0x3000000);
else else
memset(machine.root_device().memregion("abus")->base(), 0x00, 0x3000000); memset(memregion("abus")->base(), 0x00, 0x3000000);
state->m_prev_bankswitch = param; m_prev_bankswitch = param;
} }
} }
static void stv_select_game(running_machine &machine, int gameno) void saturn_state::stv_select_game(int gameno)
{ {
machine.scheduler().timer_set(attotime::zero, FUNC(stv_bankswitch_state), gameno); machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(saturn_state::stv_bankswitch_state),this), gameno);
} }
/******************************************** /********************************************
@ -194,178 +193,164 @@ static void stv_select_game(running_machine &machine, int gameno)
* *
*******************************************/ *******************************************/
static void smpc_master_on(running_machine &machine) void saturn_state::smpc_master_on()
{ {
saturn_state *state = machine.driver_data<saturn_state>(); m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
state->m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
} }
static TIMER_CALLBACK( smpc_slave_enable ) TIMER_CALLBACK_MEMBER( saturn_state::smpc_slave_enable )
{ {
saturn_state *state = machine.driver_data<saturn_state>(); 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
state->m_slave->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE); m_smpc.SF = 0x00; //clear hand-shake flag
state->m_smpc.OREG[31] = param + 0x02; //read-back for last command issued m_smpc.slave_on = param;
state->m_smpc.SF = 0x00; //clear hand-shake flag // printf("%d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos());
state->m_smpc.slave_on = param;
// printf("%d %d\n",machine.first_screen()->hpos(),machine.first_screen()->vpos());
} }
static TIMER_CALLBACK( smpc_sound_enable ) TIMER_CALLBACK_MEMBER( saturn_state::smpc_sound_enable )
{ {
saturn_state *state = machine.driver_data<saturn_state>(); m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
m_en_68k = param ^ 1;
state->m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE); m_smpc.OREG[31] = param + 0x06; //read-back for last command issued
state->m_en_68k = param ^ 1; m_smpc.SF = 0x00; //clear hand-shake flag
state->m_smpc.OREG[31] = param + 0x06; //read-back for last command issued
state->m_smpc.SF = 0x00; //clear hand-shake flag
} }
static TIMER_CALLBACK( smpc_cd_enable ) TIMER_CALLBACK_MEMBER( saturn_state::smpc_cd_enable )
{ {
saturn_state *state = machine.driver_data<saturn_state>(); 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)
state->m_smpc.OREG[31] = param + 0x08; //read-back for last command issued
state->m_smpc.SF = 0x08; //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high)
} }
static void smpc_system_reset(running_machine &machine) void saturn_state::smpc_system_reset()
{ {
saturn_state *state = machine.driver_data<saturn_state>();
/*Only backup ram and SMPC ram are retained after that this command is issued.*/ /*Only backup ram and SMPC ram are retained after that this command is issued.*/
memset(state->m_scu_regs ,0x00,0x000100); memset(m_scu_regs ,0x00,0x000100);
memset(state->m_scsp_regs,0x00,0x001000); memset(m_scsp_regs,0x00,0x001000);
memset(state->m_sound_ram,0x00,0x080000); memset(m_sound_ram,0x00,0x080000);
memset(state->m_workram_h,0x00,0x100000); memset(m_workram_h,0x00,0x100000);
memset(state->m_workram_l,0x00,0x100000); memset(m_workram_l,0x00,0x100000);
memset(state->m_vdp2_regs,0x00,0x040000); memset(m_vdp2_regs,0x00,0x040000);
memset(state->m_vdp2_vram,0x00,0x100000); memset(m_vdp2_vram,0x00,0x100000);
memset(state->m_vdp2_cram,0x00,0x080000); memset(m_vdp2_cram,0x00,0x080000);
memset(state->m_vdp1_vram,0x00,0x100000); memset(m_vdp1_vram,0x00,0x100000);
//A-Bus //A-Bus
state->m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE); m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
} }
static TIMER_CALLBACK( smpc_change_clock ) TIMER_CALLBACK_MEMBER( saturn_state::smpc_change_clock )
{ {
saturn_state *state = machine.driver_data<saturn_state>();
UINT32 xtal; UINT32 xtal;
if(LOG_SMPC) printf ("Clock change execute at (%d %d)\n",machine.first_screen()->hpos(),machine.first_screen()->vpos()); if(LOG_SMPC) printf ("Clock change execute at (%d %d)\n",machine().first_screen()->hpos(),machine().first_screen()->vpos());
xtal = param ? MASTER_CLOCK_320 : MASTER_CLOCK_352; xtal = param ? MASTER_CLOCK_320 : MASTER_CLOCK_352;
machine.device("maincpu")->set_unscaled_clock(xtal/2); machine().device("maincpu")->set_unscaled_clock(xtal/2);
machine.device("slave")->set_unscaled_clock(xtal/2); machine().device("slave")->set_unscaled_clock(xtal/2);
state->m_vdp2.dotsel = param ^ 1; m_vdp2.dotsel = param ^ 1;
state->stv_vdp2_dynamic_res_change(); stv_vdp2_dynamic_res_change();
state->m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
if(!state->m_NMI_reset) if(!m_NMI_reset)
state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
state->m_slave->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); m_slave->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
state->m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
state->m_audiocpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); m_audiocpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
/* put issued command in OREG31 */ /* put issued command in OREG31 */
state->m_smpc.OREG[31] = 0x0e + param; m_smpc.OREG[31] = 0x0e + param;
/* clear hand-shake flag */ /* clear hand-shake flag */
state->m_smpc.SF = 0x00; m_smpc.SF = 0x00;
/* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values? */ /* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values? */
} }
static TIMER_CALLBACK( stv_intback_peripheral ) TIMER_CALLBACK_MEMBER( saturn_state::stv_intback_peripheral )
{ {
saturn_state *state = machine.driver_data<saturn_state>(); if (m_smpc.intback_stage == 2)
if (state->m_smpc.intback_stage == 2)
{ {
state->m_smpc.SR = (0x80 | state->m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback m_smpc.SR = (0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
state->m_smpc.intback_stage = 0; m_smpc.intback_stage = 0;
} }
else else
{ {
state->m_smpc.SR = (0xc0 | state->m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback m_smpc.SR = (0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
state->m_smpc.intback_stage ++; m_smpc.intback_stage ++;
} }
if(!(state->m_scu.ism & IRQ_SMPC)) if(!(m_scu.ism & IRQ_SMPC))
state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
else else
state->m_scu.ist |= (IRQ_SMPC); m_scu.ist |= (IRQ_SMPC);
state->m_smpc.OREG[31] = 0x10; /* callback for last command issued */ m_smpc.OREG[31] = 0x10; /* callback for last command issued */
state->m_smpc.SF = 0x00; /* clear hand-shake flag */ m_smpc.SF = 0x00; /* clear hand-shake flag */
} }
static TIMER_CALLBACK( stv_smpc_intback ) TIMER_CALLBACK_MEMBER( saturn_state::stv_smpc_intback )
{ {
saturn_state *state = machine.driver_data<saturn_state>();
int i; int i;
// printf("%02x %02x %02x\n",state->m_smpc.intback_buf[0],state->m_smpc.intback_buf[1],state->m_smpc.intback_buf[2]); // printf("%02x %02x %02x\n",m_smpc.intback_buf[0],m_smpc.intback_buf[1],m_smpc.intback_buf[2]);
if(state->m_smpc.intback_buf[0] != 0) if(m_smpc.intback_buf[0] != 0)
{ {
state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6);
for(i=0;i<7;i++) for(i=0;i<7;i++)
state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i]; m_smpc.OREG[1+i] = m_smpc.rtc_data[i];
state->m_smpc.OREG[8]=0x00; // CTG0 / CTG1? m_smpc.OREG[8]=0x00; // CTG0 / CTG1?
state->m_smpc.OREG[9]=0x00; // TODO: system region on Saturn m_smpc.OREG[9]=0x00; // TODO: system region on Saturn
state->m_smpc.OREG[10]= 0 << 7 | m_smpc.OREG[10]= 0 << 7 |
state->m_vdp2.dotsel << 6 | m_vdp2.dotsel << 6 |
1 << 5 | 1 << 5 |
1 << 4 | 1 << 4 |
0 << 3 | //MSHNMI 0 << 3 | //MSHNMI
1 << 2 | 1 << 2 |
0 << 1 | //SYSRES 0 << 1 | //SYSRES
0 << 0; //SOUNDRES 0 << 0; //SOUNDRES
state->m_smpc.OREG[11]= 0 << 6; //CDRES m_smpc.OREG[11]= 0 << 6; //CDRES
for(i=0;i<4;i++) for(i=0;i<4;i++)
state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i]; m_smpc.OREG[12+i]=m_smpc.SMEM[i];
for(i=0;i<15;i++) for(i=0;i<15;i++)
state->m_smpc.OREG[16+i]=0xff; // undefined m_smpc.OREG[16+i]=0xff; // undefined
state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
state->m_smpc.SR = 0x40 | state->m_smpc.intback_stage << 5; m_smpc.SR = 0x40 | m_smpc.intback_stage << 5;
state->m_smpc.pmode = state->m_smpc.intback_buf[0]>>4; m_smpc.pmode = m_smpc.intback_buf[0]>>4;
// /*This is for RTC,cartridge code and similar stuff...*/ // /*This is for RTC,cartridge code and similar stuff...*/
//if(LOG_SMPC) printf ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline); //if(LOG_SMPC) printf ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline);
if(!(state->m_scu.ism & IRQ_SMPC)) if(!(m_scu.ism & IRQ_SMPC))
state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
else else
state->m_scu.ist |= (IRQ_SMPC); m_scu.ist |= (IRQ_SMPC);
/* put issued command in OREG31 */ /* put issued command in OREG31 */
state->m_smpc.OREG[31] = 0x10; // TODO: doc says 0? m_smpc.OREG[31] = 0x10; // TODO: doc says 0?
/* clear hand-shake flag */ /* clear hand-shake flag */
state->m_smpc.SF = 0x00; m_smpc.SF = 0x00;
} }
else if(state->m_smpc.intback_buf[1] & 8) else if(m_smpc.intback_buf[1] & 8)
{ {
state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
state->m_smpc.SR = 0x40; m_smpc.SR = 0x40;
state->m_smpc.OREG[31] = 0x10; m_smpc.OREG[31] = 0x10;
machine.scheduler().timer_set(attotime::from_usec(0), FUNC(stv_intback_peripheral),0); machine().scheduler().timer_set(attotime::from_usec(0), timer_expired_delegate(FUNC(saturn_state::stv_intback_peripheral),this),0);
} }
else else
{ {
/* Shienryu calls this, it would be plainly illegal on Saturn, I'll just return the command and clear the hs flag for now. */ /* Shienryu calls this, it would be plainly illegal on Saturn, I'll just return the command and clear the hs flag for now. */
state->m_smpc.OREG[31] = 0x10; m_smpc.OREG[31] = 0x10;
state->m_smpc.SF = 0x00; m_smpc.SF = 0x00;
} }
} }
@ -383,65 +368,62 @@ static TIMER_CALLBACK( stv_smpc_intback )
0x34 keyboard 0x34 keyboard
*/ */
static void smpc_digital_pad(running_machine &machine, UINT8 pad_num, UINT8 offset) void saturn_state::smpc_digital_pad(UINT8 pad_num, UINT8 offset)
{ {
saturn_state *state = machine.driver_data<saturn_state>();
static const char *const padnames[] = { "JOY1", "JOY2" }; static const char *const padnames[] = { "JOY1", "JOY2" };
UINT16 pad_data; UINT16 pad_data;
pad_data = machine.root_device().ioport(padnames[pad_num])->read(); pad_data = ioport(padnames[pad_num])->read();
state->m_smpc.OREG[0+pad_num*offset] = 0xf1; m_smpc.OREG[0+pad_num*offset] = 0xf1;
state->m_smpc.OREG[1+pad_num*offset] = 0x02; m_smpc.OREG[1+pad_num*offset] = 0x02;
state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8; m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
} }
static void smpc_analog_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id) void saturn_state::smpc_analog_pad( UINT8 pad_num, UINT8 offset, UINT8 id)
{ {
saturn_state *state = machine.driver_data<saturn_state>();
static const char *const padnames[] = { "AN_JOY1", "AN_JOY2" }; static const char *const padnames[] = { "AN_JOY1", "AN_JOY2" };
static const char *const annames[2][3] = { { "AN_X1", "AN_Y1", "AN_Z1" }, static const char *const annames[2][3] = { { "AN_X1", "AN_Y1", "AN_Z1" },
{ "AN_X2", "AN_Y2", "AN_Z2" }}; { "AN_X2", "AN_Y2", "AN_Z2" }};
UINT16 pad_data; UINT16 pad_data;
pad_data = machine.root_device().ioport(padnames[pad_num])->read(); pad_data = ioport(padnames[pad_num])->read();
state->m_smpc.OREG[0+pad_num*offset] = 0xf1; m_smpc.OREG[0+pad_num*offset] = 0xf1;
state->m_smpc.OREG[1+pad_num*offset] = id; m_smpc.OREG[1+pad_num*offset] = id;
state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8; m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
state->m_smpc.OREG[4+pad_num*offset] = machine.root_device().ioport(annames[pad_num][0])->read(); m_smpc.OREG[4+pad_num*offset] = ioport(annames[pad_num][0])->read();
if(id == 0x15) if(id == 0x15)
{ {
state->m_smpc.OREG[5+pad_num*offset] = machine.root_device().ioport(annames[pad_num][1])->read(); m_smpc.OREG[5+pad_num*offset] = ioport(annames[pad_num][1])->read();
state->m_smpc.OREG[6+pad_num*offset] = machine.root_device().ioport(annames[pad_num][2])->read(); m_smpc.OREG[6+pad_num*offset] = ioport(annames[pad_num][2])->read();
} }
} }
static void smpc_keyboard(running_machine &machine, UINT8 pad_num, UINT8 offset) void saturn_state::smpc_keyboard(UINT8 pad_num, UINT8 offset)
{ {
saturn_state *state = machine.driver_data<saturn_state>();
UINT16 game_key; UINT16 game_key;
game_key = 0xffff; game_key = 0xffff;
game_key ^= ((state->ioport("KEYS_1")->read() & 0x80) << 8); // right game_key ^= ((ioport("KEYS_1")->read() & 0x80) << 8); // right
game_key ^= ((state->ioport("KEYS_1")->read() & 0x40) << 8); // left game_key ^= ((ioport("KEYS_1")->read() & 0x40) << 8); // left
game_key ^= ((state->ioport("KEYS_1")->read() & 0x20) << 8); // down game_key ^= ((ioport("KEYS_1")->read() & 0x20) << 8); // down
game_key ^= ((state->ioport("KEYS_1")->read() & 0x10) << 8); // up game_key ^= ((ioport("KEYS_1")->read() & 0x10) << 8); // up
game_key ^= ((state->ioport("KEYF")->read() & 0x80) << 4); // ESC -> START game_key ^= ((ioport("KEYF")->read() & 0x80) << 4); // ESC -> START
game_key ^= ((state->ioport("KEY3")->read() & 0x04) << 8); // Z / A trigger game_key ^= ((ioport("KEY3")->read() & 0x04) << 8); // Z / A trigger
game_key ^= ((state->ioport("KEY4")->read() & 0x02) << 8); // C / C trigger game_key ^= ((ioport("KEY4")->read() & 0x02) << 8); // C / C trigger
game_key ^= ((state->ioport("KEY6")->read() & 0x04) << 6); // X / B trigger game_key ^= ((ioport("KEY6")->read() & 0x04) << 6); // X / B trigger
game_key ^= ((state->ioport("KEY2")->read() & 0x20) << 2); // Q / R trigger game_key ^= ((ioport("KEY2")->read() & 0x20) << 2); // Q / R trigger
game_key ^= ((state->ioport("KEY3")->read() & 0x10) << 2); // A / X trigger game_key ^= ((ioport("KEY3")->read() & 0x10) << 2); // A / X trigger
game_key ^= ((state->ioport("KEY3")->read() & 0x08) << 2); // S / Y trigger game_key ^= ((ioport("KEY3")->read() & 0x08) << 2); // S / Y trigger
game_key ^= ((state->ioport("KEY4")->read() & 0x08) << 1); // D / Z trigger game_key ^= ((ioport("KEY4")->read() & 0x08) << 1); // D / Z trigger
game_key ^= ((state->ioport("KEY4")->read() & 0x10) >> 1); // E / L trigger game_key ^= ((ioport("KEY4")->read() & 0x10) >> 1); // E / L trigger
state->m_smpc.OREG[0+pad_num*offset] = 0xf1; m_smpc.OREG[0+pad_num*offset] = 0xf1;
state->m_smpc.OREG[1+pad_num*offset] = 0x34; m_smpc.OREG[1+pad_num*offset] = 0x34;
state->m_smpc.OREG[2+pad_num*offset] = game_key>>8; // game buttons, TODO m_smpc.OREG[2+pad_num*offset] = game_key>>8; // game buttons, TODO
state->m_smpc.OREG[3+pad_num*offset] = game_key & 0xff; m_smpc.OREG[3+pad_num*offset] = game_key & 0xff;
/* /*
x--- ---- 0 x--- ---- 0
-x-- ---- caps lock -x-- ---- caps lock
@ -452,21 +434,20 @@ static void smpc_keyboard(running_machine &machine, UINT8 pad_num, UINT8 offset)
---- --x- 1 ---- --x- 1
---- ---x Break key ---- ---x Break key
*/ */
state->m_smpc.OREG[4+pad_num*offset] = state->m_keyb.status | 6; m_smpc.OREG[4+pad_num*offset] = m_keyb.status | 6;
state->m_smpc.OREG[5+pad_num*offset] = state->m_keyb.data; m_smpc.OREG[5+pad_num*offset] = m_keyb.data;
} }
static void smpc_mouse(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id) void saturn_state::smpc_mouse(UINT8 pad_num, UINT8 offset, UINT8 id)
{ {
saturn_state *state = machine.driver_data<saturn_state>();
static const char *const mousenames[2][3] = { { "MOUSEB1", "MOUSEX1", "MOUSEY1" }, static const char *const mousenames[2][3] = { { "MOUSEB1", "MOUSEX1", "MOUSEY1" },
{ "MOUSEB2", "MOUSEX2", "MOUSEY2" }}; { "MOUSEB2", "MOUSEX2", "MOUSEY2" }};
UINT8 mouse_ctrl; UINT8 mouse_ctrl;
INT16 mouse_x, mouse_y; INT16 mouse_x, mouse_y;
mouse_ctrl = machine.root_device().ioport(mousenames[pad_num][0])->read(); mouse_ctrl = ioport(mousenames[pad_num][0])->read();
mouse_x = machine.root_device().ioport(mousenames[pad_num][1])->read(); mouse_x = ioport(mousenames[pad_num][1])->read();
mouse_y = machine.root_device().ioport(mousenames[pad_num][2])->read(); mouse_y = ioport(mousenames[pad_num][2])->read();
if(mouse_x < 0) if(mouse_x < 0)
mouse_ctrl |= 0x10; mouse_ctrl |= 0x10;
@ -480,38 +461,34 @@ static void smpc_mouse(running_machine &machine, UINT8 pad_num, UINT8 offset, UI
if((mouse_y & 0xff00) != 0xff00 && (mouse_y & 0xff00) != 0x0000) if((mouse_y & 0xff00) != 0xff00 && (mouse_y & 0xff00) != 0x0000)
mouse_ctrl |= 0x80; mouse_ctrl |= 0x80;
state->m_smpc.OREG[0+pad_num*offset] = 0xf1; m_smpc.OREG[0+pad_num*offset] = 0xf1;
state->m_smpc.OREG[1+pad_num*offset] = id; // 0x23 / 0xe3 m_smpc.OREG[1+pad_num*offset] = id; // 0x23 / 0xe3
state->m_smpc.OREG[2+pad_num*offset] = mouse_ctrl; m_smpc.OREG[2+pad_num*offset] = mouse_ctrl;
state->m_smpc.OREG[3+pad_num*offset] = mouse_x & 0xff; m_smpc.OREG[3+pad_num*offset] = mouse_x & 0xff;
state->m_smpc.OREG[4+pad_num*offset] = mouse_y & 0xff; m_smpc.OREG[4+pad_num*offset] = mouse_y & 0xff;
} }
/* TODO: is there ANY game on which the MD pad works? */ /* TODO: is there ANY game on which the MD pad works? */
static void smpc_md_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id) void saturn_state::smpc_md_pad(UINT8 pad_num, UINT8 offset, UINT8 id)
{ {
saturn_state *state = machine.driver_data<saturn_state>();
static const char *const padnames[] = { "MD_JOY1", "MD_JOY2" }; static const char *const padnames[] = { "MD_JOY1", "MD_JOY2" };
UINT16 pad_data; UINT16 pad_data;
pad_data = machine.root_device().ioport(padnames[pad_num])->read(); pad_data = ioport(padnames[pad_num])->read();
state->m_smpc.OREG[0+pad_num*offset] = 0xf1; m_smpc.OREG[0+pad_num*offset] = 0xf1;
state->m_smpc.OREG[1+pad_num*offset] = id; m_smpc.OREG[1+pad_num*offset] = id;
state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8; m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
if(id == 0xe2) // MD 6 Button PAD if(id == 0xe2) // MD 6 Button PAD
state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
} }
static void smpc_unconnected(running_machine &machine, UINT8 pad_num, UINT8 offset) void saturn_state::smpc_unconnected(UINT8 pad_num, UINT8 offset)
{ {
saturn_state *state = machine.driver_data<saturn_state>(); m_smpc.OREG[0+pad_num*offset] = 0xf0;
state->m_smpc.OREG[0+pad_num*offset] = 0xf0;
} }
static TIMER_CALLBACK( intback_peripheral ) TIMER_CALLBACK_MEMBER( saturn_state::intback_peripheral )
{ {
saturn_state *state = machine.driver_data<saturn_state>();
int pad_num; int pad_num;
static const UINT8 peri_id[10] = { 0x02, 0x13, 0x15, 0x23, 0x23, 0x34, 0xe1, 0xe2, 0xe3, 0xff }; static const UINT8 peri_id[10] = { 0x02, 0x13, 0x15, 0x23, 0x23, 0x34, 0xe1, 0xe2, 0xe3, 0xff };
UINT8 read_id[2]; UINT8 read_id[2];
@ -519,13 +496,13 @@ static TIMER_CALLBACK( intback_peripheral )
// if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2); // if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2);
read_id[0] = (machine.root_device().ioport("INPUT_TYPE")->read()) & 0x0f; read_id[0] = (ioport("INPUT_TYPE")->read()) & 0x0f;
read_id[1] = (machine.root_device().ioport("INPUT_TYPE")->read()) >> 4; read_id[1] = (ioport("INPUT_TYPE")->read()) >> 4;
/* doesn't work? */ /* doesn't work? */
//pad_num = state->m_smpc.intback_stage - 1; //pad_num = m_smpc.intback_stage - 1;
if(LOG_PAD_CMD) printf("%d %d %d\n",state->m_smpc.intback_stage - 1,machine.first_screen()->vpos(),(int)machine.first_screen()->frame_number()); if(LOG_PAD_CMD) printf("%d %d %d\n",m_smpc.intback_stage - 1,machine().first_screen()->vpos(),(int)machine().first_screen()->frame_number());
offset = 0; offset = 0;
@ -533,141 +510,134 @@ static TIMER_CALLBACK( intback_peripheral )
{ {
switch(read_id[pad_num]) switch(read_id[pad_num])
{ {
case 0: smpc_digital_pad(machine,pad_num,offset); break; case 0: smpc_digital_pad(pad_num,offset); break;
case 1: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Steering Wheel */ case 1: smpc_analog_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Steering Wheel */
case 2: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Analog Pad */ case 2: smpc_analog_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Analog Pad */
case 4: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Pointing Device */ case 4: smpc_mouse(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Pointing Device */
case 5: smpc_keyboard(machine,pad_num,offset); break; case 5: smpc_keyboard(pad_num,offset); break;
case 6: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 3B PAD */ case 6: smpc_md_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 3B PAD */
case 7: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 6B PAD */ case 7: smpc_md_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 6B PAD */
case 8: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Saturn Mouse */ case 8: smpc_mouse(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Saturn Mouse */
case 9: smpc_unconnected(machine,pad_num,offset); break; case 9: smpc_unconnected(pad_num,offset); break;
} }
offset += (peri_id[read_id[pad_num]] & 0xf) + 2; /* offset for port 2 */ offset += (peri_id[read_id[pad_num]] & 0xf) + 2; /* offset for port 2 */
} }
if (state->m_smpc.intback_stage == 2) if (m_smpc.intback_stage == 2)
{ {
state->m_smpc.SR = (0x80 | state->m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback m_smpc.SR = (0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
state->m_smpc.intback_stage = 0; m_smpc.intback_stage = 0;
} }
else else
{ {
state->m_smpc.SR = (0xc0 | state->m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback m_smpc.SR = (0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
state->m_smpc.intback_stage ++; m_smpc.intback_stage ++;
} }
if(!(state->m_scu.ism & IRQ_SMPC)) if(!(m_scu.ism & IRQ_SMPC))
state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
else else
state->m_scu.ist |= (IRQ_SMPC); m_scu.ist |= (IRQ_SMPC);
state->m_smpc.OREG[31] = 0x10; /* callback for last command issued */ m_smpc.OREG[31] = 0x10; /* callback for last command issued */
state->m_smpc.SF = 0x00; /* clear hand-shake flag */ m_smpc.SF = 0x00; /* clear hand-shake flag */
} }
static TIMER_CALLBACK( saturn_smpc_intback ) TIMER_CALLBACK_MEMBER( saturn_state::saturn_smpc_intback )
{ {
saturn_state *state = machine.driver_data<saturn_state>(); if(m_smpc.intback_buf[0] != 0)
if(state->m_smpc.intback_buf[0] != 0)
{ {
{ {
int i; int i;
state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); // bit 7: SETTIME (RTC isn't setted up properly) m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6); // bit 7: SETTIME (RTC isn't setted up properly)
for(i=0;i<7;i++) for(i=0;i<7;i++)
state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i]; m_smpc.OREG[1+i] = m_smpc.rtc_data[i];
state->m_smpc.OREG[8]=0x00; //Cartridge code? m_smpc.OREG[8]=0x00; //Cartridge code?
state->m_smpc.OREG[9] = state->m_saturn_region; m_smpc.OREG[9] = m_saturn_region;
state->m_smpc.OREG[10]= 0 << 7 | m_smpc.OREG[10]= 0 << 7 |
state->m_vdp2.dotsel << 6 | m_vdp2.dotsel << 6 |
1 << 5 | 1 << 5 |
1 << 4 | 1 << 4 |
0 << 3 | //MSHNMI 0 << 3 | //MSHNMI
1 << 2 | 1 << 2 |
0 << 1 | //SYSRES 0 << 1 | //SYSRES
0 << 0; //SOUNDRES 0 << 0; //SOUNDRES
state->m_smpc.OREG[11]= 0 << 6; //CDRES m_smpc.OREG[11]= 0 << 6; //CDRES
for(i=0;i<4;i++) for(i=0;i<4;i++)
state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i]; m_smpc.OREG[12+i]=m_smpc.SMEM[i];
for(i=0;i<15;i++) for(i=0;i<15;i++)
state->m_smpc.OREG[16+i]=0xff; // undefined m_smpc.OREG[16+i]=0xff; // undefined
} }
state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
state->m_smpc.SR = 0x40 | state->m_smpc.intback_stage << 5; m_smpc.SR = 0x40 | m_smpc.intback_stage << 5;
state->m_smpc.pmode = state->m_smpc.intback_buf[0]>>4; m_smpc.pmode = m_smpc.intback_buf[0]>>4;
if(!(state->m_scu.ism & IRQ_SMPC)) if(!(m_scu.ism & IRQ_SMPC))
state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
else else
state->m_scu.ist |= (IRQ_SMPC); m_scu.ist |= (IRQ_SMPC);
/* put issued command in OREG31 */ /* put issued command in OREG31 */
state->m_smpc.OREG[31] = 0x10; m_smpc.OREG[31] = 0x10;
/* clear hand-shake flag */ /* clear hand-shake flag */
state->m_smpc.SF = 0x00; m_smpc.SF = 0x00;
} }
else if(state->m_smpc.intback_buf[1] & 8) else if(m_smpc.intback_buf[1] & 8)
{ {
state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
state->m_smpc.SR = 0x40; m_smpc.SR = 0x40;
state->m_smpc.OREG[31] = 0x10; m_smpc.OREG[31] = 0x10;
machine.scheduler().timer_set(attotime::from_usec(0), FUNC(intback_peripheral),0); machine().scheduler().timer_set(attotime::from_usec(0), timer_expired_delegate(FUNC(saturn_state::intback_peripheral),this),0);
} }
else else
{ {
printf("SMPC intback bogus behaviour called %02x %02x\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1]); printf("SMPC intback bogus behaviour called %02x %02x\n",m_smpc.IREG[0],m_smpc.IREG[1]);
} }
} }
static void smpc_rtc_write(running_machine &machine) void saturn_state::smpc_rtc_write()
{ {
saturn_state *state = machine.driver_data<saturn_state>();
int i; int i;
for(i=0;i<7;i++) for(i=0;i<7;i++)
state->m_smpc.rtc_data[i] = state->m_smpc.IREG[i]; m_smpc.rtc_data[i] = m_smpc.IREG[i];
} }
static void smpc_memory_setting(running_machine &machine) void saturn_state::smpc_memory_setting()
{ {
saturn_state *state = machine.driver_data<saturn_state>();
int i; int i;
for(i=0;i<4;i++) for(i=0;i<4;i++)
state->m_smpc.SMEM[i] = state->m_smpc.IREG[i]; m_smpc.SMEM[i] = m_smpc.IREG[i];
} }
static void smpc_nmi_req(running_machine &machine) void saturn_state::smpc_nmi_req()
{ {
saturn_state *state = machine.driver_data<saturn_state>();
/*NMI is unconditionally requested */ /*NMI is unconditionally requested */
state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
} }
static TIMER_CALLBACK( smpc_nmi_set ) TIMER_CALLBACK_MEMBER( saturn_state::smpc_nmi_set )
{ {
saturn_state *state = machine.driver_data<saturn_state>(); // printf("%d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos());
// printf("%d %d\n",machine.first_screen()->hpos(),machine.first_screen()->vpos()); m_NMI_reset = param;
state->m_NMI_reset = param;
/* put issued command in OREG31 */ /* put issued command in OREG31 */
state->m_smpc.OREG[31] = 0x19 + param; m_smpc.OREG[31] = 0x19 + param;
/* clear hand-shake flag */ /* clear hand-shake flag */
state->m_smpc.SF = 0x00; m_smpc.SF = 0x00;
//state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); //m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6);
} }
@ -682,42 +652,40 @@ TIMER_CALLBACK_MEMBER( saturn_state::smpc_audio_reset_line_pulse )
* *
*******************************************/ *******************************************/
static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv) void saturn_state::smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv)
{ {
saturn_state *state = space.machine().driver_data<saturn_state>();
switch (data) switch (data)
{ {
case 0x00: case 0x00:
if(LOG_SMPC) printf ("SMPC: Master ON\n"); if(LOG_SMPC) printf ("SMPC: Master ON\n");
smpc_master_on(space.machine()); smpc_master_on();
break; break;
//case 0x01: Master OFF? //case 0x01: Master OFF?
case 0x02: case 0x02:
case 0x03: case 0x03:
if(LOG_SMPC) printf ("SMPC: Slave %s %d %d\n",(data & 1) ? "off" : "on",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); if(LOG_SMPC) printf ("SMPC: Slave %s %d %d\n",(data & 1) ? "off" : "on",machine().first_screen()->hpos(),machine().first_screen()->vpos());
space.machine().scheduler().timer_set(attotime::from_usec(15), FUNC(smpc_slave_enable),data & 1); machine().scheduler().timer_set(attotime::from_usec(15), timer_expired_delegate(FUNC(saturn_state::smpc_slave_enable),this),data & 1);
break; break;
case 0x06: case 0x06:
case 0x07: case 0x07:
if(LOG_SMPC) printf ("SMPC: Sound %s\n",(data & 1) ? "off" : "on"); if(LOG_SMPC) printf ("SMPC: Sound %s\n",(data & 1) ? "off" : "on");
if(!is_stv) if(!is_stv)
space.machine().scheduler().timer_set(attotime::from_usec(15), FUNC(smpc_sound_enable),data & 1); machine().scheduler().timer_set(attotime::from_usec(15), timer_expired_delegate(FUNC(saturn_state::smpc_sound_enable),this),data & 1);
break; break;
/*CD (SH-1) ON/OFF */ /*CD (SH-1) ON/OFF */
case 0x08: case 0x08:
case 0x09: case 0x09:
printf ("SMPC: CD %s\n",(data & 1) ? "off" : "on"); printf ("SMPC: CD %s\n",(data & 1) ? "off" : "on");
space.machine().scheduler().timer_set(attotime::from_usec(20), FUNC(smpc_cd_enable),data & 1); machine().scheduler().timer_set(attotime::from_usec(20), timer_expired_delegate(FUNC(saturn_state::smpc_cd_enable),this),data & 1);
break; break;
case 0x0d: case 0x0d:
if(LOG_SMPC) printf ("SMPC: System Reset\n"); if(LOG_SMPC) printf ("SMPC: System Reset\n");
smpc_system_reset(space.machine()); smpc_system_reset();
break; break;
case 0x0e: case 0x0e:
case 0x0f: case 0x0f:
if(LOG_SMPC) printf ("SMPC: Change Clock to %s (%d %d)\n",data & 1 ? "320" : "352",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); if(LOG_SMPC) printf ("SMPC: Change Clock to %s (%d %d)\n",data & 1 ? "320" : "352",machine().first_screen()->hpos(),machine().first_screen()->vpos());
/* on ST-V timing of this is pretty fussy, you get 2 credits at start-up otherwise /* on ST-V timing of this is pretty fussy, you get 2 credits at start-up otherwise
My current theory is that SMPC first stops all CPUs until it executes the whole snippet for this, My current theory is that SMPC first stops all CPUs until it executes the whole snippet for this,
@ -725,29 +693,28 @@ static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv)
can do an usable mid-frame clock switching anyway. can do an usable mid-frame clock switching anyway.
*/ */
state->m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
state->m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
state->m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
space.machine().scheduler().timer_set(space.machine().first_screen()->time_until_pos(state->get_vblank_start_position()*state->get_ystep_count(), 0), FUNC(smpc_change_clock),data & 1); machine().scheduler().timer_set(machine().first_screen()->time_until_pos(get_vblank_start_position()*get_ystep_count(), 0), timer_expired_delegate(FUNC(saturn_state::smpc_change_clock),this),data & 1);
break; break;
/*"Interrupt Back"*/ /*"Interrupt Back"*/
case 0x10: case 0x10:
if(0) if(0)
{ {
saturn_state *state = space.machine().driver_data<saturn_state>(); printf ("SMPC: Status Acquire %02x %02x %02x %d\n",m_smpc.IREG[0],m_smpc.IREG[1],m_smpc.IREG[2],machine().first_screen()->vpos());
printf ("SMPC: Status Acquire %02x %02x %02x %d\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1],state->m_smpc.IREG[2],space.machine().first_screen()->vpos());
} }
int timing; int timing;
timing = 8; timing = 8;
if(state->m_smpc.IREG[0] != 0) // non-peripheral data if(m_smpc.IREG[0] != 0) // non-peripheral data
timing += 8; timing += 8;
/* TODO: At vblank-out actually ... */ /* TODO: At vblank-out actually ... */
if(state->m_smpc.IREG[1] & 8) // peripheral data if(m_smpc.IREG[1] & 8) // peripheral data
timing += 700; timing += 700;
/* TODO: check if IREG[2] is setted to 0xf0 */ /* TODO: check if IREG[2] is setted to 0xf0 */
@ -755,38 +722,38 @@ static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv)
int i; int i;
for(i=0;i<3;i++) for(i=0;i<3;i++)
state->m_smpc.intback_buf[i] = state->m_smpc.IREG[i]; m_smpc.intback_buf[i] = m_smpc.IREG[i];
} }
if(is_stv) if(is_stv)
{ {
space.machine().scheduler().timer_set(attotime::from_usec(timing), FUNC(stv_smpc_intback),0); //TODO: variable time machine().scheduler().timer_set(attotime::from_usec(timing), timer_expired_delegate(FUNC(saturn_state::stv_smpc_intback),this),0); //TODO: variable time
} }
else else
{ {
if(LOG_PAD_CMD) printf("INTBACK %02x %02x %d %d\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1],space.machine().first_screen()->vpos(),(int)space.machine().first_screen()->frame_number()); if(LOG_PAD_CMD) printf("INTBACK %02x %02x %d %d\n",m_smpc.IREG[0],m_smpc.IREG[1],machine().first_screen()->vpos(),(int)machine().first_screen()->frame_number());
space.machine().scheduler().timer_set(attotime::from_usec(timing), FUNC(saturn_smpc_intback),0); //TODO: is variable time correct? machine().scheduler().timer_set(attotime::from_usec(timing), timer_expired_delegate(FUNC(saturn_state::saturn_smpc_intback),this),0); //TODO: is variable time correct?
} }
break; break;
/* RTC write*/ /* RTC write*/
case 0x16: case 0x16:
if(LOG_SMPC) printf("SMPC: RTC write\n"); if(LOG_SMPC) printf("SMPC: RTC write\n");
smpc_rtc_write(space.machine()); smpc_rtc_write();
break; break;
/* SMPC memory setting*/ /* SMPC memory setting*/
case 0x17: case 0x17:
if(LOG_SMPC) printf ("SMPC: memory setting\n"); if(LOG_SMPC) printf ("SMPC: memory setting\n");
smpc_memory_setting(space.machine()); smpc_memory_setting();
break; break;
case 0x18: case 0x18:
if(LOG_SMPC) printf ("SMPC: NMI request\n"); if(LOG_SMPC) printf ("SMPC: NMI request\n");
smpc_nmi_req(space.machine()); smpc_nmi_req();
break; break;
case 0x19: case 0x19:
case 0x1a: case 0x1a:
/* TODO: timing */ /* TODO: timing */
if(LOG_SMPC) printf ("SMPC: NMI %sable %d %d\n",data & 1 ? "Dis" : "En",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); if(LOG_SMPC) printf ("SMPC: NMI %sable %d %d\n",data & 1 ? "Dis" : "En",machine().first_screen()->hpos(),machine().first_screen()->vpos());
space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_nmi_set),data & 1); machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_nmi_set),this),data & 1);
break; break;
default: default:
printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space.device().tag(), space.device().safe_pc(), data); printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space.device().tag(), space.device().safe_pc(), data);
@ -799,60 +766,57 @@ static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv)
* *
*******************************************/ *******************************************/
READ8_HANDLER( stv_SMPC_r ) READ8_MEMBER( saturn_state::stv_SMPC_r )
{ {
saturn_state *state = space.machine().driver_data<saturn_state>();
int return_data = 0; int return_data = 0;
if(!(offset & 1)) if(!(offset & 1))
return 0; return 0;
if(offset >= 0x21 && offset <= 0x5f) if(offset >= 0x21 && offset <= 0x5f)
return_data = state->m_smpc.OREG[(offset-0x21) >> 1]; return_data = m_smpc.OREG[(offset-0x21) >> 1];
if (offset == 0x61) // TODO: SR if (offset == 0x61) // TODO: SR
return_data = state->m_smpc.SR; return_data = m_smpc.SR;
if (offset == 0x63) if (offset == 0x63)
return_data = state->m_smpc.SF; return_data = m_smpc.SF;
if (offset == 0x75)//PDR1 read if (offset == 0x75)//PDR1 read
return_data = state->ioport("DSW1")->read(); return_data = ioport("DSW1")->read();
if (offset == 0x77)//PDR2 read if (offset == 0x77)//PDR2 read
return_data = (0xfe | state->m_eeprom->do_read()); return_data = (0xfe | m_eeprom->do_read());
return return_data; return return_data;
} }
WRITE8_HANDLER( stv_SMPC_w ) WRITE8_MEMBER( saturn_state::stv_SMPC_w )
{ {
saturn_state *state = space.machine().driver_data<saturn_state>();
if (!(offset & 1)) // avoid writing to even bytes if (!(offset & 1)) // avoid writing to even bytes
return; return;
// if(LOG_SMPC) printf ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data); // if(LOG_SMPC) printf ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data);
if(offset >= 1 && offset <= 0xd) if(offset >= 1 && offset <= 0xd)
state->m_smpc.IREG[offset >> 1] = data; m_smpc.IREG[offset >> 1] = data;
if(offset == 1) //IREG0, check if a BREAK / CONTINUE request for INTBACK command if(offset == 1) //IREG0, check if a BREAK / CONTINUE request for INTBACK command
{ {
if(state->m_smpc.intback_stage) if(m_smpc.intback_stage)
{ {
if(data & 0x40) if(data & 0x40)
{ {
if(LOG_PAD_CMD) printf("SMPC: BREAK request\n"); if(LOG_PAD_CMD) printf("SMPC: BREAK request\n");
state->m_smpc.SR &= 0x0f; m_smpc.SR &= 0x0f;
state->m_smpc.intback_stage = 0; m_smpc.intback_stage = 0;
} }
else if(data & 0x80) else if(data & 0x80)
{ {
if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n"); if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n");
space.machine().scheduler().timer_set(attotime::from_usec(700), FUNC(stv_intback_peripheral),0); /* TODO: is timing correct? */ machine().scheduler().timer_set(attotime::from_usec(700), timer_expired_delegate(FUNC(saturn_state::stv_intback_peripheral),this),0); /* TODO: is timing correct? */
state->m_smpc.OREG[31] = 0x10; m_smpc.OREG[31] = 0x10;
state->m_smpc.SF = 0x01; //TODO: set hand-shake flag? m_smpc.SF = 0x01; //TODO: set hand-shake flag?
} }
} }
} }
@ -864,14 +828,14 @@ WRITE8_HANDLER( stv_SMPC_w )
// we've processed the command, clear status flag // we've processed the command, clear status flag
if(data != 0x10 && data != 0x02 && data != 0x03 && data != 0x08 && data != 0x09 && data != 0xe && data != 0xf && data != 0x19 && data != 0x1a) if(data != 0x10 && data != 0x02 && data != 0x03 && data != 0x08 && data != 0x09 && data != 0xe && data != 0xf && data != 0x19 && data != 0x1a)
{ {
state->m_smpc.OREG[31] = data; //read-back command m_smpc.OREG[31] = data; //read-back command
state->m_smpc.SF = 0x00; m_smpc.SF = 0x00;
} }
/*TODO:emulate the timing of each command...*/ /*TODO:emulate the timing of each command...*/
} }
if(offset == 0x63) if(offset == 0x63)
state->m_smpc.SF = data & 1; m_smpc.SF = data & 1;
if(offset == 0x75) if(offset == 0x75)
{ {
@ -882,14 +846,14 @@ WRITE8_HANDLER( stv_SMPC_w )
---- -x-- EEPROM CS line ---- -x-- EEPROM CS line
---- --xx A-Bus bank bits ---- --xx A-Bus bank bits
*/ */
state->m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE); m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
state->m_eeprom->di_write((data >> 4) & 1); m_eeprom->di_write((data >> 4) & 1);
state->m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE); m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE);
state->m_stv_multi_bank = data & 3; m_stv_multi_bank = data & 3;
stv_select_game(space.machine(), state->m_stv_multi_bank); stv_select_game(m_stv_multi_bank);
state->m_smpc.PDR1 = (data & 0x60); m_smpc.PDR1 = (data & 0x60);
} }
if(offset == 0x77) if(offset == 0x77)
@ -898,15 +862,15 @@ WRITE8_HANDLER( stv_SMPC_w )
-xx- ---- PDR2 -xx- ---- PDR2
---x ---- Enable Sound System (ACTIVE LOW) ---x ---- Enable Sound System (ACTIVE LOW)
*/ */
//popmessage("PDR2 = %02x",state->m_smpc_ram[0x77]); //popmessage("PDR2 = %02x",m_smpc_ram[0x77]);
if(LOG_SMPC) printf("SMPC: M68k %s\n",(data & 0x10) ? "off" : "on"); if(LOG_SMPC) printf("SMPC: M68k %s\n",(data & 0x10) ? "off" : "on");
//space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_sound_enable),(state->m_smpc_ram[0x77] & 0x10) >> 4); //machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_sound_enable),this),(m_smpc_ram[0x77] & 0x10) >> 4);
state->m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE); m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
state->m_en_68k = ((data & 0x10) >> 4) ^ 1; m_en_68k = ((data & 0x10) >> 4) ^ 1;
//if(LOG_SMPC) printf("SMPC: ram [0x77] = %02x\n",data); //if(LOG_SMPC) printf("SMPC: ram [0x77] = %02x\n",data);
state->m_smpc.PDR2 = (data & 0x60); m_smpc.PDR2 = (data & 0x60);
} }
if(offset == 0x7d) if(offset == 0x7d)
@ -915,15 +879,15 @@ WRITE8_HANDLER( stv_SMPC_w )
---- --x- IOSEL2 direct (1) / control mode (0) port select ---- --x- IOSEL2 direct (1) / control mode (0) port select
---- ---x IOSEL1 direct (1) / control mode (0) port select ---- ---x IOSEL1 direct (1) / control mode (0) port select
*/ */
state->m_smpc.IOSEL1 = (data & 1) >> 0; m_smpc.IOSEL1 = (data & 1) >> 0;
state->m_smpc.IOSEL2 = (data & 2) >> 1; m_smpc.IOSEL2 = (data & 2) >> 1;
} }
if(offset == 0x7f) if(offset == 0x7f)
{ {
//enable PAD irq & VDP2 external latch for port 1/2 //enable PAD irq & VDP2 external latch for port 1/2
state->m_smpc.EXLE1 = (data & 1) >> 0; m_smpc.EXLE1 = (data & 1) >> 0;
state->m_smpc.EXLE2 = (data & 2) >> 1; m_smpc.EXLE2 = (data & 2) >> 1;
} }
} }
@ -1001,7 +965,7 @@ READ8_MEMBER( saturn_state::saturn_SMPC_r )
if (offset == 0x63) if (offset == 0x63)
{ {
//printf("SF %d %d\n",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); //printf("SF %d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos());
return_data = m_smpc.SF; return_data = m_smpc.SF;
} }
@ -1060,7 +1024,7 @@ WRITE8_MEMBER( saturn_state::saturn_SMPC_w )
else if(data & 0x80) else if(data & 0x80)
{ {
if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n"); if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n");
machine().scheduler().timer_set(attotime::from_usec(700), FUNC(intback_peripheral),0); /* TODO: is timing correct? */ 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.OREG[31] = 0x10;
m_smpc.SF = 0x01; //TODO: set hand-shake flag? m_smpc.SF = 0x01; //TODO: set hand-shake flag?
} }

View File

@ -1,4 +1,5 @@
DECLARE_WRITE8_HANDLER( stv_SMPC_w ); // TODO: make separate device when code is decoupled better
DECLARE_READ8_HANDLER( stv_SMPC_r ); //DECLARE_WRITE8_MEMBER( stv_SMPC_w );
DECLARE_WRITE8_HANDLER( saturn_SMPC_w ); //DECLARE_READ8_MEMBER( stv_SMPC_r );
DECLARE_READ8_HANDLER( saturn_SMPC_r ); //DECLARE_WRITE8_MEMBER( saturn_SMPC_w );
//DECLARE_READ8_MEMBER( saturn_SMPC_r );

View File

@ -429,12 +429,12 @@ READ32_MEMBER ( saturn_state::saturn_vdp1_framebuffer0_r )
} }
#ifdef UNUSED_FUNCTION #ifdef UNUSED_FUNCTION
WRITE32_HANDLER ( saturn_vdp1_framebuffer1_w ) WRITE32_MEMBER ( saturn_state::saturn_vdp1_framebuffer1_w )
{ {
//popmessage ("STV VDP1 Framebuffer 1 WRITE offset %08x data %08x",offset, data); //popmessage ("STV VDP1 Framebuffer 1 WRITE offset %08x data %08x",offset, data);
} }
READ32_HANDLER ( saturn_vdp1_framebuffer1_r ) READ32_MEMBER ( saturn_state::saturn_vdp1_framebuffer1_r )
{ {
//popmessage ("STV VDP1 Framebuffer 1 READ offset %08x",offset); //popmessage ("STV VDP1 Framebuffer 1 READ offset %08x",offset);
return 0xffff; return 0xffff;

View File

@ -927,7 +927,7 @@ static const sh2_cpu_core sh2_conf_slave = { 1, NULL };
static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32, stv_state ) static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32, stv_state )
AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6") // bios AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6") // bios
AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8_LEGACY(stv_SMPC_r, stv_SMPC_w,0xffffffff) AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(stv_SMPC_r, stv_SMPC_w,0xffffffff)
AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r,saturn_backupram_w,0xffffffff) AM_SHARE("share1") AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r,saturn_backupram_w,0xffffffff) AM_SHARE("share1")
AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l") AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l")
// AM_RANGE(0x00400000, 0x0040001f) AM_READWRITE(stv_ioga_r32, stv_io_w32) AM_SHARE("ioga") AM_MIRROR(0x20) /* installed with per-game specific */ // AM_RANGE(0x00400000, 0x0040001f) AM_READWRITE(stv_ioga_r32, stv_io_w32) AM_SHARE("ioga") AM_MIRROR(0x20) /* installed with per-game specific */

View File

@ -645,6 +645,34 @@ public:
DECLARE_WRITE_LINE_MEMBER(scudsp_end_w); DECLARE_WRITE_LINE_MEMBER(scudsp_end_w);
DECLARE_READ16_MEMBER(scudsp_dma_r); DECLARE_READ16_MEMBER(scudsp_dma_r);
DECLARE_WRITE16_MEMBER(scudsp_dma_w); DECLARE_WRITE16_MEMBER(scudsp_dma_w);
// FROM smpc.c
TIMER_CALLBACK_MEMBER( stv_bankswitch_state );
void stv_select_game(int gameno);
void smpc_master_on();
TIMER_CALLBACK_MEMBER( smpc_slave_enable );
TIMER_CALLBACK_MEMBER( smpc_sound_enable );
TIMER_CALLBACK_MEMBER( smpc_cd_enable );
void smpc_system_reset();
TIMER_CALLBACK_MEMBER( smpc_change_clock );
TIMER_CALLBACK_MEMBER( stv_intback_peripheral );
TIMER_CALLBACK_MEMBER( stv_smpc_intback );
void smpc_digital_pad(UINT8 pad_num, UINT8 offset);
void smpc_analog_pad(UINT8 pad_num, UINT8 offset, UINT8 id);
void smpc_keyboard(UINT8 pad_num, UINT8 offset);
void smpc_mouse(UINT8 pad_num, UINT8 offset, UINT8 id);
void smpc_md_pad(UINT8 pad_num, UINT8 offset, UINT8 id);
void smpc_unconnected(UINT8 pad_num, UINT8 offset);
TIMER_CALLBACK_MEMBER( intback_peripheral );
TIMER_CALLBACK_MEMBER( saturn_smpc_intback );
void smpc_rtc_write();
void smpc_memory_setting();
void smpc_nmi_req();
TIMER_CALLBACK_MEMBER( smpc_nmi_set );
void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv);
DECLARE_READ8_MEMBER( stv_SMPC_r );
DECLARE_WRITE8_MEMBER( stv_SMPC_w );
}; };
class stv_state : public saturn_state class stv_state : public saturn_state