mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
ps2sony: Fixed some R3000 bugs, started fleshing out IOP devices, nw
This commit is contained in:
parent
65a876f818
commit
9d60df7b06
@ -3063,6 +3063,10 @@ files {
|
|||||||
MAME_DIR .. "src/mame/drivers/ps2sony.cpp",
|
MAME_DIR .. "src/mame/drivers/ps2sony.cpp",
|
||||||
MAME_DIR .. "src/mame/machine/ps2timer.cpp",
|
MAME_DIR .. "src/mame/machine/ps2timer.cpp",
|
||||||
MAME_DIR .. "src/mame/machine/ps2timer.h",
|
MAME_DIR .. "src/mame/machine/ps2timer.h",
|
||||||
|
MAME_DIR .. "src/mame/machine/ioptimer.cpp",
|
||||||
|
MAME_DIR .. "src/mame/machine/ioptimer.h",
|
||||||
|
MAME_DIR .. "src/mame/machine/iopdma.cpp",
|
||||||
|
MAME_DIR .. "src/mame/machine/iopdma.h",
|
||||||
}
|
}
|
||||||
|
|
||||||
createMESSProjects(_target, _subtarget, "sord")
|
createMESSProjects(_target, _subtarget, "sord")
|
||||||
|
@ -211,7 +211,10 @@ r3081_device::r3081_device(const machine_config &mconfig, const char *tag, devic
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
: r3000_device(mconfig, SONYPS2_IOP, tag, owner, clock, CHIP_TYPE_IOP) { }
|
: r3000_device(mconfig, SONYPS2_IOP, tag, owner, clock, CHIP_TYPE_IOP)
|
||||||
|
{
|
||||||
|
m_endianness = ENDIANNESS_LITTLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -384,7 +387,6 @@ void r3000_device::device_start()
|
|||||||
save_item(NAME(m_dcache));
|
save_item(NAME(m_dcache));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// device_post_load -
|
// device_post_load -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -416,7 +418,7 @@ void r3000_device::device_reset()
|
|||||||
void iop_device::device_reset()
|
void iop_device::device_reset()
|
||||||
{
|
{
|
||||||
r3000_device::device_reset();
|
r3000_device::device_reset();
|
||||||
m_cpr[0][COP0_PRId] = 0x2;
|
m_cpr[0][COP0_PRId] = 0x1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -506,31 +508,43 @@ inline uint32_t r3000_device::readop(offs_t pc)
|
|||||||
|
|
||||||
uint8_t r3000_device::readmem(offs_t offset)
|
uint8_t r3000_device::readmem(offs_t offset)
|
||||||
{
|
{
|
||||||
|
if (SR & SR_IsC)
|
||||||
|
return 0;
|
||||||
return m_program->read_byte(offset);
|
return m_program->read_byte(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t r3000_device::readmem_word(offs_t offset)
|
uint16_t r3000_device::readmem_word(offs_t offset)
|
||||||
{
|
{
|
||||||
|
if (SR & SR_IsC)
|
||||||
|
return 0;
|
||||||
return m_program->read_word(offset);
|
return m_program->read_word(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t r3000_device::readmem_dword(offs_t offset)
|
uint32_t r3000_device::readmem_dword(offs_t offset)
|
||||||
{
|
{
|
||||||
|
if (SR & SR_IsC)
|
||||||
|
return 0;
|
||||||
return m_program->read_dword(offset);
|
return m_program->read_dword(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void r3000_device::writemem(offs_t offset, uint8_t data)
|
void r3000_device::writemem(offs_t offset, uint8_t data)
|
||||||
{
|
{
|
||||||
|
if (SR & SR_IsC)
|
||||||
|
return;
|
||||||
m_program->write_byte(offset, data);
|
m_program->write_byte(offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void r3000_device::writemem_word(offs_t offset, uint16_t data)
|
void r3000_device::writemem_word(offs_t offset, uint16_t data)
|
||||||
{
|
{
|
||||||
|
if (SR & SR_IsC)
|
||||||
|
return;
|
||||||
m_program->write_word(offset, data);
|
m_program->write_word(offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void r3000_device::writemem_dword(offs_t offset, uint32_t data)
|
void r3000_device::writemem_dword(offs_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
|
if (SR & SR_IsC)
|
||||||
|
return;
|
||||||
m_program->write_dword(offset, data);
|
m_program->write_dword(offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,7 +638,7 @@ void r3000_device::writecache_le_dword(offs_t offset, uint32_t data)
|
|||||||
inline void r3000_device::generate_exception(int exception)
|
inline void r3000_device::generate_exception(int exception)
|
||||||
{
|
{
|
||||||
// set the exception PC
|
// set the exception PC
|
||||||
m_cpr[0][COP0_EPC] = m_pc;
|
m_cpr[0][COP0_EPC] = (exception == EXCEPTION_SYSCALL ? m_ppc : m_pc);
|
||||||
|
|
||||||
// put the cause in the low 8 bits and clear the branch delay flag
|
// put the cause in the low 8 bits and clear the branch delay flag
|
||||||
CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
|
CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
|
||||||
@ -641,10 +655,11 @@ inline void r3000_device::generate_exception(int exception)
|
|||||||
SR = (SR & 0xffffffc0) | ((SR << 2) & 0x3c);
|
SR = (SR & 0xffffffc0) | ((SR << 2) & 0x3c);
|
||||||
|
|
||||||
// based on the BEV bit, we either go to ROM or RAM
|
// based on the BEV bit, we either go to ROM or RAM
|
||||||
m_pc = (SR & SR_BEV) ? 0xbfc00000 : 0x80000000;
|
bool bev = (SR & SR_BEV) ? true : false;
|
||||||
|
m_pc = bev ? 0xbfc00000 : 0x80000000;
|
||||||
|
|
||||||
// most exceptions go to offset 0x180, except for TLB stuff
|
// most exceptions go to offset 0x180, except for TLB stuff and syscall (if BEV is unset)
|
||||||
if (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE)
|
if ((exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE) || !bev)
|
||||||
m_pc += 0x80;
|
m_pc += 0x80;
|
||||||
else
|
else
|
||||||
m_pc += 0x180;
|
m_pc += 0x180;
|
||||||
|
@ -159,6 +159,8 @@ iLinkSGUID=0x--------
|
|||||||
#include "cpu/mips/mips3.h"
|
#include "cpu/mips/mips3.h"
|
||||||
#include "cpu/mips/r3000.h"
|
#include "cpu/mips/r3000.h"
|
||||||
#include "machine/ps2timer.h"
|
#include "machine/ps2timer.h"
|
||||||
|
#include "machine/ioptimer.h"
|
||||||
|
#include "machine/iopdma.h"
|
||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
@ -168,7 +170,10 @@ public:
|
|||||||
ps2sony_state(const machine_config &mconfig, device_type type, const char *tag)
|
ps2sony_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||||
: driver_device(mconfig, type, tag)
|
: driver_device(mconfig, type, tag)
|
||||||
, m_maincpu(*this, "maincpu")
|
, m_maincpu(*this, "maincpu")
|
||||||
|
, m_iop(*this, "iop")
|
||||||
, m_timer(*this, "timer%u", 0U)
|
, m_timer(*this, "timer%u", 0U)
|
||||||
|
, m_iop_timer(*this, "iop_timer")
|
||||||
|
, m_iop_dma(*this, "iop_dma")
|
||||||
, m_screen(*this, "screen")
|
, m_screen(*this, "screen")
|
||||||
, m_iop_ram(*this, "iop_ram")
|
, m_iop_ram(*this, "iop_ram")
|
||||||
, m_sp_ram(*this, "sp_ram")
|
, m_sp_ram(*this, "sp_ram")
|
||||||
@ -210,25 +215,46 @@ protected:
|
|||||||
DECLARE_WRITE32_MEMBER(dmac_w);
|
DECLARE_WRITE32_MEMBER(dmac_w);
|
||||||
DECLARE_READ32_MEMBER(intc_r);
|
DECLARE_READ32_MEMBER(intc_r);
|
||||||
DECLARE_WRITE32_MEMBER(intc_w);
|
DECLARE_WRITE32_MEMBER(intc_w);
|
||||||
DECLARE_READ32_MEMBER(sif_smflg_r);
|
DECLARE_READ32_MEMBER(sif_r);
|
||||||
DECLARE_WRITE32_MEMBER(sif_smflg_w);
|
DECLARE_WRITE32_MEMBER(sif_w);
|
||||||
DECLARE_WRITE8_MEMBER(debug_w);
|
DECLARE_WRITE8_MEMBER(debug_w);
|
||||||
DECLARE_READ32_MEMBER(unk_f430_r);
|
DECLARE_READ32_MEMBER(unk_f430_r);
|
||||||
DECLARE_WRITE32_MEMBER(unk_f430_w);
|
DECLARE_WRITE32_MEMBER(unk_f430_w);
|
||||||
DECLARE_READ32_MEMBER(unk_f440_r);
|
DECLARE_READ32_MEMBER(unk_f440_r);
|
||||||
DECLARE_WRITE32_MEMBER(unk_f440_w);
|
DECLARE_WRITE32_MEMBER(unk_f440_w);
|
||||||
DECLARE_READ32_MEMBER(unk_f520_r);
|
DECLARE_READ32_MEMBER(unk_f520_r);
|
||||||
|
DECLARE_READ64_MEMBER(board_id_r);
|
||||||
|
|
||||||
|
DECLARE_WRITE64_MEMBER(ee_iop_ram_w);
|
||||||
|
DECLARE_READ64_MEMBER(ee_iop_ram_r);
|
||||||
|
DECLARE_READ32_MEMBER(iop_intc_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(iop_intc_w);
|
||||||
|
DECLARE_READ32_MEMBER(iop_sif_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(iop_sif_w);
|
||||||
|
DECLARE_READ32_MEMBER(iop_dma_ctrl0_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(iop_dma_ctrl0_w);
|
||||||
|
DECLARE_READ32_MEMBER(iop_dma_ctrl1_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(iop_dma_ctrl1_w);
|
||||||
|
DECLARE_WRITE32_MEMBER(iop_debug_w);
|
||||||
|
|
||||||
|
DECLARE_WRITE_LINE_MEMBER(iop_timer_irq);
|
||||||
|
|
||||||
void check_irq0();
|
void check_irq0();
|
||||||
void raise_interrupt(int line);
|
void raise_interrupt(int line);
|
||||||
|
|
||||||
|
void check_iop_irq();
|
||||||
|
void raise_iop_interrupt(int line);
|
||||||
|
|
||||||
void mem_map(address_map &map);
|
void mem_map(address_map &map);
|
||||||
void iop_map(address_map &map);
|
void iop_map(address_map &map);
|
||||||
|
|
||||||
required_device<cpu_device> m_maincpu;
|
required_device<cpu_device> m_maincpu;
|
||||||
|
required_device<iop_device> m_iop;
|
||||||
required_device_array<ps2_timer_device, 4> m_timer;
|
required_device_array<ps2_timer_device, 4> m_timer;
|
||||||
|
required_device<iop_timer_device> m_iop_timer;
|
||||||
|
required_device<iop_dma_device> m_iop_dma;
|
||||||
required_device<screen_device> m_screen;
|
required_device<screen_device> m_screen;
|
||||||
required_shared_ptr<uint64_t> m_iop_ram;
|
required_shared_ptr<uint32_t> m_iop_ram;
|
||||||
required_shared_ptr<uint64_t> m_sp_ram;
|
required_shared_ptr<uint64_t> m_sp_ram;
|
||||||
required_shared_ptr<uint64_t> m_vu0_imem;
|
required_shared_ptr<uint64_t> m_vu0_imem;
|
||||||
required_shared_ptr<uint64_t> m_vu0_dmem;
|
required_shared_ptr<uint64_t> m_vu0_dmem;
|
||||||
@ -252,6 +278,14 @@ protected:
|
|||||||
uint64_t m_ipu_out_fifo[0x1000];
|
uint64_t m_ipu_out_fifo[0x1000];
|
||||||
uint64_t m_ipu_out_fifo_index;
|
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;
|
||||||
|
|
||||||
|
uint32_t m_dmac_d5_chcr;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INT_GS = 0,
|
INT_GS = 0,
|
||||||
@ -274,6 +308,10 @@ protected:
|
|||||||
uint32_t m_istat;
|
uint32_t m_istat;
|
||||||
uint32_t m_imask;
|
uint32_t m_imask;
|
||||||
|
|
||||||
|
uint32_t m_iop_istat;
|
||||||
|
uint32_t m_iop_imask;
|
||||||
|
uint32_t m_iop_ienable;
|
||||||
|
|
||||||
emu_timer *m_vblank_timer;
|
emu_timer *m_vblank_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -428,6 +466,7 @@ READ32_MEMBER(ps2sony_state::dmac_channel_r)
|
|||||||
logerror("%s: dmac_channel_r: D4_TADR (%08x)\n", machine().describe_context(), ret);
|
logerror("%s: dmac_channel_r: D4_TADR (%08x)\n", machine().describe_context(), ret);
|
||||||
break;
|
break;
|
||||||
case 0xc000/8: /* D5_CHCR */
|
case 0xc000/8: /* D5_CHCR */
|
||||||
|
ret = m_dmac_d5_chcr;
|
||||||
logerror("%s: dmac_channel_r: D5_CHCR (%08x)\n", machine().describe_context(), ret);
|
logerror("%s: dmac_channel_r: D5_CHCR (%08x)\n", machine().describe_context(), ret);
|
||||||
break;
|
break;
|
||||||
case 0xc010/8: /* D5_MADR */
|
case 0xc010/8: /* D5_MADR */
|
||||||
@ -493,6 +532,8 @@ READ32_MEMBER(ps2sony_state::dmac_channel_r)
|
|||||||
|
|
||||||
WRITE32_MEMBER(ps2sony_state::dmac_channel_w)
|
WRITE32_MEMBER(ps2sony_state::dmac_channel_w)
|
||||||
{
|
{
|
||||||
|
static const char* mode_strings[4] = { "Normal", "Chain", "Interleave", "Undefined" };
|
||||||
|
|
||||||
switch (offset + 0x8000/8)
|
switch (offset + 0x8000/8)
|
||||||
{
|
{
|
||||||
case 0x8000/8: /* D0_CHCR */
|
case 0x8000/8: /* D0_CHCR */
|
||||||
@ -571,7 +612,9 @@ WRITE32_MEMBER(ps2sony_state::dmac_channel_w)
|
|||||||
logerror("%s: dmac_channel_w: D4_TADR = %08x\n", machine().describe_context(), data);
|
logerror("%s: dmac_channel_w: D4_TADR = %08x\n", machine().describe_context(), data);
|
||||||
break;
|
break;
|
||||||
case 0xc000/8: /* D5_CHCR */
|
case 0xc000/8: /* D5_CHCR */
|
||||||
logerror("%s: dmac_channel_w: D5_CHCR = %08x\n", machine().describe_context(), data);
|
logerror("%s: dmac_channel_w: D5_CHCR = %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 1) & 3], (data >> 3) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
|
||||||
|
logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
|
||||||
|
COMBINE_DATA(&m_dmac_d5_chcr);
|
||||||
break;
|
break;
|
||||||
case 0xc010/8: /* D5_MADR */
|
case 0xc010/8: /* D5_MADR */
|
||||||
logerror("%s: dmac_channel_w: D5_MADR = %08x\n", machine().describe_context(), data);
|
logerror("%s: dmac_channel_w: D5_MADR = %08x\n", machine().describe_context(), data);
|
||||||
@ -875,19 +918,95 @@ void ps2sony_state::check_irq0()
|
|||||||
m_maincpu->set_input_line(MIPS3_IRQ0, (m_istat & m_imask) ? ASSERT_LINE : CLEAR_LINE);
|
m_maincpu->set_input_line(MIPS3_IRQ0, (m_istat & m_imask) ? ASSERT_LINE : CLEAR_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ps2sony_state::check_iop_irq()
|
||||||
|
{
|
||||||
|
bool active = (m_iop_ienable && (m_iop_istat & m_iop_imask));
|
||||||
|
logerror("%s: check_iop_irq: %d\n", machine().describe_context(), active ? 1 : 0);
|
||||||
|
m_iop->set_input_line(R3000_IRQ0, active ? ASSERT_LINE : CLEAR_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
void ps2sony_state::raise_interrupt(int line)
|
void ps2sony_state::raise_interrupt(int line)
|
||||||
{
|
{
|
||||||
printf("raise_interrupt: %d\n", (1 << line));
|
|
||||||
m_istat |= (1 << line);
|
m_istat |= (1 << line);
|
||||||
check_irq0();
|
check_irq0();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ps2sony_state::raise_iop_interrupt(int line)
|
||||||
|
{
|
||||||
|
logerror("%s: raise_iop_interrupt: %d\n", machine().describe_context(), line);
|
||||||
|
m_iop_istat |= (1 << line);
|
||||||
|
check_iop_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_LINE_MEMBER(ps2sony_state::iop_timer_irq)
|
||||||
|
{
|
||||||
|
logerror("%s: iop_timer_irq: %d\n", machine().describe_context(), state);
|
||||||
|
if (state)
|
||||||
|
raise_iop_interrupt(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE32_MEMBER(ps2sony_state::iop_debug_w)
|
||||||
|
{
|
||||||
|
//printf("%08x ", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
READ32_MEMBER(ps2sony_state::iop_intc_r)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: // I_STAT
|
||||||
|
ret = m_iop_istat;
|
||||||
|
logerror("%s: iop_intc_r: I_STAT %08x\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 1: // I_MASK
|
||||||
|
ret = m_iop_imask;
|
||||||
|
logerror("%s: iop_intc_r: I_MASK %08x\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 2: // I_ENABLE
|
||||||
|
ret = m_iop_ienable;
|
||||||
|
m_iop_ienable = 0;
|
||||||
|
check_iop_irq();
|
||||||
|
logerror("%s: iop_intc_r: I_ENABLE %08x\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logerror("%s: iop_intc_r: Unknown offset %08x\n", machine().describe_context(), 0x1f801070 + (offset << 2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE32_MEMBER(ps2sony_state::iop_intc_w)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: // I_STAT
|
||||||
|
logerror("%s: iop_intc_w: I_STAT = %08x\n", machine().describe_context(), data);
|
||||||
|
m_iop_istat &= data;
|
||||||
|
check_iop_irq();
|
||||||
|
break;
|
||||||
|
case 1: // I_MASK
|
||||||
|
logerror("%s: iop_intc_w: I_MASK = %08x\n", machine().describe_context(), data);
|
||||||
|
m_iop_imask = data;
|
||||||
|
check_iop_irq();
|
||||||
|
break;
|
||||||
|
case 2: // I_ENABLE
|
||||||
|
logerror("%s: iop_intc_w: I_ENABLE = %08x\n", machine().describe_context(), data);
|
||||||
|
m_iop_ienable = BIT(data, 0);
|
||||||
|
check_iop_irq();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logerror("%s: iop_intc_w: Unknown offset %08x = %08x\n", machine().describe_context(), 0x1f801070 + (offset << 2), data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
READ32_MEMBER(ps2sony_state::intc_r)
|
READ32_MEMBER(ps2sony_state::intc_r)
|
||||||
{
|
{
|
||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
case 0: // I_STAT
|
case 0: // I_STAT
|
||||||
logerror("%s: intc_r: I_STAT %08x\n", machine().describe_context(), m_istat);
|
//logerror("%s: intc_r: I_STAT %08x\n", machine().describe_context(), m_istat);
|
||||||
return m_istat;
|
return m_istat;
|
||||||
case 2: // I_MASK
|
case 2: // I_MASK
|
||||||
logerror("%s: intc_r: I_MASK %08x\n", machine().describe_context(), m_imask);
|
logerror("%s: intc_r: I_MASK %08x\n", machine().describe_context(), m_imask);
|
||||||
@ -909,7 +1028,7 @@ WRITE32_MEMBER(ps2sony_state::intc_w)
|
|||||||
break;
|
break;
|
||||||
case 2: // I_MASK
|
case 2: // I_MASK
|
||||||
logerror("%s: intc_w: I_MASK = %08x\n", machine().describe_context(), data);
|
logerror("%s: intc_w: I_MASK = %08x\n", machine().describe_context(), data);
|
||||||
COMBINE_DATA(&m_imask);
|
m_imask ^= data & 0x7fff;
|
||||||
check_irq0();
|
check_irq0();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -918,26 +1037,162 @@ WRITE32_MEMBER(ps2sony_state::intc_w)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
READ32_MEMBER(ps2sony_state::sif_smflg_r)
|
READ32_MEMBER(ps2sony_state::iop_sif_r)
|
||||||
{
|
{
|
||||||
uint32_t ret = 0x00010000;
|
uint32_t ret = 0;
|
||||||
logerror("%s: sif_smflg_r (%08x)\n", machine().describe_context(), ret);
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ret = m_sif_ms_mailbox;
|
||||||
|
logerror("%s: iop_sif_r: SIF master->slave mailbox (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ret = m_sif_sm_mailbox;
|
||||||
|
logerror("%s: iop_sif_r: SIF slave->master mailbox (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ret = m_sif_ms_flag;
|
||||||
|
logerror("%s: iop_sif_r: SIF master->slave flag (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
ret = m_sif_sm_flag;
|
||||||
|
logerror("%s: iop_sif_r: SIF slave->master flag (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
ret = m_sif_ctrl | 0xf0000002;
|
||||||
|
logerror("%s: iop_sif_r: SIF control register (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logerror("%s: iop_sif_r: Unknown read (%08x)\n", machine().describe_context(), 0x1d000000 + (offset << 2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE32_MEMBER(ps2sony_state::sif_smflg_w)
|
WRITE32_MEMBER(ps2sony_state::iop_sif_w)
|
||||||
{
|
{
|
||||||
logerror("%s: sif_smflg_w = %08x\n", machine().describe_context(), data);
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
logerror("%s: iop_sif_w: SIF set slave->master mailbox (%08x)\n", machine().describe_context(), data);
|
||||||
|
m_sif_sm_mailbox = data;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
if (m_sif_sm_flag == 0 && data != 0)
|
||||||
|
{
|
||||||
|
//raise_interrupt(INT_SBUS);
|
||||||
|
}
|
||||||
|
logerror("%s: iop_sif_w: SIF set slave->master flag (%08x)\n", machine().describe_context(), data);
|
||||||
|
m_sif_sm_flag |= data;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logerror("%s: iop_sif_w: Unknown write %08x = %08x\n", machine().describe_context(), 0x1d000000 + (offset << 2), data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
READ32_MEMBER(ps2sony_state::sif_r)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ret = m_sif_ms_mailbox;
|
||||||
|
logerror("%s: sif_r: SIF master->slave mailbox (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ret = m_sif_sm_mailbox;
|
||||||
|
logerror("%s: sif_r: SIF slave->master mailbox (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ret = m_sif_ms_flag;
|
||||||
|
logerror("%s: sif_r: SIF master->slave flag (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
ret = m_sif_sm_flag;
|
||||||
|
logerror("%s: sif_r: SIF slave->master flag (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ret = m_sif_ctrl;
|
||||||
|
logerror("%s: sif_r: SIF control (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logerror("%s: sif_r: Unknown (%08x)\n", machine().describe_context(), 0x1000f200 + (offset << 3));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE32_MEMBER(ps2sony_state::sif_w)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
logerror("%s: sif_w: SIF set master->slave mailbox (%08x)\n", machine().describe_context(), data);
|
||||||
|
m_sif_ms_mailbox |= data;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
logerror("%s: sif_w: SIF set master->slave flag (%08x)\n", machine().describe_context(), data);
|
||||||
|
m_sif_ms_flag |= data;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
logerror("%s: sif_w: SIF clear slave->master flag (%08x)\n", machine().describe_context(), data);
|
||||||
|
m_sif_sm_flag &= ~data;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
logerror("%s: sif_w: SIF control = %08x\n", machine().describe_context(), data);
|
||||||
|
m_sif_ctrl = data; // ??
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logerror("%s: sif_w: Unknown %08x = %08x\n", machine().describe_context(), 0x1000f200 + (offset << 3), data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps2sony_state::machine_start()
|
void ps2sony_state::machine_start()
|
||||||
{
|
{
|
||||||
|
save_item(NAME(m_gs_base_regs));
|
||||||
|
save_item(NAME(m_gs_csr));
|
||||||
|
save_item(NAME(m_gs_imr));
|
||||||
|
save_item(NAME(m_gs_busdir));
|
||||||
|
save_item(NAME(m_gs_sig_label_id));
|
||||||
|
|
||||||
|
save_item(NAME(m_unk_f430_reg));
|
||||||
|
save_item(NAME(m_unk_f440_counter));
|
||||||
|
save_item(NAME(m_unk_f440_reg));
|
||||||
|
save_item(NAME(m_unk_f440_ret));
|
||||||
|
|
||||||
|
save_item(NAME(m_ipu_ctrl));
|
||||||
|
save_item(NAME(m_ipu_in_fifo));
|
||||||
|
save_item(NAME(m_ipu_in_fifo_index));
|
||||||
|
save_item(NAME(m_ipu_out_fifo));
|
||||||
|
save_item(NAME(m_ipu_out_fifo_index));
|
||||||
|
|
||||||
|
save_item(NAME(m_sif_ms_flag));
|
||||||
|
save_item(NAME(m_sif_sm_flag));
|
||||||
|
save_item(NAME(m_sif_ctrl));
|
||||||
|
|
||||||
|
save_item(NAME(m_dmac_d5_chcr));
|
||||||
|
|
||||||
|
save_item(NAME(m_istat));
|
||||||
|
save_item(NAME(m_imask));
|
||||||
|
|
||||||
|
save_item(NAME(m_iop_istat));
|
||||||
|
save_item(NAME(m_iop_imask));
|
||||||
|
save_item(NAME(m_iop_ienable));
|
||||||
|
|
||||||
if (!m_vblank_timer)
|
if (!m_vblank_timer)
|
||||||
m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ps2sony_state::vblank), this));
|
m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ps2sony_state::vblank), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps2sony_state::machine_reset()
|
void ps2sony_state::machine_reset()
|
||||||
{
|
{
|
||||||
|
m_istat = 0;
|
||||||
|
m_imask = 0;
|
||||||
|
|
||||||
|
m_iop_istat = 0;
|
||||||
|
m_iop_imask = 0;
|
||||||
|
|
||||||
m_unk_f430_reg = 0;
|
m_unk_f430_reg = 0;
|
||||||
m_unk_f440_reg = 0;
|
m_unk_f440_reg = 0;
|
||||||
m_unk_f440_ret = 0;
|
m_unk_f440_ret = 0;
|
||||||
@ -956,6 +1211,14 @@ void ps2sony_state::machine_reset()
|
|||||||
m_gs_sig_label_id = 0ULL;
|
m_gs_sig_label_id = 0ULL;
|
||||||
|
|
||||||
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
|
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;
|
||||||
|
|
||||||
|
m_dmac_d5_chcr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
|
TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
|
||||||
@ -963,15 +1226,15 @@ TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
|
|||||||
if (param)
|
if (param)
|
||||||
{
|
{
|
||||||
// VBlank enter
|
// VBlank enter
|
||||||
printf("1 ");
|
|
||||||
raise_interrupt(INT_VB_ON);
|
raise_interrupt(INT_VB_ON);
|
||||||
|
raise_iop_interrupt(0);
|
||||||
m_vblank_timer->adjust(m_screen->time_until_pos(0), 0);
|
m_vblank_timer->adjust(m_screen->time_until_pos(0), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("0 ");
|
|
||||||
// VBlank exit
|
// VBlank exit
|
||||||
raise_interrupt(INT_VB_OFF);
|
raise_interrupt(INT_VB_OFF);
|
||||||
|
raise_iop_interrupt(11);
|
||||||
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
|
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -981,6 +1244,28 @@ WRITE8_MEMBER(ps2sony_state::debug_w)
|
|||||||
printf("%c", (char)data);
|
printf("%c", (char)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WRITE64_MEMBER(ps2sony_state::ee_iop_ram_w)
|
||||||
|
{
|
||||||
|
const uint32_t offset_hi = (offset << 1);
|
||||||
|
const uint32_t offset_lo = (offset << 1) + 1;
|
||||||
|
const uint32_t mask_hi = (uint32_t)(mem_mask >> 32);
|
||||||
|
const uint32_t mask_lo = (uint32_t)mem_mask;
|
||||||
|
m_iop_ram[offset_hi] &= ~mask_hi;
|
||||||
|
m_iop_ram[offset_hi] |= (uint32_t)(data >> 32) & mask_hi;
|
||||||
|
m_iop_ram[offset_lo] &= ~mask_lo;
|
||||||
|
m_iop_ram[offset_lo] |= (uint32_t)data & mask_lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
READ64_MEMBER(ps2sony_state::ee_iop_ram_r)
|
||||||
|
{
|
||||||
|
return ((uint64_t)m_iop_ram[offset << 1] << 32) | m_iop_ram[(offset << 1) + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
READ64_MEMBER(ps2sony_state::board_id_r)
|
||||||
|
{
|
||||||
|
return 0x1234;
|
||||||
|
}
|
||||||
|
|
||||||
READ32_MEMBER(ps2sony_state::unk_f520_r)
|
READ32_MEMBER(ps2sony_state::unk_f520_r)
|
||||||
{
|
{
|
||||||
// Unknown purpose - BIOS seems to expect this value initially
|
// Unknown purpose - BIOS seems to expect this value initially
|
||||||
@ -1182,7 +1467,7 @@ void ps2sony_state::mem_map(address_map &map)
|
|||||||
map(0x1000f000, 0x1000f017).rw(FUNC(ps2sony_state::intc_r), FUNC(ps2sony_state::intc_w)).umask64(0x00000000ffffffff);
|
map(0x1000f000, 0x1000f017).rw(FUNC(ps2sony_state::intc_r), FUNC(ps2sony_state::intc_w)).umask64(0x00000000ffffffff);
|
||||||
map(0x1000f130, 0x1000f137).nopr();
|
map(0x1000f130, 0x1000f137).nopr();
|
||||||
map(0x1000f180, 0x1000f187).w(FUNC(ps2sony_state::debug_w)).umask64(0x00000000000000ff);
|
map(0x1000f180, 0x1000f187).w(FUNC(ps2sony_state::debug_w)).umask64(0x00000000000000ff);
|
||||||
map(0x1000f230, 0x1000f237).rw(FUNC(ps2sony_state::sif_smflg_r), FUNC(ps2sony_state::sif_smflg_w)).umask64(0x00000000ffffffff);
|
map(0x1000f200, 0x1000f24f).rw(FUNC(ps2sony_state::sif_r), FUNC(ps2sony_state::sif_w)).umask64(0x00000000ffffffff);
|
||||||
map(0x1000f430, 0x1000f437).rw(FUNC(ps2sony_state::unk_f430_r), FUNC(ps2sony_state::unk_f430_w)).umask64(0x00000000ffffffff); // Unknown
|
map(0x1000f430, 0x1000f437).rw(FUNC(ps2sony_state::unk_f430_r), FUNC(ps2sony_state::unk_f430_w)).umask64(0x00000000ffffffff); // Unknown
|
||||||
map(0x1000f440, 0x1000f447).rw(FUNC(ps2sony_state::unk_f440_r), FUNC(ps2sony_state::unk_f440_w)).umask64(0x00000000ffffffff); // Unknown
|
map(0x1000f440, 0x1000f447).rw(FUNC(ps2sony_state::unk_f440_r), FUNC(ps2sony_state::unk_f440_w)).umask64(0x00000000ffffffff); // Unknown
|
||||||
map(0x1000f520, 0x1000f527).r(FUNC(ps2sony_state::unk_f520_r)).umask64(0x00000000ffffffff); // Unknown
|
map(0x1000f520, 0x1000f527).r(FUNC(ps2sony_state::unk_f520_r)).umask64(0x00000000ffffffff); // Unknown
|
||||||
@ -1192,7 +1477,8 @@ void ps2sony_state::mem_map(address_map &map)
|
|||||||
map(0x1100c000, 0x1100ffff).ram().share(m_vu1_dmem);
|
map(0x1100c000, 0x1100ffff).ram().share(m_vu1_dmem);
|
||||||
map(0x12000000, 0x120003ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs0_r), FUNC(ps2sony_state::gs_regs0_w));
|
map(0x12000000, 0x120003ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs0_r), FUNC(ps2sony_state::gs_regs0_w));
|
||||||
map(0x12001000, 0x120013ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs1_r), FUNC(ps2sony_state::gs_regs1_w));
|
map(0x12001000, 0x120013ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs1_r), FUNC(ps2sony_state::gs_regs1_w));
|
||||||
map(0x1c000000, 0x1c1fffff).ram().share(m_iop_ram); // IOP has 2MB EDO RAM per Wikipedia, and writes go up to this point
|
map(0x1c000000, 0x1c1fffff).rw(FUNC(ps2sony_state::ee_iop_ram_r), FUNC(ps2sony_state::ee_iop_ram_w)); // IOP has 2MB EDO RAM per Wikipedia, and writes go up to this point
|
||||||
|
map(0x1f803800, 0x1f803807).r(FUNC(ps2sony_state::board_id_r));
|
||||||
map(0x1fc00000, 0x1fffffff).rom().region("bios", 0);
|
map(0x1fc00000, 0x1fffffff).rom().region("bios", 0);
|
||||||
|
|
||||||
map(0x70000000, 0x70003fff).ram().share(m_sp_ram); // 16KB Scratchpad RAM
|
map(0x70000000, 0x70003fff).ram().share(m_sp_ram); // 16KB Scratchpad RAM
|
||||||
@ -1201,30 +1487,45 @@ void ps2sony_state::mem_map(address_map &map)
|
|||||||
void ps2sony_state::iop_map(address_map &map)
|
void ps2sony_state::iop_map(address_map &map)
|
||||||
{
|
{
|
||||||
map(0x00000000, 0x001fffff).ram().share(m_iop_ram);
|
map(0x00000000, 0x001fffff).ram().share(m_iop_ram);
|
||||||
map(0x1f802070, 0x1f802073).noprw();
|
map(0x1d000000, 0x1d00004f).rw(FUNC(ps2sony_state::iop_sif_r), FUNC(ps2sony_state::iop_sif_w));
|
||||||
map(0x1fc00000, 0x1fdfffff).rom().region("bios", 0);
|
map(0x1f402004, 0x1f402007).nopr();
|
||||||
|
map(0x1f801070, 0x1f80107b).rw(FUNC(ps2sony_state::iop_intc_r), FUNC(ps2sony_state::iop_intc_w));
|
||||||
|
map(0x1f8010f0, 0x1f8010f7).rw(m_iop_dma, FUNC(iop_dma_device::ctrl0_r), FUNC(iop_dma_device::ctrl0_w));
|
||||||
|
map(0x1f801450, 0x1f801453).noprw();
|
||||||
|
map(0x1f8014a0, 0x1f8014af).rw(m_iop_timer, FUNC(iop_timer_device::read), FUNC(iop_timer_device::write));
|
||||||
|
map(0x1f801570, 0x1f801577).rw(m_iop_dma, FUNC(iop_dma_device::ctrl1_r), FUNC(iop_dma_device::ctrl1_w));
|
||||||
|
map(0x1f801578, 0x1f80157b).noprw();
|
||||||
|
map(0x1f802070, 0x1f802073).w(FUNC(ps2sony_state::iop_debug_w)).nopr();
|
||||||
|
map(0x1fc00000, 0x1fffffff).rom().region("bios", 0);
|
||||||
|
map(0x1ffe0130, 0x1ffe0133).nopw();
|
||||||
}
|
}
|
||||||
|
|
||||||
static INPUT_PORTS_START( ps2sony )
|
static INPUT_PORTS_START( ps2sony )
|
||||||
INPUT_PORTS_END
|
INPUT_PORTS_END
|
||||||
|
|
||||||
MACHINE_CONFIG_START(ps2sony_state::ps2sony)
|
MACHINE_CONFIG_START(ps2sony_state::ps2sony)
|
||||||
MCFG_DEVICE_ADD("maincpu", R5900LE, 294'912'000)
|
MCFG_DEVICE_ADD(m_maincpu, R5900LE, 294'912'000)
|
||||||
MCFG_CPU_FORCE_NO_DRC()
|
MCFG_CPU_FORCE_NO_DRC()
|
||||||
MCFG_MIPS3_ICACHE_SIZE(16384)
|
MCFG_MIPS3_ICACHE_SIZE(16384)
|
||||||
MCFG_MIPS3_DCACHE_SIZE(16384)
|
MCFG_MIPS3_DCACHE_SIZE(16384)
|
||||||
MCFG_DEVICE_PROGRAM_MAP(mem_map)
|
MCFG_DEVICE_PROGRAM_MAP(mem_map)
|
||||||
|
|
||||||
MCFG_DEVICE_ADD("iop", SONYPS2_IOP, XTAL(67'737'600)/2)
|
MCFG_DEVICE_ADD(m_iop, SONYPS2_IOP, XTAL(67'737'600)/2)
|
||||||
MCFG_DEVICE_PROGRAM_MAP(iop_map)
|
MCFG_DEVICE_PROGRAM_MAP(iop_map)
|
||||||
|
|
||||||
MCFG_QUANTUM_TIME(attotime::from_hz(1000000))
|
MCFG_QUANTUM_PERFECT_CPU("maincpu")
|
||||||
|
MCFG_QUANTUM_PERFECT_CPU("iop")
|
||||||
|
|
||||||
MCFG_DEVICE_ADD(m_timer[0], SONYPS2_TIMER, 294912000/2, true)
|
MCFG_DEVICE_ADD(m_timer[0], SONYPS2_TIMER, 294912000/2, true)
|
||||||
MCFG_DEVICE_ADD(m_timer[1], SONYPS2_TIMER, 294912000/2, true)
|
MCFG_DEVICE_ADD(m_timer[1], SONYPS2_TIMER, 294912000/2, true)
|
||||||
MCFG_DEVICE_ADD(m_timer[2], SONYPS2_TIMER, 294912000/2, false)
|
MCFG_DEVICE_ADD(m_timer[2], SONYPS2_TIMER, 294912000/2, false)
|
||||||
MCFG_DEVICE_ADD(m_timer[3], SONYPS2_TIMER, 294912000/2, false)
|
MCFG_DEVICE_ADD(m_timer[3], SONYPS2_TIMER, 294912000/2, false)
|
||||||
|
|
||||||
|
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_dma, SONYIOP_DMA, XTAL(67'737'600)/2)
|
||||||
|
|
||||||
/* video hardware */
|
/* video hardware */
|
||||||
MCFG_SCREEN_ADD("screen", RASTER)
|
MCFG_SCREEN_ADD("screen", RASTER)
|
||||||
MCFG_SCREEN_REFRESH_RATE(60)
|
MCFG_SCREEN_REFRESH_RATE(60)
|
||||||
|
138
src/mame/machine/iopdma.cpp
Normal file
138
src/mame/machine/iopdma.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Ryan Holtz
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Sony Playstation 2 IOP DMA device skeleton
|
||||||
|
*
|
||||||
|
* To Do:
|
||||||
|
* Everything
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "iopdma.h"
|
||||||
|
|
||||||
|
DEFINE_DEVICE_TYPE(SONYIOP_DMA, iop_dma_device, "iopdma", "Sony IOP DMA")
|
||||||
|
|
||||||
|
iop_dma_device::iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
|
: device_t(mconfig, SONYIOP_DMA, tag, owner, clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_dma_device::device_start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_dma_device::device_reset()
|
||||||
|
{
|
||||||
|
m_dpcr[0] = 0;
|
||||||
|
m_dpcr[1] = 0;
|
||||||
|
m_dicr[0] = 0;
|
||||||
|
m_dicr[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
READ32_MEMBER(iop_dma_device::ctrl0_r)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: // 0x1f8010f0, DPCR
|
||||||
|
ret = m_dpcr[0];
|
||||||
|
logerror("%s: ctrl0_r: DPCR (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 1: // 0x1f8010f4, DICR
|
||||||
|
ret = m_dicr[0];
|
||||||
|
logerror("%s: ctrl0_r: DICR (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Can't happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE32_MEMBER(iop_dma_device::ctrl0_w)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: // 0x1f8010f0, DPCR
|
||||||
|
logerror("%s: ctrl0_w: DPCR = %08x\n", machine().describe_context(), data);
|
||||||
|
set_dpcr(data, 0);
|
||||||
|
break;
|
||||||
|
case 1: // 0x1f8010f4, DICR
|
||||||
|
logerror("%s: ctrl0_w: DICR = %08x\n", machine().describe_context(), data);
|
||||||
|
set_dicr(data, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Can't happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
READ32_MEMBER(iop_dma_device::ctrl1_r)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: // 0x1f801570, DPCR2
|
||||||
|
ret = m_dpcr[1];
|
||||||
|
logerror("%s: ctrl1_r: DPCR2 (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
case 1: // 0x1f801574, DICR2
|
||||||
|
ret = m_dicr[1];
|
||||||
|
logerror("%s: ctrl1_r: DICR2 (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Can't happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE32_MEMBER(iop_dma_device::ctrl1_w)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: // 0x1f8010f0, DPCR
|
||||||
|
logerror("%s: ctrl1_w: DPCR2 = %08x\n", machine().describe_context(), data);
|
||||||
|
set_dpcr(data, 1);
|
||||||
|
break;
|
||||||
|
case 1: // 0x1f8010f4, DICR
|
||||||
|
logerror("%s: ctrl1_w: DICR2 = %08x\n", machine().describe_context(), data);
|
||||||
|
set_dicr(data, 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Can't happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_dma_device::update_interrupts()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_dma_device::set_dpcr(uint32_t data, uint32_t index)
|
||||||
|
{
|
||||||
|
m_dpcr[index] = data;
|
||||||
|
for (uint32_t channel = index*8, bit = 0; channel < index*8 + 8; channel++, bit += 4)
|
||||||
|
{
|
||||||
|
const uint8_t field = (data >> bit) & 0xf;
|
||||||
|
const bool was_enabled = m_channels[channel].m_enabled;
|
||||||
|
const bool is_enabled = BIT(field, 3);
|
||||||
|
m_channels[channel].m_enabled = is_enabled;
|
||||||
|
m_channels[channel].m_priority = field & 7;
|
||||||
|
if (!was_enabled && is_enabled)
|
||||||
|
{
|
||||||
|
// Check for running status?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_dma_device::set_dicr(uint32_t data, uint32_t index)
|
||||||
|
{
|
||||||
|
m_dicr[index] = data;
|
||||||
|
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);
|
||||||
|
update_interrupts();
|
||||||
|
}
|
58
src/mame/machine/iopdma.h
Normal file
58
src/mame/machine/iopdma.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Ryan Holtz
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Sony Playstation 2 IOP DMA device skeleton
|
||||||
|
*
|
||||||
|
* To Do:
|
||||||
|
* Everything
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAME_MACHINE_IOPDMA_H
|
||||||
|
#define MAME_MACHINE_IOPDMA_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
|
||||||
|
class iop_dma_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
|
DECLARE_READ32_MEMBER(ctrl0_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(ctrl0_w);
|
||||||
|
DECLARE_READ32_MEMBER(ctrl1_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(ctrl1_w);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct intctrl_t
|
||||||
|
{
|
||||||
|
uint8_t m_mask;
|
||||||
|
uint8_t m_status;
|
||||||
|
bool m_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct channel_t
|
||||||
|
{
|
||||||
|
uint8_t m_priority;
|
||||||
|
bool m_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
|
||||||
|
void set_dpcr(uint32_t data, uint32_t index);
|
||||||
|
void set_dicr(uint32_t data, uint32_t index);
|
||||||
|
void update_interrupts();
|
||||||
|
|
||||||
|
uint32_t m_dpcr[2];
|
||||||
|
uint32_t m_dicr[2];
|
||||||
|
channel_t m_channels[16];
|
||||||
|
intctrl_t m_int_ctrl[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(SONYIOP_DMA, iop_dma_device)
|
||||||
|
|
||||||
|
#endif // MAME_MACHINE_IOPDMA_H
|
262
src/mame/machine/ioptimer.cpp
Normal file
262
src/mame/machine/ioptimer.cpp
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Ryan Holtz
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Sony Playstation 2 IOP Timer device skeleton
|
||||||
|
*
|
||||||
|
* To Do:
|
||||||
|
* Everything
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ioptimer.h"
|
||||||
|
|
||||||
|
DEFINE_DEVICE_TYPE(SONYIOP_TIMER, iop_timer_device, "ioptimer", "Sony IOP Timer")
|
||||||
|
|
||||||
|
iop_timer_device::iop_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
|
: device_t(mconfig, SONYIOP_TIMER, tag, owner, clock)
|
||||||
|
, m_compare_timer(nullptr)
|
||||||
|
, m_overflow_timer(nullptr)
|
||||||
|
, m_last_update_time(attotime::zero)
|
||||||
|
, m_elapsed_time(attotime::zero)
|
||||||
|
, m_zero_return(false)
|
||||||
|
, m_count(0)
|
||||||
|
, m_compare(0)
|
||||||
|
, m_gate_enable(false)
|
||||||
|
, m_gate_mode(GATM_LOW)
|
||||||
|
, m_cmp_int_enabled(false)
|
||||||
|
, m_cmp_int(false)
|
||||||
|
, m_ovf_int_enabled(false)
|
||||||
|
, m_ovf_int(false)
|
||||||
|
, m_ienable(false)
|
||||||
|
, m_int_cb(*this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::device_start()
|
||||||
|
{
|
||||||
|
m_int_cb.resolve_safe();
|
||||||
|
|
||||||
|
if (!m_compare_timer)
|
||||||
|
m_compare_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(iop_timer_device::compare), this));
|
||||||
|
|
||||||
|
if (!m_overflow_timer)
|
||||||
|
m_overflow_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(iop_timer_device::overflow), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::device_reset()
|
||||||
|
{
|
||||||
|
m_ctrl = 0;
|
||||||
|
|
||||||
|
m_last_update_time = attotime::zero;
|
||||||
|
m_elapsed_time = attotime::zero;
|
||||||
|
|
||||||
|
m_zero_return = false;
|
||||||
|
|
||||||
|
m_count = 0;
|
||||||
|
m_compare = 0;
|
||||||
|
|
||||||
|
m_gate_enable = false;
|
||||||
|
m_gate_mode = GATM_LOW;
|
||||||
|
|
||||||
|
m_cmp_int_enabled = false;
|
||||||
|
m_cmp_int = false;
|
||||||
|
|
||||||
|
m_ovf_int_enabled = false;
|
||||||
|
m_ovf_int = false;
|
||||||
|
|
||||||
|
m_ienable = false;
|
||||||
|
|
||||||
|
m_compare_timer->adjust(attotime::never);
|
||||||
|
m_overflow_timer->adjust(attotime::never);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::update_gate()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::update_interrupts()
|
||||||
|
{
|
||||||
|
if (!m_int_cb.isnull())
|
||||||
|
{
|
||||||
|
bool interrupt = m_ienable && ((m_ovf_int && m_ovf_int_enabled) || (m_cmp_int && m_cmp_int_enabled));
|
||||||
|
m_int_cb(interrupt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::update_compare_timer()
|
||||||
|
{
|
||||||
|
// TODO: Compare timer functionality is a total guess
|
||||||
|
if (!m_ienable || !m_cmp_int_enabled)
|
||||||
|
m_compare_timer->adjust(attotime::never);
|
||||||
|
m_compare_timer->adjust(attotime::from_ticks(m_compare - m_count, clock()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::update_overflow_timer()
|
||||||
|
{
|
||||||
|
// TODO: Overflow timer functionality is not used yet, total guess
|
||||||
|
/*
|
||||||
|
uint32_t ticks = 0;
|
||||||
|
if (m_zero_return)
|
||||||
|
{
|
||||||
|
if (m_compare > m_count)
|
||||||
|
ticks = m_compare - m_count;
|
||||||
|
else
|
||||||
|
ticks = (uint32_t)(0x100000000ULL - (m_count - m_compare));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ticks = (uint32_t)(0x100000000ULL - m_count);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
m_overflow_timer->adjust(attotime::never);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::update_count()
|
||||||
|
{
|
||||||
|
attotime curr_time = machine().scheduler().time();
|
||||||
|
attotime time_delta = curr_time - m_last_update_time;
|
||||||
|
m_last_update_time = curr_time;
|
||||||
|
m_elapsed_time += time_delta;
|
||||||
|
uint32_t ticks = (uint32_t)m_elapsed_time.as_ticks(clock());
|
||||||
|
if (ticks > 0)
|
||||||
|
{
|
||||||
|
m_elapsed_time -= attotime::from_ticks(ticks, clock());
|
||||||
|
m_count += ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iop_timer_device::set_ctrl(uint32_t data)
|
||||||
|
{
|
||||||
|
static const char *gatm_names[4] = { "low?", "reset+rising?", "reset+falling?", "reset+both?" };
|
||||||
|
logerror("%s: set_ctrl: GATE=%d, GATM=%s, ZRET=%d\n", machine().describe_context(), data & CTRL_GATE, gatm_names[(data & CTRL_GATM) >> 1], (data & CTRL_ZRET) >> 3);
|
||||||
|
logerror("%s: CMPE=%d, OVFE=%d, REP_INT=%d, TOG_INT=%d\n", machine().describe_context(), (data & CTRL_CMPE) >> 4, (data & CTRL_OVFE) >> 5, (data & CTRL_REPI) >> 6, (data & CTRL_TOGI) >> 7);
|
||||||
|
|
||||||
|
const uint32_t old = m_ctrl;
|
||||||
|
m_ctrl = data | CTRL_INTE;
|
||||||
|
const uint32_t changed = old ^ data;
|
||||||
|
|
||||||
|
if (!changed) return;
|
||||||
|
|
||||||
|
m_gate_enable = data & CTRL_GATE;
|
||||||
|
m_gate_mode = (timer_gate_mode)((data & CTRL_GATM) >> 1);
|
||||||
|
m_zero_return = (data & CTRL_ZRET) >> 3;
|
||||||
|
m_cmp_int_enabled = (data & CTRL_CMPE) >> 4;
|
||||||
|
m_ovf_int_enabled = (data & CTRL_OVFE) >> 5;
|
||||||
|
m_repeat_int = (data & CTRL_REPI) >> 6;
|
||||||
|
m_toggle_int = (data & CTRL_TOGI) >> 7;
|
||||||
|
m_ienable = 1;
|
||||||
|
|
||||||
|
m_count = 0;
|
||||||
|
if (changed & CTRL_CMPE)
|
||||||
|
{
|
||||||
|
if (data & CTRL_CMPE)
|
||||||
|
update_compare_timer();
|
||||||
|
else
|
||||||
|
m_compare_timer->adjust(attotime::never);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed & CTRL_OVFE)
|
||||||
|
{
|
||||||
|
if (data & CTRL_OVFE)
|
||||||
|
update_overflow_timer();
|
||||||
|
else
|
||||||
|
m_overflow_timer->adjust(attotime::never);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed & CTRL_INTE)
|
||||||
|
{
|
||||||
|
update_interrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMER_CALLBACK_MEMBER(iop_timer_device::compare)
|
||||||
|
{
|
||||||
|
if (m_zero_return)
|
||||||
|
{
|
||||||
|
m_count = 0; // Guess
|
||||||
|
update_compare_timer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_compare_timer->adjust(attotime::never);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_cmp_int_enabled)
|
||||||
|
m_cmp_int = 1;
|
||||||
|
|
||||||
|
update_interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMER_CALLBACK_MEMBER(iop_timer_device::overflow)
|
||||||
|
{
|
||||||
|
if (m_ovf_int_enabled)
|
||||||
|
m_ovf_int = 1;
|
||||||
|
|
||||||
|
update_interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
READ32_MEMBER(iop_timer_device::read)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
{
|
||||||
|
const uint32_t old = m_count;
|
||||||
|
update_count();
|
||||||
|
ret = m_count;
|
||||||
|
if (old != m_count)
|
||||||
|
logerror("%s: IOP timer read: COUNT (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01:
|
||||||
|
ret = m_ctrl | (m_ovf_int ? CTRL_OVFF : 0) | (m_cmp_int ? CTRL_CMPF : 0);
|
||||||
|
logerror("%s: IOP timer read: MODE (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02:
|
||||||
|
ret = m_compare;
|
||||||
|
logerror("%s: IOP timer read: COMPARE (%08x)\n", machine().describe_context(), ret);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE32_MEMBER(iop_timer_device::write)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
m_count = data;
|
||||||
|
logerror("%s: IOP timer write: COUNT = %08x\n", machine().describe_context(), data);
|
||||||
|
update_compare_timer();
|
||||||
|
update_overflow_timer();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x01:
|
||||||
|
set_ctrl(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02:
|
||||||
|
{
|
||||||
|
logerror("%s: IOP timer write: COMPARE = %08x\n", machine().describe_context(), data);
|
||||||
|
if (m_compare == data)
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_compare = data;
|
||||||
|
if (!m_toggle_int)
|
||||||
|
m_ienable = true;
|
||||||
|
update_compare_timer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
100
src/mame/machine/ioptimer.h
Normal file
100
src/mame/machine/ioptimer.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Ryan Holtz
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Sony Playstation 2 IOP Timer device skeleton
|
||||||
|
*
|
||||||
|
* To Do:
|
||||||
|
* Everything
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAME_MACHINE_IOPTIMER_H
|
||||||
|
#define MAME_MACHINE_IOPTIMER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
|
||||||
|
#define MCFG_IOP_TIMER_IRQ_CALLBACK(_write) \
|
||||||
|
devcb = &downcast<iop_timer_device &>(*device).set_int_cb(DEVCB_##_write);
|
||||||
|
|
||||||
|
class iop_timer_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
iop_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
|
template <class Object> devcb_base &set_int_cb(Object &&cb) { return m_int_cb.set_callback(std::forward<Object>(cb)); }
|
||||||
|
|
||||||
|
DECLARE_READ32_MEMBER(read);
|
||||||
|
DECLARE_WRITE32_MEMBER(write);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum timer_ctrl_mask : uint32_t
|
||||||
|
{
|
||||||
|
CTRL_GATE = (1 << 0),
|
||||||
|
CTRL_GATM = (3 << 1),
|
||||||
|
CTRL_ZRET = (1 << 3),
|
||||||
|
CTRL_CMPE = (1 << 4),
|
||||||
|
CTRL_OVFE = (1 << 5),
|
||||||
|
CTRL_REPI = (1 << 6),
|
||||||
|
CTRL_TOGI = (1 << 7),
|
||||||
|
CTRL_INTE = (1 << 10),
|
||||||
|
CTRL_CMPF = (1 << 11),
|
||||||
|
CTRL_OVFF = (1 << 12),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum timer_gate_mode : uint32_t
|
||||||
|
{
|
||||||
|
GATM_LOW = 0,
|
||||||
|
GATM_RISING,
|
||||||
|
GATM_FALLING,
|
||||||
|
GATM_BOTH
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
|
||||||
|
TIMER_CALLBACK_MEMBER(compare);
|
||||||
|
TIMER_CALLBACK_MEMBER(overflow);
|
||||||
|
|
||||||
|
void set_ctrl(uint32_t data);
|
||||||
|
|
||||||
|
void update_gate();
|
||||||
|
void update_interrupts();
|
||||||
|
|
||||||
|
void update_compare_timer();
|
||||||
|
void update_overflow_timer();
|
||||||
|
|
||||||
|
void update_count();
|
||||||
|
|
||||||
|
emu_timer *m_compare_timer;
|
||||||
|
emu_timer *m_overflow_timer;
|
||||||
|
|
||||||
|
uint32_t m_ctrl;
|
||||||
|
|
||||||
|
attotime m_last_update_time;
|
||||||
|
attotime m_elapsed_time;
|
||||||
|
bool m_zero_return;
|
||||||
|
uint32_t m_count;
|
||||||
|
uint32_t m_compare;
|
||||||
|
|
||||||
|
bool m_gate_enable;
|
||||||
|
timer_gate_mode m_gate_mode;
|
||||||
|
|
||||||
|
bool m_cmp_int_enabled;
|
||||||
|
bool m_cmp_int;
|
||||||
|
|
||||||
|
bool m_ovf_int_enabled;
|
||||||
|
bool m_ovf_int;
|
||||||
|
|
||||||
|
bool m_repeat_int;
|
||||||
|
bool m_toggle_int;
|
||||||
|
|
||||||
|
bool m_ienable;
|
||||||
|
devcb_write_line m_int_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(SONYIOP_TIMER, iop_timer_device)
|
||||||
|
|
||||||
|
#endif // MAME_MACHINE_IOPTIMER_H
|
@ -130,6 +130,7 @@ void ps2_timer_device::update_count()
|
|||||||
{
|
{
|
||||||
m_elapsed_time -= attotime::from_ticks(ticks, frequency);
|
m_elapsed_time -= attotime::from_ticks(ticks, frequency);
|
||||||
m_count += ticks;
|
m_count += ticks;
|
||||||
|
m_count &= 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user