trunk/src/mess/drivers/snes.c
| r23520 | r23521 | |
| 37 | 37 | #include "machine/sns_rom.h" |
| 38 | 38 | #include "machine/sns_rom21.h" |
| 39 | 39 | #include "machine/sns_bsx.h" |
| 40 | #include "machine/sns_sa1.h" |
| 40 | 41 | #include "machine/sns_sdd1.h" |
| 41 | 42 | #include "machine/sns_sfx.h" |
| 42 | 43 | #include "machine/sns_spc7110.h" |
| r23520 | r23521 | |
| 70 | 71 | DECLARE_READ8_MEMBER( snessfx_lo_r ); |
| 71 | 72 | DECLARE_WRITE8_MEMBER( snessfx_hi_w ); |
| 72 | 73 | DECLARE_WRITE8_MEMBER( snessfx_lo_w ); |
| 74 | DECLARE_READ8_MEMBER( snessa1_hi_r ); |
| 75 | DECLARE_READ8_MEMBER( snessa1_lo_r ); |
| 76 | DECLARE_WRITE8_MEMBER( snessa1_hi_w ); |
| 77 | DECLARE_WRITE8_MEMBER( snessa1_lo_w ); |
| 73 | 78 | DECLARE_READ8_MEMBER( snes7110_hi_r ); |
| 74 | 79 | DECLARE_READ8_MEMBER( snes7110_lo_r ); |
| 75 | 80 | DECLARE_WRITE8_MEMBER( snes7110_hi_w ); |
| r23520 | r23521 | |
| 515 | 520 | } |
| 516 | 521 | |
| 517 | 522 | //--------------------------------------------------------------------------------- |
| 523 | // LoROM + SA-1 |
| 524 | //--------------------------------------------------------------------------------- |
| 525 | |
| 526 | READ8_MEMBER( snes_console_state::snessa1_hi_r ) |
| 527 | { |
| 528 | UINT16 address = offset & 0xffff; |
| 529 | |
| 530 | if (offset < 0x400000) |
| 531 | { |
| 532 | if (address < 0x2000) |
| 533 | return space.read_byte(0x7e0000 + address); |
| 534 | else if (address < 0x6000) |
| 535 | { |
| 536 | if (address >= 0x2200 && address < 0x2400) |
| 537 | return m_cartslot->chip_read(space, offset); // SA-1 Regs |
| 538 | else if (address >= 0x3000 && address < 0x3800) |
| 539 | return m_cartslot->chip_read(space, offset); // Internal SA-1 RAM (2K) |
| 540 | else |
| 541 | return snes_r_io(space, address); |
| 542 | } |
| 543 | else if (address < 0x8000) |
| 544 | return m_cartslot->chip_read(space, offset); // SA-1 BWRAM |
| 545 | else |
| 546 | return m_cartslot->read_h(space, offset); |
| 547 | } |
| 548 | else |
| 549 | return m_cartslot->read_h(space, offset); |
| 550 | } |
| 551 | |
| 552 | READ8_MEMBER( snes_console_state::snessa1_lo_r ) |
| 553 | { |
| 554 | UINT16 address = offset & 0xffff; |
| 555 | |
| 556 | if (offset < 0x400000) |
| 557 | { |
| 558 | if (address < 0x2000) |
| 559 | return space.read_byte(0x7e0000 + address); |
| 560 | else if (address < 0x6000) |
| 561 | { |
| 562 | if (address >= 0x2200 && address < 0x2400) |
| 563 | return m_cartslot->chip_read(space, offset); // SA-1 Regs |
| 564 | else if (address >= 0x3000 && address < 0x3800) |
| 565 | return m_cartslot->chip_read(space, offset); // Internal SA-1 RAM (2K) |
| 566 | else |
| 567 | return snes_r_io(space, address); |
| 568 | } |
| 569 | else if (address < 0x8000) |
| 570 | return m_cartslot->chip_read(space, offset); // SA-1 BWRAM |
| 571 | else |
| 572 | return m_cartslot->read_l(space, offset); |
| 573 | } |
| 574 | else if (offset < 0x500000) |
| 575 | return m_cartslot->chip_read(space, offset); // SA-1 BWRAM (not mirrored above!) |
| 576 | else |
| 577 | return snes_r_io(space, address); // nothing mapped here! |
| 578 | } |
| 579 | |
| 580 | WRITE8_MEMBER( snes_console_state::snessa1_hi_w ) |
| 581 | { |
| 582 | UINT16 address = offset & 0xffff; |
| 583 | if (offset < 0x400000) |
| 584 | { |
| 585 | if (address < 0x2000) |
| 586 | space.write_byte(0x7e0000 + address, data); |
| 587 | else if (address < 0x6000) |
| 588 | { |
| 589 | if (address >= 0x2200 && address < 0x2400) |
| 590 | m_cartslot->chip_write(space, offset, data); // SA-1 Regs |
| 591 | else if (address >= 0x3000 && address < 0x3800) |
| 592 | m_cartslot->chip_write(space, offset, data); // Internal SA-1 RAM (2K) |
| 593 | else |
| 594 | snes_w_io(space, address, data); |
| 595 | } |
| 596 | else if (address < 0x8000) |
| 597 | m_cartslot->chip_write(space, offset, data); // SA-1 BWRAM |
| 598 | } |
| 599 | } |
| 600 | |
| 601 | WRITE8_MEMBER( snes_console_state::snessa1_lo_w ) |
| 602 | { |
| 603 | if (offset >= 0x400000 && offset < 0x500000) |
| 604 | m_cartslot->chip_write(space, offset, data); // SA-1 BWRAM (not mirrored above!) |
| 605 | else |
| 606 | snessfx_hi_w(space, offset, data, 0xff); |
| 607 | } |
| 608 | |
| 609 | //--------------------------------------------------------------------------------- |
| 518 | 610 | // HiROM + SPC-7110 |
| 519 | 611 | //--------------------------------------------------------------------------------- |
| 520 | 612 | |
| r23520 | r23521 | |
| 1484 | 1576 | SLOT_INTERFACE_INTERNAL("lorom_dsp", SNS_LOROM_NECDSP) |
| 1485 | 1577 | SLOT_INTERFACE_INTERNAL("lorom_dsp4", SNS_LOROM_NECDSP) |
| 1486 | 1578 | SLOT_INTERFACE_INTERNAL("lorom_obc1", SNS_LOROM_OBC1) |
| 1487 | | SLOT_INTERFACE_INTERNAL("lorom_sa1", SNS_LOROM) // Cart + SA1 - unsupported |
| 1579 | SLOT_INTERFACE_INTERNAL("lorom_sa1", SNS_LOROM_SA1) // Cart + SA1 - unsupported |
| 1488 | 1580 | SLOT_INTERFACE_INTERNAL("lorom_sdd1", SNS_LOROM_SDD1) |
| 1489 | 1581 | SLOT_INTERFACE_INTERNAL("lorom_sfx", SNS_LOROM_SUPERFX) |
| 1490 | 1582 | SLOT_INTERFACE_INTERNAL("lorom_sgb", SNS_LOROM) // SuperGB base cart - unsupported |
| r23520 | r23521 | |
| 1535 | 1627 | case SNES_CX4: // this still uses the old simulation instead of emulating the CPU |
| 1536 | 1628 | case SNES_ST010: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w |
| 1537 | 1629 | case SNES_ST011: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w |
| 1538 | | case SNES_SA1: // still unemulated |
| 1539 | 1630 | case SNES_ST018: // still unemulated |
| 1540 | 1631 | case SNES_Z80GB: // still unemulated |
| 1541 | 1632 | break; |
| 1633 | case SNES_SA1: // skeleton support |
| 1634 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snessa1_lo_r),this), write8_delegate(FUNC(snes_console_state::snessa1_lo_w),this)); |
| 1635 | m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snessa1_hi_r),this), write8_delegate(FUNC(snes_console_state::snessa1_hi_w),this)); |
| 1636 | set_5a22_map(m_maincpu); |
| 1637 | break; |
| 1542 | 1638 | case SNES_DSP: |
| 1543 | 1639 | m_maincpu->space(AS_PROGRAM).install_read_handler(0x208000, 0x20ffff, 0, 0x9f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)m_cartslot)); |
| 1544 | 1640 | m_maincpu->space(AS_PROGRAM).install_write_handler(0x208000, 0x20ffff, 0, 0x9f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)m_cartslot)); |
trunk/src/mess/machine/sns_sa1.c
| r0 | r23521 | |
| 1 | /*********************************************************************************************************** |
| 2 | |
| 3 | SA-1 add-on chip emulation (for SNES/SFC) |
| 4 | |
| 5 | Copyright MESS Team. |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | |
| 8 | Note: |
| 9 | - SA-1 register description below is based on no$cash docs. |
| 10 | - about bankswitch handling: no matter what is ROM size, at loading the ROM is mirrored up to 8MB and a |
| 11 | rom_bank_map[0x100] array is built as a lookup table for 256x32KB banks filling the 8MB accessible ROM |
| 12 | area; this allows to handle any 0-7 value written to CXB/DXB/EXB/FXB SA-1 registers without any masking! |
| 13 | - about BWRAM "bitmap mode": in 2bits mode |
| 14 | 600000h.Bit0-1 mirrors to 400000h.Bit0-1 |
| 15 | 600001h.Bit0-1 mirrors to 400000h.Bit2-3 |
| 16 | 600002h.Bit0-1 mirrors to 400000h.Bit4-5 |
| 17 | 600003h.Bit0-1 mirrors to 400000h.Bit6-7 |
| 18 | ... |
| 19 | in 4bits mode |
| 20 | 600000h.Bit0-3 mirrors to 400000h.Bit0-3 |
| 21 | 600001h.Bit0-3 mirrors to 400000h.Bit4-7 |
| 22 | 600002h.Bit0-3 mirrors to 400001h.Bit0-3 |
| 23 | 600003h.Bit0-3 mirrors to 400001h.Bit4-7 |
| 24 | ... |
| 25 | to handle the separate modes, bitmap accesses go to offset + 0x100000 |
| 26 | |
| 27 | TODO: |
| 28 | - test case for BWRAM & IRAM write protect (bsnes does not seem to ever protect either, so it's not implemented |
| 29 | for the moment) |
| 30 | - almost everything CPU related! |
| 31 | |
| 32 | ***********************************************************************************************************/ |
| 33 | |
| 34 | |
| 35 | #include "emu.h" |
| 36 | #include "machine/sns_sa1.h" |
| 37 | |
| 38 | |
| 39 | //------------------------------------------------- |
| 40 | // constructor |
| 41 | //------------------------------------------------- |
| 42 | |
| 43 | const device_type SNS_LOROM_SA1 = &device_creator<sns_sa1_device>; |
| 44 | |
| 45 | |
| 46 | sns_sa1_device::sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 47 | : device_t(mconfig, SNS_LOROM_SA1, "SNES Cart + SA-1", tag, owner, clock, "sns_rom_sa1", __FILE__), |
| 48 | device_sns_cart_interface( mconfig, *this ), |
| 49 | m_sa1(*this, "sa1cpu") |
| 50 | { |
| 51 | } |
| 52 | |
| 53 | |
| 54 | void sns_sa1_device::device_start() |
| 55 | { |
| 56 | } |
| 57 | |
| 58 | /*------------------------------------------------- |
| 59 | mapper specific handlers |
| 60 | -------------------------------------------------*/ |
| 61 | |
| 62 | /*------------------------------------------------- |
| 63 | RAM / SRAM / Registers |
| 64 | -------------------------------------------------*/ |
| 65 | |
| 66 | UINT8 sns_sa1_device::read_regs(UINT32 offset) |
| 67 | { |
| 68 | UINT8 value = 0xff; |
| 69 | offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs |
| 70 | |
| 71 | switch (offset) |
| 72 | { |
| 73 | case 0x100: |
| 74 | // SNES SFR SNES CPU Flag Read (R) |
| 75 | break; |
| 76 | case 0x101: |
| 77 | // SA-1 CFR SA-1 CPU Flag Read (R) |
| 78 | break; |
| 79 | case 0x102: |
| 80 | // SA-1 HCR H-Count Read Lsb / Do Latching (R) |
| 81 | break; |
| 82 | case 0x103: |
| 83 | // SA-1 HCR H-Count Read Msb (R) |
| 84 | break; |
| 85 | case 0x104: |
| 86 | // SA-1 VCR V-Count Read Lsb (R) |
| 87 | break; |
| 88 | case 0x105: |
| 89 | // SA-1 VCR V-Count Read Msb (R) |
| 90 | break; |
| 91 | case 0x106: |
| 92 | // SA-1 MR Arithmetic Result, bit0-7 (Sum/Product/Quotient) (R) |
| 93 | break; |
| 94 | case 0x107: |
| 95 | // SA-1 MR Arithmetic Result, bit8-15 (Sum/Product/Quotient) (R) |
| 96 | break; |
| 97 | case 0x108: |
| 98 | // SA-1 MR Arithmetic Result, bit16-23 (Sum/Product/Remainder) (R) |
| 99 | break; |
| 100 | case 0x109: |
| 101 | // SA-1 MR Arithmetic Result, bit24-31 (Sum/Product/Remainder) (R) |
| 102 | break; |
| 103 | case 0x10a: |
| 104 | // SA-1 MR Arithmetic Result, bit32-39 (Sum) (R) |
| 105 | break; |
| 106 | case 0x10b: |
| 107 | // SA-1 OF Arithmetic Overflow Flag (R) |
| 108 | break; |
| 109 | case 0x10c: |
| 110 | // SA-1 VDP Variable-Length Data Read Port Lsb (R) |
| 111 | break; |
| 112 | case 0x10d: |
| 113 | // SA-1 VDP Variable-Length Data Read Port Msb (R) |
| 114 | break; |
| 115 | case 0x10e: |
| 116 | // SNES VC Version Code Register (R) |
| 117 | break; |
| 118 | default: |
| 119 | logerror("SA-1 Read access to an unmapped reg (%x)", offset); |
| 120 | break; |
| 121 | } |
| 122 | return value; |
| 123 | } |
| 124 | |
| 125 | void sns_sa1_device::write_regs(UINT32 offset, UINT8 data) |
| 126 | { |
| 127 | offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs |
| 128 | |
| 129 | switch (offset) |
| 130 | { |
| 131 | case 0x000: |
| 132 | // SNES CCNT 20h SA-1 CPU Control (W) |
| 133 | break; |
| 134 | case 0x001: |
| 135 | // SNES SIE 00h SNES CPU Int Enable (W) |
| 136 | break; |
| 137 | case 0x002: |
| 138 | // SNES SIC 00h SNES CPU Int Clear (W) |
| 139 | break; |
| 140 | case 0x003: |
| 141 | // SNES CRV - SA-1 CPU Reset Vector Lsb (W) |
| 142 | break; |
| 143 | case 0x004: |
| 144 | // SNES CRV - SA-1 CPU Reset Vector Msb (W) |
| 145 | break; |
| 146 | case 0x005: |
| 147 | // SNES CNV - SA-1 CPU NMI Vector Lsb (W) |
| 148 | break; |
| 149 | case 0x006: |
| 150 | // SNES CNV - SA-1 CPU NMI Vector Msb (W) |
| 151 | break; |
| 152 | case 0x007: |
| 153 | // SNES CIV - SA-1 CPU IRQ Vector Lsb (W) |
| 154 | break; |
| 155 | case 0x008: |
| 156 | // SNES CIV - SA-1 CPU IRQ Vector Msb (W) |
| 157 | break; |
| 158 | case 0x009: |
| 159 | // SA-1 SCNT 00h SNES CPU Control (W) |
| 160 | break; |
| 161 | case 0x00a: |
| 162 | // SA-1 CIE 00h SA-1 CPU Int Enable (W) |
| 163 | break; |
| 164 | case 0x00b: |
| 165 | // SA-1 CIC 00h SA-1 CPU Int Clear (W) |
| 166 | break; |
| 167 | case 0x00c: |
| 168 | // SA-1 SNV - SNES CPU NMI Vector Lsb (W) |
| 169 | break; |
| 170 | case 0x00d: |
| 171 | // SA-1 SNV - SNES CPU NMI Vector Msb (W) |
| 172 | break; |
| 173 | case 0x00e: |
| 174 | // SA-1 SIV - SNES CPU IRQ Vector Lsb (W) |
| 175 | break; |
| 176 | case 0x00f: |
| 177 | // SA-1 SIV - SNES CPU IRQ Vector Msb (W) |
| 178 | break; |
| 179 | case 0x010: |
| 180 | // SA-1 TMC 00h H/V Timer Control (W) |
| 181 | break; |
| 182 | case 0x011: |
| 183 | // SA-1 CTR - SA-1 CPU Timer Restart (W) |
| 184 | break; |
| 185 | case 0x012: |
| 186 | // SA-1 HCNT - Set H-Count Lsb (W) |
| 187 | break; |
| 188 | case 0x013: |
| 189 | // SA-1 HCNT - Set H-Count Msb (W) |
| 190 | break; |
| 191 | case 0x014: |
| 192 | // SA-1 VCNT - Set V-Count Lsb (W) |
| 193 | break; |
| 194 | case 0x015: |
| 195 | // SA-1 VCNT - Set V-Count Msb (W) |
| 196 | break; |
| 197 | case 0x020: |
| 198 | // ROM 1MB bank for [c0-cf] |
| 199 | m_bank_c_hi = BIT(data, 7); |
| 200 | m_bank_c_rom = data & 0x07; |
| 201 | break; |
| 202 | case 0x021: |
| 203 | // ROM 1MB bank for [d0-df] |
| 204 | m_bank_d_hi = BIT(data, 7); |
| 205 | m_bank_d_rom = data & 0x07; |
| 206 | break; |
| 207 | case 0x022: |
| 208 | // ROM 1MB bank for [e0-ef] |
| 209 | m_bank_e_hi = BIT(data, 7); |
| 210 | m_bank_e_rom = data & 0x07; |
| 211 | break; |
| 212 | case 0x023: |
| 213 | // ROM 1MB bank for [f0-ff] |
| 214 | m_bank_f_hi = BIT(data, 7); |
| 215 | m_bank_f_rom = data & 0x07; |
| 216 | break; |
| 217 | case 0x024: |
| 218 | // BWRAM bank from SNES side |
| 219 | m_bwram_snes = data & 0x1f; // max 32x8K banks |
| 220 | break; |
| 221 | case 0x025: |
| 222 | // BWRAM bank & type from SA-1 side |
| 223 | m_bwram_sa1_source = BIT(data, 7); // 0 = normal, 1 = bitmap? |
| 224 | m_bwram_sa1 = data & 0x7f; // up to 128x8K banks here? |
| 225 | break; |
| 226 | case 0x026: |
| 227 | // enable writing to BWRAM from SNES |
| 228 | m_bwram_write_snes = BIT(data, 7); |
| 229 | break; |
| 230 | case 0x027: |
| 231 | // enable writing to BWRAM from SA-1 |
| 232 | m_bwram_write_sa1 = BIT(data, 7); |
| 233 | break; |
| 234 | case 0x028: |
| 235 | // write protected area at bottom of BWRAM |
| 236 | m_bwpa_sa1 = 0x100 * (data & 0x0f); |
| 237 | break; |
| 238 | case 0x029: |
| 239 | // enable writing to IRAM from SNES (1 bit for each 0x100 chunk) |
| 240 | m_iram_write_snes = data; |
| 241 | break; |
| 242 | case 0x02a: |
| 243 | // enable writing to IRAM from SA-1 (1 bit for each 0x100 chunk) |
| 244 | m_iram_write_sa1 = data; |
| 245 | break; |
| 246 | case 0x030: |
| 247 | // SA-1 DCNT 00h DMA Control (W) |
| 248 | break; |
| 249 | case 0x031: |
| 250 | // Both CDMA 00h Character Conversion DMA Parameters (W) |
| 251 | break; |
| 252 | case 0x032: |
| 253 | // Both SDA - DMA Source Device Start Address Lsb (W) |
| 254 | break; |
| 255 | case 0x033: |
| 256 | // Both SDA - DMA Source Device Start Address Mid (W) |
| 257 | break; |
| 258 | case 0x034: |
| 259 | // Both SDA - DMA Source Device Start Address Msb (W) |
| 260 | break; |
| 261 | case 0x035: |
| 262 | // Both DDA - DMA Dest Device Start Address Lsb (W) |
| 263 | break; |
| 264 | case 0x036: |
| 265 | // Both DDA - DMA Dest Device Start Address Mid (Start/I-RAM) (W) |
| 266 | break; |
| 267 | case 0x037: |
| 268 | // Both DDA - DMA Dest Device Start Address Msb (Start/BW-RAM)(W) |
| 269 | break; |
| 270 | case 0x038: |
| 271 | // SA-1 DTC - DMA Terminal Counter Lsb (W) |
| 272 | break; |
| 273 | case 0x039: |
| 274 | // SA-1 DTC - DMA Terminal Counter Msb (W) |
| 275 | break; |
| 276 | case 0x03f: |
| 277 | // Format for BWRAM when mapped to bitmap |
| 278 | m_bwram_sa1_format = BIT(data, 7); // 0 = 4bit, 1 = 2bit |
| 279 | break; |
| 280 | case 0x040: |
| 281 | case 0x041: |
| 282 | case 0x042: |
| 283 | case 0x043: |
| 284 | case 0x044: |
| 285 | case 0x045: |
| 286 | case 0x046: |
| 287 | case 0x047: |
| 288 | case 0x048: |
| 289 | case 0x049: |
| 290 | case 0x04a: |
| 291 | case 0x04b: |
| 292 | case 0x04c: |
| 293 | case 0x04d: |
| 294 | case 0x04e: |
| 295 | case 0x04f: |
| 296 | // SA-1 BRF - Bit Map Register File (2240h..224Fh) (W) |
| 297 | break; |
| 298 | case 0x050: |
| 299 | // SA-1 MCNT 00h Arithmetic Control (W) |
| 300 | break; |
| 301 | case 0x051: |
| 302 | // SA-1 MA - Arithmetic Param A Lsb (Multiplicand/Dividend) (W) |
| 303 | break; |
| 304 | case 0x052: |
| 305 | // SA-1 MA - Arithmetic Param A Msb (Multiplicand/Dividend) (W) |
| 306 | break; |
| 307 | case 0x053: |
| 308 | // SA-1 MB - Arithmetic Param B Lsb (Multiplier/Divisor) (W) |
| 309 | break; |
| 310 | case 0x054: |
| 311 | // SA-1 MB - Arithmetic Param B Msb (Multiplier/Divisor)/Start (W) |
| 312 | break; |
| 313 | case 0x058: |
| 314 | // SA-1 VBD - Variable-Length Bit Processing (W) |
| 315 | break; |
| 316 | case 0x059: |
| 317 | // SA-1 VDA - Var-Length Bit Game Pak ROM Start Address Lsb (W) |
| 318 | break; |
| 319 | case 0x05a: |
| 320 | // SA-1 VDA - Var-Length Bit Game Pak ROM Start Address Mid (W) |
| 321 | break; |
| 322 | case 0x05b: |
| 323 | // SA-1 VDA - Var-Length Bit Game Pak ROM Start Address Msb & Kick |
| 324 | break; |
| 325 | default: |
| 326 | logerror("SA-1 Write access to an unmapped reg (%x) with data %x", offset, data); |
| 327 | break; |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | UINT8 sns_sa1_device::read_iram(UINT32 offset) |
| 332 | { |
| 333 | return m_internal_ram[offset & 0x7ff]; |
| 334 | } |
| 335 | |
| 336 | void sns_sa1_device::write_iram(UINT32 offset, UINT8 data) |
| 337 | { |
| 338 | m_internal_ram[offset & 0x7ff] = data; |
| 339 | } |
| 340 | |
| 341 | UINT8 sns_sa1_device::read_bwram(UINT32 offset) |
| 342 | { |
| 343 | int shift = 0; |
| 344 | UINT8 mask = 0xff; |
| 345 | |
| 346 | if (!m_nvram) |
| 347 | return 0xff; // this should probably never happen, or are there SA-1 games with no BWRAM? |
| 348 | |
| 349 | if (offset < 0x100000) |
| 350 | return m_nvram[offset & (m_nvram_size - 1)]; |
| 351 | |
| 352 | // Bitmap BWRAM |
| 353 | if (m_bwram_sa1_format) |
| 354 | { |
| 355 | // 2bits mode |
| 356 | offset /= 4; |
| 357 | shift = ((offset % 4) * 2); |
| 358 | mask = 0x03; |
| 359 | } |
| 360 | else |
| 361 | { |
| 362 | // 4bits mode |
| 363 | offset /= 2; |
| 364 | shift = ((offset % 2) * 4); |
| 365 | mask = 0x0f; |
| 366 | } |
| 367 | |
| 368 | // only return the correct bits |
| 369 | return (m_nvram[offset & (m_nvram_size - 1)] >> shift) & mask; |
| 370 | } |
| 371 | |
| 372 | void sns_sa1_device::write_bwram(UINT32 offset, UINT8 data) |
| 373 | { |
| 374 | UINT8 mask = 0xff; |
| 375 | |
| 376 | if (!m_nvram) |
| 377 | return; // this should probably never happen, or are there SA-1 games with no BWRAM? |
| 378 | |
| 379 | if (offset < 0x100000) |
| 380 | { |
| 381 | m_nvram[offset & (m_nvram_size - 1)] = data; |
| 382 | return; |
| 383 | } |
| 384 | |
| 385 | // Bitmap BWRAM |
| 386 | if (m_bwram_sa1_format) |
| 387 | { |
| 388 | // 2bits mode |
| 389 | offset /= 4; |
| 390 | data = (data & 0x03) << ((offset % 4) * 2); |
| 391 | mask = 0x03 << ((offset % 4) * 2); |
| 392 | } |
| 393 | else |
| 394 | { |
| 395 | // 4bits mode |
| 396 | offset /= 2; |
| 397 | data = (data & 0x0f) << ((offset % 2) * 4); |
| 398 | mask = 0x0f << ((offset % 2) * 4); |
| 399 | } |
| 400 | |
| 401 | // only change the correct bits, keeping the rest untouched |
| 402 | m_nvram[offset & (m_nvram_size - 1)] = (m_nvram[offset & (m_nvram_size - 1)] & ~mask) | data; |
| 403 | } |
| 404 | |
| 405 | |
| 406 | |
| 407 | /*------------------------------------------------- |
| 408 | Accesses from SNES CPU |
| 409 | -------------------------------------------------*/ |
| 410 | |
| 411 | |
| 412 | READ8_MEMBER(sns_sa1_device::read_l) |
| 413 | { |
| 414 | int bank = 0; |
| 415 | |
| 416 | // ROM is mapped to [00-3f][8000-ffff] only here |
| 417 | if (offset < 0x200000) |
| 418 | { |
| 419 | if (!m_bank_c_hi) // when HiROM mapping is disabled, we always access first 1MB here |
| 420 | bank = (offset / 0x10000) + 0x00; |
| 421 | else // when HiROM mapping is enabled, we mirror [c0-cf][0000-ffff] bank |
| 422 | bank = (offset / 0x10000) + (m_bank_c_rom * 0x20); |
| 423 | |
| 424 | return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; |
| 425 | } |
| 426 | else if (offset < 0x400000) |
| 427 | { |
| 428 | offset -= 0x200000; |
| 429 | if (!m_bank_d_hi) // when HiROM mapping is disabled, we always access second 1MB here |
| 430 | bank = (offset / 0x10000) + 0x20; |
| 431 | else // when HiROM mapping is enabled, we mirror [d0-df][0000-ffff] bank |
| 432 | bank = (offset / 0x10000) + (m_bank_d_rom * 0x20); |
| 433 | |
| 434 | return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; |
| 435 | } |
| 436 | else |
| 437 | return 0; // this should not happen (the driver should only call read_l in the above case) |
| 438 | } |
| 439 | |
| 440 | READ8_MEMBER(sns_sa1_device::read_h) |
| 441 | { |
| 442 | int bank = 0; |
| 443 | |
| 444 | // ROM is mapped to [80-bf][8000-ffff] & [c0-ff][0000-ffff] |
| 445 | if (offset < 0x200000) |
| 446 | { |
| 447 | if (!m_bank_e_hi) // when HiROM mapping is disabled, we always access third 1MB here |
| 448 | bank = (offset / 0x10000) + 0x40; |
| 449 | else // when HiROM mapping is enabled, we mirror [e0-ef][0000-ffff] bank |
| 450 | bank = (offset / 0x10000) + (m_bank_e_rom * 0x20); |
| 451 | |
| 452 | return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; |
| 453 | } |
| 454 | else if (offset < 0x400000) |
| 455 | { |
| 456 | offset -= 0x200000; |
| 457 | if (!m_bank_f_hi) // when HiROM mapping is disabled, we always access fourth 1MB here |
| 458 | bank = (offset / 0x10000) + 0x60; |
| 459 | else // when HiROM mapping is enabled, we mirror [f0-ff][0000-ffff] bank |
| 460 | bank = (offset / 0x10000) + (m_bank_f_rom * 0x20); |
| 461 | |
| 462 | return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; |
| 463 | } |
| 464 | else if (offset < 0x500000) |
| 465 | return m_rom[rom_bank_map[(m_bank_c_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; |
| 466 | else if (offset < 0x600000) |
| 467 | return m_rom[rom_bank_map[(m_bank_d_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; |
| 468 | else if (offset < 0x700000) |
| 469 | return m_rom[rom_bank_map[(m_bank_e_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; |
| 470 | else |
| 471 | return m_rom[rom_bank_map[(m_bank_f_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; |
| 472 | } |
| 473 | |
| 474 | WRITE8_MEMBER(sns_sa1_device::write_l) |
| 475 | { |
| 476 | } |
| 477 | |
| 478 | WRITE8_MEMBER(sns_sa1_device::write_h) |
| 479 | { |
| 480 | } |
| 481 | |
| 482 | READ8_MEMBER( sns_sa1_device::chip_read ) |
| 483 | { |
| 484 | UINT16 address = offset & 0xffff; |
| 485 | |
| 486 | if (offset < 0x400000 && address >= 0x2200 && address < 0x2400) |
| 487 | return read_regs(address & 0x1ff); // SA-1 Regs |
| 488 | |
| 489 | if (offset < 0x400000 && address >= 0x3000 && address < 0x3800) |
| 490 | return read_iram(address & 0x7ff); // Internal SA-1 RAM (2K) |
| 491 | |
| 492 | if (offset < 0x400000 && address >= 0x6000 && address < 0x8000) |
| 493 | return read_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff)); // SA-1 BWRAM |
| 494 | |
| 495 | if (offset >= 0x400000 && offset < 0x500000) |
| 496 | return read_bwram(offset); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored) |
| 497 | |
| 498 | return 0xff; |
| 499 | } |
| 500 | |
| 501 | |
| 502 | WRITE8_MEMBER( sns_sa1_device::chip_write ) |
| 503 | { |
| 504 | UINT16 address = offset & 0xffff; |
| 505 | |
| 506 | if (offset < 0x400000 && address >= 0x2200 && address < 0x2400) |
| 507 | write_regs(address & 0x1ff, data); // SA-1 Regs |
| 508 | |
| 509 | if (offset < 0x400000 && address >= 0x3000 && address < 0x3800) |
| 510 | write_iram(address & 0x7ff, data); // Internal SA-1 RAM (2K) |
| 511 | |
| 512 | if (offset < 0x400000 && address >= 0x6000 && address < 0x8000) |
| 513 | write_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff), data); // SA-1 BWRAM |
| 514 | |
| 515 | if (offset >= 0x400000 && offset < 0x500000) |
| 516 | write_bwram(offset, data); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored) |
| 517 | } |
| 518 | |
| 519 | |
| 520 | /*------------------------------------------------- |
| 521 | Accesses from SA-1 CPU |
| 522 | -------------------------------------------------*/ |
| 523 | |
| 524 | // These handlers basically match the SNES CPU ones, but there is no access to internal |
| 525 | // I/O regs or WRAM, and there are a few additional accesses to IRAM (in [00-3f][0000-07ff]) |
| 526 | // and to BWRAM (in [60-6f][0000-ffff], so-called bitmap mode) |
| 527 | |
| 528 | READ8_MEMBER( sns_sa1_device::sa1_hi_r ) |
| 529 | { |
| 530 | UINT16 address = offset & 0xffff; |
| 531 | |
| 532 | if (offset < 0x400000) |
| 533 | { |
| 534 | if (address < 0x6000) |
| 535 | { |
| 536 | if (address < 0x0800) |
| 537 | return read_iram(offset); // Internal SA-1 RAM (2K) |
| 538 | else if (address >= 0x2200 && address < 0x2400) |
| 539 | return read_regs(offset & 0x1ff); // SA-1 Regs |
| 540 | else if (address >= 0x3000 && address < 0x3800) |
| 541 | return read_iram(offset); // Internal SA-1 RAM (2K) |
| 542 | } |
| 543 | else if (address < 0x8000) |
| 544 | return read_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000)); // SA-1 BWRAM |
| 545 | else |
| 546 | return read_h(space, offset); // ROM |
| 547 | |
| 548 | return 0xff; // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...) |
| 549 | } |
| 550 | else |
| 551 | return read_h(space, offset); // ROM |
| 552 | } |
| 553 | |
| 554 | READ8_MEMBER( sns_sa1_device::sa1_lo_r ) |
| 555 | { |
| 556 | UINT16 address = offset & 0xffff; |
| 557 | |
| 558 | if (offset < 0x400000) |
| 559 | { |
| 560 | if (address < 0x6000) |
| 561 | { |
| 562 | if (address < 0x0800) |
| 563 | return read_iram(offset); // Internal SA-1 RAM (2K) |
| 564 | else if (address >= 0x2200 && address < 0x2400) |
| 565 | return read_regs(offset & 0x1ff); // SA-1 Regs |
| 566 | else if (address >= 0x3000 && address < 0x3800) |
| 567 | return read_iram(offset); // Internal SA-1 RAM (2K) |
| 568 | } |
| 569 | else if (address < 0x8000) |
| 570 | return read_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000)); // SA-1 BWRAM |
| 571 | else |
| 572 | return read_l(space, offset); // ROM |
| 573 | |
| 574 | return 0xff; // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...) |
| 575 | } |
| 576 | else if (offset < 0x500000) |
| 577 | return read_bwram(offset); // SA-1 BWRAM (not mirrored above!) |
| 578 | else if (offset >= 0x600000 && offset < 0x700000) |
| 579 | return read_bwram((offset & 0xfffff) + 0x100000); // SA-1 BWRAM Bitmap mode |
| 580 | else |
| 581 | return 0xff; // nothing should be mapped here, so maybe open bus? |
| 582 | } |
| 583 | |
| 584 | WRITE8_MEMBER( sns_sa1_device::sa1_hi_w ) |
| 585 | { |
| 586 | UINT16 address = offset & 0xffff; |
| 587 | if (offset < 0x400000) |
| 588 | { |
| 589 | if (address < 0x6000) |
| 590 | { |
| 591 | if (address < 0x0800) |
| 592 | write_iram(offset, data); // Internal SA-1 RAM (2K) |
| 593 | else if (address >= 0x2200 && address < 0x2400) |
| 594 | write_regs(offset & 0x1ff, data); // SA-1 Regs |
| 595 | else if (address >= 0x3000 && address < 0x3800) |
| 596 | write_iram(offset, data); // Internal SA-1 RAM (2K) |
| 597 | } |
| 598 | else if (address < 0x8000) |
| 599 | write_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000), data); // SA-1 BWRAM |
| 600 | } |
| 601 | } |
| 602 | |
| 603 | WRITE8_MEMBER( sns_sa1_device::sa1_lo_w ) |
| 604 | { |
| 605 | if (offset >= 0x400000 && offset < 0x500000) |
| 606 | write_bwram(offset & 0xfffff, data); // SA-1 BWRAM (not mirrored above!) |
| 607 | else if (offset >= 0x600000 && offset < 0x700000) |
| 608 | write_bwram((offset & 0xfffff) + 0x100000, data); // SA-1 BWRAM Bitmap mode |
| 609 | else |
| 610 | sa1_hi_w(space, offset, data); |
| 611 | } |
| 612 | |
| 613 | static ADDRESS_MAP_START( sa1_map, AS_PROGRAM, 8, sns_sa1_device ) |
| 614 | AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(sa1_lo_r, sa1_lo_w) |
| 615 | AM_RANGE(0x7e0000, 0x7fffff) AM_NOP |
| 616 | AM_RANGE(0x800000, 0xffffff) AM_READWRITE(sa1_hi_r, sa1_hi_w) |
| 617 | ADDRESS_MAP_END |
| 618 | |
| 619 | |
| 620 | static MACHINE_CONFIG_FRAGMENT( snes_sa1 ) |
| 621 | MCFG_CPU_ADD("sa1cpu", _5A22, 10000000) |
| 622 | MCFG_CPU_PROGRAM_MAP(sa1_map) |
| 623 | MACHINE_CONFIG_END |
| 624 | |
| 625 | machine_config_constructor sns_sa1_device::device_mconfig_additions() const |
| 626 | { |
| 627 | return MACHINE_CONFIG_NAME( snes_sa1 ); |
| 628 | } |