Mercurial > repos > blastem
comparison genesis.c @ 1907:b021ca0bc375
Some partial work on TMSS registers, more accurate open bus locations and implement machine freezes for unmapped areas in the IO region
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 25 Mar 2020 22:59:59 -0700 |
parents | 2d462aa78349 |
children | 508522f08e4d |
comparison
equal
deleted
inserted
replaced
1906:2d462aa78349 | 1907:b021ca0bc375 |
---|---|
750 } else { | 750 } else { |
751 fatal_error("68K write to unhandled Z80 address %X\n", location); | 751 fatal_error("68K write to unhandled Z80 address %X\n", location); |
752 } | 752 } |
753 } | 753 } |
754 } else { | 754 } else { |
755 location &= 0x1FFF; | 755 if (location < 0x10100) { |
756 if (location < 0x100) { | 756 switch(location >> 1 & 0xFF) |
757 switch(location/2) | |
758 { | 757 { |
759 case 0x1: | 758 case 0x1: |
760 io_data_write(gen->io.ports, value, context->current_cycle); | 759 io_data_write(gen->io.ports, value, context->current_cycle); |
761 break; | 760 break; |
762 case 0x2: | 761 case 0x2: |
797 case 0xF: | 796 case 0xF: |
798 gen->io.ports[2].serial_ctrl = value; | 797 gen->io.ports[2].serial_ctrl = value; |
799 break; | 798 break; |
800 } | 799 } |
801 } else { | 800 } else { |
802 if (location == 0x1100) { | 801 uint32_t masked = location & 0xFFF00; |
802 if (masked == 0x11100) { | |
803 if (value & 1) { | 803 if (value & 1) { |
804 dputs("bus requesting Z80"); | 804 dputs("bus requesting Z80"); |
805 if (z80_enabled) { | 805 if (z80_enabled) { |
806 z80_assert_busreq(gen->z80, context->current_cycle); | 806 z80_assert_busreq(gen->z80, context->current_cycle); |
807 } else { | 807 } else { |
822 z80_clear_busreq(gen->z80, context->current_cycle); | 822 z80_clear_busreq(gen->z80, context->current_cycle); |
823 } else { | 823 } else { |
824 gen->z80->busack = 0; | 824 gen->z80->busack = 0; |
825 } | 825 } |
826 } | 826 } |
827 } else if (location == 0x1200) { | 827 } else if (masked == 0x11200) { |
828 sync_z80(gen->z80, context->current_cycle); | 828 sync_z80(gen->z80, context->current_cycle); |
829 if (value & 1) { | 829 if (value & 1) { |
830 if (z80_enabled) { | 830 if (z80_enabled) { |
831 z80_clear_reset(gen->z80, context->current_cycle); | 831 z80_clear_reset(gen->z80, context->current_cycle); |
832 } else { | 832 } else { |
838 } else { | 838 } else { |
839 gen->z80->reset = 1; | 839 gen->z80->reset = 1; |
840 } | 840 } |
841 ym_reset(gen->ym); | 841 ym_reset(gen->ym); |
842 } | 842 } |
843 } else if (masked != 0x11300 && masked != 0x11000) { | |
844 fatal_error("Machine freeze due to unmapped write to address %X\n", location | 0xA00000); | |
843 } | 845 } |
844 } | 846 } |
845 } | 847 } |
846 return context; | 848 return context; |
847 } | 849 } |
874 if (location < 0x4000) { | 876 if (location < 0x4000) { |
875 value = gen->zram[location & 0x1FFF]; | 877 value = gen->zram[location & 0x1FFF]; |
876 } else if (location < 0x6000) { | 878 } else if (location < 0x6000) { |
877 sync_sound(gen, context->current_cycle); | 879 sync_sound(gen, context->current_cycle); |
878 value = ym_read_status(gen->ym, context->current_cycle, location); | 880 value = ym_read_status(gen->ym, context->current_cycle, location); |
881 } else if (location < 0x7F00) { | |
882 value = 0xFF; | |
879 } else { | 883 } else { |
884 fatal_error("Machine freeze due to read of Z80 VDP memory window by 68K: %X\n", location | 0xA00000); | |
880 value = 0xFF; | 885 value = 0xFF; |
881 } | 886 } |
882 } else { | 887 } else { |
883 value = 0xFF; | 888 value = 0xFF; |
884 } | 889 } |
885 } else { | 890 } else { |
886 location &= 0x1FFF; | 891 if (location < 0x10100) { |
887 if (location < 0x100) { | 892 switch(location >> 1 & 0xFF) |
888 switch(location/2) | |
889 { | 893 { |
890 case 0x0: | 894 case 0x0: |
891 //version bits should be 0 for now since we're not emulating TMSS | 895 //version bits should be 0 for now since we're not emulating TMSS |
892 value = gen->version_reg; | 896 value = gen->version_reg; |
893 break; | 897 break; |
935 break; | 939 break; |
936 case 0xF: | 940 case 0xF: |
937 value = gen->io.ports[2].serial_ctrl; | 941 value = gen->io.ports[2].serial_ctrl; |
938 break; | 942 break; |
939 default: | 943 default: |
940 value = 0xFF; | 944 value = get_open_bus_value(&gen->header) >> 8; |
941 } | 945 } |
942 } else { | 946 } else { |
943 if (location == 0x1100) { | 947 uint32_t masked = location & 0xFFF00; |
948 if (masked == 0x11100) { | |
944 value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : !gen->z80->busack; | 949 value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : !gen->z80->busack; |
945 value |= (get_open_bus_value(&gen->header) >> 8) & 0xFE; | 950 value |= (get_open_bus_value(&gen->header) >> 8) & 0xFE; |
946 dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset); | 951 dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset); |
947 } else if (location == 0x1200) { | 952 } else if (masked == 0x11200) { |
948 value = !gen->z80->reset; | 953 value = !gen->z80->reset; |
954 } else if (masked == 0x11300 || masked == 0x11000) { | |
955 //A11300 is apparently completely unused | |
956 //A11000 is the memory control register which I am assuming is write only | |
957 value = get_open_bus_value(&gen->header) >> 8; | |
949 } else { | 958 } else { |
959 location |= 0xA00000; | |
960 fatal_error("Machine freeze due to read of unmapped IO location %X\n", location); | |
950 value = 0xFF; | 961 value = 0xFF; |
951 printf("Byte read of unknown IO location: %X\n", location); | |
952 } | 962 } |
953 } | 963 } |
954 } | 964 } |
955 return value; | 965 return value; |
956 } | 966 } |
1056 | 1066 |
1057 gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF; | 1067 gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF; |
1058 update_z80_bank_pointer(context->system); | 1068 update_z80_bank_pointer(context->system); |
1059 | 1069 |
1060 return context; | 1070 return context; |
1071 } | |
1072 | |
1073 static uint16_t unused_read(uint32_t location, void *vcontext) | |
1074 { | |
1075 m68k_context *context = vcontext; | |
1076 genesis_context *gen = context->system; | |
1077 if ((location >= 0xA13000 && location < 0xA13100) || (location >= 0xA12000 && location < 0xA12100)) { | |
1078 //Only called if the cart/exp doesn't have a more specific handler for this region | |
1079 return get_open_bus_value(&gen->header); | |
1080 } else if (location == 0xA14000 || location == 0xA14002) { | |
1081 if (gen->version_reg & 0xF) { | |
1082 return gen->tmss_lock[location >> 1 & 1]; | |
1083 } else { | |
1084 fatal_error("Machine freeze due to read from TMSS lock when TMSS is not present %X\n", location); | |
1085 return 0xFFFF; | |
1086 } | |
1087 } else if (location == 0xA14100) { | |
1088 if (gen->version_reg & 0xF) { | |
1089 return get_open_bus_value(&gen->header); | |
1090 } else { | |
1091 fatal_error("Machine freeze due to read from TMSS control when TMSS is not present %X\n", location); | |
1092 return 0xFFFF; | |
1093 } | |
1094 } else { | |
1095 fatal_error("Machine freeze due to unmapped read from %X\n", location); | |
1096 return 0xFFFF; | |
1097 } | |
1098 } | |
1099 | |
1100 static uint8_t unused_read_b(uint32_t location, void *vcontext) | |
1101 { | |
1102 uint16_t v = unused_read(location & 0xFFFFFE, vcontext); | |
1103 if (location & 1) { | |
1104 return v; | |
1105 } else { | |
1106 return v >> 8; | |
1107 } | |
1108 } | |
1109 | |
1110 static void *unused_write(uint32_t location, void *vcontext, uint16_t value) | |
1111 { | |
1112 m68k_context *context = vcontext; | |
1113 genesis_context *gen = context->system; | |
1114 uint8_t has_tmss = gen->version_reg & 0xF; | |
1115 if (has_tmss && (location == 0xA14000 || location == 0xA14002)) { | |
1116 gen->tmss_lock[location >> 1 & 1] = value; | |
1117 } else if (has_tmss && location == 0xA14100) { | |
1118 //TODO: implement TMSS control register | |
1119 } else { | |
1120 fatal_error("Machine freeze due to unmapped write to %X\n", location); | |
1121 } | |
1122 return vcontext; | |
1123 } | |
1124 | |
1125 static void *unused_write_b(uint32_t location, void *vcontext, uint8_t value) | |
1126 { | |
1127 m68k_context *context = vcontext; | |
1128 genesis_context *gen = context->system; | |
1129 uint8_t has_tmss = gen->version_reg & 0xF; | |
1130 if (has_tmss && location >= 0xA14000 && location <= 0xA14003) { | |
1131 uint32_t offset = location >> 1 & 1; | |
1132 if (location & 1) { | |
1133 gen->tmss_lock[offset] &= 0xFF00; | |
1134 gen->tmss_lock[offset] |= value; | |
1135 } else { | |
1136 gen->tmss_lock[offset] &= 0xFF; | |
1137 gen->tmss_lock[offset] |= value << 8; | |
1138 } | |
1139 } else if (has_tmss && (location == 0xA14100 || location == 0xA14101)) { | |
1140 //TODO: implement TMSS control register | |
1141 } else { | |
1142 fatal_error("Machine freeze due to unmapped byte write to %X\n", location); | |
1143 } | |
1144 return vcontext; | |
1061 } | 1145 } |
1062 | 1146 |
1063 static void set_speed_percent(system_header * system, uint32_t percent) | 1147 static void set_speed_percent(system_header * system, uint32_t percent) |
1064 { | 1148 { |
1065 genesis_context *context = (genesis_context *)system; | 1149 genesis_context *context = (genesis_context *)system; |
1546 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, | 1630 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, |
1547 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, | 1631 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, |
1548 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, | 1632 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, |
1549 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, | 1633 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, |
1550 (read_16_fun)io_read_w, (write_16_fun)io_write_w, | 1634 (read_16_fun)io_read_w, (write_16_fun)io_write_w, |
1551 (read_8_fun)io_read, (write_8_fun)io_write} | 1635 (read_8_fun)io_read, (write_8_fun)io_write}, |
1636 {0x000000, 0xFFFFFF, 0xFFFFFF, 0, 0, 0, NULL, | |
1637 (read_16_fun)unused_read, (write_16_fun)unused_write, | |
1638 (read_8_fun)unused_read_b, (write_8_fun)unused_write_b} | |
1552 }; | 1639 }; |
1553 static tern_node *rom_db; | 1640 static tern_node *rom_db; |
1554 if (!rom_db) { | 1641 if (!rom_db) { |
1555 rom_db = load_rom_db(); | 1642 rom_db = load_rom_db(); |
1556 } | 1643 } |