branches/code_cleanup/src/mame/machine/n64.cpp
| r250319 | r250320 | |
| 9 | 9 | #include "includes/n64.h" |
| 10 | 10 | #include "video/n64.h" |
| 11 | 11 | |
| 12 | | UINT32 *n64_sram; |
| 13 | | UINT32 *rdram; |
| 14 | | UINT32 *rsp_imem; |
| 15 | | UINT32 *rsp_dmem; |
| 16 | | |
| 17 | 12 | // device type definition |
| 18 | 13 | const device_type N64PERIPH = &device_creator<n64_periphs>; |
| 19 | 14 | |
| 20 | | |
| 21 | | |
| 22 | | |
| 23 | 15 | n64_periphs::n64_periphs(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 24 | 16 | : device_t(mconfig, N64PERIPH, "N64 Periphal Chips", tag, owner, clock, "n64_periphs", __FILE__) |
| 25 | 17 | , device_video_interface(mconfig, *this) |
| r250319 | r250320 | |
| 49 | 41 | void n64_periphs::reset_tick() |
| 50 | 42 | { |
| 51 | 43 | reset_timer->adjust(attotime::never); |
| 52 | | maincpu->reset(); |
| 53 | | maincpu->execute().set_input_line(INPUT_LINE_IRQ2, CLEAR_LINE); |
| 54 | | rspcpu->reset(); |
| 55 | | rspcpu->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 56 | | rspcpu->state().set_state_int(RSP_SR, rspcpu->state().state_int(RSP_SR) | RSP_STATUS_HALT); |
| 44 | m_vr4300->reset(); |
| 45 | m_vr4300->set_input_line(INPUT_LINE_IRQ2, CLEAR_LINE); |
| 46 | m_rsp->reset(); |
| 47 | m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 48 | m_rsp->set_state_int(RSP_SR, m_rsp->state_int(RSP_SR) | RSP_STATUS_HALT); |
| 57 | 49 | reset_held = false; |
| 58 | 50 | cic_status = 0; |
| 59 | 51 | memset(pif_ram, 0, sizeof(pif_ram)); |
| r250319 | r250320 | |
| 104 | 96 | reset_held = button; |
| 105 | 97 | if(!old_held && reset_held) |
| 106 | 98 | { |
| 107 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ2, ASSERT_LINE); |
| 99 | m_vr4300->set_input_line(INPUT_LINE_IRQ2, ASSERT_LINE); |
| 108 | 100 | } |
| 109 | 101 | else if(old_held && reset_held) |
| 110 | 102 | { |
| r250319 | r250320 | |
| 123 | 115 | si_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::si_dma_callback),this)); |
| 124 | 116 | vi_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::vi_scanline_callback),this)); |
| 125 | 117 | reset_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::reset_timer_callback),this)); |
| 118 | m_n64 = machine().driver_data<n64_state>(); |
| 126 | 119 | } |
| 127 | 120 | |
| 128 | 121 | void n64_periphs::device_reset() |
| 129 | 122 | { |
| 130 | 123 | UINT32 *cart = (UINT32*)machine().root_device().memregion("user2")->base(); |
| 131 | 124 | |
| 132 | | maincpu = machine().device("maincpu"); |
| 133 | | rspcpu = machine().device("rsp"); |
| 134 | | mem_map = &maincpu->memory().space(AS_PROGRAM); |
| 125 | m_vr4300 = machine().device<mips3_device>("maincpu"); |
| 126 | m_rsp = machine().device<rsp_device>("rsp"); |
| 127 | m_mem_map = &m_vr4300->space(AS_PROGRAM); |
| 135 | 128 | |
| 129 | m_rdram = m_n64->rdram(); |
| 130 | m_rsp_imem = m_n64->rsp_imem(); |
| 131 | m_rsp_dmem = m_n64->rsp_dmem(); |
| 132 | m_sram = m_n64->sram(); |
| 133 | |
| 136 | 134 | mi_version = 0x01010101; |
| 137 | 135 | mi_interrupt = 0; |
| 138 | 136 | mi_intr_mask = 0; |
| r250319 | r250320 | |
| 238 | 236 | pif_ram[0x26] = 0x3f; |
| 239 | 237 | pif_ram[0x27] = 0x3f; |
| 240 | 238 | cic_type=2; |
| 241 | | mem_map->write_dword(0x00000318, 0x800000); /* RDRAM Size */ |
| 239 | m_mem_map->write_dword(0x00000318, 0x800000); /* RDRAM Size */ |
| 242 | 240 | |
| 243 | 241 | if (boot_checksum == U64(0x00000000001ff230)) |
| 244 | 242 | { |
| r250319 | r250320 | |
| 274 | 272 | pif_ram[0x26] = 0x91; |
| 275 | 273 | pif_ram[0x27] = 0x3f; |
| 276 | 274 | cic_type=5; |
| 277 | | mem_map->write_dword(0x000003f0, 0x800000); |
| 275 | m_mem_map->write_dword(0x000003f0, 0x800000); |
| 278 | 276 | } |
| 279 | 277 | else if (boot_checksum == U64(0x000000d6d5de4ba0)) |
| 280 | 278 | { |
| r250319 | r250320 | |
| 329 | 327 | break; |
| 330 | 328 | |
| 331 | 329 | default: |
| 332 | | logerror("mi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, mem_map->device().safe_pc()); |
| 330 | logerror("mi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 333 | 331 | break; |
| 334 | 332 | } |
| 335 | 333 | |
| r250319 | r250320 | |
| 414 | 412 | } |
| 415 | 413 | |
| 416 | 414 | default: |
| 417 | | logerror("mi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 415 | logerror("mi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 418 | 416 | break; |
| 419 | 417 | } |
| 420 | 418 | } |
| r250319 | r250320 | |
| 428 | 426 | { |
| 429 | 427 | if (mi_intr_mask & mi_interrupt) |
| 430 | 428 | { |
| 431 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); |
| 429 | m_vr4300->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); |
| 432 | 430 | } |
| 433 | 431 | else |
| 434 | 432 | { |
| 435 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); |
| 433 | m_vr4300->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); |
| 436 | 434 | } |
| 437 | 435 | } |
| 438 | 436 | |
| r250319 | r250320 | |
| 529 | 527 | { |
| 530 | 528 | if(offset > 0x24/4) |
| 531 | 529 | { |
| 532 | | logerror("rdram_reg_r: %08X, %08X at %08X\n", offset, mem_mask, maincpu->safe_pc()); |
| 530 | logerror("rdram_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 533 | 531 | return 0; |
| 534 | 532 | } |
| 535 | 533 | return rdram_regs[offset]; |
| r250319 | r250320 | |
| 539 | 537 | { |
| 540 | 538 | if(offset > 0x24/4) |
| 541 | 539 | { |
| 542 | | logerror("rdram_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 540 | logerror("rdram_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 543 | 541 | return; |
| 544 | 542 | } |
| 545 | 543 | COMBINE_DATA(&rdram_regs[offset]); |
| r250319 | r250320 | |
| 570 | 568 | length = 0x1000 - (sp_mem_addr & 0xfff); |
| 571 | 569 | } |
| 572 | 570 | |
| 573 | | UINT32 *sp_mem[2] = { rsp_dmem, rsp_imem }; |
| 571 | UINT32 *sp_mem[2] = { m_rsp_dmem, m_rsp_imem }; |
| 574 | 572 | |
| 575 | 573 | int sp_mem_page = (sp_mem_addr >> 12) & 1; |
| 576 | 574 | if(direction == 0)// RDRAM -> I/DMEM |
| r250319 | r250320 | |
| 582 | 580 | |
| 583 | 581 | for(int i = 0; i < length / 4; i++) |
| 584 | 582 | { |
| 585 | | sp_mem[sp_mem_page][(dst + i) & 0x3ff] = rdram[src + i]; |
| 583 | sp_mem[sp_mem_page][(dst + i) & 0x3ff] = m_rdram[src + i]; |
| 586 | 584 | } |
| 587 | 585 | |
| 588 | 586 | sp_mem_addr += length; |
| r250319 | r250320 | |
| 600 | 598 | |
| 601 | 599 | for(int i = 0; i < length / 4; i++) |
| 602 | 600 | { |
| 603 | | rdram[dst + i] = sp_mem[sp_mem_page][(src + i) & 0x3ff]; |
| 601 | m_rdram[dst + i] = sp_mem[sp_mem_page][(src + i) & 0x3ff]; |
| 604 | 602 | } |
| 605 | 603 | |
| 606 | 604 | sp_mem_addr += length; |
| r250319 | r250320 | |
| 615 | 613 | { |
| 616 | 614 | if (data & 0x1) |
| 617 | 615 | { |
| 618 | | rspcpu->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 619 | | rspcpu->state().set_state_int(RSP_SR, rspcpu->state().state_int(RSP_SR) | RSP_STATUS_HALT); |
| 616 | m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 617 | m_rsp->set_state_int(RSP_SR, m_rsp->state_int(RSP_SR) | RSP_STATUS_HALT); |
| 620 | 618 | } |
| 621 | 619 | |
| 622 | 620 | if (data & 0x2) |
| 623 | 621 | { |
| 624 | | rspcpu->state().set_state_int(RSP_SR, rspcpu->state().state_int(RSP_SR) | RSP_STATUS_BROKE); |
| 622 | m_rsp->set_state_int(RSP_SR, m_rsp->state_int(RSP_SR) | RSP_STATUS_BROKE); |
| 625 | 623 | |
| 626 | | if (rspcpu->state().state_int(RSP_SR) & RSP_STATUS_INTR_BREAK) |
| 624 | if (m_rsp->state_int(RSP_SR) & RSP_STATUS_INTR_BREAK) |
| 627 | 625 | { |
| 628 | 626 | signal_rcp_interrupt(SP_INTERRUPT); |
| 629 | 627 | } |
| r250319 | r250320 | |
| 632 | 630 | |
| 633 | 631 | READ32_MEMBER(n64_periphs::sp_reg_r) |
| 634 | 632 | { |
| 635 | | UINT32 ret = 0; |
| 636 | 633 | switch (offset) |
| 637 | 634 | { |
| 638 | 635 | case 0x00/4: // SP_MEM_ADDR_REG |
| 639 | | ret = sp_mem_addr; |
| 640 | | break; |
| 636 | return sp_mem_addr; |
| 641 | 637 | |
| 642 | 638 | case 0x04/4: // SP_DRAM_ADDR_REG |
| 643 | | ret = sp_dram_addr; |
| 644 | | break; |
| 639 | return sp_dram_addr; |
| 645 | 640 | |
| 646 | 641 | case 0x08/4: // SP_RD_LEN_REG |
| 647 | | ret = (sp_dma_skip << 20) | (sp_dma_count << 12) | sp_dma_length; |
| 648 | | break; |
| 642 | return (sp_dma_skip << 20) | (sp_dma_count << 12) | sp_dma_length; |
| 649 | 643 | |
| 650 | 644 | case 0x10/4: // SP_STATUS_REG |
| 651 | | ret = rspcpu->state().state_int(RSP_SR); |
| 652 | | break; |
| 645 | return m_rsp->state_int(RSP_SR); |
| 653 | 646 | |
| 654 | 647 | case 0x14/4: // SP_DMA_FULL_REG |
| 655 | | ret = 0; |
| 656 | | break; |
| 648 | return 0; |
| 657 | 649 | |
| 658 | 650 | case 0x18/4: // SP_DMA_BUSY_REG |
| 659 | | ret = 0; |
| 660 | | break; |
| 651 | return 0; |
| 661 | 652 | |
| 662 | 653 | case 0x1c/4: // SP_SEMAPHORE_REG |
| 663 | | machine().device("maincpu")->execute().yield(); |
| 654 | m_vr4300->yield(); |
| 664 | 655 | if( sp_semaphore ) |
| 665 | 656 | { |
| 666 | | ret = 1; |
| 657 | return 1; |
| 667 | 658 | } |
| 668 | 659 | else |
| 669 | 660 | { |
| 670 | 661 | sp_semaphore = 1; |
| 671 | | ret = 0; |
| 662 | return 0; |
| 672 | 663 | } |
| 673 | 664 | break; |
| 674 | 665 | |
| 675 | 666 | case 0x20/4: // DP_CMD_START |
| 676 | | { |
| 677 | | n64_state *state = machine().driver_data<n64_state>(); |
| 678 | | ret = state->m_rdp->get_start(); |
| 679 | | break; |
| 680 | | } |
| 667 | return m_n64->rdp()->get_start(); |
| 681 | 668 | |
| 682 | 669 | case 0x24/4: // DP_CMD_END |
| 683 | | { |
| 684 | | n64_state *state = machine().driver_data<n64_state>(); |
| 685 | | ret = state->m_rdp->get_end(); |
| 686 | | break; |
| 687 | | } |
| 670 | return m_n64->rdp()->get_end(); |
| 688 | 671 | |
| 689 | 672 | case 0x28/4: // DP_CMD_CURRENT |
| 690 | | { |
| 691 | | n64_state *state = machine().driver_data<n64_state>(); |
| 692 | | ret = state->m_rdp->get_current(); |
| 693 | | break; |
| 694 | | } |
| 673 | return m_n64->rdp()->get_current(); |
| 695 | 674 | |
| 696 | 675 | case 0x34/4: // DP_CMD_BUSY |
| 697 | 676 | case 0x38/4: // DP_CMD_PIPE_BUSY |
| 698 | 677 | case 0x3c/4: // DP_CMD_TMEM_BUSY |
| 699 | | break; |
| 678 | return 0; |
| 700 | 679 | |
| 701 | 680 | case 0x2c/4: // DP_CMD_STATUS |
| 702 | | { |
| 703 | | n64_state *state = machine().driver_data<n64_state>(); |
| 704 | | ret = state->m_rdp->get_status(); |
| 705 | | break; |
| 706 | | } |
| 681 | return m_n64->rdp()->get_status(); |
| 707 | 682 | |
| 708 | 683 | case 0x30/4: // DP_CMD_CLOCK |
| 709 | | { |
| 710 | | if(!(machine().driver_data<n64_state>()->m_rdp->get_status() & DP_STATUS_FREEZE)) |
| 684 | if(!(m_n64->rdp()->get_status() & DP_STATUS_FREEZE)) |
| 711 | 685 | { |
| 712 | 686 | dp_clock += 13; |
| 713 | | ret = dp_clock; |
| 687 | return dp_clock; |
| 714 | 688 | } |
| 715 | 689 | break; |
| 716 | | } |
| 717 | 690 | |
| 718 | 691 | case 0x40000/4: // PC |
| 719 | | ret = rspcpu->state().state_int(RSP_PC) & 0x00000fff; |
| 720 | | break; |
| 692 | return m_rsp->state_int(RSP_PC) & 0x00000fff; |
| 721 | 693 | |
| 722 | 694 | default: |
| 723 | | logerror("sp_reg_r: %08X at %08X\n", offset, maincpu->safe_pc()); |
| 695 | logerror("sp_reg_r: %08X at %08X\n", offset, m_vr4300->pc()); |
| 724 | 696 | break; |
| 725 | 697 | } |
| 726 | 698 | |
| 727 | | return ret; |
| 699 | return 0; |
| 728 | 700 | } |
| 729 | 701 | |
| 730 | 702 | |
| r250319 | r250320 | |
| 758 | 730 | |
| 759 | 731 | case 0x10/4: // RSP_STATUS_REG |
| 760 | 732 | { |
| 761 | | UINT32 oldstatus = rspcpu->state().state_int(RSP_SR); |
| 733 | UINT32 oldstatus = m_rsp->state_int(RSP_SR); |
| 762 | 734 | UINT32 newstatus = oldstatus; |
| 763 | 735 | |
| 764 | 736 | if (data & 0x00000001) // clear halt |
| 765 | 737 | { |
| 766 | | rspcpu->execute().set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 738 | m_rsp->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); |
| 767 | 739 | newstatus &= ~RSP_STATUS_HALT; |
| 768 | 740 | } |
| 769 | 741 | if (data & 0x00000002) // set halt |
| 770 | 742 | { |
| 771 | | rspcpu->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 743 | m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 772 | 744 | newstatus |= RSP_STATUS_HALT; |
| 773 | 745 | } |
| 774 | 746 | if (data & 0x00000004) |
| r250319 | r250320 | |
| 792 | 764 | newstatus |= RSP_STATUS_SSTEP; // set single step |
| 793 | 765 | if(!(oldstatus & (RSP_STATUS_BROKE | RSP_STATUS_HALT))) |
| 794 | 766 | { |
| 795 | | rspcpu->state().set_state_int(RSP_STEPCNT, 1 ); |
| 796 | | machine().device("rsp")->execute().yield(); |
| 767 | m_rsp->set_state_int(RSP_STEPCNT, 1 ); |
| 768 | m_rsp->yield(); |
| 797 | 769 | } |
| 798 | 770 | } |
| 799 | 771 | if (data & 0x00000080) |
| r250319 | r250320 | |
| 868 | 840 | { |
| 869 | 841 | newstatus |= RSP_STATUS_SIGNAL7; // set signal 7 |
| 870 | 842 | } |
| 871 | | rspcpu->state().set_state_int(RSP_SR, newstatus); |
| 843 | m_rsp->set_state_int(RSP_SR, newstatus); |
| 872 | 844 | break; |
| 873 | 845 | } |
| 874 | 846 | |
| r250319 | r250320 | |
| 880 | 852 | break; |
| 881 | 853 | |
| 882 | 854 | default: |
| 883 | | logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 855 | logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 884 | 856 | break; |
| 885 | 857 | } |
| 886 | 858 | } |
| r250319 | r250320 | |
| 889 | 861 | switch (offset & 0xffff) |
| 890 | 862 | { |
| 891 | 863 | case 0x00/4: // SP_PC_REG |
| 892 | | if( rspcpu->state().state_int(RSP_NEXTPC) != 0xffffffff ) |
| 864 | if( m_rsp->state_int(RSP_NEXTPC) != 0xffffffff ) |
| 893 | 865 | { |
| 894 | | rspcpu->state().set_state_int(RSP_NEXTPC, 0x1000 | (data & 0xfff)); |
| 866 | m_rsp->set_state_int(RSP_NEXTPC, 0x1000 | (data & 0xfff)); |
| 895 | 867 | } |
| 896 | 868 | else |
| 897 | 869 | { |
| 898 | | rspcpu->state().set_state_int(RSP_PC, 0x1000 | (data & 0xfff)); |
| 870 | m_rsp->set_state_int(RSP_PC, 0x1000 | (data & 0xfff)); |
| 899 | 871 | } |
| 900 | 872 | break; |
| 901 | 873 | |
| 902 | 874 | default: |
| 903 | | logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 875 | logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 904 | 876 | break; |
| 905 | 877 | } |
| 906 | 878 | } |
| r250319 | r250320 | |
| 916 | 888 | |
| 917 | 889 | READ32_MEMBER( n64_periphs::dp_reg_r ) |
| 918 | 890 | { |
| 919 | | n64_state *state = space.machine().driver_data<n64_state>(); |
| 920 | | UINT32 ret = 0; |
| 921 | | |
| 922 | 891 | switch (offset) |
| 923 | 892 | { |
| 924 | 893 | case 0x00/4: // DP_START_REG |
| 925 | | ret = state->m_rdp->get_start(); |
| 926 | | break; |
| 894 | return m_n64->rdp()->get_start(); |
| 927 | 895 | |
| 928 | 896 | case 0x04/4: // DP_END_REG |
| 929 | | ret = state->m_rdp->get_end(); |
| 930 | | break; |
| 897 | return m_n64->rdp()->get_end(); |
| 931 | 898 | |
| 932 | 899 | case 0x08/4: // DP_CURRENT_REG |
| 933 | | ret = state->m_rdp->get_current(); |
| 934 | | break; |
| 900 | return m_n64->rdp()->get_current(); |
| 935 | 901 | |
| 936 | 902 | case 0x0c/4: // DP_STATUS_REG |
| 937 | | ret = state->m_rdp->get_status(); |
| 938 | | break; |
| 903 | return m_n64->rdp()->get_status(); |
| 939 | 904 | |
| 940 | 905 | case 0x10/4: // DP_CLOCK_REG |
| 941 | | { |
| 942 | | if(!(state->m_rdp->get_status() & DP_STATUS_FREEZE)) |
| 906 | if(!(m_n64->rdp()->get_status() & DP_STATUS_FREEZE)) |
| 943 | 907 | { |
| 944 | 908 | dp_clock += 13; |
| 945 | | ret = dp_clock; |
| 909 | return dp_clock; |
| 946 | 910 | } |
| 947 | 911 | break; |
| 948 | | } |
| 949 | 912 | |
| 950 | 913 | default: |
| 951 | | logerror("dp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, safe_pc()); |
| 914 | logerror("dp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 952 | 915 | break; |
| 953 | 916 | } |
| 954 | 917 | |
| 955 | | return ret; |
| 918 | return 0; |
| 956 | 919 | } |
| 957 | 920 | |
| 958 | 921 | WRITE32_MEMBER( n64_periphs::dp_reg_w ) |
| 959 | 922 | { |
| 960 | | n64_state *state = space.machine().driver_data<n64_state>(); |
| 961 | | UINT32 status = state->m_rdp->get_status(); |
| 923 | UINT32 status = m_n64->rdp()->get_status(); |
| 962 | 924 | |
| 963 | 925 | switch (offset) |
| 964 | 926 | { |
| 965 | 927 | case 0x00/4: // DP_START_REG |
| 966 | 928 | if(status & DP_STATUS_START_VALID) |
| 929 | { |
| 967 | 930 | break; |
| 931 | } |
| 968 | 932 | else |
| 969 | 933 | { |
| 970 | | state->m_rdp->set_status(status | DP_STATUS_START_VALID); |
| 971 | | state->m_rdp->set_start(data & ~7); |
| 934 | m_n64->rdp()->set_status(status | DP_STATUS_START_VALID); |
| 935 | m_n64->rdp()->set_start(data & ~7); |
| 972 | 936 | } |
| 973 | 937 | break; |
| 974 | 938 | |
| 975 | 939 | case 0x04/4: // DP_END_REG |
| 976 | 940 | if(status & DP_STATUS_START_VALID) |
| 977 | 941 | { |
| 978 | | state->m_rdp->set_status(status & ~DP_STATUS_START_VALID); |
| 979 | | state->m_rdp->set_current(state->m_rdp->get_start()); |
| 980 | | state->m_rdp->set_end(data & ~7); |
| 942 | m_n64->rdp()->set_status(status & ~DP_STATUS_START_VALID); |
| 943 | m_n64->rdp()->set_current(m_n64->rdp()->get_start()); |
| 944 | m_n64->rdp()->set_end(data & ~7); |
| 981 | 945 | g_profiler.start(PROFILER_USER1); |
| 982 | | state->m_rdp->process_command_list(); |
| 946 | m_n64->rdp()->process_command_list(); |
| 983 | 947 | g_profiler.stop(); |
| 984 | 948 | break; |
| 985 | 949 | } |
| 986 | 950 | else |
| 987 | 951 | { |
| 988 | | state->m_rdp->set_end(data & ~7); |
| 952 | m_n64->rdp()->set_end(data & ~7); |
| 989 | 953 | g_profiler.start(PROFILER_USER1); |
| 990 | | state->m_rdp->process_command_list(); |
| 954 | m_n64->rdp()->process_command_list(); |
| 991 | 955 | g_profiler.stop(); |
| 992 | 956 | break; |
| 993 | 957 | } |
| 994 | 958 | |
| 995 | 959 | case 0x0c/4: // DP_STATUS_REG |
| 996 | 960 | { |
| 997 | | UINT32 current_status = state->m_rdp->get_status(); |
| 961 | UINT32 current_status = m_n64->rdp()->get_status(); |
| 998 | 962 | if (data & 0x00000001) current_status &= ~DP_STATUS_XBUS_DMA; |
| 999 | 963 | if (data & 0x00000002) current_status |= DP_STATUS_XBUS_DMA; |
| 1000 | 964 | if (data & 0x00000004) current_status &= ~DP_STATUS_FREEZE; |
| r250319 | r250320 | |
| 1002 | 966 | if (data & 0x00000010) current_status &= ~DP_STATUS_FLUSH; |
| 1003 | 967 | if (data & 0x00000020) current_status |= DP_STATUS_FLUSH; |
| 1004 | 968 | if (data & 0x00000200) dp_clock = 0; |
| 1005 | | state->m_rdp->set_status(current_status); |
| 969 | m_n64->rdp()->set_status(current_status); |
| 1006 | 970 | break; |
| 1007 | 971 | } |
| 1008 | 972 | |
| 1009 | 973 | default: |
| 1010 | | logerror("dp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, safe_pc()); |
| 974 | logerror("dp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 1011 | 975 | break; |
| 1012 | 976 | } |
| 1013 | 977 | } |
| 1014 | 978 | |
| 1015 | 979 | TIMER_CALLBACK_MEMBER(n64_periphs::vi_scanline_callback) |
| 1016 | 980 | { |
| 1017 | | machine().device<n64_periphs>("rcp")->vi_scanline_tick(); |
| 1018 | | } |
| 1019 | | |
| 1020 | | void n64_periphs::vi_scanline_tick() |
| 1021 | | { |
| 1022 | 981 | signal_rcp_interrupt(VI_INTERRUPT); |
| 1023 | 982 | vi_scanline_timer->adjust(m_screen->time_until_pos(vi_intr >> 1)); |
| 1024 | 983 | } |
| r250319 | r250320 | |
| 1124 | 1083 | break; |
| 1125 | 1084 | |
| 1126 | 1085 | default: |
| 1127 | | logerror("vi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, maincpu->safe_pc()); |
| 1086 | logerror("vi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 1128 | 1087 | break; |
| 1129 | 1088 | } |
| 1130 | 1089 | |
| r250319 | r250320 | |
| 1152 | 1111 | vi_recalculate_resolution(); |
| 1153 | 1112 | } |
| 1154 | 1113 | vi_width = data; |
| 1155 | | //state->m_rdp->m_misc_state.m_fb_width = data; |
| 1156 | 1114 | break; |
| 1157 | 1115 | |
| 1158 | 1116 | case 0x0c/4: // VI_INTR_REG |
| r250319 | r250320 | |
| 1214 | 1172 | */ |
| 1215 | 1173 | |
| 1216 | 1174 | default: |
| 1217 | | logerror("vi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 1175 | logerror("vi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 1218 | 1176 | break; |
| 1219 | 1177 | } |
| 1220 | 1178 | } |
| r250319 | r250320 | |
| 1289 | 1247 | |
| 1290 | 1248 | void n64_periphs::ai_dma() |
| 1291 | 1249 | { |
| 1292 | | INT16 *ram = (INT16*)rdram; |
| 1250 | INT16 *ram = (INT16*)m_rdram; |
| 1293 | 1251 | AUDIO_DMA *current = ai_fifo_get_top(); |
| 1294 | 1252 | attotime period; |
| 1295 | 1253 | |
| r250319 | r250320 | |
| 1365 | 1323 | break; |
| 1366 | 1324 | |
| 1367 | 1325 | default: |
| 1368 | | logerror("ai_reg_r: %08X, %08X at %08X\n", offset, mem_mask, maincpu->safe_pc()); |
| 1326 | logerror("ai_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 1369 | 1327 | break; |
| 1370 | 1328 | } |
| 1371 | 1329 | |
| r250319 | r250320 | |
| 1404 | 1362 | break; |
| 1405 | 1363 | |
| 1406 | 1364 | default: |
| 1407 | | logerror("ai_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 1365 | logerror("ai_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 1408 | 1366 | break; |
| 1409 | 1367 | } |
| 1410 | 1368 | } |
| r250319 | r250320 | |
| 1414 | 1372 | |
| 1415 | 1373 | TIMER_CALLBACK_MEMBER(n64_periphs::pi_dma_callback) |
| 1416 | 1374 | { |
| 1417 | | machine().device<n64_periphs>("rcp")->pi_dma_tick(); |
| 1418 | | machine().device("rsp")->execute().yield(); |
| 1375 | pi_dma_tick(); |
| 1376 | m_rsp->yield(); |
| 1419 | 1377 | } |
| 1420 | 1378 | |
| 1421 | 1379 | void n64_periphs::pi_dma_tick() |
| 1422 | 1380 | { |
| 1423 | 1381 | bool update_bm = false; |
| 1424 | 1382 | UINT16 *cart16; |
| 1425 | | UINT16 *dram16 = (UINT16*)rdram; |
| 1383 | UINT16 *dram16 = (UINT16*)m_rdram; |
| 1426 | 1384 | |
| 1427 | 1385 | UINT32 cart_addr = (pi_cart_addr & 0x0fffffff) >> 1; |
| 1428 | 1386 | UINT32 dram_addr = (pi_dram_addr & 0x007fffff) >> 1; |
| r250319 | r250320 | |
| 1441 | 1399 | } |
| 1442 | 1400 | else if((cart_addr & 0x04000000) == 0x04000000) |
| 1443 | 1401 | { |
| 1444 | | cart16 = (UINT16*)n64_sram; |
| 1402 | cart16 = (UINT16*)m_sram; |
| 1445 | 1403 | cart_addr = (pi_cart_addr & 0x0001ffff) >> 1; |
| 1446 | 1404 | } |
| 1447 | 1405 | else if((cart_addr & 0x03000000) == 0x03000000 && dd_present) |
| r250319 | r250320 | |
| 1549 | 1507 | break; |
| 1550 | 1508 | |
| 1551 | 1509 | default: |
| 1552 | | logerror("pi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, maincpu->safe_pc()); |
| 1510 | logerror("pi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 1553 | 1511 | break; |
| 1554 | 1512 | } |
| 1555 | 1513 | |
| r250319 | r250320 | |
| 1574 | 1532 | dd_status_reg &= ~DD_ASIC_STATUS_DREQ; |
| 1575 | 1533 | dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; |
| 1576 | 1534 | //logerror("Clearing DREQ, INT\n"); |
| 1577 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 1535 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 1578 | 1536 | } |
| 1579 | 1537 | if(pi_cart_addr == 0x05000000 && dd_present) |
| 1580 | 1538 | { |
| 1581 | 1539 | dd_status_reg &= ~DD_ASIC_STATUS_C2_XFER; |
| 1582 | 1540 | dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; |
| 1583 | 1541 | //logerror("Clearing C2, INT\n"); |
| 1584 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 1542 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 1585 | 1543 | } |
| 1586 | 1544 | break; |
| 1587 | 1545 | } |
| r250319 | r250320 | |
| 1658 | 1616 | break; |
| 1659 | 1617 | |
| 1660 | 1618 | default: |
| 1661 | | logerror("pi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 1619 | logerror("pi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 1662 | 1620 | break; |
| 1663 | 1621 | } |
| 1664 | 1622 | } |
| r250319 | r250320 | |
| 1669 | 1627 | { |
| 1670 | 1628 | if(offset == 0x0C/4) // RI_SELECT |
| 1671 | 1629 | { |
| 1672 | | /* This is to 'simulate' the time that RDRAM initialization |
| 1630 | /* This is to 'simulate' the time that RDRAM initialization |
| 1673 | 1631 | would take if the RI registers were not set to skip the RDRAM |
| 1674 | 1632 | testing during device reset. Proper simulation would require |
| 1675 | | emulating the RDRAM modules and bus stalls for the mips cpu. |
| 1633 | emulating the RDRAM modules and bus stalls for the mips cpu. |
| 1676 | 1634 | The cycle amount chosen represents 1/2 second, which is not |
| 1677 | 1635 | necessarily the time for RDRAM initialization, but rather the |
| 1678 | 1636 | time recommended for letting the SI devices settle after startup. |
| 1679 | 1637 | This allows the initialization routines for the SI to see that a |
| 1680 | 1638 | proper amount of time has passed since system startup. */ |
| 1681 | | machine().device<mips3_device>("maincpu")->burn_cycles(93750000/2); |
| 1639 | m_vr4300->burn_cycles(93750000/2); |
| 1682 | 1640 | } |
| 1683 | 1641 | |
| 1684 | 1642 | if(offset > 0x1c/4) |
| 1685 | 1643 | { |
| 1686 | | logerror("ri_reg_r: %08X, %08X at %08X\n", offset, mem_mask, maincpu->safe_pc()); |
| 1644 | logerror("ri_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); |
| 1687 | 1645 | return 0; |
| 1688 | 1646 | } |
| 1689 | 1647 | return ri_regs[offset]; |
| r250319 | r250320 | |
| 1693 | 1651 | { |
| 1694 | 1652 | if(offset > 0x1c/4) |
| 1695 | 1653 | { |
| 1696 | | logerror("ri_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, maincpu->safe_pc()); |
| 1654 | logerror("ri_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); |
| 1697 | 1655 | return; |
| 1698 | 1656 | } |
| 1699 | 1657 | COMBINE_DATA(&ri_regs[offset]); |
| r250319 | r250320 | |
| 2138 | 2096 | |
| 2139 | 2097 | if (direction) // RDRAM -> PIF RAM |
| 2140 | 2098 | { |
| 2141 | | UINT32 *src = (UINT32*)&rdram[(si_dram_addr & 0x1fffffff) / 4]; |
| 2099 | UINT32 *src = m_rdram + ((si_dram_addr & 0x1fffffff) / 4); |
| 2142 | 2100 | |
| 2143 | 2101 | for(int i = 0; i < 64; i+=4) |
| 2144 | 2102 | { |
| r250319 | r250320 | |
| 2155 | 2113 | { |
| 2156 | 2114 | handle_pif(); |
| 2157 | 2115 | |
| 2158 | | UINT32 *dst = (UINT32*)&rdram[(si_dram_addr & 0x1fffffff) / 4]; |
| 2116 | UINT32 *dst = m_rdram + ((si_dram_addr & 0x1fffffff) / 4); |
| 2159 | 2117 | |
| 2160 | 2118 | for(int i = 0; i < 64; i+=4) |
| 2161 | 2119 | { |
| r250319 | r250320 | |
| 2315 | 2273 | } |
| 2316 | 2274 | //logerror("DD Write, Sending Interrupt\n"); |
| 2317 | 2275 | dd_status_reg |= DD_ASIC_STATUS_BM_INT; |
| 2318 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); |
| 2276 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); |
| 2319 | 2277 | return; |
| 2320 | 2278 | } |
| 2321 | 2279 | else // dd read, BM Mode 1 |
| r250319 | r250320 | |
| 2359 | 2317 | } |
| 2360 | 2318 | //logerror("DD Read, Sending Interrupt\n"); |
| 2361 | 2319 | dd_status_reg |= DD_ASIC_STATUS_BM_INT; |
| 2362 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); |
| 2320 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); |
| 2363 | 2321 | return; |
| 2364 | 2322 | } |
| 2365 | 2323 | } |
| r250319 | r250320 | |
| 2452 | 2410 | { |
| 2453 | 2411 | dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; |
| 2454 | 2412 | //logerror("DD Read Gap, Clearing INT\n"); |
| 2455 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 2413 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 2456 | 2414 | dd_update_bm(); |
| 2457 | 2415 | } |
| 2458 | 2416 | break; |
| r250319 | r250320 | |
| 2623 | 2581 | } |
| 2624 | 2582 | //logerror("Sending MECHA Int\n"); |
| 2625 | 2583 | dd_status_reg |= DD_ASIC_STATUS_MECHA_INT; |
| 2626 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); |
| 2584 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); |
| 2627 | 2585 | break; |
| 2628 | 2586 | |
| 2629 | 2587 | case 0x10/4: // BM Status |
| r250319 | r250320 | |
| 2664 | 2622 | if(!(dd_status_reg & DD_ASIC_STATUS_BM_INT) && !(dd_status_reg & DD_ASIC_STATUS_MECHA_INT)) |
| 2665 | 2623 | { |
| 2666 | 2624 | //logerror("DD Status, Clearing INT\n"); |
| 2667 | | machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 2625 | m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); |
| 2668 | 2626 | } |
| 2669 | 2627 | if(data & DD_BM_START) |
| 2670 | 2628 | { |
| r250319 | r250320 | |
| 2742 | 2700 | device_image_interface *image = dynamic_cast<device_image_interface *>(periphs->m_nvram_image); |
| 2743 | 2701 | |
| 2744 | 2702 | UINT8 data[0x30800]; |
| 2745 | | memcpy(data, n64_sram, 0x20000); |
| 2703 | if (m_sram != NULL) |
| 2704 | { |
| 2705 | memset(data, 0, 0x20000); |
| 2706 | } |
| 2707 | else |
| 2708 | { |
| 2709 | memcpy(data, m_sram, 0x20000); |
| 2710 | } |
| 2746 | 2711 | memcpy(data + 0x20000, periphs->m_save_data.eeprom, 0x800); |
| 2747 | 2712 | memcpy(data + 0x20800, periphs->m_save_data.mempak[0], 0x8000); |
| 2748 | 2713 | memcpy(data + 0x28800, periphs->m_save_data.mempak[1], 0x8000); |
| r250319 | r250320 | |
| 2751 | 2716 | |
| 2752 | 2717 | void n64_state::machine_start() |
| 2753 | 2718 | { |
| 2754 | | rdram = reinterpret_cast<UINT32 *>(memshare("rdram")->ptr()); |
| 2755 | | n64_sram = reinterpret_cast<UINT32 *>(memshare("sram")->ptr()); |
| 2756 | | rsp_imem = reinterpret_cast<UINT32 *>(memshare("rsp_imem")->ptr()); |
| 2757 | | rsp_dmem = reinterpret_cast<UINT32 *>(memshare("rsp_dmem")->ptr()); |
| 2719 | m_vr4300->mips3drc_set_options(MIPS3DRC_COMPATIBLE_OPTIONS); |
| 2758 | 2720 | |
| 2759 | | dynamic_cast<mips3_device *>(machine().device("maincpu"))->mips3drc_set_options(MIPS3DRC_COMPATIBLE_OPTIONS); |
| 2760 | | |
| 2761 | 2721 | /* configure fast RAM regions */ |
| 2762 | | dynamic_cast<mips3_device *>(machine().device("maincpu"))->add_fastram(0x00000000, 0x007fffff, FALSE, rdram); |
| 2722 | m_vr4300->add_fastram(0x00000000, 0x007fffff, FALSE, m_rdram); |
| 2763 | 2723 | |
| 2764 | 2724 | rsp_device *rsp = machine().device<rsp_device>("rsp"); |
| 2765 | 2725 | rsp->rspdrc_set_options(RSPDRC_STRICT_VERIFY); |
| 2766 | 2726 | rsp->rspdrc_flush_drc_cache(); |
| 2767 | | rsp->rsp_add_dmem(rsp_dmem); |
| 2768 | | rsp->rsp_add_imem(rsp_imem); |
| 2727 | rsp->rsp_add_dmem(m_rsp_dmem); |
| 2728 | rsp->rsp_add_imem(m_rsp_imem); |
| 2769 | 2729 | |
| 2770 | 2730 | /* add a hook for battery save */ |
| 2771 | 2731 | machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(n64_state::n64_machine_stop),this)); |
| r250319 | r250320 | |
| 2773 | 2733 | |
| 2774 | 2734 | void n64_state::machine_reset() |
| 2775 | 2735 | { |
| 2776 | | machine().device("rsp")->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 2736 | m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 2777 | 2737 | } |