trunk/src/mess/machine/amstrad.c
| r20956 | r20957 | |
| 197 | 197 | Prototypes |
| 198 | 198 | *******************************************************************/ |
| 199 | 199 | |
| 200 | | INLINE void amstrad_update_video( running_machine &machine ); |
| 201 | | INLINE void amstrad_plus_update_video( running_machine &machine ); |
| 202 | | static void amstrad_rethinkMemory(running_machine &machine); |
| 203 | | |
| 204 | | |
| 205 | 200 | /* Initialise the palette */ |
| 206 | 201 | PALETTE_INIT_MEMBER(amstrad_state,amstrad_cpc) |
| 207 | 202 | { |
| r20956 | r20957 | |
| 363 | 358 | } |
| 364 | 359 | |
| 365 | 360 | |
| 366 | | static void amstrad_init_lookups( amstrad_state *state ) |
| 361 | void amstrad_state::amstrad_init_lookups() |
| 367 | 362 | { |
| 368 | 363 | int i; |
| 369 | 364 | |
| 370 | 365 | for ( i = 0; i < 256; i++ ) |
| 371 | 366 | { |
| 372 | | state->m_mode0_lookup[i] = ( ( i & 0x80 ) >> 7 ) | ( ( i & 0x20 ) >> 3 ) | ( ( i & 0x08 ) >> 2 ) | ( ( i & 0x02 ) << 2 ); |
| 373 | | state->m_mode1_lookup[i] = ( ( i & 0x80 ) >> 7 ) | ( ( i & 0x08 ) >> 2 ); |
| 374 | | state->m_mode2_lookup[i] = ( ( i & 0x80 ) >> 7 ); |
| 367 | m_mode0_lookup[i] = ( ( i & 0x80 ) >> 7 ) | ( ( i & 0x20 ) >> 3 ) | ( ( i & 0x08 ) >> 2 ) | ( ( i & 0x02 ) << 2 ); |
| 368 | m_mode1_lookup[i] = ( ( i & 0x80 ) >> 7 ) | ( ( i & 0x08 ) >> 2 ); |
| 369 | m_mode2_lookup[i] = ( ( i & 0x80 ) >> 7 ); |
| 375 | 370 | } |
| 376 | 371 | } |
| 377 | 372 | |
| 378 | 373 | |
| 379 | 374 | /* Set the new screen mode (0,1,2,4) from the GateArray */ |
| 380 | | static void amstrad_vh_update_mode( amstrad_state *state ) |
| 375 | void amstrad_state::amstrad_vh_update_mode() |
| 381 | 376 | { |
| 382 | | if ( state->m_system_type == SYSTEM_PLUS || state->m_system_type == SYSTEM_GX4000 ) |
| 377 | if ( m_system_type == SYSTEM_PLUS || m_system_type == SYSTEM_GX4000 ) |
| 383 | 378 | { |
| 384 | 379 | /* select a cpc plus mode */ |
| 385 | | switch ( state->m_gate_array.mrer & 0x03 ) |
| 380 | switch ( m_gate_array.mrer & 0x03 ) |
| 386 | 381 | { |
| 387 | 382 | case 0: /* Mode 0: 160x200, 16 colours */ |
| 388 | | state->m_gate_array.mode_lookup = state->m_mode0_lookup; |
| 389 | | state->m_gate_array.max_colour_ticks = 4; |
| 390 | | state->m_gate_array.ticks_increment = 1; |
| 383 | m_gate_array.mode_lookup = m_mode0_lookup; |
| 384 | m_gate_array.max_colour_ticks = 4; |
| 385 | m_gate_array.ticks_increment = 1; |
| 391 | 386 | break; |
| 392 | 387 | |
| 393 | 388 | case 1: /* Mode 1: 320x200, 4 colous */ |
| 394 | | state->m_gate_array.mode_lookup = state->m_mode1_lookup; |
| 395 | | state->m_gate_array.max_colour_ticks = 2; |
| 396 | | state->m_gate_array.ticks_increment = 1; |
| 389 | m_gate_array.mode_lookup = m_mode1_lookup; |
| 390 | m_gate_array.max_colour_ticks = 2; |
| 391 | m_gate_array.ticks_increment = 1; |
| 397 | 392 | break; |
| 398 | 393 | |
| 399 | 394 | case 2: /* Mode 2: 640x200, 2 colours */ |
| 400 | | state->m_gate_array.mode_lookup = state->m_mode2_lookup; |
| 401 | | state->m_gate_array.max_colour_ticks = 1; |
| 402 | | state->m_gate_array.ticks_increment = 1; |
| 395 | m_gate_array.mode_lookup = m_mode2_lookup; |
| 396 | m_gate_array.max_colour_ticks = 1; |
| 397 | m_gate_array.ticks_increment = 1; |
| 403 | 398 | break; |
| 404 | 399 | |
| 405 | 400 | case 3: /* Mode 3: 160x200, 4 colours */ |
| 406 | | state->m_gate_array.mode_lookup = state->m_mode0_lookup; |
| 407 | | state->m_gate_array.max_colour_ticks = 4; |
| 408 | | state->m_gate_array.ticks_increment = 1; |
| 401 | m_gate_array.mode_lookup = m_mode0_lookup; |
| 402 | m_gate_array.max_colour_ticks = 4; |
| 403 | m_gate_array.ticks_increment = 1; |
| 409 | 404 | break; |
| 410 | 405 | } |
| 411 | 406 | } |
| 412 | 407 | else |
| 413 | 408 | { |
| 414 | | if ( state->m_aleste_mode & 0x02 ) |
| 409 | if ( m_aleste_mode & 0x02 ) |
| 415 | 410 | { |
| 416 | 411 | /* select an aleste mode */ |
| 417 | | switch ( state->m_gate_array.mrer & 0x03 ) |
| 412 | switch ( m_gate_array.mrer & 0x03 ) |
| 418 | 413 | { |
| 419 | 414 | case 0: /* Aleste Mode 0 (= Amstrad CPC mode 2): 640x200, 2 colours */ |
| 420 | | state->m_gate_array.mode_lookup = state->m_mode2_lookup; |
| 421 | | state->m_gate_array.max_colour_ticks = 1; |
| 422 | | state->m_gate_array.ticks_increment = 1; |
| 415 | m_gate_array.mode_lookup = m_mode2_lookup; |
| 416 | m_gate_array.max_colour_ticks = 1; |
| 417 | m_gate_array.ticks_increment = 1; |
| 423 | 418 | break; |
| 424 | 419 | |
| 425 | 420 | case 1: /* Aleste mode 1 (= Amstrad CPC mode 1): 320x200, 4 colours */ |
| 426 | | state->m_gate_array.mode_lookup = state->m_mode1_lookup; |
| 427 | | state->m_gate_array.max_colour_ticks = 2; |
| 428 | | state->m_gate_array.ticks_increment = 1; |
| 421 | m_gate_array.mode_lookup = m_mode1_lookup; |
| 422 | m_gate_array.max_colour_ticks = 2; |
| 423 | m_gate_array.ticks_increment = 1; |
| 429 | 424 | break; |
| 430 | 425 | |
| 431 | 426 | case 2: /* Aleste mode 2: 4 colours */ |
| 432 | | state->m_gate_array.mode_lookup = state->m_mode1_lookup; |
| 433 | | state->m_gate_array.max_colour_ticks = 1; |
| 434 | | state->m_gate_array.ticks_increment = 2; |
| 427 | m_gate_array.mode_lookup = m_mode1_lookup; |
| 428 | m_gate_array.max_colour_ticks = 1; |
| 429 | m_gate_array.ticks_increment = 2; |
| 435 | 430 | break; |
| 436 | 431 | |
| 437 | 432 | case 3: /* Aleste mode 3: 16 colours */ |
| 438 | | state->m_gate_array.mode_lookup = state->m_mode0_lookup; |
| 439 | | state->m_gate_array.max_colour_ticks = 2; |
| 440 | | state->m_gate_array.ticks_increment = 2; |
| 433 | m_gate_array.mode_lookup = m_mode0_lookup; |
| 434 | m_gate_array.max_colour_ticks = 2; |
| 435 | m_gate_array.ticks_increment = 2; |
| 441 | 436 | break; |
| 442 | 437 | } |
| 443 | 438 | } |
| 444 | 439 | else |
| 445 | 440 | { |
| 446 | 441 | /* select an original cpc mode */ |
| 447 | | switch ( state->m_gate_array.mrer & 0x03 ) |
| 442 | switch ( m_gate_array.mrer & 0x03 ) |
| 448 | 443 | { |
| 449 | 444 | case 0: /* Mode 0: 160x200, 16 colours */ |
| 450 | | state->m_gate_array.mode_lookup = state->m_mode0_lookup; |
| 451 | | state->m_gate_array.max_colour_ticks = 4; |
| 452 | | state->m_gate_array.ticks_increment = 1; |
| 445 | m_gate_array.mode_lookup = m_mode0_lookup; |
| 446 | m_gate_array.max_colour_ticks = 4; |
| 447 | m_gate_array.ticks_increment = 1; |
| 453 | 448 | break; |
| 454 | 449 | |
| 455 | 450 | case 1: /* Mode 1: 320x200, 4 colous */ |
| 456 | | state->m_gate_array.mode_lookup = state->m_mode1_lookup; |
| 457 | | state->m_gate_array.max_colour_ticks = 2; |
| 458 | | state->m_gate_array.ticks_increment = 1; |
| 451 | m_gate_array.mode_lookup = m_mode1_lookup; |
| 452 | m_gate_array.max_colour_ticks = 2; |
| 453 | m_gate_array.ticks_increment = 1; |
| 459 | 454 | break; |
| 460 | 455 | |
| 461 | 456 | case 2: /* Mode 2: 640x200, 2 colours */ |
| 462 | | state->m_gate_array.mode_lookup = state->m_mode2_lookup; |
| 463 | | state->m_gate_array.max_colour_ticks = 1; |
| 464 | | state->m_gate_array.ticks_increment = 1; |
| 457 | m_gate_array.mode_lookup = m_mode2_lookup; |
| 458 | m_gate_array.max_colour_ticks = 1; |
| 459 | m_gate_array.ticks_increment = 1; |
| 465 | 460 | break; |
| 466 | 461 | |
| 467 | 462 | case 3: /* Mode 3: 160x200, 4 colours */ |
| 468 | | state->m_gate_array.mode_lookup = state->m_mode0_lookup; |
| 469 | | state->m_gate_array.max_colour_ticks = 4; |
| 470 | | state->m_gate_array.ticks_increment = 1; |
| 463 | m_gate_array.mode_lookup = m_mode0_lookup; |
| 464 | m_gate_array.max_colour_ticks = 4; |
| 465 | m_gate_array.ticks_increment = 1; |
| 471 | 466 | break; |
| 472 | 467 | } |
| 473 | 468 | } |
| r20956 | r20957 | |
| 488 | 483 | 4020h STOP Stop processing the sound list. |
| 489 | 484 | */ |
| 490 | 485 | |
| 491 | | static void amstrad_plus_dma_parse(running_machine &machine, int channel) |
| 486 | void amstrad_state::amstrad_plus_dma_parse(int channel) |
| 492 | 487 | { |
| 493 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 494 | 488 | unsigned short command; |
| 495 | 489 | |
| 496 | | if( state->m_asic.dma_addr[channel] & 0x01) |
| 497 | | state->m_asic.dma_addr[channel]++; // align to even address |
| 490 | if( m_asic.dma_addr[channel] & 0x01) |
| 491 | m_asic.dma_addr[channel]++; // align to even address |
| 498 | 492 | |
| 499 | | if ( state->m_asic.dma_pause[channel] != 0 ) |
| 493 | if ( m_asic.dma_pause[channel] != 0 ) |
| 500 | 494 | { // do nothing, this channel is paused |
| 501 | | state->m_asic.dma_prescaler[channel]--; |
| 502 | | if ( state->m_asic.dma_prescaler[channel] == 0 ) |
| 495 | m_asic.dma_prescaler[channel]--; |
| 496 | if ( m_asic.dma_prescaler[channel] == 0 ) |
| 503 | 497 | { |
| 504 | | state->m_asic.dma_pause[channel]--; |
| 505 | | state->m_asic.dma_prescaler[channel] = state->m_asic.ram[0x2c02 + (4*channel)] + 1; |
| 498 | m_asic.dma_pause[channel]--; |
| 499 | m_asic.dma_prescaler[channel] = m_asic.ram[0x2c02 + (4*channel)] + 1; |
| 506 | 500 | } |
| 507 | 501 | return; |
| 508 | 502 | } |
| 509 | | command = (state->m_ram->pointer()[state->m_asic.dma_addr[channel]+1] << 8) + state->m_ram->pointer()[state->m_asic.dma_addr[channel]]; |
| 510 | | // logerror("DMA #%i: address %04x: command %04x\n",channel,state->m_asic.dma_addr[channel],command); |
| 503 | command = (m_ram->pointer()[m_asic.dma_addr[channel]+1] << 8) + m_ram->pointer()[m_asic.dma_addr[channel]]; |
| 504 | // logerror("DMA #%i: address %04x: command %04x\n",channel,m_asic.dma_addr[channel],command); |
| 511 | 505 | switch (command & 0xf000) |
| 512 | 506 | { |
| 513 | 507 | case 0x0000: // Load PSG register |
| 514 | 508 | { |
| 515 | | device_t *ay8910 = state->m_ay; |
| 516 | | ay8910_address_w(ay8910, state->generic_space(), 0, (command & 0x0f00) >> 8); |
| 517 | | ay8910_data_w(ay8910, state->generic_space(), 0, command & 0x00ff); |
| 518 | | ay8910_address_w(ay8910, state->generic_space(), 0, state->m_prev_reg); |
| 509 | ay8910_address_w(m_ay, generic_space(), 0, (command & 0x0f00) >> 8); |
| 510 | ay8910_data_w(m_ay, generic_space(), 0, command & 0x00ff); |
| 511 | ay8910_address_w(m_ay, generic_space(), 0, m_prev_reg); |
| 519 | 512 | } |
| 520 | 513 | logerror("DMA %i: LOAD %i, %i\n",channel,(command & 0x0f00) >> 8, command & 0x00ff); |
| 521 | 514 | break; |
| 522 | 515 | case 0x1000: // Pause for n HSYNCs (0 - 4095) |
| 523 | | state->m_asic.dma_pause[channel] = (command & 0x0fff) - 1; |
| 516 | m_asic.dma_pause[channel] = (command & 0x0fff) - 1; |
| 524 | 517 | logerror("DMA %i: PAUSE %i\n",channel,command & 0x0fff); |
| 525 | 518 | break; |
| 526 | 519 | case 0x2000: // Beginning of repeat loop |
| 527 | | state->m_asic.dma_repeat[channel] = state->m_asic.dma_addr[channel]; |
| 528 | | state->m_asic.dma_loopcount[channel] = (command & 0x0fff); |
| 520 | m_asic.dma_repeat[channel] = m_asic.dma_addr[channel]; |
| 521 | m_asic.dma_loopcount[channel] = (command & 0x0fff); |
| 529 | 522 | logerror("DMA %i: REPEAT %i\n",channel,command & 0x0fff); |
| 530 | 523 | break; |
| 531 | 524 | case 0x4000: // Control functions |
| 532 | 525 | if (command & 0x01) // Loop back to last Repeat instruction |
| 533 | 526 | { |
| 534 | | if (state->m_asic.dma_loopcount[channel] > 0) |
| 527 | if (m_asic.dma_loopcount[channel] > 0) |
| 535 | 528 | { |
| 536 | | state->m_asic.dma_addr[channel] = state->m_asic.dma_repeat[channel]; |
| 537 | | logerror("DMA %i: LOOP (%i left)\n",channel,state->m_asic.dma_loopcount[channel]); |
| 538 | | state->m_asic.dma_loopcount[channel]--; |
| 529 | m_asic.dma_addr[channel] = m_asic.dma_repeat[channel]; |
| 530 | logerror("DMA %i: LOOP (%i left)\n",channel,m_asic.dma_loopcount[channel]); |
| 531 | m_asic.dma_loopcount[channel]--; |
| 539 | 532 | } |
| 540 | 533 | else |
| 541 | 534 | logerror("DMA %i: LOOP (end)\n",channel); |
| 542 | 535 | } |
| 543 | 536 | if (command & 0x10) // Cause interrupt |
| 544 | 537 | { |
| 545 | | state->m_plus_irq_cause = channel * 2; |
| 546 | | state->m_asic.ram[0x2c0f] |= (0x40 >> channel); |
| 547 | | machine.device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 538 | m_plus_irq_cause = channel * 2; |
| 539 | m_asic.ram[0x2c0f] |= (0x40 >> channel); |
| 540 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 548 | 541 | logerror("DMA %i: INT\n",channel); |
| 549 | 542 | } |
| 550 | 543 | if (command & 0x20) // Stop processing on this channel |
| 551 | 544 | { |
| 552 | | state->m_asic.dma_status &= ~(0x01 << channel); |
| 545 | m_asic.dma_status &= ~(0x01 << channel); |
| 553 | 546 | logerror("DMA %i: STOP\n",channel); |
| 554 | 547 | } |
| 555 | 548 | break; |
| 556 | 549 | default: |
| 557 | | logerror("DMA: Unknown DMA command - %04x - at address &%04x\n",command,state->m_asic.dma_addr[channel]); |
| 550 | logerror("DMA: Unknown DMA command - %04x - at address &%04x\n",command,m_asic.dma_addr[channel]); |
| 558 | 551 | } |
| 559 | | state->m_asic.dma_addr[channel] += 2; // point to next DMA instruction |
| 552 | m_asic.dma_addr[channel] += 2; // point to next DMA instruction |
| 560 | 553 | } |
| 561 | 554 | |
| 562 | 555 | |
| 563 | | static void amstrad_plus_handle_dma(running_machine &machine) |
| 556 | void amstrad_state::amstrad_plus_handle_dma() |
| 564 | 557 | { |
| 565 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 566 | | if ( state->m_asic.dma_status & 0x01 ) // DMA channel 0 |
| 567 | | amstrad_plus_dma_parse( machine, 0 ); |
| 558 | if ( m_asic.dma_status & 0x01 ) // DMA channel 0 |
| 559 | { |
| 560 | amstrad_plus_dma_parse( 0 ); |
| 561 | } |
| 568 | 562 | |
| 569 | | if ( state->m_asic.dma_status & 0x02 ) // DMA channel 1 |
| 570 | | amstrad_plus_dma_parse( machine, 1 ); |
| 563 | if ( m_asic.dma_status & 0x02 ) // DMA channel 1 |
| 564 | { |
| 565 | amstrad_plus_dma_parse( 1 ); |
| 566 | } |
| 571 | 567 | |
| 572 | | if ( state->m_asic.dma_status & 0x04 ) // DMA channel 2 |
| 573 | | amstrad_plus_dma_parse( machine, 2 ); |
| 568 | if ( m_asic.dma_status & 0x04 ) // DMA channel 2 |
| 569 | { |
| 570 | amstrad_plus_dma_parse( 2 ); |
| 571 | } |
| 574 | 572 | } |
| 575 | 573 | |
| 576 | 574 | TIMER_CALLBACK_MEMBER(amstrad_state::amstrad_video_update_timer) |
| 577 | 575 | { |
| 578 | 576 | if(param == 1) |
| 579 | | amstrad_plus_update_video(machine()); |
| 577 | { |
| 578 | amstrad_plus_update_video(); |
| 579 | } |
| 580 | 580 | else |
| 581 | | amstrad_update_video(machine()); |
| 581 | { |
| 582 | amstrad_update_video(); |
| 583 | } |
| 582 | 584 | } |
| 583 | 585 | |
| 584 | 586 | /* Set the new colour from the GateArray */ |
| 585 | | static void amstrad_vh_update_colour(running_machine &machine, int PenIndex, UINT16 hw_colour_index) |
| 587 | void amstrad_state::amstrad_vh_update_colour(int PenIndex, UINT16 hw_colour_index) |
| 586 | 588 | { |
| 587 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 588 | | if ( state->m_system_type == SYSTEM_PLUS || state->m_system_type == SYSTEM_GX4000 ) |
| 589 | if ( m_system_type == SYSTEM_PLUS || m_system_type == SYSTEM_GX4000 ) |
| 589 | 590 | { |
| 590 | 591 | int val; |
| 591 | 592 | |
| 592 | | machine.scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),state),1); |
| 593 | machine().scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),this),1); |
| 593 | 594 | |
| 594 | 595 | /* CPC+/GX4000 - normal palette changes through the Gate Array also makes the corresponding change in the ASIC palette */ |
| 595 | 596 | val = (amstrad_palette[hw_colour_index] & 0xf00000) >> 16; /* red */ |
| 596 | 597 | val |= (amstrad_palette[hw_colour_index] & 0x0000f0) >> 4; /* blue */ |
| 597 | | state->m_asic.ram[0x2400+PenIndex*2] = val; |
| 598 | m_asic.ram[0x2400+PenIndex*2] = val; |
| 598 | 599 | val = (amstrad_palette[hw_colour_index] & 0x00f000) >> 12; /* green */ |
| 599 | | state->m_asic.ram[0x2401+PenIndex*2] = val; |
| 600 | m_asic.ram[0x2401+PenIndex*2] = val; |
| 600 | 601 | } |
| 601 | 602 | else |
| 602 | 603 | { |
| 603 | | machine.scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),state),0); |
| 604 | machine().scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),this),0); |
| 604 | 605 | } |
| 605 | | state->m_GateArray_render_colours[PenIndex] = hw_colour_index; |
| 606 | m_GateArray_render_colours[PenIndex] = hw_colour_index; |
| 606 | 607 | } |
| 607 | 608 | |
| 608 | 609 | |
| 609 | | static void aleste_vh_update_colour(running_machine &machine, int PenIndex, UINT16 hw_colour_index) |
| 610 | void amstrad_state::aleste_vh_update_colour(int PenIndex, UINT16 hw_colour_index) |
| 610 | 611 | { |
| 611 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 612 | | machine.scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),state),0); |
| 613 | | state->m_GateArray_render_colours[PenIndex] = hw_colour_index+32; |
| 612 | machine().scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),this),0); |
| 613 | m_GateArray_render_colours[PenIndex] = hw_colour_index+32; |
| 614 | 614 | } |
| 615 | 615 | |
| 616 | 616 | |
| 617 | | INLINE void amstrad_gate_array_get_video_data( running_machine &machine ) |
| 617 | void amstrad_state::amstrad_gate_array_get_video_data() |
| 618 | 618 | { |
| 619 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 620 | | if ( state->m_aleste_mode & 0x02 ) |
| 621 | | state->m_gate_array.address = ( ( state->m_gate_array.ma & 0x2000 ) << 2 ) | ( ( state->m_gate_array.ra & 0x06 ) << 11 ) | ( ( state->m_gate_array.ra & 0x01 ) << 14 ) | ( ( state->m_gate_array.ma & 0x7ff ) << 1 ); |
| 619 | if ( m_aleste_mode & 0x02 ) |
| 620 | { |
| 621 | m_gate_array.address = ( ( m_gate_array.ma & 0x2000 ) << 2 ) | ( ( m_gate_array.ra & 0x06 ) << 11 ) | ( ( m_gate_array.ra & 0x01 ) << 14 ) | ( ( m_gate_array.ma & 0x7ff ) << 1 ); |
| 622 | } |
| 622 | 623 | else |
| 623 | | state->m_gate_array.address = ( ( state->m_gate_array.ma & 0x3000 ) << 2 ) | ( ( state->m_gate_array.ra & 0x07 ) << 11 ) | ( ( state->m_gate_array.ma & 0x3ff ) << 1 ); |
| 624 | | state->m_gate_array.data = state->m_ram->pointer()[ state->m_gate_array.address ]; |
| 625 | | state->m_gate_array.colour = state->m_GateArray_render_colours[ state->m_gate_array.mode_lookup[state->m_gate_array.data] ]; |
| 626 | | state->m_gate_array.colour_ticks = state->m_gate_array.max_colour_ticks; |
| 627 | | state->m_gate_array.ticks = 0; |
| 624 | { |
| 625 | m_gate_array.address = ( ( m_gate_array.ma & 0x3000 ) << 2 ) | ( ( m_gate_array.ra & 0x07 ) << 11 ) | ( ( m_gate_array.ma & 0x3ff ) << 1 ); |
| 626 | } |
| 627 | m_gate_array.data = m_ram->pointer()[ m_gate_array.address ]; |
| 628 | m_gate_array.colour = m_GateArray_render_colours[ m_gate_array.mode_lookup[m_gate_array.data] ]; |
| 629 | m_gate_array.colour_ticks = m_gate_array.max_colour_ticks; |
| 630 | m_gate_array.ticks = 0; |
| 628 | 631 | } |
| 629 | 632 | |
| 630 | 633 | |
| 631 | | INLINE void amstrad_update_video( running_machine &machine ) |
| 634 | void amstrad_state::amstrad_update_video() |
| 632 | 635 | { |
| 633 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 634 | | attotime now = machine.time(); |
| 636 | attotime now = machine().time(); |
| 635 | 637 | |
| 636 | 638 | |
| 637 | | if ( state->m_gate_array.draw_p ) |
| 639 | if ( m_gate_array.draw_p ) |
| 638 | 640 | { |
| 639 | | UINT32 cycles_passed = (now - state->m_gate_array.last_draw_time ).as_ticks(XTAL_16MHz); |
| 641 | UINT32 cycles_passed = (now - m_gate_array.last_draw_time ).as_ticks(XTAL_16MHz); |
| 640 | 642 | |
| 641 | 643 | while( cycles_passed ) |
| 642 | 644 | { |
| 643 | | if ( ! state->m_gate_array.de || ( ( state->m_aleste_mode & 0x02 ) && ! ( state->m_aleste_mode & 0x08 ) ) ) |
| 645 | if ( ! m_gate_array.de || ( ( m_aleste_mode & 0x02 ) && ! ( m_aleste_mode & 0x08 ) ) ) |
| 644 | 646 | { |
| 645 | | *state->m_gate_array.draw_p = state->m_GateArray_render_colours[ 16 ]; |
| 647 | *m_gate_array.draw_p = m_GateArray_render_colours[ 16 ]; |
| 646 | 648 | } |
| 647 | 649 | else |
| 648 | 650 | { |
| 649 | | *state->m_gate_array.draw_p = state->m_gate_array.colour; |
| 650 | | state->m_gate_array.colour_ticks--; |
| 651 | | if ( ! state->m_gate_array.colour_ticks ) |
| 651 | *m_gate_array.draw_p = m_gate_array.colour; |
| 652 | m_gate_array.colour_ticks--; |
| 653 | if ( ! m_gate_array.colour_ticks ) |
| 652 | 654 | { |
| 653 | | state->m_gate_array.data <<= 1; |
| 654 | | state->m_gate_array.colour = state->m_GateArray_render_colours[ state->m_gate_array.mode_lookup[state->m_gate_array.data] ]; |
| 655 | | state->m_gate_array.colour_ticks = state->m_gate_array.max_colour_ticks; |
| 655 | m_gate_array.data <<= 1; |
| 656 | m_gate_array.colour = m_GateArray_render_colours[ m_gate_array.mode_lookup[m_gate_array.data] ]; |
| 657 | m_gate_array.colour_ticks = m_gate_array.max_colour_ticks; |
| 656 | 658 | } |
| 657 | | state->m_gate_array.ticks += state->m_gate_array.ticks_increment; |
| 658 | | switch( state->m_gate_array.ticks) |
| 659 | m_gate_array.ticks += m_gate_array.ticks_increment; |
| 660 | switch( m_gate_array.ticks) |
| 659 | 661 | { |
| 660 | 662 | case 8: |
| 661 | | state->m_gate_array.data = state->m_ram->pointer()[ state->m_gate_array.address + 1 ]; |
| 662 | | state->m_gate_array.colour = state->m_GateArray_render_colours[ state->m_gate_array.mode_lookup[state->m_gate_array.data] ]; |
| 663 | m_gate_array.data = m_ram->pointer()[ m_gate_array.address + 1 ]; |
| 664 | m_gate_array.colour = m_GateArray_render_colours[ m_gate_array.mode_lookup[m_gate_array.data] ]; |
| 663 | 665 | break; |
| 664 | 666 | case 16: |
| 665 | | state->m_gate_array.ma += 1; /* If we were synced with the 6845 mc6845_get_ma should return this value */ |
| 666 | | amstrad_gate_array_get_video_data( machine ); |
| 667 | m_gate_array.ma += 1; /* If we were synced with the 6845 mc6845_get_ma should return this value */ |
| 668 | amstrad_gate_array_get_video_data(); |
| 667 | 669 | break; |
| 668 | 670 | } |
| 669 | 671 | } |
| 670 | | state->m_gate_array.draw_p++; |
| 672 | m_gate_array.draw_p++; |
| 671 | 673 | cycles_passed--; |
| 672 | | state->m_gate_array.line_ticks++; |
| 673 | | if ( state->m_gate_array.line_ticks > state->m_gate_array.bitmap->width() ) |
| 674 | m_gate_array.line_ticks++; |
| 675 | if ( m_gate_array.line_ticks > m_gate_array.bitmap->width() ) |
| 674 | 676 | { |
| 675 | | state->m_gate_array.draw_p = NULL; |
| 677 | m_gate_array.draw_p = NULL; |
| 676 | 678 | cycles_passed = 0; |
| 677 | 679 | } |
| 678 | 680 | } |
| 679 | 681 | } |
| 680 | 682 | |
| 681 | | state->m_gate_array.last_draw_time = now; |
| 683 | m_gate_array.last_draw_time = now; |
| 682 | 684 | } |
| 683 | 685 | |
| 684 | 686 | |
| 685 | | INLINE void amstrad_plus_gate_array_get_video_data( running_machine &machine ) |
| 687 | void amstrad_state::amstrad_plus_gate_array_get_video_data() |
| 686 | 688 | { |
| 687 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 688 | 689 | UINT16 caddr; |
| 689 | | UINT16 ma = ( state->m_gate_array.ma - state->m_asic.split_ma_started ) + state->m_asic.split_ma_base; |
| 690 | | UINT16 ra = state->m_gate_array.ra + ( ( state->m_asic.ram[0x2804] >> 4 ) & 0x07 ); |
| 690 | UINT16 ma = ( m_gate_array.ma - m_asic.split_ma_started ) + m_asic.split_ma_base; |
| 691 | UINT16 ra = m_gate_array.ra + ( ( m_asic.ram[0x2804] >> 4 ) & 0x07 ); |
| 691 | 692 | |
| 692 | 693 | if ( ra > 7 ) |
| 693 | 694 | { |
| 694 | | ma += state->m_asic.horiz_disp; |
| 695 | ma += m_asic.horiz_disp; |
| 695 | 696 | } |
| 696 | | state->m_gate_array.address = ( ( ma & 0x3000 ) << 2 ) | ( ( state->m_gate_array.ra & 0x07 ) << 11 ) | ( ( ma & 0x3ff ) << 1 ); |
| 697 | | state->m_gate_array.data = state->m_ram->pointer()[ state->m_gate_array.address ]; |
| 698 | | caddr = 0x2400 + state->m_gate_array.mode_lookup[state->m_gate_array.data] * 2; |
| 699 | | state->m_gate_array.colour = state->m_asic.ram[caddr] + ( state->m_asic.ram[caddr+1] << 8 ); |
| 700 | | state->m_gate_array.colour_ticks = state->m_gate_array.max_colour_ticks; |
| 701 | | state->m_gate_array.ticks = 0; |
| 697 | m_gate_array.address = ( ( ma & 0x3000 ) << 2 ) | ( ( m_gate_array.ra & 0x07 ) << 11 ) | ( ( ma & 0x3ff ) << 1 ); |
| 698 | m_gate_array.data = m_ram->pointer()[ m_gate_array.address ]; |
| 699 | caddr = 0x2400 + m_gate_array.mode_lookup[m_gate_array.data] * 2; |
| 700 | m_gate_array.colour = m_asic.ram[caddr] + ( m_asic.ram[caddr+1] << 8 ); |
| 701 | m_gate_array.colour_ticks = m_gate_array.max_colour_ticks; |
| 702 | m_gate_array.ticks = 0; |
| 702 | 703 | } |
| 703 | 704 | |
| 704 | 705 | |
| 705 | | INLINE void amstrad_plus_update_video( running_machine &machine ) |
| 706 | void amstrad_state::amstrad_plus_update_video() |
| 706 | 707 | { |
| 707 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 708 | | attotime now = machine.time(); |
| 708 | attotime now = machine().time(); |
| 709 | 709 | |
| 710 | | if ( state->m_gate_array.draw_p ) |
| 710 | if ( m_gate_array.draw_p ) |
| 711 | 711 | { |
| 712 | | UINT32 cycles_passed = (now - state->m_gate_array.last_draw_time ).as_ticks(XTAL_16MHz); |
| 712 | UINT32 cycles_passed = (now - m_gate_array.last_draw_time ).as_ticks(XTAL_16MHz); |
| 713 | 713 | |
| 714 | 714 | while( cycles_passed ) |
| 715 | 715 | { |
| 716 | | if ( ! state->m_gate_array.de ) |
| 716 | if ( ! m_gate_array.de ) |
| 717 | 717 | { |
| 718 | | *state->m_gate_array.draw_p = state->m_asic.ram[0x2420] + ( state->m_asic.ram[0x2421] << 8 ); |
| 718 | *m_gate_array.draw_p = m_asic.ram[0x2420] + ( m_asic.ram[0x2421] << 8 ); |
| 719 | 719 | } |
| 720 | 720 | else |
| 721 | 721 | { |
| 722 | | *state->m_gate_array.draw_p = state->m_gate_array.colour; |
| 722 | *m_gate_array.draw_p = m_gate_array.colour; |
| 723 | 723 | |
| 724 | | if ( state->m_asic.hscroll ) |
| 724 | if ( m_asic.hscroll ) |
| 725 | 725 | { |
| 726 | | state->m_asic.hscroll--; |
| 727 | | if ( state->m_asic.hscroll == 0 ) |
| 728 | | amstrad_plus_gate_array_get_video_data( machine ); |
| 726 | m_asic.hscroll--; |
| 727 | if ( m_asic.hscroll == 0 ) |
| 728 | amstrad_plus_gate_array_get_video_data(); |
| 729 | 729 | } |
| 730 | 730 | else |
| 731 | 731 | { |
| 732 | | state->m_gate_array.colour_ticks--; |
| 733 | | if ( ! state->m_gate_array.colour_ticks ) |
| 732 | m_gate_array.colour_ticks--; |
| 733 | if ( ! m_gate_array.colour_ticks ) |
| 734 | 734 | { |
| 735 | 735 | UINT16 caddr; |
| 736 | 736 | |
| 737 | | state->m_gate_array.data <<= 1; |
| 738 | | caddr = 0x2400 + state->m_gate_array.mode_lookup[state->m_gate_array.data] * 2; |
| 739 | | state->m_gate_array.colour = state->m_asic.ram[caddr] + ( state->m_asic.ram[caddr+1] << 8 ); |
| 740 | | state->m_gate_array.colour_ticks = state->m_gate_array.max_colour_ticks; |
| 737 | m_gate_array.data <<= 1; |
| 738 | caddr = 0x2400 + m_gate_array.mode_lookup[m_gate_array.data] * 2; |
| 739 | m_gate_array.colour = m_asic.ram[caddr] + ( m_asic.ram[caddr+1] << 8 ); |
| 740 | m_gate_array.colour_ticks = m_gate_array.max_colour_ticks; |
| 741 | 741 | } |
| 742 | | state->m_gate_array.ticks += state->m_gate_array.ticks_increment; |
| 743 | | switch( state->m_gate_array.ticks) |
| 742 | m_gate_array.ticks += m_gate_array.ticks_increment; |
| 743 | switch( m_gate_array.ticks) |
| 744 | 744 | { |
| 745 | 745 | case 8: |
| 746 | 746 | { |
| 747 | 747 | UINT16 caddr; |
| 748 | 748 | |
| 749 | | state->m_gate_array.data = state->m_ram->pointer()[ state->m_gate_array.address + 1 ]; |
| 750 | | caddr = 0x2400 + state->m_gate_array.mode_lookup[state->m_gate_array.data] * 2; |
| 751 | | state->m_gate_array.colour = state->m_asic.ram[caddr] + ( state->m_asic.ram[caddr+1] << 8 ); |
| 749 | m_gate_array.data = m_ram->pointer()[ m_gate_array.address + 1 ]; |
| 750 | caddr = 0x2400 + m_gate_array.mode_lookup[m_gate_array.data] * 2; |
| 751 | m_gate_array.colour = m_asic.ram[caddr] + ( m_asic.ram[caddr+1] << 8 ); |
| 752 | 752 | } |
| 753 | 753 | break; |
| 754 | 754 | case 16: |
| 755 | | state->m_gate_array.ma += 1; /* If we were synced with the 6845 mc6845_get_ma should return this value */ |
| 756 | | amstrad_plus_gate_array_get_video_data( machine ); |
| 755 | m_gate_array.ma += 1; /* If we were synced with the 6845 mc6845_get_ma should return this value */ |
| 756 | amstrad_plus_gate_array_get_video_data(); |
| 757 | 757 | break; |
| 758 | 758 | } |
| 759 | 759 | } |
| 760 | 760 | } |
| 761 | | state->m_gate_array.draw_p++; |
| 761 | m_gate_array.draw_p++; |
| 762 | 762 | cycles_passed--; |
| 763 | | state->m_gate_array.line_ticks++; |
| 764 | | if ( state->m_gate_array.line_ticks > state->m_gate_array.bitmap->width() ) |
| 763 | m_gate_array.line_ticks++; |
| 764 | if ( m_gate_array.line_ticks > m_gate_array.bitmap->width() ) |
| 765 | 765 | { |
| 766 | | state->m_gate_array.draw_p = NULL; |
| 766 | m_gate_array.draw_p = NULL; |
| 767 | 767 | cycles_passed = 0; |
| 768 | 768 | } |
| 769 | 769 | } |
| 770 | 770 | } |
| 771 | 771 | |
| 772 | | state->m_gate_array.last_draw_time = now; |
| 772 | m_gate_array.last_draw_time = now; |
| 773 | 773 | } |
| 774 | 774 | |
| 775 | 775 | |
| 776 | | INLINE void amstrad_plus_update_video_sprites( running_machine &machine ) |
| 776 | void amstrad_state::amstrad_plus_update_video_sprites() |
| 777 | 777 | { |
| 778 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 779 | | UINT16 *p = &state->m_gate_array.bitmap->pix16(state->m_gate_array.y, state->m_asic.h_start ); |
| 778 | UINT16 *p = &m_gate_array.bitmap->pix16(m_gate_array.y, m_asic.h_start ); |
| 780 | 779 | int i; |
| 781 | 780 | |
| 782 | | if ( state->m_gate_array.y < 0 ) |
| 781 | if ( m_gate_array.y < 0 ) |
| 783 | 782 | return; |
| 784 | 783 | |
| 785 | 784 | for ( i = 15 * 8; i >= 0; i -= 8 ) |
| 786 | 785 | { |
| 787 | | UINT8 xmag = ( state->m_asic.ram[ 0x2000 + i + 4 ] >> 2 ) & 0x03; |
| 788 | | UINT8 ymag = state->m_asic.ram[ 0x2000 + i + 4 ] & 0x03; |
| 786 | UINT8 xmag = ( m_asic.ram[ 0x2000 + i + 4 ] >> 2 ) & 0x03; |
| 787 | UINT8 ymag = m_asic.ram[ 0x2000 + i + 4 ] & 0x03; |
| 789 | 788 | |
| 790 | 789 | /* Check if sprite is enabled */ |
| 791 | 790 | if ( xmag && ymag ) |
| 792 | 791 | { |
| 793 | | INT16 spr_x = state->m_asic.ram[ 0x2000 + i ] + ( state->m_asic.ram[ 0x2001 + i ] << 8 ); |
| 794 | | INT16 spr_y = state->m_asic.ram[ 0x2002 + i ] + ( state->m_asic.ram[ 0x2003 + i ] << 8 ); |
| 792 | INT16 spr_x = m_asic.ram[ 0x2000 + i ] + ( m_asic.ram[ 0x2001 + i ] << 8 ); |
| 793 | INT16 spr_y = m_asic.ram[ 0x2002 + i ] + ( m_asic.ram[ 0x2003 + i ] << 8 ); |
| 795 | 794 | |
| 796 | 795 | xmag -= 1; |
| 797 | 796 | ymag -= 1; |
| 798 | 797 | |
| 799 | 798 | /* Check if sprite would appear on this scanline */ |
| 800 | | if ( spr_y <= state->m_asic.vpos && state->m_asic.vpos < spr_y + ( 16 << ymag ) && spr_x < ( state->m_asic.h_end - state->m_asic.h_start ) && spr_x + ( 16 << xmag ) > 0 ) |
| 799 | if ( spr_y <= m_asic.vpos && m_asic.vpos < spr_y + ( 16 << ymag ) && spr_x < ( m_asic.h_end - m_asic.h_start ) && spr_x + ( 16 << xmag ) > 0 ) |
| 801 | 800 | { |
| 802 | | UINT16 spr_addr = i * 32 + ( ( ( state->m_asic.vpos - spr_y ) >> ymag ) * 16 ); |
| 801 | UINT16 spr_addr = i * 32 + ( ( ( m_asic.vpos - spr_y ) >> ymag ) * 16 ); |
| 803 | 802 | int j, k; |
| 804 | 803 | |
| 805 | 804 | for ( j = 0; j < 16; j++ ) |
| r20956 | r20957 | |
| 808 | 807 | { |
| 809 | 808 | INT16 x = spr_x + ( j << xmag ) + k; |
| 810 | 809 | |
| 811 | | if ( x >= 0 && x < ( state->m_asic.h_end - state->m_asic.h_start ) ) |
| 810 | if ( x >= 0 && x < ( m_asic.h_end - m_asic.h_start ) ) |
| 812 | 811 | { |
| 813 | | UINT8 spr_col = ( state->m_asic.ram[ spr_addr + j ] & 0x0f ) * 2; |
| 812 | UINT8 spr_col = ( m_asic.ram[ spr_addr + j ] & 0x0f ) * 2; |
| 814 | 813 | |
| 815 | 814 | if ( spr_col ) |
| 816 | | p[x] = state->m_asic.ram[ 0x2420 + spr_col ] + ( state->m_asic.ram[ 0x2421 + spr_col ] << 8 ); |
| 815 | p[x] = m_asic.ram[ 0x2420 + spr_col ] + ( m_asic.ram[ 0x2421 + spr_col ] << 8 ); |
| 817 | 816 | } |
| 818 | 817 | } |
| 819 | 818 | } |
| r20956 | r20957 | |
| 825 | 824 | |
| 826 | 825 | WRITE_LINE_MEMBER(amstrad_state::amstrad_hsync_changed) |
| 827 | 826 | { |
| 828 | | amstrad_update_video(machine()); |
| 827 | amstrad_update_video(); |
| 829 | 828 | |
| 830 | 829 | /* The gate array reacts to de-assertion of the hsycnc 6845 line */ |
| 831 | 830 | if ( m_gate_array.hsync && !state ) |
| r20956 | r20957 | |
| 851 | 850 | { |
| 852 | 851 | if (m_gate_array.hsync_counter >= 32) |
| 853 | 852 | { |
| 854 | | machine().device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 853 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 855 | 854 | } |
| 856 | 855 | m_gate_array.hsync_counter = 0; |
| 857 | 856 | } |
| r20956 | r20957 | |
| 860 | 859 | if ( m_gate_array.hsync_counter >= 52 ) |
| 861 | 860 | { |
| 862 | 861 | m_gate_array.hsync_counter = 0; |
| 863 | | machine().device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 862 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 864 | 863 | } |
| 865 | 864 | } |
| 866 | 865 | m_gate_array.hsync = state ? 1 : 0; |
| r20956 | r20957 | |
| 869 | 868 | |
| 870 | 869 | WRITE_LINE_MEMBER(amstrad_state::amstrad_plus_hsync_changed) |
| 871 | 870 | { |
| 872 | | amstrad_plus_update_video(machine()); |
| 871 | amstrad_plus_update_video(); |
| 873 | 872 | |
| 874 | 873 | if ( m_gate_array.hsync && !state ) |
| 875 | 874 | { |
| r20956 | r20957 | |
| 896 | 895 | { |
| 897 | 896 | if( m_asic.pri == 0 || m_asic.enabled == 0) |
| 898 | 897 | { |
| 899 | | machine().device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 898 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 900 | 899 | } |
| 901 | 900 | } |
| 902 | 901 | m_gate_array.hsync_counter = 0; |
| r20956 | r20957 | |
| 908 | 907 | m_gate_array.hsync_counter = 0; |
| 909 | 908 | if ( m_asic.pri == 0 || m_asic.enabled == 0 ) |
| 910 | 909 | { |
| 911 | | machine().device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 910 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 912 | 911 | } |
| 913 | 912 | } |
| 914 | 913 | |
| r20956 | r20957 | |
| 920 | 919 | if ( m_asic.pri == m_asic.vpos - 1 ) |
| 921 | 920 | { |
| 922 | 921 | logerror("PRI: triggered, scanline %d\n",m_asic.pri); |
| 923 | | machine().device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 922 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 924 | 923 | m_plus_irq_cause = 0x06; // raster interrupt vector |
| 925 | 924 | m_gate_array.hsync_counter &= ~0x20; // ASIC PRI resets the MSB of the raster counter |
| 926 | 925 | } |
| r20956 | r20957 | |
| 934 | 933 | } |
| 935 | 934 | } |
| 936 | 935 | // CPC+/GX4000 DMA channels |
| 937 | | amstrad_plus_handle_dma(machine()); // a DMA command is handled at the leading edge of HSYNC (every 64us) |
| 936 | amstrad_plus_handle_dma(); // a DMA command is handled at the leading edge of HSYNC (every 64us) |
| 938 | 937 | if(m_asic.de_start != 0) |
| 939 | 938 | m_asic.vpos++; |
| 940 | 939 | } |
| r20956 | r20957 | |
| 945 | 944 | |
| 946 | 945 | WRITE_LINE_MEMBER(amstrad_state::amstrad_vsync_changed) |
| 947 | 946 | { |
| 948 | | amstrad_update_video(machine()); |
| 947 | amstrad_update_video(); |
| 949 | 948 | |
| 950 | 949 | if ( ! m_gate_array.vsync && state ) |
| 951 | 950 | { |
| r20956 | r20957 | |
| 967 | 966 | |
| 968 | 967 | WRITE_LINE_MEMBER(amstrad_state::amstrad_plus_vsync_changed) |
| 969 | 968 | { |
| 970 | | amstrad_plus_update_video(machine()); |
| 969 | amstrad_plus_update_video(); |
| 971 | 970 | |
| 972 | 971 | if ( ! m_gate_array.vsync && state ) |
| 973 | 972 | { |
| r20956 | r20957 | |
| 989 | 988 | |
| 990 | 989 | WRITE_LINE_MEMBER(amstrad_state::amstrad_de_changed) |
| 991 | 990 | { |
| 992 | | amstrad_update_video(machine()); |
| 991 | amstrad_update_video(); |
| 993 | 992 | |
| 994 | 993 | if ( ! m_gate_array.de && state ) |
| 995 | 994 | { |
| r20956 | r20957 | |
| 999 | 998 | m_gate_array.ma = mc6845->get_ma(); |
| 1000 | 999 | m_gate_array.ra = mc6845->get_ra(); |
| 1001 | 1000 | logerror("y = %d; ma = %02x; ra = %02x, address = %04x\n", m_gate_array.y, m_gate_array.ma, m_gate_array.ra, ( ( m_gate_array.ma & 0x3000 ) << 2 ) | ( ( m_gate_array.ra & 0x07 ) << 11 ) | ( ( m_gate_array.ma & 0x3ff ) << 1 ) ); |
| 1002 | | amstrad_gate_array_get_video_data(machine()); |
| 1001 | amstrad_gate_array_get_video_data(); |
| 1003 | 1002 | m_asic.de_start = 1; |
| 1004 | 1003 | } |
| 1005 | 1004 | |
| r20956 | r20957 | |
| 1009 | 1008 | |
| 1010 | 1009 | WRITE_LINE_MEMBER(amstrad_state::amstrad_plus_de_changed) |
| 1011 | 1010 | { |
| 1012 | | amstrad_plus_update_video(machine()); |
| 1011 | amstrad_plus_update_video(); |
| 1013 | 1012 | |
| 1014 | 1013 | if ( ! m_gate_array.de && state ) |
| 1015 | 1014 | { |
| 1016 | 1015 | /* DE became active, store the starting MA and RA signals */ |
| 1017 | | mc6845_device *mc6845 = m_crtc; |
| 1018 | | |
| 1019 | | m_gate_array.ma = mc6845->get_ma(); |
| 1020 | | m_gate_array.ra = mc6845->get_ra(); |
| 1016 | m_gate_array.ma = m_crtc->get_ma(); |
| 1017 | m_gate_array.ra = m_crtc->get_ra(); |
| 1021 | 1018 | m_asic.h_start = m_gate_array.line_ticks; |
| 1022 | 1019 | m_asic.de_start = 1; |
| 1023 | 1020 | |
| r20956 | r20957 | |
| 1038 | 1035 | m_asic.hscroll = m_asic.ram[0x2804] & 0x0f; |
| 1039 | 1036 | |
| 1040 | 1037 | if ( m_asic.hscroll == 0 ) |
| 1041 | | amstrad_plus_gate_array_get_video_data(machine()); |
| 1038 | amstrad_plus_gate_array_get_video_data(); |
| 1042 | 1039 | } |
| 1043 | 1040 | |
| 1044 | 1041 | if ( m_gate_array.de && ! state ) |
| 1045 | 1042 | { |
| 1046 | 1043 | m_asic.h_end = m_gate_array.line_ticks; |
| 1047 | | amstrad_plus_update_video_sprites(machine()); |
| 1044 | amstrad_plus_update_video_sprites(); |
| 1048 | 1045 | } |
| 1049 | 1046 | |
| 1050 | 1047 | m_gate_array.de = state ? 1 : 0; |
| r20956 | r20957 | |
| 1053 | 1050 | |
| 1054 | 1051 | VIDEO_START_MEMBER(amstrad_state,amstrad) |
| 1055 | 1052 | { |
| 1056 | | //screen_device *screen = downcast<screen_device *>(machine().device("screen")); |
| 1053 | amstrad_init_lookups(); |
| 1057 | 1054 | |
| 1058 | | amstrad_init_lookups(this); |
| 1059 | | |
| 1060 | 1055 | m_gate_array.bitmap = auto_bitmap_ind16_alloc( machine(), m_screen->width(), m_screen->height() ); |
| 1061 | 1056 | m_gate_array.hsync_after_vsync_counter = 3; |
| 1062 | 1057 | } |
| r20956 | r20957 | |
| 1141 | 1136 | amstrad_state *tstate = device->machine().driver_data<amstrad_state>(); |
| 1142 | 1137 | |
| 1143 | 1138 | tstate->m_gate_array.romdis = state; |
| 1144 | | amstrad_rethinkMemory(device->machine()); |
| 1139 | tstate->amstrad_rethinkMemory(); |
| 1145 | 1140 | } |
| 1146 | 1141 | |
| 1147 | 1142 | WRITE_LINE_DEVICE_HANDLER(cpc_romen) |
| r20956 | r20957 | |
| 1152 | 1147 | tstate->m_gate_array.mrer &= ~0x04; |
| 1153 | 1148 | else |
| 1154 | 1149 | tstate->m_gate_array.mrer |= 0x04; |
| 1155 | | amstrad_rethinkMemory(device->machine()); |
| 1150 | tstate->amstrad_rethinkMemory(); |
| 1156 | 1151 | } |
| 1157 | 1152 | |
| 1158 | 1153 | |
| r20956 | r20957 | |
| 1162 | 1157 | /*----------------- |
| 1163 | 1158 | - Set Lower Rom - |
| 1164 | 1159 | -----------------*/ |
| 1165 | | static void amstrad_setLowerRom(running_machine &machine) |
| 1160 | void amstrad_state::amstrad_setLowerRom() |
| 1166 | 1161 | { |
| 1167 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 1168 | 1162 | UINT8 *bank_base; |
| 1169 | 1163 | |
| 1170 | 1164 | /* b2 : "1" Lower rom area disable or "0" Lower rom area enable */ |
| 1171 | | if ( state->m_system_type == SYSTEM_CPC || state->m_system_type == SYSTEM_ALESTE ) |
| 1165 | if ( m_system_type == SYSTEM_CPC || m_system_type == SYSTEM_ALESTE ) |
| 1172 | 1166 | { |
| 1173 | | if ((state->m_gate_array.mrer & (1<<2)) == 0 && state->m_gate_array.romdis == 0) |
| 1167 | if ((m_gate_array.mrer & (1<<2)) == 0 && m_gate_array.romdis == 0) |
| 1174 | 1168 | { |
| 1175 | | bank_base = &state->memregion("maincpu")->base()[0x010000]; |
| 1169 | bank_base = &m_region_maincpu->base()[0x010000]; |
| 1176 | 1170 | } |
| 1177 | 1171 | else |
| 1178 | 1172 | { |
| 1179 | | if(state->m_aleste_mode & 0x04) |
| 1180 | | bank_base = state->m_Aleste_RamBanks[0]; |
| 1173 | if(m_aleste_mode & 0x04) |
| 1174 | bank_base = m_Aleste_RamBanks[0]; |
| 1181 | 1175 | else |
| 1182 | | bank_base = state->m_AmstradCPC_RamBanks[0]; |
| 1176 | bank_base = m_AmstradCPC_RamBanks[0]; |
| 1183 | 1177 | } |
| 1184 | | state->membank("bank1")->set_base(bank_base); |
| 1185 | | state->membank("bank2")->set_base(bank_base+0x02000); |
| 1178 | m_bank1->set_base(bank_base); |
| 1179 | m_bank2->set_base(bank_base+0x02000); |
| 1186 | 1180 | } |
| 1187 | 1181 | else // CPC+/GX4000 |
| 1188 | 1182 | { |
| 1189 | 1183 | //address_space &space = state->m_maincpu->space(AS_PROGRAM); |
| 1190 | 1184 | |
| 1191 | | /* if ( state->m_asic.enabled && ( state->m_asic.rmr2 & 0x18 ) == 0x18 ) |
| 1185 | /* if ( m_asic.enabled && ( m_asic.rmr2 & 0x18 ) == 0x18 ) |
| 1192 | 1186 | { |
| 1193 | | space.install_read_handler(0x4000, 0x5fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_4000_r),state)); |
| 1194 | | space.install_read_handler(0x6000, 0x7fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_6000_r),state)); |
| 1195 | | space.install_write_handler(0x4000, 0x5fff, write8_delegate(FUNC(amstrad_state::amstrad_plus_asic_4000_w),state)); |
| 1196 | | space.install_write_handler(0x6000, 0x7fff, write8_delegate(FUNC(amstrad_state::amstrad_plus_asic_6000_w),state)); |
| 1187 | space.install_read_handler(0x4000, 0x5fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_4000_r),this)); |
| 1188 | space.install_read_handler(0x6000, 0x7fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_6000_r),this)); |
| 1189 | space.install_write_handler(0x4000, 0x5fff, write8_delegate(FUNC(amstrad_state::amstrad_plus_asic_4000_w),this)); |
| 1190 | space.install_write_handler(0x6000, 0x7fff, write8_delegate(FUNC(amstrad_state::amstrad_plus_asic_6000_w),this)); |
| 1197 | 1191 | } |
| 1198 | 1192 | else |
| 1199 | 1193 | { |
| r20956 | r20957 | |
| 1203 | 1197 | space.install_write_bank(0x6000, 0x7fff, "bank12"); |
| 1204 | 1198 | } |
| 1205 | 1199 | */ |
| 1206 | | if(state->m_AmstradCPC_RamBanks[0] != NULL) |
| 1200 | if(m_AmstradCPC_RamBanks[0] != NULL) |
| 1207 | 1201 | { |
| 1208 | | state->membank("bank1")->set_base(state->m_AmstradCPC_RamBanks[0]); |
| 1209 | | state->membank("bank2")->set_base(state->m_AmstradCPC_RamBanks[0]+0x2000); |
| 1210 | | state->membank("bank3")->set_base(state->m_AmstradCPC_RamBanks[1]); |
| 1211 | | state->membank("bank4")->set_base(state->m_AmstradCPC_RamBanks[1]+0x2000); |
| 1212 | | state->membank("bank5")->set_base(state->m_AmstradCPC_RamBanks[2]); |
| 1213 | | state->membank("bank6")->set_base(state->m_AmstradCPC_RamBanks[2]+0x2000); |
| 1202 | m_bank1->set_base(m_AmstradCPC_RamBanks[0]); |
| 1203 | m_bank2->set_base(m_AmstradCPC_RamBanks[0]+0x2000); |
| 1204 | m_bank3->set_base(m_AmstradCPC_RamBanks[1]); |
| 1205 | m_bank4->set_base(m_AmstradCPC_RamBanks[1]+0x2000); |
| 1206 | m_bank5->set_base(m_AmstradCPC_RamBanks[2]); |
| 1207 | m_bank6->set_base(m_AmstradCPC_RamBanks[2]+0x2000); |
| 1214 | 1208 | } |
| 1215 | 1209 | |
| 1216 | | if ( (state->m_gate_array.mrer & (1<<2)) == 0 && state->m_gate_array.romdis == 0) |
| 1210 | if ( (m_gate_array.mrer & (1<<2)) == 0 && m_gate_array.romdis == 0) |
| 1217 | 1211 | { // ASIC secondary lower ROM selection (bit 5: 1 = enabled) |
| 1218 | | if ( state->m_asic.enabled ) |
| 1212 | if ( m_asic.enabled ) |
| 1219 | 1213 | { |
| 1220 | | // logerror("L-ROM: Lower ROM enabled, cart bank %i\n", state->m_asic.rmr2 & 0x07 ); |
| 1221 | | bank_base = &machine.root_device().memregion("maincpu")->base()[0x4000 * ( state->m_asic.rmr2 & 0x07 )]; |
| 1222 | | switch( state->m_asic.rmr2 & 0x18 ) |
| 1214 | // logerror("L-ROM: Lower ROM enabled, cart bank %i\n", m_asic.rmr2 & 0x07 ); |
| 1215 | bank_base = &m_region_maincpu->base()[0x4000 * ( m_asic.rmr2 & 0x07 )]; |
| 1216 | switch( m_asic.rmr2 & 0x18 ) |
| 1223 | 1217 | { |
| 1224 | 1218 | case 0x00: |
| 1225 | 1219 | // logerror("L-ROM: located at &0000\n"); |
| 1226 | | state->membank("bank1")->set_base(bank_base); |
| 1227 | | state->membank("bank2")->set_base(bank_base+0x02000); |
| 1220 | m_bank1->set_base(bank_base); |
| 1221 | m_bank2->set_base(bank_base+0x02000); |
| 1228 | 1222 | break; |
| 1229 | 1223 | case 0x08: |
| 1230 | 1224 | // logerror("L-ROM: located at &4000\n"); |
| 1231 | | state->membank("bank3")->set_base(bank_base); |
| 1232 | | state->membank("bank4")->set_base(bank_base+0x02000); |
| 1225 | m_bank3->set_base(bank_base); |
| 1226 | m_bank4->set_base(bank_base+0x02000); |
| 1233 | 1227 | break; |
| 1234 | 1228 | case 0x10: |
| 1235 | 1229 | // logerror("L-ROM: located at &8000\n"); |
| 1236 | | state->membank("bank5")->set_base(bank_base); |
| 1237 | | state->membank("bank6")->set_base(bank_base+0x02000); |
| 1230 | m_bank5->set_base(bank_base); |
| 1231 | m_bank6->set_base(bank_base+0x02000); |
| 1238 | 1232 | break; |
| 1239 | 1233 | case 0x18: |
| 1240 | 1234 | // logerror("L-ROM: located at &0000, ASIC registers enabled\n"); |
| 1241 | | state->membank("bank1")->set_base(bank_base); |
| 1242 | | state->membank("bank2")->set_base(bank_base+0x02000); |
| 1235 | m_bank1->set_base(bank_base); |
| 1236 | m_bank2->set_base(bank_base+0x02000); |
| 1243 | 1237 | break; |
| 1244 | 1238 | } |
| 1245 | 1239 | } |
| 1246 | 1240 | else |
| 1247 | 1241 | { |
| 1248 | | state->membank( "bank1" )->set_base( machine.root_device().memregion( "maincpu" )->base() ); |
| 1249 | | state->membank( "bank2" )->set_base( machine.root_device().memregion( "maincpu" )->base() + 0x2000 ); |
| 1242 | m_bank1->set_base( m_region_maincpu->base() ); |
| 1243 | m_bank2->set_base( m_region_maincpu->base() + 0x2000 ); |
| 1250 | 1244 | } |
| 1251 | 1245 | } |
| 1252 | 1246 | } |
| r20956 | r20957 | |
| 1256 | 1250 | /*----------------- |
| 1257 | 1251 | - Set Upper Rom - |
| 1258 | 1252 | -----------------*/ |
| 1259 | | static void amstrad_setUpperRom(running_machine &machine) |
| 1253 | void amstrad_state::amstrad_setUpperRom() |
| 1260 | 1254 | { |
| 1261 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 1262 | 1255 | UINT8 *bank_base = NULL; |
| 1263 | 1256 | |
| 1264 | 1257 | /* b3 : "1" Upper rom area disable or "0" Upper rom area enable */ |
| 1265 | | if ( ! ( state->m_gate_array.mrer & 0x08 ) && state->m_gate_array.romdis == 0) |
| 1258 | if ( ! ( m_gate_array.mrer & 0x08 ) && m_gate_array.romdis == 0) |
| 1266 | 1259 | { |
| 1267 | | bank_base = state->m_Amstrad_ROM_Table[ state->m_gate_array.upper_bank ]; |
| 1260 | bank_base = m_Amstrad_ROM_Table[ m_gate_array.upper_bank ]; |
| 1268 | 1261 | } |
| 1269 | 1262 | else |
| 1270 | 1263 | { |
| 1271 | | if(state->m_aleste_mode & 0x04) |
| 1272 | | bank_base = state->m_Aleste_RamBanks[3]; |
| 1264 | if(m_aleste_mode & 0x04) |
| 1265 | bank_base = m_Aleste_RamBanks[3]; |
| 1273 | 1266 | else |
| 1274 | | bank_base = state->m_AmstradCPC_RamBanks[3]; |
| 1267 | bank_base = m_AmstradCPC_RamBanks[3]; |
| 1275 | 1268 | } |
| 1276 | 1269 | |
| 1277 | 1270 | if (bank_base) |
| 1278 | 1271 | { |
| 1279 | | state->membank("bank7")->set_base(bank_base); |
| 1280 | | state->membank("bank8")->set_base(bank_base+0x2000); |
| 1272 | m_bank7->set_base(bank_base); |
| 1273 | m_bank8->set_base(bank_base+0x2000); |
| 1281 | 1274 | } |
| 1282 | 1275 | } |
| 1283 | 1276 | |
| r20956 | r20957 | |
| 1302 | 1295 | The CPC6128 has a 64k ram expansion built-in, giving 128K of RAM in this system. |
| 1303 | 1296 | In the CPC464,CPC664 and KC compact if a ram expansion is not present, then writing to this port has no effect and the ram will be in the same arrangement as if configuration 0 had been selected. |
| 1304 | 1297 | */ |
| 1305 | | static void AmstradCPC_GA_SetRamConfiguration(running_machine &machine) |
| 1298 | void amstrad_state::AmstradCPC_GA_SetRamConfiguration() |
| 1306 | 1299 | { |
| 1307 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 1308 | | int ConfigurationIndex = state->m_GateArray_RamConfiguration & 0x07; |
| 1300 | int ConfigurationIndex = m_GateArray_RamConfiguration & 0x07; |
| 1309 | 1301 | int BankIndex,i; |
| 1310 | 1302 | unsigned char *BankAddr; |
| 1311 | 1303 | |
| 1312 | 1304 | /* if b5 = 0 */ |
| 1313 | | if(((state->m_GateArray_RamConfiguration) & (1<<5)) == 0) |
| 1305 | if(((m_GateArray_RamConfiguration) & (1<<5)) == 0) |
| 1314 | 1306 | { |
| 1315 | 1307 | for (i=0;i<4;i++) |
| 1316 | 1308 | { |
| 1317 | 1309 | BankIndex = RamConfigurations[(ConfigurationIndex << 2) + i]; |
| 1318 | | BankAddr = state->m_ram->pointer() + (BankIndex << 14); |
| 1319 | | state->m_Aleste_RamBanks[i] = BankAddr; |
| 1320 | | state->m_AmstradCPC_RamBanks[i] = BankAddr; |
| 1310 | BankAddr = m_ram->pointer() + (BankIndex << 14); |
| 1311 | m_Aleste_RamBanks[i] = BankAddr; |
| 1312 | m_AmstradCPC_RamBanks[i] = BankAddr; |
| 1321 | 1313 | } |
| 1322 | 1314 | } |
| 1323 | 1315 | else |
| 1324 | 1316 | {/* Need to add the ram expansion configuration here ! */ |
| 1325 | 1317 | } |
| 1326 | | amstrad_rethinkMemory(machine); |
| 1318 | amstrad_rethinkMemory(); |
| 1327 | 1319 | } |
| 1328 | 1320 | |
| 1329 | 1321 | |
| r20956 | r20957 | |
| 1400 | 1392 | m_asic.ram[offset] = data & 0x0f; |
| 1401 | 1393 | else |
| 1402 | 1394 | { |
| 1403 | | UINT8* RAM = (UINT8*)membank("bank11")->base(); |
| 1395 | UINT8* RAM = (UINT8*)m_bank11->base(); |
| 1404 | 1396 | RAM[offset] = data; |
| 1405 | 1397 | } |
| 1406 | 1398 | } |
| r20956 | r20957 | |
| 1479 | 1471 | if(data & 0x40) |
| 1480 | 1472 | { |
| 1481 | 1473 | logerror("ASIC: DMA 0 IRQ acknowledge\n"); |
| 1482 | | machine().device("maincpu")->execute().set_input_line(0, CLEAR_LINE); |
| 1474 | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 1483 | 1475 | m_plus_irq_cause = 0x06; |
| 1484 | 1476 | m_asic.ram[0x2c0f] &= ~0x40; |
| 1485 | 1477 | } |
| 1486 | 1478 | if(data & 0x20) |
| 1487 | 1479 | { |
| 1488 | 1480 | logerror("ASIC: DMA 1 IRQ acknowledge\n"); |
| 1489 | | machine().device("maincpu")->execute().set_input_line(0, CLEAR_LINE); |
| 1481 | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 1490 | 1482 | m_plus_irq_cause = 0x06; |
| 1491 | 1483 | m_asic.ram[0x2c0f] &= ~0x20; |
| 1492 | 1484 | } |
| 1493 | 1485 | if(data & 0x10) |
| 1494 | 1486 | { |
| 1495 | 1487 | logerror("ASIC: DMA 2 IRQ acknowledge\n"); |
| 1496 | | machine().device("maincpu")->execute().set_input_line(0, CLEAR_LINE); |
| 1488 | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 1497 | 1489 | m_plus_irq_cause = 0x06; |
| 1498 | 1490 | m_asic.ram[0x2c0f] &= ~0x10; |
| 1499 | 1491 | } |
| r20956 | r20957 | |
| 1503 | 1495 | } |
| 1504 | 1496 | else |
| 1505 | 1497 | { |
| 1506 | | UINT8* RAM = (UINT8*)membank("bank12")->base(); |
| 1498 | UINT8* RAM = (UINT8*)m_bank12->base(); |
| 1507 | 1499 | RAM[offset] = data; |
| 1508 | 1500 | } |
| 1509 | 1501 | } |
| r20956 | r20957 | |
| 1516 | 1508 | return m_asic.ram[offset]; |
| 1517 | 1509 | else |
| 1518 | 1510 | { |
| 1519 | | UINT8* RAM = (UINT8*)membank("bank3")->base(); |
| 1511 | UINT8* RAM = (UINT8*)m_bank3->base(); |
| 1520 | 1512 | return RAM[offset]; |
| 1521 | 1513 | } |
| 1522 | 1514 | } |
| r20956 | r20957 | |
| 1530 | 1522 | // Analogue ports |
| 1531 | 1523 | if(offset == 0x0808) |
| 1532 | 1524 | { |
| 1533 | | return (ioport("analog1")->read() & 0x3f); |
| 1525 | return (m_io_analog1->read() & 0x3f); |
| 1534 | 1526 | } |
| 1535 | 1527 | if(offset == 0x0809) |
| 1536 | 1528 | { |
| 1537 | | return (ioport("analog2")->read() & 0x3f); |
| 1529 | return (m_io_analog2->read() & 0x3f); |
| 1538 | 1530 | } |
| 1539 | 1531 | if(offset == 0x080a) |
| 1540 | 1532 | { |
| 1541 | | return (ioport("analog3")->read() & 0x3f); |
| 1533 | return (m_io_analog3->read() & 0x3f); |
| 1542 | 1534 | } |
| 1543 | 1535 | if(offset == 0x080b) |
| 1544 | 1536 | { |
| 1545 | | return (ioport("analog4")->read() & 0x3f); |
| 1537 | return (m_io_analog4->read() & 0x3f); |
| 1546 | 1538 | } |
| 1547 | 1539 | if(offset == 0x080c || offset == 0x080e) |
| 1548 | 1540 | { |
| r20956 | r20957 | |
| 1571 | 1563 | } |
| 1572 | 1564 | else |
| 1573 | 1565 | { |
| 1574 | | UINT8* RAM = (UINT8*)membank("bank4")->base(); |
| 1566 | UINT8* RAM = (UINT8*)m_bank4->base(); |
| 1575 | 1567 | return RAM[offset]; |
| 1576 | 1568 | } |
| 1577 | 1569 | } |
| 1578 | 1570 | |
| 1579 | 1571 | |
| 1580 | 1572 | /* used for loading snapshot only ! */ |
| 1581 | | static void AmstradCPC_PALWrite(running_machine &machine, int data) |
| 1573 | void amstrad_state::AmstradCPC_PALWrite(int data) |
| 1582 | 1574 | { |
| 1583 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 1584 | 1575 | if ((data & 0x0c0)==0x0c0) |
| 1585 | 1576 | { |
| 1586 | | state->m_GateArray_RamConfiguration = data; |
| 1587 | | AmstradCPC_GA_SetRamConfiguration(machine); |
| 1577 | m_GateArray_RamConfiguration = data; |
| 1578 | AmstradCPC_GA_SetRamConfiguration(); |
| 1588 | 1579 | } |
| 1589 | 1580 | } |
| 1590 | 1581 | |
| r20956 | r20957 | |
| 1609 | 1600 | Note 1 : This function is not available in the Gate-Array, but is performed by a device at the same I/O port address location. In the CPC464,CPC664 and KC compact, this function is performed in a memory-expansion (e.g. Dk'Tronics 64K Ram Expansion), if this expansion is not present then the function is not available. In the CPC6128, this function is performed by a PAL located on the main PCB, or a memory-expansion. In the 464+ and 6128+ this function is performed by the ASIC or a memory expansion. Please read the document on Ram Management for more information.*/ |
| 1610 | 1601 | |
| 1611 | 1602 | |
| 1612 | | static void amstrad_GateArray_write(running_machine &machine, UINT8 dataToGateArray) |
| 1603 | void amstrad_state::amstrad_GateArray_write(UINT8 dataToGateArray) |
| 1613 | 1604 | { |
| 1614 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 1615 | 1605 | /* Get Bit 7 and 6 of the dataToGateArray = Gate Array function selected */ |
| 1616 | 1606 | switch ((dataToGateArray & 0xc0)>>6) |
| 1617 | 1607 | { |
| r20956 | r20957 | |
| 1628 | 1618 | case 0x00: |
| 1629 | 1619 | /* Select Border Number, get b4 */ |
| 1630 | 1620 | /* if b4 = 0 : Select Pen Number, get b3-b0 */ |
| 1631 | | state->m_gate_array.pen_selected = ( dataToGateArray & 0x10 ) ? 0x10 : ( dataToGateArray & 0x0f ); |
| 1621 | m_gate_array.pen_selected = ( dataToGateArray & 0x10 ) ? 0x10 : ( dataToGateArray & 0x0f ); |
| 1632 | 1622 | break; |
| 1633 | 1623 | |
| 1634 | 1624 | /* Colour selection |
| r20956 | r20957 | |
| 1644 | 1634 | 1 x | |
| 1645 | 1635 | 0 x |*/ |
| 1646 | 1636 | case 0x01: |
| 1647 | | amstrad_vh_update_colour( machine, state->m_gate_array.pen_selected, (dataToGateArray & 0x1F)); |
| 1637 | amstrad_vh_update_colour( m_gate_array.pen_selected, (dataToGateArray & 0x1F)); |
| 1648 | 1638 | break; |
| 1649 | 1639 | |
| 1650 | 1640 | /* Select screen mode and rom configuration |
| r20956 | r20957 | |
| 1678 | 1668 | /* If bit 5 is enabled on a CPC Plus/GX4000 when the ASIC is unlocked, sets the lower ROM position and cart bank |
| 1679 | 1669 | b5 = 1, b4b3 = RAM position for lower ROM area and if the ASIC registers are visible at &4000, |
| 1680 | 1670 | b2b1b0 = cartridge bank to read from lower ROM area (0-7 only) */ |
| 1681 | | if ( state->m_system_type == SYSTEM_PLUS || state->m_system_type == SYSTEM_GX4000 ) |
| 1671 | if ( m_system_type == SYSTEM_PLUS || m_system_type == SYSTEM_GX4000 ) |
| 1682 | 1672 | { |
| 1683 | | if ( state->m_asic.enabled && (dataToGateArray & 0x20) ) |
| 1673 | if ( m_asic.enabled && (dataToGateArray & 0x20) ) |
| 1684 | 1674 | { |
| 1685 | | state->m_asic.rmr2 = dataToGateArray; |
| 1675 | m_asic.rmr2 = dataToGateArray; |
| 1686 | 1676 | } |
| 1687 | 1677 | else |
| 1688 | 1678 | { |
| 1689 | | state->m_gate_array.mrer = dataToGateArray; |
| 1679 | m_gate_array.mrer = dataToGateArray; |
| 1690 | 1680 | } |
| 1691 | 1681 | } |
| 1692 | 1682 | else |
| 1693 | 1683 | { |
| 1694 | | state->m_gate_array.mrer = dataToGateArray; |
| 1684 | m_gate_array.mrer = dataToGateArray; |
| 1695 | 1685 | } |
| 1696 | 1686 | |
| 1697 | 1687 | /* If bit 4 of the "Select screen mode and rom configuration" register of the Gate-Array is set to "1" |
| 1698 | 1688 | then the interrupt request is cleared and the 6-bit counter is reset to "0". */ |
| 1699 | | if ( state->m_gate_array.mrer & 0x10 ) |
| 1689 | if ( m_gate_array.mrer & 0x10 ) |
| 1700 | 1690 | { |
| 1701 | | state->m_gate_array.hsync_counter = 0; |
| 1702 | | machine.device("maincpu")->execute().set_input_line(0, CLEAR_LINE); |
| 1691 | m_gate_array.hsync_counter = 0; |
| 1692 | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 1703 | 1693 | } |
| 1704 | 1694 | |
| 1705 | 1695 | /* b3b2 != 0 then change the state of upper or lower rom area and rethink memory */ |
| 1706 | | amstrad_setLowerRom(machine); |
| 1707 | | amstrad_setUpperRom(machine); |
| 1696 | amstrad_setLowerRom(); |
| 1697 | amstrad_setUpperRom(); |
| 1708 | 1698 | |
| 1709 | 1699 | /* b1b0 mode */ |
| 1710 | | amstrad_vh_update_mode(state); |
| 1700 | amstrad_vh_update_mode(); |
| 1711 | 1701 | |
| 1712 | 1702 | break; |
| 1713 | 1703 | |
| r20956 | r20957 | |
| 1719 | 1709 | In the 464+ and 6128+ this function is performed by the ASIC or a memory expansion. |
| 1720 | 1710 | */ |
| 1721 | 1711 | case 0x03: |
| 1722 | | state->m_GateArray_RamConfiguration = dataToGateArray; |
| 1712 | m_GateArray_RamConfiguration = dataToGateArray; |
| 1723 | 1713 | break; |
| 1724 | 1714 | |
| 1725 | 1715 | default: |
| r20956 | r20957 | |
| 1740 | 1730 | switch(function) |
| 1741 | 1731 | { |
| 1742 | 1732 | case 0: // Pen select (same as Gate Array?) |
| 1743 | | amstrad_GateArray_write(machine(), data); |
| 1733 | amstrad_GateArray_write(data); |
| 1744 | 1734 | break; |
| 1745 | 1735 | case 1: // Colour select (6-bit palette) |
| 1746 | | aleste_vh_update_colour( machine(), m_gate_array.pen_selected, data & 0x3f ); |
| 1736 | aleste_vh_update_colour( m_gate_array.pen_selected, data & 0x3f ); |
| 1747 | 1737 | break; |
| 1748 | 1738 | case 2: // Screen mode, Upper/Lower ROM select |
| 1749 | | amstrad_GateArray_write(machine(), data); |
| 1739 | amstrad_GateArray_write(data); |
| 1750 | 1740 | break; |
| 1751 | 1741 | case 3: // RAM banks |
| 1752 | 1742 | switch(page) |
| 1753 | 1743 | { |
| 1754 | 1744 | case 0: /* 0x0000 - 0x3fff */ |
| 1755 | | membank("bank1")->set_base(ram+ramptr); |
| 1756 | | membank("bank2")->set_base(ram+ramptr+0x2000); |
| 1757 | | membank("bank9")->set_base(ram+ramptr); |
| 1758 | | membank("bank10")->set_base(ram+ramptr+0x2000); |
| 1745 | m_bank1->set_base(ram+ramptr); |
| 1746 | m_bank2->set_base(ram+ramptr+0x2000); |
| 1747 | m_bank9->set_base(ram+ramptr); |
| 1748 | m_bank10->set_base(ram+ramptr+0x2000); |
| 1759 | 1749 | m_Aleste_RamBanks[0] = ram+ramptr; |
| 1760 | 1750 | m_aleste_active_page[0] = data; |
| 1761 | 1751 | logerror("RAM: RAM location 0x%06x (page %02x) mapped to 0x0000\n",ramptr,rampage); |
| 1762 | 1752 | break; |
| 1763 | 1753 | case 1: /* 0x4000 - 0x7fff */ |
| 1764 | | membank("bank3")->set_base(ram+ramptr); |
| 1765 | | membank("bank4")->set_base(ram+ramptr+0x2000); |
| 1766 | | membank("bank11")->set_base(ram+ramptr); |
| 1767 | | membank("bank12")->set_base(ram+ramptr+0x2000); |
| 1754 | m_bank3->set_base(ram+ramptr); |
| 1755 | m_bank4->set_base(ram+ramptr+0x2000); |
| 1756 | m_bank11->set_base(ram+ramptr); |
| 1757 | m_bank12->set_base(ram+ramptr+0x2000); |
| 1768 | 1758 | m_Aleste_RamBanks[1] = ram+ramptr; |
| 1769 | 1759 | m_aleste_active_page[1] = data; |
| 1770 | 1760 | logerror("RAM: RAM location 0x%06x (page %02x) mapped to 0x4000\n",ramptr,rampage); |
| 1771 | 1761 | break; |
| 1772 | 1762 | case 2: /* 0x8000 - 0xbfff */ |
| 1773 | | membank("bank5")->set_base(ram+ramptr); |
| 1774 | | membank("bank6")->set_base(ram+ramptr+0x2000); |
| 1775 | | membank("bank13")->set_base(ram+ramptr); |
| 1776 | | membank("bank14")->set_base(ram+ramptr+0x2000); |
| 1763 | m_bank5->set_base(ram+ramptr); |
| 1764 | m_bank6->set_base(ram+ramptr+0x2000); |
| 1765 | m_bank13->set_base(ram+ramptr); |
| 1766 | m_bank14->set_base(ram+ramptr+0x2000); |
| 1777 | 1767 | m_Aleste_RamBanks[2] = ram+ramptr; |
| 1778 | 1768 | m_aleste_active_page[2] = data; |
| 1779 | 1769 | logerror("RAM: RAM location 0x%06x (page %02x) mapped to 0x8000\n",ramptr,rampage); |
| 1780 | 1770 | break; |
| 1781 | 1771 | case 3: /* 0xc000 - 0xffff */ |
| 1782 | | membank("bank7")->set_base(ram+ramptr); |
| 1783 | | membank("bank8")->set_base(ram+ramptr+0x2000); |
| 1784 | | membank("bank15")->set_base(ram+ramptr); |
| 1785 | | membank("bank16")->set_base(ram+ramptr+0x2000); |
| 1772 | m_bank7->set_base(ram+ramptr); |
| 1773 | m_bank8->set_base(ram+ramptr+0x2000); |
| 1774 | m_bank15->set_base(ram+ramptr); |
| 1775 | m_bank16->set_base(ram+ramptr+0x2000); |
| 1786 | 1776 | m_Aleste_RamBanks[3] = ram+ramptr; |
| 1787 | 1777 | m_aleste_active_page[3] = data; |
| 1788 | 1778 | logerror("RAM: RAM location 0x%06x (page %02x) mapped to 0xc000\n",ramptr,rampage); |
| r20956 | r20957 | |
| 1856 | 1846 | |
| 1857 | 1847 | READ8_MEMBER(amstrad_state::amstrad_cpc_io_r) |
| 1858 | 1848 | { |
| 1859 | | mc6845_device *mc6845 = m_crtc; |
| 1860 | | |
| 1861 | 1849 | unsigned char data = 0xFF; |
| 1862 | 1850 | unsigned int r1r0 = (unsigned int)((offset & 0x0300) >> 8); |
| 1863 | 1851 | // m6845_personality_t crtc_type; |
| r20956 | r20957 | |
| 1882 | 1870 | switch(r1r0) |
| 1883 | 1871 | { |
| 1884 | 1872 | case 0x02: |
| 1885 | | data = mc6845->status_r( space, 0 ); |
| 1873 | data = m_crtc->status_r( space, 0 ); |
| 1886 | 1874 | #if 0 |
| 1887 | 1875 | /* CRTC Type 1 : Read Status Register |
| 1888 | 1876 | CRTC Type 3 or 4 : Read from selected internal 6845 register */ |
| r20956 | r20957 | |
| 1901 | 1889 | break; |
| 1902 | 1890 | case 0x03: |
| 1903 | 1891 | /* All CRTC type : Read from selected internal 6845 register Read only */ |
| 1904 | | data = mc6845->register_r( space, (offs_t)0 ); |
| 1892 | data = m_crtc->register_r( space, (offs_t)0 ); |
| 1905 | 1893 | break; |
| 1906 | 1894 | } |
| 1907 | 1895 | } |
| r20956 | r20957 | |
| 1991 | 1979 | /* Offset handler for write */ |
| 1992 | 1980 | WRITE8_MEMBER(amstrad_state::amstrad_cpc_io_w) |
| 1993 | 1981 | { |
| 1994 | | mc6845_device *mc6845 = m_crtc; |
| 1995 | 1982 | cpc_multiface2_device* mface2; |
| 1996 | 1983 | |
| 1997 | 1984 | if ((offset & (1<<15)) == 0) |
| r20956 | r20957 | |
| 2004 | 1991 | { |
| 2005 | 1992 | /* if b15 = 0 and b14 = 1 : Gate-Array Write Selected*/ |
| 2006 | 1993 | if ((offset & (1<<14)) != 0) |
| 2007 | | amstrad_GateArray_write(machine(), data); |
| 1994 | amstrad_GateArray_write(data); |
| 2008 | 1995 | |
| 2009 | 1996 | /* if b15 = 0 : RAM Configuration Write Selected*/ |
| 2010 | | AmstradCPC_GA_SetRamConfiguration(machine()); |
| 1997 | AmstradCPC_GA_SetRamConfiguration(); |
| 2011 | 1998 | } |
| 2012 | 1999 | } |
| 2013 | 2000 | |
| r20956 | r20957 | |
| 2018 | 2005 | switch ((offset & 0x0300) >> 8) // r1r0 |
| 2019 | 2006 | { |
| 2020 | 2007 | case 0x00: /* Select internal 6845 register Write Only */ |
| 2021 | | mc6845->address_w( space, 0, data ); |
| 2008 | m_crtc->address_w( space, 0, data ); |
| 2022 | 2009 | if ( m_system_type == SYSTEM_PLUS || m_system_type == SYSTEM_GX4000 ) |
| 2023 | 2010 | amstrad_plus_seqcheck(data); |
| 2024 | 2011 | |
| r20956 | r20957 | |
| 2033 | 2020 | machine().scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),this),1); |
| 2034 | 2021 | else |
| 2035 | 2022 | machine().scheduler().timer_set( attotime::from_usec(0), timer_expired_delegate(FUNC(amstrad_state::amstrad_video_update_timer),this),0); |
| 2036 | | mc6845->register_w( space, 0, data ); |
| 2023 | m_crtc->register_w( space, 0, data ); |
| 2037 | 2024 | |
| 2038 | 2025 | /* printer port bit 8 */ |
| 2039 | 2026 | if (m_printer_bit8_selected && m_system_type == SYSTEM_PLUS) |
| 2040 | 2027 | { |
| 2041 | | centronics_device *printer = m_centronics; |
| 2042 | | printer->d7_w(BIT(data, 3)); |
| 2028 | m_centronics->d7_w(BIT(data, 3)); |
| 2043 | 2029 | m_printer_bit8_selected = FALSE; |
| 2044 | 2030 | } |
| 2045 | 2031 | |
| r20956 | r20957 | |
| 2057 | 2043 | if ((offset & (1<<13)) == 0) |
| 2058 | 2044 | { |
| 2059 | 2045 | m_gate_array.upper_bank = data; |
| 2060 | | amstrad_setUpperRom(machine()); |
| 2046 | amstrad_setUpperRom(); |
| 2061 | 2047 | } |
| 2062 | 2048 | |
| 2063 | 2049 | /* b12 = 0 : Printer port Write Selected*/ |
| r20956 | r20957 | |
| 2065 | 2051 | { |
| 2066 | 2052 | if ((offset & (1<<12)) == 0) |
| 2067 | 2053 | { |
| 2068 | | centronics_device *printer = m_centronics; |
| 2069 | | |
| 2070 | 2054 | /* CPC has a 7-bit data port, bit 8 is the STROBE signal */ |
| 2071 | | printer->write(space, 0, data & 0x7f); |
| 2072 | | printer->strobe_w(BIT(data, 7)); |
| 2055 | m_centronics->write(space, 0, data & 0x7f); |
| 2056 | m_centronics->strobe_w(BIT(data, 7)); |
| 2073 | 2057 | } |
| 2074 | 2058 | } |
| 2075 | 2059 | |
| r20956 | r20957 | |
| 2151 | 2135 | { |
| 2152 | 2136 | m_aleste_mode = data; |
| 2153 | 2137 | logerror("EXTEND: Port &FABF write 0x%02x\n",data); |
| 2154 | | mc6845->set_clock( ( m_aleste_mode & 0x02 ) ? ( XTAL_16MHz / 8 ) : ( XTAL_16MHz / 16 ) ); |
| 2138 | m_crtc->set_clock( ( m_aleste_mode & 0x02 ) ? ( XTAL_16MHz / 8 ) : ( XTAL_16MHz / 16 ) ); |
| 2155 | 2139 | } |
| 2156 | 2140 | |
| 2157 | 2141 | mface2 = dynamic_cast<cpc_multiface2_device*>(get_expansion_device(machine(),"multiface2")); |
| 2158 | 2142 | if(mface2 != NULL) |
| 2159 | 2143 | { |
| 2160 | 2144 | if(mface2->multiface_io_write(offset, data) != 0) |
| 2161 | | amstrad_rethinkMemory(machine()); |
| 2145 | { |
| 2146 | amstrad_rethinkMemory(); |
| 2147 | } |
| 2162 | 2148 | } |
| 2163 | 2149 | } |
| 2164 | 2150 | |
| 2165 | 2151 | |
| 2166 | 2152 | /* load CPCEMU style snapshots */ |
| 2167 | | static void amstrad_handle_snapshot(running_machine &machine, unsigned char *pSnapshot) |
| 2153 | void amstrad_state::amstrad_handle_snapshot(unsigned char *pSnapshot) |
| 2168 | 2154 | { |
| 2169 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 2170 | | address_space &space = state->m_maincpu->space(AS_PROGRAM); |
| 2171 | | mc6845_device *mc6845 = state->m_crtc; |
| 2172 | | device_t *ay8910 = state->m_ay; |
| 2155 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 2173 | 2156 | int RegData; |
| 2174 | 2157 | int i; |
| 2175 | 2158 | |
| 2176 | 2159 | /* init Z80 */ |
| 2177 | 2160 | RegData = (pSnapshot[0x011] & 0x0ff) | ((pSnapshot[0x012] & 0x0ff)<<8); |
| 2178 | | state->m_maincpu->set_state_int(Z80_AF, RegData); |
| 2161 | m_maincpu->set_state_int(Z80_AF, RegData); |
| 2179 | 2162 | |
| 2180 | 2163 | RegData = (pSnapshot[0x013] & 0x0ff) | ((pSnapshot[0x014] & 0x0ff)<<8); |
| 2181 | | state->m_maincpu->set_state_int(Z80_BC, RegData); |
| 2164 | m_maincpu->set_state_int(Z80_BC, RegData); |
| 2182 | 2165 | |
| 2183 | 2166 | RegData = (pSnapshot[0x015] & 0x0ff) | ((pSnapshot[0x016] & 0x0ff)<<8); |
| 2184 | | state->m_maincpu->set_state_int(Z80_DE, RegData); |
| 2167 | m_maincpu->set_state_int(Z80_DE, RegData); |
| 2185 | 2168 | |
| 2186 | 2169 | RegData = (pSnapshot[0x017] & 0x0ff) | ((pSnapshot[0x018] & 0x0ff)<<8); |
| 2187 | | state->m_maincpu->set_state_int(Z80_HL, RegData); |
| 2170 | m_maincpu->set_state_int(Z80_HL, RegData); |
| 2188 | 2171 | |
| 2189 | 2172 | RegData = (pSnapshot[0x019] & 0x0ff) ; |
| 2190 | | state->m_maincpu->set_state_int(Z80_R, RegData); |
| 2173 | m_maincpu->set_state_int(Z80_R, RegData); |
| 2191 | 2174 | |
| 2192 | 2175 | RegData = (pSnapshot[0x01a] & 0x0ff); |
| 2193 | | state->m_maincpu->set_state_int(Z80_I, RegData); |
| 2176 | m_maincpu->set_state_int(Z80_I, RegData); |
| 2194 | 2177 | |
| 2195 | 2178 | if ((pSnapshot[0x01b] & 1)==1) |
| 2196 | 2179 | { |
| 2197 | | state->m_maincpu->set_state_int(Z80_IFF1, (UINT64)1); |
| 2180 | m_maincpu->set_state_int(Z80_IFF1, (UINT64)1); |
| 2198 | 2181 | } |
| 2199 | 2182 | else |
| 2200 | 2183 | { |
| 2201 | | state->m_maincpu->set_state_int(Z80_IFF1, (UINT64)0); |
| 2184 | m_maincpu->set_state_int(Z80_IFF1, (UINT64)0); |
| 2202 | 2185 | } |
| 2203 | 2186 | |
| 2204 | 2187 | if ((pSnapshot[0x01c] & 1)==1) |
| 2205 | 2188 | { |
| 2206 | | state->m_maincpu->set_state_int(Z80_IFF2, (UINT64)1); |
| 2189 | m_maincpu->set_state_int(Z80_IFF2, (UINT64)1); |
| 2207 | 2190 | } |
| 2208 | 2191 | else |
| 2209 | 2192 | { |
| 2210 | | state->m_maincpu->set_state_int(Z80_IFF2, (UINT64)0); |
| 2193 | m_maincpu->set_state_int(Z80_IFF2, (UINT64)0); |
| 2211 | 2194 | } |
| 2212 | 2195 | |
| 2213 | 2196 | RegData = (pSnapshot[0x01d] & 0x0ff) | ((pSnapshot[0x01e] & 0x0ff)<<8); |
| 2214 | | state->m_maincpu->set_state_int(Z80_IX, RegData); |
| 2197 | m_maincpu->set_state_int(Z80_IX, RegData); |
| 2215 | 2198 | |
| 2216 | 2199 | RegData = (pSnapshot[0x01f] & 0x0ff) | ((pSnapshot[0x020] & 0x0ff)<<8); |
| 2217 | | state->m_maincpu->set_state_int(Z80_IY, RegData); |
| 2200 | m_maincpu->set_state_int(Z80_IY, RegData); |
| 2218 | 2201 | |
| 2219 | 2202 | RegData = (pSnapshot[0x021] & 0x0ff) | ((pSnapshot[0x022] & 0x0ff)<<8); |
| 2220 | | state->m_maincpu->set_state_int(Z80_SP, RegData); |
| 2221 | | state->m_maincpu->set_state_int(STATE_GENSP, RegData); |
| 2203 | m_maincpu->set_state_int(Z80_SP, RegData); |
| 2204 | m_maincpu->set_state_int(STATE_GENSP, RegData); |
| 2222 | 2205 | |
| 2223 | 2206 | RegData = (pSnapshot[0x023] & 0x0ff) | ((pSnapshot[0x024] & 0x0ff)<<8); |
| 2224 | 2207 | |
| 2225 | | state->m_maincpu->set_state_int(Z80_PC, RegData); |
| 2226 | | // state->m_maincpu->set_state_int(REG_SP, RegData); |
| 2208 | m_maincpu->set_state_int(Z80_PC, RegData); |
| 2209 | // m_maincpu->set_state_int(REG_SP, RegData); |
| 2227 | 2210 | |
| 2228 | 2211 | RegData = (pSnapshot[0x025] & 0x0ff); |
| 2229 | | state->m_maincpu->set_state_int(Z80_IM, RegData); |
| 2212 | m_maincpu->set_state_int(Z80_IM, RegData); |
| 2230 | 2213 | |
| 2231 | 2214 | RegData = (pSnapshot[0x026] & 0x0ff) | ((pSnapshot[0x027] & 0x0ff)<<8); |
| 2232 | | state->m_maincpu->set_state_int(Z80_AF2, RegData); |
| 2215 | m_maincpu->set_state_int(Z80_AF2, RegData); |
| 2233 | 2216 | |
| 2234 | 2217 | RegData = (pSnapshot[0x028] & 0x0ff) | ((pSnapshot[0x029] & 0x0ff)<<8); |
| 2235 | | state->m_maincpu->set_state_int(Z80_BC2, RegData); |
| 2218 | m_maincpu->set_state_int(Z80_BC2, RegData); |
| 2236 | 2219 | |
| 2237 | 2220 | RegData = (pSnapshot[0x02a] & 0x0ff) | ((pSnapshot[0x02b] & 0x0ff)<<8); |
| 2238 | | state->m_maincpu->set_state_int(Z80_DE2, RegData); |
| 2221 | m_maincpu->set_state_int(Z80_DE2, RegData); |
| 2239 | 2222 | |
| 2240 | 2223 | RegData = (pSnapshot[0x02c] & 0x0ff) | ((pSnapshot[0x02d] & 0x0ff)<<8); |
| 2241 | | state->m_maincpu->set_state_int(Z80_HL2, RegData); |
| 2224 | m_maincpu->set_state_int(Z80_HL2, RegData); |
| 2242 | 2225 | |
| 2243 | 2226 | /* init GA */ |
| 2244 | 2227 | for (i=0; i<17; i++) |
| 2245 | 2228 | { |
| 2246 | | amstrad_GateArray_write(machine, i); |
| 2229 | amstrad_GateArray_write(i); |
| 2247 | 2230 | |
| 2248 | | amstrad_GateArray_write(machine, ((pSnapshot[0x02f + i] & 0x01f) | 0x040)); |
| 2231 | amstrad_GateArray_write(((pSnapshot[0x02f + i] & 0x01f) | 0x040)); |
| 2249 | 2232 | } |
| 2250 | 2233 | |
| 2251 | | amstrad_GateArray_write(machine, pSnapshot[0x02e] & 0x01f); |
| 2234 | amstrad_GateArray_write(pSnapshot[0x02e] & 0x01f); |
| 2252 | 2235 | |
| 2253 | | amstrad_GateArray_write(machine, ((pSnapshot[0x040] & 0x03f) | 0x080)); |
| 2236 | amstrad_GateArray_write(((pSnapshot[0x040] & 0x03f) | 0x080)); |
| 2254 | 2237 | |
| 2255 | | AmstradCPC_PALWrite(machine, ((pSnapshot[0x041] & 0x03f) | 0x0c0)); |
| 2238 | AmstradCPC_PALWrite(((pSnapshot[0x041] & 0x03f) | 0x0c0)); |
| 2256 | 2239 | |
| 2257 | 2240 | /* init CRTC */ |
| 2258 | 2241 | for (i=0; i<18; i++) |
| 2259 | 2242 | { |
| 2260 | | mc6845->address_w( space, 0, i ); |
| 2261 | | mc6845->register_w( space, 0, pSnapshot[0x043+i] & 0xff ); |
| 2243 | m_crtc->address_w( space, 0, i ); |
| 2244 | m_crtc->register_w( space, 0, pSnapshot[0x043+i] & 0xff ); |
| 2262 | 2245 | } |
| 2263 | 2246 | |
| 2264 | | mc6845->address_w( space, 0, i ); |
| 2247 | m_crtc->address_w( space, 0, i ); |
| 2265 | 2248 | |
| 2266 | 2249 | /* upper rom selection */ |
| 2267 | | state->m_gate_array.upper_bank = pSnapshot[0x055]; |
| 2250 | m_gate_array.upper_bank = pSnapshot[0x055]; |
| 2268 | 2251 | |
| 2269 | 2252 | /* PPI */ |
| 2270 | | state->m_ppi->write(space, 3, pSnapshot[0x059] & 0x0ff); |
| 2253 | m_ppi->write(space, 3, pSnapshot[0x059] & 0x0ff); |
| 2271 | 2254 | |
| 2272 | | state->m_ppi->write(space, 0, pSnapshot[0x056] & 0x0ff); |
| 2273 | | state->m_ppi->write(space, 1, pSnapshot[0x057] & 0x0ff); |
| 2274 | | state->m_ppi->write(space, 2, pSnapshot[0x058] & 0x0ff); |
| 2255 | m_ppi->write(space, 0, pSnapshot[0x056] & 0x0ff); |
| 2256 | m_ppi->write(space, 1, pSnapshot[0x057] & 0x0ff); |
| 2257 | m_ppi->write(space, 2, pSnapshot[0x058] & 0x0ff); |
| 2275 | 2258 | |
| 2276 | 2259 | /* PSG */ |
| 2277 | 2260 | for (i=0; i<16; i++) |
| 2278 | 2261 | { |
| 2279 | | ay8910_address_w(ay8910, space, 0, i); |
| 2280 | | ay8910_data_w(ay8910, space, 0, pSnapshot[0x05b + i] & 0x0ff); |
| 2262 | ay8910_address_w(m_ay, space, 0, i); |
| 2263 | ay8910_data_w(m_ay, space, 0, pSnapshot[0x05b + i] & 0x0ff); |
| 2281 | 2264 | } |
| 2282 | 2265 | |
| 2283 | | ay8910_address_w(ay8910, space, 0, pSnapshot[0x05a]); |
| 2266 | ay8910_address_w(m_ay, space, 0, pSnapshot[0x05a]); |
| 2284 | 2267 | |
| 2285 | 2268 | { |
| 2286 | 2269 | int MemSize; |
| r20956 | r20957 | |
| 2297 | 2280 | MemorySize = 64*1024; |
| 2298 | 2281 | } |
| 2299 | 2282 | |
| 2300 | | memcpy(state->m_ram->pointer(), &pSnapshot[0x0100], MemorySize); |
| 2283 | memcpy(m_ram->pointer(), &pSnapshot[0x0100], MemorySize); |
| 2301 | 2284 | } |
| 2302 | | amstrad_rethinkMemory(machine); |
| 2285 | amstrad_rethinkMemory(); |
| 2303 | 2286 | } |
| 2304 | 2287 | |
| 2305 | 2288 | |
| r20956 | r20957 | |
| 2307 | 2290 | All hardware is reset and the firmware is completely initialized |
| 2308 | 2291 | Once all tables and jumpblocks have been set up, |
| 2309 | 2292 | control is passed to the default entry in rom 0*/ |
| 2310 | | static void amstrad_reset_machine(running_machine &machine) |
| 2293 | void amstrad_state::amstrad_reset_machine() |
| 2311 | 2294 | { |
| 2312 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 2313 | 2295 | /* enable lower rom (OS rom) */ |
| 2314 | | amstrad_GateArray_write(machine, 0x089); |
| 2296 | amstrad_GateArray_write(0x089); |
| 2315 | 2297 | |
| 2316 | 2298 | /* set ram config 0 */ |
| 2317 | | amstrad_GateArray_write(machine, 0x0c0); |
| 2299 | amstrad_GateArray_write(0x0c0); |
| 2318 | 2300 | |
| 2319 | 2301 | // Get manufacturer name and TV refresh rate from PCB link (dipswitch for mess emulation) |
| 2320 | | state->m_ppi_port_inputs[amstrad_ppi_PortB] = (((machine.root_device().ioport("solder_links")->read()&MANUFACTURER_NAME)<<1) | (machine.root_device().ioport("solder_links")->read()&TV_REFRESH_RATE)); |
| 2302 | m_ppi_port_inputs[amstrad_ppi_PortB] = (((m_io_solder_links->read()&MANUFACTURER_NAME)<<1) | (m_io_solder_links->read()&TV_REFRESH_RATE)); |
| 2321 | 2303 | |
| 2322 | | if ( state->m_system_type == SYSTEM_PLUS || state->m_system_type == SYSTEM_GX4000 ) |
| 2323 | | memset(state->m_asic.ram,0,16384); // clear ASIC RAM |
| 2304 | if ( m_system_type == SYSTEM_PLUS || m_system_type == SYSTEM_GX4000 ) |
| 2305 | { |
| 2306 | memset(m_asic.ram,0,16384); // clear ASIC RAM |
| 2307 | } |
| 2324 | 2308 | } |
| 2325 | 2309 | |
| 2326 | 2310 | |
| 2327 | 2311 | /*------------------ |
| 2328 | 2312 | - Rethink Memory - |
| 2329 | 2313 | ------------------*/ |
| 2330 | | static void amstrad_rethinkMemory(running_machine &machine) |
| 2314 | void amstrad_state::amstrad_rethinkMemory() |
| 2331 | 2315 | { |
| 2332 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 2333 | 2316 | cpc_multiface2_device* mface2; |
| 2334 | 2317 | /* the following is used for banked memory read/writes and for setting up |
| 2335 | 2318 | * opcode and opcode argument reads */ |
| 2336 | 2319 | |
| 2337 | 2320 | /* bank 0 - 0x0000..0x03fff */ |
| 2338 | | amstrad_setLowerRom(machine); |
| 2321 | amstrad_setLowerRom(); |
| 2339 | 2322 | |
| 2340 | 2323 | /* bank 1 - 0x04000..0x07fff */ |
| 2341 | | if ( state->m_system_type == SYSTEM_CPC || state->m_system_type == SYSTEM_ALESTE || state->m_asic.enabled == 0 ) |
| 2324 | if ( m_system_type == SYSTEM_CPC || m_system_type == SYSTEM_ALESTE || m_asic.enabled == 0 ) |
| 2342 | 2325 | { |
| 2343 | | if(state->m_aleste_mode & 0x04) |
| 2326 | if(m_aleste_mode & 0x04) |
| 2344 | 2327 | { |
| 2345 | | state->membank("bank3")->set_base(state->m_Aleste_RamBanks[1]); |
| 2346 | | state->membank("bank4")->set_base(state->m_Aleste_RamBanks[1]+0x2000); |
| 2328 | m_bank3->set_base(m_Aleste_RamBanks[1]); |
| 2329 | m_bank4->set_base(m_Aleste_RamBanks[1]+0x2000); |
| 2347 | 2330 | /* bank 2 - 0x08000..0x0bfff */ |
| 2348 | | state->membank("bank5")->set_base(state->m_Aleste_RamBanks[2]); |
| 2349 | | state->membank("bank6")->set_base(state->m_Aleste_RamBanks[2]+0x2000); |
| 2331 | m_bank5->set_base(m_Aleste_RamBanks[2]); |
| 2332 | m_bank6->set_base(m_Aleste_RamBanks[2]+0x2000); |
| 2350 | 2333 | } |
| 2351 | 2334 | else |
| 2352 | 2335 | { |
| 2353 | | state->membank("bank3")->set_base(state->m_AmstradCPC_RamBanks[1]); |
| 2354 | | state->membank("bank4")->set_base(state->m_AmstradCPC_RamBanks[1]+0x2000); |
| 2336 | m_bank3->set_base(m_AmstradCPC_RamBanks[1]); |
| 2337 | m_bank4->set_base(m_AmstradCPC_RamBanks[1]+0x2000); |
| 2355 | 2338 | /* bank 2 - 0x08000..0x0bfff */ |
| 2356 | | state->membank("bank5")->set_base(state->m_AmstradCPC_RamBanks[2]); |
| 2357 | | state->membank("bank6")->set_base(state->m_AmstradCPC_RamBanks[2]+0x2000); |
| 2339 | m_bank5->set_base(m_AmstradCPC_RamBanks[2]); |
| 2340 | m_bank6->set_base(m_AmstradCPC_RamBanks[2]+0x2000); |
| 2358 | 2341 | } |
| 2359 | 2342 | } |
| 2360 | 2343 | else |
| 2361 | | amstrad_setLowerRom(machine); |
| 2344 | { |
| 2345 | amstrad_setLowerRom(); |
| 2346 | } |
| 2362 | 2347 | |
| 2363 | 2348 | /* bank 3 - 0x0c000..0x0ffff */ |
| 2364 | | amstrad_setUpperRom(machine); |
| 2349 | amstrad_setUpperRom(); |
| 2365 | 2350 | |
| 2366 | 2351 | /* other banks */ |
| 2367 | | if(state->m_aleste_mode & 0x04) |
| 2352 | if(m_aleste_mode & 0x04) |
| 2368 | 2353 | { |
| 2369 | | state->membank("bank9")->set_base(state->m_Aleste_RamBanks[0]); |
| 2370 | | state->membank("bank10")->set_base(state->m_Aleste_RamBanks[0]+0x2000); |
| 2371 | | state->membank("bank11")->set_base(state->m_Aleste_RamBanks[1]); |
| 2372 | | state->membank("bank12")->set_base(state->m_Aleste_RamBanks[1]+0x2000); |
| 2373 | | state->membank("bank13")->set_base(state->m_Aleste_RamBanks[2]); |
| 2374 | | state->membank("bank14")->set_base(state->m_Aleste_RamBanks[2]+0x2000); |
| 2375 | | state->membank("bank15")->set_base(state->m_Aleste_RamBanks[3]); |
| 2376 | | state->membank("bank16")->set_base(state->m_Aleste_RamBanks[3]+0x2000); |
| 2354 | m_bank9->set_base(m_Aleste_RamBanks[0]); |
| 2355 | m_bank10->set_base(m_Aleste_RamBanks[0]+0x2000); |
| 2356 | m_bank11->set_base(m_Aleste_RamBanks[1]); |
| 2357 | m_bank12->set_base(m_Aleste_RamBanks[1]+0x2000); |
| 2358 | m_bank13->set_base(m_Aleste_RamBanks[2]); |
| 2359 | m_bank14->set_base(m_Aleste_RamBanks[2]+0x2000); |
| 2360 | m_bank15->set_base(m_Aleste_RamBanks[3]); |
| 2361 | m_bank16->set_base(m_Aleste_RamBanks[3]+0x2000); |
| 2377 | 2362 | } |
| 2378 | 2363 | else |
| 2379 | 2364 | { |
| 2380 | | state->membank("bank9")->set_base(state->m_AmstradCPC_RamBanks[0]); |
| 2381 | | state->membank("bank10")->set_base(state->m_AmstradCPC_RamBanks[0]+0x2000); |
| 2382 | | state->membank("bank11")->set_base(state->m_AmstradCPC_RamBanks[1]); |
| 2383 | | state->membank("bank12")->set_base(state->m_AmstradCPC_RamBanks[1]+0x2000); |
| 2384 | | state->membank("bank13")->set_base(state->m_AmstradCPC_RamBanks[2]); |
| 2385 | | state->membank("bank14")->set_base(state->m_AmstradCPC_RamBanks[2]+0x2000); |
| 2386 | | state->membank("bank15")->set_base(state->m_AmstradCPC_RamBanks[3]); |
| 2387 | | state->membank("bank16")->set_base(state->m_AmstradCPC_RamBanks[3]+0x2000); |
| 2365 | m_bank9->set_base(m_AmstradCPC_RamBanks[0]); |
| 2366 | m_bank10->set_base(m_AmstradCPC_RamBanks[0]+0x2000); |
| 2367 | m_bank11->set_base(m_AmstradCPC_RamBanks[1]); |
| 2368 | m_bank12->set_base(m_AmstradCPC_RamBanks[1]+0x2000); |
| 2369 | m_bank13->set_base(m_AmstradCPC_RamBanks[2]); |
| 2370 | m_bank14->set_base(m_AmstradCPC_RamBanks[2]+0x2000); |
| 2371 | m_bank15->set_base(m_AmstradCPC_RamBanks[3]); |
| 2372 | m_bank16->set_base(m_AmstradCPC_RamBanks[3]+0x2000); |
| 2388 | 2373 | } |
| 2389 | 2374 | |
| 2390 | 2375 | /* multiface hardware enabled? */ |
| 2391 | | mface2 = dynamic_cast<cpc_multiface2_device*>(get_expansion_device(machine,"multiface2")); |
| 2376 | mface2 = dynamic_cast<cpc_multiface2_device*>(get_expansion_device(machine(),"multiface2")); |
| 2392 | 2377 | if(mface2 != NULL) |
| 2393 | 2378 | { |
| 2394 | 2379 | if (mface2->multiface_hardware_enabled()) |
| 2395 | 2380 | { |
| 2396 | | if((state->m_gate_array.mrer & 0x04) == 0) |
| 2381 | if((m_gate_array.mrer & 0x04) == 0) |
| 2382 | { |
| 2397 | 2383 | mface2->multiface_rethink_memory(); |
| 2384 | } |
| 2398 | 2385 | } |
| 2399 | 2386 | } |
| 2400 | 2387 | } |
| 2401 | 2388 | |
| 2402 | 2389 | |
| 2403 | | static void kccomp_reset_machine(running_machine &machine) |
| 2390 | void amstrad_state::kccomp_reset_machine() |
| 2404 | 2391 | { |
| 2405 | 2392 | /* enable lower rom (OS rom) */ |
| 2406 | | amstrad_GateArray_write(machine, 0x089); |
| 2393 | amstrad_GateArray_write(0x089); |
| 2407 | 2394 | |
| 2408 | 2395 | /* set ram config 0 */ |
| 2409 | | amstrad_GateArray_write(machine, 0x0c0); |
| 2396 | amstrad_GateArray_write(0x0c0); |
| 2410 | 2397 | } |
| 2411 | 2398 | |
| 2412 | 2399 | |
| r20956 | r20957 | |
| 2447 | 2434 | 1 1 | Select PSG register. When set, the PSG will take the data at PPI Port A and select a register |
| 2448 | 2435 | */ |
| 2449 | 2436 | /* PSG function selected */ |
| 2450 | | static void update_psg(running_machine &machine) |
| 2437 | void amstrad_state::update_psg() |
| 2451 | 2438 | { |
| 2452 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 2453 | | address_space &space = state->m_maincpu->space(AS_PROGRAM); |
| 2454 | | device_t *ay8910 = state->m_ay; |
| 2455 | | mc146818_device *rtc = state->m_rtc; |
| 2439 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 2456 | 2440 | |
| 2457 | | if(state->m_aleste_mode & 0x20) // RTC selected |
| 2441 | if(m_aleste_mode & 0x20) // RTC selected |
| 2458 | 2442 | { |
| 2459 | | switch(state->m_aleste_rtc_function) |
| 2443 | switch(m_aleste_rtc_function) |
| 2460 | 2444 | { |
| 2461 | 2445 | case 0x02: // AS |
| 2462 | | rtc->write(space, 0,state->m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2446 | m_rtc->write(space, 0,m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2463 | 2447 | break; |
| 2464 | 2448 | case 0x04: // DS write |
| 2465 | | rtc->write(space, 1,state->m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2449 | m_rtc->write(space, 1,m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2466 | 2450 | break; |
| 2467 | 2451 | case 0x05: // DS read |
| 2468 | | state->m_ppi_port_inputs[amstrad_ppi_PortA] = rtc->read(space, 1); |
| 2452 | m_ppi_port_inputs[amstrad_ppi_PortA] = m_rtc->read(space, 1); |
| 2469 | 2453 | break; |
| 2470 | 2454 | } |
| 2471 | 2455 | return; |
| 2472 | 2456 | } |
| 2473 | | switch (state->m_Psg_FunctionSelected) |
| 2457 | switch (m_Psg_FunctionSelected) |
| 2474 | 2458 | { |
| 2475 | 2459 | case 0: |
| 2476 | 2460 | {/* Inactive */ |
| 2477 | 2461 | } break; |
| 2478 | 2462 | case 1: |
| 2479 | 2463 | {/* b6 = 1 ? : Read from selected PSG register and make the register data available to PPI Port A */ |
| 2480 | | state->m_ppi_port_inputs[amstrad_ppi_PortA] = ay8910_r(ay8910, space, 0); |
| 2464 | m_ppi_port_inputs[amstrad_ppi_PortA] = ay8910_r(m_ay, space, 0); |
| 2481 | 2465 | } |
| 2482 | 2466 | break; |
| 2483 | 2467 | case 2: |
| 2484 | 2468 | {/* b7 = 1 ? : Write to selected PSG register and write data to PPI Port A */ |
| 2485 | | ay8910_data_w(ay8910, space, 0, state->m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2469 | ay8910_data_w(m_ay, space, 0, m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2486 | 2470 | } |
| 2487 | 2471 | break; |
| 2488 | 2472 | case 3: |
| 2489 | 2473 | {/* b6 and b7 = 1 ? : The register will now be selected and the user can read from or write to it. The register will remain selected until another is chosen.*/ |
| 2490 | | ay8910_address_w(ay8910, space, 0, state->m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2491 | | state->m_prev_reg = state->m_ppi_port_outputs[amstrad_ppi_PortA]; |
| 2474 | ay8910_address_w(m_ay, space, 0, m_ppi_port_outputs[amstrad_ppi_PortA]); |
| 2475 | m_prev_reg = m_ppi_port_outputs[amstrad_ppi_PortA]; |
| 2492 | 2476 | } |
| 2493 | 2477 | break; |
| 2494 | 2478 | default: |
| r20956 | r20957 | |
| 2501 | 2485 | /* Read/Write 8255 PPI port A (connected to AY-3-8912 databus) */ |
| 2502 | 2486 | READ8_MEMBER(amstrad_state::amstrad_ppi_porta_r) |
| 2503 | 2487 | { |
| 2504 | | update_psg(machine()); |
| 2488 | update_psg(); |
| 2505 | 2489 | return m_ppi_port_inputs[amstrad_ppi_PortA]; |
| 2506 | 2490 | } |
| 2507 | 2491 | |
| r20956 | r20957 | |
| 2509 | 2493 | WRITE8_MEMBER(amstrad_state::amstrad_ppi_porta_w) |
| 2510 | 2494 | { |
| 2511 | 2495 | m_ppi_port_outputs[amstrad_ppi_PortA] = data; |
| 2512 | | update_psg(machine()); |
| 2496 | update_psg(); |
| 2513 | 2497 | } |
| 2514 | 2498 | |
| 2515 | 2499 | |
| r20956 | r20957 | |
| 2553 | 2537 | /* Set b6 with Parallel/Printer port ready */ |
| 2554 | 2538 | if(m_system_type != SYSTEM_GX4000) |
| 2555 | 2539 | { |
| 2556 | | centronics_device *printer = m_centronics; |
| 2557 | | data |= printer->busy_r() << 6; |
| 2540 | data |= m_centronics->busy_r() << 6; |
| 2558 | 2541 | } |
| 2559 | 2542 | /* Set b4-b1 50Hz/60Hz state and manufacturer name defined by links on PCB */ |
| 2560 | 2543 | data |= (m_ppi_port_inputs[amstrad_ppi_PortB] & 0x1e); |
| r20956 | r20957 | |
| 2609 | 2592 | m_aleste_rtc_function = data & 0x07; |
| 2610 | 2593 | |
| 2611 | 2594 | /* Perform PSG function */ |
| 2612 | | update_psg(machine()); |
| 2595 | update_psg(); |
| 2613 | 2596 | |
| 2614 | 2597 | /* b5 Cassette Write data */ |
| 2615 | 2598 | if(m_system_type != SYSTEM_GX4000) |
| r20956 | r20957 | |
| 2644 | 2627 | READ8_MEMBER(amstrad_state::amstrad_psg_porta_read) |
| 2645 | 2628 | { |
| 2646 | 2629 | /* Read CPC Keyboard |
| 2647 | | If keyboard matrix line 11-14 are selected, the byte is always &ff. |
| 2630 | If keyboard matrix line 11-15 are selected, the byte is always &ff. |
| 2648 | 2631 | After testing on a real CPC, it is found that these never change, they always return &FF. */ |
| 2649 | 2632 | |
| 2650 | | static const char *const keynames[] = { |
| 2651 | | "keyboard_row_0", "keyboard_row_1", "keyboard_row_2", "keyboard_row_3", "keyboard_row_4", |
| 2652 | | "keyboard_row_5", "keyboard_row_6", "keyboard_row_7", "keyboard_row_8", "keyboard_row_9", |
| 2653 | | "keyboard_row_10" |
| 2633 | ioport_port *keyrow[] = { |
| 2634 | m_io_keyboard_row_0, m_io_keyboard_row_1, m_io_keyboard_row_2, m_io_keyboard_row_3, m_io_keyboard_row_4, |
| 2635 | m_io_keyboard_row_5, m_io_keyboard_row_6, m_io_keyboard_row_7, m_io_keyboard_row_8, m_io_keyboard_row_9, |
| 2636 | m_io_keyboard_row_10 |
| 2654 | 2637 | }; |
| 2655 | 2638 | |
| 2656 | 2639 | if ( ( m_ppi_port_outputs[amstrad_ppi_PortC] & 0x0F ) > 10) |
| r20956 | r20957 | |
| 2662 | 2645 | if(m_aleste_mode == 0x08 && ( m_ppi_port_outputs[amstrad_ppi_PortC] & 0x0F ) == 10) |
| 2663 | 2646 | return 0xff; |
| 2664 | 2647 | |
| 2665 | | return machine().root_device().ioport(keynames[m_ppi_port_outputs[amstrad_ppi_PortC] & 0x0F])->read_safe(0) & 0xFF; |
| 2648 | if (keyrow[m_ppi_port_outputs[amstrad_ppi_PortC] & 0x0F]) |
| 2649 | { |
| 2650 | return keyrow[m_ppi_port_outputs[amstrad_ppi_PortC] & 0x0F]->read_safe(0) & 0xFF; |
| 2651 | } |
| 2652 | return 0xFF; |
| 2666 | 2653 | } |
| 2667 | 2654 | } |
| 2668 | 2655 | |
| r20956 | r20957 | |
| 2679 | 2666 | m_asic.ram[0x2c0f] &= ~0x80; // not a raster interrupt, so this bit is reset |
| 2680 | 2667 | return (m_asic.ram[0x2805] & 0xf8) | m_plus_irq_cause; |
| 2681 | 2668 | } |
| 2682 | | machine().device("maincpu")->execute().set_input_line(0, CLEAR_LINE); |
| 2669 | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 2683 | 2670 | m_gate_array.hsync_counter &= 0x1F; |
| 2684 | 2671 | if ( m_asic.enabled ) |
| 2685 | 2672 | { |
| r20956 | r20957 | |
| 2816 | 2803 | 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0 |
| 2817 | 2804 | }; |
| 2818 | 2805 | |
| 2819 | | static void amstrad_common_init(running_machine &machine) |
| 2806 | void amstrad_state::amstrad_common_init() |
| 2820 | 2807 | { |
| 2821 | | amstrad_state *state = machine.driver_data<amstrad_state>(); |
| 2822 | | address_space &space = state->m_maincpu->space(AS_PROGRAM); |
| 2808 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 2823 | 2809 | device_t* romexp; |
| 2824 | 2810 | rom_image_device* romimage; |
| 2825 | 2811 | char str[20]; |
| 2826 | 2812 | int x; |
| 2827 | 2813 | |
| 2828 | | state->m_aleste_mode = 0; |
| 2814 | m_aleste_mode = 0; |
| 2829 | 2815 | |
| 2830 | | state->m_gate_array.mrer = 0; |
| 2831 | | state->m_gate_array.vsync = 0; |
| 2832 | | state->m_gate_array.hsync = 0; |
| 2833 | | state->m_GateArray_RamConfiguration = 0; |
| 2834 | | state->m_gate_array.hsync_counter = 2; |
| 2816 | m_gate_array.mrer = 0; |
| 2817 | m_gate_array.vsync = 0; |
| 2818 | m_gate_array.hsync = 0; |
| 2819 | m_GateArray_RamConfiguration = 0; |
| 2820 | m_gate_array.hsync_counter = 2; |
| 2835 | 2821 | |
| 2836 | 2822 | space.install_read_bank(0x0000, 0x1fff, "bank1"); |
| 2837 | 2823 | space.install_read_bank(0x2000, 0x3fff, "bank2"); |
| r20956 | r20957 | |
| 2858 | 2844 | space.install_write_bank(0xe000, 0xffff, "bank16"); |
| 2859 | 2845 | |
| 2860 | 2846 | /* Set up ROMs, if we have an expansion device connected */ |
| 2861 | | romexp = get_expansion_device(machine,"rom"); |
| 2847 | romexp = get_expansion_device(machine(),"rom"); |
| 2862 | 2848 | if(romexp) |
| 2863 | 2849 | { |
| 2864 | 2850 | for(x=0;x<6;x++) |
| r20956 | r20957 | |
| 2867 | 2853 | romimage = romexp->subdevice<rom_image_device>(str); |
| 2868 | 2854 | if(romimage->base() != NULL) |
| 2869 | 2855 | { |
| 2870 | | state->m_Amstrad_ROM_Table[x+1] = romimage->base(); |
| 2856 | m_Amstrad_ROM_Table[x+1] = romimage->base(); |
| 2871 | 2857 | } |
| 2872 | 2858 | } |
| 2873 | 2859 | } |
| 2874 | 2860 | |
| 2875 | | state->m_maincpu->reset(); |
| 2876 | | if ( state->m_system_type == SYSTEM_CPC || state->m_system_type == SYSTEM_ALESTE ) |
| 2877 | | state->m_maincpu->set_input_line_vector(0, 0xff); |
| 2861 | m_maincpu->reset(); |
| 2862 | if ( m_system_type == SYSTEM_CPC || m_system_type == SYSTEM_ALESTE ) |
| 2863 | m_maincpu->set_input_line_vector(0, 0xff); |
| 2878 | 2864 | else |
| 2879 | | state->m_maincpu->set_input_line_vector(0, 0x00); |
| 2865 | m_maincpu->set_input_line_vector(0, 0x00); |
| 2880 | 2866 | |
| 2881 | 2867 | /* The opcode timing in the Amstrad is different to the opcode |
| 2882 | 2868 | timing in the core for the Z80 CPU. |
| r20956 | r20957 | |
| 2888 | 2874 | |
| 2889 | 2875 | /* Using the cool code Juergen has provided, I will override |
| 2890 | 2876 | the timing tables with the values for the amstrad */ |
| 2891 | | z80_set_cycle_tables(state->m_maincpu, |
| 2877 | z80_set_cycle_tables(m_maincpu, |
| 2892 | 2878 | (const UINT8*)amstrad_cycle_table_op, |
| 2893 | 2879 | (const UINT8*)amstrad_cycle_table_cb, |
| 2894 | 2880 | (const UINT8*)amstrad_cycle_table_ed, |
| r20956 | r20957 | |
| 2897 | 2883 | (const UINT8*)amstrad_cycle_table_ex); |
| 2898 | 2884 | |
| 2899 | 2885 | /* Juergen is a cool dude! */ |
| 2900 | | state->m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(amstrad_state::amstrad_cpu_acknowledge_int),state)); |
| 2886 | m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(amstrad_state::amstrad_cpu_acknowledge_int),this)); |
| 2901 | 2887 | } |
| 2902 | 2888 | |
| 2903 | 2889 | TIMER_CALLBACK_MEMBER(amstrad_state::cb_set_resolution) |
| 2904 | 2890 | { |
| 2905 | | // screen_device *screen = downcast<screen_device *>(m_screen); |
| 2906 | 2891 | rectangle visarea; |
| 2907 | 2892 | attoseconds_t refresh; |
| 2908 | 2893 | int height; |
| 2909 | 2894 | |
| 2910 | | if ( machine().root_device().ioport( "solder_links" )->read() & 0x10 ) |
| 2895 | if ( m_io_solder_links->read() & 0x10 ) |
| 2911 | 2896 | { |
| 2912 | 2897 | /* PAL */ |
| 2913 | 2898 | visarea.set(0, 64 + 640 + 64 - 1, 34, 34 + 15 + 242 + 15 - 1); |
| r20956 | r20957 | |
| 2933 | 2918 | MACHINE_RESET_MEMBER(amstrad_state,amstrad) |
| 2934 | 2919 | { |
| 2935 | 2920 | int i; |
| 2936 | | UINT8 *rom = memregion("maincpu")->base(); |
| 2921 | UINT8 *rom = m_region_maincpu->base(); |
| 2937 | 2922 | |
| 2938 | 2923 | for (i=0; i<256; i++) |
| 2939 | 2924 | { |
| r20956 | r20957 | |
| 2941 | 2926 | } |
| 2942 | 2927 | |
| 2943 | 2928 | m_Amstrad_ROM_Table[7] = &rom[0x018000]; |
| 2944 | | amstrad_common_init(machine()); |
| 2945 | | amstrad_reset_machine(machine()); |
| 2929 | amstrad_common_init(); |
| 2930 | amstrad_reset_machine(); |
| 2946 | 2931 | // amstrad_init_palette(machine()); |
| 2947 | 2932 | |
| 2948 | 2933 | m_gate_array.de = 0; |
| r20956 | r20957 | |
| 2956 | 2941 | |
| 2957 | 2942 | MACHINE_START_MEMBER(amstrad_state,plus) |
| 2958 | 2943 | { |
| 2959 | | m_asic.ram = memregion("user1")->base(); // 16kB RAM for ASIC, memory-mapped registers. |
| 2944 | m_asic.ram = m_region_user1->base(); // 16kB RAM for ASIC, memory-mapped registers. |
| 2960 | 2945 | m_system_type = SYSTEM_PLUS; |
| 2961 | 2946 | } |
| 2962 | 2947 | |
| r20956 | r20957 | |
| 2965 | 2950 | { |
| 2966 | 2951 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 2967 | 2952 | int i; |
| 2968 | | UINT8 *rom = memregion("maincpu")->base(); |
| 2953 | UINT8 *rom = m_region_maincpu->base(); |
| 2969 | 2954 | |
| 2970 | 2955 | for (i=0; i<128; i++) // fill ROM table |
| 2971 | 2956 | { |
| r20956 | r20957 | |
| 2990 | 2975 | m_asic.dma_clear = 1; // by default, DMA interrupts must be cleared by writing to the DSCR (&6c0f) |
| 2991 | 2976 | m_plus_irq_cause = 6; |
| 2992 | 2977 | |
| 2993 | | amstrad_common_init(machine()); |
| 2994 | | amstrad_reset_machine(machine()); |
| 2978 | amstrad_common_init(); |
| 2979 | amstrad_reset_machine(); |
| 2995 | 2980 | m_asic.ram[0x2805] = 0x01; // interrupt vector is undefined at startup, except that bit 0 is always 1. |
| 2996 | | AmstradCPC_GA_SetRamConfiguration(machine()); |
| 2997 | | amstrad_GateArray_write(machine(), 0x081); // Epyx World of Sports requires upper ROM to be enabled by default |
| 2981 | AmstradCPC_GA_SetRamConfiguration(); |
| 2982 | amstrad_GateArray_write(0x081); // Epyx World of Sports requires upper ROM to be enabled by default |
| 2998 | 2983 | |
| 2999 | 2984 | space.install_read_handler(0x4000, 0x5fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_4000_r),this)); |
| 3000 | 2985 | space.install_read_handler(0x6000, 0x7fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_6000_r),this)); |
| r20956 | r20957 | |
| 3007 | 2992 | |
| 3008 | 2993 | MACHINE_START_MEMBER(amstrad_state,gx4000) |
| 3009 | 2994 | { |
| 3010 | | m_asic.ram = memregion("user1")->base(); // 16kB RAM for ASIC, memory-mapped registers. |
| 2995 | m_asic.ram = m_region_user1->base(); // 16kB RAM for ASIC, memory-mapped registers. |
| 3011 | 2996 | m_system_type = SYSTEM_GX4000; |
| 3012 | 2997 | } |
| 3013 | 2998 | |
| r20956 | r20957 | |
| 3015 | 3000 | { |
| 3016 | 3001 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 3017 | 3002 | int i; |
| 3018 | | UINT8 *rom = memregion("maincpu")->base(); |
| 3003 | UINT8 *rom = m_region_maincpu->base(); |
| 3019 | 3004 | |
| 3020 | 3005 | for (i=0; i<128; i++) // fill ROM table |
| 3021 | 3006 | { |
| r20956 | r20957 | |
| 3040 | 3025 | m_asic.dma_clear = 1; // by default, DMA interrupts must be cleared by writing to the DSCR (&6c0f) |
| 3041 | 3026 | m_plus_irq_cause = 6; |
| 3042 | 3027 | |
| 3043 | | amstrad_common_init(machine()); |
| 3044 | | amstrad_reset_machine(machine()); |
| 3028 | amstrad_common_init(); |
| 3029 | amstrad_reset_machine(); |
| 3045 | 3030 | m_asic.ram[0x2805] = 0x01; // interrupt vector is undefined at startup, except that bit 0 is always 1. |
| 3046 | | AmstradCPC_GA_SetRamConfiguration(machine()); |
| 3047 | | amstrad_GateArray_write(machine(), 0x081); // Epyx World of Sports requires upper ROM to be enabled by default |
| 3031 | AmstradCPC_GA_SetRamConfiguration(); |
| 3032 | amstrad_GateArray_write(0x081); // Epyx World of Sports requires upper ROM to be enabled by default |
| 3048 | 3033 | // multiface_init(); |
| 3049 | 3034 | space.install_read_handler(0x4000, 0x5fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_4000_r),this)); |
| 3050 | 3035 | space.install_read_handler(0x6000, 0x7fff, read8_delegate(FUNC(amstrad_state::amstrad_plus_asic_6000_r),this)); |
| r20956 | r20957 | |
| 3063 | 3048 | MACHINE_RESET_MEMBER(amstrad_state,kccomp) |
| 3064 | 3049 | { |
| 3065 | 3050 | int i; |
| 3066 | | UINT8 *rom = memregion("maincpu")->base(); |
| 3051 | UINT8 *rom = m_region_maincpu->base(); |
| 3067 | 3052 | |
| 3068 | 3053 | for (i=0; i<256; i++) |
| 3069 | 3054 | { |
| 3070 | 3055 | m_Amstrad_ROM_Table[i] = &rom[0x014000]; |
| 3071 | 3056 | } |
| 3072 | 3057 | |
| 3073 | | amstrad_common_init(machine()); |
| 3074 | | kccomp_reset_machine(machine()); |
| 3058 | amstrad_common_init(); |
| 3059 | kccomp_reset_machine(); |
| 3075 | 3060 | |
| 3076 | 3061 | /* bit 1 = /TEST. When 0, KC compact will enter data transfer |
| 3077 | 3062 | sequence, where another system using the expansion port signals |
| r20956 | r20957 | |
| 3091 | 3076 | MACHINE_RESET_MEMBER(amstrad_state,aleste) |
| 3092 | 3077 | { |
| 3093 | 3078 | int i; |
| 3094 | | UINT8 *rom = memregion("maincpu")->base(); |
| 3079 | UINT8 *rom = m_region_maincpu->base(); |
| 3095 | 3080 | |
| 3096 | 3081 | for (i=0; i<256; i++) |
| 3097 | 3082 | { |
| r20956 | r20957 | |
| 3100 | 3085 | |
| 3101 | 3086 | m_Amstrad_ROM_Table[3] = &rom[0x01c000]; // MSX-DOS / BIOS |
| 3102 | 3087 | m_Amstrad_ROM_Table[7] = &rom[0x018000]; // AMSDOS |
| 3103 | | amstrad_common_init(machine()); |
| 3104 | | amstrad_reset_machine(machine()); |
| 3088 | amstrad_common_init(); |
| 3089 | amstrad_reset_machine(); |
| 3105 | 3090 | |
| 3106 | 3091 | machine().scheduler().timer_set( attotime::zero, timer_expired_delegate(FUNC(amstrad_state::cb_set_resolution),this)); |
| 3107 | 3092 | } |
| r20956 | r20957 | |
| 3129 | 3114 | return IMAGE_INIT_FAIL; |
| 3130 | 3115 | } |
| 3131 | 3116 | |
| 3132 | | amstrad_handle_snapshot(image.device().machine(), snapshot); |
| 3117 | image.device().machine().driver_data<amstrad_state>()->amstrad_handle_snapshot(snapshot); |
| 3133 | 3118 | free(snapshot); |
| 3134 | 3119 | return IMAGE_INIT_PASS; |
| 3135 | 3120 | } |
| r20956 | r20957 | |
| 3152 | 3137 | int chunksize; // chunk length, calcaulated from the above |
| 3153 | 3138 | int ramblock; // 16k RAM block chunk is to be loaded in to |
| 3154 | 3139 | unsigned int bytes_to_read; // total bytes to read, as mame_feof doesn't react to EOF without trying to go past it. |
| 3155 | | unsigned char* mem = image.device().machine().root_device().memregion("maincpu")->base(); |
| 3140 | unsigned char* mem = m_region_maincpu->base(); |
| 3156 | 3141 | |
| 3157 | 3142 | if (image.software_entry() == NULL) |
| 3158 | 3143 | { |
| 3159 | 3144 | size = image.length(); |
| 3160 | | temp_copy = auto_alloc_array(image.device().machine(), UINT8, size); |
| 3145 | temp_copy = auto_alloc_array(machine(), UINT8, size); |
| 3161 | 3146 | if (image.fread(temp_copy, size) != size) |
| 3162 | 3147 | { |
| 3163 | 3148 | logerror("IMG: failed to read from cart image\n"); |
| 3164 | | auto_free(image.device().machine(), temp_copy); |
| 3149 | auto_free(machine(), temp_copy); |
| 3165 | 3150 | return IMAGE_INIT_FAIL; |
| 3166 | 3151 | } |
| 3167 | 3152 | } |
| 3168 | 3153 | else |
| 3169 | 3154 | { |
| 3170 | 3155 | size= image.get_software_region_length("rom"); |
| 3171 | | temp_copy = auto_alloc_array(image.device().machine(), UINT8, size); |
| 3156 | temp_copy = auto_alloc_array(machine(), UINT8, size); |
| 3172 | 3157 | memcpy(temp_copy, image.get_software_region("rom"), size); |
| 3173 | 3158 | } |
| 3174 | 3159 | |
| r20956 | r20957 | |
| 3190 | 3175 | if ((size - offset) < 0x4000) |
| 3191 | 3176 | { |
| 3192 | 3177 | logerror("BIN: block %i loaded is smaller than 16kB in size\n", offset / 0x4000); |
| 3193 | | auto_free(image.device().machine(), temp_copy); |
| 3178 | auto_free(machine(), temp_copy); |
| 3194 | 3179 | return IMAGE_INIT_FAIL; |
| 3195 | 3180 | } |
| 3196 | 3181 | offset += 0x4000; |
| r20956 | r20957 | |
| 3202 | 3187 | if (strncmp((char*)(header + 8), "AMS!", 4) != 0) |
| 3203 | 3188 | { |
| 3204 | 3189 | logerror("CPR: not an Amstrad CPC cartridge image\n"); |
| 3205 | | auto_free(image.device().machine(), temp_copy); |
| 3190 | auto_free(machine(), temp_copy); |
| 3206 | 3191 | return IMAGE_INIT_FAIL; |
| 3207 | 3192 | } |
| 3208 | 3193 | |
| r20956 | r20957 | |
| 3260 | 3245 | else // CPR carts in our softlist |
| 3261 | 3246 | { |
| 3262 | 3247 | logerror("Gamelist cart in RIFF format\n"); |
| 3263 | | auto_free(image.device().machine(), temp_copy); |
| 3248 | auto_free(machine(), temp_copy); |
| 3264 | 3249 | return IMAGE_INIT_FAIL; |
| 3265 | 3250 | } |
| 3266 | 3251 | |
| 3267 | | auto_free(image.device().machine(), temp_copy); |
| 3252 | auto_free(machine(), temp_copy); |
| 3268 | 3253 | return IMAGE_INIT_PASS; |
| 3269 | 3254 | } |