trunk/src/emu/bus/nes/bootleg.c
r32462 | r32463 | |
759 | 759 | READ8_MEMBER(nes_asn_device::read_m) |
760 | 760 | { |
761 | 761 | LOG_MMC(("Ai Senshi Nicol read_m, offset: %04x\n", offset)); |
762 | | return m_prg[((m_latch * 0x2000) + (offset & 0x1fff)) & (m_prg.count() - 1)]; |
| 762 | return m_prg[((m_latch * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)]; |
763 | 763 | } |
764 | 764 | |
765 | 765 | |
r32462 | r32463 | |
923 | 923 | READ8_MEMBER(nes_whirl2706_device::read_m) |
924 | 924 | { |
925 | 925 | LOG_MMC(("whirl2706 read_m, offset: %04x\n", offset)); |
926 | | return m_prg[(m_latch * 0x2000 + (offset & 0x1fff)) & (m_prg.count() - 1)]; |
| 926 | return m_prg[(m_latch * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)]; |
927 | 927 | } |
928 | 928 | |
929 | 929 | /*------------------------------------------------- |
r32462 | r32463 | |
1060 | 1060 | READ8_MEMBER(nes_smb2ja_device::read_m) |
1061 | 1061 | { |
1062 | 1062 | LOG_MMC(("smb2ja read_m, offset: %04x\n", offset)); |
1063 | | return m_prg[(0xfe * 0x2000 + (offset & 0x1fff)) & (m_prg.count() - 1)]; |
| 1063 | return m_prg[(0xfe * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)]; |
1064 | 1064 | } |
1065 | 1065 | |
1066 | 1066 | /*------------------------------------------------- |
r32462 | r32463 | |
1118 | 1118 | READ8_MEMBER(nes_smb2jb_device::read_m) |
1119 | 1119 | { |
1120 | 1120 | LOG_MMC(("smb2jb read_m, offset: %04x\n", offset)); |
1121 | | return m_prg[((0x0f * 0x2000) + (offset & 0x1fff)) & (m_prg.count() - 1)]; |
| 1121 | return m_prg[((0x0f * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)]; |
1122 | 1122 | } |
1123 | 1123 | |
1124 | 1124 | /* This goes to 0x4020-0x403f & 0x40a0-0x40bf */ |
trunk/src/emu/bus/nes/nes_slot.c
r32462 | r32463 | |
104 | 104 | |
105 | 105 | device_nes_cart_interface::device_nes_cart_interface(const machine_config &mconfig, device_t &device) |
106 | 106 | : device_slot_card_interface(mconfig, device), |
| 107 | m_prg(NULL), |
| 108 | m_vrom(NULL), |
107 | 109 | m_ciram(NULL), |
| 110 | m_prg_size(0), |
| 111 | m_vrom_size(0), |
108 | 112 | m_mapper_sram(NULL), |
109 | 113 | m_mapper_sram_size(0), |
110 | 114 | m_ce_mask(0), |
r32462 | r32463 | |
140 | 144 | // pointer allocators |
141 | 145 | //------------------------------------------------- |
142 | 146 | |
143 | | void device_nes_cart_interface::prg_alloc(size_t size) |
| 147 | void device_nes_cart_interface::prg_alloc(size_t size, const char *tag) |
144 | 148 | { |
145 | | m_prg.resize(size); |
146 | | m_prg_chunks = size / 0x4000; |
147 | | if (size % 0x2000) |
| 149 | if (m_prg == NULL) |
148 | 150 | { |
149 | | // A few pirate carts have PRG made of 32K + 2K or some weird similar config |
150 | | // in this case we treat the banking as if this 'extra' PRG is not present and |
151 | | // the pcb code has to handle it by accessing directly m_prg! |
152 | | printf("Warning! The loaded PRG has size not a multiple of 8KB (0x%X)\n", (UINT32)size); |
153 | | m_prg_chunks--; |
154 | | } |
155 | | |
156 | | m_prg_mask = ((m_prg_chunks << 1) - 1); |
157 | | |
158 | | // printf("first mask %x!\n", m_prg_mask); |
159 | | if ((m_prg_chunks << 1) & m_prg_mask) |
160 | | { |
161 | | int mask_bits = 0, temp = (m_prg_chunks << 1), mapsize; |
162 | | // contrary to what happens with later systems, like e.g. SNES or MD, |
163 | | // only half a dozen of NES carts have PRG which is not a power of 2 |
164 | | // so we use this bank_map only as an exception |
165 | | // printf("uneven rom!\n"); |
166 | | |
167 | | // 1. redefine mask as (next power of 2)-1 |
168 | | for (; temp; ) |
| 151 | astring tempstring(tag); |
| 152 | tempstring.cat(NESSLOT_PRGROM_REGION_TAG); |
| 153 | m_prg = device().machine().memory().region_alloc(tempstring, size, 1, ENDIANNESS_LITTLE)->base(); |
| 154 | m_prg_size = size; |
| 155 | m_prg_chunks = size / 0x4000; |
| 156 | if (size % 0x2000) |
169 | 157 | { |
170 | | mask_bits++; |
171 | | temp >>= 1; |
| 158 | // A few pirate carts have PRG made of 32K + 2K or some weird similar config |
| 159 | // in this case we treat the banking as if this 'extra' PRG is not present and |
| 160 | // the pcb code has to handle it by accessing directly m_prg! |
| 161 | printf("Warning! The loaded PRG has size not a multiple of 8KB (0x%X)\n", (UINT32)size); |
| 162 | m_prg_chunks--; |
172 | 163 | } |
173 | | m_prg_mask = (1 << mask_bits) - 1; |
174 | | // printf("new mask %x!\n", m_prg_mask); |
175 | | mapsize = (1 << mask_bits)/2; |
176 | 164 | |
177 | | // 2. create a bank_map for banks in the range mask/2 -> mask |
178 | | m_prg_bank_map.resize(mapsize); |
| 165 | m_prg_mask = ((m_prg_chunks << 1) - 1); |
179 | 166 | |
180 | | // 3. fill the bank_map accounting for mirrors |
181 | | int j; |
182 | | for (j = mapsize; j < (m_prg_chunks << 1); j++) |
183 | | m_prg_bank_map[j - mapsize] = j; |
184 | | |
185 | | while (j % mapsize) |
| 167 | // printf("first mask %x!\n", m_prg_mask); |
| 168 | if ((m_prg_chunks << 1) & m_prg_mask) |
186 | 169 | { |
187 | | int k = 0, repeat_banks; |
188 | | while ((j % (mapsize >> k)) && k < mask_bits) |
189 | | k++; |
190 | | repeat_banks = j % (mapsize >> (k - 1)); |
191 | | for (int l = 0; l < repeat_banks; l++) |
192 | | m_prg_bank_map[(j - mapsize) + l] = m_prg_bank_map[(j - mapsize) + l - repeat_banks]; |
193 | | j += repeat_banks; |
194 | | } |
195 | | |
196 | | // check bank map! |
| 170 | int mask_bits = 0, temp = (m_prg_chunks << 1), mapsize; |
| 171 | // contrary to what happens with later systems, like e.g. SNES or MD, |
| 172 | // only half a dozen of NES carts have PRG which is not a power of 2 |
| 173 | // so we use this bank_map only as an exception |
| 174 | // printf("uneven rom!\n"); |
| 175 | |
| 176 | // 1. redefine mask as (next power of 2)-1 |
| 177 | for (; temp; ) |
| 178 | { |
| 179 | mask_bits++; |
| 180 | temp >>= 1; |
| 181 | } |
| 182 | m_prg_mask = (1 << mask_bits) - 1; |
| 183 | // printf("new mask %x!\n", m_prg_mask); |
| 184 | mapsize = (1 << mask_bits)/2; |
| 185 | |
| 186 | // 2. create a bank_map for banks in the range mask/2 -> mask |
| 187 | m_prg_bank_map.resize(mapsize); |
| 188 | |
| 189 | // 3. fill the bank_map accounting for mirrors |
| 190 | int j; |
| 191 | for (j = mapsize; j < (m_prg_chunks << 1); j++) |
| 192 | m_prg_bank_map[j - mapsize] = j; |
| 193 | |
| 194 | while (j % mapsize) |
| 195 | { |
| 196 | int k = 0, repeat_banks; |
| 197 | while ((j % (mapsize >> k)) && k < mask_bits) |
| 198 | k++; |
| 199 | repeat_banks = j % (mapsize >> (k - 1)); |
| 200 | for (int l = 0; l < repeat_banks; l++) |
| 201 | m_prg_bank_map[(j - mapsize) + l] = m_prg_bank_map[(j - mapsize) + l - repeat_banks]; |
| 202 | j += repeat_banks; |
| 203 | } |
| 204 | |
| 205 | // check bank map! |
197 | 206 | // for (int i = 0; i < mapsize; i++) |
198 | 207 | // { |
199 | 208 | // printf("bank %3d = %3d\t", i, m_prg_bank_map[i]); |
200 | 209 | // if ((i%8) == 7) |
201 | 210 | // printf("\n"); |
202 | 211 | // } |
| 212 | } |
203 | 213 | } |
204 | 214 | } |
205 | 215 | |
206 | | void device_nes_cart_interface::prgram_alloc(size_t size) |
| 216 | void device_nes_cart_interface::vrom_alloc(size_t size, const char *tag) |
207 | 217 | { |
208 | | m_prgram.resize(size); |
| 218 | if (m_vrom == NULL) |
| 219 | { |
| 220 | astring tempstring(tag); |
| 221 | tempstring.cat(NESSLOT_CHRROM_REGION_TAG); |
| 222 | m_vrom = device().machine().memory().region_alloc(tempstring, size, 1, ENDIANNESS_LITTLE)->base(); |
| 223 | m_vrom_size = size; |
| 224 | m_vrom_chunks = size / 0x2000; |
| 225 | } |
209 | 226 | } |
210 | 227 | |
211 | | void device_nes_cart_interface::vrom_alloc(size_t size) |
| 228 | void device_nes_cart_interface::prgram_alloc(size_t size) |
212 | 229 | { |
213 | | m_vrom.resize(size); |
214 | | m_vrom_chunks = size / 0x2000; |
| 230 | m_prgram.resize(size); |
215 | 231 | } |
216 | 232 | |
217 | 233 | void device_nes_cart_interface::vram_alloc(size_t size) |
r32462 | r32463 | |
669 | 685 | { |
670 | 686 | if (m_prg_bank_mem[i]) |
671 | 687 | { |
672 | | m_prg_bank_mem[i]->configure_entries(0, m_prg.count() / 0x2000, m_prg, 0x2000); |
| 688 | m_prg_bank_mem[i]->configure_entries(0, m_prg_size / 0x2000, m_prg, 0x2000); |
673 | 689 | m_prg_bank_mem[i]->set_entry(i); |
674 | 690 | m_prg_bank[i] = i; |
675 | 691 | } |
r32462 | r32463 | |
732 | 748 | device_slot_interface(mconfig, *this), |
733 | 749 | m_crc_hack(0), |
734 | 750 | m_pcb_id(NO_BOARD), |
735 | | m_must_be_loaded(1), |
736 | | m_empty(TRUE) |
| 751 | m_must_be_loaded(1) |
737 | 752 | { |
738 | 753 | } |
739 | 754 | |
r32462 | r32463 | |
770 | 785 | void nes_cart_slot_device::pcb_start(UINT8 *ciram_ptr) |
771 | 786 | { |
772 | 787 | if (m_cart) |
773 | | m_cart->pcb_start(machine(), ciram_ptr, cart_mounted()); |
| 788 | m_cart->pcb_start(machine(), ciram_ptr, exists()); |
774 | 789 | } |
775 | 790 | |
776 | 791 | void nes_cart_slot_device::pcb_reset() |
r32462 | r32463 | |
835 | 850 | } |
836 | 851 | |
837 | 852 | call_load_ines(); |
838 | | m_empty = FALSE; |
839 | 853 | } |
840 | 854 | else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) /* If header starts with 'UNIF' it is UNIF */ |
841 | 855 | { |
r32462 | r32463 | |
846 | 860 | } |
847 | 861 | |
848 | 862 | call_load_unif(); |
849 | | m_empty = FALSE; |
850 | 863 | } |
851 | 864 | else |
852 | 865 | { |
r32462 | r32463 | |
855 | 868 | } |
856 | 869 | } |
857 | 870 | else |
858 | | { |
859 | 871 | call_load_pcb(); |
860 | | m_empty = FALSE; |
861 | | } |
862 | 872 | } |
863 | 873 | |
864 | 874 | return IMAGE_INIT_PASS; |
trunk/src/emu/bus/nes/nes_slot.h
r32462 | r32463 | |
176 | 176 | // hack until disk system is made modern! |
177 | 177 | virtual void disk_flip_side() { } |
178 | 178 | |
179 | | void prg_alloc(size_t size); |
| 179 | void prg_alloc(size_t size, const char *tag); |
| 180 | void vrom_alloc(size_t size, const char *tag); |
180 | 181 | void prgram_alloc(size_t size); |
181 | | void vrom_alloc(size_t size); |
182 | 182 | void vram_alloc(size_t size); |
183 | 183 | void battery_alloc(size_t size); |
184 | 184 | |
r32462 | r32463 | |
204 | 204 | UINT8* get_battery_base() { return m_battery; } |
205 | 205 | UINT8* get_mapper_sram_base() { return m_mapper_sram; } |
206 | 206 | |
207 | | UINT32 get_prg_size() { return m_prg.bytes(); } |
| 207 | UINT32 get_prg_size() { return m_prg_size; } |
208 | 208 | UINT32 get_prgram_size() { return m_prgram.bytes(); } |
209 | | UINT32 get_vrom_size() { return m_vrom.bytes(); } |
| 209 | UINT32 get_vrom_size() { return m_vrom_size; } |
210 | 210 | UINT32 get_vram_size() { return m_vram.bytes(); } |
211 | 211 | UINT32 get_battery_size() { return m_battery.bytes(); } |
212 | 212 | UINT32 get_mapper_sram_size() { return m_mapper_sram_size; } |
r32462 | r32463 | |
226 | 226 | protected: |
227 | 227 | |
228 | 228 | // internal state |
229 | | dynamic_buffer m_prg; |
| 229 | UINT8 *m_prg; |
| 230 | UINT8 *m_vrom; |
| 231 | UINT8 *m_ciram; |
230 | 232 | dynamic_buffer m_prgram; |
231 | | dynamic_buffer m_vrom; |
232 | 233 | dynamic_buffer m_vram; |
233 | 234 | dynamic_buffer m_battery; |
234 | | UINT8 *m_ciram; |
| 235 | UINT32 m_prg_size; |
| 236 | UINT32 m_vrom_size; |
235 | 237 | |
236 | 238 | // HACK: to reduce tagmap lookups for PPU-related IRQs, we add a hook to the |
237 | 239 | // main NES CPU here, even if it does not belong to this device. |
r32462 | r32463 | |
364 | 366 | const char * get_default_card_unif(UINT8 *ROM, UINT32 len); |
365 | 367 | const char * nes_get_slot(int pcb_id); |
366 | 368 | int nes_get_pcb_id(const char *slot); |
367 | | bool cart_mounted() { return !m_empty; } |
368 | 369 | |
369 | 370 | // reading and writing |
370 | 371 | virtual DECLARE_READ8_MEMBER(read_l); |
r32462 | r32463 | |
396 | 397 | device_nes_cart_interface* m_cart; |
397 | 398 | int m_pcb_id; |
398 | 399 | bool m_must_be_loaded; |
399 | | bool m_empty; |
400 | 400 | }; |
401 | 401 | |
402 | 402 | // device type definition |
r32462 | r32463 | |
407 | 407 | DEVICE CONFIGURATION MACROS |
408 | 408 | ***************************************************************************/ |
409 | 409 | |
| 410 | #define NESSLOT_PRGROM_REGION_TAG ":cart:prg_rom" |
| 411 | #define NESSLOT_CHRROM_REGION_TAG ":cart:chr_rom" |
| 412 | |
| 413 | |
410 | 414 | #define MCFG_NES_CARTRIDGE_ADD(_tag, _slot_intf, _def_slot) \ |
411 | 415 | MCFG_DEVICE_ADD(_tag, NES_CART_SLOT, 0) \ |
412 | 416 | MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) |
r32462 | r32463 | |
414 | 418 | #define MCFG_NES_CARTRIDGE_NOT_MANDATORY \ |
415 | 419 | static_cast<nes_cart_slot_device *>(device)->set_must_be_loaded(FALSE); |
416 | 420 | |
| 421 | |
417 | 422 | // Hacky configuration to add a slot with fixed disksys interface |
418 | 423 | #define MCFG_DISKSYS_ADD(_tag, _slot_intf, _def_slot) \ |
419 | 424 | MCFG_DEVICE_ADD(_tag, NES_CART_SLOT, 0) \ |