trunk/src/mame/drivers/saturn.c
| r18148 | r18149 | |
| 121 | 121 | return res; |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | | static void scu_do_transfer(running_machine &machine,UINT8 event); |
| 125 | | static void scu_dma_direct(address_space &space, UINT8 dma_ch); /*DMA level 0 direct transfer function*/ |
| 126 | | static void scu_dma_indirect(address_space &space, UINT8 dma_ch); /*DMA level 0 indirect transfer function*/ |
| 127 | | |
| 128 | 124 | /**************************************************************************************/ |
| 129 | 125 | |
| 130 | 126 | /* |
| r18148 | r18149 | |
| 216 | 212 | -Add level priority & DMA status register. |
| 217 | 213 | */ |
| 218 | 214 | |
| 219 | | #define DIRECT_MODE(_lv_) (!(state->m_scu_regs[5+(_lv_*8)] & 0x01000000)) |
| 220 | | #define INDIRECT_MODE(_lv_) (state->m_scu_regs[5+(_lv_*8)] & 0x01000000) |
| 221 | | #define DRUP(_lv_) (state->m_scu_regs[5+(_lv_*8)] & 0x00010000) |
| 222 | | #define DWUP(_lv_) (state->m_scu_regs[5+(_lv_*8)] & 0x00000100) |
| 215 | #define DIRECT_MODE(_lv_) (!(m_scu_regs[5+(_lv_*8)] & 0x01000000)) |
| 216 | #define INDIRECT_MODE(_lv_) (m_scu_regs[5+(_lv_*8)] & 0x01000000) |
| 217 | #define DRUP(_lv_) (m_scu_regs[5+(_lv_*8)] & 0x00010000) |
| 218 | #define DWUP(_lv_) (m_scu_regs[5+(_lv_*8)] & 0x00000100) |
| 223 | 219 | |
| 224 | | #define DMA_STATUS (state->m_scu_regs[31]) |
| 220 | #define DMA_STATUS (m_scu_regs[31]) |
| 225 | 221 | /*These macros sets the various DMA status flags.*/ |
| 226 | 222 | #define DnMV_1(_ch_) DMA_STATUS|=(0x10 << 4 * _ch_) |
| 227 | 223 | #define DnMV_0(_ch_) DMA_STATUS&=~(0x10 << 4 * _ch_) |
| 228 | 224 | |
| 229 | 225 | /*For area checking*/ |
| 230 | 226 | #define BIOS_BUS(var) (var & 0x07000000) == 0 |
| 231 | | #define ABUS(_lv_) ((state->m_scu.src[_lv_] & 0x07000000) >= 0x02000000) && ((state->m_scu.src[_lv_] & 0x07000000) <= 0x04000000) |
| 227 | #define ABUS(_lv_) ((m_scu.src[_lv_] & 0x07000000) >= 0x02000000) && ((m_scu.src[_lv_] & 0x07000000) <= 0x04000000) |
| 232 | 228 | #define BBUS(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05ffffff) |
| 233 | 229 | #define VDP1_REGS(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05d00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05dfffff) |
| 234 | 230 | #define VDP2(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05e00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05fdffff) |
| r18148 | r18149 | |
| 236 | 232 | #define WORK_RAM_H(var) (var & 0x07000000) == 0x06000000 |
| 237 | 233 | #define SOUND_RAM(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05afffff) |
| 238 | 234 | |
| 239 | | static void scu_do_transfer(running_machine &machine,UINT8 event) |
| 235 | void saturn_state::scu_do_transfer(UINT8 event) |
| 240 | 236 | { |
| 241 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 242 | | address_space &space = machine.device("maincpu")->memory().space(AS_PROGRAM); |
| 237 | address_space &space = machine().device("maincpu")->memory().space(AS_PROGRAM); |
| 243 | 238 | int i; |
| 244 | 239 | |
| 245 | 240 | for(i=0;i<3;i++) |
| 246 | 241 | { |
| 247 | | if(state->m_scu.enable_mask[i] && state->m_scu.start_factor[i] == event) |
| 242 | if(m_scu.enable_mask[i] && m_scu.start_factor[i] == event) |
| 248 | 243 | { |
| 249 | 244 | if(DIRECT_MODE(i)) { scu_dma_direct(space,i); } |
| 250 | 245 | else { scu_dma_indirect(space,i); } |
| r18148 | r18149 | |
| 253 | 248 | } |
| 254 | 249 | |
| 255 | 250 | /* test pending irqs */ |
| 256 | | static void scu_test_pending_irq(running_machine &machine) |
| 251 | void saturn_state::scu_test_pending_irq() |
| 257 | 252 | { |
| 258 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 259 | 253 | int i; |
| 260 | 254 | const int irq_level[32] = { 0xf, 0xe, 0xd, 0xc, |
| 261 | 255 | 0xb, 0xa, 0x9, 0x8, |
| r18148 | r18149 | |
| 268 | 262 | |
| 269 | 263 | for(i=0;i<32;i++) |
| 270 | 264 | { |
| 271 | | if((!(state->m_scu.ism & 1 << i)) && (state->m_scu.ist & 1 << i)) |
| 265 | if((!(m_scu.ism & 1 << i)) && (m_scu.ist & 1 << i)) |
| 272 | 266 | { |
| 273 | 267 | if(irq_level[i] != -1) /* TODO: cheap check for undefined irqs */ |
| 274 | 268 | { |
| 275 | | state->m_maincpu->set_input_line_and_vector(irq_level[i], HOLD_LINE, 0x40 + i); |
| 276 | | state->m_scu.ist &= ~(1 << i); |
| 269 | m_maincpu->set_input_line_and_vector(irq_level[i], HOLD_LINE, 0x40 + i); |
| 270 | m_scu.ist &= ~(1 << i); |
| 277 | 271 | return; /* avoid spurious irqs, correct? */ |
| 278 | 272 | } |
| 279 | 273 | } |
| 280 | 274 | } |
| 281 | 275 | } |
| 282 | 276 | |
| 283 | | static READ32_HANDLER( saturn_scu_r ) |
| 277 | READ32_MEMBER(saturn_state::saturn_scu_r) |
| 284 | 278 | { |
| 285 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 286 | 279 | UINT32 res; |
| 287 | 280 | |
| 288 | 281 | /*TODO: write only registers must return 0 or open bus */ |
| r18148 | r18149 | |
| 291 | 284 | case 0x5c/4: |
| 292 | 285 | // Super Major League and Shin Megami Tensei - Akuma Zensho reads from there (undocumented), DMA status mirror? |
| 293 | 286 | if(LOG_SCU) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc()); |
| 294 | | res = state->m_scu_regs[0x7c/4]; |
| 287 | res = m_scu_regs[0x7c/4]; |
| 295 | 288 | break; |
| 296 | 289 | case 0x7c/4: |
| 297 | 290 | if(LOG_SCU) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc()); |
| 298 | | res = state->m_scu_regs[offset]; |
| 291 | res = m_scu_regs[offset]; |
| 299 | 292 | break; |
| 300 | 293 | case 0x80/4: |
| 301 | 294 | res = dsp_prg_ctrl_r(space); |
| 302 | 295 | break; |
| 303 | 296 | case 0x8c/4: |
| 304 | | if(LOG_SCU) logerror( "DSP mem read at %08X\n", state->m_scu_regs[34]); |
| 297 | if(LOG_SCU) logerror( "DSP mem read at %08X\n", m_scu_regs[34]); |
| 305 | 298 | res = dsp_ram_addr_r(); |
| 306 | 299 | break; |
| 307 | 300 | case 0xa0/4: |
| 308 | | if(LOG_SCU) logerror("(PC=%08x) IRQ mask reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,state->m_scu_regs[0xa0/4]); |
| 309 | | res = state->m_scu.ism; |
| 301 | if(LOG_SCU) logerror("(PC=%08x) IRQ mask reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,m_scu_regs[0xa0/4]); |
| 302 | res = m_scu.ism; |
| 310 | 303 | break; |
| 311 | 304 | case 0xa4/4: |
| 312 | | if(LOG_SCU) logerror("(PC=%08x) IRQ status reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,state->m_scu_regs[0xa0/4]); |
| 313 | | res = state->m_scu.ist; |
| 305 | if(LOG_SCU) logerror("(PC=%08x) IRQ status reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,m_scu_regs[0xa0/4]); |
| 306 | res = m_scu.ist; |
| 314 | 307 | break; |
| 315 | 308 | case 0xc8/4: |
| 316 | 309 | logerror("(PC=%08x) SCU version reg read\n",space.device().safe_pc()); |
| 317 | 310 | res = 0x00000004;/*SCU Version 4, OK? */ |
| 318 | 311 | break; |
| 319 | 312 | default: |
| 320 | | if(LOG_SCU) logerror("(PC=%08x) SCU reg read at %d = %08x\n",space.device().safe_pc(),offset,state->m_scu_regs[offset]); |
| 321 | | res = state->m_scu_regs[offset]; |
| 313 | if(LOG_SCU) logerror("(PC=%08x) SCU reg read at %d = %08x\n",space.device().safe_pc(),offset,m_scu_regs[offset]); |
| 314 | res = m_scu_regs[offset]; |
| 322 | 315 | break; |
| 323 | 316 | } |
| 324 | 317 | |
| r18148 | r18149 | |
| 327 | 320 | |
| 328 | 321 | #define DMA_CH ((offset & 0x18) / 8) |
| 329 | 322 | |
| 330 | | static WRITE32_HANDLER( saturn_scu_w ) |
| 323 | WRITE32_MEMBER(saturn_state::saturn_scu_w) |
| 331 | 324 | { |
| 332 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 325 | COMBINE_DATA(&m_scu_regs[offset]); |
| 333 | 326 | |
| 334 | | COMBINE_DATA(&state->m_scu_regs[offset]); |
| 335 | | |
| 336 | 327 | switch(offset) |
| 337 | 328 | { |
| 338 | 329 | /*LV 0 DMA*/ |
| 339 | | case 0x00/4: case 0x20/4: case 0x40/4: state->m_scu.src[DMA_CH] = ((state->m_scu_regs[offset] & 0x07ffffff) >> 0); break; |
| 340 | | case 0x04/4: case 0x24/4: case 0x44/4: state->m_scu.dst[DMA_CH] = ((state->m_scu_regs[offset] & 0x07ffffff) >> 0); break; |
| 341 | | case 0x08/4: case 0x28/4: case 0x48/4: state->m_scu.size[DMA_CH] = ((state->m_scu_regs[offset] & ((offset == 2) ? 0x000fffff : 0xfff)) >> 0); break; |
| 330 | case 0x00/4: case 0x20/4: case 0x40/4: m_scu.src[DMA_CH] = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break; |
| 331 | case 0x04/4: case 0x24/4: case 0x44/4: m_scu.dst[DMA_CH] = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break; |
| 332 | case 0x08/4: case 0x28/4: case 0x48/4: m_scu.size[DMA_CH] = ((m_scu_regs[offset] & ((offset == 2) ? 0x000fffff : 0xfff)) >> 0); break; |
| 342 | 333 | case 0x0c/4: case 0x2c/4: case 0x4c/4: |
| 343 | | state->m_scu.src_add[DMA_CH] = (state->m_scu_regs[offset] & 0x100) ? 4 : 0; |
| 344 | | state->m_scu.dst_add[DMA_CH] = 1 << (state->m_scu_regs[offset] & 7); |
| 345 | | if(state->m_scu.dst_add[DMA_CH] == 1) { state->m_scu.dst_add[DMA_CH] = 0; } |
| 334 | m_scu.src_add[DMA_CH] = (m_scu_regs[offset] & 0x100) ? 4 : 0; |
| 335 | m_scu.dst_add[DMA_CH] = 1 << (m_scu_regs[offset] & 7); |
| 336 | if(m_scu.dst_add[DMA_CH] == 1) { m_scu.dst_add[DMA_CH] = 0; } |
| 346 | 337 | break; |
| 347 | 338 | case 0x10/4: case 0x30/4: case 0x50/4: |
| 348 | | state->m_scu.enable_mask[DMA_CH] = (data & 0x100) >> 8; |
| 349 | | if(state->m_scu.enable_mask[DMA_CH] && state->m_scu.start_factor[DMA_CH] == 7 && state->m_scu_regs[offset] & 1) |
| 339 | m_scu.enable_mask[DMA_CH] = (data & 0x100) >> 8; |
| 340 | if(m_scu.enable_mask[DMA_CH] && m_scu.start_factor[DMA_CH] == 7 && m_scu_regs[offset] & 1) |
| 350 | 341 | { |
| 351 | 342 | if(DIRECT_MODE(DMA_CH)) { scu_dma_direct(space,DMA_CH); } |
| 352 | 343 | else { scu_dma_indirect(space,DMA_CH); } |
| 353 | | state->m_scu_regs[offset]&=~1;//disable starting bit. |
| 344 | m_scu_regs[offset]&=~1;//disable starting bit. |
| 354 | 345 | } |
| 355 | 346 | break; |
| 356 | 347 | case 0x14/4: case 0x34/4: case 0x54/4: |
| 357 | 348 | if(INDIRECT_MODE(DMA_CH)) |
| 358 | 349 | { |
| 359 | 350 | //if(LOG_SCU) logerror("Indirect Mode DMA lv %d set\n",DMA_CH); |
| 360 | | if(!DWUP(DMA_CH)) state->m_scu.index[DMA_CH] = state->m_scu.dst[DMA_CH]; |
| 351 | if(!DWUP(DMA_CH)) m_scu.index[DMA_CH] = m_scu.dst[DMA_CH]; |
| 361 | 352 | } |
| 362 | 353 | |
| 363 | | state->m_scu.start_factor[DMA_CH] = state->m_scu_regs[offset] & 7; |
| 354 | m_scu.start_factor[DMA_CH] = m_scu_regs[offset] & 7; |
| 364 | 355 | break; |
| 365 | 356 | |
| 366 | 357 | case 0x60/4: |
| 367 | | if(LOG_SCU) logerror("DMA Forced Stop Register set = %02x\n",state->m_scu_regs[24]); |
| 358 | if(LOG_SCU) logerror("DMA Forced Stop Register set = %02x\n",m_scu_regs[24]); |
| 368 | 359 | break; |
| 369 | 360 | case 0x7c/4: if(LOG_SCU) logerror("Warning: DMA status WRITE! Offset %02x(%d)\n",offset*4,offset); break; |
| 370 | 361 | /*DSP section*/ |
| 371 | 362 | case 0x80/4: |
| 372 | 363 | /* TODO: you can't overwrite some flags with this */ |
| 373 | | dsp_prg_ctrl_w(space, state->m_scu_regs[offset]); |
| 364 | dsp_prg_ctrl_w(space, m_scu_regs[offset]); |
| 374 | 365 | if(LOG_SCU) logerror("SCU DSP: Program Control Port Access %08x\n",data); |
| 375 | 366 | break; |
| 376 | 367 | case 0x84/4: |
| 377 | | dsp_prg_data(state->m_scu_regs[offset]); |
| 368 | dsp_prg_data(m_scu_regs[offset]); |
| 378 | 369 | if(LOG_SCU) logerror("SCU DSP: Program RAM Data Port Access %08x\n",data); |
| 379 | 370 | break; |
| 380 | 371 | case 0x88/4: |
| 381 | | dsp_ram_addr_ctrl(state->m_scu_regs[offset]); |
| 372 | dsp_ram_addr_ctrl(m_scu_regs[offset]); |
| 382 | 373 | if(LOG_SCU) logerror("SCU DSP: Data RAM Address Port Access %08x\n",data); |
| 383 | 374 | break; |
| 384 | 375 | case 0x8c/4: |
| 385 | | dsp_ram_addr_w(state->m_scu_regs[offset]); |
| 376 | dsp_ram_addr_w(m_scu_regs[offset]); |
| 386 | 377 | if(LOG_SCU) logerror("SCU DSP: Data RAM Data Port Access %08x\n",data); |
| 387 | 378 | break; |
| 388 | | case 0x90/4: /*if(LOG_SCU) logerror("timer 0 compare data = %03x\n",state->m_scu_regs[36]);*/ break; |
| 389 | | case 0x94/4: /*if(LOG_SCU) logerror("timer 1 set data = %08x\n",state->m_scu_regs[37]);*/ break; |
| 390 | | case 0x98/4: /*if(LOG_SCU) logerror("timer 1 mode data = %08x\n",state->m_scu_regs[38]);*/ break; |
| 379 | case 0x90/4: /*if(LOG_SCU) logerror("timer 0 compare data = %03x\n",m_scu_regs[36]);*/ break; |
| 380 | case 0x94/4: /*if(LOG_SCU) logerror("timer 1 set data = %08x\n",m_scu_regs[37]);*/ break; |
| 381 | case 0x98/4: /*if(LOG_SCU) logerror("timer 1 mode data = %08x\n",m_scu_regs[38]);*/ break; |
| 391 | 382 | case 0xa0/4: /* IRQ mask */ |
| 392 | | state->m_scu.ism = state->m_scu_regs[0xa0/4]; |
| 393 | | scu_test_pending_irq(space.machine()); |
| 383 | m_scu.ism = m_scu_regs[0xa0/4]; |
| 384 | scu_test_pending_irq(); |
| 394 | 385 | break; |
| 395 | 386 | case 0xa4/4: /* IRQ control */ |
| 396 | | if(LOG_SCU) logerror("PC=%08x IRQ status reg set:%08x %08x\n",space.device().safe_pc(),state->m_scu_regs[41],mem_mask); |
| 397 | | state->m_scu.ist &= state->m_scu_regs[offset]; |
| 387 | if(LOG_SCU) logerror("PC=%08x IRQ status reg set:%08x %08x\n",space.device().safe_pc(),m_scu_regs[41],mem_mask); |
| 388 | m_scu.ist &= m_scu_regs[offset]; |
| 398 | 389 | break; |
| 399 | | case 0xa8/4: if(LOG_SCU) logerror("A-Bus IRQ ACK %08x\n",state->m_scu_regs[42]); break; |
| 400 | | case 0xc4/4: if(LOG_SCU) logerror("SCU SDRAM set: %02x\n",state->m_scu_regs[49]); break; |
| 390 | case 0xa8/4: if(LOG_SCU) logerror("A-Bus IRQ ACK %08x\n",m_scu_regs[42]); break; |
| 391 | case 0xc4/4: if(LOG_SCU) logerror("SCU SDRAM set: %02x\n",m_scu_regs[49]); break; |
| 401 | 392 | default: if(LOG_SCU) logerror("Warning: unused SCU reg set %d = %08x\n",offset,data); |
| 402 | 393 | } |
| 403 | 394 | } |
| 404 | 395 | |
| 405 | 396 | /*Lv 0 DMA end irq*/ |
| 406 | | static TIMER_CALLBACK( dma_lv0_ended ) |
| 397 | TIMER_CALLBACK_MEMBER(saturn_state::dma_lv0_ended ) |
| 407 | 398 | { |
| 408 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 409 | | |
| 410 | | if(!(state->m_scu.ism & IRQ_DMALV0)) |
| 411 | | state->m_maincpu->set_input_line_and_vector(5, HOLD_LINE, 0x4b); |
| 399 | if(!(m_scu.ism & IRQ_DMALV0)) |
| 400 | m_maincpu->set_input_line_and_vector(5, HOLD_LINE, 0x4b); |
| 412 | 401 | else |
| 413 | | state->m_scu.ist |= (IRQ_DMALV0); |
| 402 | m_scu.ist |= (IRQ_DMALV0); |
| 414 | 403 | |
| 415 | 404 | DnMV_0(0); |
| 416 | 405 | } |
| 417 | 406 | |
| 418 | 407 | /*Lv 1 DMA end irq*/ |
| 419 | | static TIMER_CALLBACK( dma_lv1_ended ) |
| 408 | TIMER_CALLBACK_MEMBER(saturn_state::dma_lv1_ended) |
| 420 | 409 | { |
| 421 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 422 | | |
| 423 | | if(!(state->m_scu.ism & IRQ_DMALV1)) |
| 424 | | state->m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x4a); |
| 410 | if(!(m_scu.ism & IRQ_DMALV1)) |
| 411 | m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x4a); |
| 425 | 412 | else |
| 426 | | state->m_scu.ist |= (IRQ_DMALV1); |
| 413 | m_scu.ist |= (IRQ_DMALV1); |
| 427 | 414 | |
| 428 | 415 | DnMV_0(1); |
| 429 | 416 | } |
| 430 | 417 | |
| 431 | 418 | /*Lv 2 DMA end irq*/ |
| 432 | | static TIMER_CALLBACK( dma_lv2_ended ) |
| 419 | TIMER_CALLBACK_MEMBER(saturn_state::dma_lv2_ended) |
| 433 | 420 | { |
| 434 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 435 | | |
| 436 | | if(!(state->m_scu.ism & IRQ_DMALV2)) |
| 437 | | state->m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x49); |
| 421 | if(!(m_scu.ism & IRQ_DMALV2)) |
| 422 | m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x49); |
| 438 | 423 | else |
| 439 | | state->m_scu.ist |= (IRQ_DMALV2); |
| 424 | m_scu.ist |= (IRQ_DMALV2); |
| 440 | 425 | |
| 441 | 426 | DnMV_0(2); |
| 442 | 427 | } |
| 443 | 428 | |
| 444 | | static void scu_single_transfer(address_space &space, UINT32 src, UINT32 dst,UINT8 *src_shift) |
| 429 | void saturn_state::scu_single_transfer(address_space &space, UINT32 src, UINT32 dst,UINT8 *src_shift) |
| 445 | 430 | { |
| 446 | 431 | UINT32 src_data; |
| 447 | 432 | |
| r18148 | r18149 | |
| 460 | 445 | *src_shift ^= 1; |
| 461 | 446 | } |
| 462 | 447 | |
| 463 | | static void scu_dma_direct(address_space &space, UINT8 dma_ch) |
| 448 | void saturn_state::scu_dma_direct(address_space &space, UINT8 dma_ch) |
| 464 | 449 | { |
| 465 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 466 | 450 | UINT32 tmp_src,tmp_dst,tmp_size; |
| 467 | 451 | UINT8 cd_transfer_flag; |
| 468 | 452 | |
| 469 | | if(state->m_scu.src_add[dma_ch] == 0 || (state->m_scu.dst_add[dma_ch] != 2 && state->m_scu.dst_add[dma_ch] != 4)) |
| 453 | if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2 && m_scu.dst_add[dma_ch] != 4)) |
| 470 | 454 | { |
| 471 | 455 | if(LOG_SCU) printf("DMA lv %d transfer START\n" |
| 472 | | "Start %08x End %08x Size %04x\n",dma_ch,state->m_scu.src[dma_ch],state->m_scu.dst[dma_ch],state->m_scu.size[dma_ch]); |
| 473 | | if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",state->m_scu.src_add[dma_ch],state->m_scu.dst_add[dma_ch]); |
| 456 | "Start %08x End %08x Size %04x\n",dma_ch,m_scu.src[dma_ch],m_scu.dst[dma_ch],m_scu.size[dma_ch]); |
| 457 | if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]); |
| 474 | 458 | } |
| 475 | 459 | |
| 476 | 460 | /* TODO: Game Basic trips this, bogus transfer from BIOS area to VDP1? */ |
| 477 | | if(BIOS_BUS(state->m_scu.src[dma_ch])) |
| 461 | if(BIOS_BUS(m_scu.src[dma_ch])) |
| 478 | 462 | popmessage("Warning: SCU transfer from BIOS area, contact MAMEdev"); |
| 479 | 463 | |
| 480 | 464 | DnMV_1(dma_ch); |
| 481 | 465 | |
| 482 | 466 | /* max size */ |
| 483 | | if(state->m_scu.size[dma_ch] == 0) { state->m_scu.size[dma_ch] = (dma_ch == 0) ? 0x00100000 : 0x1000; } |
| 467 | if(m_scu.size[dma_ch] == 0) { m_scu.size[dma_ch] = (dma_ch == 0) ? 0x00100000 : 0x1000; } |
| 484 | 468 | |
| 485 | 469 | tmp_src = tmp_dst = 0; |
| 486 | 470 | |
| 487 | | tmp_size = state->m_scu.size[dma_ch]; |
| 488 | | if(!(DRUP(dma_ch))) tmp_src = state->m_scu.src[dma_ch]; |
| 489 | | if(!(DWUP(dma_ch))) tmp_dst = state->m_scu.dst[dma_ch]; |
| 471 | tmp_size = m_scu.size[dma_ch]; |
| 472 | if(!(DRUP(dma_ch))) tmp_src = m_scu.src[dma_ch]; |
| 473 | if(!(DWUP(dma_ch))) tmp_dst = m_scu.dst[dma_ch]; |
| 490 | 474 | |
| 491 | | cd_transfer_flag = state->m_scu.src_add[dma_ch] == 0 && state->m_scu.src[dma_ch] == 0x05818000; |
| 475 | cd_transfer_flag = m_scu.src_add[dma_ch] == 0 && m_scu.src[dma_ch] == 0x05818000; |
| 492 | 476 | |
| 493 | 477 | /* TODO: Many games directly accesses CD-ROM register 0x05818000, it must be a dword access with current implementation otherwise it won't work */ |
| 494 | 478 | if(cd_transfer_flag) |
| 495 | 479 | { |
| 496 | 480 | int i; |
| 497 | | if(WORK_RAM_H(state->m_scu.dst[dma_ch])) |
| 498 | | state->m_scu.dst_add[dma_ch] = 4; |
| 481 | if(WORK_RAM_H(m_scu.dst[dma_ch])) |
| 482 | m_scu.dst_add[dma_ch] = 4; |
| 499 | 483 | else |
| 500 | | state->m_scu.dst_add[dma_ch] <<= 1; |
| 484 | m_scu.dst_add[dma_ch] <<= 1; |
| 501 | 485 | |
| 502 | | for (i = 0; i < state->m_scu.size[dma_ch];i+=state->m_scu.dst_add[dma_ch]) |
| 486 | for (i = 0; i < m_scu.size[dma_ch];i+=m_scu.dst_add[dma_ch]) |
| 503 | 487 | { |
| 504 | | space.write_dword(state->m_scu.dst[dma_ch],space.read_dword(state->m_scu.src[dma_ch])); |
| 505 | | if(state->m_scu.dst_add[dma_ch] == 8) |
| 506 | | space.write_dword(state->m_scu.dst[dma_ch]+4,space.read_dword(state->m_scu.src[dma_ch])); |
| 488 | space.write_dword(m_scu.dst[dma_ch],space.read_dword(m_scu.src[dma_ch])); |
| 489 | if(m_scu.dst_add[dma_ch] == 8) |
| 490 | space.write_dword(m_scu.dst[dma_ch]+4,space.read_dword(m_scu.src[dma_ch])); |
| 507 | 491 | |
| 508 | | state->m_scu.src[dma_ch]+=state->m_scu.src_add[dma_ch]; |
| 509 | | state->m_scu.dst[dma_ch]+=state->m_scu.dst_add[dma_ch]; |
| 492 | m_scu.src[dma_ch]+=m_scu.src_add[dma_ch]; |
| 493 | m_scu.dst[dma_ch]+=m_scu.dst_add[dma_ch]; |
| 510 | 494 | } |
| 511 | 495 | } |
| 512 | 496 | else |
| r18148 | r18149 | |
| 514 | 498 | int i; |
| 515 | 499 | UINT8 src_shift; |
| 516 | 500 | |
| 517 | | src_shift = ((state->m_scu.src[dma_ch] & 2) >> 1) ^ 1; |
| 501 | src_shift = ((m_scu.src[dma_ch] & 2) >> 1) ^ 1; |
| 518 | 502 | |
| 519 | | for (i = 0; i < state->m_scu.size[dma_ch];i+=2) |
| 503 | for (i = 0; i < m_scu.size[dma_ch];i+=2) |
| 520 | 504 | { |
| 521 | | scu_single_transfer(space,state->m_scu.src[dma_ch],state->m_scu.dst[dma_ch],&src_shift); |
| 505 | scu_single_transfer(space,m_scu.src[dma_ch],m_scu.dst[dma_ch],&src_shift); |
| 522 | 506 | |
| 523 | 507 | if(src_shift) |
| 524 | | state->m_scu.src[dma_ch]+=state->m_scu.src_add[dma_ch]; |
| 508 | m_scu.src[dma_ch]+=m_scu.src_add[dma_ch]; |
| 525 | 509 | |
| 526 | 510 | /* if target is Work RAM H, the add value is fixed, behaviour confirmed by Final Romance 2, Virtual Mahjong and Burning Rangers */ |
| 527 | | state->m_scu.dst[dma_ch]+=(WORK_RAM_H(state->m_scu.dst[dma_ch])) ? 2 : state->m_scu.dst_add[dma_ch]; |
| 511 | m_scu.dst[dma_ch]+=(WORK_RAM_H(m_scu.dst[dma_ch])) ? 2 : m_scu.dst_add[dma_ch]; |
| 528 | 512 | } |
| 529 | 513 | } |
| 530 | 514 | |
| 531 | | state->m_scu.size[dma_ch] = tmp_size; |
| 532 | | if(!(DRUP(dma_ch))) state->m_scu.src[dma_ch] = tmp_src; |
| 533 | | if(!(DWUP(dma_ch))) state->m_scu.dst[dma_ch] = tmp_dst; |
| 515 | m_scu.size[dma_ch] = tmp_size; |
| 516 | if(!(DRUP(dma_ch))) m_scu.src[dma_ch] = tmp_src; |
| 517 | if(!(DWUP(dma_ch))) m_scu.dst[dma_ch] = tmp_dst; |
| 534 | 518 | |
| 535 | 519 | { |
| 536 | 520 | /*TODO: this is completely wrong HW-wise ... */ |
| 537 | 521 | switch(dma_ch) |
| 538 | 522 | { |
| 539 | | case 0: space.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dma_lv0_ended)); break; |
| 540 | | case 1: space.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dma_lv1_ended)); break; |
| 541 | | case 2: space.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dma_lv2_ended)); break; |
| 523 | case 0: machine().scheduler().timer_set(attotime::from_usec(300), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break; |
| 524 | case 1: machine().scheduler().timer_set(attotime::from_usec(300), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break; |
| 525 | case 2: machine().scheduler().timer_set(attotime::from_usec(300), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break; |
| 542 | 526 | } |
| 543 | 527 | } |
| 544 | 528 | } |
| 545 | 529 | |
| 546 | | static void scu_dma_indirect(address_space &space,UINT8 dma_ch) |
| 530 | void saturn_state::scu_dma_indirect(address_space &space,UINT8 dma_ch) |
| 547 | 531 | { |
| 548 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 549 | | |
| 550 | 532 | /*Helper to get out of the cycle*/ |
| 551 | 533 | UINT8 job_done = 0; |
| 552 | 534 | /*temporary storage for the transfer data*/ |
| r18148 | r18149 | |
| 556 | 538 | |
| 557 | 539 | DnMV_1(dma_ch); |
| 558 | 540 | |
| 559 | | state->m_scu.index[dma_ch] = state->m_scu.dst[dma_ch]; |
| 541 | m_scu.index[dma_ch] = m_scu.dst[dma_ch]; |
| 560 | 542 | |
| 561 | 543 | do{ |
| 562 | | tmp_src = state->m_scu.index[dma_ch]; |
| 544 | tmp_src = m_scu.index[dma_ch]; |
| 563 | 545 | |
| 564 | | indirect_size = space.read_dword(state->m_scu.index[dma_ch]); |
| 565 | | indirect_src = space.read_dword(state->m_scu.index[dma_ch]+8); |
| 566 | | indirect_dst = space.read_dword(state->m_scu.index[dma_ch]+4); |
| 546 | indirect_size = space.read_dword(m_scu.index[dma_ch]); |
| 547 | indirect_src = space.read_dword(m_scu.index[dma_ch]+8); |
| 548 | indirect_dst = space.read_dword(m_scu.index[dma_ch]+4); |
| 567 | 549 | |
| 568 | 550 | /*Indirect Mode end factor*/ |
| 569 | 551 | if(indirect_src & 0x80000000) |
| 570 | 552 | job_done = 1; |
| 571 | 553 | |
| 572 | | if(state->m_scu.src_add[dma_ch] == 0 || (state->m_scu.dst_add[dma_ch] != 2)) |
| 554 | if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2)) |
| 573 | 555 | { |
| 574 | 556 | if(LOG_SCU) printf("DMA lv %d indirect mode transfer START\n" |
| 575 | 557 | "Index %08x Start %08x End %08x Size %04x\n",dma_ch,tmp_src,indirect_src,indirect_dst,indirect_size); |
| 576 | | if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",state->m_scu.src_add[dma_ch],state->m_scu.dst_add[dma_ch]); |
| 558 | if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]); |
| 577 | 559 | } |
| 578 | 560 | |
| 579 | 561 | indirect_src &=0x07ffffff; |
| r18148 | r18149 | |
| 593 | 575 | scu_single_transfer(space,indirect_src,indirect_dst,&src_shift); |
| 594 | 576 | |
| 595 | 577 | if(src_shift) |
| 596 | | indirect_src+=state->m_scu.src_add[dma_ch]; |
| 578 | indirect_src+=m_scu.src_add[dma_ch]; |
| 597 | 579 | |
| 598 | | indirect_dst+= (WORK_RAM_H(indirect_dst)) ? 2 : state->m_scu.dst_add[dma_ch]; |
| 580 | indirect_dst+= (WORK_RAM_H(indirect_dst)) ? 2 : m_scu.dst_add[dma_ch]; |
| 599 | 581 | } |
| 600 | 582 | } |
| 601 | 583 | |
| 602 | | //if(DRUP(0)) space.write_dword(tmp_src+8,state->m_scu.src[0]|job_done ? 0x80000000 : 0); |
| 603 | | //if(DWUP(0)) space.write_dword(tmp_src+4,state->m_scu.dst[0]); |
| 584 | //if(DRUP(0)) space.write_dword(tmp_src+8,m_scu.src[0]|job_done ? 0x80000000 : 0); |
| 585 | //if(DWUP(0)) space.write_dword(tmp_src+4,m_scu.dst[0]); |
| 604 | 586 | |
| 605 | | state->m_scu.index[dma_ch] = tmp_src+0xc; |
| 587 | m_scu.index[dma_ch] = tmp_src+0xc; |
| 606 | 588 | |
| 607 | 589 | }while(job_done == 0); |
| 608 | 590 | |
| r18148 | r18149 | |
| 610 | 592 | /*TODO: this is completely wrong HW-wise ... */ |
| 611 | 593 | switch(dma_ch) |
| 612 | 594 | { |
| 613 | | case 0: space.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dma_lv0_ended)); break; |
| 614 | | case 1: space.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dma_lv1_ended)); break; |
| 615 | | case 2: space.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dma_lv2_ended)); break; |
| 595 | case 0: machine().scheduler().timer_set(attotime::from_usec(300), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break; |
| 596 | case 1: machine().scheduler().timer_set(attotime::from_usec(300), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break; |
| 597 | case 2: machine().scheduler().timer_set(attotime::from_usec(300), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break; |
| 616 | 598 | } |
| 617 | 599 | } |
| 618 | 600 | } |
| r18148 | r18149 | |
| 620 | 602 | |
| 621 | 603 | /**************************************************************************************/ |
| 622 | 604 | |
| 623 | | static WRITE16_HANDLER( saturn_soundram_w ) |
| 605 | WRITE16_MEMBER(saturn_state::saturn_soundram_w) |
| 624 | 606 | { |
| 625 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 607 | //machine().scheduler().synchronize(); // force resync |
| 626 | 608 | |
| 627 | | //space.machine().scheduler().synchronize(); // force resync |
| 628 | | |
| 629 | | COMBINE_DATA(&state->m_sound_ram[offset]); |
| 609 | COMBINE_DATA(&m_sound_ram[offset]); |
| 630 | 610 | } |
| 631 | 611 | |
| 632 | | static READ16_HANDLER( saturn_soundram_r ) |
| 612 | READ16_MEMBER(saturn_state::saturn_soundram_r) |
| 633 | 613 | { |
| 634 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 614 | //machine().scheduler().synchronize(); // force resync |
| 635 | 615 | |
| 636 | | //space.machine().scheduler().synchronize(); // force resync |
| 637 | | |
| 638 | | return state->m_sound_ram[offset]; |
| 616 | return m_sound_ram[offset]; |
| 639 | 617 | } |
| 640 | 618 | |
| 641 | 619 | /* communication,SLAVE CPU acquires data from the MASTER CPU and triggers an irq. */ |
| 642 | | static WRITE32_HANDLER( minit_w ) |
| 620 | WRITE32_MEMBER(saturn_state::minit_w) |
| 643 | 621 | { |
| 644 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 645 | | |
| 646 | 622 | //logerror("cpu %s (PC=%08X) MINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data); |
| 647 | | space.machine().scheduler().boost_interleave(state->m_minit_boost_timeslice, attotime::from_usec(state->m_minit_boost)); |
| 648 | | space.machine().scheduler().trigger(1000); |
| 649 | | sh2_set_frt_input(state->m_slave, PULSE_LINE); |
| 623 | machine().scheduler().boost_interleave(m_minit_boost_timeslice, attotime::from_usec(m_minit_boost)); |
| 624 | machine().scheduler().trigger(1000); |
| 625 | sh2_set_frt_input(m_slave, PULSE_LINE); |
| 650 | 626 | } |
| 651 | 627 | |
| 652 | | static WRITE32_HANDLER( sinit_w ) |
| 628 | WRITE32_MEMBER(saturn_state::sinit_w) |
| 653 | 629 | { |
| 654 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 655 | | |
| 656 | 630 | //logerror("cpu %s (PC=%08X) SINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data); |
| 657 | | space.machine().scheduler().boost_interleave(state->m_sinit_boost_timeslice, attotime::from_usec(state->m_sinit_boost)); |
| 658 | | sh2_set_frt_input(state->m_maincpu, PULSE_LINE); |
| 631 | machine().scheduler().boost_interleave(m_sinit_boost_timeslice, attotime::from_usec(m_sinit_boost)); |
| 632 | sh2_set_frt_input(m_maincpu, PULSE_LINE); |
| 659 | 633 | } |
| 660 | 634 | |
| 661 | | static READ8_HANDLER(saturn_backupram_r) |
| 635 | READ8_MEMBER(saturn_state::saturn_backupram_r) |
| 662 | 636 | { |
| 663 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 664 | | |
| 665 | 637 | if(!(offset & 1)) |
| 666 | 638 | return 0; // yes, it makes sure the "holes" are there. |
| 667 | 639 | |
| 668 | | return state->m_backupram[offset >> 1] & 0xff; |
| 640 | return m_backupram[offset >> 1] & 0xff; |
| 669 | 641 | } |
| 670 | 642 | |
| 671 | | static WRITE8_HANDLER(saturn_backupram_w) |
| 643 | WRITE8_MEMBER(saturn_state::saturn_backupram_w) |
| 672 | 644 | { |
| 673 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 674 | | |
| 675 | 645 | if(!(offset & 1)) |
| 676 | 646 | return; |
| 677 | 647 | |
| 678 | | state->m_backupram[offset >> 1] = data; |
| 648 | m_backupram[offset >> 1] = data; |
| 679 | 649 | } |
| 680 | 650 | |
| 681 | 651 | /* TODO: if you change the driver configuration then NVRAM contents gets screwed, needs mods in MAME framework */ |
| r18148 | r18149 | |
| 741 | 711 | } |
| 742 | 712 | } |
| 743 | 713 | |
| 744 | | static READ8_HANDLER( saturn_cart_type_r ) |
| 714 | READ8_MEMBER(saturn_state::saturn_cart_type_r) |
| 745 | 715 | { |
| 746 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 747 | 716 | const int cart_ram_header[7] = { 0xff, 0x21, 0x22, 0x23, 0x24, 0x5a, 0x5c }; |
| 748 | 717 | |
| 749 | | return cart_ram_header[state->m_cart_type]; |
| 718 | return cart_ram_header[m_cart_type]; |
| 750 | 719 | } |
| 751 | 720 | |
| 752 | 721 | static ADDRESS_MAP_START( saturn_mem, AS_PROGRAM, 32, saturn_state ) |
| 753 | 722 | AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6") // bios |
| 754 | 723 | AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8_LEGACY(saturn_SMPC_r, saturn_SMPC_w,0xffffffff) |
| 755 | | AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8_LEGACY(saturn_backupram_r, saturn_backupram_w,0xffffffff) AM_SHARE("share1") |
| 724 | AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r, saturn_backupram_w,0xffffffff) AM_SHARE("share1") |
| 756 | 725 | AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l") |
| 757 | | AM_RANGE(0x01000000, 0x017fffff) AM_WRITE_LEGACY(minit_w) |
| 758 | | AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE_LEGACY(sinit_w) |
| 726 | AM_RANGE(0x01000000, 0x017fffff) AM_WRITE(minit_w) |
| 727 | AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE(sinit_w) |
| 759 | 728 | AM_RANGE(0x02000000, 0x023fffff) AM_ROM AM_SHARE("share7") AM_REGION("maincpu", 0x80000) // cartridge space |
| 760 | 729 | // AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated |
| 761 | 730 | // AM_RANGE(0x04000000, 0x047fffff) AM_RAM //backup RAM area, dynamically allocated |
| 762 | | AM_RANGE(0x04fffffc, 0x04ffffff) AM_READ8_LEGACY(saturn_cart_type_r,0x000000ff) |
| 731 | AM_RANGE(0x04fffffc, 0x04ffffff) AM_READ8(saturn_cart_type_r,0x000000ff) |
| 763 | 732 | AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE_LEGACY(stvcd_r, stvcd_w) |
| 764 | 733 | /* Sound */ |
| 765 | | AM_RANGE(0x05a00000, 0x05a7ffff) AM_READWRITE16_LEGACY(saturn_soundram_r, saturn_soundram_w,0xffffffff) |
| 734 | AM_RANGE(0x05a00000, 0x05a7ffff) AM_READWRITE16(saturn_soundram_r, saturn_soundram_w,0xffffffff) |
| 766 | 735 | AM_RANGE(0x05b00000, 0x05b00fff) AM_DEVREADWRITE16_LEGACY("scsp", scsp_r, scsp_w, 0xffffffff) |
| 767 | 736 | /* VDP1 */ |
| 768 | 737 | AM_RANGE(0x05c00000, 0x05c7ffff) AM_READWRITE_LEGACY(saturn_vdp1_vram_r, saturn_vdp1_vram_w) |
| r18148 | r18149 | |
| 771 | 740 | AM_RANGE(0x05e00000, 0x05efffff) AM_READWRITE_LEGACY(saturn_vdp2_vram_r, saturn_vdp2_vram_w) |
| 772 | 741 | AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE_LEGACY(saturn_vdp2_cram_r, saturn_vdp2_cram_w) |
| 773 | 742 | AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16_LEGACY(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff) |
| 774 | | AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE_LEGACY(saturn_scu_r, saturn_scu_w) |
| 743 | AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w) |
| 775 | 744 | AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h") |
| 776 | 745 | AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6") // bios mirror |
| 777 | 746 | AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7") // cart mirror |
| r18148 | r18149 | |
| 782 | 751 | static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32, saturn_state ) |
| 783 | 752 | AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6") // bios |
| 784 | 753 | AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8_LEGACY(stv_SMPC_r, stv_SMPC_w,0xffffffff) |
| 785 | | AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8_LEGACY(saturn_backupram_r,saturn_backupram_w,0xffffffff) AM_SHARE("share1") |
| 754 | AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r,saturn_backupram_w,0xffffffff) AM_SHARE("share1") |
| 786 | 755 | AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l") |
| 787 | 756 | // AM_RANGE(0x00400000, 0x0040001f) AM_READWRITE_LEGACY(stv_ioga_r32, stv_io_w32) AM_SHARE("ioga") AM_MIRROR(0x20) /* installed with per-game specific */ |
| 788 | | AM_RANGE(0x01000000, 0x017fffff) AM_WRITE_LEGACY(minit_w) |
| 789 | | AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE_LEGACY(sinit_w) |
| 757 | AM_RANGE(0x01000000, 0x017fffff) AM_WRITE(minit_w) |
| 758 | AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE(sinit_w) |
| 790 | 759 | AM_RANGE(0x02000000, 0x04ffffff) AM_ROM AM_SHARE("share7") AM_REGION("abus", 0) // cartridge |
| 791 | 760 | AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE_LEGACY(stvcd_r, stvcd_w) |
| 792 | 761 | /* Sound */ |
| 793 | | AM_RANGE(0x05a00000, 0x05afffff) AM_READWRITE16_LEGACY(saturn_soundram_r, saturn_soundram_w,0xffffffff) |
| 762 | AM_RANGE(0x05a00000, 0x05afffff) AM_READWRITE16(saturn_soundram_r, saturn_soundram_w,0xffffffff) |
| 794 | 763 | AM_RANGE(0x05b00000, 0x05b00fff) AM_DEVREADWRITE16_LEGACY("scsp", scsp_r, scsp_w, 0xffffffff) |
| 795 | 764 | /* VDP1 */ |
| 796 | 765 | AM_RANGE(0x05c00000, 0x05c7ffff) AM_READWRITE_LEGACY(saturn_vdp1_vram_r, saturn_vdp1_vram_w) |
| r18148 | r18149 | |
| 799 | 768 | AM_RANGE(0x05e00000, 0x05efffff) AM_READWRITE_LEGACY(saturn_vdp2_vram_r, saturn_vdp2_vram_w) |
| 800 | 769 | AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE_LEGACY(saturn_vdp2_cram_r, saturn_vdp2_cram_w) |
| 801 | 770 | AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16_LEGACY(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff) |
| 802 | | AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE_LEGACY(saturn_scu_r, saturn_scu_w) |
| 771 | AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w) |
| 803 | 772 | AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h") |
| 804 | 773 | AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6") // bios mirror |
| 805 | 774 | AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7") // cart mirror |
| r18148 | r18149 | |
| 824 | 793 | |
| 825 | 794 | if(oldval && !newval) |
| 826 | 795 | { |
| 827 | | //state->m_keyb.status &= ~8; |
| 796 | //m_keyb.status &= ~8; |
| 828 | 797 | m_keyb.data = 0; |
| 829 | 798 | } |
| 830 | 799 | } |
| r18148 | r18149 | |
| 1628 | 1597 | static const sh2_cpu_core sh2_conf_master = { 0, NULL }; |
| 1629 | 1598 | static const sh2_cpu_core sh2_conf_slave = { 1, NULL }; |
| 1630 | 1599 | |
| 1631 | | static int scsp_last_line = 0; |
| 1632 | | |
| 1633 | 1600 | static void scsp_irq(device_t *device, int irq) |
| 1634 | 1601 | { |
| 1635 | 1602 | saturn_state *state = device->machine().driver_data<saturn_state>(); |
| r18148 | r18149 | |
| 1642 | 1609 | |
| 1643 | 1610 | if (irq > 0) |
| 1644 | 1611 | { |
| 1645 | | scsp_last_line = irq; |
| 1612 | state->m_scsp_last_line = irq; |
| 1646 | 1613 | device->machine().device("audiocpu")->execute().set_input_line(irq, ASSERT_LINE); |
| 1647 | 1614 | } |
| 1648 | 1615 | else if (irq < 0) |
| r18148 | r18149 | |
| 1651 | 1618 | } |
| 1652 | 1619 | else |
| 1653 | 1620 | { |
| 1654 | | device->machine().device("audiocpu")->execute().set_input_line(scsp_last_line, CLEAR_LINE); |
| 1621 | device->machine().device("audiocpu")->execute().set_input_line(state->m_scsp_last_line, CLEAR_LINE); |
| 1655 | 1622 | } |
| 1656 | 1623 | } |
| 1657 | 1624 | |
| 1658 | | static WRITE_LINE_DEVICE_HANDLER( scsp_to_main_irq ) |
| 1625 | WRITE_LINE_MEMBER(saturn_state::scsp_to_main_irq) |
| 1659 | 1626 | { |
| 1660 | | saturn_state *drvstate = device->machine().driver_data<saturn_state>(); |
| 1661 | | |
| 1662 | | if(!(drvstate->m_scu.ism & IRQ_SOUND_REQ)) |
| 1627 | if(!(m_scu.ism & IRQ_SOUND_REQ)) |
| 1663 | 1628 | { |
| 1664 | | drvstate->m_maincpu->set_input_line_and_vector(9, HOLD_LINE, 0x46); |
| 1665 | | scu_do_transfer(device->machine(),5); |
| 1629 | m_maincpu->set_input_line_and_vector(9, HOLD_LINE, 0x46); |
| 1630 | scu_do_transfer(5); |
| 1666 | 1631 | } |
| 1667 | 1632 | else |
| 1668 | | drvstate->m_scu.ist |= (IRQ_SOUND_REQ); |
| 1633 | m_scu.ist |= (IRQ_SOUND_REQ); |
| 1669 | 1634 | } |
| 1670 | 1635 | |
| 1671 | 1636 | static const scsp_interface scsp_config = |
| 1672 | 1637 | { |
| 1673 | 1638 | 0, |
| 1674 | 1639 | scsp_irq, |
| 1675 | | DEVCB_LINE(scsp_to_main_irq) |
| 1640 | DEVCB_DRIVER_LINE_MEMBER(saturn_state, scsp_to_main_irq) |
| 1676 | 1641 | }; |
| 1677 | 1642 | |
| 1678 | | static TIMER_CALLBACK(stv_rtc_increment) |
| 1643 | TIMER_CALLBACK_MEMBER(saturn_state::stv_rtc_increment) |
| 1679 | 1644 | { |
| 1680 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 1681 | 1645 | static const UINT8 dpm[12] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 }; |
| 1682 | 1646 | static int year_num, year_count; |
| 1683 | 1647 | |
| 1684 | 1648 | /* |
| 1685 | | state->m_smpc.rtc_data[0] = DectoBCD(systime.local_time.year /100); |
| 1686 | | state->m_smpc.rtc_data[1] = DectoBCD(systime.local_time.year %100); |
| 1687 | | state->m_smpc.rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1); |
| 1688 | | state->m_smpc.rtc_data[3] = DectoBCD(systime.local_time.mday); |
| 1689 | | state->m_smpc.rtc_data[4] = DectoBCD(systime.local_time.hour); |
| 1690 | | state->m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute); |
| 1691 | | state->m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second); |
| 1649 | m_smpc.rtc_data[0] = DectoBCD(systime.local_time.year /100); |
| 1650 | m_smpc.rtc_data[1] = DectoBCD(systime.local_time.year %100); |
| 1651 | m_smpc.rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1); |
| 1652 | m_smpc.rtc_data[3] = DectoBCD(systime.local_time.mday); |
| 1653 | m_smpc.rtc_data[4] = DectoBCD(systime.local_time.hour); |
| 1654 | m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute); |
| 1655 | m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second); |
| 1692 | 1656 | */ |
| 1693 | 1657 | |
| 1694 | | state->m_smpc.rtc_data[6]++; |
| 1658 | m_smpc.rtc_data[6]++; |
| 1695 | 1659 | |
| 1696 | 1660 | /* seconds from 9 -> 10*/ |
| 1697 | | if((state->m_smpc.rtc_data[6] & 0x0f) >= 0x0a) { state->m_smpc.rtc_data[6]+=0x10; state->m_smpc.rtc_data[6]&=0xf0; } |
| 1661 | if((m_smpc.rtc_data[6] & 0x0f) >= 0x0a) { m_smpc.rtc_data[6]+=0x10; m_smpc.rtc_data[6]&=0xf0; } |
| 1698 | 1662 | /* seconds from 59 -> 0 */ |
| 1699 | | if((state->m_smpc.rtc_data[6] & 0xf0) >= 0x60) { state->m_smpc.rtc_data[5]++; state->m_smpc.rtc_data[6] = 0; } |
| 1663 | if((m_smpc.rtc_data[6] & 0xf0) >= 0x60) { m_smpc.rtc_data[5]++; m_smpc.rtc_data[6] = 0; } |
| 1700 | 1664 | /* minutes from 9 -> 10 */ |
| 1701 | | if((state->m_smpc.rtc_data[5] & 0x0f) >= 0x0a) { state->m_smpc.rtc_data[5]+=0x10; state->m_smpc.rtc_data[5]&=0xf0; } |
| 1665 | if((m_smpc.rtc_data[5] & 0x0f) >= 0x0a) { m_smpc.rtc_data[5]+=0x10; m_smpc.rtc_data[5]&=0xf0; } |
| 1702 | 1666 | /* minutes from 59 -> 0 */ |
| 1703 | | if((state->m_smpc.rtc_data[5] & 0xf0) >= 0x60) { state->m_smpc.rtc_data[4]++; state->m_smpc.rtc_data[5] = 0; } |
| 1667 | if((m_smpc.rtc_data[5] & 0xf0) >= 0x60) { m_smpc.rtc_data[4]++; m_smpc.rtc_data[5] = 0; } |
| 1704 | 1668 | /* hours from 9 -> 10 */ |
| 1705 | | if((state->m_smpc.rtc_data[4] & 0x0f) >= 0x0a) { state->m_smpc.rtc_data[4]+=0x10; state->m_smpc.rtc_data[4]&=0xf0; } |
| 1669 | if((m_smpc.rtc_data[4] & 0x0f) >= 0x0a) { m_smpc.rtc_data[4]+=0x10; m_smpc.rtc_data[4]&=0xf0; } |
| 1706 | 1670 | /* hours from 23 -> 0 */ |
| 1707 | | if((state->m_smpc.rtc_data[4] & 0xff) >= 0x24) { state->m_smpc.rtc_data[3]++; state->m_smpc.rtc_data[2]+=0x10; state->m_smpc.rtc_data[4] = 0; } |
| 1671 | if((m_smpc.rtc_data[4] & 0xff) >= 0x24) { m_smpc.rtc_data[3]++; m_smpc.rtc_data[2]+=0x10; m_smpc.rtc_data[4] = 0; } |
| 1708 | 1672 | /* week day name sunday -> monday */ |
| 1709 | | if((state->m_smpc.rtc_data[2] & 0xf0) >= 0x70) { state->m_smpc.rtc_data[2]&=0x0f; } |
| 1673 | if((m_smpc.rtc_data[2] & 0xf0) >= 0x70) { m_smpc.rtc_data[2]&=0x0f; } |
| 1710 | 1674 | /* day number 9 -> 10 */ |
| 1711 | | if((state->m_smpc.rtc_data[3] & 0x0f) >= 0x0a) { state->m_smpc.rtc_data[3]+=0x10; state->m_smpc.rtc_data[3]&=0xf0; } |
| 1675 | if((m_smpc.rtc_data[3] & 0x0f) >= 0x0a) { m_smpc.rtc_data[3]+=0x10; m_smpc.rtc_data[3]&=0xf0; } |
| 1712 | 1676 | |
| 1713 | 1677 | // year BCD to dec conversion (for the leap year stuff) |
| 1714 | 1678 | { |
| 1715 | | year_num = (state->m_smpc.rtc_data[1] & 0xf); |
| 1679 | year_num = (m_smpc.rtc_data[1] & 0xf); |
| 1716 | 1680 | |
| 1717 | | for(year_count = 0; year_count < (state->m_smpc.rtc_data[1] & 0xf0); year_count += 0x10) |
| 1681 | for(year_count = 0; year_count < (m_smpc.rtc_data[1] & 0xf0); year_count += 0x10) |
| 1718 | 1682 | year_num += 0xa; |
| 1719 | 1683 | |
| 1720 | | year_num += (state->m_smpc.rtc_data[0] & 0xf)*0x64; |
| 1684 | year_num += (m_smpc.rtc_data[0] & 0xf)*0x64; |
| 1721 | 1685 | |
| 1722 | | for(year_count = 0; year_count < (state->m_smpc.rtc_data[0] & 0xf0); year_count += 0x10) |
| 1686 | for(year_count = 0; year_count < (m_smpc.rtc_data[0] & 0xf0); year_count += 0x10) |
| 1723 | 1687 | year_num += 0x3e8; |
| 1724 | 1688 | } |
| 1725 | 1689 | |
| 1726 | 1690 | /* month +1 check */ |
| 1727 | 1691 | /* the RTC have a range of 1980 - 2100, so we don't actually need to support the leap year special conditions */ |
| 1728 | | if(((year_num % 4) == 0) && (state->m_smpc.rtc_data[2] & 0xf) == 2) |
| 1692 | if(((year_num % 4) == 0) && (m_smpc.rtc_data[2] & 0xf) == 2) |
| 1729 | 1693 | { |
| 1730 | | if((state->m_smpc.rtc_data[3] & 0xff) >= dpm[(state->m_smpc.rtc_data[2] & 0xf)-1]+1+1) |
| 1731 | | { state->m_smpc.rtc_data[2]++; state->m_smpc.rtc_data[3] = 0x01; } |
| 1694 | if((m_smpc.rtc_data[3] & 0xff) >= dpm[(m_smpc.rtc_data[2] & 0xf)-1]+1+1) |
| 1695 | { m_smpc.rtc_data[2]++; m_smpc.rtc_data[3] = 0x01; } |
| 1732 | 1696 | } |
| 1733 | | else if((state->m_smpc.rtc_data[3] & 0xff) >= dpm[(state->m_smpc.rtc_data[2] & 0xf)-1]+1){ state->m_smpc.rtc_data[2]++; state->m_smpc.rtc_data[3] = 0x01; } |
| 1697 | else if((m_smpc.rtc_data[3] & 0xff) >= dpm[(m_smpc.rtc_data[2] & 0xf)-1]+1){ m_smpc.rtc_data[2]++; m_smpc.rtc_data[3] = 0x01; } |
| 1734 | 1698 | /* year +1 check */ |
| 1735 | | if((state->m_smpc.rtc_data[2] & 0x0f) > 12) { state->m_smpc.rtc_data[1]++; state->m_smpc.rtc_data[2] = (state->m_smpc.rtc_data[2] & 0xf0) | 0x01; } |
| 1699 | if((m_smpc.rtc_data[2] & 0x0f) > 12) { m_smpc.rtc_data[1]++; m_smpc.rtc_data[2] = (m_smpc.rtc_data[2] & 0xf0) | 0x01; } |
| 1736 | 1700 | /* year from 9 -> 10 */ |
| 1737 | | if((state->m_smpc.rtc_data[1] & 0x0f) >= 0x0a) { state->m_smpc.rtc_data[1]+=0x10; state->m_smpc.rtc_data[1]&=0xf0; } |
| 1701 | if((m_smpc.rtc_data[1] & 0x0f) >= 0x0a) { m_smpc.rtc_data[1]+=0x10; m_smpc.rtc_data[1]&=0xf0; } |
| 1738 | 1702 | /* year from 99 -> 100 */ |
| 1739 | | if((state->m_smpc.rtc_data[1] & 0xf0) >= 0xa0) { state->m_smpc.rtc_data[0]++; state->m_smpc.rtc_data[1] = 0; } |
| 1703 | if((m_smpc.rtc_data[1] & 0xf0) >= 0xa0) { m_smpc.rtc_data[0]++; m_smpc.rtc_data[1] = 0; } |
| 1740 | 1704 | |
| 1741 | 1705 | // probably not SO precise, here just for reference ... |
| 1742 | 1706 | /* year from 999 -> 1000 */ |
| 1743 | | //if((state->m_smpc.rtc_data[0] & 0x0f) >= 0x0a) { state->m_smpc.rtc_data[0]+=0x10; state->m_smpc.rtc_data[0]&=0xf0; } |
| 1707 | //if((m_smpc.rtc_data[0] & 0x0f) >= 0x0a) { m_smpc.rtc_data[0]+=0x10; m_smpc.rtc_data[0]&=0xf0; } |
| 1744 | 1708 | /* year from 9999 -> 0 */ |
| 1745 | | //if((state->m_smpc.rtc_data[0] & 0xf0) >= 0xa0) { state->m_smpc.rtc_data[0] = 0; } //roll over |
| 1709 | //if((m_smpc.rtc_data[0] & 0xf0) >= 0xa0) { m_smpc.rtc_data[0] = 0; } //roll over |
| 1746 | 1710 | } |
| 1747 | 1711 | |
| 1748 | 1712 | MACHINE_START_MEMBER(saturn_state,stv) |
| r18148 | r18149 | |
| 1770 | 1734 | state_save_register_global(machine(), m_smpc.PDR2); |
| 1771 | 1735 | state_save_register_global(machine(), m_port_sel); |
| 1772 | 1736 | state_save_register_global(machine(), m_mux_data); |
| 1773 | | state_save_register_global(machine(), scsp_last_line); |
| 1737 | state_save_register_global(machine(), m_scsp_last_line); |
| 1774 | 1738 | |
| 1775 | 1739 | stv_register_protection_savestates(machine()); // machine/stvprot.c |
| 1776 | 1740 | |
| r18148 | r18149 | |
| 1784 | 1748 | m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute); |
| 1785 | 1749 | m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second); |
| 1786 | 1750 | |
| 1787 | | m_stv_rtc_timer = machine().scheduler().timer_alloc(FUNC(stv_rtc_increment)); |
| 1751 | m_stv_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(saturn_state::stv_rtc_increment),this)); |
| 1788 | 1752 | } |
| 1789 | 1753 | |
| 1790 | 1754 | |
| r18148 | r18149 | |
| 1812 | 1776 | state_save_register_global(machine(), m_smpc.PDR2); |
| 1813 | 1777 | // state_save_register_global(machine(), m_port_sel); |
| 1814 | 1778 | // state_save_register_global(machine(), mux_data); |
| 1815 | | state_save_register_global(machine(), scsp_last_line); |
| 1779 | state_save_register_global(machine(), m_scsp_last_line); |
| 1816 | 1780 | state_save_register_global(machine(), m_smpc.intback_stage); |
| 1817 | 1781 | state_save_register_global(machine(), m_smpc.pmode); |
| 1818 | 1782 | state_save_register_global(machine(), m_smpc.SR); |
| r18148 | r18149 | |
| 1829 | 1793 | m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute); |
| 1830 | 1794 | m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second); |
| 1831 | 1795 | |
| 1832 | | m_stv_rtc_timer = machine().scheduler().timer_alloc(FUNC(stv_rtc_increment)); |
| 1796 | m_stv_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(saturn_state::stv_rtc_increment),this)); |
| 1833 | 1797 | } |
| 1834 | 1798 | |
| 1835 | 1799 | |
| r18148 | r18149 | |
| 1860 | 1824 | { |
| 1861 | 1825 | saturn_state *state = machine().driver_data<saturn_state>(); |
| 1862 | 1826 | int scanline = param; |
| 1863 | | int max_y = timer.machine().primary_screen->height(); |
| 1827 | int max_y = machine().primary_screen->height(); |
| 1864 | 1828 | int y_step,vblank_line; |
| 1865 | 1829 | |
| 1866 | 1830 | y_step = 2; |
| r18148 | r18149 | |
| 1874 | 1838 | |
| 1875 | 1839 | if(scanline == (0)*y_step) |
| 1876 | 1840 | { |
| 1877 | | video_update_vdp1(timer.machine()); |
| 1841 | video_update_vdp1(machine()); |
| 1878 | 1842 | |
| 1879 | 1843 | if(STV_VDP1_VBE) |
| 1880 | 1844 | m_vdp1.framebuffer_clear_on_next_frame = 1; |
| r18148 | r18149 | |
| 1882 | 1846 | if(!(m_scu.ism & IRQ_VDP1_END)) |
| 1883 | 1847 | { |
| 1884 | 1848 | m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d); |
| 1885 | | scu_do_transfer(timer.machine(),6); |
| 1849 | scu_do_transfer(6); |
| 1886 | 1850 | } |
| 1887 | 1851 | else |
| 1888 | 1852 | m_scu.ist |= (IRQ_VDP1_END); |
| r18148 | r18149 | |
| 1893 | 1857 | if(!(m_scu.ism & IRQ_VBLANK_OUT)) |
| 1894 | 1858 | { |
| 1895 | 1859 | m_maincpu->set_input_line_and_vector(0xe, HOLD_LINE, 0x41); |
| 1896 | | scu_do_transfer(timer.machine(),1); |
| 1860 | scu_do_transfer(1); |
| 1897 | 1861 | } |
| 1898 | 1862 | else |
| 1899 | 1863 | m_scu.ist |= (IRQ_VBLANK_OUT); |
| r18148 | r18149 | |
| 1904 | 1868 | if(!(m_scu.ism & IRQ_VBLANK_IN)) |
| 1905 | 1869 | { |
| 1906 | 1870 | m_maincpu->set_input_line_and_vector(0xf, HOLD_LINE ,0x40); |
| 1907 | | scu_do_transfer(timer.machine(),0); |
| 1871 | scu_do_transfer(0); |
| 1908 | 1872 | } |
| 1909 | 1873 | else |
| 1910 | 1874 | m_scu.ist |= (IRQ_VBLANK_IN); |
| r18148 | r18149 | |
| 1914 | 1878 | if(!(m_scu.ism & IRQ_HBLANK_IN)) |
| 1915 | 1879 | { |
| 1916 | 1880 | m_maincpu->set_input_line_and_vector(0xd, HOLD_LINE, 0x42); |
| 1917 | | scu_do_transfer(timer.machine(),2); |
| 1881 | scu_do_transfer(2); |
| 1918 | 1882 | } |
| 1919 | 1883 | else |
| 1920 | 1884 | m_scu.ist |= (IRQ_HBLANK_IN); |
| r18148 | r18149 | |
| 1925 | 1889 | if(!(m_scu.ism & IRQ_TIMER_0)) |
| 1926 | 1890 | { |
| 1927 | 1891 | m_maincpu->set_input_line_and_vector(0xc, HOLD_LINE, 0x43 ); |
| 1928 | | scu_do_transfer(timer.machine(),3); |
| 1892 | scu_do_transfer(3); |
| 1929 | 1893 | } |
| 1930 | 1894 | else |
| 1931 | 1895 | m_scu.ist |= (IRQ_TIMER_0); |
| r18148 | r18149 | |
| 1940 | 1904 | if(!(m_scu.ism & IRQ_TIMER_1)) |
| 1941 | 1905 | { |
| 1942 | 1906 | m_maincpu->set_input_line_and_vector(0xb, HOLD_LINE, 0x44 ); |
| 1943 | | scu_do_transfer(timer.machine(),4); |
| 1907 | scu_do_transfer(4); |
| 1944 | 1908 | } |
| 1945 | 1909 | else |
| 1946 | 1910 | m_scu.ist |= (IRQ_TIMER_1); |
| r18148 | r18149 | |
| 1951 | 1915 | TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_slave_scanline ) |
| 1952 | 1916 | { |
| 1953 | 1917 | int scanline = param; |
| 1954 | | int max_y = timer.machine().primary_screen->height(); |
| 1918 | int max_y = machine().primary_screen->height(); |
| 1955 | 1919 | int y_step,vblank_line; |
| 1956 | 1920 | |
| 1957 | 1921 | y_step = 2; |
| r18148 | r18149 | |
| 1968 | 1932 | } |
| 1969 | 1933 | |
| 1970 | 1934 | /* Die Hard Trilogy tests RAM address 0x25e7ffe bit 2 with Slave during FRT minit irq, in-development tool for breaking execution of it? */ |
| 1971 | | static READ32_HANDLER( saturn_null_ram_r ) |
| 1935 | READ32_MEMBER(saturn_state::saturn_null_ram_r) |
| 1972 | 1936 | { |
| 1973 | 1937 | return 0xffffffff; |
| 1974 | 1938 | } |
| 1975 | 1939 | |
| 1976 | | static WRITE32_HANDLER( saturn_null_ram_w ) |
| 1940 | WRITE32_MEMBER(saturn_state::saturn_null_ram_w) |
| 1977 | 1941 | { |
| 1978 | 1942 | |
| 1979 | 1943 | } |
| 1980 | 1944 | |
| 1981 | | static READ32_HANDLER( saturn_cart_dram0_r ) |
| 1945 | READ32_MEMBER(saturn_state::saturn_cart_dram0_r) |
| 1982 | 1946 | { |
| 1983 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 1984 | | |
| 1985 | | return state->m_cart_dram[offset]; |
| 1947 | return m_cart_dram[offset]; |
| 1986 | 1948 | } |
| 1987 | 1949 | |
| 1988 | | static WRITE32_HANDLER( saturn_cart_dram0_w ) |
| 1950 | WRITE32_MEMBER(saturn_state::saturn_cart_dram0_w) |
| 1989 | 1951 | { |
| 1990 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 1991 | | |
| 1992 | | COMBINE_DATA(&state->m_cart_dram[offset]); |
| 1952 | COMBINE_DATA(&m_cart_dram[offset]); |
| 1993 | 1953 | } |
| 1994 | 1954 | |
| 1995 | | static READ32_HANDLER( saturn_cart_dram1_r ) |
| 1955 | READ32_MEMBER(saturn_state::saturn_cart_dram1_r) |
| 1996 | 1956 | { |
| 1997 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 1998 | | |
| 1999 | | return state->m_cart_dram[offset+0x200000/4]; |
| 1957 | return m_cart_dram[offset+0x200000/4]; |
| 2000 | 1958 | } |
| 2001 | 1959 | |
| 2002 | | static WRITE32_HANDLER( saturn_cart_dram1_w ) |
| 1960 | WRITE32_MEMBER(saturn_state::saturn_cart_dram1_w) |
| 2003 | 1961 | { |
| 2004 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 2005 | | |
| 2006 | | COMBINE_DATA(&state->m_cart_dram[offset+0x200000/4]); |
| 1962 | COMBINE_DATA(&m_cart_dram[offset+0x200000/4]); |
| 2007 | 1963 | } |
| 2008 | 1964 | |
| 2009 | | static READ32_HANDLER( saturn_cs1_r ) |
| 1965 | READ32_MEMBER(saturn_state::saturn_cs1_r) |
| 2010 | 1966 | { |
| 2011 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 2012 | 1967 | UINT32 res; |
| 2013 | 1968 | |
| 2014 | 1969 | res = 0; |
| 2015 | | //res = state->m_cart_backupram[offset*4+0] << 24; |
| 2016 | | res |= state->m_cart_backupram[offset*2+0] << 16; |
| 2017 | | //res |= state->m_cart_backupram[offset*4+2] << 8; |
| 2018 | | res |= state->m_cart_backupram[offset*2+1] << 0; |
| 1970 | //res = m_cart_backupram[offset*4+0] << 24; |
| 1971 | res |= m_cart_backupram[offset*2+0] << 16; |
| 1972 | //res |= m_cart_backupram[offset*4+2] << 8; |
| 1973 | res |= m_cart_backupram[offset*2+1] << 0; |
| 2019 | 1974 | |
| 2020 | 1975 | return res; |
| 2021 | 1976 | } |
| 2022 | 1977 | |
| 2023 | | static WRITE32_HANDLER( saturn_cs1_w ) |
| 1978 | WRITE32_MEMBER(saturn_state::saturn_cs1_w) |
| 2024 | 1979 | { |
| 2025 | | saturn_state *state = space.machine().driver_data<saturn_state>(); |
| 2026 | | |
| 2027 | 1980 | if(ACCESSING_BITS_16_23) |
| 2028 | | state->m_cart_backupram[offset*2+0] = (data & 0x00ff0000) >> 16; |
| 1981 | m_cart_backupram[offset*2+0] = (data & 0x00ff0000) >> 16; |
| 2029 | 1982 | if(ACCESSING_BITS_0_7) |
| 2030 | | state->m_cart_backupram[offset*2+1] = (data & 0x000000ff) >> 0; |
| 1983 | m_cart_backupram[offset*2+1] = (data & 0x000000ff) >> 0; |
| 2031 | 1984 | } |
| 2032 | 1985 | |
| 2033 | 1986 | MACHINE_RESET_MEMBER(saturn_state,saturn) |
| 2034 | 1987 | { |
| 1988 | m_scsp_last_line = 0; |
| 1989 | |
| 2035 | 1990 | // don't let the slave cpu and the 68k go anywhere |
| 2036 | 1991 | machine().device("slave")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 2037 | 1992 | machine().device("audiocpu")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| r18148 | r18149 | |
| 2053 | 2008 | |
| 2054 | 2009 | m_cart_type = ioport("CART_AREA")->read() & 7; |
| 2055 | 2010 | |
| 2056 | | machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02400000, 0x027fffff, FUNC(saturn_null_ram_r), FUNC(saturn_null_ram_w)); |
| 2057 | | machine().device("slave")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02400000, 0x027fffff, FUNC(saturn_null_ram_r), FUNC(saturn_null_ram_w)); |
| 2011 | machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_null_ram_r),this), write32_delegate(FUNC(saturn_state::saturn_null_ram_w),this)); |
| 2012 | machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_null_ram_r),this), write32_delegate(FUNC(saturn_state::saturn_null_ram_w),this)); |
| 2058 | 2013 | |
| 2059 | 2014 | if(m_cart_type == 5) |
| 2060 | 2015 | { |
| r18148 | r18149 | |
| 2062 | 2017 | machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff); |
| 2063 | 2018 | machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff); |
| 2064 | 2019 | |
| 2065 | | machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02400000, 0x0247ffff, FUNC(saturn_cart_dram0_r), FUNC(saturn_cart_dram0_w)); |
| 2066 | | machine().device("slave")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02400000, 0x0247ffff, FUNC(saturn_cart_dram0_r), FUNC(saturn_cart_dram0_w)); |
| 2067 | | machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02600000, 0x0267ffff, FUNC(saturn_cart_dram1_r), FUNC(saturn_cart_dram1_w)); |
| 2068 | | machine().device("slave")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02600000, 0x0267ffff, FUNC(saturn_cart_dram1_r), FUNC(saturn_cart_dram1_w)); |
| 2020 | machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x0247ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this)); |
| 2021 | machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x0247ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this)); |
| 2022 | machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x0267ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this)); |
| 2023 | machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x0267ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this)); |
| 2069 | 2024 | } |
| 2070 | 2025 | |
| 2071 | 2026 | if(m_cart_type == 6) |
| r18148 | r18149 | |
| 2074 | 2029 | machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff); |
| 2075 | 2030 | machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff); |
| 2076 | 2031 | |
| 2077 | | machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02400000, 0x025fffff, FUNC(saturn_cart_dram0_r), FUNC(saturn_cart_dram0_w)); |
| 2078 | | machine().device("slave")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02400000, 0x025fffff, FUNC(saturn_cart_dram0_r), FUNC(saturn_cart_dram0_w)); |
| 2079 | | machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02600000, 0x027fffff, FUNC(saturn_cart_dram1_r), FUNC(saturn_cart_dram1_w)); |
| 2080 | | machine().device("slave")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x02600000, 0x027fffff, FUNC(saturn_cart_dram1_r), FUNC(saturn_cart_dram1_w)); |
| 2032 | machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x025fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this)); |
| 2033 | machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x025fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this)); |
| 2034 | machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this)); |
| 2035 | machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this)); |
| 2081 | 2036 | } |
| 2082 | 2037 | |
| 2083 | 2038 | machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x04000000, 0x047fffff); |
| r18148 | r18149 | |
| 2092 | 2047 | //mask = 0x7fffff >> 4-3 = 0x3fffff 16mbit |
| 2093 | 2048 | //mask = 0x7fffff >> 4-2 = 0x1fffff 8mbit |
| 2094 | 2049 | //mask = 0x7fffff >> 4-1 = 0x0fffff 4mbit |
| 2095 | | machine().device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x04000000, 0x04000000 | mask, FUNC(saturn_cs1_r), FUNC(saturn_cs1_w)); |
| 2096 | | machine().device("slave")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x04000000, 0x04000000 | mask, FUNC(saturn_cs1_r), FUNC(saturn_cs1_w)); |
| 2050 | machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x04000000, 0x04000000 | mask, read32_delegate(FUNC(saturn_state::saturn_cs1_r),this), write32_delegate(FUNC(saturn_state::saturn_cs1_w),this)); |
| 2051 | machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x04000000, 0x04000000 | mask, read32_delegate(FUNC(saturn_state::saturn_cs1_r),this), write32_delegate(FUNC(saturn_state::saturn_cs1_w),this)); |
| 2097 | 2052 | } |
| 2098 | 2053 | |
| 2099 | 2054 | |
| r18148 | r18149 | |
| 2111 | 2066 | |
| 2112 | 2067 | MACHINE_RESET_MEMBER(saturn_state,stv) |
| 2113 | 2068 | { |
| 2114 | | |
| 2069 | m_scsp_last_line = 0; |
| 2070 | |
| 2115 | 2071 | // don't let the slave cpu and the 68k go anywhere |
| 2116 | 2072 | machine().device("slave")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 2117 | 2073 | machine().device("audiocpu")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| r18148 | r18149 | |
| 2403 | 2359 | MACHINE_CONFIG_END |
| 2404 | 2360 | |
| 2405 | 2361 | |
| 2406 | | static void saturn_init_driver(running_machine &machine, int rgn) |
| 2362 | void saturn_state::saturn_init_driver(int rgn) |
| 2407 | 2363 | { |
| 2408 | | saturn_state *state = machine.driver_data<saturn_state>(); |
| 2364 | m_saturn_region = rgn; |
| 2365 | m_vdp2.pal = (rgn == 12) ? 1 : 0; |
| 2409 | 2366 | |
| 2410 | | state->m_saturn_region = rgn; |
| 2411 | | state->m_vdp2.pal = (rgn == 12) ? 1 : 0; |
| 2412 | | |
| 2413 | 2367 | // set compatible options |
| 2414 | | sh2drc_set_options(machine.device("maincpu"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL); |
| 2415 | | sh2drc_set_options(machine.device("slave"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL); |
| 2368 | sh2drc_set_options(machine().device("maincpu"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL); |
| 2369 | sh2drc_set_options(machine().device("slave"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL); |
| 2416 | 2370 | |
| 2417 | 2371 | /* amount of time to boost interleave for on MINIT / SINIT, needed for communication to work */ |
| 2418 | | state->m_minit_boost = 400; |
| 2419 | | state->m_sinit_boost = 400; |
| 2420 | | state->m_minit_boost_timeslice = attotime::zero; |
| 2421 | | state->m_sinit_boost_timeslice = attotime::zero; |
| 2372 | m_minit_boost = 400; |
| 2373 | m_sinit_boost = 400; |
| 2374 | m_minit_boost_timeslice = attotime::zero; |
| 2375 | m_sinit_boost_timeslice = attotime::zero; |
| 2422 | 2376 | |
| 2423 | | state->m_scu_regs = auto_alloc_array(machine, UINT32, 0x100/4); |
| 2424 | | state->m_scsp_regs = auto_alloc_array(machine, UINT16, 0x1000/2); |
| 2425 | | state->m_cart_dram = auto_alloc_array(machine, UINT32, 0x400000/4); |
| 2426 | | state->m_backupram = auto_alloc_array(machine, UINT8, 0x8000); |
| 2427 | | state->m_cart_backupram = auto_alloc_array(machine, UINT8, 0x400000); |
| 2377 | m_scu_regs = auto_alloc_array(machine(), UINT32, 0x100/4); |
| 2378 | m_scsp_regs = auto_alloc_array(machine(), UINT16, 0x1000/2); |
| 2379 | m_cart_dram = auto_alloc_array(machine(), UINT32, 0x400000/4); |
| 2380 | m_backupram = auto_alloc_array(machine(), UINT8, 0x8000); |
| 2381 | m_cart_backupram = auto_alloc_array(machine(), UINT8, 0x400000); |
| 2428 | 2382 | } |
| 2429 | 2383 | |
| 2430 | 2384 | DRIVER_INIT_MEMBER(saturn_state,saturnus) |
| 2431 | 2385 | { |
| 2432 | | saturn_init_driver(machine(), 4); |
| 2386 | saturn_init_driver(4); |
| 2433 | 2387 | } |
| 2434 | 2388 | |
| 2435 | 2389 | DRIVER_INIT_MEMBER(saturn_state,saturneu) |
| 2436 | 2390 | { |
| 2437 | | saturn_init_driver(machine(), 12); |
| 2391 | saturn_init_driver(12); |
| 2438 | 2392 | } |
| 2439 | 2393 | |
| 2440 | 2394 | DRIVER_INIT_MEMBER(saturn_state,saturnjp) |
| 2441 | 2395 | { |
| 2442 | | saturn_init_driver(machine(), 1); |
| 2396 | saturn_init_driver(1); |
| 2443 | 2397 | } |
| 2444 | 2398 | |
| 2445 | 2399 | |