ps2sony: Checkpoint. Adds a bunch of vector and parallel ops to the EE core, and skeleton GIF VIF1, and GS devices.

This commit is contained in:
mooglyguy 2018-07-14 04:00:12 +02:00
parent 1d987e9f2a
commit cf34ccd3b4
22 changed files with 3714 additions and 381 deletions

View File

@ -3060,14 +3060,22 @@ files {
MAME_DIR .. "src/mame/drivers/pve500.cpp",
MAME_DIR .. "src/mame/drivers/smc777.cpp",
MAME_DIR .. "src/mame/drivers/ps2sony.cpp",
MAME_DIR .. "src/mame/machine/ps2timer.cpp",
MAME_DIR .. "src/mame/machine/ps2timer.h",
MAME_DIR .. "src/mame/machine/ps2dma.cpp",
MAME_DIR .. "src/mame/machine/ps2dma.h",
MAME_DIR .. "src/mame/machine/ps2gif.cpp",
MAME_DIR .. "src/mame/machine/ps2gif.h",
MAME_DIR .. "src/mame/machine/ps2intc.cpp",
MAME_DIR .. "src/mame/machine/ps2intc.h",
MAME_DIR .. "src/mame/machine/ps2mc.cpp",
MAME_DIR .. "src/mame/machine/ps2mc.h",
MAME_DIR .. "src/mame/machine/ps2pad.cpp",
MAME_DIR .. "src/mame/machine/ps2pad.h",
MAME_DIR .. "src/mame/machine/ps2sif.cpp",
MAME_DIR .. "src/mame/machine/ps2sif.h",
MAME_DIR .. "src/mame/machine/ps2timer.cpp",
MAME_DIR .. "src/mame/machine/ps2timer.h",
MAME_DIR .. "src/mame/machine/ps2vif1.cpp",
MAME_DIR .. "src/mame/machine/ps2vif1.h",
MAME_DIR .. "src/mame/machine/iopcdvd.cpp",
MAME_DIR .. "src/mame/machine/iopcdvd.h",
MAME_DIR .. "src/mame/machine/iopdma.cpp",
@ -3080,6 +3088,8 @@ files {
MAME_DIR .. "src/mame/machine/ioptimer.h",
MAME_DIR .. "src/mame/audio/iopspu.cpp",
MAME_DIR .. "src/mame/audio/iopspu.h",
MAME_DIR .. "src/mame/video/ps2gs.cpp",
MAME_DIR .. "src/mame/video/ps2gs.h",
}
createMESSProjects(_target, _subtarget, "sord")

View File

@ -283,7 +283,8 @@ void mips3_device::generate_exception(int exception, int backup)
/* most exceptions go to offset 0x180, except for TLB stuff */
if (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE)
{
osd_printf_debug("TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]);
//printf("TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]);
//machine().debug_break();
}
else
{
@ -313,7 +314,7 @@ void mips3_device::generate_tlb_exception(int exception, offs_t address)
void mips3_device::invalid_instruction(uint32_t op)
{
printf("Invalid instruction! %08x\n", op);
fatalerror("Invalid instruction! %08x\n", op);
generate_exception(EXCEPTION_INVALIDOP, 1);
}
@ -345,9 +346,6 @@ void mips3_device::device_start()
/* initialize based on the config */
memset(m_core, 0, sizeof(internal_mips3_state));
m_core->vfr[0][3] = 1.0f;
m_core->vfmem = &m_core->vumem[0];
m_core->vimem = reinterpret_cast<uint32_t*>(m_core->vfmem);
m_cpu_clock = clock();
m_program = &space(AS_PROGRAM);
@ -1072,6 +1070,13 @@ void mips3_device::device_reset()
m_core->mode = (MODE_KERNEL << 1) | 0;
m_cache_dirty = true;
m_interrupt_cycles = 0;
m_core->vfr[0][3] = 1.0f;
m_core->vfmem = &m_core->vumem[0];
m_core->vimem = reinterpret_cast<uint32_t*>(m_core->vfmem);
m_core->vr = &m_core->vcr[20];
m_core->i = reinterpret_cast<float*>(&m_core->vcr[21]);
m_core->q = reinterpret_cast<float*>(&m_core->vcr[22]);
}
@ -2929,6 +2934,7 @@ void mips3_device::handle_extra_cop2(uint32_t op)
void r5900le_device::handle_extra_cop2(uint32_t op)
{
// TODO: Flags, rounding...
const int rd = (op >> 6) & 31;
const int rs = (op >> 11) & 31;
const int rt = (op >> 16) & 31;
@ -2936,25 +2942,136 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
switch (op & 0x3f)
{
case 0x00: case 0x01: case 0x02: case 0x03:
printf("Unsupported instruction: VADDbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x04: case 0x05: case 0x06: case 0x07:
printf("Unsupported instruction: VSUBbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x08: case 0x09: case 0x0a: case 0x0b:
printf("Unsupported instruction: VMADDbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x00: case 0x01: case 0x02: case 0x03: /* VADDbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] + ft[bc];
}
}
}
break;
case 0x04: case 0x05: case 0x06: case 0x07: /* VSUBbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] - ft[bc];
}
}
}
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: /* VMADDbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = m_core->vacc[field] + fs[field] + ft[bc];
}
}
}
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
printf("Unsupported instruction: VMSUBbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x10: case 0x11: case 0x12: case 0x13:
printf("Unsupported instruction: VMAXbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x14: case 0x15: case 0x16: case 0x17:
printf("Unsupported instruction: VMINIbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x18: case 0x19: case 0x1a: case 0x1b:
printf("Unsupported instruction: VMULbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1c: printf("Unsupported instruction: VMULq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x10: case 0x11: case 0x12: case 0x13: /* VMAXbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = std::fmax(fs[field], ft[bc]);
}
}
}
break;
case 0x14: case 0x15: case 0x16: case 0x17: /* VMINIbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = std::fmin(fs[field], ft[bc]);
}
}
}
break;
case 0x18: case 0x19: case 0x1a: case 0x1b: /* VMULbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] * ft[bc];
}
}
}
break;
case 0x1c: /* VMULq */
if (rd)
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] * ft[field];
}
}
}
break;
case 0x1d: printf("Unsupported instruction: VMAXi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1e: printf("Unsupported instruction: VMULi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1f: printf("Unsupported instruction: VMINIi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x20: printf("Unsupported instruction: VADDq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x20: /* VADDq */
if (rd)
{
float *fs = m_core->vfr[rs];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] + *(m_core->q);
}
}
}
break;
case 0x21: printf("Unsupported instruction: VMADDq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x22: printf("Unsupported instruction: VADDi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x23: printf("Unsupported instruction: VMADDi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
@ -2962,26 +3079,67 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
case 0x25: printf("Unsupported instruction: VMSUBq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x26: printf("Unsupported instruction: VSUBi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x27: printf("Unsupported instruction: VMSUBi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x28: printf("Unsupported instruction: VADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x29: printf("Unsupported instruction: VMADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2a: printf("Unsupported instruction: VMUL @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2b: printf("Unsupported instruction: VMAX @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2c:
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rt];
for (int field = 0; field < 4; field++)
case 0x28: /* VADD */
if (rd)
{
if (BIT(op, 24-field))
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
fd[field] = fs[field] - ft[field];
if (BIT(op, 24-field))
{
fd[field] = fs[field] + ft[field];
}
}
}
break;
case 0x29: printf("Unsupported instruction: VMADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2a: /* VMUL */
if (rd)
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] * ft[field];
}
}
}
break;
case 0x2b: printf("Unsupported instruction: VMAX @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2c: /* VSUB */
{
if (rd)
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = fs[field] - ft[field];
}
}
}
break;
}
case 0x2d: printf("Unsupported instruction: VMSUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2e: printf("Unsupported instruction: VOPMSUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2e: /* VOPMSUB */
if (rd)
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
fd[0] = m_core->vacc[0] - fs[1] * ft[2];
fd[1] = m_core->vacc[1] - fs[2] * ft[0];
fd[2] = m_core->vacc[2] - fs[0] * ft[1];
}
break;
case 0x2f: printf("Unsupported instruction: VMINI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x30:
if (rd)
@ -3002,20 +3160,72 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
printf("Unsupported instruction: VADDAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x04: case 0x05: case 0x06: case 0x07:
printf("Unsupported instruction: VSUBAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x08: case 0x09: case 0x0a: case 0x0b:
printf("Unsupported instruction: VMADDAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x08: case 0x09: case 0x0a: case 0x0b: /* VMADDAbc */
if (rd)
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
float *fd = m_core->vfr[rd];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
fd[field] = m_core->vacc[field] + fs[field] * ft[bc];
}
}
}
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
printf("Unsupported instruction: VMSUBAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x10: printf("Unsupported instruction: VITOF0 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x11: printf("Unsupported instruction: VITOF4 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x12: printf("Unsupported instruction: VITOF12 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x13: printf("Unsupported instruction: VITOF15 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x14: printf("Unsupported instruction: VFTOI0 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x15: printf("Unsupported instruction: VFTOI4 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x14: /* VFTOI0 */
if (rt)
{
float *fs = m_core->vfr[rs];
int32_t *ft = reinterpret_cast<int32_t*>(m_core->vfr[rt]);
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
ft[field] = (int32_t)(fs[field]);
}
}
}
break;
case 0x15: /* VFTOI4 */
if (rt)
{
float *fs = m_core->vfr[rs];
int32_t *ft = reinterpret_cast<int32_t*>(m_core->vfr[rt]);
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
ft[field] = (int32_t)(fs[field] * 16.0f);
}
}
}
break;
case 0x16: printf("Unsupported instruction: VFTOI12 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x17: printf("Unsupported instruction: VFTOI15 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x18: case 0x19: case 0x1a: case 0x1b:
printf("Unsupported instruction: VMULAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x18: case 0x19: case 0x1a: case 0x1b: /* VMULAbc */
{
const uint32_t bc = op & 3;
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
m_core->vacc[field] = fs[field] * ft[bc];
}
}
}
break;
case 0x1c: printf("Unsupported instruction: VMULAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1d: printf("Unsupported instruction: VABS @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1e: printf("Unsupported instruction: VMULAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
@ -3034,16 +3244,51 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
// 2b?
case 0x2c: printf("Unsupported instruction: VSUBA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2d: printf("Unsupported instruction: VMSUBA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2e: printf("Unsupported instruction: VOPMULA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2f: printf("Unsupported instruction: VNOP @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x30: printf("Unsupported instruction: VMOVE @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x31: printf("Unsupported instruction: VMR32 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2e: /* VOPMULA */
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
m_core->vacc[0] = fs[1] * ft[2];
m_core->vacc[1] = fs[2] * ft[0];
m_core->vacc[2] = fs[0] * ft[1];
}
break;
case 0x2f: /* VNOP */
break;
case 0x30: /* VMOVE */
if (rt)
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
ft[field] = fs[field];
}
}
}
break;
case 0x31: /* VMR32 */
if (rt)
{
float *fs = m_core->vfr[rs];
float *ft = m_core->vfr[rt];
for (int field = 0; field < 4; field++)
{
if (BIT(op, 24-field))
{
ft[field] = fs[(field + 3) & 3];
}
}
}
break;
// 32?
// 33?
case 0x34: printf("Unsupported instruction: VLQI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x35:
case 0x35: /* VSQI */
{
uint32_t *base = &m_core->vimem[m_core->vcr[rt] << 2];
uint32_t *base = &m_core->vimem[(m_core->vcr[rt] << 2) & 0xfff];
uint32_t *fs = reinterpret_cast<uint32_t*>(m_core->vfr[rs]);
for (int field = 0; field < 4; field++)
{
@ -3061,10 +3306,27 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
}
case 0x36: printf("Unsupported instruction: VLQD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x37: printf("Unsupported instruction: VSQD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x38: printf("Unsupported instruction: VDIV @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x39: printf("Unsupported instruction: VSQRT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x38: /* VDIV */
{
const uint32_t fsf = (op >> 21) & 3;
const uint32_t ftf = (op >> 23) & 3;
const float *fs = m_core->vfr[rs];
const float *ft = m_core->vfr[rt];
const float ftval = ft[ftf];
if (ftval)
*(m_core->q) = fs[fsf] / ft[ftf];
}
break;
case 0x39: /* VSQRT */
{
const uint32_t ftf = (op >> 23) & 3;
*(m_core->q) = (float)sqrt(m_core->vfr[rt][ftf]);
}
break;
case 0x3a: printf("Unsupported instruction: VRSQRT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x3b: printf("Unsupported instruction: VWAITQ @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x3b: /* VWAITQ */
// TODO: We assume Q is instantly available. Fix this!
break;
case 0x3c: printf("Unsupported instruction: VMTIR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x3d: printf("Unsupported instruction: VMFIR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x3e: printf("Unsupported instruction: VILWR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
@ -3076,7 +3338,7 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
{
if (BIT(op, 24-field))
{
m_core->vimem[base + field] = val;
m_core->vimem[(base + field) & 0xfff] = val;
}
}
break;
@ -3408,8 +3670,15 @@ void r5900le_device::handle_idt(uint32_t op)
switch (op & 0x3f)
{
case 0x00: /* MADD */
printf("Unsupported instruction: MADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
{
uint64_t temp64 = (int64_t)(int32_t)RSVAL32 * (int64_t)(int32_t)RTVAL32;
m_core->r[REG_LO] += (int32_t)temp64;
m_core->r[REG_HI] += (int32_t)(temp64 >> 32);
if (rd)
m_core->r[rd] = m_core->r[REG_LO];
m_core->icount -= 3; // ?
break;
}
case 0x01: /* MADDU */
printf("Unsupported instruction: MADDU @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
@ -3537,7 +3806,18 @@ void r5900le_device::handle_mmi0(uint32_t op)
printf("Unsupported instruction: PADDW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
case 0x01: /* PSUBW */
printf("Unsupported instruction: PSUBW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
if (rd)
{
const uint32_t rsval[4] = { (uint32_t)(m_core->rh[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->r[rs] };
const uint32_t rtval[4] = { (uint32_t)(m_core->rh[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->r[rt] };
uint32_t rdval[4] = { 0, 0, 0, 0 };
for (int word_idx = 0; word_idx < 4; word_idx++)
{
rdval[word_idx] = rsval[word_idx] - rtval[word_idx];
}
m_core->rh[rd] = ((uint64_t)rdval[0] << 32) | rdval[1];
m_core->r[rd] = ((uint64_t)rdval[2] << 32) | rdval[3];
}
break;
case 0x02: /* PCGTW */
printf("Unsupported instruction: PCGTW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
@ -3673,27 +3953,32 @@ void r5900le_device::handle_mmi1(uint32_t op)
printf("Unsupported instruction: PCEQB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
case 0x10: /* PADDUW */
{
if (rd == 0) break;
uint32_t rsval[4] = { (uint32_t)m_core->r[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->rh[rs] >> 32) };
uint32_t rtval[4] = { (uint32_t)m_core->r[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->rh[rt] >> 32) };
uint64_t rdval[4] = { 0 };
for (int i = 0; i < 4; i++)
if (rd)
{
uint64_t sum = (uint64_t)rsval[i] + (uint64_t)rtval[i];
rdval[i] = (sum >= 0x100000000ULL) ? 0xffffffffULL : sum;
}
m_core->r[rd] = rdval[0] | (rdval[1] << 32);
m_core->rh[rd] = rdval[2] | (rdval[3] << 32);
break;
}
uint32_t rsval[4] = { (uint32_t)m_core->r[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->rh[rs] >> 32) };
uint32_t rtval[4] = { (uint32_t)m_core->r[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->rh[rt] >> 32) };
uint64_t rdval[4] = { 0 };
for (int i = 0; i < 4; i++)
{
uint64_t sum = (uint64_t)rsval[i] + (uint64_t)rtval[i];
rdval[i] = (sum >= 0x100000000ULL) ? 0xffffffffULL : sum;
}
m_core->r[rd] = rdval[0] | (rdval[1] << 32);
m_core->rh[rd] = rdval[2] | (rdval[3] << 32);
}
break;
case 0x11: /* PSUBUW */
printf("Unsupported instruction: PSUBUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
case 0x12: /* PEXTUW */
printf("Unsupported instruction: PEXTUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
if (rd)
{
uint64_t rsval = m_core->rh[rs];
uint64_t rtval = m_core->rh[rt];
m_core->rh[rd] = (rsval & 0xffffffff00000000ULL) | (rtval >> 32);
m_core->r[rd] = (rtval & 0x00000000ffffffffULL) | (rsval << 32);
}
break;
case 0x14: /* PADDUH */
printf("Unsupported instruction: PADDUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");

View File

@ -366,11 +366,17 @@ protected:
float acc;
/* VU0 registers (R5900 only) */
float vfr[32][4];
float vfr[32][4]; // 0..3 = w..x
uint32_t vcr[32];
float vumem[0x1000];
float* vfmem;
uint32_t* vimem;
float vacc[4];
float p;
uint32_t* vr;
float* i;
float* q;
uint32_t mode; /* current global mode */

View File

@ -170,9 +170,15 @@ iLinkSGUID=0x--------
#include "machine/ioptimer.h"
#include "machine/ps2dma.h"
#include "machine/ps2gif.h"
#include "machine/ps2intc.h"
#include "machine/ps2mc.h"
#include "machine/ps2pad.h"
#include "machine/ps2sif.h"
#include "machine/ps2timer.h"
#include "machine/ps2vif1.h"
#include "video/ps2gs.h"
#include "emupal.h"
#include "screen.h"
@ -194,6 +200,11 @@ public:
, m_iop_spu(*this, "iop_spu")
, m_iop_cdvd(*this, "iop_cdvd")
, m_iop_sio2(*this, "iop_sio2")
, m_gif(*this, "gif")
, m_gs(*this, "gs")
, m_vif1(*this, "vif1")
, m_pad(*this, "pad%u", 0U)
, m_mc(*this, "mc")
, m_screen(*this, "screen")
, m_ram(*this, "ram")
, m_iop_ram(*this, "iop_ram")
@ -215,17 +226,10 @@ protected:
TIMER_CALLBACK_MEMBER(vblank);
DECLARE_READ64_MEMBER(gs_regs0_r);
DECLARE_WRITE64_MEMBER(gs_regs0_w);
DECLARE_READ64_MEMBER(gs_regs1_r);
DECLARE_WRITE64_MEMBER(gs_regs1_w);
DECLARE_READ32_MEMBER(ipu_r);
DECLARE_WRITE32_MEMBER(ipu_w);
DECLARE_READ64_MEMBER(vif0_fifo_r);
DECLARE_WRITE64_MEMBER(vif0_fifo_w);
DECLARE_READ64_MEMBER(vif1_fifo_r);
DECLARE_WRITE64_MEMBER(vif1_fifo_w);
DECLARE_READ64_MEMBER(gif_fifo_r);
DECLARE_WRITE64_MEMBER(gif_fifo_w);
DECLARE_READ64_MEMBER(ipu_fifo_r);
@ -259,6 +263,11 @@ protected:
required_device<iop_spu_device> m_iop_spu;
required_device<iop_cdvd_device> m_iop_cdvd;
required_device<iop_sio2_device> m_iop_sio2;
required_device<ps2_gif_device> m_gif;
required_device<ps2_gs_device> m_gs;
required_device<ps2_vif1_device> m_vif1;
required_device_array<ps2_pad_device, 2> m_pad;
required_device<ps2_mc_device> m_mc;
required_device<screen_device> m_screen;
required_shared_ptr<uint64_t> m_ram;
required_shared_ptr<uint32_t> m_iop_ram;
@ -268,12 +277,6 @@ protected:
required_shared_ptr<uint64_t> m_vu1_imem;
required_shared_ptr<uint64_t> m_vu1_dmem;
uint64_t m_gs_base_regs[15];
uint64_t m_gs_csr;
uint64_t m_gs_imr;
uint64_t m_gs_busdir;
uint64_t m_gs_sig_label_id;
uint32_t m_unk_f430_reg;
uint32_t m_unk_f440_counter;
uint32_t m_unk_f440_reg;
@ -320,32 +323,6 @@ WRITE64_MEMBER(ps2sony_state::vif0_fifo_w)
}
}
READ64_MEMBER(ps2sony_state::vif1_fifo_r)
{
uint64_t ret = 0ULL;
if (offset)
{
logerror("%s: vif1_fifo_r [127..64]: (%08x%08x & %08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret, (uint32_t)(mem_mask >> 32), (uint32_t)mem_mask);
}
else
{
logerror("%s: vif1_fifo_r [63..0]: (%08x%08x & %08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret, (uint32_t)(mem_mask >> 32), (uint32_t)mem_mask);
}
return ret;
}
WRITE64_MEMBER(ps2sony_state::vif1_fifo_w)
{
if (offset)
{
logerror("%s: vif1_fifo_w [127..64]: %08x%08x & %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, (uint32_t)(mem_mask >> 32), (uint32_t)mem_mask);
}
else
{
logerror("%s: vif1_fifo_w [63..0]: %08x%08x & %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, (uint32_t)(mem_mask >> 32), (uint32_t)mem_mask);
}
}
READ64_MEMBER(ps2sony_state::gif_fifo_r)
{
uint64_t ret = 0ULL;
@ -545,12 +522,6 @@ WRITE32_MEMBER(ps2sony_state::iop_debug_w)
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));
@ -579,12 +550,6 @@ void ps2sony_state::machine_reset()
memset(m_ipu_out_fifo, 0, sizeof(uint64_t)*0x1000);
m_ipu_out_fifo_index = 0;
memset(m_gs_base_regs, 0, sizeof(uint64_t) * 15);
m_gs_csr = 0ULL;
m_gs_imr = 0ULL;
m_gs_busdir = 0ULL;
m_gs_sig_label_id = 0ULL;
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
}
@ -596,13 +561,15 @@ TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
m_intc->raise_interrupt(ps2_intc_device::INT_VB_ON);
m_iop_intc->raise_interrupt(iop_intc_device::INT_VB_ON);
m_vblank_timer->adjust(m_screen->time_until_pos(0), 0);
m_gs->vblank_start();
}
else
{
// VBlank exit
m_intc->raise_interrupt(ps2_intc_device::INT_VB_OFF);
//m_intc->raise_interrupt(ps2_intc_device::INT_VB_OFF);
m_iop_intc->raise_interrupt(iop_intc_device::INT_VB_OFF);
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
m_gs->vblank_end();
}
}
@ -703,109 +670,6 @@ WRITE32_MEMBER(ps2sony_state::unk_f440_w)
*
*/
READ64_MEMBER(ps2sony_state::gs_regs0_r)
{
uint64_t ret = m_gs_base_regs[offset >> 1];
switch (offset)
{
case 0x00: logerror("%s: gs_regs0_r: PMODE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x02: logerror("%s: gs_regs0_r: SMODE1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x04: logerror("%s: gs_regs0_r: SMODE2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x06: logerror("%s: gs_regs0_r: SRFSH (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x08: logerror("%s: gs_regs0_r: SYNCH1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x0a: logerror("%s: gs_regs0_r: SYNCH2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x0c: logerror("%s: gs_regs0_r: SYNCV (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x0e: logerror("%s: gs_regs0_r: DISPFB1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x10: logerror("%s: gs_regs0_r: DISPLAY1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x12: logerror("%s: gs_regs0_r: DISPFB2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x14: logerror("%s: gs_regs0_r: DISPLAY2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x16: logerror("%s: gs_regs0_r: EXTBUF (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x18: logerror("%s: gs_regs0_r: EXTDATA (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x1a: logerror("%s: gs_regs0_r: EXTWRITE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x1c: logerror("%s: gs_regs0_r: BGCOLOR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
default: logerror("%s: gs_regs0_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3)); break;
}
return ret;
}
WRITE64_MEMBER(ps2sony_state::gs_regs0_w)
{
switch (offset)
{
case 0x00: logerror("%s: gs_regs0_w: PMODE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x02: logerror("%s: gs_regs0_w: SMODE1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x04: logerror("%s: gs_regs0_w: SMODE2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x06: logerror("%s: gs_regs0_w: SRFSH = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x08: logerror("%s: gs_regs0_w: SYNCH1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x0a: logerror("%s: gs_regs0_w: SYNCH2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x0c: logerror("%s: gs_regs0_w: SYNCV = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x0e: logerror("%s: gs_regs0_w: DISPFB1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x10: logerror("%s: gs_regs0_w: DISPLAY1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x12: logerror("%s: gs_regs0_w: DISPFB2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x14: logerror("%s: gs_regs0_w: DISPLAY2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x16: logerror("%s: gs_regs0_w: EXTBUF = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x18: logerror("%s: gs_regs0_w: EXTDATA = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x1a: logerror("%s: gs_regs0_w: EXTWRITE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x1c: logerror("%s: gs_regs0_w: BGCOLOR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
default: logerror("%s: gs_regs0_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data); break;
}
COMBINE_DATA(&m_gs_base_regs[offset >> 1]);
}
READ64_MEMBER(ps2sony_state::gs_regs1_r)
{
uint64_t ret = 0;
switch (offset)
{
case 0x00:
ret = m_gs_csr;
logerror("%s: gs_regs1_r: CSR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x02:
ret = m_gs_imr;
logerror("%s: gs_regs1_r: IMR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x08:
ret = m_gs_busdir;
logerror("%s: gs_regs1_r: BUSDIR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x10:
ret = m_gs_sig_label_id;
logerror("%s: gs_regs1_r: SIGLBLID (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
default:
logerror("%s: gs_regs1_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3));
break;
}
return ret;
}
WRITE64_MEMBER(ps2sony_state::gs_regs1_w)
{
switch (offset)
{
case 0x00:
logerror("%s: gs_regs1_w: CSR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
COMBINE_DATA(&m_gs_csr);
break;
case 0x02:
logerror("%s: gs_regs1_w: IMR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
COMBINE_DATA(&m_gs_imr);
break;
case 0x08:
logerror("%s: gs_regs1_w: BUSDIR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
COMBINE_DATA(&m_gs_busdir);
break;
case 0x10:
logerror("%s: gs_regs1_w: SIGLBLID = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
COMBINE_DATA(&m_gs_sig_label_id);
break;
default:
logerror("%s: gs_regs1_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data);
break;
}
}
uint32_t ps2sony_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
return 0;
@ -819,8 +683,9 @@ void ps2sony_state::mem_map(address_map &map)
map(0x10001000, 0x100017ff).rw(m_timer[2], FUNC(ps2_timer_device::read), FUNC(ps2_timer_device::write)).umask64(0x00000000ffffffff);
map(0x10001800, 0x10001fff).rw(m_timer[3], FUNC(ps2_timer_device::read), FUNC(ps2_timer_device::write)).umask64(0x00000000ffffffff);
map(0x10002000, 0x10002fff).rw(FUNC(ps2sony_state::ipu_r), FUNC(ps2sony_state::ipu_w)).umask64(0x00000000ffffffff);
map(0x10003000, 0x100030af).rw(m_gif, FUNC(ps2_gif_device::read), FUNC(ps2_gif_device::write));
map(0x10004000, 0x1000400f).mirror(0xff0).rw(FUNC(ps2sony_state::vif0_fifo_r), FUNC(ps2sony_state::vif0_fifo_w));
map(0x10005000, 0x1000500f).mirror(0xff0).rw(FUNC(ps2sony_state::vif1_fifo_r), FUNC(ps2sony_state::vif1_fifo_w));
map(0x10005000, 0x1000500f).mirror(0xff0).rw(m_vif1, FUNC(ps2_vif1_device::mmio_r), FUNC(ps2_vif1_device::mmio_w));
map(0x10006000, 0x1000600f).mirror(0xff0).rw(FUNC(ps2sony_state::gif_fifo_r), FUNC(ps2sony_state::gif_fifo_w));
map(0x10007000, 0x1000701f).mirror(0xfe0).rw(FUNC(ps2sony_state::ipu_fifo_r), FUNC(ps2sony_state::ipu_fifo_w));
map(0x10008000, 0x1000dfff).rw(m_dmac, FUNC(ps2_dmac_device::channel_r), FUNC(ps2_dmac_device::channel_w)).umask64(0x00000000ffffffff);;
@ -837,8 +702,8 @@ void ps2sony_state::mem_map(address_map &map)
map(0x11004000, 0x11004fff).mirror(0x3000).ram().share(m_vu0_dmem);
map(0x11008000, 0x1100bfff).ram().share(m_vu1_imem);
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(0x12001000, 0x120013ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs1_r), FUNC(ps2sony_state::gs_regs1_w));
map(0x12000000, 0x120003ff).mirror(0xc00).rw(m_gs, FUNC(ps2_gs_device::priv_regs0_r), FUNC(ps2_gs_device::priv_regs0_w));
map(0x12001000, 0x120013ff).mirror(0xc00).rw(m_gs, FUNC(ps2_gs_device::priv_regs1_r), FUNC(ps2_gs_device::priv_regs1_w));
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);
@ -875,14 +740,18 @@ MACHINE_CONFIG_START(ps2sony_state::ps2sony)
MCFG_MIPS3_DCACHE_SIZE(16384)
MCFG_DEVICE_PROGRAM_MAP(mem_map)
MCFG_DEVICE_ADD(m_vif1, SONYPS2_VIF1, 294912000/2, m_gif)
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[2], SONYPS2_TIMER, 294912000/2, false)
MCFG_DEVICE_ADD(m_timer[3], SONYPS2_TIMER, 294912000/2, false)
MCFG_DEVICE_ADD(m_gs, SONYPS2_GS, 294912000/2)
MCFG_DEVICE_ADD(m_intc, SONYPS2_INTC, m_maincpu)
MCFG_DEVICE_ADD(m_dmac, SONYPS2_DMAC, 294912000/2, m_maincpu, m_ram, m_sif)
MCFG_DEVICE_ADD(m_dmac, SONYPS2_DMAC, 294912000/2, m_maincpu, m_ram, m_sif, m_gif, m_vif1)
MCFG_DEVICE_ADD(m_sif, SONYPS2_SIF, m_intc)
MCFG_DEVICE_ADD(m_gif, SONYPS2_GIF, m_gs)
MCFG_DEVICE_ADD(m_iop, SONYPS2_IOP, XTAL(67'737'600)/2)
MCFG_DEVICE_PROGRAM_MAP(iop_map)
@ -890,8 +759,12 @@ MACHINE_CONFIG_START(ps2sony_state::ps2sony)
MCFG_QUANTUM_PERFECT_CPU("maincpu")
MCFG_QUANTUM_PERFECT_CPU("iop")
MCFG_DEVICE_ADD(m_pad[0], SONYPS2_PAD)
MCFG_DEVICE_ADD(m_pad[1], SONYPS2_PAD)
MCFG_DEVICE_ADD(m_mc, SONYPS2_MC)
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_sio2, SONYIOP_SIO2, m_iop_intc, m_pad[0], m_pad[1], m_mc)
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))

View File

@ -139,7 +139,7 @@ void iop_dma_device::transfer_sif0(uint32_t chan)
{
if (channel.end())
{
logerror("sif0.end\n");
//logerror("sif0.end\n");
transfer_finish(SIF0);
}
else if (m_sif->fifo_depth(0) < ps2_sif_device::MAX_FIFO_DEPTH - 2)
@ -151,7 +151,7 @@ void iop_dma_device::transfer_sif0(uint32_t chan)
const uint32_t ee_hi = m_ram[tag_addr + 2];
const uint32_t ee_lo = m_ram[tag_addr + 3];
logerror("%s: following sif0 iop tag, full tag is %08x %08x %08x %08x\n", machine().describe_context(), iop_hi, iop_lo, ee_hi, ee_lo);
//logerror("%s: following sif0 iop tag, full tag is %08x %08x %08x %08x\n", machine().describe_context(), iop_hi, iop_lo, ee_hi, ee_lo);
channel.set_addr(iop_hi & 0x00ffffff);
channel.set_count((iop_lo + 3) & ~3);
channel.set_tag_addr(tag_addr_bytes + 0x10);
@ -189,7 +189,7 @@ void iop_dma_device::transfer_sif1(uint32_t chan)
{
if (channel.end())
{
logerror("sif1.end\n");
//logerror("sif1.end\n");
transfer_finish(SIF1);
}
else if (m_sif->fifo_depth(1) >= 4)
@ -198,7 +198,7 @@ void iop_dma_device::transfer_sif1(uint32_t chan)
const uint32_t iop_lo = m_sif->fifo_pop(1);
m_sif->fifo_pop(1); // ee_hi - ignored
m_sif->fifo_pop(1); // ee_lo - ignored
logerror("%s: following sif1 iop tag, tag is %08x %08x\n", machine().describe_context(), iop_hi, iop_lo);
//logerror("%s: following sif1 iop tag, tag is %08x %08x\n", machine().describe_context(), iop_hi, iop_lo);
channel.set_addr(iop_hi & 0x00ffffff);
channel.set_count(iop_lo);
@ -249,10 +249,10 @@ void iop_dma_device::transfer_to_sio2(uint32_t chan)
{
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);
m_sio2->transmit(data & 0xff);
m_sio2->transmit((data >> 8) & 0xff);
m_sio2->transmit((data >> 16) & 0xff);
m_sio2->transmit((data >> 24) & 0xff);
channel.set_count(count - 1);
channel.set_addr(addr + 4);
}
@ -272,10 +272,10 @@ void iop_dma_device::transfer_from_sio2(uint32_t chan)
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();
uint32_t data = m_sio2->receive();
data |= m_sio2->receive() << 8;
data |= m_sio2->receive() << 16;
data |= m_sio2->receive() << 24;
m_ram[addr >> 2] = data;
channel.set_count(count - 1);
channel.set_addr(addr + 4);
@ -312,29 +312,29 @@ READ32_MEMBER(iop_dma_device::bank0_r)
{
case 0x00/4: case 0x10/4: case 0x20/4: case 0x30/4: case 0x40/4: case 0x50/4: case 0x60/4:
ret = m_channels[offset >> 2].addr();
logerror("%s: bank0_r: channel[%d].addr (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask);
//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].block();
logerror("%s: bank0_r: channel[%d].block (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask);
//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:
ret = m_channels[offset >> 2].ctrl();
logerror("%s: bank0_r: channel[%d].ctrl (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask);
//logerror("%s: bank0_r: channel[%d].ctrl (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask);
break;
case 0x0c/4: case 0x1c/4: case 0x2c/4: case 0x3c/4: case 0x4c/4: case 0x5c/4: case 0x6c/4:
ret = m_channels[offset >> 2].tag_addr();
logerror("%s: bank0_r: channel[%d].tag_addr (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask);
//logerror("%s: bank0_r: channel[%d].tag_addr (%08x & %08x)\n", machine().describe_context(), offset >> 2, ret, mem_mask);
break;
case 0x70/4: // 0x1f8010f0, DPCR
ret = m_dpcr[0];
logerror("%s: bank0_r: DPCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: bank0_r: DPCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x74/4: // 0x1f8010f4, DICR
ret = m_dicr[0];
if ((m_int_ctrl[0].m_status & m_int_ctrl[0].m_mask) && m_int_ctrl[0].m_enabled)
ret |= 0x80000000;
logerror("%s: bank0_r: DICR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: bank0_r: DICR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
default:
logerror("%s: bank0_r: Unknown %08x & %08x\n", machine().describe_context(), 0x1f801080 + (offset << 2), mem_mask);
@ -348,28 +348,28 @@ WRITE32_MEMBER(iop_dma_device::bank0_w)
switch (offset)
{
case 0x00/4: case 0x10/4: case 0x20/4: case 0x30/4: case 0x40/4: case 0x50/4: case 0x60/4:
logerror("%s: bank0_w: channel[%d].addr = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
//logerror("%s: bank0_w: channel[%d].addr = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
m_channels[offset >> 2].set_addr(data);
break;
case 0x04/4: case 0x14/4: case 0x24/4: case 0x34/4: case 0x44/4: case 0x54/4: case 0x64/4:
logerror("%s: bank0_w: channel[%d].block = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
//logerror("%s: bank0_w: channel[%d].block = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
m_channels[offset >> 2].set_block(data, mem_mask);
break;
case 0x08/4: case 0x18/4: case 0x28/4: case 0x38/4: case 0x48/4: case 0x58/4: case 0x68/4:
logerror("%s: bank0_w: channel[%d].ctrl = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
//logerror("%s: bank0_w: channel[%d].ctrl = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
m_channels[offset >> 2].set_ctrl(data);
m_running_mask |= m_channels[offset >> 2].busy() ? (1 << (offset >> 2)) : 0;
break;
case 0x0c/4: case 0x1c/4: case 0x2c/4: case 0x3c/4: case 0x4c/4: case 0x5c/4: case 0x6c/4:
logerror("%s: bank0_w: channel[%d].tag_addr = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
//logerror("%s: bank0_w: channel[%d].tag_addr = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
m_channels[offset >> 2].set_tag_addr(data);
break;
case 0x70/4: // 0x1f8010f0, DPCR
logerror("%s: bank0_w: DPCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: bank0_w: DPCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
set_dpcr(data, 0);
break;
case 0x74/4: // 0x1f8010f4, DICR
logerror("%s: bank0_w: DICR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: bank0_w: DICR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
set_dicr(data, 0);
break;
default:
@ -385,29 +385,30 @@ READ32_MEMBER(iop_dma_device::bank1_r)
{
case 0x00/4: case 0x10/4: case 0x20/4: case 0x30/4: case 0x40/4: case 0x50/4: case 0x60/4:
ret = m_channels[(offset >> 2) + 8].addr();
logerror("%s: bank1_r: channel[%d].addr (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask);
//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].block();
logerror("%s: bank1_r: channel[%d].block (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask);
//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:
ret = m_channels[(offset >> 2) + 8].ctrl();
logerror("%s: bank1_r: channel[%d].ctrl (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask);
//if ((offset >> 2) != 2)
//logerror("%s: bank1_r: channel[%d].ctrl (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask);
break;
case 0x0c/4: case 0x1c/4: case 0x2c/4: case 0x3c/4: case 0x4c/4: case 0x5c/4: case 0x6c/4:
ret = m_channels[(offset >> 2) + 8].tag_addr();
logerror("%s: bank1_r: channel[%d].tag_addr (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask);
//logerror("%s: bank1_r: channel[%d].tag_addr (%08x & %08x)\n", machine().describe_context(), (offset >> 2) + 8, ret, mem_mask);
break;
case 0x70/4: // 0x1f801570, DPCR2
ret = m_dpcr[1];
logerror("%s: bank1_r: DPCR2 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: bank1_r: DPCR2 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x74/4: // 0x1f801574, DICR2
ret = m_dicr[1];
if ((m_int_ctrl[1].m_status & m_int_ctrl[1].m_mask) && m_int_ctrl[1].m_enabled)
ret |= 0x80000000;
logerror("%s: bank1_r: DICR2 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: bank1_r: DICR2 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
default:
logerror("%s: bank1_r: Unknown %08x & %08x\n", machine().describe_context(), 0x1f801500 + (offset << 2), mem_mask);
@ -421,28 +422,28 @@ WRITE32_MEMBER(iop_dma_device::bank1_w)
switch (offset & 0x1f)
{
case 0x00/4: case 0x10/4: case 0x20/4: case 0x30/4: case 0x40/4: case 0x50/4: case 0x60/4:
logerror("%s: bank1_w: channel[%d].addr = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
//logerror("%s: bank1_w: channel[%d].addr = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
m_channels[(offset >> 2) + 8].set_addr(data);
break;
case 0x04/4: case 0x14/4: case 0x24/4: case 0x34/4: case 0x44/4: case 0x54/4: case 0x64/4:
logerror("%s: bank1_w: channel[%d].block = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
//logerror("%s: bank1_w: channel[%d].block = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
m_channels[(offset >> 2) + 8].set_block(data, mem_mask);
break;
case 0x08/4: case 0x18/4: case 0x28/4: case 0x38/4: case 0x48/4: case 0x58/4: case 0x68/4:
logerror("%s: bank1_w: channel[%d].ctrl = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
//logerror("%s: bank1_w: channel[%d].ctrl = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
m_channels[(offset >> 2) + 8].set_ctrl(data);
m_running_mask |= m_channels[(offset >> 2) + 8].busy() ? (1 << ((offset >> 2) + 8)) : 0;
break;
case 0x0c/4: case 0x1c/4: case 0x2c/4: case 0x3c/4: case 0x4c/4: case 0x5c/4: case 0x6c/4:
logerror("%s: bank1_w: channel[%d].tag_addr = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
//logerror("%s: bank1_w: channel[%d].tag_addr = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
m_channels[(offset >> 2) + 8].set_tag_addr(data);
break;
case 0x70/4: // 0x1f801570, DPCR2
logerror("%s: bank1_w: DPCR2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: bank1_w: DPCR2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
set_dpcr(data, 1);
break;
case 0x74/4: // 0x1f801574, DICR2
logerror("%s: bank1_w: DICR2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: bank1_w: DICR2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
set_dicr(data, 1);
break;
default:

View File

@ -40,11 +40,11 @@ READ32_MEMBER(iop_intc_device::read)
{
case 0: // I_STAT
ret = m_status;
logerror("%s: read: I_STAT %08x & %08x\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: read: I_STAT %08x & %08x\n", machine().describe_context(), ret, mem_mask);
break;
case 1: // I_MASK
ret = m_mask;
logerror("%s: read: I_MASK %08x & %08x\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: read: I_MASK %08x & %08x\n", machine().describe_context(), ret, mem_mask);
break;
case 2: // I_ENABLE
ret = m_enabled ? 1 : 0;
@ -64,12 +64,12 @@ WRITE32_MEMBER(iop_intc_device::write)
switch (offset)
{
case 0: // I_STAT
logerror("%s: write: I_STAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: write: I_STAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_status &= data;
update_interrupts();
break;
case 1: // I_MASK
logerror("%s: write: I_MASK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: write: I_MASK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_mask = data;
update_interrupts();
break;
@ -86,7 +86,7 @@ WRITE32_MEMBER(iop_intc_device::write)
void iop_intc_device::raise_interrupt(uint32_t line)
{
logerror("%s: raise_interrupt: %d\n", machine().describe_context(), line);
//logerror("%s: raise_interrupt: %d\n", machine().describe_context(), line);
m_status |= (1 << line);
update_interrupts();
}

View File

@ -11,38 +11,61 @@
#include "iopsio2.h"
/*static*/ const size_t iop_sio2_device::BUFFER_SIZE = 64; // total guess
/*static*/ const size_t iop_sio2_device::BUFFER_SIZE = 512; // total guess based on memcard block size
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)
, m_pad0(*this, finder_base::DUMMY_TAG)
, m_pad1(*this, finder_base::DUMMY_TAG)
, m_mc0(*this, finder_base::DUMMY_TAG)
{
}
void iop_sio2_device::device_start()
{
if (!m_response_timer)
m_response_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(iop_sio2_device::response_timer), this));
save_item(NAME(m_buffer));
save_item(NAME(m_curr_byte));
save_item(NAME(m_end_byte));
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));
save_item(NAME(m_unknown_0x6c));
save_item(NAME(m_unknown_0x70));
save_item(NAME(m_unknown_0x74));
save_item(NAME(m_cmdbuf));
save_item(NAME(m_curr_port));
save_item(NAME(m_cmd_size));
save_item(NAME(m_cmd_length));
save_item(NAME(m_databuf[0]));
save_item(NAME(m_databuf[1]));
save_item(NAME(m_target_device));
}
void iop_sio2_device::device_reset()
{
memset(m_buffer, 0, BUFFER_SIZE);
m_curr_byte = 0;
m_end_byte = 0;
m_ctrl = 0;
memset(m_receive_buf, 0, BUFFER_SIZE);
m_receive_curr = 0;
m_receive_end = 0;
m_unknown_0x6c = 0;
m_unknown_0x70 = 0xf;
m_unknown_0x74 = 0;
memset(m_transmit_buf, 0, BUFFER_SIZE);
m_transmit_curr = 0;
m_transmit_end = 0;
memset(m_cmdbuf, 0, sizeof(uint32_t) * 16);
m_curr_port = 0;
m_cmd_size = 0;
m_cmd_length = 0;
memset(m_databuf, 0, sizeof(uint32_t) * 4 * 2);
m_target_device = 0;
}
READ32_MEMBER(iop_sio2_device::read)
@ -50,8 +73,28 @@ READ32_MEMBER(iop_sio2_device::read)
uint32_t ret = 0;
switch (offset)
{
case 0x64/4:
ret = receive();
//logerror("%s: read: FIFO RECV %08x & %08x\n", machine().describe_context(), ret, mem_mask);
break;
case 0x68/4: // Control?
logerror("%s: read: CTRL %08x & %08x\n", machine().describe_context(), ret, mem_mask);
ret = m_ctrl;
//logerror("%s: read: CTRL %08x & %08x\n", machine().describe_context(), ret, mem_mask);
break;
case 0x6c/4:
ret = m_unknown_0x6c;
//logerror("%s: read: Unknown 0x6c (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x70/4:
ret = m_unknown_0x70;
//logerror("%s: read: Unknown 0x70 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x74/4:
ret = m_unknown_0x74;
//logerror("%s: read: Unknown 0x74 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x80/4:
// Unknown. Case is here to prevent log spam.
break;
default:
logerror("%s: read: Unknown offset %08x & %08x\n", machine().describe_context(), 0x1f808200 + (offset << 2), mem_mask);
@ -64,39 +107,203 @@ WRITE32_MEMBER(iop_sio2_device::write)
{
switch (offset)
{
case 0x00/4: case 0x04/4: case 0x08/4: case 0x0c/4: case 0x10/4: case 0x14/4: case 0x18/4: case 0x1c/4:
case 0x20/4: case 0x24/4: case 0x28/4: case 0x2c/4: case 0x30/4: case 0x34/4: case 0x38/4: case 0x3c/4:
//logerror("%s: write: CMDBUF[%d] = %08x & %08x\n", machine().describe_context(), offset, data, mem_mask);
COMBINE_DATA(&m_cmdbuf[offset]);
break;
case 0x40/4: case 0x44/4:
//logerror("%s: write: DATABUF[0][%d] = %08x & %08x\n", machine().describe_context(), offset - 0x40/4, data, mem_mask);
COMBINE_DATA(&m_databuf[0][offset - 0x40/4]);
break;
case 0x48/4: case 0x4c/4:
//logerror("%s: write: DATABUF[1][%d] = %08x & %08x\n", machine().describe_context(), offset - 0x48/4, data, mem_mask);
COMBINE_DATA(&m_databuf[1][offset - 0x48/4]);
break;
case 0x50/4: case 0x54/4:
//logerror("%s: write: DATABUF[2][%d] = %08x & %08x\n", machine().describe_context(), offset - 0x50/4, data, mem_mask);
COMBINE_DATA(&m_databuf[2][offset - 0x50/4]);
break;
case 0x58/4: case 0x5c/4:
//logerror("%s: write: DATABUF[3][%d] = %08x & %08x\n", machine().describe_context(), offset - 0x58/4, data, mem_mask);
COMBINE_DATA(&m_databuf[3][offset - 0x58/4]);
break;
case 0x60/4:
//logerror("%s: write: XMIT %08x & %08x\n", machine().describe_context(), data, mem_mask);
transmit_to_device_hack((uint8_t)data);
break;
case 0x68/4: // Control?
{
uint32_t old_ctrl = m_ctrl;
m_ctrl = data & CTRL_IRQ;
if (old_ctrl != m_ctrl && (m_ctrl & CTRL_IRQ))
//logerror("%s: write: Control? %08x & %08x\n", machine().describe_context(), data, mem_mask);
//uint32_t old_ctrl = m_ctrl;
m_ctrl = data & ~CTRL_IRQ;
if (data & CTRL_IRQ)
{
m_intc->raise_interrupt(iop_intc_device::INT_SIO2);
}
else
{
m_curr_port = 0;
m_cmd_size = 0;
m_cmd_length = 0;
m_end_byte = 0;
m_curr_byte = 0;
m_target_device = 0;
}
break;
}
case 0x80/4:
// Unknown. Case is here to prevent log spam.
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()
uint8_t iop_sio2_device::receive()
{
if (m_transmit_curr == m_transmit_end)
if (m_curr_byte >= m_end_byte)
{
//logerror("D:%d == E:%d, returning 0\n", m_curr_byte, m_end_byte);
return 0;
}
uint8_t ret = m_transmit_buf[m_transmit_curr];
m_transmit_curr = (m_transmit_curr + 1) & (BUFFER_SIZE-1);
const uint8_t ret = m_buffer[m_curr_byte];
//logerror("buf[%d] = %02x\n", m_curr_byte, ret);
m_curr_byte++;
if (m_curr_byte >= m_end_byte)
{
//logerror("Reached end of buffer, resetting to 0\n");
m_curr_byte = 0;
m_end_byte = 0;
}
return ret;
}
void iop_sio2_device::receive(uint8_t data)
void iop_sio2_device::transmit(uint8_t data)
{
if (m_receive_end >= BUFFER_SIZE)
//logerror("%s: Transmitting: %02x\n", machine().describe_context(), data);
if (!m_cmd_size && m_cmdbuf[m_curr_port])
{
m_cmd_size = (m_cmdbuf[m_curr_port++] & 0x0001ff00) >> 8;
m_cmd_length = m_cmd_size;
}
// TODO: Transmit serially to actual slot device at 250kHz-2MHz as needed
transmit_to_device_hack(data);
}
ps2_pad_device* iop_sio2_device::pad(uint8_t port)
{
return (port == 0) ? m_pad0.target() : m_pad1.target();
}
TIMER_CALLBACK_MEMBER(iop_sio2_device::response_timer)
{
if (param < 2)
{
pad(param)->process_fifos();
while (pad(param)->xmit_fifo_depth() && m_end_byte < BUFFER_SIZE)
{
receive_from_device_hack(pad(param)->xmit_fifo_pop());
}
}
else
{
}
}
void iop_sio2_device::transmit_to_device_hack(uint8_t data)
{
if (m_target_device == 0)
{
select_device_hack(data);
}
//bool cmd_complete = false;
if (m_cmd_size)
{
m_cmd_size--;
if (!m_cmd_size)
{
//cmd_complete = true;
}
}
switch (m_target_device)
{
case ps2_pad_device::SIO_DEVICE_ID:
m_unknown_0x6c = 0x0001d100; // TODO: As above
receive_from_device_hack(0);
/*m_unknown_0x6c = 0x00001100; // TODO: What do these bits mean and why does the code expect them?
pad(m_curr_port)->recv_fifo_push(data);
if (!m_cmd_size)
{
m_response_timer->adjust(attotime::from_ticks(8*pad(m_curr_port)->xmit_fifo_depth(), 250'000), m_curr_port);
m_curr_port++;
}*/
break;
case ps2_mc_device::SIO_DEVICE_ID:
/*if (m_cmd_size || cmd_complete)
{
logerror("Pushing %02x to memory card, m_cmd_size is %d\n", data, m_cmd_size);
m_mc0->recv_fifo_push(data);
}
if (cmd_complete)
{
logerror("Command is complete, processing fifos\n");
m_unknown_0x6c = 0x00001100;
m_mc0->process_fifos();
while (m_mc0->xmit_fifo_depth() && m_end_byte < BUFFER_SIZE)
{
logerror("xmit fifo is %d, end byte is %d\n", m_mc0->xmit_fifo_depth(), m_end_byte);
receive_from_device_hack(m_mc0->xmit_fifo_pop());
}
m_unknown_0x74 = m_cmd_length;
}*/
m_unknown_0x6c = 0x0001d100; // TODO: As above
receive_from_device_hack(0);
break;
default:
m_unknown_0x6c = 0x0001d100; // TODO: As above
receive_from_device_hack(0);
logerror("%s: Unknown device selected, can't write data %02x\n", machine().describe_context(), data);
break;
}
}
void iop_sio2_device::select_device_hack(uint8_t data)
{
switch (data)
{
case ps2_pad_device::SIO_DEVICE_ID:
m_target_device = data;
// TODO: Select transmit frequency, etc.
//logerror("%s: Selecting transmit device: Pad\n", machine().describe_context());
break;
case ps2_mc_device::SIO_DEVICE_ID:
m_target_device = data;
//logerror("%s: Selecting transmit device: Memcard\n", machine().describe_context());
break;
default:
m_target_device = 0xff;
//logerror("%s: Selecting transmit device: Unknown\n", machine().describe_context());
break;
}
}
void iop_sio2_device::receive_from_device_hack(uint8_t data)
{
if (m_end_byte == BUFFER_SIZE)
{
return;
}
m_receive_buf[m_receive_end] = data;
m_receive_end++;
m_buffer[m_end_byte++] = data;
//logerror("%s: Receiving byte from device (new top: %d)\n", machine().describe_context(), m_end_byte);
}

View File

@ -16,15 +16,20 @@
#include "emu.h"
#include "iopintc.h"
#include "ps2pad.h"
#include "ps2mc.h"
class iop_sio2_device : public device_t
{
public:
template <typename T>
iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&intc_tag)
template <typename T, typename U, typename V, typename W>
iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&intc_tag, U &&pad0_tag, V &&pad1_tag, W &&mc0_tag)
: iop_sio2_device(mconfig, tag, owner, (uint32_t)0)
{
m_intc.set_tag(std::forward<T>(intc_tag));
m_pad0.set_tag(std::forward<U>(pad0_tag));
m_pad1.set_tag(std::forward<V>(pad1_tag));
m_mc0.set_tag(std::forward<W>(mc0_tag));
}
iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -32,29 +37,51 @@ public:
DECLARE_READ32_MEMBER(read);
DECLARE_WRITE32_MEMBER(write);
void receive(uint8_t data);
uint8_t transmit();
void transmit(uint8_t data);
uint8_t receive();
void receive_from_device_hack(uint8_t data); // TODO: Turn me into a bus interface!
protected:
virtual void device_start() override;
virtual void device_reset() override;
enum
TIMER_CALLBACK_MEMBER(response_timer);
void select_device_hack(uint8_t data);
void transmit_to_device_hack(uint8_t data); // TODO: Turn me into a bus interface!
ps2_pad_device* pad(uint8_t port);
enum : uint32_t
{
CTRL_IRQ = 0x01,
};
required_device<iop_intc_device> m_intc;
required_device<ps2_pad_device> m_pad0;
required_device<ps2_pad_device> m_pad1;
required_device<ps2_mc_device> m_mc0;
// 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;
// HACK: Buffer size is a guess.
uint8_t m_buffer[512];
uint32_t m_curr_byte;
uint32_t m_end_byte;
uint32_t m_ctrl;
uint32_t m_unknown_0x6c; // Device status?
uint32_t m_unknown_0x70;
uint32_t m_unknown_0x74;
uint32_t m_cmdbuf[16];
uint32_t m_curr_port;
uint32_t m_cmd_size;
uint32_t m_cmd_length;
uint32_t m_databuf[4][2];
uint32_t m_target_device;
emu_timer *m_response_timer;
static const size_t BUFFER_SIZE;
};

View File

@ -21,6 +21,8 @@ ps2_dmac_device::ps2_dmac_device(const machine_config &mconfig, const char *tag,
, m_ee(*this, finder_base::DUMMY_TAG)
, m_ram(*this, finder_base::DUMMY_TAG)
, m_sif(*this, finder_base::DUMMY_TAG)
, m_gif(*this, finder_base::DUMMY_TAG)
, m_vif1(*this, finder_base::DUMMY_TAG)
, m_icount(0)
{
}
@ -91,6 +93,12 @@ void ps2_dmac_device::execute_run()
switch (m_last_serviced)
{
case VIF1:
transfer_vif1();
break;
case GIF:
transfer_gif();
break;
case SIF0:
transfer_sif0();
break;
@ -107,6 +115,97 @@ void ps2_dmac_device::execute_run()
}
}
void ps2_dmac_device::transfer_vif1()
{
if (m_mem_drain)
{
logerror("%s: transfer_vif1: Not yet implemented: memory drain bit. HACK: Disabling channel.\n", machine().describe_context());
transfer_finish(VIF1);
return;
}
channel_t &channel = m_channels[VIF1];
const uint32_t count = channel.quadword_count();
if (count)
{
//logerror("%s: DMAC VIF1 quadword count: %08x\n", machine().describe_context(), count);
uint32_t addr = channel.addr();
if (BIT(addr, 31))
addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
uint32_t words[4] = { 0, 0, 0, 0 };
for (int word = 0; word < 4; word++)
{
words[word] = space.read_dword(addr);
addr += 4;
}
m_vif1->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]);
channel.set_addr(channel.addr() + 0x10);
channel.set_quadword_count(count - 1);
}
else if (channel.end_tag())
{
logerror("%s: DMAC VIF1 end tag\n", machine().describe_context());
transfer_finish(VIF1);
}
else
{
logerror("%s: DMAC VIF1 following source tag\n", machine().describe_context());
uint32_t tag_addr = channel.tag_addr();
if (BIT(tag_addr, 31))
tag_addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
uint32_t words[4] = { 0, 0, 0, 0 };
for (int word = 0; word < 4; word++)
{
words[word] = space.read_dword(tag_addr);
tag_addr += 4;
}
m_vif1->tag_write(words);
follow_source_tag(VIF1);
}
}
void ps2_dmac_device::transfer_gif()
{
if (m_mem_drain)
{
logerror("%s: Not yet implemented: memory drain bit. HACK: Disabling channel.\n", machine().describe_context());
transfer_finish(GIF);
return;
}
channel_t &channel = m_channels[GIF];
const uint32_t count = channel.quadword_count();
if (count)
{
//logerror("%s: DMAC GIF quadword count: %08x\n", machine().describe_context(), count);
uint32_t addr = channel.addr();
if (BIT(addr, 31))
addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
uint32_t words[4] = { 0, 0, 0, 0 };
for (int word = 0; word < 4; word++)
{
words[word] = space.read_dword(addr);
addr += 4;
}
m_gif->write_path3(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]);
channel.set_addr(channel.addr() + 0x10);
channel.set_quadword_count(count - 1);
}
else if (channel.end_tag())
{
logerror("%s: DMAC GIF end tag\n", machine().describe_context());
transfer_finish(GIF);
}
else
{
logerror("%s: DMAC GIF following source tag\n", machine().describe_context());
follow_source_tag(GIF);
}
}
void ps2_dmac_device::transfer_sif0()
{
channel_t &channel = m_channels[SIF0];
@ -117,6 +216,8 @@ void ps2_dmac_device::transfer_sif0()
{
//logerror("%s: SIF0 depth is %d\n", machine().describe_context(), m_sif->fifo_depth(0));
uint32_t addr = channel.addr();
if (BIT(addr, 31))
addr -= 0x10000000;
for (int word = 0; word < 4; word++)
{
const uint32_t data = m_sif->fifo_pop(0);
@ -124,7 +225,7 @@ void ps2_dmac_device::transfer_sif0()
m_ee->space(AS_PROGRAM).write_dword(addr, data);
addr += 4;
}
channel.set_addr(addr);
channel.set_addr(channel.addr() + 0x10);
channel.set_quadword_count(count - 1);
//logerror("%s: SIF0 remaining count: %08x\n", machine().describe_context(), channel.quadword_count());
}
@ -163,6 +264,8 @@ void ps2_dmac_device::transfer_sif1()
if (m_sif->fifo_depth(1) < (ps2_sif_device::MAX_FIFO_DEPTH - 4))
{
uint32_t addr = channel.addr();
if (BIT(addr, 31))
addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
for (int word = 0; word < 4; word++)
{
@ -171,7 +274,7 @@ void ps2_dmac_device::transfer_sif1()
addr += 4;
m_sif->fifo_push(1, data);
}
channel.set_addr(addr);
channel.set_addr(channel.addr() + 0x10);
channel.set_quadword_count(count - 1);
}
}
@ -190,9 +293,12 @@ void ps2_dmac_device::transfer_sif1()
void ps2_dmac_device::follow_source_tag(uint32_t chan)
{
channel_t &channel = m_channels[chan];
const uint32_t tag_addr = channel.tag_addr() >> 3;
const uint64_t hi = m_ram[tag_addr];
const uint64_t lo = m_ram[tag_addr + 1];
uint32_t tag_addr = channel.tag_addr();
if (BIT(tag_addr, 31))
tag_addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
const uint64_t hi = space.read_qword(tag_addr);
const uint64_t lo = space.read_dword(tag_addr + 8);
const uint32_t tag = (uint32_t)hi;
const uint32_t addr = (uint32_t)(hi >> 32) & ~0xf;
logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
@ -204,17 +310,30 @@ void ps2_dmac_device::follow_source_tag(uint32_t chan)
switch (id)
{
case ID_CNT:
channel.set_addr(channel.tag_addr() + 0x10);
channel.set_tag_addr(channel.addr() + (channel.quadword_count() << 4));
break;
case ID_REFE:
channel.set_end_tag(true);
// Intentional fall-through
case ID_REF:
channel.set_addr(addr);
channel.set_tag_addr(channel.tag_addr() + 0x10);
break;
case ID_REFS:
// We don't handle stalls yet, just act the same as REF for now
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;
case ID_END:
channel.set_addr(channel.tag_addr() + 0x10);
channel.set_end_tag(true);
break;
default:
logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id);
break;
@ -281,6 +400,7 @@ WRITE32_MEMBER(ps2_dmac_device::write)
case 0: /* D_CTRL */
logerror("%s: dmac_w: D_CTRL = %08x & %08x\n", machine().describe_context(), data, mem_mask);
logerror("%s: ENABLE=%d MEM_DRAIN=%d\n", machine().describe_context(), BIT(data, 0), (data >> 2) & 3);
m_ctrl = data;
m_enabled = BIT(data, 0);
m_mem_drain = (data >> 2) & 3;
break;
@ -334,41 +454,49 @@ READ32_MEMBER(ps2_dmac_device::channel_r)
case 0x8050/8: /* D0_ASR1 */
logerror("%s: dmac_channel_r: D0_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x9000/8: /* D1_CHCR */
logerror("%s: dmac_channel_r: D1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0x9000/8: /* VIF1_CHCR */
ret = m_channels[VIF1].chcr();
//logerror("%s: dmac_channel_r: VIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x9010/8: /* D1_MADR */
logerror("%s: dmac_channel_r: D1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0x9010/8: /* VIF1_MADR */
ret = m_channels[VIF1].addr();
logerror("%s: dmac_channel_r: VIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x9020/8: /* D1_QWC */
logerror("%s: dmac_channel_r: D1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0x9020/8: /* VIF1_QWC */
ret = m_channels[VIF1].quadword_count();
logerror("%s: dmac_channel_r: VIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x9030/8: /* D1_TADR */
logerror("%s: dmac_channel_r: D1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0x9030/8: /* VIF1_TADR */
ret = m_channels[VIF1].tag_addr();
logerror("%s: dmac_channel_r: VIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x9040/8: /* D1_ASR0 */
logerror("%s: dmac_channel_r: D1_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0x9040/8: /* VIF1_ASR0 */
logerror("%s: dmac_channel_r: VIF1_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0x9050/8: /* D1_ASR1 */
logerror("%s: dmac_channel_r: D1_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0x9050/8: /* VIF1_ASR1 */
logerror("%s: dmac_channel_r: VIF1_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xa000/8: /* D2_CHCR */
logerror("%s: dmac_channel_r: D2_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0xa000/8: /* GIF_CHCR */
ret = m_channels[GIF].chcr();
//logerror("%s: dmac_channel_r: GIF_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xa010/8: /* D2_MADR */
logerror("%s: dmac_channel_r: D2_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0xa010/8: /* GIF_MADR */
ret = m_channels[GIF].addr();
logerror("%s: dmac_channel_r: GIF_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xa020/8: /* D2_QWC */
logerror("%s: dmac_channel_r: D2_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0xa020/8: /* GIF_QWC */
ret = m_channels[GIF].quadword_count();
logerror("%s: dmac_channel_r: GIF_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xa030/8: /* D2_TADR */
logerror("%s: dmac_channel_r: D2_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0xa030/8: /* GIF_TADR */
ret = m_channels[GIF].tag_addr();
logerror("%s: dmac_channel_r: GIF_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xa040/8: /* D2_ASR0 */
logerror("%s: dmac_channel_r: D2_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0xa040/8: /* GIF_ASR0 */
logerror("%s: dmac_channel_r: GIF_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xa050/8: /* D2_ASR1 */
logerror("%s: dmac_channel_r: D2_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
case 0xa050/8: /* GIF_ASR1 */
logerror("%s: dmac_channel_r: GIF_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xb000/8: /* D3_CHCR */
logerror("%s: dmac_channel_r: D3_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
@ -486,41 +614,51 @@ WRITE32_MEMBER(ps2_dmac_device::channel_w)
case 0x8050/8: /* D0_ASR1 */
logerror("%s: dmac_channel_w: D0_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0x9000/8: /* D1_CHCR */
logerror("%s: dmac_channel_w: D1_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0x9000/8: /* VIF1_CHCR */
logerror("%s: dmac_channel_w: VIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 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);
m_channels[VIF1].set_chcr(data);
break;
case 0x9010/8: /* D1_MADR */
logerror("%s: dmac_channel_w: D1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0x9010/8: /* VIF1_MADR */
logerror("%s: dmac_channel_w: VIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[VIF1].set_addr(data);
break;
case 0x9020/8: /* D1_QWC */
logerror("%s: dmac_channel_w: D1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0x9020/8: /* VIF1_QWC */
logerror("%s: dmac_channel_w: VIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[VIF1].set_quadword_count(data);
break;
case 0x9030/8: /* D1_TADR */
logerror("%s: dmac_channel_w: D1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0x9030/8: /* VIF1_TADR */
logerror("%s: dmac_channel_w: VIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[VIF1].set_tag_addr(data);
break;
case 0x9040/8: /* D1_ASR0 */
logerror("%s: dmac_channel_w: D1_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0x9040/8: /* VIF1_ASR0 */
logerror("%s: dmac_channel_w: VIF1_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0x9050/8: /* D1_ASR1 */
logerror("%s: dmac_channel_w: D1_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0x9050/8: /* VIF1_ASR1 */
logerror("%s: dmac_channel_w: VIF1_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0xa000/8: /* D2_CHCR */
logerror("%s: dmac_channel_w: D2_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0xa000/8: /* GIF_CHCR */
logerror("%s: dmac_channel_w: GIF_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 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);
m_channels[GIF].set_chcr(data);
break;
case 0xa010/8: /* D2_MADR */
logerror("%s: dmac_channel_w: D2_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0xa010/8: /* GIF_MADR */
logerror("%s: dmac_channel_w: GIF_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[GIF].set_addr(data);
break;
case 0xa020/8: /* D2_QWC */
logerror("%s: dmac_channel_w: D2_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0xa020/8: /* GIF_QWC */
logerror("%s: dmac_channel_w: GIF_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[GIF].set_quadword_count(data);
break;
case 0xa030/8: /* D2_TADR */
logerror("%s: dmac_channel_w: D2_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0xa030/8: /* GIF_TADR */
logerror("%s: dmac_channel_w: GIF_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[GIF].set_tag_addr(data);
break;
case 0xa040/8: /* D2_ASR0 */
logerror("%s: dmac_channel_w: D2_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0xa040/8: /* GIF_ASR0 */
logerror("%s: dmac_channel_w: GIF_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0xa050/8: /* D2_ASR1 */
logerror("%s: dmac_channel_w: D2_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
case 0xa050/8: /* GIF_ASR1 */
logerror("%s: dmac_channel_w: GIF_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0xb000/8: /* D3_CHCR */
logerror("%s: dmac_channel_w: D3_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);

View File

@ -15,17 +15,21 @@
#pragma once
#include "emu.h"
#include "ps2gif.h"
#include "ps2vif1.h"
class ps2_dmac_device : public device_t, public device_execute_interface
{
public:
template <typename T, typename U, typename V>
ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&ee_tag, U &&ram_tag, V &&sif_tag)
template <typename T, typename U, typename V, typename W, typename X>
ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&ee_tag, U &&ram_tag, V &&sif_tag, W &&gif_tag, X &&vif1_tag)
: ps2_dmac_device(mconfig, tag, owner, clock)
{
m_ee.set_tag(std::forward<T>(ee_tag));
m_ram.set_tag(std::forward<U>(ram_tag));
m_sif.set_tag(std::forward<V>(sif_tag));
m_gif.set_tag(std::forward<W>(gif_tag));
m_vif1.set_tag(std::forward<X>(vif1_tag));
}
ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -113,6 +117,8 @@ protected:
uint32_t m_tag_addr;
};
void transfer_vif1();
void transfer_gif();
void transfer_sif0();
void transfer_sif1();
void transfer_finish(uint32_t chan);
@ -122,6 +128,8 @@ protected:
required_device<cpu_device> m_ee;
required_shared_ptr<uint64_t> m_ram;
required_device<ps2_sif_device> m_sif;
required_device<ps2_gif_device> m_gif;
required_device<ps2_vif1_device> m_vif1;
int m_icount;

256
src/mame/machine/ps2gif.cpp Normal file
View File

@ -0,0 +1,256 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 GS interface (GIF) device skeleton
*
* To Do:
* Everything
*
*/
#include "ps2gif.h"
DEFINE_DEVICE_TYPE(SONYPS2_GIF, ps2_gif_device, "ps2gif", "Playstation 2 GIF")
ps2_gif_device::ps2_gif_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SONYPS2_GIF, tag, owner, clock)
, m_gs(*this, finder_base::DUMMY_TAG)
{
}
ps2_gif_device::tag_t::tag_t(const uint64_t hi, const uint64_t lo)
: m_nloop(lo & 0x7fffULL)
, m_end((lo >> 15) & 1)
, m_prim_enable((lo >> 46) & 1)
, m_prim_output(false)
, m_prim((lo >> 47) & 0x7ff)
, m_format((format_t)((lo >> 58) & 3))
, m_reg_count((uint8_t)(lo >> 60))
, m_curr_reg(0)
{
if (!m_reg_count)
m_reg_count = 16;
for (uint32_t shift = 0, index = 0; shift < 64; shift += 4, index++)
{
m_regs[index] = (uint8_t)(hi >> shift) & 0xf;
}
m_words[0] = (uint32_t)(hi >> 32);
m_words[1] = (uint32_t)hi;
m_words[2] = (uint32_t)(lo >> 32);
m_words[3] = (uint32_t)lo;
}
void ps2_gif_device::device_start()
{
save_item(NAME(m_ctrl));
save_item(NAME(m_mode));
save_item(NAME(m_stat));
save_item(NAME(m_cnt));
save_item(NAME(m_p3cnt));
save_item(NAME(m_p3tag));
save_item(NAME(m_p3mask));
// TODO: Save current tag
}
void ps2_gif_device::device_reset()
{
gif_reset();
}
void ps2_gif_device::gif_reset()
{
m_ctrl = CTRL_RST;
m_mode = 0;
m_stat = 0;
m_cnt = 0;
m_p3cnt = 0;
m_p3tag = 0;
m_p3mask = false;
m_current_tag = tag_t();
}
READ32_MEMBER(ps2_gif_device::read)
{
uint32_t ret = 0;
switch (offset)
{
case 0x00/4: // GIF_CTRL
if (BIT(m_ctrl, 3))
{
ret = m_ctrl;
logerror("%s: Read: GIF_CTRL (%08x)\n", machine().describe_context(), ret);
}
else
{
logerror("%s: Read: GIF_CTRL (00000000) (read-only; actual value %08x)\n", machine().describe_context(), m_ctrl);
}
break;
case 0x10/4: // GIF_MODE
ret = m_mode;
logerror("%s: Read: GIF_MODE (00000000) (read-only; actual value %08x)\n", machine().describe_context(), ret);
break;
case 0x20/4: // GIF_STAT
ret = m_stat;
logerror("%s: Read: GIF_STAT (%08x)\n", machine().describe_context(), ret);
break;
case 0x40/4: // GIF_TAG0
ret = m_current_tag.word(0);
logerror("%s: Read: GIF_TAG0 (%08x)\n", machine().describe_context(), ret);
break;
case 0x50/4: // GIF_TAG1
ret = m_current_tag.word(1);
logerror("%s: Read: GIF_TAG1 (%08x)\n", machine().describe_context(), ret);
break;
case 0x60/4: // GIF_TAG2
ret = m_current_tag.word(2);
logerror("%s: Read: GIF_TAG2 (%08x)\n", machine().describe_context(), ret);
break;
case 0x70/4: // GIF_TAG3
ret = m_current_tag.word(0);
logerror("%s: Read: GIF_TAG3 (%08x)\n", machine().describe_context(), ret);
break;
case 0x80/4: // GIF_CNT
ret = m_cnt;
logerror("%s: Read: GIF_CNT (%08x)\n", machine().describe_context(), ret);
break;
case 0x90/4: // GIF_P3CNT
ret = m_p3cnt;
logerror("%s: Read: GIF_P3CNT (%08x)\n", machine().describe_context(), ret);
break;
case 0xa0/4: // GIF_P3TAG
ret = m_p3tag;
logerror("%s: Read: GIF_P3TAG (%08x)\n", machine().describe_context(), ret);
break;
default:
logerror("%s: Read: Unknown %08x\n", machine().describe_context(), 0x10003000 + (offset << 2));
break;
}
return ret;
}
WRITE32_MEMBER(ps2_gif_device::write)
{
switch (offset)
{
case 0x00/4: // GIF_CTRL
m_ctrl = data;
if (BIT(data, 0))
{
gif_reset();
}
logerror("%s: Write: GIF_CTRL = %08x: STOP=%d, RESET=%d\n", machine().describe_context(), data, BIT(data, 3), BIT(data, 0));
break;
case 0x10/4: // GIF_MODE
m_mode = data;
logerror("%s: Write: GIF_MODE = %08x: IMT=%s, MASK=%s\n", machine().describe_context(), data, BIT(data, 2) ? "Intermittent" : "Continuous", BIT(data, 0) ? "Yes" : "No");
break;
case 0x20/4: // GIF_STAT
logerror("%s: Write: GIF_STAT = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0x40/4: // GIF_TAG0
logerror("%s: Write: GIF_TAG0 = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0x50/4: // GIF_TAG1
logerror("%s: Write: GIF_TAG1 = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0x60/4: // GIF_TAG2
logerror("%s: Write: GIF_TAG2 = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0x70/4: // GIF_TAG3
logerror("%s: Write: GIF_TAG3 = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0x80/4: // GIF_CNT
logerror("%s: Write: GIF_CNT = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0x90/4: // GIF_P3CNT
logerror("%s: Write: GIF_P3CNT = %08x (ignored)\n", machine().describe_context(), data);
break;
case 0xa0/4: // GIF_P3TAG
logerror("%s: Write: GIF_P3TAG = %08x (ignored)\n", machine().describe_context(), data);
break;
default:
logerror("%s: Write: Unknown %08x = %08x\n", machine().describe_context(), 0x10003000 + (offset << 2), data);
break;
}
}
void ps2_gif_device::write_path3(uint64_t hi, uint64_t lo)
{
if (m_p3mask)
{
return;
}
if (!m_current_tag.valid())
{
m_current_tag = tag_t(hi, lo);
return;
}
switch (m_current_tag.format())
{
case tag_t::format_t::FMT_PACKED:
if (m_current_tag.is_prim() && !m_current_tag.is_prim_output())
{
m_current_tag.set_prim_output();
logerror("%s: PATH3: PACKED: Not yet implemented: PRIM\n", machine().describe_context());
}
else if (m_current_tag.nloop())
{
const uint8_t reg = m_current_tag.reg();
m_gs->write_packed(reg, hi, lo);
m_current_tag.next_reg();
}
break;
case tag_t::format_t::FMT_REGLIST:
logerror("%s: PATH3: Not yet implemented: REGLIST (%08x%08x%08x%08x)\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
m_current_tag.loop();
break;
default:
//logerror("%s: PATH3: Not yet implemented: IMAGE (%08x%08x%08x%08x)\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
m_gs->regs_w(machine().dummy_space(), 0x54, lo);
m_gs->regs_w(machine().dummy_space(), 0x54, hi);
m_current_tag.loop();
break;
}
}
void ps2_gif_device::tag_t::next_reg()
{
m_curr_reg++;
if (m_curr_reg == m_reg_count)
{
m_curr_reg = 0;
loop();
}
}
void ps2_gif_device::set_path3_mask(bool masked)
{
m_p3mask = masked;
}

109
src/mame/machine/ps2gif.h Normal file
View File

@ -0,0 +1,109 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 GS Interface (GIF) device skeleton
*
* To Do:
* Everything
*
*/
#ifndef MAME_MACHINE_PS2GIF_H
#define MAME_MACHINE_PS2GIF_H
#pragma once
#include "emu.h"
#include "video/ps2gs.h"
class ps2_gif_device : public device_t
{
public:
template <typename T>
ps2_gif_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&gs_tag)
: ps2_gif_device(mconfig, tag, owner, (uint32_t)0)
{
m_gs.set_tag(std::forward<T>(gs_tag));
}
ps2_gif_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_READ32_MEMBER(read);
DECLARE_WRITE32_MEMBER(write);
void write_path3(uint64_t hi, uint64_t lo);
void set_path3_mask(bool masked);
protected:
virtual void device_start() override;
virtual void device_reset() override;
void gif_reset();
class tag_t
{
public:
tag_t() : m_nloop(0), m_end(false), m_prim_enable(false), m_prim_output(false), m_prim(0), m_format(FMT_DISABLE), m_reg_count(0), m_curr_reg(0)
{
memset(m_regs, 0, 16);
memset(m_words, 0, sizeof(uint32_t) * 4);
}
tag_t(uint64_t lo, uint64_t hi);
enum format_t : uint8_t
{
FMT_PACKED = 0,
FMT_REGLIST,
FMT_IMAGE,
FMT_DISABLE
};
bool valid() const { return m_nloop != 0; }
uint16_t nloop() const { return m_nloop; }
bool end() const { return m_end; }
bool is_prim() const { return m_prim_enable; }
bool is_prim_output() const { return m_prim_output; }
void set_prim_output() { m_prim_output = true; }
uint16_t prim() const { return m_prim; }
format_t format() const { return m_format; }
uint32_t word(offs_t index) const { return m_words[index]; }
uint32_t reg() const { return m_regs[m_curr_reg]; }
void loop() { m_nloop--; }
void next_reg();
protected:
uint16_t m_nloop;
bool m_end;
bool m_prim_enable;
bool m_prim_output;
uint16_t m_prim;
format_t m_format;
uint8_t m_reg_count;
uint8_t m_curr_reg;
uint8_t m_regs[16];
uint32_t m_words[4];
};
enum : uint32_t
{
CTRL_RST = (1 << 0),
CTRL_PSE = (1 << 3)
};
required_device<ps2_gs_device> m_gs;
uint32_t m_ctrl;
uint32_t m_mode;
uint32_t m_stat;
tag_t m_current_tag; // tag0..3
uint32_t m_cnt;
uint32_t m_p3cnt;
uint32_t m_p3tag;
bool m_p3mask;
};
DECLARE_DEVICE_TYPE(SONYPS2_GIF, ps2_gif_device)
#endif // MAME_MACHINE_PS2GIF_H

View File

@ -67,4 +67,4 @@ protected:
DECLARE_DEVICE_TYPE(SONYPS2_INTC, ps2_intc_device)
#endif // MAME_MACHINE_PS2SIF_H
#endif // MAME_MACHINE_PS2INTC_H

197
src/mame/machine/ps2mc.cpp Normal file
View File

@ -0,0 +1,197 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 memory card skeleton
*
* To Do:
* Everything
*
*/
#include "ps2mc.h"
/*static*/ const size_t ps2_mc_device::BUFFER_SIZE = 512; // Total guess
/*static*/ const uint8_t ps2_mc_device::DEFAULT_TERMINATOR = 0x55;
DEFINE_DEVICE_TYPE(SONYPS2_MC, ps2_mc_device, "ps2mc", "PlayStation 2 Memory Card")
ps2_mc_device::ps2_mc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SONYPS2_MC, tag, owner, clock)
{
}
void ps2_mc_device::device_start()
{
save_item(NAME(m_recv_buf));
save_item(NAME(m_xmit_buf));
save_item(NAME(m_curr_recv));
save_item(NAME(m_curr_xmit));
save_item(NAME(m_end_recv));
save_item(NAME(m_end_xmit));
save_item(NAME(m_cmd));
save_item(NAME(m_cmd_size));
save_item(NAME(m_terminator));
save_item(NAME(m_status));
}
void ps2_mc_device::device_reset()
{
memset(m_recv_buf, 0, BUFFER_SIZE);
memset(m_xmit_buf, 0, BUFFER_SIZE);
m_curr_recv = 0;
m_curr_xmit = 0;
m_end_recv = 0;
m_end_xmit = 0;
m_cmd = 0;
m_cmd_size = 0;
m_terminator = DEFAULT_TERMINATOR;
m_status = 0;
}
void ps2_mc_device::recv_fifo_push(uint8_t data)
{
if (m_end_recv >= BUFFER_SIZE)
{
return;
}
m_recv_buf[m_end_recv++] = data;
//logerror("%s: Receiving %02x from SIO2, new top: %d\n", machine().describe_context(), data, m_end_recv);
}
void ps2_mc_device::xmit_fifo_push(uint8_t data)
{
if (m_end_xmit >= BUFFER_SIZE)
{
return;
}
//logerror("%s: Pushing %02x onto transmit FIFO\n", machine().describe_context(), data);
m_xmit_buf[m_end_xmit++] = data;
}
uint8_t ps2_mc_device::xmit_fifo_pop()
{
uint8_t ret = 0;
if (m_curr_xmit < m_end_xmit)
{
ret = m_xmit_buf[m_curr_xmit++];
}
if (m_curr_xmit >= m_end_xmit)
{
m_curr_xmit = 0;
m_end_xmit = 0;
}
return ret;
}
uint8_t ps2_mc_device::recv_fifo_pop()
{
uint8_t ret = 0;
if (m_curr_recv < m_end_recv)
{
ret = m_recv_buf[m_curr_recv++];
}
if (m_curr_recv >= m_end_recv)
{
m_curr_recv = 0;
m_end_recv = 0;
}
//logerror("recv_fifo_pop %02x, %d/%d\n", ret, m_curr_recv, m_end_recv);
return ret;
}
void ps2_mc_device::process_fifos()
{
m_status = 0;
m_cmd_size = 0;
while (recv_fifo_depth())
{
const uint8_t data = recv_fifo_pop();
m_cmd_size++;
if (m_cmd_size == 1)
{
if (data == SIO_DEVICE_ID)
{
xmit_fifo_push(0x2b);
}
else
{
logerror("%s: Unknkown command byte 1: %02x\n", machine().describe_context(), data);
}
}
else if (m_cmd_size == 2)
{
process_command(data);
}
}
m_curr_recv = 0;
m_end_recv = 0;
}
void ps2_mc_device::process_command(uint8_t data)
{
m_cmd = data;
switch (m_cmd)
{
case CMD_UNKNOWN_F3:
//logerror("%s: MC command: Unknown 0xf3\n", machine().describe_context());
cmd_init();
m_status = 0;
break;
case CMD_INIT:
//logerror("%s: MC command: Init (%02x)\n", machine().describe_context(), m_cmd);
cmd_init();
break;
case CMD_GET_TERM:
//logerror("%s: MC command: Get Terminator\n", machine().describe_context());
cmd_get_term();
break;
default:
logerror("%s: Unknown MC command: %02x\n", machine().describe_context(), m_cmd);
break;
}
}
void ps2_mc_device::cmd_init()
{
while (recv_fifo_depth())
{
recv_fifo_pop();
if (m_cmd_size == 2)
{
m_status = 0x8c;
xmit_fifo_push(m_terminator);
}
m_cmd_size++;
}
}
void ps2_mc_device::cmd_get_term()
{
while (recv_fifo_depth())
{
recv_fifo_pop();
if (m_cmd_size == 2)
{
m_status = 0x8b;
xmit_fifo_push(m_terminator);
xmit_fifo_push(0x55);
}
m_cmd_size++;
}
}

75
src/mame/machine/ps2mc.h Normal file
View File

@ -0,0 +1,75 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 memory card skeleton
*
* To Do:
* Everything
*
*/
#ifndef MAME_MACHINE_PS2MC_H
#define MAME_MACHINE_PS2MC_H
#pragma once
#include "emu.h"
class ps2_mc_device : public device_t
{
public:
ps2_mc_device(const machine_config &mconfig, const char *tag, device_t *owner)
: ps2_mc_device(mconfig, tag, owner, (uint32_t)0)
{
}
ps2_mc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void recv_fifo_push(uint8_t data); // TODO: Turn me into a bus interface!
uint8_t xmit_fifo_pop();
uint8_t xmit_fifo_depth() const { return m_end_xmit - m_curr_xmit; }
void process_fifos();
uint8_t status() const { return m_status; }
static const uint8_t SIO_DEVICE_ID = 0x81;
protected:
virtual void device_start() override;
virtual void device_reset() override;
void xmit_fifo_push(uint8_t data);
uint8_t recv_fifo_pop();
uint8_t recv_fifo_depth() const { return m_end_recv - m_curr_recv; }
void process_command(uint8_t data);
void cmd_init();
void cmd_get_term();
enum : uint8_t
{
CMD_INIT = 0x11,
CMD_GET_TERM = 0x28,
CMD_UNKNOWN_F3 = 0xf3,
};
uint8_t m_recv_buf[512]; // Buffer size is a guess
uint8_t m_xmit_buf[512];
uint32_t m_curr_recv;
uint32_t m_curr_xmit;
uint32_t m_end_recv;
uint32_t m_end_xmit;
uint8_t m_cmd;
uint32_t m_cmd_size;
uint8_t m_terminator;
uint8_t m_status;
static const size_t BUFFER_SIZE;
static const uint8_t DEFAULT_TERMINATOR;
};
DECLARE_DEVICE_TYPE(SONYPS2_MC, ps2_mc_device)
#endif // MAME_MACHINE_PS2MC_H

328
src/mame/machine/ps2pad.cpp Normal file
View File

@ -0,0 +1,328 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 DualShock 2 ('pad') device skeleton
*
* To Do:
* Everything
*
*/
#include "ps2pad.h"
/*static*/ const size_t ps2_pad_device::BUFFER_SIZE = 64; // Total guess
DEFINE_DEVICE_TYPE(SONYPS2_PAD, ps2_pad_device, "ps2pad", "DualShock 2")
ps2_pad_device::ps2_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SONYPS2_PAD, tag, owner, clock)
{
}
void ps2_pad_device::device_start()
{
save_item(NAME(m_recv_buf));
save_item(NAME(m_xmit_buf));
save_item(NAME(m_curr_recv));
save_item(NAME(m_curr_xmit));
save_item(NAME(m_end_recv));
save_item(NAME(m_end_xmit));
save_item(NAME(m_cmd));
save_item(NAME(m_cmd_size));
save_item(NAME(m_configuring));
}
void ps2_pad_device::device_reset()
{
memset(m_recv_buf, 0, BUFFER_SIZE);
memset(m_xmit_buf, 0, BUFFER_SIZE);
m_curr_recv = 0;
m_curr_xmit = 0;
m_end_recv = 0;
m_end_xmit = 0;
m_cmd = 0;
m_cmd_size = 0;
m_configuring = false;
}
void ps2_pad_device::recv_fifo_push(uint8_t data)
{
if (m_end_recv >= BUFFER_SIZE)
{
return;
}
//logerror("%s: Receiving %02x from SIO2\n", machine().describe_context(), data);
m_recv_buf[m_end_recv++] = data;
}
void ps2_pad_device::xmit_fifo_push(uint8_t data)
{
if (m_end_xmit >= BUFFER_SIZE)
{
return;
}
//logerror("%s: Pushing %02x onto transmit FIFO\n", machine().describe_context(), data);
m_xmit_buf[m_end_xmit++] = data;
}
uint8_t ps2_pad_device::xmit_fifo_pop()
{
uint8_t ret = 0;
if (m_curr_xmit < m_end_xmit)
{
ret = m_xmit_buf[m_curr_xmit++];
}
if (m_curr_xmit == m_end_xmit)
{
m_curr_xmit = 0;
m_end_xmit = 0;
}
return ret;
}
uint8_t ps2_pad_device::recv_fifo_pop()
{
uint8_t ret = 0;
if (m_curr_recv < m_end_recv)
{
ret = m_recv_buf[m_curr_recv++];
}
if (m_curr_recv == m_end_recv)
{
m_curr_recv = 0;
m_end_recv = 0;
}
return ret;
}
void ps2_pad_device::process_fifos()
{
m_cmd_size = 0;
while (recv_fifo_depth())
{
const uint8_t data = recv_fifo_pop();
m_cmd_size++;
if (m_cmd_size == 1)
{
if (data == SIO_DEVICE_ID)
{
xmit_fifo_push(0xff);
}
else
{
logerror("%s: Unknkown command byte 1: %02x\n", machine().describe_context(), data);
}
}
else if (m_cmd_size == 2)
{
process_command(data);
}
}
m_curr_recv = 0;
m_end_recv = 0;
}
void ps2_pad_device::process_command(uint8_t data)
{
m_cmd = data;
switch (m_cmd)
{
case CMD_READ_BUTTONS:
//logerror("%s: Pad command: Read Buttons\n", machine().describe_context());
cmd_read_buttons();
break;
case CMD_CONFIG:
//logerror("%s: Pad command: Config\n", machine().describe_context());
cmd_config();
break;
case CMD_GET_MODEL:
//logerror("%s: Pad command: Get Model\n", machine().describe_context());
cmd_get_model();
break;
case CMD_GET_ACT:
//logerror("%s: Pad command: Get Act\n", machine().describe_context());
cmd_get_act();
break;
case CMD_GET_COMB:
//logerror("%s: Pad command: Get Comb\n", machine().describe_context());
cmd_get_comb();
break;
case CMD_GET_MODE:
//logerror("%s: Pad command: Get Mode\n", machine().describe_context());
cmd_get_comb();
break;
default:
logerror("%s: Unknown pad command: %02x, forcing idle\n", machine().describe_context(), m_cmd);
break;
}
}
void ps2_pad_device::cmd_read_buttons()
{
while (recv_fifo_depth())
{
recv_fifo_pop();
if (m_cmd_size == 2)
{
xmit_fifo_push(0x41);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
}
m_cmd_size++;
}
}
void ps2_pad_device::cmd_config()
{
if (m_configuring)
{
xmit_fifo_push(0xf3);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
return;
}
while (recv_fifo_depth())
{
const uint8_t data = recv_fifo_pop();
if (m_cmd_size == 2)
{
xmit_fifo_push(0x41);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
}
else if (m_cmd_size == 3)
{
m_configuring = BIT(data, 0);
//logerror("%s: Entering config mode? %c\n", machine().describe_context(), m_configuring ? 'Y' : 'N');
}
m_cmd_size++;
}
}
void ps2_pad_device::cmd_get_model()
{
while (recv_fifo_depth())
{
recv_fifo_pop();
if (m_cmd_size == 2)
{
xmit_fifo_push(0xf3);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x01);
xmit_fifo_push(0x02);
xmit_fifo_push(0x00);
xmit_fifo_push(0x02);
xmit_fifo_push(0x01);
xmit_fifo_push(0x00);
}
m_cmd_size++;
}
}
void ps2_pad_device::cmd_get_act()
{
while (recv_fifo_depth())
{
const uint8_t data = recv_fifo_pop();
if (m_cmd_size == 3)
{
xmit_fifo_push(0xf3);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x01);
if (data < 2)
{
xmit_fifo_push(0x01);
xmit_fifo_push(0x01);
xmit_fifo_push(0x14);
}
else
{
xmit_fifo_push(0x02);
xmit_fifo_push(0x00);
xmit_fifo_push(0x0a);
}
}
m_cmd_size++;
}
}
void ps2_pad_device::cmd_get_comb()
{
while (recv_fifo_depth())
{
recv_fifo_pop();
if (m_cmd_size == 2)
{
xmit_fifo_push(0xf3);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x02);
xmit_fifo_push(0x00);
xmit_fifo_push(0x01);
xmit_fifo_push(0x00);
}
m_cmd_size++;
}
}
void ps2_pad_device::cmd_get_mode()
{
while (recv_fifo_depth())
{
const uint8_t data = recv_fifo_pop();
if (m_cmd_size == 3)
{
xmit_fifo_push(0xf3);
xmit_fifo_push(0x5a);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
if (data < 2)
{
xmit_fifo_push(4 + data * 3);
}
else
{
xmit_fifo_push(0x00);
}
xmit_fifo_push(0x00);
xmit_fifo_push(0x00);
}
m_cmd_size++;
}
}

78
src/mame/machine/ps2pad.h Normal file
View File

@ -0,0 +1,78 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 DualShock 2 ('pad') device skeleton
*
* To Do:
* Everything
*
*/
#ifndef MAME_MACHINE_PS2PAD_H
#define MAME_MACHINE_PS2PAD_H
#pragma once
#include "emu.h"
class ps2_pad_device : public device_t
{
public:
ps2_pad_device(const machine_config &mconfig, const char *tag, device_t *owner)
: ps2_pad_device(mconfig, tag, owner, (uint32_t)0)
{
}
ps2_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void recv_fifo_push(uint8_t data); // TODO: Turn me into a bus interface!
uint8_t xmit_fifo_pop();
uint8_t xmit_fifo_depth() const { return m_end_xmit - m_curr_xmit; }
void process_fifos();
static const uint8_t SIO_DEVICE_ID = 0x01;
protected:
virtual void device_start() override;
virtual void device_reset() override;
void xmit_fifo_push(uint8_t data);
uint8_t recv_fifo_pop();
uint8_t recv_fifo_depth() const { return m_end_recv - m_curr_recv; }
void process_command(uint8_t data);
void cmd_read_buttons();
void cmd_config();
void cmd_get_model();
void cmd_get_act();
void cmd_get_comb();
void cmd_get_mode();
enum : uint8_t
{
CMD_READ_BUTTONS = 0x42,
CMD_CONFIG = 0x43,
CMD_GET_MODEL = 0x45,
CMD_GET_ACT = 0x46,
CMD_GET_COMB = 0x47,
CMD_GET_MODE = 0x4c,
};
uint8_t m_recv_buf[64]; // Buffer size is a guess
uint8_t m_xmit_buf[64];
uint8_t m_curr_recv;
uint8_t m_curr_xmit;
uint8_t m_end_recv;
uint8_t m_end_xmit;
uint8_t m_cmd;
uint8_t m_cmd_size;
bool m_configuring;
static const size_t BUFFER_SIZE;
};
DECLARE_DEVICE_TYPE(SONYPS2_PAD, ps2_pad_device)
#endif // MAME_MACHINE_PS2PAD_H

View File

@ -54,15 +54,15 @@ READ32_MEMBER(ps2_sif_device::ee_r)
{
case 0:
ret = m_ms_mailbox;
logerror("%s: ee_r: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: ee_r: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 2:
ret = m_sm_mailbox;
logerror("%s: ee_r: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: ee_r: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 4:
ret = m_ms_flag;
logerror("%s: ee_r: SIF master->slave flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: ee_r: SIF master->slave flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 6:
ret = m_sm_flag;
@ -71,7 +71,7 @@ READ32_MEMBER(ps2_sif_device::ee_r)
break;
case 8:
ret = m_ctrl | 0xF0000102;
logerror("%s: ee_r: SIF control (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: ee_r: SIF control (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
default:
logerror("%s: ee_r: Unknown (%08x & %08x)\n", machine().describe_context(), 0x1000f200 + (offset << 3), mem_mask);
@ -85,19 +85,19 @@ WRITE32_MEMBER(ps2_sif_device::ee_w)
switch (offset)
{
case 0:
logerror("%s: ee_w: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: ee_w: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_ms_mailbox = data;
break;
case 4:
logerror("%s: ee_w: SIF set master->slave flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: ee_w: SIF set master->slave flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_ms_flag |= data;
break;
case 6:
logerror("%s: ee_w: SIF clear slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: ee_w: SIF clear slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_sm_flag &= ~data;
break;
case 8:
logerror("%s: ee_w: SIF set control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: ee_w: SIF set control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
if (BIT(data, 8))
m_ctrl |= (1 << 8);
else
@ -117,24 +117,24 @@ READ32_MEMBER(ps2_sif_device::iop_r)
{
case 0:
ret = m_ms_mailbox;
logerror("%s: iop_r: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: iop_r: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 4:
ret = m_sm_mailbox;
logerror("%s: iop_r: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: iop_r: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 8:
ret = m_ms_flag;
if (ret != 0)
logerror("%s: iop_r: SIF master->slave flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//if (ret != 0)
//logerror("%s: iop_r: SIF master->slave flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 12:
ret = m_sm_flag;
logerror("%s: iop_r: SIF slave->master flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: iop_r: SIF slave->master flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 16:
ret = m_ctrl | 0xf0000002;
logerror("%s: iop_r: SIF control register (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: iop_r: SIF control register (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
default:
logerror("%s: iop_r: Unknown read (%08x & %08x)\n", machine().describe_context(), 0x1d000000 + (offset << 2), mem_mask);
@ -148,19 +148,19 @@ WRITE32_MEMBER(ps2_sif_device::iop_w)
switch (offset)
{
case 4:
logerror("%s: iop_w: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: iop_w: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_sm_mailbox = data;
break;
case 8:
logerror("%s: iop_w: SIF clear master->slave flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: iop_w: SIF clear master->slave flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_ms_flag &= ~data;
break;
case 12:
logerror("%s: iop_w: SIF set slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: iop_w: SIF set slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_sm_flag |= data;
break;
case 16:
logerror("%s: iop_w: SIF set control (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
//logerror("%s: iop_w: SIF set control (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
m_ctrl ^= data & 0xf0;
if (data & 0x80 || data & 0x20)
{

View File

@ -0,0 +1,571 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 VU1 interface (VIF1) device skeleton
*
* To Do:
* Everything
*
* Note: STAT mode bit twiddling is a total guess
*
*/
#include "ps2vif1.h"
DEFINE_DEVICE_TYPE(SONYPS2_VIF1, ps2_vif1_device, "ps2vif1", "Playstation 2 VIF1")
/*static*/ const size_t ps2_vif1_device::BUFFER_SIZE = 0x40;
/*static*/ const uint32_t ps2_vif1_device::FORMAT_SIZE[] = {
1, 1, 1, 1,
2, 1, 1, 1,
3, 2, 1, 1,
4, 2, 1, 2
};
ps2_vif1_device::ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SONYPS2_VIF1, tag, owner, clock)
, device_execute_interface(mconfig, *this)
, m_gif(*this, finder_base::DUMMY_TAG)
{
}
void ps2_vif1_device::device_start()
{
set_icountptr(m_icount);
save_item(NAME(m_icount));
save_item(NAME(m_buffer));
save_item(NAME(m_curr));
save_item(NAME(m_end));
save_item(NAME(m_status));
save_item(NAME(m_control));
save_item(NAME(m_err));
save_item(NAME(m_mark));
save_item(NAME(m_cycle));
save_item(NAME(m_mode));
save_item(NAME(m_num));
save_item(NAME(m_mask));
save_item(NAME(m_code));
save_item(NAME(m_itops));
save_item(NAME(m_base));
save_item(NAME(m_offset));
save_item(NAME(m_tops));
save_item(NAME(m_itop));
save_item(NAME(m_top));
save_item(NAME(m_row_fill));
save_item(NAME(m_col_fill));
save_item(NAME(m_data_needed));
save_item(NAME(m_data_index));
save_item(NAME(m_command));
save_item(NAME(m_alignment));
save_item(NAME(m_mpg_count));
save_item(NAME(m_mpg_addr));
save_item(NAME(m_mpg_insn));
save_item(NAME(m_unpack_count));
save_item(NAME(m_unpack_addr));
save_item(NAME(m_unpack_last));
save_item(NAME(m_unpack_bits_remaining));
save_item(NAME(m_unpack_signed));
save_item(NAME(m_unpack_add_tops));
save_item(NAME(m_unpack_format));
}
void ps2_vif1_device::device_reset()
{
m_icount = 0;
memset(m_buffer, 0, sizeof(uint32_t) * BUFFER_SIZE);
m_curr = 0;
m_end = 0;
m_status = 0;
m_control = 0;
m_err = 0;
m_mark = 0;
m_cycle = 0;
m_mode = 0;
m_num = 0;
m_mask = 0;
m_code = 0;
m_itops = 0;
m_base = 0;
m_offset = 0;
m_tops = 0;
m_itop = 0;
m_top = 0;
memset(m_row_fill, 0, sizeof(uint32_t) * 4);
memset(m_col_fill, 0, sizeof(uint32_t) * 4);
m_data_needed = 0;
m_data_index = 0;
m_command = 0;
m_alignment = 0;
m_mpg_count = 0;
m_mpg_addr = 0;
m_mpg_insn = 0;
m_unpack_count = 0;
m_unpack_addr = 0;
m_unpack_last = 0;
m_unpack_bits_remaining = 0;
m_unpack_signed = false;
m_unpack_add_tops = false;
m_unpack_format = FMT_S32;
}
READ32_MEMBER(ps2_vif1_device::regs_r)
{
uint32_t ret = 0;
switch (offset)
{
case 0x00/4:
ret = m_status;
logerror("%s: Read: VIF1_STAT (%08x)\n", machine().describe_context(), ret);
break;
case 0x10/4:
ret = m_control;
logerror("%s: Read: VIF1_FBRST (%08x)\n", machine().describe_context(), ret);
break;
case 0x20/4:
ret = m_err;
logerror("%s: Read: VIF1_ERR (%08x)\n", machine().describe_context(), ret);
break;
case 0x30/4:
ret = m_mark;
logerror("%s: Read: VIF1_MARK (%08x)\n", machine().describe_context(), ret);
break;
case 0x40/4:
ret = m_cycle;
logerror("%s: Read: VIF1_CYCLE (%08x)\n", machine().describe_context(), ret);
break;
case 0x50/4:
ret = m_mode;
logerror("%s: Read: VIF1_MODE (%08x)\n", machine().describe_context(), ret);
break;
case 0x60/4:
ret = m_num;
logerror("%s: Read: VIF1_NUM (%08x)\n", machine().describe_context(), ret);
break;
case 0x70/4:
ret = m_mask;
logerror("%s: Read: VIF1_MASK (%08x)\n", machine().describe_context(), ret);
break;
case 0x80/4:
ret = m_code;
logerror("%s: Read: VIF1_CODE (%08x)\n", machine().describe_context(), ret);
break;
case 0x90/4:
ret = m_itops;
logerror("%s: Read: VIF1_ITOPS (%08x)\n", machine().describe_context(), ret);
break;
case 0xa0/4:
ret = m_base;
logerror("%s: Read: VIF1_BASE (%08x)\n", machine().describe_context(), ret);
break;
case 0xb0/4:
ret = m_offset;
logerror("%s: Read: VIF1_OFST (%08x)\n", machine().describe_context(), ret);
break;
case 0xc0/4:
ret = m_tops;
logerror("%s: Read: VIF1_TOPS (%08x)\n", machine().describe_context(), ret);
break;
case 0xd0/4:
ret = m_itop;
logerror("%s: Read: VIF1_ITOP (%08x)\n", machine().describe_context(), ret);
break;
case 0xe0/4:
ret = m_top;
logerror("%s: Read: VIF1_TOP (%08x)\n", machine().describe_context(), ret);
break;
case 0x100/4:
ret = m_row_fill[0];
logerror("%s: Read: VIF1_R0 (%08x)\n", machine().describe_context(), ret);
break;
case 0x110/4:
ret = m_row_fill[1];
logerror("%s: Read: VIF1_R1 (%08x)\n", machine().describe_context(), ret);
break;
case 0x120/4:
ret = m_row_fill[2];
logerror("%s: Read: VIF1_R2 (%08x)\n", machine().describe_context(), ret);
break;
case 0x130/4:
ret = m_row_fill[3];
logerror("%s: Read: VIF1_R3 (%08x)\n", machine().describe_context(), ret);
break;
case 0x140/4:
ret = m_col_fill[0];
logerror("%s: Read: VIF1_C0 (%08x)\n", machine().describe_context(), ret);
break;
case 0x150/4:
ret = m_col_fill[1];
logerror("%s: Read: VIF1_C1 (%08x)\n", machine().describe_context(), ret);
break;
case 0x160/4:
ret = m_col_fill[2];
logerror("%s: Read: VIF1_C2 (%08x)\n", machine().describe_context(), ret);
break;
case 0x170/4:
ret = m_col_fill[3];
logerror("%s: Read: VIF1_C3 (%08x)\n", machine().describe_context(), ret);
break;
default:
logerror("%s: Read: Unknown (%08x)\n", machine().describe_context(), 0x10003c00 + (offset << 2));
break;
}
return ret;
}
WRITE32_MEMBER(ps2_vif1_device::regs_w)
{
logerror("%s: Write: Unknown %08x = %08x\n", machine().describe_context(), 0x10003c00 + (offset << 2), data);
}
READ64_MEMBER(ps2_vif1_device::mmio_r)
{
uint64_t ret = 0ULL;
if (offset)
{
logerror("%s: mmio_r [127..64]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
}
else
{
logerror("%s: mmio_r [63..0]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
}
return ret;
}
WRITE64_MEMBER(ps2_vif1_device::mmio_w)
{
if (offset)
{
logerror("%s: mmio_w [127..64]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
fifo_push((uint32_t)data);
fifo_push((uint32_t)(data >> 32));
}
else
{
logerror("%s: mmio_w [63..0]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
fifo_push((uint32_t)data);
fifo_push((uint32_t)(data >> 32));
}
}
void ps2_vif1_device::dma_write(const uint64_t hi, const uint64_t lo)
{
logerror("%s: dma_write: %08x%08x%08x%08x\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
fifo_push((uint32_t)(hi >> 32));
fifo_push((uint32_t)hi);
fifo_push((uint32_t)(lo >> 32));
fifo_push((uint32_t)lo);
}
void ps2_vif1_device::tag_write(uint32_t *data)
{
logerror("%s: tag_write: %08x%08x\n", machine().describe_context(), data[2], data[3]);
fifo_push(data[2]);
fifo_push(data[3]);
}
void ps2_vif1_device::fifo_push(uint32_t value)
{
if (m_end >= BUFFER_SIZE)
{
return;
}
m_buffer[m_end++] = value;
}
uint32_t ps2_vif1_device::fifo_pop()
{
m_alignment = (m_alignment + 1) & 3;
if (m_curr >= m_end)
{
return 0;
}
const uint32_t ret = m_buffer[m_curr++];
if (m_curr >= m_end)
{
m_curr = 0;
m_end = 0;
}
return ret;
}
void ps2_vif1_device::execute_run()
{
while (m_icount > 0)
{
if (m_status & (STAT_E_WAIT | STAT_GS_WAIT | STAT_STALL_STOP | STAT_STALL_FBRK | STAT_STALL_INT))
{
m_icount = 0;
break;
}
switch (m_status & STAT_MODE_MASK)
{
case STAT_MODE_IDLE:
if (fifo_depth())
{
m_code = fifo_pop();
}
else
{
m_icount = 0;
break;
}
// Intentional fall-through
case STAT_MODE_DECODE:
decode_vifcode();
break;
case STAT_MODE_WAIT:
if (fifo_depth() == 0)
{
m_icount = 0;
break;
}
// Intentional fall-through
case STAT_MODE_DATA:
transfer_vifcode_data();
break;
}
}
}
void ps2_vif1_device::transfer_vifcode_data()
{
m_status &= ~STAT_MODE_MASK;
if (fifo_depth() < m_data_needed)
{
m_status |= STAT_MODE_WAIT;
m_icount = 0;
return;
}
switch (m_command)
{
case 0x20: /* STMASK */
m_mask = fifo_pop();
m_data_needed = 0;
break;
case 0x30: /* STROW */
m_row_fill[m_data_index] = fifo_pop();
m_data_needed = 0;
break;
case 0x31: /* STCOL */
m_col_fill[m_data_index] = fifo_pop();
m_data_needed = 0;
break;
case 0x4a: /* MPG */
transfer_mpg();
break;
default:
if ((m_command & 0x60) == 0x60)
{
transfer_unpack();
}
break;
}
if (m_data_needed)
{
if (fifo_depth() == 0)
{
m_status |= STAT_MODE_WAIT;
m_icount = 0;
}
else
{
m_status |= STAT_MODE_DATA;
m_icount--;
}
}
else if (fifo_depth() > 0)
{
m_code = fifo_pop();
m_status |= STAT_MODE_DECODE;
m_icount--;
}
else
{
m_status |= STAT_MODE_IDLE;
m_icount = 0;
}
}
void ps2_vif1_device::transfer_unpack()
{
switch (m_unpack_format)
{
case FMT_V4_32:
logerror("%s: Unpacking V4-32.\n", machine().describe_context());
for (int element = 0; element < 4; element++)
{
fifo_pop();
//const uint32_t data = fifo_pop();
//m_vu->write_data(m_unpack_addr, data);
m_unpack_addr += 4;
}
m_unpack_count--;
break;
default:
logerror("%s: Unsupported unpack format: %02x\n", machine().describe_context(), m_unpack_format);
break;
}
m_data_needed = FORMAT_SIZE[m_unpack_format] - (m_unpack_bits_remaining ? 1 : 0);
}
void ps2_vif1_device::transfer_mpg()
{
while (m_data_needed > 2)
{
fifo_pop();
m_data_needed--;
}
m_mpg_insn = fifo_pop();
m_mpg_insn |= (uint64_t)fifo_pop() << 32;
m_mpg_addr += 8;
m_mpg_count--;
m_data_needed = m_mpg_count ? 2 : 0;
logerror("%s: MPG, VU insn: %08x%08x, %d remaining\n", machine().describe_context(), (uint32_t)(m_mpg_insn >> 32), (uint32_t)m_mpg_insn, m_mpg_count);
//m_vu->write_instruction(m_mpg_addr, m_mpg_insn);
}
void ps2_vif1_device::decode_vifcode()
{
//bool trigger_interrupt = BIT(m_code, 31);
m_command = (m_code >> 24) & 0x7f;
m_status &= ~STAT_MODE_MASK;
switch (m_command)
{
case 0x00: /* NOP */
break;
case 0x01: /* STCYCL */
m_cycle = (uint16_t)m_code;
logerror("%s: STCYCL: %04x\n", machine().describe_context(), (uint16_t)m_cycle);
break;
case 0x02: /* OFFSET */
m_offset = m_code & 0x3ff;
logerror("%s: OFFSET: %03x\n", machine().describe_context(), m_offset);
break;
case 0x03: /* BASE */
m_base = m_code & 0x3ff;
logerror("%s: BASE: %03x\n", machine().describe_context(), m_base);
break;
case 0x04: /* ITOP */
m_itops = m_code & 0x3ff;
logerror("%s: ITOP: %03x\n", machine().describe_context(), m_itops);
break;
case 0x05: /* STMOD */
m_mode = m_code & 3;
logerror("%s: MODE: %03x\n", machine().describe_context(), m_mode);
break;
case 0x06: /* MSKPATH3 */
m_gif->set_path3_mask(BIT(m_code, 15));
logerror("%s: MSKPATH3: %d\n", machine().describe_context(), BIT(m_code, 15));
break;
case 0x07: /* Oh hi, MARK */
m_mark = (uint16_t)m_code;
logerror("%s: MARK: %04x\n", machine().describe_context(), (uint16_t)m_mark);
break;
case 0x20: /* STMASK */
m_data_needed = 1;
m_data_index = 0;
logerror("%s: STMASK\n", machine().describe_context());
break;
case 0x30: /* STROW */
m_data_needed = 4;
m_data_index = 0;
logerror("%s: STROW\n", machine().describe_context());
break;
case 0x31: /* STCOL */
m_data_needed = 4;
m_data_index = 0;
logerror("%s: STCOL\n", machine().describe_context());
break;
case 0x4a: /* MPG */
m_data_needed = 2 + (m_alignment & 1);
m_data_index = 0;
m_mpg_count = (m_code >> 16) & 0xff;
if (!m_mpg_count)
m_mpg_count = 0x100;
m_mpg_addr = m_code & 0xffff;
logerror("%s: MPG\n", machine().describe_context());
break;
default:
if ((m_command & 0x60) == 0x60)
{ /* UNPACK */
m_unpack_count = calculate_unpack_count();
m_unpack_signed = BIT(m_code, 14);
m_unpack_add_tops = BIT(m_code, 15);
m_unpack_format = (uint8_t)(m_command & 0xf);
m_data_needed = FORMAT_SIZE[m_unpack_format];
}
else
{ /* unknown */
logerror("%s: decode_vifcode: Unknown command %02x\n", machine().describe_context(), m_command);
}
break;
}
if (m_data_needed > 0)
{
if (fifo_depth())
{
m_status |= STAT_MODE_DATA;
m_icount--;
}
else
{
m_status |= STAT_MODE_WAIT;
m_icount = 0;
}
}
else if (fifo_depth())
{
m_code = fifo_pop();
m_status |= STAT_MODE_DECODE;
m_icount--;
}
else
{
m_status |= STAT_MODE_IDLE;
m_icount = 0;
}
}
uint32_t ps2_vif1_device::calculate_unpack_count()
{
const uint32_t wl = (m_cycle >> 8) & 0xff;
const uint32_t cl = m_cycle & 0xff;
const uint32_t vl = m_command & 3;
const uint32_t vn = (m_command >> 2) & 3;
uint32_t num = (m_code >> 16) & 0xff;
if (wl > cl)
{
const uint32_t mod = num % wl;
num = cl * (num / wl) + ((mod > cl) ? cl : mod);
}
return (uint32_t)std::ceil(((32 >> vl) * (vn + 1) * num) / 32.0f);
}

155
src/mame/machine/ps2vif1.h Normal file
View File

@ -0,0 +1,155 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 VU1 interface (VIF1) device skeleton
*
* To Do:
* Everything
*
*/
#ifndef MAME_MACHINE_PS2VIF1_H
#define MAME_MACHINE_PS2VIF1_H
#pragma once
#include "emu.h"
#include "ps2gif.h"
class ps2_vif1_device : public device_t, public device_execute_interface
{
public:
template <typename T>
ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&gif_tag)
: ps2_vif1_device(mconfig, tag, owner, clock)
{
m_gif.set_tag(std::forward<T>(gif_tag));
}
ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_READ64_MEMBER(mmio_r);
DECLARE_WRITE64_MEMBER(mmio_w);
DECLARE_READ32_MEMBER(regs_r);
DECLARE_WRITE32_MEMBER(regs_w);
void dma_write(const uint64_t hi, const uint64_t lo);
void tag_write(uint32_t *data);
protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void execute_run() override;
uint32_t calculate_unpack_count();
void decode_vifcode();
void transfer_vifcode_data();
void transfer_mpg();
void transfer_unpack();
void fifo_push(uint32_t value);
uint32_t fifo_pop();
uint32_t fifo_depth() const { return m_end - m_curr; }
enum : uint32_t
{
STAT_MODE_MASK = (3 << 0),
STAT_MODE_IDLE = 0,
STAT_MODE_WAIT = 1,
STAT_MODE_DECODE = 2,
STAT_MODE_DATA = 3,
STAT_E_WAIT = (1 << 2),
STAT_GS_WAIT = (1 << 3),
STAT_MARK = (1 << 6),
STAT_DBUF = (1 << 7),
STAT_STALL_STOP = (1 << 8),
STAT_STALL_FBRK = (1 << 9),
STAT_STALL_INT = (1 << 10),
STAT_INT = (1 << 11),
STAT_BAD_TAG = (1 << 12),
STAT_BAD_CODE = (1 << 13),
STAT_FDR_TO_HOST = (1 << 23)
};
enum : uint8_t
{
CMD_INT = 0x80,
CMD_UNPACK_MASK = 0x10
};
enum : uint8_t
{
FMT_S32 = 0x00,
FMT_S16 = 0x01,
FMT_S8 = 0x02,
//FMT_UNK0 = 0x03,
FMT_V2_32 = 0x04,
FMT_V2_16 = 0x05,
FMT_V2_8 = 0x06,
//FMT_UNK1 = 0x07,
FMT_V3_32 = 0x08,
FMT_V3_16 = 0x09,
FMT_V3_8 = 0x0a,
//FMT_UNK2 = 0x0b,
FMT_V4_32 = 0x0c,
FMT_V4_16 = 0x0d,
FMT_V4_8 = 0x0e,
FMT_V4_5 = 0x0f,
};
required_device<ps2_gif_device> m_gif;
int m_icount;
uint32_t m_buffer[0x40];
uint32_t m_curr;
uint32_t m_end;
uint32_t m_status;
uint32_t m_control;
uint32_t m_err;
uint32_t m_mark;
uint32_t m_cycle;
uint32_t m_mode;
uint32_t m_num;
uint32_t m_mask;
uint32_t m_code;
uint32_t m_itops;
uint32_t m_base;
uint32_t m_offset;
uint32_t m_tops;
uint32_t m_itop;
uint32_t m_top;
uint32_t m_row_fill[4];
uint32_t m_col_fill[4];
uint32_t m_data_needed;
uint32_t m_data_index;
uint8_t m_command;
uint8_t m_alignment;
uint32_t m_mpg_count;
uint32_t m_mpg_addr;
uint64_t m_mpg_insn;
uint32_t m_unpack_count;
uint32_t m_unpack_addr;
uint32_t m_unpack_last;
uint32_t m_unpack_bits_remaining;
bool m_unpack_signed;
bool m_unpack_add_tops;
uint8_t m_unpack_format;
static const size_t BUFFER_SIZE;
static const uint32_t FORMAT_SIZE[0x10];
};
DECLARE_DEVICE_TYPE(SONYPS2_VIF1, ps2_vif1_device)
#endif // MAME_MACHINE_PS2VIF1_H

730
src/mame/video/ps2gs.cpp Normal file
View File

@ -0,0 +1,730 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 Graphics Synthesizer device skeleton
*
* To Do:
* Everything
*
*/
#include "ps2gs.h"
DEFINE_DEVICE_TYPE(SONYPS2_GS, ps2_gs_device, "ps2gs", "Playstation 2 GS")
/*static*/ const size_t ps2_gs_device::FORMAT_PIXEL_WIDTHS[] = {
32, 24, 16, 0, 0, 0, 0, 0,
0, 0, 16, 0, 0, 0, 0, 0,
0, 0, 0, 8, 4, 0, 0, 0,
0, 0, 0, 8, 0, 0, 0, 0,
0, 0, 0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 4, 0, 0, 0,
32, 24, 16, 0, 0, 0, 0, 0,
0, 0, 16, 0, 0, 0, 0, 0
};
/*static*/ const char* ps2_gs_device::FORMAT_NAMES[] = {
"PSMCT32", "PSMCT24", "PSMCT16", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "PCMCT16S", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "Unknown", "PSMT8", "PSMT4", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "Unknown", "PSMT8H", "Unknown", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "Unknown", "Unknown", "PSMT4HL", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "Unknown", "Unknown", "PSMT4HH", "Unknown", "Unknown", "Unknown",
"PSMZ32", "PSMZ24", "PSMZ16", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "PSMZ16S", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown"
};
/*static*/ const uint32_t ps2_gs_device::KICK_COUNTS[] = {
1, 2, 2, 3, 3, 3, 2, 1
};
ps2_gs_device::ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SONYPS2_GS, tag, owner, clock)
{
}
void ps2_gs_device::device_start()
{
save_item(NAME(m_bitbltbuf));
save_item(NAME(m_src_buf_base));
save_item(NAME(m_src_buf_width));
save_item(NAME(m_src_buf_fmt));
save_item(NAME(m_dst_buf_base));
save_item(NAME(m_dst_buf_width));
save_item(NAME(m_dst_buf_fmt));
save_item(NAME(m_trx_pos));
save_item(NAME(m_src_ul_x));
save_item(NAME(m_src_ul_y));
save_item(NAME(m_dst_ul_x));
save_item(NAME(m_dst_ul_y));
save_item(NAME(m_copy_dir));
save_item(NAME(m_trx_reg));
save_item(NAME(m_trx_width));
save_item(NAME(m_trx_height));
save_item(NAME(m_trx_dir));
save_item(NAME(m_base_regs));
save_item(NAME(m_pmode));
save_item(NAME(m_read_circuit_enable));
save_item(NAME(m_use_fixed_alpha));
save_item(NAME(m_alpha_out_select));
save_item(NAME(m_blend_to_background));
save_item(NAME(m_fixed_alpha));
save_item(NAME(m_smode2));
save_item(NAME(m_interlace));
save_item(NAME(m_frame_interlace));
save_item(NAME(m_dpms_mode));
save_item(NAME(m_dispfb));
save_item(NAME(m_dispfb_base));
save_item(NAME(m_dispfb_width));
save_item(NAME(m_dispfb_format));
save_item(NAME(m_dispfb_x));
save_item(NAME(m_dispfb_y));
save_item(NAME(m_display));
save_item(NAME(m_display_xpos));
save_item(NAME(m_display_ypos));
save_item(NAME(m_magh));
save_item(NAME(m_magv));
save_item(NAME(m_display_width));
save_item(NAME(m_display_height));
save_item(NAME(m_bgcolor));
save_item(NAME(m_bg_r));
save_item(NAME(m_bg_g));
save_item(NAME(m_bg_b));
save_item(NAME(m_csr));
save_item(NAME(m_imr));
save_item(NAME(m_busdir));
save_item(NAME(m_sig_label_id));
save_item(NAME(m_vertex_count));
save_item(NAME(m_kick_count));
save_item(NAME(m_context[0].m_xyoffset));
save_item(NAME(m_context[0].m_offset_x));
save_item(NAME(m_context[0].m_offset_y));
save_item(NAME(m_context[0].m_scissor));
save_item(NAME(m_context[0].m_scissor_x0));
save_item(NAME(m_context[0].m_scissor_x1));
save_item(NAME(m_context[0].m_scissor_y0));
save_item(NAME(m_context[0].m_scissor_y1));
save_item(NAME(m_context[0].m_test));
save_item(NAME(m_context[0].m_alpha_test));
save_item(NAME(m_context[0].m_alpha_func));
save_item(NAME(m_context[0].m_alpha_ref));
save_item(NAME(m_context[0].m_alpha_fail));
save_item(NAME(m_context[0].m_dstalpha_test));
save_item(NAME(m_context[0].m_dstalpha_pass1));
save_item(NAME(m_context[0].m_depth_test));
save_item(NAME(m_context[0].m_depth_func));
save_item(NAME(m_context[0].m_frame));
save_item(NAME(m_context[0].m_fb_base));
save_item(NAME(m_context[0].m_fb_format));
save_item(NAME(m_context[0].m_fb_width));
save_item(NAME(m_context[0].m_fb_mask));
save_item(NAME(m_context[0].m_zbuf));
save_item(NAME(m_context[0].m_z_base));
save_item(NAME(m_context[0].m_z_format));
save_item(NAME(m_context[0].m_z_mask));
save_item(NAME(m_context[1].m_xyoffset));
save_item(NAME(m_context[1].m_offset_x));
save_item(NAME(m_context[1].m_offset_y));
save_item(NAME(m_context[1].m_scissor));
save_item(NAME(m_context[1].m_scissor_x0));
save_item(NAME(m_context[1].m_scissor_x1));
save_item(NAME(m_context[1].m_scissor_y0));
save_item(NAME(m_context[1].m_scissor_y1));
save_item(NAME(m_context[1].m_test));
save_item(NAME(m_context[1].m_alpha_test));
save_item(NAME(m_context[1].m_alpha_func));
save_item(NAME(m_context[1].m_alpha_ref));
save_item(NAME(m_context[1].m_alpha_fail));
save_item(NAME(m_context[1].m_dstalpha_test));
save_item(NAME(m_context[1].m_dstalpha_pass1));
save_item(NAME(m_context[1].m_depth_test));
save_item(NAME(m_context[1].m_depth_func));
save_item(NAME(m_context[1].m_frame));
save_item(NAME(m_context[1].m_fb_base));
save_item(NAME(m_context[1].m_fb_format));
save_item(NAME(m_context[1].m_fb_width));
save_item(NAME(m_context[1].m_fb_mask));
save_item(NAME(m_context[1].m_zbuf));
save_item(NAME(m_context[1].m_z_base));
save_item(NAME(m_context[1].m_z_format));
save_item(NAME(m_context[1].m_z_mask));
m_ram = std::make_unique<uint32_t[]>(0x400000/4);
m_vertices = std::make_unique<vertex_t[]>(0x10000); // Arbitrary count
}
void ps2_gs_device::device_reset()
{
m_bitbltbuf = 0;
m_src_buf_base = 0;
m_src_buf_width = 0;
m_src_buf_fmt = PSMCT32;
m_dst_buf_base = 0;
m_dst_buf_width = 0;
m_dst_buf_fmt = PSMCT32;
m_trx_pos = 0;
m_src_ul_x = 0;
m_src_ul_y = 0;
m_dst_ul_x = 0;
m_dst_ul_y = 0;
m_copy_dir = 0;
m_trx_reg = 0;
m_trx_width = 0;
m_trx_height = 0;
m_trx_dir = 0;
memset(m_base_regs, 0, sizeof(uint64_t) * 15);
m_pmode = 0;
memset(m_read_circuit_enable, 0, 2);
m_use_fixed_alpha = 0;
m_alpha_out_select = 0;
m_blend_to_background = 0;
m_fixed_alpha = 0;
m_smode2 = 0;
m_interlace = 0;
m_frame_interlace = 0;
m_dpms_mode = 0;
memset(m_dispfb, 0, sizeof(uint64_t) * 2);
memset(m_dispfb_base, 0, sizeof(uint32_t) * 2);
memset(m_dispfb_width, 0, sizeof(uint32_t) * 2);
memset(m_dispfb_format, 0, sizeof(uint8_t) * 2);
memset(m_dispfb_x, 0, sizeof(uint32_t) * 2);
memset(m_dispfb_y, 0, sizeof(uint32_t) * 2);
memset(m_display, 0, sizeof(uint64_t) * 2);
memset(m_display_xpos, 0, sizeof(uint32_t) * 2);
memset(m_display_ypos, 0, sizeof(uint32_t) * 2);
memset(m_magh, 0, sizeof(uint8_t) * 2);
memset(m_magv, 0, sizeof(uint8_t) * 2);
memset(m_display_width, 0, sizeof(uint32_t) * 2);
memset(m_display_height, 0, sizeof(uint32_t) * 2);
m_bgcolor = 0;
m_bg_r = 0;
m_bg_g = 0;
m_bg_b = 0;
m_csr = 0;
m_imr = 0;
m_busdir = 0;
m_sig_label_id = 0;
memset(m_context, 0, sizeof(context_t) * 2);
m_vertex_count = 0;
m_kick_count = 0;
}
READ64_MEMBER(ps2_gs_device::priv_regs0_r)
{
uint64_t ret = m_base_regs[offset >> 1];
switch (offset)
{
case 0x00:
ret = m_pmode;
logerror("%s: regs0_r: PMODE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x04:
ret = m_smode2;
logerror("%s: regs0_r: SMODE2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x0e:
case 0x12:
ret = m_dispfb[(offset - 0x0e) / 4];
logerror("%s: regs0_r: DISPFB2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x10:
case 0x14:
ret = m_display[(offset - 0x10) / 4];
logerror("%s: regs0_r: DISPLAY2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x1c:
ret = m_bgcolor;
logerror("%s: regs0_r: BGCOLOR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x02: logerror("%s: regs0_r: SMODE1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x06: logerror("%s: regs0_r: SRFSH (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x08: logerror("%s: regs0_r: SYNCH1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x0a: logerror("%s: regs0_r: SYNCH2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x0c: logerror("%s: regs0_r: SYNCV (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x16: logerror("%s: regs0_r: EXTBUF (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x18: logerror("%s: regs0_r: EXTDATA (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
case 0x1a: logerror("%s: regs0_r: EXTWRITE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
default: logerror("%s: regs0_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3)); break;
}
return ret;
}
WRITE64_MEMBER(ps2_gs_device::priv_regs0_w)
{
switch (offset)
{
case 0x00: // PMODE
m_pmode = data;
m_read_circuit_enable[0] = BIT(data, 0);
m_read_circuit_enable[1] = BIT(data, 1);
m_use_fixed_alpha = BIT(data, 5);
m_alpha_out_select = BIT(data, 6);
m_blend_to_background = BIT(data, 7);
m_fixed_alpha = (data >> 8) & 0xff;
logerror("%s: regs0_w: PMODE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
break;
case 0x04: // SMODE2
m_smode2 = data;
m_interlace = BIT(data, 0);
m_frame_interlace = BIT(data, 1);
m_dpms_mode = (data >> 2) & 3;
logerror("%s: regs0_w: SMODE2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
break;
case 0x0e: // DISPFB1
case 0x12: // DISPFB2
{
const uint8_t index = (offset - 0x0e) / 4;
m_dispfb[index] = data;
m_dispfb_base[index] = (data & 0x1ff) << 11;
m_dispfb_width[index] = (data & 0x7e00) >> 3;
m_dispfb_format[index] = (data >> 15) & 0x1f;
m_dispfb_x[index] = (data >> 32) & 0x7ff;
m_dispfb_y[index] = (data >> 42) & 0x7ff;
logerror("%s: regs0_w: DISPFB%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
break;
}
case 0x10: // DISPLAY1
case 0x14: // DISPLAY2
{
const uint8_t index = (offset - 0x10) / 4;
m_display[index] = data;
m_display_xpos[index] = data & 0xfff;
m_display_ypos[index] = (data >> 12) & 0x7ff;
m_magh[index] = (data >> 23) & 0xf;
m_magv[index] = (data >> 27) & 3;
m_display_width[index] = (data >> 32) & 0xfff;
m_display_height[index] = (data >> 44) & 0x7ff;
logerror("%s: regs0_w: DISPLAY%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
break;
}
case 0x1c: // BGCOLOR
m_bgcolor = data;
m_bg_r = data & 0xff;
m_bg_g = (data >> 8) & 0xff;
m_bg_b = (data >> 16) & 0xff;
logerror("%s: regs0_w: BGCOLOR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
break;
case 0x02: logerror("%s: regs0_w: SMODE1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x06: logerror("%s: regs0_w: SRFSH = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x08: logerror("%s: regs0_w: SYNCH1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x0a: logerror("%s: regs0_w: SYNCH2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x0c: logerror("%s: regs0_w: SYNCV = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x16: logerror("%s: regs0_w: EXTBUF = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x18: logerror("%s: regs0_w: EXTDATA = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
case 0x1a: logerror("%s: regs0_w: EXTWRITE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
default: logerror("%s: regs0_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data); break;
}
m_base_regs[offset >> 1] = data;
}
READ64_MEMBER(ps2_gs_device::priv_regs1_r)
{
uint64_t ret = 0;
switch (offset)
{
case 0x00:
ret = m_csr;
logerror("%s: regs1_r: CSR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x02:
ret = m_imr;
logerror("%s: regs1_r: IMR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x08:
ret = m_busdir;
logerror("%s: regs1_r: BUSDIR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x10:
ret = m_sig_label_id;
logerror("%s: regs1_r: SIGLBLID (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
default:
logerror("%s: regs1_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3));
break;
}
return ret;
}
WRITE64_MEMBER(ps2_gs_device::priv_regs1_w)
{
switch (offset)
{
case 0x00:
logerror("%s: regs1_w: CSR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
m_csr = data &~ CSR_RESET;
break;
case 0x02:
logerror("%s: regs1_w: IMR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
m_imr = data;
break;
case 0x08:
logerror("%s: regs1_w: BUSDIR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
m_busdir = data;
break;
case 0x10:
logerror("%s: regs1_w: SIGLBLID = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
m_sig_label_id = data;
break;
default:
logerror("%s: regs1_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data);
break;
}
}
void ps2_gs_device::write_packed(const uint8_t reg, const uint64_t hi, const uint64_t lo)
{
switch (reg)
{
case 0x0e:
regs_w(machine().dummy_space(), (uint32_t)hi, lo, ~0ULL);
break;
default:
logerror("%s: write_packed: Unknown register %02x = %08x%08x%08x%08x\n", machine().describe_context(), reg, (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
break;
}
}
WRITE64_MEMBER(ps2_gs_device::regs_w)
{
static const char* dir_strs[4] = {
"Host->Local", "Local->Host", "Local->Local", "None"
};
static const char* prim_strs[8] = {
"Point", "Line", "Line Strip", "Tri", "Tri Strip", "Tri Fan", "Sprite", "Invalid"
};
switch (offset)
{
case 0x00: // PRIM
m_prim = data;
m_prim_type = data & 7;
m_gouraud_enable = BIT(data, 3);
m_texture_enable = BIT(data, 4);
m_fog_enable = BIT(data, 5);
m_blend_enable = BIT(data, 6);
m_aa_enable = BIT(data, 7);
m_no_perspective = BIT(data, 8);
m_curr_context = (data >> 9) & 1;
m_fix_fragments = BIT(data, 10);
m_kick_count = KICK_COUNTS[m_prim_type];
logerror("%s: regs_w: PRIM = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s TYPE=%s GOUR=%d TEX=%d FOG=%d BLEND=%d\n", machine().describe_context(), prim_strs[m_prim_type], BIT(data, 3), BIT(data, 4), BIT(data, 5), BIT(data, 6));
logerror("%s AA=%d NOPERSP=%d CONTEXT=%d FIXFRAG=%d\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), BIT(data, 9), BIT(data, 10));
break;
case 0x01: // RGBAQ
{
m_rgbaq = data;
m_vc_r = data & 0xff;
m_vc_g = (data >> 8) & 0xff;
m_vc_b = (data >> 16) & 0xff;
m_vc_a = (data >> 24) & 0xff;
uint32_t q = (uint32_t)(data >> 32);
m_q = *reinterpret_cast<float*>(&q);
logerror("%s: regs_w: RGBAQ = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s R=%02x G=%02x B=%02x A=%02x Q=%f\n", machine().describe_context(), m_vc_r, m_vc_g, m_vc_b, m_vc_a, m_q);
break;
}
case 0x05: // XYZ2
{
uint16_t x = (uint16_t)data;
uint16_t y = (uint16_t)(data >> 16);
uint32_t z = (uint32_t)(data >> 32);
m_vertices[m_vertex_count] = {
x, y, z,
m_vc_r, m_vc_g, m_vc_b, m_vc_a, m_q,
0, 0, 0 // TODO: U/S, V/T, fog
};
m_vertex_count++;
logerror("%s: regs_w: XYZ2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s: X=%f Y=%f Z=%08x\n", machine().describe_context(), x / 16.0f, y / 16.0f, z);
if (m_vertex_count >= m_kick_count)
{
logerror("%s: Should begin primitive drawing...\n", machine().describe_context());
switch (m_prim_type & 7)
{
case PRIM_TYPE_LINE_STRIP:
m_vertices[0] = m_vertices[m_vertex_count - 1];
m_vertex_count = 1;
m_kick_count = 1;
break;
case PRIM_TYPE_TRI_STRIP:
case PRIM_TYPE_TRI_FAN:
m_vertices[0] = m_vertices[m_vertex_count - 2];
m_vertices[1] = m_vertices[m_vertex_count - 1];
m_vertex_count = 2;
m_kick_count = 1;
break;
case PRIM_TYPE_POINT:
case PRIM_TYPE_LINE:
case PRIM_TYPE_TRI:
case PRIM_TYPE_SPRITE:
case PRIM_TYPE_INVALID:
default:
m_vertex_count = 0;
m_kick_count = 0;
break;
}
}
break;
}
case 0x18: // XYOFFSET1
case 0x19: // XYOFFSET2
{
const uint8_t index = offset - 0x18;
m_context[index].m_xyoffset = data;
m_context[index].m_offset_x = data & 0xffff;
m_context[index].m_offset_y = (data >> 32) & 0xffff;
logerror("%s: regs_w: XYFOFFSET%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s X=%f Y=%f\n", machine().describe_context(), m_context[index].m_offset_x / 16.0f, m_context[index].m_offset_y / 16.0f);
break;
}
case 0x1a: // PRMODECONT
m_prmodecont = data;
m_use_prim_for_attrs = BIT(data, 0);
logerror("%s: regs_w: PRMODECONT = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_use_prim_for_attrs ? "Use PRIM" : "Use PRMODE");
break;
case 0x40: // SCISSOR1
case 0x41: // SCISSOR2
{
const uint8_t index = offset - 0x40;
m_context[index].m_scissor = data;
m_context[index].m_scissor_x0 = data & 0x7ff;
m_context[index].m_scissor_x1 = (data >> 16) & 0x7ff;
m_context[index].m_scissor_y0 = (data >> 32) & 0x7ff;
m_context[index].m_scissor_y1 = (data >> 48) & 0x7ff;
logerror("%s: regs_w: SCISSOR%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s X0=d Y0=%d X1=%d Y1=%d\n", machine().describe_context(), m_context[index].m_scissor_x0, m_context[index].m_scissor_y0, m_context[index].m_scissor_x1, m_context[index].m_scissor_y1);
break;
}
case 0x45: // DTHE
m_dthe = data;
m_dither = BIT(data, 0);
logerror("%s: regs_w: DTHE = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_clamp_color ? "Dither" : "No Dither");
break;
case 0x46: // COLCLAMP
m_colclamp = data;
m_clamp_color = BIT(data, 0);
logerror("%s: regs_w: COLCLAMP = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_clamp_color ? "Clamp Color" : "Wrap Color");
break;
case 0x47: // TEST1
case 0x48: // TEST2
{
const uint8_t index = offset - 0x47;
m_context[index].m_test = data;
m_context[index].m_alpha_test = BIT(data, 0);
m_context[index].m_alpha_func = (data >> 1) & 7;
m_context[index].m_alpha_ref = (data >> 4) & 0xff;
m_context[index].m_alpha_fail = (data >> 12) & 3;
m_context[index].m_dstalpha_test = BIT(data, 14);
m_context[index].m_dstalpha_pass1 = BIT(data, 15);
m_context[index].m_depth_test = BIT(data, 16);
m_context[index].m_depth_func = (data >> 17) & 3;
logerror("%s: regs_w: SCISSOR%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s X0=d Y0=%d X1=%d Y1=%d\n", machine().describe_context(), m_context[index].m_scissor_x0, m_context[index].m_scissor_y0, m_context[index].m_scissor_x1, m_context[index].m_scissor_y1);
break;
}
case 0x4c: // FRAME1
case 0x4d: // FRAME2
{
const uint8_t index = offset - 0x4c;
m_context[index].m_frame = data;
m_context[index].m_fb_base = (data & 0x1ff) << 11;
m_context[index].m_fb_width = (data >> 10) & 0xfc0;
m_context[index].m_fb_format = (data >> 24) & 0x3f;
m_context[index].m_fb_mask = (uint32_t)(data >> 32);
logerror("%s: regs_w: FRAME%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s BASE=%08x WIDTH=%d FORMAT=%d MASK=%08x\n", machine().describe_context(), m_context[index].m_fb_base, m_context[index].m_fb_width, m_context[index].m_fb_format, m_context[index].m_fb_mask);
break;
}
case 0x4e: // ZBUF1
case 0x4f: // ZBUF2
{
const uint8_t index = offset - 0x4e;
m_context[index].m_zbuf = data;
m_context[index].m_z_base = (data & 0x1ff) << 11;
m_context[index].m_z_format = (data >> 24) & 0xf;
m_context[index].m_z_mask = BIT(data, 32);
logerror("%s: regs_w: ZBUF%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s BASE=%08x FORMAT=%d MASK=%d\n", machine().describe_context(), m_context[index].m_z_base, m_context[index].m_z_format, BIT(data, 32));
break;
}
case 0x50: // BITBLTBUF
m_bitbltbuf = data;
m_src_buf_base = ((uint32_t)m_bitbltbuf & 0x7fff) << 6;
m_src_buf_width = ((uint32_t)(m_bitbltbuf >> 16) & 0x3f) << 6;
m_src_buf_fmt = (uint8_t)((m_bitbltbuf >> 24) & 0x3f);
m_dst_buf_base = ((uint32_t)(m_bitbltbuf >> 32) & 0x7fff) << 6;
m_dst_buf_width = ((uint32_t)(m_bitbltbuf >> 48) & 0x3f) << 6;
m_dst_buf_fmt = (uint8_t)((m_bitbltbuf >> 56) & 0x3f);
logerror("%s: regs_w: BITBLTBUF = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
logerror("%s: SRCBASE=%08x SRCWIDTH=%d SRCFMT=%s\n", machine().describe_context(), m_src_buf_base, m_src_buf_width, FORMAT_NAMES[m_src_buf_fmt]);
logerror("%s: DSTBASE=%08x DSTWIDTH=%d DSTFMT=%s\n", machine().describe_context(), m_dst_buf_base, m_dst_buf_width, FORMAT_NAMES[m_dst_buf_fmt]);
break;
case 0x51: // TRXPOS
m_trx_pos = data;
m_src_ul_x = (uint32_t)m_trx_pos & 0x7ff;
m_src_ul_y = (uint32_t)(m_trx_pos >> 16) & 0x7ff;
m_dst_ul_x = (uint32_t)(m_trx_pos >> 32) & 0x7ff;
m_dst_ul_y = (uint32_t)(m_trx_pos >> 48) & 0x7ff;
m_copy_dir = (uint8_t)(m_trx_pos >> 59) & 3;
logerror("%s: regs_w: TRXPOS = %08x%08x, SRCUL=%d,%d DSTUL=%d,%d, DIR=%d\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_src_ul_x, m_src_ul_y, m_dst_ul_x, m_dst_ul_y, m_copy_dir);
break;
case 0x52: // TRXREG
m_trx_reg = data;
m_trx_width = (uint32_t)m_trx_reg & 0xfff;
m_trx_height = (uint32_t)(m_trx_reg >> 32) & 0xfff;
logerror("%s: regs_w: TRXREG = %08x%08x, DIMS=%dx%d\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_trx_width, m_trx_height);
break;
case 0x53: // TRXDIR
m_trx_dir = data & 3;
logerror("%s: regs_w: TRXDIR = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, dir_strs[m_trx_dir]);
break;
case 0x54: // HWREG
logerror("%s: regs_w: HWREG = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
copy_dword_from_host(data);
break;
default:
logerror("%s: regs_w: Unknown register %02x = %08x%08x\n", machine().describe_context(), offset, (uint32_t)(data >> 32), (uint32_t)data);
break;
}
}
void ps2_gs_device::copy_dword_from_host(uint64_t data)
{
if (m_src_buf_fmt == PSMCT24 || m_src_buf_fmt == PSMZ24)
{
// Special-case for unevenly-sized data.
// TODO: What do we do with leftover data, if any, when an IMAGE transfer finishes?
logerror("%s: Unsupported src format: PSMCT24/PSMZ24\n", machine().describe_context());
return;
}
const size_t bpp = FORMAT_PIXEL_WIDTHS[m_src_buf_fmt];
offs_t dst_offset = (m_dst_buf_base + m_dst_ul_y * m_dst_buf_width + m_dst_ul_x) >> 2;
for (size_t shift = 0, index = 0; shift < 64; shift += bpp, index++)
{
uint64_t src = (data >> shift) & ((1ULL << bpp) - 1ULL);
switch (m_dst_buf_fmt)
{
case PSMCT32:
case PSMZ32:
{
m_ram[dst_offset + index] = (uint32_t)src;
break;
}
case PSMCT24:
case PSMZ24:
logerror("%s: Unsupported dst format: PSMCT24/PSMZ24\n", machine().describe_context());
break;
case PSMCT16:
case PSMCT16S:
case PSMZ16:
case PSMZ16S:
{
const offs_t dst_shift = ((index & 1) << 4);
m_ram[dst_offset + (index >> 1)] &= ~(0x0000ffff << dst_shift);
m_ram[dst_offset + (index >> 1)] |= (uint32_t)src << dst_shift;
break;
}
case PSMT8:
{
const offs_t dst_shift = ((index & 3) << 3);
m_ram[dst_offset + (index >> 2)] &= ~(0x000000ff << dst_shift);
m_ram[dst_offset + (index >> 2)] |= (uint32_t)src << dst_shift;
break;
}
case PSMT8H:
{
m_ram[dst_offset + index] &= 0x00ffffff;
m_ram[dst_offset + index] |= (uint32_t)src << 24;
break;
}
case PSMT4:
{
const offs_t dst_shift = ((index & 7) << 2);
m_ram[dst_offset + (index >> 3)] &= ~(0x0000000f << dst_shift);
m_ram[dst_offset + (index >> 3)] |= (uint32_t)src << dst_shift;
break;
}
case PSMT4HL:
m_ram[dst_offset + index] &= 0xf0ffffff;
m_ram[dst_offset + index] |= (uint32_t)src << 24;
break;
case PSMT4HH:
m_ram[dst_offset + index] &= 0x0fffffff;
m_ram[dst_offset + index] |= (uint32_t)src << 28;
break;
default:
logerror("%s: copy_dword_from_host: Unknown format %02x\n", machine().describe_context(), m_dst_buf_fmt);
return;
}
}
}
void ps2_gs_device::vblank_start()
{
}
void ps2_gs_device::vblank_end()
{
m_curr_field ^= 1;
if (m_curr_field)
m_csr |= CSR_FIELD_ODD;
else
m_csr &= ~CSR_FIELD_ODD;
}

279
src/mame/video/ps2gs.h Normal file
View File

@ -0,0 +1,279 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 Graphics Synthesizer device skeleton
*
* To Do:
* Everything
*
*/
#ifndef MAME_MACHINE_PS2GS_H
#define MAME_MACHINE_PS2GS_H
#pragma once
#include "emu.h"
class ps2_gs_device : public device_t
{
public:
ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_READ64_MEMBER(priv_regs0_r);
DECLARE_WRITE64_MEMBER(priv_regs0_w);
DECLARE_READ64_MEMBER(priv_regs1_r);
DECLARE_WRITE64_MEMBER(priv_regs1_w);
DECLARE_WRITE64_MEMBER(regs_w);
void reg_write(const uint8_t reg, const uint64_t value);
void write_packed(const uint8_t reg, const uint64_t hi, const uint64_t lo);
void vblank_start();
void vblank_end();
protected:
virtual void device_start() override;
virtual void device_reset() override;
void copy_dword_from_host(uint64_t data);
enum : uint64_t
{
HOST_TO_LOCAL,
LOCAL_TO_HOST,
LOCAL_TO_LOCAL,
NO_TRANSFER
};
enum : uint8_t
{
UL_TO_BR,
BL_TO_UR,
UR_TO_BL,
BR_TO_UL
};
enum : uint8_t
{
PSMCT32 = 0x00,
PSMCT24 = 0x01,
PSMCT16 = 0x02,
PSMCT16S = 0x0a,
PSMT8 = 0x13,
PSMT4 = 0x14,
PSMT8H = 0x1b,
PSMT4HL = 0x24,
PSMT4HH = 0x2c,
PSMZ32 = 0x30,
PSMZ24 = 0x31,
PSMZ16 = 0x32,
PSMZ16S = 0x3a
};
enum : uint8_t
{
ALPHA_FUNC_NEVER,
ALPHA_FUNC_ALWAYS,
ALPHA_FUNC_LESS,
ALPHA_FUNC_LEQUAL,
ALPHA_FUNC_EQUAL,
ALPHA_FUNC_GEQUAL,
ALPHA_FUNC_GREATER,
ALPHA_FUNC_NOTEQUAL
};
enum : uint8_t
{
ALPHA_FAIL_KEEP,
ALPHA_FAIL_UPDATE_FB,
ALPHA_FAIL_UPDATE_ZB,
ALPHA_FAIL_UPDATE_RGB
};
enum : uint8_t
{
DEPTH_FUNC_NEVER,
DEPTH_FUNC_ALWAYS,
DEPTH_FUNC_GEQUAL,
DEPTH_FUNC_GREATER
};
enum : uint8_t
{
PRIM_TYPE_POINT,
PRIM_TYPE_LINE,
PRIM_TYPE_LINE_STRIP,
PRIM_TYPE_TRI,
PRIM_TYPE_TRI_STRIP,
PRIM_TYPE_TRI_FAN,
PRIM_TYPE_SPRITE,
PRIM_TYPE_INVALID
};
enum : uint32_t
{
CSR_RESET = 0x00000200,
CSR_FIELD_ODD = 0x00002000
};
struct vertex_t
{
uint16_t m_x;
uint16_t m_y;
uint32_t m_z;
uint8_t m_r;
uint8_t m_g;
uint8_t m_b;
uint8_t m_a;
float m_q;
uint32_t m_us;
uint32_t m_vt;
uint8_t m_fog;
};
std::unique_ptr<uint32_t[]> m_ram;
std::unique_ptr<vertex_t[]> m_vertices;
struct context_t
{
uint64_t m_xyoffset; // 0x18, 0x19
uint32_t m_offset_x;
uint32_t m_offset_y;
uint64_t m_scissor; // 0x40, 0x41
uint16_t m_scissor_x0;
uint16_t m_scissor_x1;
uint16_t m_scissor_y0;
uint16_t m_scissor_y1;
uint64_t m_test; // 0x47, 0x48
bool m_alpha_test;
uint8_t m_alpha_func;
uint8_t m_alpha_ref;
uint8_t m_alpha_fail;
bool m_dstalpha_test;
bool m_dstalpha_pass1;
bool m_depth_test;
uint8_t m_depth_func;
uint64_t m_frame; // 0x4c, 0x4d
uint32_t m_fb_base;
uint32_t m_fb_width;
uint8_t m_fb_format;
uint32_t m_fb_mask;
uint64_t m_zbuf; // 0x4e, 0x4f
uint32_t m_z_base;
uint8_t m_z_format;
bool m_z_mask;
};
context_t m_context[2];
uint64_t m_prim; // 0x00
uint8_t m_prim_type;
bool m_gouraud_enable;
bool m_texture_enable;
bool m_fog_enable;
bool m_blend_enable;
bool m_aa_enable;
bool m_no_perspective;
uint8_t m_curr_context;
bool m_fix_fragments;
uint64_t m_rgbaq; // 0x01
uint8_t m_vc_r;
uint8_t m_vc_g;
uint8_t m_vc_b;
uint8_t m_vc_a;
float m_q;
uint64_t m_prmodecont; // 0x1a
bool m_use_prim_for_attrs;
uint64_t m_dthe; // 0x45
bool m_dither;
uint64_t m_colclamp; // 0x46
bool m_clamp_color;
uint64_t m_bitbltbuf; // 0x50
uint32_t m_src_buf_base;
uint32_t m_src_buf_width;
uint8_t m_src_buf_fmt;
uint32_t m_dst_buf_base;
uint32_t m_dst_buf_width;
uint8_t m_dst_buf_fmt;
uint64_t m_trx_pos; // 0x51
uint32_t m_src_ul_x;
uint32_t m_src_ul_y;
uint32_t m_dst_ul_x;
uint32_t m_dst_ul_y;
uint8_t m_copy_dir;
uint64_t m_trx_reg; // 0x52
uint32_t m_trx_width;
uint32_t m_trx_height;
uint64_t m_trx_dir; // 0x53
// Privileged regs
uint64_t m_base_regs[15];
uint64_t m_pmode; // Privileged 0x00
bool m_read_circuit_enable[2];
bool m_use_fixed_alpha;
uint8_t m_alpha_out_select;
bool m_blend_to_background;
uint8_t m_fixed_alpha;
uint64_t m_smode2; // Privileged 0x02
bool m_interlace;
bool m_frame_interlace;
uint8_t m_dpms_mode;
uint64_t m_dispfb[2]; // Privileged 0x07, 0x09
uint32_t m_dispfb_base[2];
uint32_t m_dispfb_width[2];
uint8_t m_dispfb_format[2];
uint32_t m_dispfb_x[2];
uint32_t m_dispfb_y[2];
uint64_t m_display[2]; // Privileged 0x08, 0x0a
uint32_t m_display_xpos[2];
uint32_t m_display_ypos[2];
uint8_t m_magh[2];
uint8_t m_magv[2];
uint32_t m_display_width[2];
uint32_t m_display_height[2];
uint64_t m_bgcolor; // Privileged 0x0e
uint8_t m_bg_r;
uint8_t m_bg_g;
uint8_t m_bg_b;
uint64_t m_csr;
uint64_t m_imr;
uint64_t m_busdir;
uint64_t m_sig_label_id;
uint32_t m_vertex_count;
uint32_t m_kick_count;
uint8_t m_curr_field;
static const size_t FORMAT_PIXEL_WIDTHS[0x40];
static const char* FORMAT_NAMES[0x40];
static const uint32_t KICK_COUNTS[8];
};
DECLARE_DEVICE_TYPE(SONYPS2_GS, ps2_gs_device)
#endif // MAME_MACHINE_PS2GS_H