diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index da3c575e7f4..a905c433936 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -3064,14 +3064,20 @@ files { MAME_DIR .. "src/mame/machine/ps2intc.h", MAME_DIR .. "src/mame/machine/ps2sif.cpp", MAME_DIR .. "src/mame/machine/ps2sif.h", + MAME_DIR .. "src/mame/machine/iopcdvd.cpp", + MAME_DIR .. "src/mame/machine/iopcdvd.h", MAME_DIR .. "src/mame/machine/iopdma.cpp", MAME_DIR .. "src/mame/machine/iopdma.h", MAME_DIR .. "src/mame/machine/iopintc.cpp", MAME_DIR .. "src/mame/machine/iopintc.h", - MAME_DIR .. "src/mame/audio/iopspu.cpp", - MAME_DIR .. "src/mame/audio/iopspu.h", + MAME_DIR .. "src/mame/machine/iopsio2.cpp", + MAME_DIR .. "src/mame/machine/iopsio2.h", + MAME_DIR .. "src/mame/machine/iopspu.cpp", + MAME_DIR .. "src/mame/machine/iopspu.h", MAME_DIR .. "src/mame/machine/ioptimer.cpp", MAME_DIR .. "src/mame/machine/ioptimer.h", + MAME_DIR .. "src/mame/audio/iopspu.cpp", + MAME_DIR .. "src/mame/audio/iopspu.h", } createMESSProjects(_target, _subtarget, "sord") diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index ceaffbd97ce..6550aa27d2f 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -3443,20 +3443,16 @@ void r5900le_device::handle_idt(uint32_t op) case 0x10: /* MFHI1 */ if (rd) m_core->r[rd] = m_core->rh[REG_HI]; - m_core->icount--; break; case 0x11: /* MTHI1 */ m_core->rh[REG_HI] = m_core->r[rs]; - m_core->icount--; break; case 0x12: /* MFLO1 */ - if (rd) - m_core->r[rd] = m_core->rh[REG_LO]; - m_core->icount--; + if (rd) + m_core->r[rd] = m_core->rh[REG_LO]; break; case 0x13: /* MTLO1 */ m_core->rh[REG_LO] = m_core->r[rs]; - m_core->icount--; break; case 0x18: /* MULT1 */ { @@ -3565,7 +3561,24 @@ void r5900le_device::handle_mmi0(uint32_t op) printf("Unsupported instruction: PADDB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x09: /* PSUBB */ - printf("Unsupported instruction: PSUBB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int word_idx = 0; word_idx < 2; word_idx++) + { + for (int byte_idx = 0; byte_idx < 64; byte_idx += 8) + { + const uint8_t rsbyte = (uint8_t)(rsval[word_idx] >> byte_idx); + const uint8_t rtbyte = (uint8_t)(rtval[word_idx] >> byte_idx); + const uint8_t result = rsbyte - rtbyte; + rdval[word_idx] |= (uint64_t)result << byte_idx; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x0a: /* PCGTB */ printf("Unsupported instruction: PCGTB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -3674,7 +3687,6 @@ void r5900le_device::handle_mmi1(uint32_t op) } m_core->r[rd] = rdval[0] | (rdval[1] << 32); m_core->rh[rd] = rdval[2] | (rdval[3] << 32); - m_core->icount -= 1; break; } case 0x11: /* PSUBUW */ @@ -3736,7 +3748,6 @@ void r5900le_device::handle_mmi2(uint32_t op) m_core->r[rd] = m_core->r[REG_HI]; m_core->rh[rd] = m_core->rh[REG_HI]; } - m_core->icount--; break; case 0x09: /* PMFLO */ if (rd) @@ -3744,7 +3755,6 @@ void r5900le_device::handle_mmi2(uint32_t op) m_core->r[rd] = m_core->r[REG_LO]; m_core->rh[rd] = m_core->rh[REG_LO]; } - m_core->icount--; break; case 0x0a: /* PINTH */ printf("Unsupported instruction: PINTH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -3761,7 +3771,6 @@ void r5900le_device::handle_mmi2(uint32_t op) m_core->rh[rd] = m_core->r[rs]; m_core->r[rd] = m_core->r[rt]; } - m_core->icount--; break; case 0x10: /* PMADDH */ printf("Unsupported instruction: PMADDH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -3770,10 +3779,18 @@ void r5900le_device::handle_mmi2(uint32_t op) printf("Unsupported instruction: PHMADH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x12: /* PAND */ - printf("Unsupported instruction: PAND @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + m_core->rh[rd] = m_core->rh[rs] & m_core->rh[rt]; + m_core->r[rd] = m_core->r[rs] & m_core->r[rt]; + } break; case 0x13: /* PXOR */ - printf("Unsupported instruction: PXOR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + m_core->rh[rd] = m_core->rh[rs] ^ m_core->rh[rt]; + m_core->r[rd] = m_core->r[rs] ^ m_core->r[rt]; + } break; case 0x14: /* PMSUBH */ printf("Unsupported instruction: PMSUBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -3840,7 +3857,6 @@ void r5900le_device::handle_mmi3(uint32_t op) m_core->rh[rd] = m_core->rh[rs]; m_core->r[rd] = m_core->rh[rt]; } - m_core->icount--; break; case 0x12: /* POR */ if (rd) @@ -3848,16 +3864,26 @@ void r5900le_device::handle_mmi3(uint32_t op) m_core->rh[rd] = m_core->rh[rs] | m_core->rh[rt]; m_core->r[rd] = m_core->r[rs] | m_core->r[rt]; } - m_core->icount--; break; case 0x13: /* PNOR */ - printf("Unsupported instruction: PNOR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + m_core->rh[rd] = ~(m_core->rh[rs] | m_core->rh[rt]); + m_core->r[rd] = ~(m_core->r[rs] | m_core->r[rt]); + } break; case 0x1a: /* PEXCH */ printf("Unsupported instruction: PEXCH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x1b: /* PCPYH */ - printf("Unsupported instruction: PCPYH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint16_t msh = (uint16_t)m_core->rh[rt]; + const uint16_t lsh = (uint16_t)m_core->r[rt]; + m_core->rh[rd] = msh * 0x0001000100010001ULL; + m_core->r[rd] = lsh * 0x0001000100010001ULL; + } + m_core->icount--; break; case 0x1e: /* PEXCW */ printf("Unsupported instruction: PEXCW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); diff --git a/src/mame/audio/iopspu.cpp b/src/mame/audio/iopspu.cpp index 0e04e1283d9..bc60f19c48b 100644 --- a/src/mame/audio/iopspu.cpp +++ b/src/mame/audio/iopspu.cpp @@ -15,80 +15,152 @@ DEFINE_DEVICE_TYPE(SONYIOP_SPU, iop_spu_device, "iopspu", "Playstation 2 IOP SPU iop_spu_device::iop_spu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SONYIOP_SPU, tag, owner, clock) + , device_sound_interface(mconfig, *this) , m_iop(*this, finder_base::DUMMY_TAG) + , m_intc(*this, finder_base::DUMMY_TAG) { } void iop_spu_device::device_start() { m_ram = std::make_unique(2 * 1024 * 1024); // ? + + if (!m_core[0].m_autodma_done_timer_hack) + m_core[0].m_autodma_done_timer_hack = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(iop_spu_device::autodma_done_timer_hack), this), 0); + + if (!m_core[1].m_autodma_done_timer_hack) + m_core[1].m_autodma_done_timer_hack = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(iop_spu_device::autodma_done_timer_hack), this), (void*)1); + + save_item(NAME(m_core[0].m_status)); + save_item(NAME(m_core[0].m_start_port_addr)); + save_item(NAME(m_core[0].m_curr_port_addr)); + save_item(NAME(m_core[0].m_unknown_0x19a)); + save_item(NAME(m_core[0].m_autodma_ctrl)); + save_item(NAME(m_core[1].m_status)); + save_item(NAME(m_core[1].m_start_port_addr)); + save_item(NAME(m_core[1].m_curr_port_addr)); + save_item(NAME(m_core[1].m_unknown_0x19a)); + save_item(NAME(m_core[1].m_autodma_ctrl)); } void iop_spu_device::device_reset() { - m_status = 0; - m_start_port_addr = 0; - m_curr_port_addr = 0; - m_unknown_0x19a = 0; + m_core[0].m_status = 0; + m_core[0].m_start_port_addr = 0; + m_core[0].m_curr_port_addr = 0; + m_core[0].m_unknown_0x19a = 0; + m_core[0].m_autodma_ctrl = 0; + m_core[1].m_status = 0; + m_core[1].m_start_port_addr = 0; + m_core[1].m_curr_port_addr = 0; + m_core[1].m_unknown_0x19a = 0; + m_core[1].m_autodma_ctrl = 0; } -void iop_spu_device::dma_write(uint32_t data) +void iop_spu_device::dma_write(int bank, uint32_t data) { - //m_ram[m_curr_port_addr] = (uint16_t)(data >> 16); - m_curr_port_addr++; - //m_ram[m_curr_port_addr] = (uint16_t)data; - m_curr_port_addr++; + iop_spu_core_t &core = m_core[bank]; + //m_ram[core.m_curr_port_addr] = (uint16_t)(data >> 16); + core.m_curr_port_addr++; + //m_ram[core.m_curr_port_addr] = (uint16_t)data; + core.m_curr_port_addr++; - m_status &= ~STATUS_DMA_DONE; - m_status |= STATUS_DMA_ACTIVE; + if (core.m_curr_port_addr >= 0xfffff) + core.m_curr_port_addr = 0x2800 >> 1; + + core.m_status &= ~STATUS_DMA_DONE; + core.m_status |= STATUS_DMA_ACTIVE; + + if ((core.m_autodma_ctrl & (1 << bank)) && core.m_autodma_done_timer_hack->expire().is_never()) + { + core.m_autodma_done_timer_hack->adjust(attotime::from_ticks(256, 48000), bank); // 256 halfwords * assumed 48kHz sampling rate + } } -void iop_spu_device::dma_done() +void iop_spu_device::dma_done(int bank) { - m_status |= STATUS_DMA_DONE; - m_status &= ~STATUS_DMA_ACTIVE; + iop_spu_core_t &core = m_core[bank]; + core.m_status |= STATUS_DMA_DONE; + core.m_status &= ~STATUS_DMA_ACTIVE; } -uint16_t iop_spu_device::port_read() +void iop_spu_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { - uint16_t ret = m_ram[m_curr_port_addr]; - m_curr_port_addr++; + // TODO +} + +TIMER_CALLBACK_MEMBER(iop_spu_device::autodma_done_timer_hack) +{ + m_core[param].m_autodma_done_timer_hack->adjust(attotime::never); + m_intc->raise_interrupt(iop_intc_device::INT_SPU); +} + +uint16_t iop_spu_device::port_read(int bank) +{ + iop_spu_core_t &core = m_core[bank]; + const uint16_t ret = m_ram[core.m_curr_port_addr]; + core.m_curr_port_addr++; + if (core.m_curr_port_addr >= 0xfffff) + core.m_curr_port_addr = 0x2800 >> 1; return ret; } -void iop_spu_device::port_write(uint16_t data) +void iop_spu_device::port_write(int bank, uint16_t data) { - m_ram[m_curr_port_addr] = data; - m_curr_port_addr++; + iop_spu_core_t &core = m_core[bank]; + m_ram[core.m_curr_port_addr] = data; + core.m_curr_port_addr++; + if (core.m_curr_port_addr >= 0xfffff) + core.m_curr_port_addr = 0x2800 >> 1; } READ16_MEMBER(iop_spu_device::read) { - uint32_t ret = 0; + return reg_read(BIT(offset, 9), (offset << 1) & 0x3ff, mem_mask); +} + +uint16_t iop_spu_device::reg_read(int bank, uint32_t offset, uint16_t mem_mask) +{ + iop_spu_core_t &core = m_core[bank]; + uint16_t ret = 0; + + if (offset < 0x180) + { + const uint32_t reg = offset & 0xf; + ret = core.m_voices[offset >> 4].read(reg); + logerror("%s %d: Voice read: Unknown offset %d (%04x & %04x)\n", machine().describe_context(), bank, reg, ret, mem_mask); + return ret; + } + switch (offset) { - case 0x19a/2: - ret = m_unknown_0x19a; - logerror("%s: read: Unknown 0x19a (%04x & %04x)\n", machine().describe_context(), ret, mem_mask); + case 0x19a: + ret = core.m_unknown_0x19a; + logerror("%s %d: read: Unknown 0x19a (%04x & %04x)\n", machine().describe_context(), bank, ret, mem_mask); break; - case 0x1a8/2: - ret = (uint16_t)(m_start_port_addr >> 16); - logerror("%s: read: PORT_ADDR_HI: %04x & %04x\n", machine().describe_context(), ret, mem_mask); + case 0x1a8: + ret = (uint16_t)(core.m_start_port_addr >> 16); + logerror("%s %d: read: PORT_ADDR_HI: %04x & %04x\n", machine().describe_context(), bank, ret, mem_mask); break; - case 0x1aa/2: - ret = (uint16_t)m_start_port_addr; - logerror("%s: read: PORT_ADDR_LO: %04x & %04x\n", machine().describe_context(), ret, mem_mask); + case 0x1aa: + ret = (uint16_t)core.m_start_port_addr; + logerror("%s %d: read: PORT_ADDR_LO: %04x & %04x\n", machine().describe_context(), bank, ret, mem_mask); break; - case 0x344/2: - ret = m_status; - logerror("%s: read: STATUS: %04x & %04x\n", machine().describe_context(), ret, mem_mask); + case 0x1b0: + ret = core.m_autodma_ctrl; + logerror("%s %d: read: Auto DMA control: %04x & %04x\n", machine().describe_context(), bank, ret, mem_mask); + break; + + case 0x344: + ret = core.m_status; + logerror("%s %d: read: STATUS: %04x & %04x\n", machine().describe_context(), bank, ret, mem_mask); break; default: - logerror("%s: read: Unknown %08x (%04x)\n", machine().describe_context(), 0x1f900000 + (offset << 1), mem_mask); + logerror("%s %d: read: Unknown %08x (%04x)\n", machine().describe_context(), bank, 0x1f900000 + (offset << 1) + (bank << 10), mem_mask); break; } return ret; @@ -96,29 +168,65 @@ READ16_MEMBER(iop_spu_device::read) WRITE16_MEMBER(iop_spu_device::write) { + reg_write(BIT(offset, 9), (offset << 1) & 0x3ff, data, mem_mask); +} + +void iop_spu_device::reg_write(int bank, uint32_t offset, uint16_t data, uint16_t mem_mask) +{ + iop_spu_core_t &core = m_core[bank]; + + if (offset < 0x180) + { + const uint32_t reg = offset & 0xf; + logerror("%s %d: Voice write: Unknown offset %d = %04x & %04x\n", machine().describe_context(), bank, reg, data, mem_mask); + core.m_voices[offset >> 4].write(reg, data); + return; + } + switch (offset) { - case 0x19a/2: - logerror("%s: write: Unknown 0x19a = %04x & %04x\n", machine().describe_context(), data, mem_mask); - m_unknown_0x19a = data; + case 0x19a: + logerror("%s %d: write: Unknown 0x19a = %04x & %04x\n", machine().describe_context(), bank, data, mem_mask); + if (BIT(data, 15)) // Reset? + { + data &= 0x7fff; + core.m_status = 0; + core.m_autodma_ctrl = 0; + } + core.m_unknown_0x19a = data; break; - case 0x1a8/2: - logerror("%s: write: PORT_ADDR_HI: %04x & %04x\n", machine().describe_context(), data, mem_mask); - m_start_port_addr &= ~0x000f0000; - m_start_port_addr |= ((uint32_t)data << 16) & 0x000f0000; - m_curr_port_addr = m_start_port_addr; + case 0x1a8: + logerror("%s %d: write: PORT_ADDR_HI: %04x & %04x\n", machine().describe_context(), bank, data, mem_mask); + core.m_start_port_addr &= ~0x000f0000; + core.m_start_port_addr |= ((uint32_t)data << 16) & 0x000f0000; + core.m_curr_port_addr = core.m_start_port_addr; break; - case 0x1aa/2: - logerror("%s: write: PORT_ADDR_LO: %04x & %04x\n", machine().describe_context(), data, mem_mask); - m_start_port_addr &= ~0x0000ffff; - m_start_port_addr |= data; - m_curr_port_addr = m_start_port_addr; + case 0x1aa: + logerror("%s %d: write: PORT_ADDR_LO: %04x & %04x\n", machine().describe_context(), bank, data, mem_mask); + core.m_start_port_addr &= ~0x0000ffff; + core.m_start_port_addr |= data; + core.m_curr_port_addr = core.m_start_port_addr; break; + case 0x1b0: + logerror("%s %d: write: Auto DMA control: %04x & %04x\n", machine().describe_context(), bank, data, mem_mask); + core.m_autodma_ctrl = data; + break; + default: - logerror("%s: write: Unknown %08x = %04x & %04x\n", machine().describe_context(), 0x1f900000 + (offset << 1), data, mem_mask); + logerror("%s %d: write: Unknown %08x = %04x & %04x\n", machine().describe_context(), bank, 0x1f900000 + (offset << 1) + (bank << 10), data, mem_mask); break; } } + +void iop_spu_device::voice_t::write(uint32_t offset, uint16_t data) +{ + m_unknown[(offset >> 1) & 7] = data; +} + +uint16_t iop_spu_device::voice_t::read(uint32_t offset) +{ + return m_unknown[(offset >> 1) & 7]; +} diff --git a/src/mame/audio/iopspu.h b/src/mame/audio/iopspu.h index 5c224669f21..02a6e699b7a 100644 --- a/src/mame/audio/iopspu.h +++ b/src/mame/audio/iopspu.h @@ -16,15 +16,17 @@ #include "emu.h" #include "cpu/mips/r3000.h" +#include "machine/iopintc.h" -class iop_spu_device : public device_t +class iop_spu_device : public device_t, public device_sound_interface { public: - template - iop_spu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&iop_tag) + template + iop_spu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&iop_tag, U &&intc_tag) : iop_spu_device(mconfig, tag, owner, clock) { m_iop.set_tag(std::forward(iop_tag)); + m_intc.set_tag(std::forward(intc_tag)); } iop_spu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -32,29 +34,66 @@ public: DECLARE_READ16_MEMBER(read); DECLARE_WRITE16_MEMBER(write); - uint16_t port_read(); - void port_write(uint16_t data); + uint16_t reg_read(int bank, uint32_t offset, uint16_t mem_mask); + void reg_write(int bank, uint32_t offset, uint16_t data, uint16_t mem_mask); - void dma_write(uint32_t data); - void dma_done(); + uint16_t port_read(int bank); + void port_write(int bank, uint16_t data); + + void dma_write(int bank, uint32_t data); + void dma_done(int bank); protected: virtual void device_start() override; virtual void device_reset() override; + // sound stream update overrides + virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; + + // HACK: This timer is currently used to trigger an interrupt after the auto-DMA-transferred buffer would have been + // mixed and played back, as the PS2 BIOS pulls a null return address and crashes if we trigger the auto-DMA-complete + // interrupt at the same time as the DMA-complete interrupt. + TIMER_CALLBACK_MEMBER(autodma_done_timer_hack); + enum { STATUS_DMA_DONE = (1 << 7), STATUS_DMA_ACTIVE = (1 << 10) }; + class voice_t + { + public: + voice_t() {} + + void write(uint32_t offset, uint16_t data); + uint16_t read(uint32_t offset); + + protected: + uint16_t m_unknown[8]; + }; + required_device m_iop; + required_device m_intc; std::unique_ptr m_ram; - uint32_t m_status; - uint32_t m_start_port_addr; - uint32_t m_curr_port_addr; - uint32_t m_unknown_0x19a; + struct iop_spu_core_t + { + voice_t m_voices[24]; + + uint32_t m_start_port_addr; + uint32_t m_curr_port_addr; + + uint16_t m_status; + uint16_t m_unknown_0x19a; + uint16_t m_autodma_ctrl; + + emu_timer *m_autodma_done_timer_hack; + }; + + iop_spu_core_t m_core[2]; + + sound_stream *m_stream; }; DECLARE_DEVICE_TYPE(SONYIOP_SPU, iop_spu_device) diff --git a/src/mame/drivers/ps2sony.cpp b/src/mame/drivers/ps2sony.cpp index 932514eb07c..50eb5e8a3e6 100644 --- a/src/mame/drivers/ps2sony.cpp +++ b/src/mame/drivers/ps2sony.cpp @@ -155,17 +155,25 @@ iLinkSGUID=0x-------- (*) values are not detected ************************************************************************************************************************/ + #include "emu.h" + #include "audio/iopspu.h" + #include "cpu/mips/mips3.h" #include "cpu/mips/r3000.h" -#include "machine/ioptimer.h" + +#include "machine/iopcdvd.h" #include "machine/iopdma.h" #include "machine/iopintc.h" -#include "machine/ps2timer.h" +#include "machine/iopsio2.h" +#include "machine/ioptimer.h" + #include "machine/ps2dma.h" #include "machine/ps2intc.h" #include "machine/ps2sif.h" +#include "machine/ps2timer.h" + #include "emupal.h" #include "screen.h" @@ -183,7 +191,9 @@ public: , m_iop_timer(*this, "iop_timer") , m_iop_dma(*this, "iop_dma") , m_iop_intc(*this, "iop_intc") - , m_iop_spu(*this, "iop_spu%u", 1U) + , m_iop_spu(*this, "iop_spu") + , m_iop_cdvd(*this, "iop_cdvd") + , m_iop_sio2(*this, "iop_sio2") , m_screen(*this, "screen") , m_ram(*this, "ram") , m_iop_ram(*this, "iop_ram") @@ -231,12 +241,6 @@ protected: DECLARE_WRITE64_MEMBER(ee_iop_ram_w); DECLARE_READ64_MEMBER(ee_iop_ram_r); DECLARE_WRITE32_MEMBER(iop_debug_w); - DECLARE_READ32_MEMBER(unk_iop_r); - DECLARE_WRITE32_MEMBER(unk_iop_w); - DECLARE_WRITE16_MEMBER(iop_spu_w); - DECLARE_READ16_MEMBER(iop_spu_r); - DECLARE_WRITE16_MEMBER(iop_spu2_w); - DECLARE_READ16_MEMBER(iop_spu2_r); DECLARE_WRITE_LINE_MEMBER(iop_timer_irq); @@ -252,7 +256,9 @@ protected: required_device m_iop_timer; required_device m_iop_dma; required_device m_iop_intc; - required_device_array m_iop_spu; + required_device m_iop_spu; + required_device m_iop_cdvd; + required_device m_iop_sio2; required_device m_screen; required_shared_ptr m_ram; required_shared_ptr m_iop_ram; @@ -279,12 +285,6 @@ protected: uint64_t m_ipu_out_fifo[0x1000]; uint64_t m_ipu_out_fifo_index; - uint32_t m_sif_ms_mailbox; - uint32_t m_sif_sm_mailbox; - uint32_t m_sif_ms_flag; - uint32_t m_sif_sm_flag; - uint32_t m_sif_ctrl; - emu_timer *m_vblank_timer; }; @@ -543,50 +543,6 @@ WRITE32_MEMBER(ps2sony_state::iop_debug_w) //printf("%08x ", data); } -READ32_MEMBER(ps2sony_state::unk_iop_r) -{ - uint32_t ret = 0; - switch (offset) - { - case 1: - if (mem_mask & 0xff00) - ret |= 0x4000; - logerror("%s; unk_iop_r: Unknown read: %08x = %08x & %08x\n", machine().describe_context(), 0x1f402000 + (offset << 2), ret, mem_mask); - break; - default: - logerror("%s; unk_iop_r: Unknown read: %08x & %08x\n", machine().describe_context(), 0x1f402000 + (offset << 2), mem_mask); - break; - } - return ret; -} - -WRITE32_MEMBER(ps2sony_state::unk_iop_w) -{ - logerror("%s; unk_iop_w: Unknown write: %08x = %08x & %08x\n", machine().describe_context(), 0x1f402000 + (offset << 2), data, mem_mask); -} - -WRITE16_MEMBER(ps2sony_state::iop_spu2_w) -{ - switch (offset) - { - default: - logerror("%s: iop_spu2_w: Unknown %08x = %04x & %04x\n", 0x1f900000 + (offset << 1), data, mem_mask); - break; - } -} - -READ16_MEMBER(ps2sony_state::iop_spu2_r) -{ - uint32_t ret = 0; - switch (offset) - { - default: - logerror("%s: iop_spu2_r: Unknown %08x (%04x)\n", 0x1f900000 + (offset << 1), mem_mask); - break; - } - return ret; -} - void ps2sony_state::machine_start() { save_item(NAME(m_gs_base_regs)); @@ -630,12 +586,6 @@ void ps2sony_state::machine_reset() m_gs_sig_label_id = 0ULL; m_vblank_timer->adjust(m_screen->time_until_pos(480), 1); - - m_sif_ms_mailbox = 0; - m_sif_sm_mailbox = 0; - m_sif_ms_flag = 0; - m_sif_sm_flag = 0; - m_sif_ctrl = 0; } TIMER_CALLBACK_MEMBER(ps2sony_state::vblank) @@ -901,7 +851,7 @@ void ps2sony_state::iop_map(address_map &map) map(0x00000000, 0x001fffff).ram().share(m_iop_ram); map(0x1d000000, 0x1d00004f).rw(m_sif, FUNC(ps2_sif_device::iop_r), FUNC(ps2_sif_device::iop_w)); map(0x1e000000, 0x1e003fff).nopr(); - map(0x1f402000, 0x1f40200f).rw(FUNC(ps2sony_state::unk_iop_r), FUNC(ps2sony_state::unk_iop_w)); + map(0x1f402000, 0x1f40201f).rw(m_iop_cdvd, FUNC(iop_cdvd_device::read), FUNC(iop_cdvd_device::write)); map(0x1f801070, 0x1f80107b).rw(m_iop_intc, FUNC(iop_intc_device::read), FUNC(iop_intc_device::write)); map(0x1f801080, 0x1f8010f7).rw(m_iop_dma, FUNC(iop_dma_device::bank0_r), FUNC(iop_dma_device::bank0_w)); map(0x1f801450, 0x1f801453).noprw(); @@ -909,8 +859,8 @@ void ps2sony_state::iop_map(address_map &map) map(0x1f801500, 0x1f801577).rw(m_iop_dma, FUNC(iop_dma_device::bank1_r), FUNC(iop_dma_device::bank1_w)); map(0x1f801578, 0x1f80157b).noprw(); map(0x1f802070, 0x1f802073).w(FUNC(ps2sony_state::iop_debug_w)).nopr(); - map(0x1f900000, 0x1f9003ff).rw(m_iop_spu[0], FUNC(iop_spu_device::read), FUNC(iop_spu_device::write)); - map(0x1f900400, 0x1f9007ff).rw(m_iop_spu[1], FUNC(iop_spu_device::read), FUNC(iop_spu_device::write)); + map(0x1f808200, 0x1f8082ff).rw(m_iop_sio2, FUNC(iop_sio2_device::read), FUNC(iop_sio2_device::write)); + map(0x1f900000, 0x1f9007ff).rw(m_iop_spu, FUNC(iop_spu_device::read), FUNC(iop_spu_device::write)); map(0x1fc00000, 0x1fffffff).rom().region("bios", 0); map(0x1ffe0130, 0x1ffe0133).nopw(); } @@ -941,12 +891,13 @@ MACHINE_CONFIG_START(ps2sony_state::ps2sony) MCFG_QUANTUM_PERFECT_CPU("iop") MCFG_DEVICE_ADD(m_iop_intc, SONYIOP_INTC, m_iop) + MCFG_DEVICE_ADD(m_iop_sio2, SONYIOP_SIO2, m_iop_intc) + MCFG_DEVICE_ADD(m_iop_cdvd, SONYIOP_CDVD, m_iop_intc) MCFG_DEVICE_ADD(m_iop_timer, SONYIOP_TIMER, XTAL(67'737'600)/2) MCFG_IOP_TIMER_IRQ_CALLBACK(WRITELINE(*this, ps2sony_state, iop_timer_irq)) - MCFG_DEVICE_ADD(m_iop_spu[0], SONYIOP_SPU, XTAL(67'737'600)/2, m_iop) - MCFG_DEVICE_ADD(m_iop_spu[1], SONYIOP_SPU, XTAL(67'737'600)/2, m_iop) + MCFG_DEVICE_ADD(m_iop_spu, SONYIOP_SPU, XTAL(67'737'600)/2, m_iop, m_iop_intc) - MCFG_DEVICE_ADD(m_iop_dma, SONYIOP_DMA, XTAL(67'737'600)/2, m_iop_intc, m_iop_ram, m_sif, m_iop_spu[0], m_iop_spu[1]) + MCFG_DEVICE_ADD(m_iop_dma, SONYIOP_DMA, XTAL(67'737'600)/2, m_iop_intc, m_iop_ram, m_sif, m_iop_spu, m_iop_sio2) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) diff --git a/src/mame/machine/iopcdvd.cpp b/src/mame/machine/iopcdvd.cpp new file mode 100644 index 00000000000..ff3ce8ac021 --- /dev/null +++ b/src/mame/machine/iopcdvd.cpp @@ -0,0 +1,122 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 disc controller device skeleton +* +* To Do: +* Everything +* +*/ + +#include "iopcdvd.h" + +/*static*/ const size_t iop_cdvd_device::BUFFER_SIZE = 2048; // Total guess + +DEFINE_DEVICE_TYPE(SONYIOP_CDVD, iop_cdvd_device, "iopcdvd", "Playstation 2 disc controller") + +iop_cdvd_device::iop_cdvd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SONYIOP_CDVD, tag, owner, clock) + , m_intc(*this, finder_base::DUMMY_TAG) +{ +} + +void iop_cdvd_device::device_start() +{ + m_out_buf = std::make_unique(BUFFER_SIZE); + + save_item(NAME(m_status_0x05)); + save_item(NAME(m_status_0x17)); + save_item(NAME(m_command)); + save_item(NAME(m_out_count)); + save_item(NAME(m_out_curr)); +} + +void iop_cdvd_device::device_reset() +{ + m_status_0x05 = CDVD_STATUS_BOOT; + m_status_0x17 = CDVD_STATUS_IDLE; + m_command = 0; + memset(&m_out_buf[0], 0, BUFFER_SIZE); + m_out_count = 0; + m_out_curr = 0; +} + +READ8_MEMBER(iop_cdvd_device::read) +{ + uint8_t ret = 0; + switch (offset) + { + case 0x05: + ret = m_status_0x05; + logerror("%s: cdvd_r: Status 0x05? (%02x)\n", machine().describe_context(), ret); + break; + case 0x16: + ret = m_command; + logerror("%s: cdvd_r: Command? (%02x)\n", machine().describe_context(), ret); + break; + case 0x17: + ret = m_status_0x17; + logerror("%s: cdvd_r: Status 0x17? (%02x)\n", machine().describe_context(), ret); + break; + case 0x18: + ret = m_out_buf[m_out_curr]; + if (m_out_curr < m_out_count) + { + m_out_curr++; + if (m_out_curr == m_out_count) + { + m_status_0x17 |= CDVD_STATUS_IDLE; + m_out_count = 0; + m_out_curr = 0; + } + } + logerror("%s: cdvd_r: Command Output (%02x) (%d left)\n", machine().describe_context(), ret, m_out_count - m_out_curr); + break; + default: + logerror("%s: cdvd_r: Unknown read: %08x\n", machine().describe_context(), 0x1f402000 + offset); + break; + } + return ret; +} + +WRITE8_MEMBER(iop_cdvd_device::write) +{ + switch (offset) + { + case 0x16: + m_command = data; + m_status_0x17 &= ~(CDVD_STATUS_IDLE | CDVD_STATUS_BOOT); + m_status_0x05 &= ~CDVD_STATUS_BOOT; + if (m_out_count > 0) + logerror("%s: cdvd_w: Command warning: Issuing command without reading previous results\n", machine().describe_context()); + switch (data) + { + case 0x15: + logerror("%s: cdvd_w: Command 0x15?\n", machine().describe_context()); + m_out_buf[m_out_count++] = 1; + m_intc->raise_interrupt(5); + break; + case 0x40: + logerror("%s: cdvd_w: Command 0x40?\n", machine().describe_context()); + m_out_buf[m_out_count++] = 0; + break; + case 0x41: + logerror("%s: cdvd_w: Command 0x41?\n", machine().describe_context()); + m_out_count = 0x10; + memset(&m_out_buf[0], 0, 0x10); + break; + case 0x43: + logerror("%s: cdvd_w: Command 0x43?\n", machine().describe_context()); + m_out_buf[m_out_count++] = 0; + break; + default: + logerror("%s: cdvd_r: Unknown command(?) %02x\n", machine().describe_context(), data); + break; + } + break; + default: + logerror("%s: cdvd_w: Unknown write: %08x = %02x\n", machine().describe_context(), 0x1f402000 + offset, data); + break; + } +} diff --git a/src/mame/machine/iopcdvd.h b/src/mame/machine/iopcdvd.h new file mode 100644 index 00000000000..e8d13da45b0 --- /dev/null +++ b/src/mame/machine/iopcdvd.h @@ -0,0 +1,60 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 disc controller device skeleton +* +* To Do: +* Everything +* +*/ + +#ifndef MAME_MACHINE_IOPCDVD_H +#define MAME_MACHINE_IOPCDVD_H + +#pragma once + +#include "emu.h" +#include "iopintc.h" + +class iop_cdvd_device : public device_t +{ +public: + template + iop_cdvd_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&intc_tag) + : iop_cdvd_device(mconfig, tag, owner, (uint32_t)0) + { + m_intc.set_tag(std::forward(intc_tag)); + } + + iop_cdvd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + enum + { + CDVD_STATUS_BOOT = 0x08, + CDVD_STATUS_IDLE = 0x40, + + CDVD_COMMAND_0x15 = 0x15, + }; + + required_device m_intc; + uint8_t m_status_0x05; + uint8_t m_status_0x17; + uint8_t m_command; + std::unique_ptr m_out_buf; + uint8_t m_out_count; + uint8_t m_out_curr; + + static const size_t BUFFER_SIZE; +}; + +DECLARE_DEVICE_TYPE(SONYIOP_CDVD, iop_cdvd_device) + +#endif // MAME_MACHINE_IOPCDVD_H \ No newline at end of file diff --git a/src/mame/machine/iopdma.cpp b/src/mame/machine/iopdma.cpp index d619779011f..4713a425ad2 100644 --- a/src/mame/machine/iopdma.cpp +++ b/src/mame/machine/iopdma.cpp @@ -21,7 +21,7 @@ iop_dma_device::iop_dma_device(const machine_config &mconfig, const char *tag, d , m_ram(*this, finder_base::DUMMY_TAG) , m_sif(*this, finder_base::DUMMY_TAG) , m_spu(*this, finder_base::DUMMY_TAG) - , m_spu2(*this, finder_base::DUMMY_TAG) + , m_sio2(*this, finder_base::DUMMY_TAG) , m_icount(0) { } @@ -38,11 +38,12 @@ void iop_dma_device::device_start() save_item(NAME(m_channels[channel].m_end), channel); save_item(NAME(m_channels[channel].m_addr), channel); - save_item(NAME(m_channels[channel].m_block), channel); save_item(NAME(m_channels[channel].m_ctrl), channel); save_item(NAME(m_channels[channel].m_tag_addr), channel); - save_item(NAME(m_channels[channel].m_size), channel); + save_item(NAME(m_channels[channel].m_block), channel); + save_item(NAME(m_channels[channel].m_block_count), channel); + save_item(NAME(m_channels[channel].m_word_count), channel); save_item(NAME(m_channels[channel].m_count), channel); } @@ -92,8 +93,8 @@ void iop_dma_device::execute_run() { switch (channel) { - case SPU: - case SPU2: + case SPU_BANK1: + case SPU_BANK2: transfer_spu(channel); break; case SIF0: @@ -102,6 +103,12 @@ void iop_dma_device::execute_run() case SIF1: transfer_sif1(channel); break; + case SIO2_IN: + transfer_to_sio2(channel); + break; + case SIO2_OUT: + transfer_from_sio2(channel); + break; default: logerror("%s: Attempting to transfer an unimplemented DMA channel (%d)\n", machine().describe_context(), channel); break; @@ -164,16 +171,18 @@ void iop_dma_device::transfer_sif0(uint32_t chan) void iop_dma_device::transfer_sif1(uint32_t chan) { channel_t &channel = m_channels[chan]; - if (channel.m_count) + const uint32_t count = channel.count(); + if (count) { if (m_sif->fifo_depth(1)) { const uint32_t data = m_sif->fifo_pop(1); + const uint32_t addr = channel.addr(); //logerror("%s: sif1 pop value: %08x\n", machine().describe_context(), (uint32_t)data); - m_ram[channel.m_addr >> 2] = data; + m_ram[addr >> 2] = data; - channel.m_addr += 4; - channel.m_count--; + channel.set_addr(addr + 4); + channel.set_count(count - 1); } } else @@ -205,35 +214,77 @@ void iop_dma_device::transfer_sif1(uint32_t chan) void iop_dma_device::transfer_spu(uint32_t chan) { channel_t &channel = m_channels[chan]; - const uint32_t size = channel.size(); - if (size) + const uint32_t count = channel.count(); + const bool first_bank = chan == SPU_BANK1; + const int bank = first_bank ? 0 : 1; + if (count) { - printf("Size: %08x\n", size); const uint32_t addr = channel.addr(); - if (chan == SPU) - m_spu->dma_write(m_ram[addr >> 2]); - else - m_spu2->dma_write(m_ram[addr >> 2]); + m_spu->dma_write(bank, m_ram[addr >> 2]); - channel.set_size(size - 1); + channel.set_count(count - 1); + channel.set_addr(addr + 4); + } + else if (channel.busy()) + { + channel.set_word_count(0); + channel.set_block_count(0); + + m_spu->dma_done(bank); + + //if (first_bank) + //m_intc->raise_interrupt(iop_intc_device::INT_SPU); + + transfer_finish(chan); + } +} + +void iop_dma_device::transfer_to_sio2(uint32_t chan) +{ + channel_t &channel = m_channels[chan]; + const uint32_t count = channel.count(); + // TODO: Clock out at correct serial rate + if (count) + { + const uint32_t addr = channel.addr(); + const uint32_t data = m_ram[addr >> 2]; + m_sio2->receive((data >> 24) & 0xff); + m_sio2->receive((data >> 16) & 0xff); + m_sio2->receive((data >> 8) & 0xff); + m_sio2->receive(data & 0xff); + channel.set_count(count - 1); channel.set_addr(addr + 4); } else { - channel.set_count(0); + channel.set_block_count(0); + channel.set_word_count(0); + transfer_finish(SIO2_IN); + } +} - if (chan == SPU) - m_spu->dma_done(); - else - m_spu2->dma_done(); - - if (chan == SPU) - { - m_intc->raise_interrupt(iop_intc_device::INT_SPU); - } - - transfer_finish(chan); +void iop_dma_device::transfer_from_sio2(uint32_t chan) +{ + channel_t &channel = m_channels[chan]; + const uint32_t count = channel.count(); + // TODO: Clock in at correct serial rate + if (count) + { + const uint32_t addr = channel.addr(); + uint32_t data = m_sio2->transmit() << 24; + data |= m_sio2->transmit() << 16; + data |= m_sio2->transmit() << 8; + data |= m_sio2->transmit(); + m_ram[addr >> 2] = data; + channel.set_count(count - 1); + channel.set_addr(addr + 4); + } + else + { + channel.set_block_count(0); + channel.set_word_count(0); + transfer_finish(SIO2_OUT); } } @@ -264,7 +315,7 @@ READ32_MEMBER(iop_dma_device::bank0_r) logerror("%s: bank0_r: channel[%d].addr (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask); break; case 0x04/4: case 0x14/4: case 0x24/4: case 0x34/4: case 0x44/4: case 0x54/4: case 0x64/4: - ret = (m_channels[offset >> 2].count() << 16) | m_channels[offset >> 2].size(); + ret = m_channels[offset >> 2].block(); logerror("%s: bank0_r: channel[%d].block (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask); break; case 0x08/4: case 0x18/4: case 0x28/4: case 0x38/4: case 0x48/4: case 0x58/4: case 0x68/4: @@ -337,7 +388,7 @@ READ32_MEMBER(iop_dma_device::bank1_r) logerror("%s: bank1_r: channel[%d].addr (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask); break; case 0x04/4: case 0x14/4: case 0x24/4: case 0x34/4: case 0x44/4: case 0x54/4: case 0x64/4: - ret = (m_channels[(offset >> 2) + 8].count() << 16) | m_channels[(offset >> 2) + 8].size(); + ret = m_channels[(offset >> 2) + 8].block(); logerror("%s: bank1_r: channel[%d].block (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask); break; case 0x08/4: case 0x18/4: case 0x28/4: case 0x38/4: case 0x48/4: case 0x58/4: case 0x68/4: @@ -421,8 +472,8 @@ void iop_dma_device::set_dpcr(uint32_t data, uint32_t index) void iop_dma_device::set_dicr(uint32_t data, uint32_t index) { - m_dicr[index] = (m_dicr[index] & (0x7f << 24)) | (data & ~(0x7f << 24)); - m_dicr[index] &= ~(data & (0x7f << 24)); + m_dicr[index] = (m_dicr[index] & 0x7f000000) | (data & ~0x7f007fff); + m_dicr[index] &= ~(data & 0x7f000000); m_int_ctrl[index].m_mask = (data >> 16) & 0x7f; m_int_ctrl[index].m_status &= ~((data >> 24) & 0x7f); m_int_ctrl[index].m_enabled = BIT(data, 23); @@ -440,10 +491,23 @@ void iop_dma_device::channel_t::set_pri_ctrl(uint32_t pri_ctrl) void iop_dma_device::channel_t::set_block(uint32_t block, uint32_t mem_mask) { + m_block = block; if (mem_mask & 0xffff) - m_size = (uint16_t)block; + set_block_count(block); if (mem_mask & 0xffff0000) - m_count = (uint16_t)(block >> 16); + set_word_count(block >> 16); +} + +void iop_dma_device::channel_t::set_block_count(uint32_t block_count) +{ + m_block_count = (uint16_t)block_count; + m_count = m_block_count * m_word_count; +} + +void iop_dma_device::channel_t::set_word_count(uint32_t word_count) +{ + m_word_count = (uint16_t)word_count; + m_count = m_block_count * m_word_count; } void iop_dma_device::channel_t::set_ctrl(uint32_t ctrl) diff --git a/src/mame/machine/iopdma.h b/src/mame/machine/iopdma.h index 1c17f324813..338f1287228 100644 --- a/src/mame/machine/iopdma.h +++ b/src/mame/machine/iopdma.h @@ -17,20 +17,21 @@ #include "emu.h" #include "ps2sif.h" #include "iopintc.h" +#include "iopsio2.h" #include "audio/iopspu.h" class iop_dma_device : public device_t, public device_execute_interface { public: template - iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc_tag, U &&ram_tag, V &&sif_tag, W &&spu_tag, X &&spu2_tag) + iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc_tag, U &&ram_tag, V &&sif_tag, W &&spu_tag, X &&sio2_tag) : iop_dma_device(mconfig, tag, owner, clock) { m_intc.set_tag(std::forward(intc_tag)); m_ram.set_tag(std::forward(ram_tag)); m_sif.set_tag(std::forward(sif_tag)); m_spu.set_tag(std::forward(spu_tag)); - m_spu2.set_tag(std::forward(spu2_tag)); + m_sio2.set_tag(std::forward(sio2_tag)); } iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -46,11 +47,11 @@ public: MDEC_OUT, GPU, CDVD, - SPU, + SPU_BANK1, PIO, OTC, UNUSED_BANK0, - SPU2, + SPU_BANK2, UNKNOWN0, SIF0, SIF1, @@ -74,27 +75,41 @@ protected: public: channel_t() - : m_priority(0), m_enabled(false), m_addr(0), m_block(0), m_ctrl(0), m_tag_addr(0), m_size(0), m_count(0) + : m_priority(0) + , m_enabled(false) + , m_busy(false) + , m_end(false) + , m_addr(0) + , m_ctrl(0) + , m_tag_addr(0) + , m_block(0) + , m_block_count(0) + , m_word_count(0) + , m_count(0) { } void set_pri_ctrl(uint32_t pri_ctrl); void set_addr(uint32_t addr) { m_addr = addr; } void set_block(uint32_t block, uint32_t mem_mask); - void set_size(uint32_t size) { m_size = size; } + void set_block_count(uint32_t block_count); + void set_word_count(uint32_t word_count); void set_count(uint32_t count) { m_count = count; } void set_ctrl(uint32_t ctrl); void set_tag_addr(uint32_t tag_addr) { m_tag_addr = tag_addr; } bool enabled() const { return m_enabled; } + bool end() const { return m_end; } bool busy() const { return m_busy; } + uint32_t addr() const { return m_addr; } - uint32_t block() const { return m_block; } - uint32_t size() const { return m_size; } - uint32_t count() const { return m_count; } uint32_t ctrl() const { return m_ctrl; } uint32_t tag_addr() const { return m_tag_addr; } - bool end() const { return m_end; } + + uint32_t block() const { return m_block; } + uint32_t block_count() const { return m_block_count; } + uint32_t word_count() const { return m_word_count; } + uint32_t count() const { return m_count; } protected: uint8_t m_priority; @@ -103,11 +118,12 @@ protected: bool m_end; uint32_t m_addr; - uint32_t m_block; uint32_t m_ctrl; uint32_t m_tag_addr; - uint32_t m_size; + uint32_t m_block; + uint32_t m_block_count; + uint32_t m_word_count; uint32_t m_count; }; @@ -122,13 +138,15 @@ protected: void transfer_sif0(uint32_t chan); void transfer_sif1(uint32_t chan); void transfer_spu(uint32_t chan); + void transfer_to_sio2(uint32_t chan); + void transfer_from_sio2(uint32_t chan); void transfer_finish(uint32_t chan); required_device m_intc; required_shared_ptr m_ram; required_device m_sif; required_device m_spu; - required_device m_spu2; + required_device m_sio2; int m_icount; diff --git a/src/mame/machine/iopintc.h b/src/mame/machine/iopintc.h index d2e4fb6bfbf..dc3e68ab6c5 100644 --- a/src/mame/machine/iopintc.h +++ b/src/mame/machine/iopintc.h @@ -40,7 +40,8 @@ public: INT_DMA = 3, INT_SPU = 9, INT_VB_OFF = 11, - INT_TIMER = 16 + INT_TIMER = 16, + INT_SIO2 = 17 }; protected: diff --git a/src/mame/machine/iopsio2.cpp b/src/mame/machine/iopsio2.cpp new file mode 100644 index 00000000000..20ec5956e5d --- /dev/null +++ b/src/mame/machine/iopsio2.cpp @@ -0,0 +1,102 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 SIO2 device skeleton +* +* To Do: +* Everything +* +*/ + +#include "iopsio2.h" + +/*static*/ const size_t iop_sio2_device::BUFFER_SIZE = 64; // total guess + +DEFINE_DEVICE_TYPE(SONYIOP_SIO2, iop_sio2_device, "iopsio2", "Playstation 2 SIO2") + +iop_sio2_device::iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SONYIOP_SIO2, tag, owner, clock) + , m_intc(*this, finder_base::DUMMY_TAG) +{ +} + +void iop_sio2_device::device_start() +{ + save_item(NAME(m_ctrl)); + save_item(NAME(m_receive_buf)); + save_item(NAME(m_receive_curr)); + save_item(NAME(m_receive_end)); + save_item(NAME(m_transmit_buf)); + save_item(NAME(m_transmit_curr)); + save_item(NAME(m_transmit_end)); +} + +void iop_sio2_device::device_reset() +{ + m_ctrl = 0; + + memset(m_receive_buf, 0, BUFFER_SIZE); + m_receive_curr = 0; + m_receive_end = 0; + + memset(m_transmit_buf, 0, BUFFER_SIZE); + m_transmit_curr = 0; + m_transmit_end = 0; +} + +READ32_MEMBER(iop_sio2_device::read) +{ + uint32_t ret = 0; + switch (offset) + { + case 0x68/4: // Control? + logerror("%s: read: CTRL %08x & %08x\n", machine().describe_context(), ret, mem_mask); + break; + default: + logerror("%s: read: Unknown offset %08x & %08x\n", machine().describe_context(), 0x1f808200 + (offset << 2), mem_mask); + break; + } + return ret; +} + +WRITE32_MEMBER(iop_sio2_device::write) +{ + switch (offset) + { + case 0x68/4: // Control? + { + uint32_t old_ctrl = m_ctrl; + m_ctrl = data & CTRL_IRQ; + if (old_ctrl != m_ctrl && (m_ctrl & CTRL_IRQ)) + { + m_intc->raise_interrupt(iop_intc_device::INT_SIO2); + } + break; + } + default: + logerror("%s: write: Unknown offset %08x = %08x & %08x\n", machine().describe_context(), 0x1f808200 + (offset << 2), data, mem_mask); + break; + } +} + +uint8_t iop_sio2_device::transmit() +{ + if (m_transmit_curr == m_transmit_end) + { + return 0; + } + uint8_t ret = m_transmit_buf[m_transmit_curr]; + m_transmit_curr = (m_transmit_curr + 1) & (BUFFER_SIZE-1); + return ret; +} + +void iop_sio2_device::receive(uint8_t data) +{ + if (m_receive_end >= BUFFER_SIZE) + { + return; + } + m_receive_buf[m_receive_end] = data; + m_receive_end++; +} diff --git a/src/mame/machine/iopsio2.h b/src/mame/machine/iopsio2.h new file mode 100644 index 00000000000..354b970c842 --- /dev/null +++ b/src/mame/machine/iopsio2.h @@ -0,0 +1,63 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 SIO2 device skeleton +* +* To Do: +* Everything +* +*/ + +#ifndef MAME_MACHINE_IOPSIO2_H +#define MAME_MACHINE_IOPSIO2_H + +#pragma once + +#include "emu.h" +#include "iopintc.h" + +class iop_sio2_device : public device_t +{ +public: + template + iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&intc_tag) + : iop_sio2_device(mconfig, tag, owner, (uint32_t)0) + { + m_intc.set_tag(std::forward(intc_tag)); + } + + iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ32_MEMBER(read); + DECLARE_WRITE32_MEMBER(write); + + void receive(uint8_t data); + uint8_t transmit(); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + enum + { + CTRL_IRQ = 0x01, + }; + + required_device m_intc; + + // HACK: Buffer sizes are guesses. + uint8_t m_receive_buf[64]; + uint8_t m_receive_curr; + uint8_t m_receive_end; + uint8_t m_transmit_buf[64]; + uint8_t m_transmit_curr; + uint8_t m_transmit_end; + uint32_t m_ctrl; + + static const size_t BUFFER_SIZE; +}; + +DECLARE_DEVICE_TYPE(SONYIOP_SIO2, iop_sio2_device) + +#endif // MAME_MACHINE_IOPSIO2_H \ No newline at end of file diff --git a/src/mame/machine/ps2dma.cpp b/src/mame/machine/ps2dma.cpp index 90153ae44ac..34058d3cf94 100644 --- a/src/mame/machine/ps2dma.cpp +++ b/src/mame/machine/ps2dma.cpp @@ -211,6 +211,10 @@ void ps2_dmac_device::follow_source_tag(uint32_t chan) channel.set_addr(addr); channel.set_tag_addr(channel.tag_addr() + 0x10); break; + case ID_NEXT: + channel.set_addr(channel.tag_addr() + 0x10); + channel.set_tag_addr(addr); + break; default: logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id); break; @@ -401,7 +405,7 @@ READ32_MEMBER(ps2_dmac_device::channel_r) break; case 0xc400/8: /* SIF1_CHCR */ ret = m_channels[SIF1].chcr(); - logerror("%s: dmac_channel_r: SIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc410/8: /* SIF1_MADR */ ret = m_channels[SIF1].addr(); @@ -413,7 +417,7 @@ READ32_MEMBER(ps2_dmac_device::channel_r) break; case 0xc430/8: /* SIF1_TADR */ ret = m_channels[SIF1].tag_addr(); - logerror("%s: dmac_channel_r: SIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc800/8: /* D7_CHCR */ logerror("%s: dmac_channel_r: D7_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); diff --git a/src/mame/machine/ps2sif.cpp b/src/mame/machine/ps2sif.cpp index 3160103f9b5..a47747892af 100644 --- a/src/mame/machine/ps2sif.cpp +++ b/src/mame/machine/ps2sif.cpp @@ -66,8 +66,8 @@ READ32_MEMBER(ps2_sif_device::ee_r) break; case 6: ret = m_sm_flag; - if (ret != 0) - logerror("%s: ee_r: SIF slave->master flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //if (ret != 0) + //logerror("%s: ee_r: SIF slave->master flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 8: ret = m_ctrl | 0xF0000102;