From 585cfd07121c315b476bb0581431248fe786f513 Mon Sep 17 00:00:00 2001 From: Ted Green Date: Sun, 29 May 2016 17:26:59 -0600 Subject: [PATCH] (nw) WIP: Updated atlantis driver. --- src/devices/machine/pci-ide.cpp | 14 +- src/devices/machine/pci9050.cpp | 74 +++-- src/devices/machine/pci9050.h | 13 + src/mame/audio/dcs.cpp | 1 + src/mame/drivers/atlantis.cpp | 483 ++++++++++++++++++++++++++++++-- 5 files changed, 539 insertions(+), 46 deletions(-) diff --git a/src/devices/machine/pci-ide.cpp b/src/devices/machine/pci-ide.cpp index fe54b7595b5..c90a8afb311 100644 --- a/src/devices/machine/pci-ide.cpp +++ b/src/devices/machine/pci-ide.cpp @@ -82,6 +82,9 @@ void ide_pci_device::device_start() void ide_pci_device::device_reset() { pci_device::device_reset(); + // PCI0646U allow BAR + if (main_id == 0x10950646) + m_config_data[0x10 / 4] |= 0x0C40; } READ32_MEMBER(ide_pci_device::ide_read_cs1) @@ -89,6 +92,8 @@ READ32_MEMBER(ide_pci_device::ide_read_cs1) // PCI offset starts at 0x3f4, idectrl expects 0x3f0 UINT32 data = 0; data = m_ide->read_cs1(space, ++offset, mem_mask); + if (0) + logerror("%s:ide_read_cs1 offset=%08X data=%08X mask=%08X\n", machine().describe_context(), offset, data, mem_mask); return data; } @@ -117,6 +122,9 @@ WRITE_LINE_MEMBER(ide_pci_device::ide_interrupt) if (m_irq_num != -1) { m_cpu->set_input_line(m_irq_num, state); } + // PCI646U2 Offset 0x50 is interrupt status + if (main_id == 0x10950646 && state) + m_config_data[0x10/4] |= 0x4; if (0) logerror("%s:ide_interrupt %i set to %i\n", machine().describe_context(), m_irq_num, state); } @@ -129,11 +137,15 @@ READ32_MEMBER(ide_pci_device::pcictrl_r) WRITE32_MEMBER(ide_pci_device::pcictrl_w) { COMBINE_DATA(&m_config_data[offset]); + // PCI646U2 Offset 0x50 is interrupt status + if (main_id == 0x10950646 && offset == 0x10/4 && (data & 0x4)) + m_config_data[0x10/4] &= ~0x4; } WRITE32_MEMBER(ide_pci_device::address_base_w) { - if (1) { + // data==0xffffffff is used to identify required memory space + if (data != 0xffffffff) { // Bits 0 (ide) and 2 (ide2) control if the mapping is legacy or BAR switch (offset) { case 0: diff --git a/src/devices/machine/pci9050.cpp b/src/devices/machine/pci9050.cpp index 6e74a19e284..718a64e0fa1 100644 --- a/src/devices/machine/pci9050.cpp +++ b/src/devices/machine/pci9050.cpp @@ -41,7 +41,8 @@ DEVICE_ADDRESS_MAP_START(empty, 32, pci9050_device) ADDRESS_MAP_END pci9050_device::pci9050_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : pci_device(mconfig, PCI9050, "PLX PCI9050 PCI to Local Bus Bridge", tag, owner, clock, "pci9050", __FILE__) + : pci_device(mconfig, PCI9050, "PLX PCI9050 PCI to Local Bus Bridge", tag, owner, clock, "pci9050", __FILE__), + m_user_input_handler(*this), m_user_output_handler(*this) { for(int i=0; i<4; i++) { m_devices[i] = nullptr; @@ -68,8 +69,8 @@ void pci9050_device::device_start() pci_device::device_start(); - add_map(0x100, M_MEM, FUNC(pci9050_device::map)); // map 0 is our config registers, mem space - add_map(0x100, M_IO, FUNC(pci9050_device::map)); // map 1 is our config registers, i/o space + add_map(0x80, M_MEM, FUNC(pci9050_device::map)); // map 0 is our config registers, mem space + add_map(0x80, M_IO, FUNC(pci9050_device::map)); // map 1 is our config registers, i/o space for(int i=0; i<4; i++) if(m_names[i]) @@ -77,6 +78,9 @@ void pci9050_device::device_start() add_map(0, M_MEM | M_DISABLED, trampolines[i], m_names[i]); else add_map(0, M_MEM | M_DISABLED, FUNC(pci9050_device::empty)); + + m_user_input_handler.resolve(); + m_user_output_handler.resolve(); } void pci9050_device::device_config_complete() @@ -106,7 +110,7 @@ void pci9050_device::remap_local(int id) { UINT32 csbase = m_csbase[id]; UINT32 lasrr = m_lasrr[id]; - logerror("%d csbase=%08x lasrr=%08x\n", id, csbase, lasrr); + logerror("local bus %d csbase=%08x lasrr=%08x\n", id, csbase, lasrr); if(!(csbase & 1)) { set_map_flags(id+2, M_MEM | M_DISABLED); @@ -119,10 +123,11 @@ void pci9050_device::remap_local(int id) return; } int size = 2 << lsize; - if(csbase & 0x0fffffff & ~(size-1)) { - logerror("PCI9050 local bus %d disabled due to unimplemented post-decode remapping\n", id); - // set_map_flags(id+2, M_MEM | M_DISABLED); - // return; + // Address map is directly connected to PCI address space so post-decode mapping is not needed. (Ted Green) + if(0 & csbase & 0x0fffffff & ~(size-1)) { + logerror("PCI9050 local bus %d size=%08x csbase=%08X disabled due to unimplemented post-decode remapping\n", id, size, csbase); + set_map_flags(id+2, M_MEM | M_DISABLED); + return; } UINT32 mask = ~(size - 1); @@ -143,6 +148,21 @@ void pci9050_device::remap_local(int id) void pci9050_device::remap_rom() { + switch ((m_cntrl >> 12) & 0x3) { + case 0: + case 3: + set_map_flags(0, M_MEM); + set_map_flags(1, M_IO); + break; + case 1: + set_map_flags(0, M_MEM); + set_map_flags(1, M_IO | M_DISABLED); + break; + case 2: + set_map_flags(0, M_MEM | M_DISABLED); + set_map_flags(1, M_IO); + break; + } } READ32_MEMBER (pci9050_device::lasrr_r) @@ -152,7 +172,7 @@ READ32_MEMBER (pci9050_device::lasrr_r) WRITE32_MEMBER(pci9050_device::lasrr_w) { - logerror("%06X:PCI9050 local bus %d range %08x: %s flags %d pf %d addr bits 27-4 %08x\n", space.device().safe_pc(), offset, data, (data & 1) ? "I/O" : "MEM", (data & 6)>>1, (data & 8)>>3, data & 0xfffffff); + logerror("%06X:PCI9050 local bus %d range = %08x: %s flags %d pf %d addr bits 27-4 %08x\n", machine().device("maincpu")->safe_pc(), offset, data, (data & 1) ? "I/O" : "MEM", (data & 6)>>1, (data & 8)>>3, data & 0xfffffff); m_lasrr[offset] = data; remap_local(offset); } @@ -164,7 +184,7 @@ READ32_MEMBER (pci9050_device::eromrr_r) WRITE32_MEMBER(pci9050_device::eromrr_w) { - logerror("%06X:PCI9050 ROM range %08x: addr bits 27-11 %08x\n", space.device().safe_pc(), data, data & 0xfffff800); + logerror("%06X:PCI9050 ROM range = %08x: addr bits 27-11 %08x\n", machine().device("maincpu")->safe_pc(), data, data & 0xfffff800); m_eromrr = data; remap_rom(); } @@ -176,7 +196,7 @@ READ32_MEMBER (pci9050_device::lasba_r) WRITE32_MEMBER(pci9050_device::lasba_w) { - logerror("%06X:PCI9050 local bus %d base %08x: enable %d remap %08x\n", space.device().safe_pc(), offset, data, data&1, data & 0x0ffffffe); + logerror("%06X:PCI9050 local bus %d base = %08x: enable %d remap %08x\n", machine().device("maincpu")->safe_pc(), offset, data, data&1, data & 0x0ffffffe); m_lasba[offset] = data; remap_local(offset); } @@ -188,7 +208,7 @@ READ32_MEMBER (pci9050_device::eromba_r) WRITE32_MEMBER(pci9050_device::eromba_w) { - logerror("%06X:PCI9050 ROM base %08x: remap %08x\n", space.device().safe_pc(), data, data & 0x0ffff800); + logerror("%06X:PCI9050 ROM base = %08x: remap %08x\n", machine().device("maincpu")->safe_pc(), data, data & 0x0ffff800); m_eromba = data; remap_rom(); } @@ -200,7 +220,7 @@ READ32_MEMBER (pci9050_device::lasbrd_r) WRITE32_MEMBER(pci9050_device::lasbrd_w) { - logerror("%06X:PCI9050 local bus %d descriptors %08x: burst %d prefetch %d width %d, endian %s, endian mode %d\n", space.device().safe_pc(), offset, data, data&1, (data >> 5) & 1, (data >> 22) & 3, ((data >> 24) & 1) ? "BE" : "LE", (data >> 25) & 1); + logerror("%06X:PCI9050 local bus %d descriptors = %08x: burst %d prefetch %d width %d, endian %s, endian mode %d\n", machine().device("maincpu")->safe_pc(), offset, data, data&1, (data >> 5) & 1, (data >> 22) & 3, ((data >> 24) & 1) ? "BE" : "LE", (data >> 25) & 1); m_lasbrd[offset] = data; remap_local(offset); } @@ -212,7 +232,7 @@ READ32_MEMBER (pci9050_device::erombrd_r) WRITE32_MEMBER(pci9050_device::erombrd_w) { - logerror("%06X:PCI9050 ROM descriptors %08x: burst %d prefetch %d bits %d, endian %s, endian mode %d\n", space.device().safe_pc(), data, data&1, (data >> 5) & 1, (data >> 22) & 3, ((data >> 24) & 1) ? "BE" : "LE", (data >> 25) & 1); + logerror("%06X:PCI9050 ROM descriptors = %08x: burst %d prefetch %d bits %d, endian %s, endian mode %d\n", machine().device("maincpu")->safe_pc(), data, data&1, (data >> 5) & 1, (data >> 22) & 3, ((data >> 24) & 1) ? "BE" : "LE", (data >> 25) & 1); m_erombrd = data; remap_rom(); } @@ -224,31 +244,51 @@ READ32_MEMBER (pci9050_device::csbase_r) WRITE32_MEMBER(pci9050_device::csbase_w) { - logerror("%06X:PCI9050 chip select %d base %08x: enable %d size %08x\n", space.device().safe_pc(), offset, data, data&1, data&0xfffffffe); + logerror("%06X:PCI9050 chip select %d base = %08x: enable %d size %08x\n", machine().device("maincpu")->safe_pc(), offset, data, data&1, data&0xfffffffe); m_csbase[offset] = data; remap_local(offset); } READ32_MEMBER (pci9050_device::intcsr_r) { + logerror("%06X:PCI9050 IRQ CSR read %08x\n", machine().device("maincpu")->safe_pc(), m_intcsr); return m_intcsr; } WRITE32_MEMBER(pci9050_device::intcsr_w) { - logerror("%06X:PCI9050 IRQ control %08x\n", space.device().safe_pc(), data); + logerror("%06X:PCI9050 IRQ CSR write %08x\n", machine().device("maincpu")->safe_pc(), data); m_intcsr = data; remap_rom(); } READ32_MEMBER (pci9050_device::cntrl_r) { + if (!m_user_input_handler.isnull()) + { + int readData = m_user_input_handler(); + for (int userIndex = 0; userIndex < 4; userIndex++) + if ((m_cntrl & (1 << (1 + userIndex * 3)))==0) + m_cntrl = (m_cntrl & ~(1<<(2 + userIndex * 3))) | (((readData>>userIndex)&1) << (2 + userIndex * 3)); + } + if (0) + logerror("%06X:PCI9050 CNTRL read = %08x\n", machine().device("maincpu")->safe_pc(), m_cntrl); return m_cntrl; } WRITE32_MEMBER(pci9050_device::cntrl_w) { - logerror("%06X:PCI9050 IRQ control %08x\n", space.device().safe_pc(), data); + if (0) + logerror("%06X:PCI9050 CNTRL write %08x\n", machine().device("maincpu")->safe_pc(), data); + UINT32 oldData = m_cntrl; m_cntrl = data; remap_rom(); + if ((oldData ^ m_cntrl) & 0x3000) + remap_cb(); + if (!m_user_output_handler.isnull()) { + int userData = 0; + for (int userIndex = 0; userIndex < 4; userIndex++) + userData |= ((m_cntrl >> (2 + userIndex * 3)) & 1) << userIndex; + m_user_output_handler(userData); + } } diff --git a/src/devices/machine/pci9050.h b/src/devices/machine/pci9050.h index adb3ac969e0..a9de08ba6c9 100644 --- a/src/devices/machine/pci9050.h +++ b/src/devices/machine/pci9050.h @@ -19,6 +19,12 @@ #define MCFG_PCI9050_SET_MAP(id, map) \ downcast(device)->set_map(id, ADDRESS_MAP_NAME(map), #map, owner); +#define MCFG_PCI9050_USER_INPUT_CALLBACK(_write) \ + devcb = &pci9050_device::set_user_input_callback(*device, DEVCB_##_write); + +#define MCFG_PCI9050_USER_OUTPUT_CALLBACK(_read) \ + devcb = &pci9050_device::set_user_output_callback(*device, DEVCB_##_read); + class pci9050_device : public pci_device { @@ -45,6 +51,9 @@ public: DECLARE_READ32_MEMBER( cntrl_r ); DECLARE_WRITE32_MEMBER(cntrl_w ); + template static devcb_base &set_user_input_callback(device_t &device, _Object object) { return downcast(device).m_user_input_handler.set_callback(object); } + template static devcb_base &set_user_output_callback(device_t &device, _Object object) { return downcast(device).m_user_output_handler.set_callback(object); } + void set_map(int id, address_map_constructor map, const char *name, device_t *device); protected: @@ -69,6 +78,10 @@ private: template void map_trampoline(address_map &map, device_t &device) { m_maps[id](map, *m_devices[id]); } + + devcb_read32 m_user_input_handler; + devcb_write32 m_user_output_handler; + }; extern const device_type PCI9050; diff --git a/src/mame/audio/dcs.cpp b/src/mame/audio/dcs.cpp index 92ff46c2018..f6ae766bdb6 100644 --- a/src/mame/audio/dcs.cpp +++ b/src/mame/audio/dcs.cpp @@ -562,6 +562,7 @@ MACHINE_CONFIG_FRAGMENT( dcs2_audio_denver ) MCFG_TIMER_DEVICE_ADD("dcs_reg_timer", DEVICE_SELF, dcs_audio_device, dcs_irq) MCFG_TIMER_DEVICE_ADD("dcs_int_timer", DEVICE_SELF, dcs_audio_device, internal_timer_callback) + MCFG_TIMER_DEVICE_ADD("dcs_sport_timer", DEVICE_SELF, dcs_audio_device, sport0_irq) // Atlantis driver waits for sport0 rx interrupts MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") diff --git a/src/mame/drivers/atlantis.cpp b/src/mame/drivers/atlantis.cpp index 8dc2bb4b4b5..d967cf97dae 100644 --- a/src/mame/drivers/atlantis.cpp +++ b/src/mame/drivers/atlantis.cpp @@ -41,6 +41,18 @@ #include "machine/pci.h" #include "machine/vrc4373.h" #include "machine/pci9050.h" +#include "machine/pci-ide.h" +#include "includes/midzeus.h" +#include "includes/midzeus2.h" +#include "machine/nvram.h" +#include "coreutil.h" + +/* static interrupts */ +#define GALILEO_IRQ_NUM MIPS3_IRQ2 +#define IOASIC_IRQ_NUM MIPS3_IRQ4 +#define IDE_IRQ_NUM MIPS3_IRQ4 + +#define LOG_RTC (1) class atlantis_state : public driver_device { @@ -48,55 +60,307 @@ public: atlantis_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), - m_dcs(*this, "dcs") { } + m_dcs(*this, "dcs"), + m_ioasic(*this, "ioasic"), + m_rtc(*this, "rtc") + { } DECLARE_DRIVER_INIT(mwskins); virtual void machine_start() override; virtual void machine_reset() override; UINT32 screen_update_mwskins(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); required_device m_maincpu; + //required_device m_dcs; required_device m_dcs; + required_device m_ioasic; + required_device m_rtc; + std::vector m_rtc_data; + UINT32 m_last_offset; + READ8_MEMBER(cmos_r); + WRITE8_MEMBER(cmos_w); + DECLARE_WRITE32_MEMBER(cmos_protect_w); + DECLARE_READ32_MEMBER(cmos_protect_r); + UINT32 m_cmos_write_enabled; + + DECLARE_READ32_MEMBER(status_leds_r); + DECLARE_WRITE32_MEMBER(status_leds_w); + UINT8 m_status_leds; + + DECLARE_WRITE32_MEMBER(zeus_w); + DECLARE_READ32_MEMBER(zeus_r); + UINT32 m_zeus_data; + + READ8_MEMBER (red_r); + WRITE8_MEMBER(red_w); + std::vector m_red_data; + int m_red_count; - READ32_MEMBER (red_r); - WRITE32_MEMBER(red_w); READ32_MEMBER (green_r); WRITE32_MEMBER(green_w); - READ32_MEMBER (blue_r); - WRITE32_MEMBER(blue_w); + READ8_MEMBER (blue_r); + WRITE8_MEMBER(blue_w); + + READ32_MEMBER(map2_r); + WRITE32_MEMBER(map2_w); + + WRITE32_MEMBER(user_io_output); + READ32_MEMBER(user_io_input); + int m_user_io_state; + + DECLARE_READ32_MEMBER(asic_reset_r); + DECLARE_WRITE32_MEMBER(asic_reset_w); + DECLARE_WRITE32_MEMBER(asic_fifo_w); + int m_asic_reset; + + DECLARE_WRITE_LINE_MEMBER(ioasic_irq); }; -READ32_MEMBER (atlantis_state::red_r) +READ8_MEMBER (atlantis_state::red_r) { - logerror("red_r %x\n", offset); - return 0; + UINT8 data = m_red_data[offset]; + logerror("%06X: red_r %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, data); + m_last_offset = offset | 0x10000; + return data; } -WRITE32_MEMBER(atlantis_state::red_w) +WRITE8_MEMBER(atlantis_state::red_w) { - logerror("red_w %x,%x\n", offset, data); + COMBINE_DATA(&m_red_data[offset]); + + switch (offset) { + case 0: + // Data written is shifted by 1 bit each time. Maybe a serial line output? + if (m_red_count == 0) + logerror("%06X: red_w start serial %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, data); + m_red_count++; + if (m_red_count == 8) + m_red_count = 0; + break; + default: + logerror("%06X: red_w %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, data); + break; + } + m_last_offset = offset | 0x10000; } -READ32_MEMBER (atlantis_state::green_r) +READ32_MEMBER(atlantis_state::green_r) { - logerror("green_r %x\n", offset); - return 0; + // If not 0x80 cpu writes to 00e80000 = 0 + if ((offset | 0x20000) != m_last_offset) + logerror("%06X: green_r %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, 0x80); + m_last_offset = offset | 0x20000; + return 0x80; } WRITE32_MEMBER(atlantis_state::green_w) { - logerror("green_w %x,%x\n", offset, data); + logerror("%06X: green_w %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, data); + m_last_offset = offset | 0x20000; } -READ32_MEMBER (atlantis_state::blue_r) +READ32_MEMBER(atlantis_state::map2_r) { - logerror("blue_r %x\n", offset); + UINT32 data = 0; + switch (offset) { + case 0x104/4: + // CPU resets map2, writes 0xffffffff here, and then expects this read + data = 0x1fff03ff; + break; + } + logerror("%06X: map2_r %08x = %08x\n", machine().device("maincpu")->safe_pc(), offset*4, data); + return data; +} + +WRITE32_MEMBER(atlantis_state::map2_w) +{ + logerror("%06X: map2_w %08x = %08x\n", machine().device("maincpu")->safe_pc(), offset*4, data); +} + +READ8_MEMBER (atlantis_state::blue_r) +{ + //UINT8 data = m_red_data[offset]; + logerror("%06X: blue_r %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, 0); + //return data; return 0; } -WRITE32_MEMBER(atlantis_state::blue_w) +WRITE8_MEMBER(atlantis_state::blue_w) { - logerror("blue_w %x,%x\n", offset, data); + logerror("%06X: blue_w %08x = %02x\n", machine().device("maincpu")->safe_pc(), offset, data); } +WRITE32_MEMBER(atlantis_state::user_io_output) +{ + m_user_io_state = data; + logerror("atlantis_state::user_io_output m_user_io_state = %1x\n", m_user_io_state); +} + +READ32_MEMBER(atlantis_state::user_io_input) +{ + // Set user i/o (2) Power Detect? + m_user_io_state |= 1 << 2; + + // User I/O 0 = Allow write to red[0]. Serial line? + // Loop user_io(0) to user_io(1) + m_user_io_state = (m_user_io_state & ~(0x2)) | ((m_user_io_state & 1) << 1); + if (0) + logerror("atlantis_state::user_io_input m_user_io_state = %1x\n", m_user_io_state); + return m_user_io_state; +} + +READ32_MEMBER(atlantis_state::asic_reset_r) +{ + logerror("%s:asic_reset_r read from offset %04X = %08X & %08X\n", machine().describe_context(), offset, m_asic_reset, mem_mask); + return m_asic_reset; +} + +WRITE32_MEMBER(atlantis_state::asic_reset_w) +{ + // 0x1 IOASIC Reset + // 0x4 Map2 Reset? + // 0x10 IDE Reset + logerror("%s:asic_reset_w write to offset %04X = %08X & %08X\n", machine().describe_context(), offset, data, mem_mask); + //UINT32 oldData = m_asic_reset; + COMBINE_DATA(&m_asic_reset); + //if (!(m_asic_reset & 0x0002)) + //if ((m_asic_reset & 0x0002)) + if ((m_asic_reset & 0x0001)==0) + m_ioasic->ioasic_reset(); +} + + +WRITE32_MEMBER(atlantis_state::asic_fifo_w) +{ + m_ioasic->fifo_w(data); +} + +READ8_MEMBER(atlantis_state::cmos_r) +{ + UINT8 result = m_rtc_data[offset]; + + switch (offset) { + case 0x7F9: + case 0x7FA: + case 0x7FB: + case 0x7FC: + case 0x7FD: + case 0x7FE: + case 0x7FF: + if ((m_rtc_data[0x7F8] & 0x40)==0) { + system_time systime; + // get the current date/time from the core + machine().current_datetime(systime); + m_rtc_data[0x7F9] = dec_2_bcd(systime.local_time.second); + m_rtc_data[0x7FA] = dec_2_bcd(systime.local_time.minute); + m_rtc_data[0x7FB] = dec_2_bcd(systime.local_time.hour); + + m_rtc_data[0x7FC] = dec_2_bcd((systime.local_time.weekday != 0) ? systime.local_time.weekday : 7); + m_rtc_data[0x7FD] = dec_2_bcd(systime.local_time.mday); + m_rtc_data[0x7FE] = dec_2_bcd(systime.local_time.month + 1); + m_rtc_data[0x7FF] = dec_2_bcd(systime.local_time.year - 1900); // Epoch is 1900 + result = m_rtc_data[offset]; + } + break; + default: + if (LOG_RTC) + logerror("%s:RTC read from offset %04X = %08X m_rtc_data[0x7F8] %02X\n", machine().describe_context(), offset, result, m_rtc_data[0x7F8]); + break; + } + return result; +} + +WRITE8_MEMBER(atlantis_state::cmos_w) +{ + system_time systime; + + if (m_cmos_write_enabled) { + COMBINE_DATA(&m_rtc_data[offset]); + m_cmos_write_enabled = FALSE; + switch (offset) { + case 0x7F8: // M48T02 time + if (data & 0x40) { + // get the current date/time from the core + machine().current_datetime(systime); + m_rtc_data[0x7F9] = dec_2_bcd(systime.local_time.second); + m_rtc_data[0x7FA] = dec_2_bcd(systime.local_time.minute); + m_rtc_data[0x7FB] = dec_2_bcd(systime.local_time.hour); + + m_rtc_data[0x7FC] = dec_2_bcd((systime.local_time.weekday != 0) ? systime.local_time.weekday : 7); + m_rtc_data[0x7FD] = dec_2_bcd(systime.local_time.mday); + m_rtc_data[0x7FE] = dec_2_bcd(systime.local_time.month + 1); + m_rtc_data[0x7FF] = dec_2_bcd(systime.local_time.year - 1900); // Epoch is 1900 + } + if (LOG_RTC) + logerror("%s:RTC write to offset %04X = %08X & %08X\n", machine().describe_context(), offset, data, mem_mask); + + break; + default: + if (LOG_RTC) + logerror("%s:RTC write to offset %04X = %08X & %08X\n", machine().describe_context(), offset, data, mem_mask); + break; + } + } +} + +WRITE32_MEMBER(atlantis_state::cmos_protect_w) +{ + m_cmos_write_enabled = TRUE; +} + +READ32_MEMBER(atlantis_state::status_leds_r) +{ + return m_status_leds | 0xffffff00; +} + + +WRITE32_MEMBER(atlantis_state::status_leds_w) +{ + if (ACCESSING_BITS_0_7) { + m_status_leds = data; + if (1) { + char digit = 'U'; + switch (m_status_leds) { + case 0xc0: digit = '0'; break; + case 0xf9: digit = '1'; break; + case 0xa4: digit = '2'; break; + case 0xb0: digit = '3'; break; + case 0x99: digit = '4'; break; + case 0x92: digit = '5'; break; + case 0x82: digit = '6'; break; + case 0xf8: digit = '7'; break; + case 0x80: digit = '8'; break; + case 0x90: digit = '9'; break; + case 0x88: digit = 'A'; break; + case 0x83: digit = 'B'; break; + case 0xc6: digit = 'C'; break; + case 0xa1: digit = 'D'; break; + case 0x86: digit = 'E'; break; + case 0x87: digit = 'F'; break; + case 0x7f: digit = 'Z'; break; + } + popmessage("LED: %c", digit); + osd_printf_debug("%06X: status_leds_w digit: %c %08x = %02x\n", machine().device("maincpu")->safe_pc(), digit, offset, data); + logerror("%06X: status_leds_w digit: %c %08x = %02x\n", machine().device("maincpu")->safe_pc(), digit, offset, data); + } + } +} + +READ32_MEMBER(atlantis_state::zeus_r) +{ + logerror("%s:zeus_r read from offset %04X = %08X & %08X\n", machine().describe_context(), offset, m_zeus_data, mem_mask); + return m_zeus_data; +} + +WRITE32_MEMBER(atlantis_state::zeus_w) +{ + COMBINE_DATA(&m_zeus_data); + logerror("%s:zeus_w write to offset %04X = %08X & %08X\n", machine().describe_context(), offset, data, mem_mask); +} + + +READ32_MEMBER(atlantis_state::cmos_protect_r) +{ + return m_cmos_write_enabled; +} /************************************* * @@ -106,6 +370,10 @@ WRITE32_MEMBER(atlantis_state::blue_w) void atlantis_state::machine_start() { + m_rtc_data.resize(0x800); + m_rtc->set_base(m_rtc_data.data(), m_rtc_data.size()); + + m_red_data.resize(0x1000); /* set the fastest DRC options */ m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS); } @@ -122,6 +390,22 @@ void atlantis_state::machine_reset() { m_dcs->reset_w(1); m_dcs->reset_w(0); + m_user_io_state = 0; + m_cmos_write_enabled = FALSE; + m_zeus_data = 0; + m_red_count = 0; +} + +/************************************* +* +* I/O ASIC interrupts +* +*************************************/ + +WRITE_LINE_MEMBER(atlantis_state::ioasic_irq) +{ + logerror("atlantis_state::ioasic_irq state = %i\n", state); + m_maincpu->set_input_line(IOASIC_IRQ_NUM, state); } @@ -146,15 +430,38 @@ UINT32 atlantis_state::screen_update_mwskins(screen_device &screen, bitmap_ind16 *************************************/ static ADDRESS_MAP_START( map0, AS_PROGRAM, 32, atlantis_state ) - AM_RANGE(0x000000, 0xffffff) AM_READWRITE(red_r, red_w) + //00b80000 + //00980000 + //00a00000 + //00a80000 + //00900000 + // 00200004 + // 00200008 + AM_RANGE(0x000000, 0xfff) AM_READWRITE8(red_r, red_w, 0xff) + AM_RANGE(0x0001e000, 0x0001ffff) AM_READWRITE8(cmos_r, cmos_w, 0xff) + //AM_RANGE(0x00180010, 0x00180013) AM_READWRITE(asic_reset_r, asic_reset_w) + AM_RANGE(0x00400000, 0x0040002f) AM_READWRITE8(blue_r, blue_w, 0xff) + AM_RANGE(0x00d80000, 0x00d80003) AM_READWRITE(status_leds_r, status_leds_w) + AM_RANGE(0x00e00000, 0x00e00003) AM_READWRITE(cmos_protect_r, cmos_protect_w) + AM_RANGE(0x00c80000, 0x00c80003) AM_READWRITE(green_r, green_w) + //AM_RANGE(0x00e80000, 0x00e80003) AM_NOP // Watchdog? + AM_RANGE(0x00880000, 0x00880003) AM_READWRITE(asic_reset_r, asic_reset_w) ADDRESS_MAP_END static ADDRESS_MAP_START( map1, AS_PROGRAM, 32, atlantis_state ) - AM_RANGE(0x000000, 0xffffff) AM_READWRITE(green_r, green_w) + AM_RANGE(0x00000000, 0x0000003f) AM_DEVREADWRITE("ioasic", midway_ioasic_device, read, write) + // asic_fifo_w + // dcs3_fifo_full_w + AM_RANGE(0x00400000, 0x00400003) AM_DEVWRITE("dcs", dcs_audio_device, dsio_idma_addr_w) + AM_RANGE(0x00600000, 0x00600003) AM_DEVREADWRITE("dcs", dcs_audio_device, dsio_idma_data_r, dsio_idma_data_w) +ADDRESS_MAP_END + +static ADDRESS_MAP_START(map2, AS_PROGRAM, 32, atlantis_state) + AM_RANGE(0x00000000, 0x000001ff) AM_READWRITE(map2_r, map2_w) ADDRESS_MAP_END static ADDRESS_MAP_START( map3, AS_PROGRAM, 32, atlantis_state ) - AM_RANGE(0x000000, 0xffffff) AM_READWRITE(blue_r, blue_w) + //AM_RANGE(0x000000, 0xffffff) AM_READWRITE(blue_r, blue_w) ADDRESS_MAP_END /************************************* @@ -164,6 +471,107 @@ ADDRESS_MAP_END *************************************/ static INPUT_PORTS_START( mwskins ) + PORT_START("DIPS") + PORT_DIPNAME(0x0003, 0x0003, "Boot Mode") + PORT_DIPSETTING(0x0003, "Normal Boot") + PORT_DIPSETTING(0x0002, "Boot EEPROM Based Self Test") + PORT_DIPSETTING(0x0001, "Boot Disk Based Self Test") + PORT_DIPSETTING(0x0000, "Run Factory Tests") + PORT_DIPNAME(0x0004, 0x0004, "Unknown0004") + PORT_DIPSETTING(0x0004, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0008, 0x0008, "Unknown0008") + PORT_DIPSETTING(0x0008, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0010, 0x0010, "Unknown0010") + PORT_DIPSETTING(0x0010, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0020, 0x0020, "Unknown0020") + PORT_DIPSETTING(0x0020, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0040, 0x0040, "Unknown0040") + PORT_DIPSETTING(0x0040, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0080, 0x0080, "Unknown0080") + PORT_DIPSETTING(0x0080, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0100, 0x0100, "Unknown0100") + PORT_DIPSETTING(0x0100, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0200, 0x0200, "Unknown0200") + PORT_DIPSETTING(0x0200, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0400, 0x0400, "Unknown0400") + PORT_DIPSETTING(0x0400, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x0800, 0x0800, "Unknown0800") + PORT_DIPSETTING(0x0800, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x1000, 0x1000, "Unknown1000") + PORT_DIPSETTING(0x1000, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x2000, 0x2000, "Unknown2000") + PORT_DIPSETTING(0x2000, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x4000, 0x4000, "Unknown4000") + PORT_DIPSETTING(0x4000, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + PORT_DIPNAME(0x8000, 0x8000, "Unknown8000") + PORT_DIPSETTING(0x8000, DEF_STR(Off)) + PORT_DIPSETTING(0x0000, DEF_STR(On)) + + PORT_START("SYSTEM") + PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_COIN1) + PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_COIN2) + PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_START1) + PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_TILT) + PORT_SERVICE_NO_TOGGLE(0x0010, IP_ACTIVE_LOW) + PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_START2) + PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_SERVICE1) + PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_COIN3) + PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_COIN4) + PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_START3) + PORT_BIT(0x0400, IP_ACTIVE_LOW, IPT_START4) + PORT_BIT(0x0800, IP_ACTIVE_LOW, IPT_VOLUME_DOWN) + PORT_BIT(0x1000, IP_ACTIVE_LOW, IPT_VOLUME_UP) + PORT_BIT(0x6000, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x8000, IP_ACTIVE_LOW, IPT_BILL1) + + PORT_START("IN1") + PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1) + PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(1) + PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) + PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_PLAYER(1) /* 3d cam */ + PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) + PORT_BIT(0x1000, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2) + PORT_BIT(0x2000, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(2) + PORT_BIT(0x4000, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) + PORT_BIT(0x8000, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_PLAYER(2) + + PORT_START("IN2") + PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(3) + PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(3) + PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(3) + PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(3) + PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(3) + PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(3) + PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(3) + PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(4) + PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(4) + PORT_BIT(0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(4) + PORT_BIT(0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(4) + PORT_BIT(0x1000, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(4) + PORT_BIT(0x2000, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(4) + PORT_BIT(0x4000, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(4) + PORT_BIT(0x8000, IP_ACTIVE_LOW, IPT_UNUSED) INPUT_PORTS_END /************************************* @@ -172,6 +580,8 @@ INPUT_PORTS_END * *************************************/ #define PCI_ID_NILE ":pci:00.0" +#define PCI_ID_9050 ":pci:0b.0" +#define PCI_ID_IDE ":pci:0c.0" static MACHINE_CONFIG_START( mwskins, atlantis_state ) @@ -182,12 +592,19 @@ static MACHINE_CONFIG_START( mwskins, atlantis_state ) MCFG_PCI_ROOT_ADD( ":pci") MCFG_VRC4373_ADD( PCI_ID_NILE, ":maincpu") - MCFG_PCI9050_ADD( ":pci:0b.0") + MCFG_PCI9050_ADD( PCI_ID_9050) MCFG_PCI9050_SET_MAP(0, map0) - MCFG_PCI9050_SET_MAP(1, map1) // 2 skipped for testing + MCFG_PCI9050_SET_MAP(1, map1) + MCFG_PCI9050_SET_MAP(2, map2) MCFG_PCI9050_SET_MAP(3, map3) + MCFG_PCI9050_USER_OUTPUT_CALLBACK(DEVWRITE32(":", atlantis_state, user_io_output)) + MCFG_PCI9050_USER_INPUT_CALLBACK(DEVREAD32(":", atlantis_state, user_io_input)) + + MCFG_NVRAM_ADD_0FILL("rtc") - MCFG_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", nullptr, true) + //MCFG_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", nullptr, true) + MCFG_IDE_PCI_ADD(PCI_ID_IDE, 0x10950646, 0x03, 0x0) + MCFG_IDE_PCI_IRQ_ADD(":maincpu", IDE_IRQ_NUM) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) @@ -202,8 +619,18 @@ static MACHINE_CONFIG_START( mwskins, atlantis_state ) MCFG_PALETTE_ADD_BBBBBGGGGGRRRRR("palette") /* sound hardware */ + //MCFG_DEVICE_ADD("dcs", DCS2_AUDIO_DSIO, 0) MCFG_DEVICE_ADD("dcs", DCS2_AUDIO_DENVER, 0) - MCFG_DCS2_AUDIO_DRAM_IN_MB(8) + MCFG_DCS2_AUDIO_DRAM_IN_MB(4) + MCFG_DCS2_AUDIO_POLLING_OFFSET(0) /* no place to hook :-( */ + + MCFG_DEVICE_ADD("ioasic", MIDWAY_IOASIC, 0) + MCFG_MIDWAY_IOASIC_SHUFFLE(MIDWAY_IOASIC_STANDARD) + MCFG_MIDWAY_SERIAL_PIC2_YEAR_OFFS(80) + MCFG_MIDWAY_IOASIC_UPPER(325) + MCFG_MIDWAY_IOASIC_IRQ_CALLBACK(WRITELINE(atlantis_state, ioasic_irq)) + MCFG_MIDWAY_IOASIC_AUTO_ACK(1) + MACHINE_CONFIG_END @@ -218,7 +645,7 @@ ROM_START( mwskins ) ROM_REGION32_LE( 0x80000, PCI_ID_NILE":rom", 0 ) /* 512k for R4310 code */ ROM_LOAD( "skins_game_u4_boot_1.00.u4", 0x000000, 0x080000, CRC(0fe87720) SHA1(4b24abbe662a2d7b61e6a3f079e28b73605ba19f) ) - DISK_REGION( "ide:0:hdd:image" ) + DISK_REGION(PCI_ID_IDE":ide:0:hdd:image" ) DISK_IMAGE( "mwskins", 0, SHA1(5cb293a6fdb2478293f48ddfc93cdd018acb2bb5) ) ROM_END @@ -226,7 +653,7 @@ ROM_START( mwskinsa ) ROM_REGION32_LE( 0x80000, PCI_ID_NILE":rom", 0 ) /* 512k for R4310 code */ ROM_LOAD( "skins_game_u4_boot_1.00.u4", 0x000000, 0x080000, CRC(0fe87720) SHA1(4b24abbe662a2d7b61e6a3f079e28b73605ba19f) ) - DISK_REGION( "ide:0:hdd:image" ) + DISK_REGION(PCI_ID_IDE":ide:0:hdd:image" ) DISK_IMAGE( "mwskinsa", 0, SHA1(72497917b31156eb11a46bbcc6f22a254dcec044) ) ROM_END @@ -234,7 +661,7 @@ ROM_START( mwskinso ) ROM_REGION32_LE( 0x80000, PCI_ID_NILE":rom", 0 ) /* 512k for R4310 code */ ROM_LOAD( "skins_game_u4_boot_1.00.u4", 0x000000, 0x080000, CRC(0fe87720) SHA1(4b24abbe662a2d7b61e6a3f079e28b73605ba19f) ) - DISK_REGION( "ide:0:hdd:image" ) + DISK_REGION(PCI_ID_IDE":ide:0:hdd:image" ) DISK_IMAGE( "mwskins104", 0, SHA1(6917f66718999c144c854795c5856bf5659b85fa) ) ROM_END