diff --git a/src/pse/gte.cpp b/src/pse/gte.cpp index 7ecc17c45..63186bcf7 100644 --- a/src/pse/gte.cpp +++ b/src/pse/gte.cpp @@ -270,10 +270,26 @@ void Core::ExecuteInstruction(Instruction inst) Execute_NCLIP(inst); break; + case 0x10: + Execute_DPCS(inst); + break; + + case 0x12: + Execute_MVMVA(inst); + break; + case 0x13: Execute_NCDS(inst); break; + case 0x16: + Execute_NCCT(inst); + break; + + case 0x1B: + Execute_NCCS(inst); + break; + case 0x28: Execute_SQR(inst); break; @@ -290,8 +306,8 @@ void Core::ExecuteInstruction(Instruction inst) Execute_RTPT(inst); break; - case 0x12: - Execute_MVMVA(inst); + case 0x3F: + Execute_NCCT(inst); break; default: @@ -631,6 +647,50 @@ void Core::MulMatVec(const s16 M[3][3], const s32 T[3], const s16 Vx, const s16 TruncateAndSetIR<3>(m_regs.MAC3, lm); } +void Core::NCCS(const s16 V[3], bool sf, bool lm) +{ + const u8 shift = sf ? 12 : 0; + + // [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] = (LLM*V0) SAR (sf*12) + MulMatVec(m_regs.LLM, V[0], V[1], V[2], sf, lm); + + // [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] = (BK*1000h + LCM*IR) SAR (sf*12) + MulMatVec(m_regs.LCM, m_regs.BK, m_regs.IR1, m_regs.IR2, m_regs.IR3, sf, lm); + + // [MAC1,MAC2,MAC3] = [R*IR1,G*IR2,B*IR3] SHL 4 ;<--- for NCDx/NCCx + // [MAC1,MAC2,MAC3] = [MAC1,MAC2,MAC3] SAR (sf*12) ;<--- for NCDx/NCCx + TruncateAndSetMAC<1>((s64(ZeroExtend64(m_regs.RGBC[0])) << 4) * s64(m_regs.MAC1), sf); + TruncateAndSetMAC<2>((s64(ZeroExtend64(m_regs.RGBC[1])) << 4) * s64(m_regs.MAC2), sf); + TruncateAndSetMAC<3>((s64(ZeroExtend64(m_regs.RGBC[2])) << 4) * s64(m_regs.MAC3), sf); + + // Color FIFO = [MAC1/16,MAC2/16,MAC3/16,CODE], [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] + PushRGB(TruncateRGB<0>(m_regs.MAC1 / 16), TruncateRGB<1>(m_regs.MAC2 / 16), TruncateRGB<2>(m_regs.MAC3 / 16), + m_regs.RGBC[3]); + TruncateAndSetIR<1>(m_regs.MAC1, lm); + TruncateAndSetIR<2>(m_regs.MAC2, lm); + TruncateAndSetIR<3>(m_regs.MAC3, lm); +} + +void Core::Execute_NCCS(Instruction inst) +{ + m_regs.FLAG.Clear(); + + NCCS(m_regs.V0, inst.sf, inst.lm); + + m_regs.FLAG.UpdateError(); +} + +void Core::Execute_NCCT(Instruction inst) +{ + m_regs.FLAG.Clear(); + + NCCS(m_regs.V0, inst.sf, inst.lm); + NCCS(m_regs.V1, inst.sf, inst.lm); + NCCS(m_regs.V2, inst.sf, inst.lm); + + m_regs.FLAG.UpdateError(); +} + void Core::NCDS(const s16 V[3], bool sf, bool lm) { const u8 shift = sf ? 12 : 0; @@ -675,6 +735,17 @@ void Core::Execute_NCDS(Instruction inst) m_regs.FLAG.UpdateError(); } +void Core::Execute_NCDT(Instruction inst) +{ + m_regs.FLAG.Clear(); + + NCDS(m_regs.V0, inst.sf, inst.lm); + NCDS(m_regs.V1, inst.sf, inst.lm); + NCDS(m_regs.V2, inst.sf, inst.lm); + + m_regs.FLAG.UpdateError(); +} + void Core::Execute_MVMVA(Instruction inst) { // TODO: Remove memcpy.. @@ -745,4 +816,35 @@ void Core::Execute_MVMVA(Instruction inst) MulMatVec(M, T, Vx, Vy, Vz, inst.sf, inst.lm); } +void Core::Execute_DPCS(Instruction inst) +{ + const bool sf = inst.sf; + const bool lm = inst.lm; + + // In: [IR1,IR2,IR3]=Vector, FC=Far Color, IR0=Interpolation value, CODE=MSB of RGBC + // [MAC1,MAC2,MAC3] = [R,G,B] SHL 16 ;<--- for DPCS/DPCT + TruncateAndSetMAC<1>((s64(ZeroExtend64(m_regs.RGBC[0])) << 16), false); + TruncateAndSetMAC<2>((s64(ZeroExtend64(m_regs.RGBC[1])) << 16), false); + TruncateAndSetMAC<3>((s64(ZeroExtend64(m_regs.RGBC[2])) << 16), false); + + // [MAC1,MAC2,MAC3] = MAC+(FC-MAC)*IR0 + // [IR1,IR2,IR3] = (([RFC,GFC,BFC] SHL 12) - [MAC1,MAC2,MAC3]) SAR (sf*12) + TruncateAndSetIR<1>(s32((s64(m_regs.FC[0]) << 12) - s64(m_regs.MAC1)) >> (sf ? 12 : 0), false); + TruncateAndSetIR<2>(s32((s64(m_regs.FC[1]) << 12) - s64(m_regs.MAC2)) >> (sf ? 12 : 0), false); + TruncateAndSetIR<3>(s32((s64(m_regs.FC[2]) << 12) - s64(m_regs.MAC3)) >> (sf ? 12 : 0), false); + + // [MAC1,MAC2,MAC3] = (([IR1,IR2,IR3] * IR0) + [MAC1,MAC2,MAC3]) + // [MAC1,MAC2,MAC3] = [MAC1,MAC2,MAC3] SAR (sf*12) + TruncateAndSetMAC<1>(s64(s32(m_regs.IR1) * s32(m_regs.IR0)) + s64(m_regs.MAC1), sf); + TruncateAndSetMAC<2>(s64(s32(m_regs.IR2) * s32(m_regs.IR0)) + s64(m_regs.MAC2), sf); + TruncateAndSetMAC<3>(s64(s32(m_regs.IR3) * s32(m_regs.IR0)) + s64(m_regs.MAC3), sf); + + // Color FIFO = [MAC1/16,MAC2/16,MAC3/16,CODE], [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] + PushRGB(TruncateRGB<0>(m_regs.MAC1 / 16), TruncateRGB<1>(m_regs.MAC2 / 16), TruncateRGB<2>(m_regs.MAC3 / 16), + m_regs.RGBC[3]); + TruncateAndSetIR<1>(m_regs.MAC1, lm); + TruncateAndSetIR<2>(m_regs.MAC2, lm); + TruncateAndSetIR<3>(m_regs.MAC3, lm); +} + } // namespace GTE \ No newline at end of file diff --git a/src/pse/gte.h b/src/pse/gte.h index 67405001f..fe3592e7d 100644 --- a/src/pse/gte.h +++ b/src/pse/gte.h @@ -67,6 +67,7 @@ private: void MulMatVec(const s16 M[3][3], const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, bool sf, bool lm); void RTPS(const s16 V[3], bool sf); + void NCCS(const s16 V[3], bool sf, bool lm); void NCDS(const s16 V[3], bool sf, bool lm); void Execute_RTPS(Instruction inst); @@ -75,8 +76,12 @@ private: void Execute_SQR(Instruction inst); void Execute_AVSZ3(Instruction inst); void Execute_AVSZ4(Instruction inst); + void Execute_NCCS(Instruction inst); + void Execute_NCCT(Instruction inst); void Execute_NCDS(Instruction inst); + void Execute_NCDT(Instruction inst); void Execute_MVMVA(Instruction inst); + void Execute_DPCS(Instruction inst); Regs m_regs = {}; };