diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index a3760cb5455..af69b2af3cf 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -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") diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 6550aa27d2f..b2a1e3b7fdf 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -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(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(m_core->vfmem); + m_core->vr = &m_core->vcr[20]; + m_core->i = reinterpret_cast(&m_core->vcr[21]); + m_core->q = reinterpret_cast(&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(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(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(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"); diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index cdc6edfaa0d..a2aa5a345dc 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -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 */ diff --git a/src/mame/drivers/ps2sony.cpp b/src/mame/drivers/ps2sony.cpp index 50eb5e8a3e6..826b629d938 100644 --- a/src/mame/drivers/ps2sony.cpp +++ b/src/mame/drivers/ps2sony.cpp @@ -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 m_iop_spu; required_device m_iop_cdvd; required_device m_iop_sio2; + required_device m_gif; + required_device m_gs; + required_device m_vif1; + required_device_array m_pad; + required_device m_mc; required_device m_screen; required_shared_ptr m_ram; required_shared_ptr m_iop_ram; @@ -268,12 +277,6 @@ protected: required_shared_ptr m_vu1_imem; required_shared_ptr 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)) diff --git a/src/mame/machine/iopdma.cpp b/src/mame/machine/iopdma.cpp index 4713a425ad2..bc0dfd8b980 100644 --- a/src/mame/machine/iopdma.cpp +++ b/src/mame/machine/iopdma.cpp @@ -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: diff --git a/src/mame/machine/iopintc.cpp b/src/mame/machine/iopintc.cpp index 85ff79e0b52..f1ca66ed85b 100644 --- a/src/mame/machine/iopintc.cpp +++ b/src/mame/machine/iopintc.cpp @@ -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(); } diff --git a/src/mame/machine/iopsio2.cpp b/src/mame/machine/iopsio2.cpp index 20ec5956e5d..69a3896266f 100644 --- a/src/mame/machine/iopsio2.cpp +++ b/src/mame/machine/iopsio2.cpp @@ -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); } diff --git a/src/mame/machine/iopsio2.h b/src/mame/machine/iopsio2.h index 354b970c842..915a5294e28 100644 --- a/src/mame/machine/iopsio2.h +++ b/src/mame/machine/iopsio2.h @@ -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 - iop_sio2_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&intc_tag) + template + 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(intc_tag)); + m_pad0.set_tag(std::forward(pad0_tag)); + m_pad1.set_tag(std::forward(pad1_tag)); + m_mc0.set_tag(std::forward(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 m_intc; + required_device m_pad0; + required_device m_pad1; + required_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; }; diff --git a/src/mame/machine/ps2dma.cpp b/src/mame/machine/ps2dma.cpp index 34058d3cf94..b342445176a 100644 --- a/src/mame/machine/ps2dma.cpp +++ b/src/mame/machine/ps2dma.cpp @@ -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); diff --git a/src/mame/machine/ps2dma.h b/src/mame/machine/ps2dma.h index c6dea56749c..b076188cdac 100644 --- a/src/mame/machine/ps2dma.h +++ b/src/mame/machine/ps2dma.h @@ -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 - 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 + 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(ee_tag)); m_ram.set_tag(std::forward(ram_tag)); m_sif.set_tag(std::forward(sif_tag)); + m_gif.set_tag(std::forward(gif_tag)); + m_vif1.set_tag(std::forward(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 m_ee; required_shared_ptr m_ram; required_device m_sif; + required_device m_gif; + required_device m_vif1; int m_icount; diff --git a/src/mame/machine/ps2gif.cpp b/src/mame/machine/ps2gif.cpp new file mode 100644 index 00000000000..f894d380bdf --- /dev/null +++ b/src/mame/machine/ps2gif.cpp @@ -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; +} + diff --git a/src/mame/machine/ps2gif.h b/src/mame/machine/ps2gif.h new file mode 100644 index 00000000000..c5e6169f45c --- /dev/null +++ b/src/mame/machine/ps2gif.h @@ -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 + 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(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 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 \ No newline at end of file diff --git a/src/mame/machine/ps2intc.h b/src/mame/machine/ps2intc.h index 952dcb8c748..b77769e2dd6 100644 --- a/src/mame/machine/ps2intc.h +++ b/src/mame/machine/ps2intc.h @@ -67,4 +67,4 @@ protected: DECLARE_DEVICE_TYPE(SONYPS2_INTC, ps2_intc_device) -#endif // MAME_MACHINE_PS2SIF_H \ No newline at end of file +#endif // MAME_MACHINE_PS2INTC_H \ No newline at end of file diff --git a/src/mame/machine/ps2mc.cpp b/src/mame/machine/ps2mc.cpp new file mode 100644 index 00000000000..854180dfc05 --- /dev/null +++ b/src/mame/machine/ps2mc.cpp @@ -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++; + } +} diff --git a/src/mame/machine/ps2mc.h b/src/mame/machine/ps2mc.h new file mode 100644 index 00000000000..efca9e5ab8b --- /dev/null +++ b/src/mame/machine/ps2mc.h @@ -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 \ No newline at end of file diff --git a/src/mame/machine/ps2pad.cpp b/src/mame/machine/ps2pad.cpp new file mode 100644 index 00000000000..1c34ebfd6fa --- /dev/null +++ b/src/mame/machine/ps2pad.cpp @@ -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++; + } +} diff --git a/src/mame/machine/ps2pad.h b/src/mame/machine/ps2pad.h new file mode 100644 index 00000000000..da04362bcca --- /dev/null +++ b/src/mame/machine/ps2pad.h @@ -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 \ No newline at end of file diff --git a/src/mame/machine/ps2sif.cpp b/src/mame/machine/ps2sif.cpp index a47747892af..454e707f373 100644 --- a/src/mame/machine/ps2sif.cpp +++ b/src/mame/machine/ps2sif.cpp @@ -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) { diff --git a/src/mame/machine/ps2vif1.cpp b/src/mame/machine/ps2vif1.cpp new file mode 100644 index 00000000000..57901041e47 --- /dev/null +++ b/src/mame/machine/ps2vif1.cpp @@ -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); +} diff --git a/src/mame/machine/ps2vif1.h b/src/mame/machine/ps2vif1.h new file mode 100644 index 00000000000..cc2d1d0d359 --- /dev/null +++ b/src/mame/machine/ps2vif1.h @@ -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 + 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(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 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 \ No newline at end of file diff --git a/src/mame/video/ps2gs.cpp b/src/mame/video/ps2gs.cpp new file mode 100644 index 00000000000..a7d77c392b3 --- /dev/null +++ b/src/mame/video/ps2gs.cpp @@ -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(0x400000/4); + m_vertices = std::make_unique(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(&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; +} diff --git a/src/mame/video/ps2gs.h b/src/mame/video/ps2gs.h new file mode 100644 index 00000000000..ed825e4a6e0 --- /dev/null +++ b/src/mame/video/ps2gs.h @@ -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 m_ram; + std::unique_ptr 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 \ No newline at end of file