trunk/src/emu/machine/smpc.c
| r29211 | r29212 | |
| 164 | 164 | * |
| 165 | 165 | *******************************************/ |
| 166 | 166 | |
| 167 | | static TIMER_CALLBACK( stv_bankswitch_state ) |
| 167 | TIMER_CALLBACK_MEMBER( saturn_state::stv_bankswitch_state ) |
| 168 | 168 | { |
| 169 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 170 | 169 | static const char *const banknames[] = { "game0", "game1", "game2", "game3" }; |
| 171 | 170 | UINT8* game_region; |
| 172 | 171 | |
| 173 | | if(state->m_prev_bankswitch != param) |
| 172 | if(m_prev_bankswitch != param) |
| 174 | 173 | { |
| 175 | | game_region = machine.root_device().memregion(banknames[param])->base(); |
| 174 | game_region = memregion(banknames[param])->base(); |
| 176 | 175 | |
| 177 | 176 | if (game_region) |
| 178 | | memcpy(machine.root_device().memregion("abus")->base(), game_region, 0x3000000); |
| 177 | memcpy(memregion("abus")->base(), game_region, 0x3000000); |
| 179 | 178 | else |
| 180 | | memset(machine.root_device().memregion("abus")->base(), 0x00, 0x3000000); |
| 179 | memset(memregion("abus")->base(), 0x00, 0x3000000); |
| 181 | 180 | |
| 182 | | state->m_prev_bankswitch = param; |
| 181 | m_prev_bankswitch = param; |
| 183 | 182 | } |
| 184 | 183 | } |
| 185 | 184 | |
| 186 | | static void stv_select_game(running_machine &machine, int gameno) |
| 185 | void saturn_state::stv_select_game(int gameno) |
| 187 | 186 | { |
| 188 | | machine.scheduler().timer_set(attotime::zero, FUNC(stv_bankswitch_state), gameno); |
| 187 | machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(saturn_state::stv_bankswitch_state),this), gameno); |
| 189 | 188 | } |
| 190 | 189 | |
| 191 | 190 | /******************************************** |
| r29211 | r29212 | |
| 194 | 193 | * |
| 195 | 194 | *******************************************/ |
| 196 | 195 | |
| 197 | | static void smpc_master_on(running_machine &machine) |
| 196 | void saturn_state::smpc_master_on() |
| 198 | 197 | { |
| 199 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 200 | | |
| 201 | | state->m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); |
| 198 | m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); |
| 202 | 199 | } |
| 203 | 200 | |
| 204 | | static TIMER_CALLBACK( smpc_slave_enable ) |
| 201 | TIMER_CALLBACK_MEMBER( saturn_state::smpc_slave_enable ) |
| 205 | 202 | { |
| 206 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 207 | | |
| 208 | | state->m_slave->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE); |
| 209 | | state->m_smpc.OREG[31] = param + 0x02; //read-back for last command issued |
| 210 | | state->m_smpc.SF = 0x00; //clear hand-shake flag |
| 211 | | state->m_smpc.slave_on = param; |
| 212 | | // printf("%d %d\n",machine.first_screen()->hpos(),machine.first_screen()->vpos()); |
| 203 | m_slave->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE); |
| 204 | m_smpc.OREG[31] = param + 0x02; //read-back for last command issued |
| 205 | m_smpc.SF = 0x00; //clear hand-shake flag |
| 206 | m_smpc.slave_on = param; |
| 207 | // printf("%d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 213 | 208 | } |
| 214 | 209 | |
| 215 | | static TIMER_CALLBACK( smpc_sound_enable ) |
| 210 | TIMER_CALLBACK_MEMBER( saturn_state::smpc_sound_enable ) |
| 216 | 211 | { |
| 217 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 218 | | |
| 219 | | state->m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE); |
| 220 | | state->m_en_68k = param ^ 1; |
| 221 | | state->m_smpc.OREG[31] = param + 0x06; //read-back for last command issued |
| 222 | | state->m_smpc.SF = 0x00; //clear hand-shake flag |
| 212 | m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE); |
| 213 | m_en_68k = param ^ 1; |
| 214 | m_smpc.OREG[31] = param + 0x06; //read-back for last command issued |
| 215 | m_smpc.SF = 0x00; //clear hand-shake flag |
| 223 | 216 | } |
| 224 | 217 | |
| 225 | | static TIMER_CALLBACK( smpc_cd_enable ) |
| 218 | TIMER_CALLBACK_MEMBER( saturn_state::smpc_cd_enable ) |
| 226 | 219 | { |
| 227 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 228 | | |
| 229 | | state->m_smpc.OREG[31] = param + 0x08; //read-back for last command issued |
| 230 | | state->m_smpc.SF = 0x08; //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high) |
| 220 | m_smpc.OREG[31] = param + 0x08; //read-back for last command issued |
| 221 | m_smpc.SF = 0x08; //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high) |
| 231 | 222 | } |
| 232 | 223 | |
| 233 | | static void smpc_system_reset(running_machine &machine) |
| 224 | void saturn_state::smpc_system_reset() |
| 234 | 225 | { |
| 235 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 236 | | |
| 237 | 226 | /*Only backup ram and SMPC ram are retained after that this command is issued.*/ |
| 238 | | memset(state->m_scu_regs ,0x00,0x000100); |
| 239 | | memset(state->m_scsp_regs,0x00,0x001000); |
| 240 | | memset(state->m_sound_ram,0x00,0x080000); |
| 241 | | memset(state->m_workram_h,0x00,0x100000); |
| 242 | | memset(state->m_workram_l,0x00,0x100000); |
| 243 | | memset(state->m_vdp2_regs,0x00,0x040000); |
| 244 | | memset(state->m_vdp2_vram,0x00,0x100000); |
| 245 | | memset(state->m_vdp2_cram,0x00,0x080000); |
| 246 | | memset(state->m_vdp1_vram,0x00,0x100000); |
| 227 | memset(m_scu_regs ,0x00,0x000100); |
| 228 | memset(m_scsp_regs,0x00,0x001000); |
| 229 | memset(m_sound_ram,0x00,0x080000); |
| 230 | memset(m_workram_h,0x00,0x100000); |
| 231 | memset(m_workram_l,0x00,0x100000); |
| 232 | memset(m_vdp2_regs,0x00,0x040000); |
| 233 | memset(m_vdp2_vram,0x00,0x100000); |
| 234 | memset(m_vdp2_cram,0x00,0x080000); |
| 235 | memset(m_vdp1_vram,0x00,0x100000); |
| 247 | 236 | //A-Bus |
| 248 | 237 | |
| 249 | | state->m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE); |
| 238 | m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE); |
| 250 | 239 | } |
| 251 | 240 | |
| 252 | | static TIMER_CALLBACK( smpc_change_clock ) |
| 241 | TIMER_CALLBACK_MEMBER( saturn_state::smpc_change_clock ) |
| 253 | 242 | { |
| 254 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 255 | 243 | UINT32 xtal; |
| 256 | 244 | |
| 257 | | if(LOG_SMPC) printf ("Clock change execute at (%d %d)\n",machine.first_screen()->hpos(),machine.first_screen()->vpos()); |
| 245 | if(LOG_SMPC) printf ("Clock change execute at (%d %d)\n",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 258 | 246 | |
| 259 | 247 | xtal = param ? MASTER_CLOCK_320 : MASTER_CLOCK_352; |
| 260 | 248 | |
| 261 | | machine.device("maincpu")->set_unscaled_clock(xtal/2); |
| 262 | | machine.device("slave")->set_unscaled_clock(xtal/2); |
| 249 | machine().device("maincpu")->set_unscaled_clock(xtal/2); |
| 250 | machine().device("slave")->set_unscaled_clock(xtal/2); |
| 263 | 251 | |
| 264 | | state->m_vdp2.dotsel = param ^ 1; |
| 265 | | state->stv_vdp2_dynamic_res_change(); |
| 252 | m_vdp2.dotsel = param ^ 1; |
| 253 | stv_vdp2_dynamic_res_change(); |
| 266 | 254 | |
| 267 | | state->m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 268 | | if(!state->m_NMI_reset) |
| 269 | | state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 270 | | state->m_slave->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 271 | | state->m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 272 | | state->m_audiocpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 255 | m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 256 | if(!m_NMI_reset) |
| 257 | m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 258 | m_slave->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 259 | m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 260 | m_audiocpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 273 | 261 | |
| 274 | 262 | /* put issued command in OREG31 */ |
| 275 | | state->m_smpc.OREG[31] = 0x0e + param; |
| 263 | m_smpc.OREG[31] = 0x0e + param; |
| 276 | 264 | /* clear hand-shake flag */ |
| 277 | | state->m_smpc.SF = 0x00; |
| 265 | m_smpc.SF = 0x00; |
| 278 | 266 | |
| 279 | 267 | /* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values? */ |
| 280 | 268 | } |
| 281 | 269 | |
| 282 | | static TIMER_CALLBACK( stv_intback_peripheral ) |
| 270 | TIMER_CALLBACK_MEMBER( saturn_state::stv_intback_peripheral ) |
| 283 | 271 | { |
| 284 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 285 | | |
| 286 | | if (state->m_smpc.intback_stage == 2) |
| 272 | if (m_smpc.intback_stage == 2) |
| 287 | 273 | { |
| 288 | | state->m_smpc.SR = (0x80 | state->m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback |
| 289 | | state->m_smpc.intback_stage = 0; |
| 274 | m_smpc.SR = (0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback |
| 275 | m_smpc.intback_stage = 0; |
| 290 | 276 | } |
| 291 | 277 | else |
| 292 | 278 | { |
| 293 | | state->m_smpc.SR = (0xc0 | state->m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback |
| 294 | | state->m_smpc.intback_stage ++; |
| 279 | m_smpc.SR = (0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback |
| 280 | m_smpc.intback_stage ++; |
| 295 | 281 | } |
| 296 | 282 | |
| 297 | | if(!(state->m_scu.ism & IRQ_SMPC)) |
| 298 | | state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 283 | if(!(m_scu.ism & IRQ_SMPC)) |
| 284 | m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 299 | 285 | else |
| 300 | | state->m_scu.ist |= (IRQ_SMPC); |
| 286 | m_scu.ist |= (IRQ_SMPC); |
| 301 | 287 | |
| 302 | | state->m_smpc.OREG[31] = 0x10; /* callback for last command issued */ |
| 303 | | state->m_smpc.SF = 0x00; /* clear hand-shake flag */ |
| 288 | m_smpc.OREG[31] = 0x10; /* callback for last command issued */ |
| 289 | m_smpc.SF = 0x00; /* clear hand-shake flag */ |
| 304 | 290 | } |
| 305 | 291 | |
| 306 | 292 | |
| 307 | | static TIMER_CALLBACK( stv_smpc_intback ) |
| 293 | TIMER_CALLBACK_MEMBER( saturn_state::stv_smpc_intback ) |
| 308 | 294 | { |
| 309 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 310 | 295 | int i; |
| 311 | 296 | |
| 312 | | // printf("%02x %02x %02x\n",state->m_smpc.intback_buf[0],state->m_smpc.intback_buf[1],state->m_smpc.intback_buf[2]); |
| 297 | // printf("%02x %02x %02x\n",m_smpc.intback_buf[0],m_smpc.intback_buf[1],m_smpc.intback_buf[2]); |
| 313 | 298 | |
| 314 | | if(state->m_smpc.intback_buf[0] != 0) |
| 299 | if(m_smpc.intback_buf[0] != 0) |
| 315 | 300 | { |
| 316 | | state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); |
| 301 | m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6); |
| 317 | 302 | |
| 318 | 303 | for(i=0;i<7;i++) |
| 319 | | state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i]; |
| 304 | m_smpc.OREG[1+i] = m_smpc.rtc_data[i]; |
| 320 | 305 | |
| 321 | | state->m_smpc.OREG[8]=0x00; // CTG0 / CTG1? |
| 306 | m_smpc.OREG[8]=0x00; // CTG0 / CTG1? |
| 322 | 307 | |
| 323 | | state->m_smpc.OREG[9]=0x00; // TODO: system region on Saturn |
| 308 | m_smpc.OREG[9]=0x00; // TODO: system region on Saturn |
| 324 | 309 | |
| 325 | | state->m_smpc.OREG[10]= 0 << 7 | |
| 326 | | state->m_vdp2.dotsel << 6 | |
| 310 | m_smpc.OREG[10]= 0 << 7 | |
| 311 | m_vdp2.dotsel << 6 | |
| 327 | 312 | 1 << 5 | |
| 328 | 313 | 1 << 4 | |
| 329 | 314 | 0 << 3 | //MSHNMI |
| 330 | 315 | 1 << 2 | |
| 331 | 316 | 0 << 1 | //SYSRES |
| 332 | 317 | 0 << 0; //SOUNDRES |
| 333 | | state->m_smpc.OREG[11]= 0 << 6; //CDRES |
| 318 | m_smpc.OREG[11]= 0 << 6; //CDRES |
| 334 | 319 | |
| 335 | 320 | for(i=0;i<4;i++) |
| 336 | | state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i]; |
| 321 | m_smpc.OREG[12+i]=m_smpc.SMEM[i]; |
| 337 | 322 | |
| 338 | 323 | for(i=0;i<15;i++) |
| 339 | | state->m_smpc.OREG[16+i]=0xff; // undefined |
| 324 | m_smpc.OREG[16+i]=0xff; // undefined |
| 340 | 325 | |
| 341 | | state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 342 | | state->m_smpc.SR = 0x40 | state->m_smpc.intback_stage << 5; |
| 343 | | state->m_smpc.pmode = state->m_smpc.intback_buf[0]>>4; |
| 326 | m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 327 | m_smpc.SR = 0x40 | m_smpc.intback_stage << 5; |
| 328 | m_smpc.pmode = m_smpc.intback_buf[0]>>4; |
| 344 | 329 | |
| 345 | 330 | // /*This is for RTC,cartridge code and similar stuff...*/ |
| 346 | 331 | //if(LOG_SMPC) printf ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline); |
| 347 | | if(!(state->m_scu.ism & IRQ_SMPC)) |
| 348 | | state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 332 | if(!(m_scu.ism & IRQ_SMPC)) |
| 333 | m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 349 | 334 | else |
| 350 | | state->m_scu.ist |= (IRQ_SMPC); |
| 335 | m_scu.ist |= (IRQ_SMPC); |
| 351 | 336 | |
| 352 | 337 | /* put issued command in OREG31 */ |
| 353 | | state->m_smpc.OREG[31] = 0x10; // TODO: doc says 0? |
| 338 | m_smpc.OREG[31] = 0x10; // TODO: doc says 0? |
| 354 | 339 | /* clear hand-shake flag */ |
| 355 | | state->m_smpc.SF = 0x00; |
| 340 | m_smpc.SF = 0x00; |
| 356 | 341 | } |
| 357 | | else if(state->m_smpc.intback_buf[1] & 8) |
| 342 | else if(m_smpc.intback_buf[1] & 8) |
| 358 | 343 | { |
| 359 | | state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 360 | | state->m_smpc.SR = 0x40; |
| 361 | | state->m_smpc.OREG[31] = 0x10; |
| 362 | | machine.scheduler().timer_set(attotime::from_usec(0), FUNC(stv_intback_peripheral),0); |
| 344 | m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 345 | m_smpc.SR = 0x40; |
| 346 | m_smpc.OREG[31] = 0x10; |
| 347 | machine().scheduler().timer_set(attotime::from_usec(0), timer_expired_delegate(FUNC(saturn_state::stv_intback_peripheral),this),0); |
| 363 | 348 | } |
| 364 | 349 | else |
| 365 | 350 | { |
| 366 | 351 | /* Shienryu calls this, it would be plainly illegal on Saturn, I'll just return the command and clear the hs flag for now. */ |
| 367 | | state->m_smpc.OREG[31] = 0x10; |
| 368 | | state->m_smpc.SF = 0x00; |
| 352 | m_smpc.OREG[31] = 0x10; |
| 353 | m_smpc.SF = 0x00; |
| 369 | 354 | } |
| 370 | 355 | } |
| 371 | 356 | |
| r29211 | r29212 | |
| 383 | 368 | 0x34 keyboard |
| 384 | 369 | */ |
| 385 | 370 | |
| 386 | | static void smpc_digital_pad(running_machine &machine, UINT8 pad_num, UINT8 offset) |
| 371 | void saturn_state::smpc_digital_pad(UINT8 pad_num, UINT8 offset) |
| 387 | 372 | { |
| 388 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 389 | 373 | static const char *const padnames[] = { "JOY1", "JOY2" }; |
| 390 | 374 | UINT16 pad_data; |
| 391 | 375 | |
| 392 | | pad_data = machine.root_device().ioport(padnames[pad_num])->read(); |
| 393 | | state->m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 394 | | state->m_smpc.OREG[1+pad_num*offset] = 0x02; |
| 395 | | state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8; |
| 396 | | state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; |
| 376 | pad_data = ioport(padnames[pad_num])->read(); |
| 377 | m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 378 | m_smpc.OREG[1+pad_num*offset] = 0x02; |
| 379 | m_smpc.OREG[2+pad_num*offset] = pad_data>>8; |
| 380 | m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; |
| 397 | 381 | } |
| 398 | 382 | |
| 399 | | static void smpc_analog_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id) |
| 383 | void saturn_state::smpc_analog_pad( UINT8 pad_num, UINT8 offset, UINT8 id) |
| 400 | 384 | { |
| 401 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 402 | 385 | static const char *const padnames[] = { "AN_JOY1", "AN_JOY2" }; |
| 403 | 386 | static const char *const annames[2][3] = { { "AN_X1", "AN_Y1", "AN_Z1" }, |
| 404 | 387 | { "AN_X2", "AN_Y2", "AN_Z2" }}; |
| 405 | 388 | UINT16 pad_data; |
| 406 | 389 | |
| 407 | | pad_data = machine.root_device().ioport(padnames[pad_num])->read(); |
| 408 | | state->m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 409 | | state->m_smpc.OREG[1+pad_num*offset] = id; |
| 410 | | state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8; |
| 411 | | state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; |
| 412 | | state->m_smpc.OREG[4+pad_num*offset] = machine.root_device().ioport(annames[pad_num][0])->read(); |
| 390 | pad_data = ioport(padnames[pad_num])->read(); |
| 391 | m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 392 | m_smpc.OREG[1+pad_num*offset] = id; |
| 393 | m_smpc.OREG[2+pad_num*offset] = pad_data>>8; |
| 394 | m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; |
| 395 | m_smpc.OREG[4+pad_num*offset] = ioport(annames[pad_num][0])->read(); |
| 413 | 396 | if(id == 0x15) |
| 414 | 397 | { |
| 415 | | state->m_smpc.OREG[5+pad_num*offset] = machine.root_device().ioport(annames[pad_num][1])->read(); |
| 416 | | state->m_smpc.OREG[6+pad_num*offset] = machine.root_device().ioport(annames[pad_num][2])->read(); |
| 398 | m_smpc.OREG[5+pad_num*offset] = ioport(annames[pad_num][1])->read(); |
| 399 | m_smpc.OREG[6+pad_num*offset] = ioport(annames[pad_num][2])->read(); |
| 417 | 400 | } |
| 418 | 401 | } |
| 419 | 402 | |
| 420 | | static void smpc_keyboard(running_machine &machine, UINT8 pad_num, UINT8 offset) |
| 403 | void saturn_state::smpc_keyboard(UINT8 pad_num, UINT8 offset) |
| 421 | 404 | { |
| 422 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 423 | 405 | UINT16 game_key; |
| 424 | 406 | |
| 425 | 407 | game_key = 0xffff; |
| 426 | 408 | |
| 427 | | game_key ^= ((state->ioport("KEYS_1")->read() & 0x80) << 8); // right |
| 428 | | game_key ^= ((state->ioport("KEYS_1")->read() & 0x40) << 8); // left |
| 429 | | game_key ^= ((state->ioport("KEYS_1")->read() & 0x20) << 8); // down |
| 430 | | game_key ^= ((state->ioport("KEYS_1")->read() & 0x10) << 8); // up |
| 431 | | game_key ^= ((state->ioport("KEYF")->read() & 0x80) << 4); // ESC -> START |
| 432 | | game_key ^= ((state->ioport("KEY3")->read() & 0x04) << 8); // Z / A trigger |
| 433 | | game_key ^= ((state->ioport("KEY4")->read() & 0x02) << 8); // C / C trigger |
| 434 | | game_key ^= ((state->ioport("KEY6")->read() & 0x04) << 6); // X / B trigger |
| 435 | | game_key ^= ((state->ioport("KEY2")->read() & 0x20) << 2); // Q / R trigger |
| 436 | | game_key ^= ((state->ioport("KEY3")->read() & 0x10) << 2); // A / X trigger |
| 437 | | game_key ^= ((state->ioport("KEY3")->read() & 0x08) << 2); // S / Y trigger |
| 438 | | game_key ^= ((state->ioport("KEY4")->read() & 0x08) << 1); // D / Z trigger |
| 439 | | game_key ^= ((state->ioport("KEY4")->read() & 0x10) >> 1); // E / L trigger |
| 409 | game_key ^= ((ioport("KEYS_1")->read() & 0x80) << 8); // right |
| 410 | game_key ^= ((ioport("KEYS_1")->read() & 0x40) << 8); // left |
| 411 | game_key ^= ((ioport("KEYS_1")->read() & 0x20) << 8); // down |
| 412 | game_key ^= ((ioport("KEYS_1")->read() & 0x10) << 8); // up |
| 413 | game_key ^= ((ioport("KEYF")->read() & 0x80) << 4); // ESC -> START |
| 414 | game_key ^= ((ioport("KEY3")->read() & 0x04) << 8); // Z / A trigger |
| 415 | game_key ^= ((ioport("KEY4")->read() & 0x02) << 8); // C / C trigger |
| 416 | game_key ^= ((ioport("KEY6")->read() & 0x04) << 6); // X / B trigger |
| 417 | game_key ^= ((ioport("KEY2")->read() & 0x20) << 2); // Q / R trigger |
| 418 | game_key ^= ((ioport("KEY3")->read() & 0x10) << 2); // A / X trigger |
| 419 | game_key ^= ((ioport("KEY3")->read() & 0x08) << 2); // S / Y trigger |
| 420 | game_key ^= ((ioport("KEY4")->read() & 0x08) << 1); // D / Z trigger |
| 421 | game_key ^= ((ioport("KEY4")->read() & 0x10) >> 1); // E / L trigger |
| 440 | 422 | |
| 441 | | state->m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 442 | | state->m_smpc.OREG[1+pad_num*offset] = 0x34; |
| 443 | | state->m_smpc.OREG[2+pad_num*offset] = game_key>>8; // game buttons, TODO |
| 444 | | state->m_smpc.OREG[3+pad_num*offset] = game_key & 0xff; |
| 423 | m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 424 | m_smpc.OREG[1+pad_num*offset] = 0x34; |
| 425 | m_smpc.OREG[2+pad_num*offset] = game_key>>8; // game buttons, TODO |
| 426 | m_smpc.OREG[3+pad_num*offset] = game_key & 0xff; |
| 445 | 427 | /* |
| 446 | 428 | x--- ---- 0 |
| 447 | 429 | -x-- ---- caps lock |
| r29211 | r29212 | |
| 452 | 434 | ---- --x- 1 |
| 453 | 435 | ---- ---x Break key |
| 454 | 436 | */ |
| 455 | | state->m_smpc.OREG[4+pad_num*offset] = state->m_keyb.status | 6; |
| 456 | | state->m_smpc.OREG[5+pad_num*offset] = state->m_keyb.data; |
| 437 | m_smpc.OREG[4+pad_num*offset] = m_keyb.status | 6; |
| 438 | m_smpc.OREG[5+pad_num*offset] = m_keyb.data; |
| 457 | 439 | } |
| 458 | 440 | |
| 459 | | static void smpc_mouse(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id) |
| 441 | void saturn_state::smpc_mouse(UINT8 pad_num, UINT8 offset, UINT8 id) |
| 460 | 442 | { |
| 461 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 462 | 443 | static const char *const mousenames[2][3] = { { "MOUSEB1", "MOUSEX1", "MOUSEY1" }, |
| 463 | 444 | { "MOUSEB2", "MOUSEX2", "MOUSEY2" }}; |
| 464 | 445 | UINT8 mouse_ctrl; |
| 465 | 446 | INT16 mouse_x, mouse_y; |
| 466 | 447 | |
| 467 | | mouse_ctrl = machine.root_device().ioport(mousenames[pad_num][0])->read(); |
| 468 | | mouse_x = machine.root_device().ioport(mousenames[pad_num][1])->read(); |
| 469 | | mouse_y = machine.root_device().ioport(mousenames[pad_num][2])->read(); |
| 448 | mouse_ctrl = ioport(mousenames[pad_num][0])->read(); |
| 449 | mouse_x = ioport(mousenames[pad_num][1])->read(); |
| 450 | mouse_y = ioport(mousenames[pad_num][2])->read(); |
| 470 | 451 | |
| 471 | 452 | if(mouse_x < 0) |
| 472 | 453 | mouse_ctrl |= 0x10; |
| r29211 | r29212 | |
| 480 | 461 | if((mouse_y & 0xff00) != 0xff00 && (mouse_y & 0xff00) != 0x0000) |
| 481 | 462 | mouse_ctrl |= 0x80; |
| 482 | 463 | |
| 483 | | state->m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 484 | | state->m_smpc.OREG[1+pad_num*offset] = id; // 0x23 / 0xe3 |
| 485 | | state->m_smpc.OREG[2+pad_num*offset] = mouse_ctrl; |
| 486 | | state->m_smpc.OREG[3+pad_num*offset] = mouse_x & 0xff; |
| 487 | | state->m_smpc.OREG[4+pad_num*offset] = mouse_y & 0xff; |
| 464 | m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 465 | m_smpc.OREG[1+pad_num*offset] = id; // 0x23 / 0xe3 |
| 466 | m_smpc.OREG[2+pad_num*offset] = mouse_ctrl; |
| 467 | m_smpc.OREG[3+pad_num*offset] = mouse_x & 0xff; |
| 468 | m_smpc.OREG[4+pad_num*offset] = mouse_y & 0xff; |
| 488 | 469 | } |
| 489 | 470 | |
| 490 | 471 | /* TODO: is there ANY game on which the MD pad works? */ |
| 491 | | static void smpc_md_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id) |
| 472 | void saturn_state::smpc_md_pad(UINT8 pad_num, UINT8 offset, UINT8 id) |
| 492 | 473 | { |
| 493 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 494 | 474 | static const char *const padnames[] = { "MD_JOY1", "MD_JOY2" }; |
| 495 | 475 | UINT16 pad_data; |
| 496 | 476 | |
| 497 | | pad_data = machine.root_device().ioport(padnames[pad_num])->read(); |
| 498 | | state->m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 499 | | state->m_smpc.OREG[1+pad_num*offset] = id; |
| 500 | | state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8; |
| 477 | pad_data = ioport(padnames[pad_num])->read(); |
| 478 | m_smpc.OREG[0+pad_num*offset] = 0xf1; |
| 479 | m_smpc.OREG[1+pad_num*offset] = id; |
| 480 | m_smpc.OREG[2+pad_num*offset] = pad_data>>8; |
| 501 | 481 | if(id == 0xe2) // MD 6 Button PAD |
| 502 | | state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; |
| 482 | m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff; |
| 503 | 483 | } |
| 504 | 484 | |
| 505 | | static void smpc_unconnected(running_machine &machine, UINT8 pad_num, UINT8 offset) |
| 485 | void saturn_state::smpc_unconnected(UINT8 pad_num, UINT8 offset) |
| 506 | 486 | { |
| 507 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 508 | | |
| 509 | | state->m_smpc.OREG[0+pad_num*offset] = 0xf0; |
| 487 | m_smpc.OREG[0+pad_num*offset] = 0xf0; |
| 510 | 488 | } |
| 511 | 489 | |
| 512 | | static TIMER_CALLBACK( intback_peripheral ) |
| 490 | TIMER_CALLBACK_MEMBER( saturn_state::intback_peripheral ) |
| 513 | 491 | { |
| 514 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 515 | 492 | int pad_num; |
| 516 | 493 | static const UINT8 peri_id[10] = { 0x02, 0x13, 0x15, 0x23, 0x23, 0x34, 0xe1, 0xe2, 0xe3, 0xff }; |
| 517 | 494 | UINT8 read_id[2]; |
| r29211 | r29212 | |
| 519 | 496 | |
| 520 | 497 | // if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2); |
| 521 | 498 | |
| 522 | | read_id[0] = (machine.root_device().ioport("INPUT_TYPE")->read()) & 0x0f; |
| 523 | | read_id[1] = (machine.root_device().ioport("INPUT_TYPE")->read()) >> 4; |
| 499 | read_id[0] = (ioport("INPUT_TYPE")->read()) & 0x0f; |
| 500 | read_id[1] = (ioport("INPUT_TYPE")->read()) >> 4; |
| 524 | 501 | |
| 525 | 502 | /* doesn't work? */ |
| 526 | | //pad_num = state->m_smpc.intback_stage - 1; |
| 503 | //pad_num = m_smpc.intback_stage - 1; |
| 527 | 504 | |
| 528 | | 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()); |
| 505 | if(LOG_PAD_CMD) printf("%d %d %d\n",m_smpc.intback_stage - 1,machine().first_screen()->vpos(),(int)machine().first_screen()->frame_number()); |
| 529 | 506 | |
| 530 | 507 | offset = 0; |
| 531 | 508 | |
| r29211 | r29212 | |
| 533 | 510 | { |
| 534 | 511 | switch(read_id[pad_num]) |
| 535 | 512 | { |
| 536 | | case 0: smpc_digital_pad(machine,pad_num,offset); break; |
| 537 | | case 1: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Steering Wheel */ |
| 538 | | case 2: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Analog Pad */ |
| 539 | | case 4: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Pointing Device */ |
| 540 | | case 5: smpc_keyboard(machine,pad_num,offset); break; |
| 541 | | case 6: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 3B PAD */ |
| 542 | | case 7: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 6B PAD */ |
| 543 | | case 8: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Saturn Mouse */ |
| 544 | | case 9: smpc_unconnected(machine,pad_num,offset); break; |
| 513 | case 0: smpc_digital_pad(pad_num,offset); break; |
| 514 | case 1: smpc_analog_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Steering Wheel */ |
| 515 | case 2: smpc_analog_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Analog Pad */ |
| 516 | case 4: smpc_mouse(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Pointing Device */ |
| 517 | case 5: smpc_keyboard(pad_num,offset); break; |
| 518 | case 6: smpc_md_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 3B PAD */ |
| 519 | case 7: smpc_md_pad(pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 6B PAD */ |
| 520 | case 8: smpc_mouse(pad_num,offset,peri_id[read_id[pad_num]]); break; /* Saturn Mouse */ |
| 521 | case 9: smpc_unconnected(pad_num,offset); break; |
| 545 | 522 | } |
| 546 | 523 | |
| 547 | 524 | offset += (peri_id[read_id[pad_num]] & 0xf) + 2; /* offset for port 2 */ |
| 548 | 525 | } |
| 549 | 526 | |
| 550 | | if (state->m_smpc.intback_stage == 2) |
| 527 | if (m_smpc.intback_stage == 2) |
| 551 | 528 | { |
| 552 | | state->m_smpc.SR = (0x80 | state->m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback |
| 553 | | state->m_smpc.intback_stage = 0; |
| 529 | m_smpc.SR = (0x80 | m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback |
| 530 | m_smpc.intback_stage = 0; |
| 554 | 531 | } |
| 555 | 532 | else |
| 556 | 533 | { |
| 557 | | state->m_smpc.SR = (0xc0 | state->m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback |
| 558 | | state->m_smpc.intback_stage ++; |
| 534 | m_smpc.SR = (0xc0 | m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback |
| 535 | m_smpc.intback_stage ++; |
| 559 | 536 | } |
| 560 | 537 | |
| 561 | | if(!(state->m_scu.ism & IRQ_SMPC)) |
| 562 | | state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 538 | if(!(m_scu.ism & IRQ_SMPC)) |
| 539 | m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 563 | 540 | else |
| 564 | | state->m_scu.ist |= (IRQ_SMPC); |
| 541 | m_scu.ist |= (IRQ_SMPC); |
| 565 | 542 | |
| 566 | | state->m_smpc.OREG[31] = 0x10; /* callback for last command issued */ |
| 567 | | state->m_smpc.SF = 0x00; /* clear hand-shake flag */ |
| 543 | m_smpc.OREG[31] = 0x10; /* callback for last command issued */ |
| 544 | m_smpc.SF = 0x00; /* clear hand-shake flag */ |
| 568 | 545 | } |
| 569 | 546 | |
| 570 | | static TIMER_CALLBACK( saturn_smpc_intback ) |
| 547 | TIMER_CALLBACK_MEMBER( saturn_state::saturn_smpc_intback ) |
| 571 | 548 | { |
| 572 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 573 | | |
| 574 | | if(state->m_smpc.intback_buf[0] != 0) |
| 549 | if(m_smpc.intback_buf[0] != 0) |
| 575 | 550 | { |
| 576 | 551 | { |
| 577 | 552 | int i; |
| 578 | 553 | |
| 579 | | state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); // bit 7: SETTIME (RTC isn't setted up properly) |
| 554 | m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6); // bit 7: SETTIME (RTC isn't setted up properly) |
| 580 | 555 | |
| 581 | 556 | for(i=0;i<7;i++) |
| 582 | | state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i]; |
| 557 | m_smpc.OREG[1+i] = m_smpc.rtc_data[i]; |
| 583 | 558 | |
| 584 | | state->m_smpc.OREG[8]=0x00; //Cartridge code? |
| 559 | m_smpc.OREG[8]=0x00; //Cartridge code? |
| 585 | 560 | |
| 586 | | state->m_smpc.OREG[9] = state->m_saturn_region; |
| 561 | m_smpc.OREG[9] = m_saturn_region; |
| 587 | 562 | |
| 588 | | state->m_smpc.OREG[10]= 0 << 7 | |
| 589 | | state->m_vdp2.dotsel << 6 | |
| 563 | m_smpc.OREG[10]= 0 << 7 | |
| 564 | m_vdp2.dotsel << 6 | |
| 590 | 565 | 1 << 5 | |
| 591 | 566 | 1 << 4 | |
| 592 | 567 | 0 << 3 | //MSHNMI |
| 593 | 568 | 1 << 2 | |
| 594 | 569 | 0 << 1 | //SYSRES |
| 595 | 570 | 0 << 0; //SOUNDRES |
| 596 | | state->m_smpc.OREG[11]= 0 << 6; //CDRES |
| 571 | m_smpc.OREG[11]= 0 << 6; //CDRES |
| 597 | 572 | |
| 598 | 573 | for(i=0;i<4;i++) |
| 599 | | state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i]; |
| 574 | m_smpc.OREG[12+i]=m_smpc.SMEM[i]; |
| 600 | 575 | |
| 601 | 576 | for(i=0;i<15;i++) |
| 602 | | state->m_smpc.OREG[16+i]=0xff; // undefined |
| 577 | m_smpc.OREG[16+i]=0xff; // undefined |
| 603 | 578 | } |
| 604 | 579 | |
| 605 | | state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 606 | | state->m_smpc.SR = 0x40 | state->m_smpc.intback_stage << 5; |
| 607 | | state->m_smpc.pmode = state->m_smpc.intback_buf[0]>>4; |
| 580 | m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 581 | m_smpc.SR = 0x40 | m_smpc.intback_stage << 5; |
| 582 | m_smpc.pmode = m_smpc.intback_buf[0]>>4; |
| 608 | 583 | |
| 609 | | if(!(state->m_scu.ism & IRQ_SMPC)) |
| 610 | | state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 584 | if(!(m_scu.ism & IRQ_SMPC)) |
| 585 | m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47); |
| 611 | 586 | else |
| 612 | | state->m_scu.ist |= (IRQ_SMPC); |
| 587 | m_scu.ist |= (IRQ_SMPC); |
| 613 | 588 | |
| 614 | 589 | /* put issued command in OREG31 */ |
| 615 | | state->m_smpc.OREG[31] = 0x10; |
| 590 | m_smpc.OREG[31] = 0x10; |
| 616 | 591 | /* clear hand-shake flag */ |
| 617 | | state->m_smpc.SF = 0x00; |
| 592 | m_smpc.SF = 0x00; |
| 618 | 593 | } |
| 619 | | else if(state->m_smpc.intback_buf[1] & 8) |
| 594 | else if(m_smpc.intback_buf[1] & 8) |
| 620 | 595 | { |
| 621 | | state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 622 | | state->m_smpc.SR = 0x40; |
| 623 | | state->m_smpc.OREG[31] = 0x10; |
| 624 | | machine.scheduler().timer_set(attotime::from_usec(0), FUNC(intback_peripheral),0); |
| 596 | m_smpc.intback_stage = (m_smpc.intback_buf[1] & 8) >> 3; // first peripheral |
| 597 | m_smpc.SR = 0x40; |
| 598 | m_smpc.OREG[31] = 0x10; |
| 599 | machine().scheduler().timer_set(attotime::from_usec(0), timer_expired_delegate(FUNC(saturn_state::intback_peripheral),this),0); |
| 625 | 600 | } |
| 626 | 601 | else |
| 627 | 602 | { |
| 628 | | printf("SMPC intback bogus behaviour called %02x %02x\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1]); |
| 603 | printf("SMPC intback bogus behaviour called %02x %02x\n",m_smpc.IREG[0],m_smpc.IREG[1]); |
| 629 | 604 | } |
| 630 | 605 | |
| 631 | 606 | } |
| 632 | 607 | |
| 633 | | static void smpc_rtc_write(running_machine &machine) |
| 608 | void saturn_state::smpc_rtc_write() |
| 634 | 609 | { |
| 635 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 636 | 610 | int i; |
| 637 | 611 | |
| 638 | 612 | for(i=0;i<7;i++) |
| 639 | | state->m_smpc.rtc_data[i] = state->m_smpc.IREG[i]; |
| 613 | m_smpc.rtc_data[i] = m_smpc.IREG[i]; |
| 640 | 614 | } |
| 641 | 615 | |
| 642 | | static void smpc_memory_setting(running_machine &machine) |
| 616 | void saturn_state::smpc_memory_setting() |
| 643 | 617 | { |
| 644 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 645 | 618 | int i; |
| 646 | 619 | |
| 647 | 620 | for(i=0;i<4;i++) |
| 648 | | state->m_smpc.SMEM[i] = state->m_smpc.IREG[i]; |
| 621 | m_smpc.SMEM[i] = m_smpc.IREG[i]; |
| 649 | 622 | } |
| 650 | 623 | |
| 651 | | static void smpc_nmi_req(running_machine &machine) |
| 624 | void saturn_state::smpc_nmi_req() |
| 652 | 625 | { |
| 653 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 654 | | |
| 655 | 626 | /*NMI is unconditionally requested */ |
| 656 | | state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 627 | m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 657 | 628 | } |
| 658 | 629 | |
| 659 | | static TIMER_CALLBACK( smpc_nmi_set ) |
| 630 | TIMER_CALLBACK_MEMBER( saturn_state::smpc_nmi_set ) |
| 660 | 631 | { |
| 661 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 632 | // printf("%d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 662 | 633 | |
| 663 | | // printf("%d %d\n",machine.first_screen()->hpos(),machine.first_screen()->vpos()); |
| 664 | | state->m_NMI_reset = param; |
| 634 | m_NMI_reset = param; |
| 665 | 635 | /* put issued command in OREG31 */ |
| 666 | | state->m_smpc.OREG[31] = 0x19 + param; |
| 636 | m_smpc.OREG[31] = 0x19 + param; |
| 667 | 637 | /* clear hand-shake flag */ |
| 668 | | state->m_smpc.SF = 0x00; |
| 638 | m_smpc.SF = 0x00; |
| 669 | 639 | |
| 670 | | //state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); |
| 640 | //m_smpc.OREG[0] = (0x80) | ((m_NMI_reset & 1) << 6); |
| 671 | 641 | } |
| 672 | 642 | |
| 673 | 643 | |
| r29211 | r29212 | |
| 682 | 652 | * |
| 683 | 653 | *******************************************/ |
| 684 | 654 | |
| 685 | | static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv) |
| 655 | void saturn_state::smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv) |
| 686 | 656 | { |
| 687 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 688 | | |
| 689 | 657 | switch (data) |
| 690 | 658 | { |
| 691 | 659 | case 0x00: |
| 692 | 660 | if(LOG_SMPC) printf ("SMPC: Master ON\n"); |
| 693 | | smpc_master_on(space.machine()); |
| 661 | smpc_master_on(); |
| 694 | 662 | break; |
| 695 | 663 | //case 0x01: Master OFF? |
| 696 | 664 | case 0x02: |
| 697 | 665 | case 0x03: |
| 698 | | if(LOG_SMPC) printf ("SMPC: Slave %s %d %d\n",(data & 1) ? "off" : "on",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); |
| 699 | | space.machine().scheduler().timer_set(attotime::from_usec(15), FUNC(smpc_slave_enable),data & 1); |
| 666 | if(LOG_SMPC) printf ("SMPC: Slave %s %d %d\n",(data & 1) ? "off" : "on",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 667 | machine().scheduler().timer_set(attotime::from_usec(15), timer_expired_delegate(FUNC(saturn_state::smpc_slave_enable),this),data & 1); |
| 700 | 668 | break; |
| 701 | 669 | case 0x06: |
| 702 | 670 | case 0x07: |
| 703 | 671 | if(LOG_SMPC) printf ("SMPC: Sound %s\n",(data & 1) ? "off" : "on"); |
| 704 | 672 | |
| 705 | 673 | if(!is_stv) |
| 706 | | space.machine().scheduler().timer_set(attotime::from_usec(15), FUNC(smpc_sound_enable),data & 1); |
| 674 | machine().scheduler().timer_set(attotime::from_usec(15), timer_expired_delegate(FUNC(saturn_state::smpc_sound_enable),this),data & 1); |
| 707 | 675 | break; |
| 708 | 676 | /*CD (SH-1) ON/OFF */ |
| 709 | 677 | case 0x08: |
| 710 | 678 | case 0x09: |
| 711 | 679 | printf ("SMPC: CD %s\n",(data & 1) ? "off" : "on"); |
| 712 | | space.machine().scheduler().timer_set(attotime::from_usec(20), FUNC(smpc_cd_enable),data & 1); |
| 680 | machine().scheduler().timer_set(attotime::from_usec(20), timer_expired_delegate(FUNC(saturn_state::smpc_cd_enable),this),data & 1); |
| 713 | 681 | break; |
| 714 | 682 | case 0x0d: |
| 715 | 683 | if(LOG_SMPC) printf ("SMPC: System Reset\n"); |
| 716 | | smpc_system_reset(space.machine()); |
| 684 | smpc_system_reset(); |
| 717 | 685 | break; |
| 718 | 686 | case 0x0e: |
| 719 | 687 | case 0x0f: |
| 720 | | 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()); |
| 688 | if(LOG_SMPC) printf ("SMPC: Change Clock to %s (%d %d)\n",data & 1 ? "320" : "352",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 721 | 689 | |
| 722 | 690 | /* on ST-V timing of this is pretty fussy, you get 2 credits at start-up otherwise |
| 723 | 691 | My current theory is that SMPC first stops all CPUs until it executes the whole snippet for this, |
| r29211 | r29212 | |
| 725 | 693 | can do an usable mid-frame clock switching anyway. |
| 726 | 694 | */ |
| 727 | 695 | |
| 728 | | state->m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 729 | | state->m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 730 | | state->m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 696 | m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 697 | m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 698 | m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 731 | 699 | |
| 732 | | 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); |
| 700 | 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); |
| 733 | 701 | break; |
| 734 | 702 | /*"Interrupt Back"*/ |
| 735 | 703 | case 0x10: |
| 736 | 704 | if(0) |
| 737 | 705 | { |
| 738 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 739 | | 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()); |
| 706 | 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()); |
| 740 | 707 | } |
| 741 | 708 | |
| 742 | 709 | int timing; |
| 743 | 710 | |
| 744 | 711 | timing = 8; |
| 745 | 712 | |
| 746 | | if(state->m_smpc.IREG[0] != 0) // non-peripheral data |
| 713 | if(m_smpc.IREG[0] != 0) // non-peripheral data |
| 747 | 714 | timing += 8; |
| 748 | 715 | |
| 749 | 716 | /* TODO: At vblank-out actually ... */ |
| 750 | | if(state->m_smpc.IREG[1] & 8) // peripheral data |
| 717 | if(m_smpc.IREG[1] & 8) // peripheral data |
| 751 | 718 | timing += 700; |
| 752 | 719 | |
| 753 | 720 | /* TODO: check if IREG[2] is setted to 0xf0 */ |
| r29211 | r29212 | |
| 755 | 722 | int i; |
| 756 | 723 | |
| 757 | 724 | for(i=0;i<3;i++) |
| 758 | | state->m_smpc.intback_buf[i] = state->m_smpc.IREG[i]; |
| 725 | m_smpc.intback_buf[i] = m_smpc.IREG[i]; |
| 759 | 726 | } |
| 760 | 727 | |
| 761 | 728 | if(is_stv) |
| 762 | 729 | { |
| 763 | | space.machine().scheduler().timer_set(attotime::from_usec(timing), FUNC(stv_smpc_intback),0); //TODO: variable time |
| 730 | machine().scheduler().timer_set(attotime::from_usec(timing), timer_expired_delegate(FUNC(saturn_state::stv_smpc_intback),this),0); //TODO: variable time |
| 764 | 731 | } |
| 765 | 732 | else |
| 766 | 733 | { |
| 767 | | 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()); |
| 768 | | space.machine().scheduler().timer_set(attotime::from_usec(timing), FUNC(saturn_smpc_intback),0); //TODO: is variable time correct? |
| 734 | 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()); |
| 735 | machine().scheduler().timer_set(attotime::from_usec(timing), timer_expired_delegate(FUNC(saturn_state::saturn_smpc_intback),this),0); //TODO: is variable time correct? |
| 769 | 736 | } |
| 770 | 737 | break; |
| 771 | 738 | /* RTC write*/ |
| 772 | 739 | case 0x16: |
| 773 | 740 | if(LOG_SMPC) printf("SMPC: RTC write\n"); |
| 774 | | smpc_rtc_write(space.machine()); |
| 741 | smpc_rtc_write(); |
| 775 | 742 | break; |
| 776 | 743 | /* SMPC memory setting*/ |
| 777 | 744 | case 0x17: |
| 778 | 745 | if(LOG_SMPC) printf ("SMPC: memory setting\n"); |
| 779 | | smpc_memory_setting(space.machine()); |
| 746 | smpc_memory_setting(); |
| 780 | 747 | break; |
| 781 | 748 | case 0x18: |
| 782 | 749 | if(LOG_SMPC) printf ("SMPC: NMI request\n"); |
| 783 | | smpc_nmi_req(space.machine()); |
| 750 | smpc_nmi_req(); |
| 784 | 751 | break; |
| 785 | 752 | case 0x19: |
| 786 | 753 | case 0x1a: |
| 787 | 754 | /* TODO: timing */ |
| 788 | | if(LOG_SMPC) printf ("SMPC: NMI %sable %d %d\n",data & 1 ? "Dis" : "En",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); |
| 789 | | space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_nmi_set),data & 1); |
| 755 | if(LOG_SMPC) printf ("SMPC: NMI %sable %d %d\n",data & 1 ? "Dis" : "En",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 756 | machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_nmi_set),this),data & 1); |
| 790 | 757 | break; |
| 791 | 758 | default: |
| 792 | 759 | printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space.device().tag(), space.device().safe_pc(), data); |
| r29211 | r29212 | |
| 799 | 766 | * |
| 800 | 767 | *******************************************/ |
| 801 | 768 | |
| 802 | | READ8_HANDLER( stv_SMPC_r ) |
| 769 | READ8_MEMBER( saturn_state::stv_SMPC_r ) |
| 803 | 770 | { |
| 804 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 805 | 771 | int return_data = 0; |
| 806 | 772 | |
| 807 | 773 | if(!(offset & 1)) |
| 808 | 774 | return 0; |
| 809 | 775 | |
| 810 | 776 | if(offset >= 0x21 && offset <= 0x5f) |
| 811 | | return_data = state->m_smpc.OREG[(offset-0x21) >> 1]; |
| 777 | return_data = m_smpc.OREG[(offset-0x21) >> 1]; |
| 812 | 778 | |
| 813 | 779 | if (offset == 0x61) // TODO: SR |
| 814 | | return_data = state->m_smpc.SR; |
| 780 | return_data = m_smpc.SR; |
| 815 | 781 | |
| 816 | 782 | if (offset == 0x63) |
| 817 | | return_data = state->m_smpc.SF; |
| 783 | return_data = m_smpc.SF; |
| 818 | 784 | |
| 819 | 785 | if (offset == 0x75)//PDR1 read |
| 820 | | return_data = state->ioport("DSW1")->read(); |
| 786 | return_data = ioport("DSW1")->read(); |
| 821 | 787 | |
| 822 | 788 | if (offset == 0x77)//PDR2 read |
| 823 | | return_data = (0xfe | state->m_eeprom->do_read()); |
| 789 | return_data = (0xfe | m_eeprom->do_read()); |
| 824 | 790 | |
| 825 | 791 | return return_data; |
| 826 | 792 | } |
| 827 | 793 | |
| 828 | | WRITE8_HANDLER( stv_SMPC_w ) |
| 794 | WRITE8_MEMBER( saturn_state::stv_SMPC_w ) |
| 829 | 795 | { |
| 830 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 831 | | |
| 832 | 796 | if (!(offset & 1)) // avoid writing to even bytes |
| 833 | 797 | return; |
| 834 | 798 | |
| 835 | 799 | // if(LOG_SMPC) printf ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data); |
| 836 | 800 | |
| 837 | 801 | if(offset >= 1 && offset <= 0xd) |
| 838 | | state->m_smpc.IREG[offset >> 1] = data; |
| 802 | m_smpc.IREG[offset >> 1] = data; |
| 839 | 803 | |
| 840 | 804 | if(offset == 1) //IREG0, check if a BREAK / CONTINUE request for INTBACK command |
| 841 | 805 | { |
| 842 | | if(state->m_smpc.intback_stage) |
| 806 | if(m_smpc.intback_stage) |
| 843 | 807 | { |
| 844 | 808 | if(data & 0x40) |
| 845 | 809 | { |
| 846 | 810 | if(LOG_PAD_CMD) printf("SMPC: BREAK request\n"); |
| 847 | | state->m_smpc.SR &= 0x0f; |
| 848 | | state->m_smpc.intback_stage = 0; |
| 811 | m_smpc.SR &= 0x0f; |
| 812 | m_smpc.intback_stage = 0; |
| 849 | 813 | } |
| 850 | 814 | else if(data & 0x80) |
| 851 | 815 | { |
| 852 | 816 | if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n"); |
| 853 | | space.machine().scheduler().timer_set(attotime::from_usec(700), FUNC(stv_intback_peripheral),0); /* TODO: is timing correct? */ |
| 854 | | state->m_smpc.OREG[31] = 0x10; |
| 855 | | state->m_smpc.SF = 0x01; //TODO: set hand-shake flag? |
| 817 | machine().scheduler().timer_set(attotime::from_usec(700), timer_expired_delegate(FUNC(saturn_state::stv_intback_peripheral),this),0); /* TODO: is timing correct? */ |
| 818 | m_smpc.OREG[31] = 0x10; |
| 819 | m_smpc.SF = 0x01; //TODO: set hand-shake flag? |
| 856 | 820 | } |
| 857 | 821 | } |
| 858 | 822 | } |
| r29211 | r29212 | |
| 864 | 828 | // we've processed the command, clear status flag |
| 865 | 829 | if(data != 0x10 && data != 0x02 && data != 0x03 && data != 0x08 && data != 0x09 && data != 0xe && data != 0xf && data != 0x19 && data != 0x1a) |
| 866 | 830 | { |
| 867 | | state->m_smpc.OREG[31] = data; //read-back command |
| 868 | | state->m_smpc.SF = 0x00; |
| 831 | m_smpc.OREG[31] = data; //read-back command |
| 832 | m_smpc.SF = 0x00; |
| 869 | 833 | } |
| 870 | 834 | /*TODO:emulate the timing of each command...*/ |
| 871 | 835 | } |
| 872 | 836 | |
| 873 | 837 | if(offset == 0x63) |
| 874 | | state->m_smpc.SF = data & 1; |
| 838 | m_smpc.SF = data & 1; |
| 875 | 839 | |
| 876 | 840 | if(offset == 0x75) |
| 877 | 841 | { |
| r29211 | r29212 | |
| 882 | 846 | ---- -x-- EEPROM CS line |
| 883 | 847 | ---- --xx A-Bus bank bits |
| 884 | 848 | */ |
| 885 | | state->m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE); |
| 886 | | state->m_eeprom->di_write((data >> 4) & 1); |
| 887 | | state->m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE); |
| 888 | | state->m_stv_multi_bank = data & 3; |
| 849 | m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE); |
| 850 | m_eeprom->di_write((data >> 4) & 1); |
| 851 | m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE); |
| 852 | m_stv_multi_bank = data & 3; |
| 889 | 853 | |
| 890 | | stv_select_game(space.machine(), state->m_stv_multi_bank); |
| 854 | stv_select_game(m_stv_multi_bank); |
| 891 | 855 | |
| 892 | | state->m_smpc.PDR1 = (data & 0x60); |
| 856 | m_smpc.PDR1 = (data & 0x60); |
| 893 | 857 | } |
| 894 | 858 | |
| 895 | 859 | if(offset == 0x77) |
| r29211 | r29212 | |
| 898 | 862 | -xx- ---- PDR2 |
| 899 | 863 | ---x ---- Enable Sound System (ACTIVE LOW) |
| 900 | 864 | */ |
| 901 | | //popmessage("PDR2 = %02x",state->m_smpc_ram[0x77]); |
| 865 | //popmessage("PDR2 = %02x",m_smpc_ram[0x77]); |
| 902 | 866 | |
| 903 | 867 | if(LOG_SMPC) printf("SMPC: M68k %s\n",(data & 0x10) ? "off" : "on"); |
| 904 | | //space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_sound_enable),(state->m_smpc_ram[0x77] & 0x10) >> 4); |
| 905 | | state->m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE); |
| 906 | | state->m_en_68k = ((data & 0x10) >> 4) ^ 1; |
| 868 | //machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_sound_enable),this),(m_smpc_ram[0x77] & 0x10) >> 4); |
| 869 | m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE); |
| 870 | m_en_68k = ((data & 0x10) >> 4) ^ 1; |
| 907 | 871 | |
| 908 | 872 | //if(LOG_SMPC) printf("SMPC: ram [0x77] = %02x\n",data); |
| 909 | | state->m_smpc.PDR2 = (data & 0x60); |
| 873 | m_smpc.PDR2 = (data & 0x60); |
| 910 | 874 | } |
| 911 | 875 | |
| 912 | 876 | if(offset == 0x7d) |
| r29211 | r29212 | |
| 915 | 879 | ---- --x- IOSEL2 direct (1) / control mode (0) port select |
| 916 | 880 | ---- ---x IOSEL1 direct (1) / control mode (0) port select |
| 917 | 881 | */ |
| 918 | | state->m_smpc.IOSEL1 = (data & 1) >> 0; |
| 919 | | state->m_smpc.IOSEL2 = (data & 2) >> 1; |
| 882 | m_smpc.IOSEL1 = (data & 1) >> 0; |
| 883 | m_smpc.IOSEL2 = (data & 2) >> 1; |
| 920 | 884 | } |
| 921 | 885 | |
| 922 | 886 | if(offset == 0x7f) |
| 923 | 887 | { |
| 924 | 888 | //enable PAD irq & VDP2 external latch for port 1/2 |
| 925 | | state->m_smpc.EXLE1 = (data & 1) >> 0; |
| 926 | | state->m_smpc.EXLE2 = (data & 2) >> 1; |
| 889 | m_smpc.EXLE1 = (data & 1) >> 0; |
| 890 | m_smpc.EXLE2 = (data & 2) >> 1; |
| 927 | 891 | } |
| 928 | 892 | } |
| 929 | 893 | |
| r29211 | r29212 | |
| 1001 | 965 | |
| 1002 | 966 | if (offset == 0x63) |
| 1003 | 967 | { |
| 1004 | | //printf("SF %d %d\n",space.machine().first_screen()->hpos(),space.machine().first_screen()->vpos()); |
| 968 | //printf("SF %d %d\n",machine().first_screen()->hpos(),machine().first_screen()->vpos()); |
| 1005 | 969 | return_data = m_smpc.SF; |
| 1006 | 970 | } |
| 1007 | 971 | |
| r29211 | r29212 | |
| 1060 | 1024 | else if(data & 0x80) |
| 1061 | 1025 | { |
| 1062 | 1026 | if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n"); |
| 1063 | | machine().scheduler().timer_set(attotime::from_usec(700), FUNC(intback_peripheral),0); /* TODO: is timing correct? */ |
| 1027 | machine().scheduler().timer_set(attotime::from_usec(700), timer_expired_delegate(FUNC(saturn_state::intback_peripheral),this),0); /* TODO: is timing correct? */ |
| 1064 | 1028 | m_smpc.OREG[31] = 0x10; |
| 1065 | 1029 | m_smpc.SF = 0x01; //TODO: set hand-shake flag? |
| 1066 | 1030 | } |