trunk/src/mame/machine/snes.c
| r21699 | r21700 | |
| 676 | 676 | |
| 677 | 677 | */ |
| 678 | 678 | |
| 679 | | static UINT8 snes_rom_access(running_machine &machine, UINT32 offset) |
| 679 | inline UINT8 snes_state::snes_rom_access(UINT32 offset) |
| 680 | 680 | { |
| 681 | | snes_state *state = machine.driver_data<snes_state>(); |
| 682 | 681 | UINT32 addr; |
| 683 | 682 | UINT8 value = 0xff; |
| 684 | 683 | UINT8 base_bank = (offset < 0x800000) ? 0x80 : 0x00; |
| 685 | 684 | |
| 686 | | switch (state->m_cart[0].mode) |
| 685 | switch (m_cart[0].mode) |
| 687 | 686 | { |
| 688 | 687 | case SNES_MODE_20: |
| 689 | 688 | case SNES_MODE_22: |
| 690 | | addr = (state->m_cart[0].rom_bank_map[offset/0x10000] * 0x8000) + (offset & 0x7fff); |
| 691 | | value = state->m_cart[0].m_rom[addr]; |
| 689 | addr = (m_cart[0].rom_bank_map[offset/0x10000] * 0x8000) + (offset & 0x7fff); |
| 690 | value = m_cart[0].m_rom[addr]; |
| 692 | 691 | break; |
| 693 | 692 | case SNES_MODE_21: |
| 694 | 693 | case SNES_MODE_25: |
| 695 | 694 | offset &= 0x3fffff; |
| 696 | | addr = (state->m_cart[0].rom_bank_map[base_bank + (offset/0x8000)] * 0x8000) + (offset & 0x7fff); |
| 697 | | value = state->m_cart[0].m_rom[addr]; |
| 695 | addr = (m_cart[0].rom_bank_map[base_bank + (offset/0x8000)] * 0x8000) + (offset & 0x7fff); |
| 696 | value = m_cart[0].m_rom[addr]; |
| 698 | 697 | break; |
| 699 | 698 | } |
| 700 | 699 | |
| r21699 | r21700 | |
| 702 | 701 | } |
| 703 | 702 | |
| 704 | 703 | /* 0x000000 - 0x7dffff */ |
| 705 | | READ8_HANDLER( snes_r_bank1 ) |
| 704 | READ8_MEMBER(snes_state::snes_r_bank1) |
| 706 | 705 | { |
| 707 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 708 | 706 | UINT8 value = 0xff; |
| 709 | 707 | UINT16 address = offset & 0xffff; |
| 710 | 708 | |
| r21699 | r21700 | |
| 713 | 711 | if (address < 0x2000) /* Mirror of Low RAM */ |
| 714 | 712 | value = space.read_byte(0x7e0000 + address); |
| 715 | 713 | else if (address < 0x6000) /* I/O */ |
| 716 | | value = state->snes_r_io(space, address); |
| 714 | value = snes_r_io(space, address); |
| 717 | 715 | else if (address < 0x8000) |
| 718 | 716 | { |
| 719 | | if (offset >= 0x300000 && state->m_cart[0].mode == SNES_MODE_21 && state->m_cart[0].m_nvram_size > 0) |
| 717 | if (offset >= 0x300000 && m_cart[0].mode == SNES_MODE_21 && m_cart[0].m_nvram_size > 0) |
| 720 | 718 | { |
| 721 | 719 | /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */ |
| 722 | 720 | /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */ |
| 723 | | int mask = (state->m_cart[0].m_nvram_size - 1) & 0x7fff; /* Limit SRAM size to what's actually present */ |
| 724 | | value = state->m_cart[0].m_nvram[(offset - 0x6000) & mask]; |
| 721 | int mask = (m_cart[0].m_nvram_size - 1) & 0x7fff; /* Limit SRAM size to what's actually present */ |
| 722 | value = m_cart[0].m_nvram[(offset - 0x6000) & mask]; |
| 725 | 723 | } |
| 726 | 724 | else |
| 727 | 725 | value = snes_open_bus_r(space, 0); /* Reserved */ |
| 728 | 726 | } |
| 729 | 727 | else |
| 730 | | value = snes_rom_access(space.machine(), offset); //ROM |
| 728 | value = snes_rom_access(offset); //ROM |
| 731 | 729 | } |
| 732 | 730 | else if (offset < 0x700000) |
| 733 | 731 | { |
| 734 | | if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */ |
| 732 | if (m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */ |
| 735 | 733 | value = snes_open_bus_r(space, 0); |
| 736 | 734 | else |
| 737 | | value = snes_rom_access(space.machine(), offset); //ROM |
| 735 | value = snes_rom_access(offset); //ROM |
| 738 | 736 | } |
| 739 | 737 | else |
| 740 | 738 | { |
| 741 | | if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 */ |
| 739 | if (m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 */ |
| 742 | 740 | { |
| 743 | | if (state->m_cart[0].m_nvram_size > 0x8000) |
| 741 | if (m_cart[0].m_nvram_size > 0x8000) |
| 744 | 742 | { |
| 745 | 743 | // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc. |
| 746 | | int mask = state->m_cart[0].m_nvram_size - 1; |
| 744 | int mask = m_cart[0].m_nvram_size - 1; |
| 747 | 745 | offset = (offset / 0x10000) * 0x8000 + (offset & 0x7fff); |
| 748 | | value = state->m_cart[0].m_nvram[offset & mask]; |
| 746 | value = m_cart[0].m_nvram[offset & mask]; |
| 749 | 747 | } |
| 750 | | else if (state->m_cart[0].m_nvram_size > 0) |
| 748 | else if (m_cart[0].m_nvram_size > 0) |
| 751 | 749 | { |
| 752 | | int mask = state->m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 753 | | value = state->m_cart[0].m_nvram[offset & mask]; |
| 750 | int mask = m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 751 | value = m_cart[0].m_nvram[offset & mask]; |
| 754 | 752 | } |
| 755 | 753 | else |
| 756 | 754 | { |
| r21699 | r21700 | |
| 759 | 757 | } |
| 760 | 758 | } |
| 761 | 759 | else |
| 762 | | value = snes_rom_access(space.machine(), offset); //ROM |
| 760 | value = snes_rom_access(offset); //ROM |
| 763 | 761 | } |
| 764 | 762 | |
| 765 | 763 | return value; |
| r21699 | r21700 | |
| 767 | 765 | |
| 768 | 766 | |
| 769 | 767 | /* 0x800000 - 0xffffff */ |
| 770 | | READ8_HANDLER( snes_r_bank2 ) |
| 768 | READ8_MEMBER(snes_state::snes_r_bank2) |
| 771 | 769 | { |
| 772 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 773 | 770 | UINT8 value = 0; |
| 774 | 771 | UINT16 address = offset & 0xffff; |
| 775 | 772 | |
| r21699 | r21700 | |
| 778 | 775 | if (address < 0x8000) |
| 779 | 776 | value = space.read_byte(offset); |
| 780 | 777 | else |
| 781 | | value = snes_rom_access(space.machine(), 0x800000 + offset); //ROM |
| 778 | value = snes_rom_access(0x800000 + offset); //ROM |
| 782 | 779 | } |
| 783 | 780 | else |
| 784 | 781 | { |
| 785 | | if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */ |
| 782 | if (m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */ |
| 786 | 783 | { |
| 787 | 784 | if (offset < 0x700000) |
| 788 | 785 | value = space.read_byte(offset); |
| 789 | 786 | else |
| 790 | 787 | { |
| 791 | | if (state->m_cart[0].m_nvram_size > 0x8000) |
| 788 | if (m_cart[0].m_nvram_size > 0x8000) |
| 792 | 789 | { |
| 793 | 790 | // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc. |
| 794 | | int mask = state->m_cart[0].m_nvram_size - 1; |
| 791 | int mask = m_cart[0].m_nvram_size - 1; |
| 795 | 792 | offset = (offset / 0x10000) * 0x8000 + (offset & 0x7fff); |
| 796 | | value = state->m_cart[0].m_nvram[offset & mask]; |
| 793 | value = m_cart[0].m_nvram[offset & mask]; |
| 797 | 794 | } |
| 798 | | else if (state->m_cart[0].m_nvram_size > 0) |
| 795 | else if (m_cart[0].m_nvram_size > 0) |
| 799 | 796 | { |
| 800 | | int mask = state->m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 801 | | value = state->m_cart[0].m_nvram[offset & mask]; |
| 797 | int mask = m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 798 | value = m_cart[0].m_nvram[offset & mask]; |
| 802 | 799 | } |
| 803 | 800 | else |
| 804 | 801 | { |
| r21699 | r21700 | |
| 808 | 805 | } |
| 809 | 806 | } |
| 810 | 807 | else |
| 811 | | value = snes_rom_access(space.machine(), 0x800000 + offset); //ROM |
| 808 | value = snes_rom_access(0x800000 + offset); //ROM |
| 812 | 809 | } |
| 813 | 810 | |
| 814 | 811 | return value; |
| r21699 | r21700 | |
| 816 | 813 | |
| 817 | 814 | |
| 818 | 815 | /* 0x000000 - 0x7dffff */ |
| 819 | | WRITE8_HANDLER( snes_w_bank1 ) |
| 816 | WRITE8_MEMBER(snes_state::snes_w_bank1) |
| 820 | 817 | { |
| 821 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 822 | 818 | UINT16 address = offset & 0xffff; |
| 823 | 819 | |
| 824 | 820 | if (offset < 0x400000) |
| r21699 | r21700 | |
| 826 | 822 | if (address < 0x2000) /* Mirror of Low RAM */ |
| 827 | 823 | space.write_byte(0x7e0000 + address, data); |
| 828 | 824 | else if (address < 0x6000) /* I/O */ |
| 829 | | state->snes_w_io(space, address, data); |
| 825 | snes_w_io(space, address, data); |
| 830 | 826 | else if (address < 0x8000) |
| 831 | 827 | { |
| 832 | | if (offset >= 0x300000 && state->m_cart[0].mode == SNES_MODE_21 && state->m_cart[0].m_nvram_size > 0) |
| 828 | if (offset >= 0x300000 && m_cart[0].mode == SNES_MODE_21 && m_cart[0].m_nvram_size > 0) |
| 833 | 829 | { |
| 834 | 830 | /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */ |
| 835 | 831 | /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */ |
| 836 | | int mask = (state->m_cart[0].m_nvram_size - 1) & 0x7fff; /* Limit SRAM size to what's actually present */ |
| 837 | | state->m_cart[0].m_nvram[(offset - 0x6000) & mask] = data; |
| 832 | int mask = (m_cart[0].m_nvram_size - 1) & 0x7fff; /* Limit SRAM size to what's actually present */ |
| 833 | m_cart[0].m_nvram[(offset - 0x6000) & mask] = data; |
| 838 | 834 | } |
| 839 | 835 | else |
| 840 | 836 | logerror("(PC=%06x) snes_w_bank1: Attempt to write to reserved address: %X = %02X\n", space.device().safe_pc(), offset, data); |
| r21699 | r21700 | |
| 844 | 840 | } |
| 845 | 841 | else if (offset >= 0x600000 && offset < 0x700000) |
| 846 | 842 | { |
| 847 | | if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 */ |
| 843 | if (m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 */ |
| 848 | 844 | logerror("(PC=%06x) snes_w_bank1: Attempt to write to reserved address: %X = %02X\n", space.device().safe_pc(), offset, data); |
| 849 | 845 | else |
| 850 | 846 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n", space.device().safe_pc(), offset); |
| 851 | 847 | } |
| 852 | 848 | else if (offset >= 0x700000) |
| 853 | 849 | { |
| 854 | | if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 */ |
| 850 | if (m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 */ |
| 855 | 851 | { |
| 856 | | if (state->m_cart[0].m_nvram_size > 0x8000) |
| 852 | if (m_cart[0].m_nvram_size > 0x8000) |
| 857 | 853 | { |
| 858 | 854 | // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc. |
| 859 | | int mask = state->m_cart[0].m_nvram_size - 1; |
| 855 | int mask = m_cart[0].m_nvram_size - 1; |
| 860 | 856 | offset = (offset / 0x10000) * 0x8000 + (offset & 0x7fff); |
| 861 | | state->m_cart[0].m_nvram[offset & mask] = data; |
| 857 | m_cart[0].m_nvram[offset & mask] = data; |
| 862 | 858 | } |
| 863 | | else if (state->m_cart[0].m_nvram_size > 0) |
| 859 | else if (m_cart[0].m_nvram_size > 0) |
| 864 | 860 | { |
| 865 | | int mask = state->m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 866 | | state->m_cart[0].m_nvram[offset & mask] = data; |
| 861 | int mask = m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 862 | m_cart[0].m_nvram[offset & mask] = data; |
| 867 | 863 | } |
| 868 | 864 | else |
| 869 | 865 | logerror("(PC=%06x) snes_w_bank1: Attempt to write to reserved address: %X = %02X\n", space.device().safe_pc(), offset, data); |
| r21699 | r21700 | |
| 874 | 870 | } |
| 875 | 871 | |
| 876 | 872 | /* 0x800000 - 0xffffff */ |
| 877 | | WRITE8_HANDLER( snes_w_bank2 ) |
| 873 | WRITE8_MEMBER(snes_state::snes_w_bank2) |
| 878 | 874 | { |
| 879 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 880 | 875 | UINT16 address = offset & 0xffff; |
| 881 | 876 | |
| 882 | 877 | if (offset < 0x400000) |
| r21699 | r21700 | |
| 888 | 883 | } |
| 889 | 884 | else |
| 890 | 885 | { |
| 891 | | if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */ |
| 886 | if (m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */ |
| 892 | 887 | { |
| 893 | 888 | if (offset < 0x700000) |
| 894 | 889 | space.write_byte(offset, data); |
| 895 | 890 | else |
| 896 | 891 | { |
| 897 | | if (state->m_cart[0].m_nvram_size > 0x8000) |
| 892 | if (m_cart[0].m_nvram_size > 0x8000) |
| 898 | 893 | { |
| 899 | 894 | // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc. |
| 900 | | int mask = state->m_cart[0].m_nvram_size - 1; |
| 895 | int mask = m_cart[0].m_nvram_size - 1; |
| 901 | 896 | offset = (offset / 0x10000) * 0x8000 + (offset & 0x7fff); |
| 902 | | state->m_cart[0].m_nvram[offset & mask] = data; |
| 897 | m_cart[0].m_nvram[offset & mask] = data; |
| 903 | 898 | } |
| 904 | | else if (state->m_cart[0].m_nvram_size > 0) |
| 899 | else if (m_cart[0].m_nvram_size > 0) |
| 905 | 900 | { |
| 906 | | int mask = state->m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 907 | | state->m_cart[0].m_nvram[offset & mask] = data; |
| 901 | int mask = m_cart[0].m_nvram_size - 1; /* Limit SRAM size to what's actually present */ |
| 902 | m_cart[0].m_nvram[offset & mask] = data; |
| 908 | 903 | } |
| 909 | 904 | else |
| 910 | 905 | logerror("(PC=%06x) snes_w_bank2: Attempt to write to reserved address: %X = %02X\n", space.device().safe_pc(), offset, data); |
| r21699 | r21700 | |
| 1206 | 1201 | /* for mame we use an init, maybe we will need more for the different games */ |
| 1207 | 1202 | DRIVER_INIT_MEMBER(snes_state,snes) |
| 1208 | 1203 | { |
| 1209 | | UINT8 *rom = memregion("user3")->base(); |
| 1210 | 1204 | snes_ram = auto_alloc_array_clear(machine(), UINT8, 0x1400000); |
| 1211 | 1205 | |
| 1212 | 1206 | m_cart[0].m_rom_size = memregion("user3")->bytes(); |
| 1213 | | m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size); |
| 1214 | | memcpy(m_cart[0].m_rom, rom, m_cart[0].m_rom_size); |
| 1207 | m_cart[0].m_rom = memregion("user3")->base(); |
| 1215 | 1208 | rom_map_setup(m_cart[0].m_rom_size); |
| 1216 | 1209 | |
| 1217 | 1210 | m_cart[0].m_nvram_size = 0; |
| 1218 | | if (rom[0x7fd8] > 0) |
| 1211 | if (m_cart[0].m_rom[0x7fd8] > 0) |
| 1219 | 1212 | { |
| 1220 | | UINT32 nvram_size = (1024 << rom[0x7fd8]); |
| 1213 | UINT32 nvram_size = (1024 << m_cart[0].m_rom[0x7fd8]); |
| 1221 | 1214 | if (nvram_size > 0x40000) |
| 1222 | 1215 | nvram_size = 0x40000; |
| 1223 | 1216 | |
| r21699 | r21700 | |
| 1232 | 1225 | |
| 1233 | 1226 | DRIVER_INIT_MEMBER(snes_state,snes_hirom) |
| 1234 | 1227 | { |
| 1235 | | UINT8 *rom = memregion("user3")->base(); |
| 1236 | 1228 | snes_ram = auto_alloc_array(machine(), UINT8, 0x1400000); |
| 1237 | 1229 | memset(snes_ram, 0, 0x1400000); |
| 1238 | 1230 | |
| 1239 | 1231 | m_cart[0].m_rom_size = memregion("user3")->bytes(); |
| 1240 | | m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size); |
| 1241 | | memcpy(m_cart[0].m_rom, rom, m_cart[0].m_rom_size); |
| 1232 | m_cart[0].m_rom = memregion("user3")->base(); |
| 1242 | 1233 | rom_map_setup(m_cart[0].m_rom_size); |
| 1243 | 1234 | |
| 1244 | 1235 | m_cart[0].m_nvram_size = 0; |
| 1245 | | if (rom[0xffd8] > 0) |
| 1236 | if (m_cart[0].m_rom[0xffd8] > 0) |
| 1246 | 1237 | { |
| 1247 | | UINT32 nvram_size = (1024 << rom[0xffd8]); |
| 1238 | UINT32 nvram_size = (1024 << m_cart[0].m_rom[0xffd8]); |
| 1248 | 1239 | if (nvram_size > 0x40000) |
| 1249 | 1240 | nvram_size = 0x40000; |
| 1250 | 1241 | |