From 1bb170a3c4e149ffc5794d33ac80cc7c177e438c Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Fri, 28 Jul 2017 11:19:20 +0700 Subject: [PATCH] Implement command 0x05. This command generates polygons for terrain geometry. Very large and complex. --- src/F3DSWRS.cpp | 1051 ++++++++++++++++++++++++++++++++++++---- src/GraphicsDrawer.cpp | 5 - src/gSP.h | 1 - 3 files changed, 954 insertions(+), 103 deletions(-) diff --git a/src/F3DSWRS.cpp b/src/F3DSWRS.cpp index 0f1acf3a..c9266e4e 100644 --- a/src/F3DSWRS.cpp +++ b/src/F3DSWRS.cpp @@ -1,9 +1,11 @@ /* Star Wars Rogue Squadron ucode - * Ported from Lemmy's LemNemu plugin + * Initial code ported from Lemmy's LemNemu plugin * Incomplete! */ +#include #include +#include #include "GLideN64.h" #include "DebugDump.h" #include "F3D.h" @@ -19,7 +21,7 @@ #define F3DSWRS_VTXCOLOR 0x02 #define F3DSWRS_MOVEMEM 0x03 #define F3DSWRS_VTX 0x04 -#define F3DSWRS_JUMP3 0x05 +#define F3DSWRS_TRI_GEN 0x05 #define F3DSWRS_DL 0x06 #define F3DSWRS_BRANCHDL 0x07 @@ -36,7 +38,98 @@ #define F3DSWRS_MW_FOG_MULTIPLIER 0x08 #define F3DSWRS_MW_FOG_OFFSET 0x0A -static u32 G_SETOTHERMODE_H_EX, G_SETOTHERMODE_L_EX; +//#define TRIGEN_DEBUG + +static u32 G_SETOTHERMODE_H_EX, G_SETOTHERMODE_L_EX, G_JUMPSWDL; + +struct SWRSTriangle +{ + u32 V0, V1, V2; + int avrgZ; + +}; + +bool SWRSTriangleCompare(const SWRSTriangle & _first, const SWRSTriangle & _second) +{ + return _first.avrgZ > _second.avrgZ; +} + +static +SWRSTriangle TriGen0000_defaultTriangleOrder[32] = { + // D1 D1 D2 D2 D3 D6 D3 D6 D4 D4 + // D7 D6 D8 D7 D9 D12 D8 D11 D10 D9 + // D2 D7 D3 D8 D4 D7 D9 D12 D5 D10 + { 0, 6, 1, 0 }, + { 0, 5, 6, 0 }, + { 1, 7, 2, 0 }, + { 1, 6, 7, 0 }, + { 2, 8, 3, 0 }, + { 5, 11, 6, 0 }, + { 2, 7, 8, 0 }, + { 5, 10, 11, 0 }, + { 3, 9, 4, 0 }, + { 3, 8, 9, 0 }, + + // D7 D7 D11 D8 D11 D8 D9 D12 D9 D12 + // D13 D12 D17 D14 D16 D13 D15 D18 D14 D17 + // D8 D13 D12 D9 D17 D14 D10 D13 D15 D18 + { 6, 12, 7, 0 }, + { 6, 11, 12, 0 }, + { 10, 16, 11, 0 }, + { 7, 13, 8, 0 }, + { 10, 15, 16, 0 }, + { 7, 12, 13, 0 }, + { 8, 14, 9, 0 }, + { 11, 17, 12, 0 }, + { 8, 13, 14, 0 }, + { 11, 16, 17, 0 }, + + // D16 D13 D16 D13 D14 D17 D17 D14 D18 D18 + // D22 D19 D21 D18 D20 D23 D22 D19 D24 D23 + // D17 D14 D22 D19 D15 D18 D23 D20 D19 D24 + { 15, 21, 16, 0 }, + { 12, 18, 13, 0 }, + { 15, 20, 21, 0 }, + { 12, 17, 18, 0 }, + { 13, 19, 14, 0 }, + { 16, 22, 17, 0 }, + { 16, 21, 22, 0 }, + { 13, 18, 19, 0 }, + { 17, 23, 18, 0 }, + { 17, 22, 23, 0 }, + + // D19 D19 + // D25 D24 + // D20 D25 + { 18, 24, 19, 0 }, + { 18, 23, 24, 0 } +}; + +static +SWRSTriangle TriGen0001_defaultTriangleOrder[8] = { + // D1 D1 D2 D2 D4 D4 D5 D5 + // D4 D5 D5 D6 D7 D8 D8 D9 + // D5 D2 D6 D3 D8 D5 D9 D6 + { 0, 3, 4, 0 }, + { 0, 4, 1, 0 }, + { 1, 4, 5, 0 }, + { 1, 5, 2, 0 }, + { 3, 6, 7, 0 }, + { 3, 7, 4, 0 }, + { 4, 7, 8, 0 }, + { 4, 8, 5, 0 } +}; + +inline +void _updateSWDL() +{ + // Lemmy's note: + // differs from the other DL commands because it does skip the first command + // the first 32 bits are stored, because they are + // used as branch target address in the command in the QUAD "slot" + RSP.swDL[RSP.PCi].SWStartDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi]], 0, 24); + RSP.swDL[RSP.PCi].SWOtherDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4], 0, 24); +} void F3DSWRS_VertexColor(u32, u32 _w1) { @@ -74,7 +167,7 @@ void F3DSWRS_Vtx(u32 _w0, u32 _w1) } static -void F3DSWRS_PrepareVertices(const u32* _vert, const u8* _colorbase, const u32* _color, const u8* _texbase, bool _useTex, u32 _num) +void F3DSWRS_PrepareVertices(const u32* _vert, const u8* _colorbase, const u32* _color, const u8* _texbase, bool _useTex, bool _persp, u32 _num) { const u32 sscale = _SHIFTR(gSP.textureCoordScale[0], 16, 16); const u32 tscale = _SHIFTR(gSP.textureCoordScale[0], 0, 16); @@ -110,22 +203,20 @@ void F3DSWRS_PrepareVertices(const u32* _vert, const u8* _colorbase, const u32* const s16 scaledS = low_acum_S + hi_acum_S; const s16 scaledT = low_acum_T + hi_acum_T; - if (gDP.otherMode.texturePersp == 0) { - vtx.s = _FIXED2FLOAT(scaledS, 4); - vtx.t = _FIXED2FLOAT(scaledT, 4); - } - else { + if (_persp) { vtx.s = _FIXED2FLOAT(scaledS, 5); vtx.t = _FIXED2FLOAT(scaledT, 5); + } else { + vtx.s = _FIXED2FLOAT(scaledS, 4); + vtx.t = _FIXED2FLOAT(scaledT, 4); } } } } static -void Jump3_2(const u32 * _params, u32 * _result) { -// if (_params[1] == 0xFDA00050 && _params[9] == 0xE2000200 && _params[8] == 0xF0000000) -// int k = 0; +void TriGen02_PrepareVtxData(const u32 * _params, u32 * _result) +{ typedef std::array Vector; Vector v0 = { 0, 0, 0, 0 }; Vector v1 = { 0, 0, 0, 0 }; @@ -157,97 +248,866 @@ void Jump3_2(const u32 * _params, u32 * _result) { _result[7] = ((v0[2] + v1[2]) << 16) | ((v0[3] + v1[3]) & 0xFFFF); } - -bool _print = false; -void F3DSWRS_Jump3(u32 _w0, u32 _w1) +static +void TriGen0000_PrepareColorData(const u32 * _params, std::vector & _data) { - DebugMsg(DEBUG_NORMAL, "F3DSWRS_Jump3 (0x%08x, 0x%08x)\n", _w0, _w1); + assert((_params[3] & 0x07) % 4 == 0); + const u32* data32 = (const u32*)&RDRAM[_SHIFTR(_params[3], 0, 24)]; + std::copy_n(data32, 25, _data.begin()); + for (u32 i = 0; i < 25; ++i) + _data[i] |= 0xFF; +} + +static +void TriGen0001_PrepareColorData(const u32 * _params, std::vector & _data) +{ + assert((_params[3] & 0x07) % 4 == 0); + const u32 dataSize = (((_SHIFTR(_params[4], 0, 16) + 0x13) & 0xFF0) - (_params[3] & 0x07)) / 4; + const u32 dataAddr = (_SHIFTR(_params[3], 0, 24) & 0x00FFFFF8) +(_params[3] & 0x07); + const u32* data32 = (const u32*)&RDRAM[dataAddr]; + + u32 idx32 = 0; + do { + _data.push_back(data32[idx32++]); + idx32++; + _data.push_back(data32[idx32++]); + idx32++; + _data.push_back(data32[idx32]); + idx32 += 6; + } while(dataSize > idx32); + + const size_t colorDataSize = _data.size(); + for (u32 i = 0; i < colorDataSize; ++i) + _data[i] |= 0xFF; +} + +static +void TriGen0000_PrepareVtxData(const u32 * _params, std::vector & _data) +{ + const u32 dataAddr = _SHIFTR(_params[2], 0, 24) & 0x00FFFFF8; + const s8* rdram_data8 = (const s8*)(RDRAM + dataAddr); + + u32 idx8 = _params[2] & 0x07; + u32 dataIdx = 0; + + for (u32 i = 0; i < 25; ++i) { + const s8 val = rdram_data8[idx8^3]; + ++idx8; + u16 res = _SHIFTL(val, 4, 8) | (val < 0 ? 0xF000 : 0); + _data[dataIdx^1] = res; + ++dataIdx; + } +} + +static +void TriGen0001_PrepareVtxData(const u32 * _params, std::vector & _data) +{ + const u32 dataSize = (_SHIFTR(_params[4], 16, 16) + 0x16) & 0xFF0; + _data.resize(dataSize / 2); + const u32 dataAddr = _SHIFTR(_params[2], 0, 24) & 0x00FFFFF8; + + const s8* rdram_data8 = (const s8*)(RDRAM + dataAddr); + + u32 idx8 = _params[2] & 0x07; + u32 dataIdx = 0; + + do { + for (u32 i = 0; i < 3; ++i) { + const s8 val = rdram_data8[idx8^3]; + idx8 += 2; + u16 res = _SHIFTL(val, 4, 8) | (val < 0 ? 0xF000 : 0); + _data[dataIdx^1] = res; + ++dataIdx; + } + idx8 += 4; + } while(dataSize > idx8); +} + +inline +void TriGen00_correctVertexForOption(std::vector & _vtxData, u32 _src1, u32 _src2, u32 _dst) +{ + const s16 vd = (s16)_vtxData[_src1] + (s16)_vtxData[_src2]; + _vtxData[_dst] = (u16)(vd / 2); +} + +inline +void TriGen00_correctColorForOption(u32* _pColor, u32 _src1, u32 _src2, u32 _dst) +{ + u8* pSrc1 = (u8*)(_pColor + _src1); + u8* pSrc2 = (u8*)(_pColor + _src2); + u8* pDst = (u8*)(_pColor + _dst); + for (u32 i = 0; i < 4; ++i) { + const u16 c = pSrc1[i] + pSrc2[i]; + pDst[i] = _SHIFTR(c, 1, 8); + } +} + +inline +void TriGen00_correctVertexForPonderation(std::vector & _vtxData, u32 _src1, u32 _src2, u32 _dst, u16 ponderation) +{ + const s16 * vtxData = (const s16*)_vtxData.data(); + s32 vd = vtxData[_dst] * (0x10000 - ponderation); + vd += ((vtxData[_src1] + vtxData[_src2]) * ponderation) >> 1; + _vtxData[_dst] = _SHIFTR(vd, 16, 16); +} + +inline +void TriGen00_correctColorForPonderation(u32* _pColor, u32 _src1, u32 _src2, u32 _dst, u16 ponderation) +{ + u8* pSrc1 = (u8*)(_pColor + _src1); + u8* pSrc2 = (u8*)(_pColor + _src2); + u8* pDst = (u8*)(_pColor + _dst); + for (u32 i = 0; i < 4; ++i) { + const u32 c = pDst[i] * (0x10000 - ponderation) + (((pSrc1[i] + pSrc2[i]) * ponderation) >> 1); + pDst[i] = _SHIFTR(c, 16, 8); + } +} + +static +void TriGen0000_option_00000100(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF00) != 0x0100) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 1, 3, 0); + TriGen00_correctVertexForOption(_vtxData, 3, 5, 2); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 0, 2, 1); + TriGen00_correctColorForOption(_colorData.data(), 2, 4, 3); + + // Additional triangle + SWRSTriangle t1 = { 0, 10, 5, 0 }; + _triangles.push_back(t1); + SWRSTriangle t2 = { 10, 20, 15, 0 }; + _triangles.push_back(t2); +} + +static +void TriGen0000_ponderation1(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation1 = _SHIFTR(_params[6], 0, 16); + if (ponderation1 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 1, 3, 0, ponderation1); + TriGen00_correctVertexForPonderation(_vtxData, 3, 5, 2, ponderation1); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 0, 2, 1, ponderation1); + TriGen00_correctColorForPonderation(_colorData.data(), 2, 4, 3, ponderation1); +} + +static +void TriGen0000_option_00000001(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF) != 0x01) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 21, 23, 20); + TriGen00_correctVertexForOption(_vtxData, 23, 25, 22); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 20, 22, 21); + TriGen00_correctColorForOption(_colorData.data(), 22, 24, 23); + + // Additional triangle + SWRSTriangle t1 = { 4, 9, 14, 0 }; + _triangles.push_back(t1); + SWRSTriangle t2 = { 14, 19, 24, 0 }; + _triangles.push_back(t2); +} + +static +void TriGen0000_ponderation2(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation2 = _SHIFTR(_params[7], 16, 16); + if (ponderation2 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 21, 23, 20, ponderation2); + TriGen00_correctVertexForPonderation(_vtxData, 23, 25, 22, ponderation2); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 20, 22, 21, ponderation2); + TriGen00_correctColorForPonderation(_colorData.data(), 22, 24, 23, ponderation2); +} + +static +void TriGen0000_option_01000000(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF000000) != 0x01000000) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 1, 11, 4); + TriGen00_correctVertexForOption(_vtxData, 11, 21, 14); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 0, 10, 5); + TriGen00_correctColorForOption(_colorData.data(), 10, 20, 15); + + // Additional triangle + SWRSTriangle t1 = { 0, 1, 2, 0 }; + _triangles.push_back(t1); + SWRSTriangle t2 = { 2, 3, 4, 0 }; + _triangles.push_back(t2); +} + +static +void TriGen0000_ponderation3(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation3 = _SHIFTR(_params[5], 0, 16); + if (ponderation3 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 1, 11, 4, ponderation3); + TriGen00_correctVertexForPonderation(_vtxData, 11, 21, 14, ponderation3); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 0, 10, 5, ponderation3); + TriGen00_correctColorForPonderation(_colorData.data(), 10, 20, 15, ponderation3); +} + +static +void TriGen0000_option_00010000(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF0000) != 0x010000) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 5, 15, 8); + TriGen00_correctVertexForOption(_vtxData, 15, 25, 18); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 4, 14, 9); + TriGen00_correctColorForOption(_colorData.data(), 14, 24, 19); + + // Additional triangle + SWRSTriangle t1 = { 22, 24, 23, 0 }; + _triangles.push_back(t1); + SWRSTriangle t2 = { 20, 22, 21, 0 }; + _triangles.push_back(t2); +} + +static +void TriGen0000_ponderation4(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation4 = _SHIFTR(_params[6], 16, 16); + if (ponderation4 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 5, 15, 8, ponderation4); + TriGen00_correctVertexForPonderation(_vtxData, 15, 25, 18, ponderation4); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 4, 14, 9, ponderation4); + TriGen00_correctColorForPonderation(_colorData.data(), 14, 24, 19, ponderation4); +} + +static +void TriGen0000_ponderation5(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation5 = _SHIFTR(_params[5], 16, 16); + if (ponderation5 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 1, 13, 7, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 3, 13, 6, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 3, 15, 9, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 11, 13, 10, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 13, 15, 12, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 11, 23, 17, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 13, 23, 16, ponderation5); + TriGen00_correctVertexForPonderation(_vtxData, 13, 25, 19, ponderation5); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 0, 12, 6, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 2, 12, 7, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 2, 14, 8, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 10, 12, 11, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 12, 14, 13, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 10, 22, 16, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 12, 22, 17, ponderation5); + TriGen00_correctColorForPonderation(_colorData.data(), 12, 24, 18, ponderation5); +} + +static +void TriGen0001_option_01010201(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF00) != 0x0200) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 1, 3, 0); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 0, 2, 1); + + // Additional triangle + SWRSTriangle t = { 0, 6, 3, 0 }; + _triangles.push_back(t); +} + +static +void TriGen0001_ponderation1(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation1 = _SHIFTR(_params[6], 0, 16); + if (ponderation1 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 1, 3, 0, ponderation1); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 0, 2, 1, ponderation1); +} + +static +void TriGen0001_option_01010102(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF) != 0x02) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 7, 9, 8); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 6, 8, 7); + + // Additional triangle + SWRSTriangle t = { 2, 5, 8, 0 }; + _triangles.push_back(t); +} + +static +void TriGen0001_ponderation2(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation2 = _SHIFTR(_params[7], 16, 16); + if (ponderation2 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 7, 9, 6, ponderation2); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 6, 8, 7, ponderation2); +} + +static +void TriGen0001_option_02010101(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0xFF000000) != 0x02000000) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 1, 7, 2); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 0, 6, 3); + + // Additional triangle + SWRSTriangle t = { 0, 1, 2, 0 }; + _triangles.push_back(t); +} + +static +void TriGen0001_ponderation3(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation3 = _SHIFTR(_params[5], 0, 16); + if (ponderation3 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 1, 7, 2, ponderation3); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 0, 6, 3, ponderation3); +} + +static +void TriGen0001_option_01020101(const u32 * _params, std::vector & _vtxData, std::vector & _colorData, std::vector & _triangles) +{ + if ((_params[1] & 0x00FF0000) != 0x00020000) + return; + + // Correct vertex data + TriGen00_correctVertexForOption(_vtxData, 3, 9, 4); + + // Correct color data + TriGen00_correctColorForOption(_colorData.data(), 2, 8, 5); + + // Additional triangle + SWRSTriangle t = { 6, 8, 7, 0 }; + _triangles.push_back(t); +} + +static +void TriGen0001_ponderation4(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation4 = _SHIFTR(_params[6], 16, 16); + if (ponderation4 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 3, 9, 4, ponderation4); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 2, 8, 5, ponderation4); +} + +static +void TriGen0001_ponderation5(const u32 * _params, std::vector & _vtxData, std::vector & _colorData) +{ + const u16 ponderation5 = _SHIFTR(_params[5], 16, 16); + if (ponderation5 == 0) + return; + + // Correct vertex data + TriGen00_correctVertexForPonderation(_vtxData, 1, 9, 5, ponderation5); + + // Correct color data + TriGen00_correctColorForPonderation(_colorData.data(), 0, 8, 4, ponderation5); +} + +struct Vector2 { + union { + u16 vec16[4]; + u32 vec32[2]; + u64 qw; + } data; + + Vector2() { + data.qw = 0; + } + + Vector2 ADD(const Vector2 & _v) const { + Vector2 res; + for (u32 i = 0; i < 4; ++i) + res.data.vec16[i] = data.vec16[i] + _v.data.vec16[i]; + return res; + } + + void VAL(u32 _idx, u16 _val) { + data.vec16[_idx] = _val; + } +}; + +static +void TriGen00_BuildVtxData(const u32 * _params, u32 _step, const std::vector & _input, std::vector & _output) { + u16 V0 = _SHIFTR(_params[9], 0, 16); + u16 V1 = _SHIFTR(_params[8], 0, 16); + V1 <<= 4; + Vector2 v0; + v0.VAL(1, _SHIFTR(_params[8], 16, 16)); + v0.VAL(3, _SHIFTR(_params[9], 16, 16)); + v0.VAL(0, V1); + Vector2 v2; + v2.VAL(1, V0); + Vector2 v3; + v3.VAL(3, V0); + Vector2 v1; + + const u32 bound = _step * (_step - 1) + 1; + for (u32 startDataIdx = 0; startDataIdx < _step; ++startDataIdx) { + for (u32 idx = 0; idx < bound; idx += _step) { + v1.VAL(0, _input[(startDataIdx + idx) ^ 1]); + Vector2 v4 = v1.ADD(v0); + _output.push_back(v4.data.vec32[0]); + _output.push_back(v4.data.vec32[1]); + v1 = v1.ADD(v3); + } + v1 = v1.ADD(v2); + v1.VAL(3, 0); + } +} + + + +static +void TriGen0000_BuildVtxData(const u32 * _params, const std::vector & _input, std::vector & _output) { +#ifdef TRIGEN_DEBUG + u32 debug_params[10] = { + 0x05050000, + 0x00000000, + 0x8027E226, + 0x8020A8B4, + 0x00190064, + 0x5BA75BA7, + 0x5BA769B8, + 0x5BA701F8, + 0xFA000000, + 0x00000080 + }; + _params = debug_params; +#endif + + +#ifdef TRIGEN_DEBUG + const u32 RDRAM_data[] = { + 0x07100729, + 0x07600763, + 0x077006E0, + 0x07020725, + 0x0757075A, + 0x06B006D2, + 0x0700071D, + 0x0730066D, + 0x069F06CD, + 0x06EF070D, + 0x0620065D, + 0x069006BD, + 0x06E00000 + }; + const u16* input =(u16*)RDRAM_data; +#else +#endif + + + u16 V0 = _SHIFTR(_params[9], 0, 16); + u16 V1 = _SHIFTR(_params[8], 0, 16); + V1 <<= 4; + Vector2 v0; + v0.VAL(1, _SHIFTR(_params[8], 16, 16)); + v0.VAL(3, _SHIFTR(_params[9], 16, 16)); + v0.VAL(0, V1); + Vector2 v2; + v2.VAL(1, V0); + Vector2 v3; + v3.VAL(3, V0); + Vector2 v1; + + for (u32 startDataIdx = 0; startDataIdx < 5; ++startDataIdx) { + for (u32 idx = 0; idx < 21; idx += 5) { + v1.VAL(0, _input[(startDataIdx + idx) ^ 1]); + Vector2 v4 = v1.ADD(v0); + _output.push_back(v4.data.vec32[0]); + _output.push_back(v4.data.vec32[1]); + v1 = v1.ADD(v3); + } + v1 = v1.ADD(v2); + v1.VAL(3, 0); + } +} + +static +void TriGen0001_BuildVtxData(const u32 * _params, const std::vector & _input, std::vector & _output) { + u16 V0 = _SHIFTR(_params[9], 0, 16); + u16 V1 = _SHIFTR(_params[8], 0, 16); + V1 <<= 4; + Vector2 v0; + v0.VAL(1, _SHIFTR(_params[8], 16, 16)); + v0.VAL(3, _SHIFTR(_params[9], 16, 16)); + v0.VAL(0, V1); + Vector2 v2; + v2.VAL(1, V0); + Vector2 v3; + v3.VAL(3, V0); + Vector2 v1; + + for (u32 startDataIdx = 0; startDataIdx < 3; ++startDataIdx) { + for (u32 idx = 0; idx < 7; idx += 3) { + v1.VAL(0, _input[(startDataIdx + idx) ^ 1]); + Vector2 v4 = v1.ADD(v0); + _output.push_back(v4.data.vec32[0]); + _output.push_back(v4.data.vec32[1]); + v1 = v1.ADD(v3); + } + v1 = v1.ADD(v2); + v1.VAL(3, 0); + } +} + +static +void TriGen00_BuildColorIndices(u32 _step, u32 _vtxSize, std::vector & _colorIndices) +{ + u32 startColorIdx = 0; + u32 colorIdx = 0; + for (u32 i = 0; i < _vtxSize; i += _step) { + for (u32 j = 0; j < _step; ++j) { + _colorIndices[colorIdx++] = (startColorIdx + j * _step) << 2; + } + startColorIdx++; + } +} + +static +void TriGen00_BuildTextureCoords(u32 _step, const u32 * _params, std::vector & _texCoords) +{ + const u16 tex = _SHIFTR(_params[7], 0, 16); + union { + u16 w[2]; + u32 dw; + } texCoord; + u32 texIdx = 0; + for (u32 i = 0; i < _step; ++i) { + texCoord.w[0] = tex * (_step - 1); + texCoord.w[1] = tex * i; + for (u32 j = 0; j < _step; ++j) { + _texCoords[texIdx++] = texCoord.dw; + texCoord.dw -= tex; + } + } +} + +inline +int screenZ(const SPVertex & _v) +{ + return int(((_v.z / _v.w) * gSP.viewport.vscale[2] + gSP.viewport.vtrans[2])*32768.0f); +} + +static +int calcAvrgZ(GraphicsDrawer & drawer, const SWRSTriangle & t) +{ + int zsum = screenZ(drawer.getVertex(t.V0)); + zsum += screenZ(drawer.getVertex(t.V1)); + zsum += screenZ(drawer.getVertex(t.V2)); + return zsum / 3; +} + +static +void TriGen0000() +{ + const u32* params = (const u32*)&RDRAM[RSP.PC[RSP.PCi]]; + + // Step 1. Load data from RDRAM + + std::vector colorData(25); + TriGen0000_PrepareColorData(params, colorData); + + std::vector vtxData16(26, 0); + TriGen0000_PrepareVtxData(params, vtxData16); + + std::vector triangles; + + // Step 1.1 Options + + TriGen0000_option_00000100(params, vtxData16, colorData, triangles); + TriGen0000_ponderation1(params, vtxData16, colorData); + TriGen0000_option_00000001(params, vtxData16, colorData, triangles); + TriGen0000_ponderation2(params, vtxData16, colorData); + TriGen0000_option_01000000(params, vtxData16, colorData, triangles); + TriGen0000_ponderation3(params, vtxData16, colorData); + TriGen0000_option_00010000(params, vtxData16, colorData, triangles); + TriGen0000_ponderation4(params, vtxData16, colorData); + TriGen0000_ponderation5(params, vtxData16, colorData); + + // Step 2. Build vertex data from bytes obtained on Step 1. + + std::vector vtxData32; + TriGen00_BuildVtxData(params, 5, vtxData16, vtxData32); + + // Step 3. Process vertices + const SWVertex * vertex = (const SWVertex*)vtxData32.data(); + const size_t vtxSize = vtxData32.size() / 2; + gSPSWVertex(vertex, vtxSize, 0); + + // Step 4. Prepare color indices and texture coordinates. Prepare vertices for rendering + + std::vector colorIndices(vtxSize); + TriGen00_BuildColorIndices(5, vtxSize, colorIndices); + + std::vector texCoords(vtxSize); + TriGen00_BuildTextureCoords(5, params, texCoords); + + std::vector vertices(vtxSize); + for (u32 i = 0; i < vtxSize; i++) { + vertices[i] = i; + } + + F3DSWRS_PrepareVertices(vertices.data(), (u8*)colorData.data(), + colorIndices.data(), (u8*)texCoords.data(), true, false, vtxSize); + + // Step 5. Prepare triangles, sort them by z and draw. + + GraphicsDrawer & drawer = dwnd().getDrawer(); + + for (auto& t : triangles) { + t.avrgZ = calcAvrgZ(drawer, t); + } + for (u32 i = 0; i < 32; ++i) { + const SWRSTriangle & t = TriGen0000_defaultTriangleOrder[i]; + triangles.push_back(t); + triangles.back().avrgZ = calcAvrgZ(drawer, t); + } + std::stable_sort(triangles.begin(), triangles.end(), SWRSTriangleCompare); + + for (const auto& t : triangles) { + gSP1Triangle(t.V0, t.V1, t.V2); + } + drawer.drawTriangles(); +} + +static +void TriGen0001() +{ +#ifdef TRIGEN_DEBUG + u32 debug_params[10] = { + 0x05050001, + 0x01010101, + 0x8022C467, + 0x802139E4, + 0x00190064, + 0x00000000, + 0x00000000, + 0x000003F0, + 0xF0000000, + 0xF4000100 + }; + const u32* params = debug_params; +#else + + const u32* params = (const u32*)&RDRAM[RSP.PC[RSP.PCi]]; +#endif + + // Step 1. Load data from RDRAM + + std::vector colorData; + TriGen0001_PrepareColorData(params, colorData); + + std::vector vtxData16; + TriGen0001_PrepareVtxData(params, vtxData16); + + std::vector triangles; + + // Step 1.1 Options + + TriGen0001_option_01010201(params, vtxData16, colorData, triangles); + TriGen0001_ponderation1(params, vtxData16, colorData); + TriGen0001_option_01010102(params, vtxData16, colorData, triangles); + TriGen0001_ponderation2(params, vtxData16, colorData); + TriGen0001_option_02010101(params, vtxData16, colorData, triangles); + TriGen0001_ponderation3(params, vtxData16, colorData); + TriGen0001_option_01020101(params, vtxData16, colorData, triangles); + TriGen0001_ponderation4(params, vtxData16, colorData); + TriGen0001_ponderation5(params, vtxData16, colorData); + + // Step 2. Build vertex data from bytes obtained on Step 1. + + std::vector vtxData32; + TriGen00_BuildVtxData(params, 3, vtxData16, vtxData32); + + // Step 3. Process vertices + const SWVertex * vertex = (const SWVertex*)vtxData32.data(); + const size_t vtxSize = vtxData32.size() / 2; + gSPSWVertex(vertex, vtxSize, 0); + + // Step 4. Prepare color indices and texture coordinates. Prepare vertices for rendering + + std::vector colorIndices(vtxSize); + TriGen00_BuildColorIndices(3, vtxSize, colorIndices); + + std::vector texCoords(vtxSize); + TriGen00_BuildTextureCoords(3, params, texCoords); + + std::vector vertices(vtxSize); + for (u32 i = 0; i < vtxSize; i++) { + vertices[i] = i; + } + + F3DSWRS_PrepareVertices(vertices.data(), (u8*)colorData.data(), + colorIndices.data(), (u8*)texCoords.data(), true, false, vtxSize); + + // Step 5. Prepare triangles, sort them by z and draw. + + GraphicsDrawer & drawer = dwnd().getDrawer(); + + for (auto& t : triangles) { + t.avrgZ = calcAvrgZ(drawer, t); + } + for (u32 i = 0; i < 8; ++i) { + const SWRSTriangle & t = TriGen0001_defaultTriangleOrder[i]; + triangles.push_back(t); + triangles.back().avrgZ = calcAvrgZ(drawer, t); + } + std::stable_sort(triangles.begin(), triangles.end(), SWRSTriangleCompare); + + for (const auto& t : triangles) { + gSP1Triangle(t.V0, t.V1, t.V2); + } + drawer.drawTriangles(); +} + +static +void TriGen02() +{ + const u32* params = (const u32*)&RDRAM[RSP.PC[RSP.PCi]]; + + u32 vecdata[8]; + TriGen02_PrepareVtxData(params, vecdata); + const SWVertex * vertex = (const SWVertex*)&vecdata[0]; + gSPSWVertex(vertex, 4, 0); + GraphicsDrawer & drawer = dwnd().getDrawer(); + + const u32 v1 = 0; + const u32 v2 = 1; + const u32 v3 = 2; + const u32 v4 = 3; + const u32 vert[4] = { v1, v2, v3, v4 }; + + const u32 colorbase[4] = { params[3] | 0xFF, params[4] | 0xFF, params[5] | 0xFF, params[6] | 0xFF }; + const u32 color[4] = { 0, 4, 8, 12 }; + + const u32 tex = _SHIFTR(params[7], 0, 16); + const u32 texbase[4] = { tex, tex | (tex << 16), 0, (tex << 16) }; + + F3DSWRS_PrepareVertices(vert, (u8*)colorbase, color, (u8*)texbase, true, false, 4); + + SPVertex & vtx2 = drawer.getVertex(v2); + SPVertex & vtx3 = drawer.getVertex(v3); + + if (vtx3.z / vtx3.w > vtx2.z / vtx2.w) + gSP2Triangles(v1, v2, v4, 0, v1, v4, v3, 0); + else + gSP2Triangles(v1, v4, v3, 0, v1, v2, v4, 0); + drawer.drawTriangles(); +} + +void F3DSWRS_TriGen(u32 _w0, u32 _w1) +{ + DebugMsg(DEBUG_NORMAL, "F3DSWRS_TriGen (0x%08x, 0x%08x)\n", _w0, _w1); + + const u32 nextCmd = RSP.nextCmd; + RSP.nextCmd = G_TRI1; const u32 mode = _SHIFTR(_w0, 8, 8); switch (mode) { - case 0x02: + case 0x00: { - /* - u32 params[10] = { - 0x05050200, - 0xFDA00050, - 0xFDD00190, - 0xF4F4F401, - 0xE4E4E4FF, - 0xFFFFFFFF, - 0xFFFFFFFF, - 0x000007E0, - 0xF0000000, - 0xE2000200 }; - */ - u32 params[10]; - for (u32 i = 1; i < 10; ++i) - params[i] = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + i * 4]; - - u32 vecdata[8]; - Jump3_2(params, vecdata); - const SWVertex * vertex = (const SWVertex*)&vecdata[0]; - gSPSWVertex(vertex, 4, 0); - GraphicsDrawer & drawer = dwnd().getDrawer(); - if (_print) { - for (u32 i = 0; i < 4; ++i) { - SPVertex & v = drawer.getVertex(i); - f32 sx = v.x / v.w * gSP.viewport.vscale[0] + gSP.viewport.vtrans[0]; - f32 sy = v.y / v.w * gSP.viewport.vscale[1] + gSP.viewport.vtrans[1]; - f32 sz = v.z / v.w * gSP.viewport.vscale[2] + gSP.viewport.vtrans[2]; - DebugMsg(DEBUG_NORMAL, "v[%d] x=%02f y=%02f z=%02f\n", i, sx, gDP.scissor.lry - sy, sz); - } + const u32 mode00 = _SHIFTR(_w0, 0, 8); + switch (mode00) { + case 0x00: + TriGen0000(); + break; + case 0x01: + TriGen0001(); + break; + default: + break; } - - const u32 v1 = 0; - const u32 v2 = 1; - const u32 v3 = 2; - const u32 v4 = 3; - const u32 vert[4] = { v1, v2, v3, v4 }; - - const u32 colorbase[4] = { params[3] | 0xFF, params[4] | 0xFF, params[5] | 0xFF, params[6] | 0xFF }; - const u32 color[4] = { 0, 4, 8, 12 }; - - const u32 tex = _SHIFTR(params[7], 0, 16); - const u32 texbase[4] = { tex, tex | (tex << 16), 0, (tex << 16) }; - - - const bool useTex = true;// (_w0 & 2) != 0; - F3DSWRS_PrepareVertices(vert, (u8*)colorbase, color, (u8*)texbase, useTex, 4); - - SPVertex & vtx2 = drawer.getVertex(v2); - SPVertex & vtx3 = drawer.getVertex(v3); - - gSP.swrs_special = true; - if (vtx3.z / vtx3.w > vtx2.z / vtx2.w) - gSP2Triangles(v1, v2, v4, 0, v1, v4, v3, 0); - else - gSP2Triangles(v1, v4, v3, 0, v1, v2, v4, 0); - dwnd().getDrawer().drawTriangles(); - gSP.swrs_special = false; - } break; + case 0x02: + TriGen02(); + break; default: break; } - RSP.PC[RSP.PCi] = RSP.swDL[RSP.PCi].SWOtherDL; - RSP.swDL[RSP.PCi].SWStartDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi]], 0, 24); - RSP.swDL[RSP.PCi].SWOtherDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4], 0, 24); -} -inline -void _updateSWDL() -{ - // Lemmy's note: - // differs from the other DL commands because it does skip the first command - // the first 32 bits are stored, because they are - // used as branch target address in the command in the QUAD "slot" - RSP.swDL[RSP.PCi].SWStartDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi]], 0, 24); - RSP.swDL[RSP.PCi].SWOtherDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4], 0, 24); + RSP.nextCmd = nextCmd; + RSP.PC[RSP.PCi] += 32; +// RSP.PC[RSP.PCi] = RSP.swDL[RSP.PCi].SWOtherDL; +// RSP.swDL[RSP.PCi].SWStartDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi]], 0, 24); +// RSP.swDL[RSP.PCi].SWOtherDL = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4], 0, 24); } - void F3DSWRS_JumpSWDL(u32, u32) { DebugMsg(DEBUG_NORMAL, "F3DSWRS_JumpSWDL\n"); @@ -289,7 +1149,7 @@ void F3DSWRS_Tri1(u32 _w0, u32 _w1) const bool useTex = (_w0 & 2) != 0; const u8 * texbase = RDRAM + RSP.PC[RSP.PCi] + 16; - F3DSWRS_PrepareVertices(vert, RDRAM + gSP.vertexColorBase, color, texbase, useTex, 3); + F3DSWRS_PrepareVertices(vert, RDRAM + gSP.vertexColorBase, color, texbase, useTex, gDP.otherMode.texturePersp != 0, 3); if (useTex) RSP.PC[RSP.PCi] += 16; @@ -313,7 +1173,7 @@ void F3DSWRS_Tri2(u32 _w0, u32 _w1) const bool useTex = (_w0 & 2) != 0; const u8 * texbase = RDRAM + RSP.PC[RSP.PCi] + 16; - F3DSWRS_PrepareVertices(vert, RDRAM + gSP.vertexColorBase, color, texbase, useTex, 4); + F3DSWRS_PrepareVertices(vert, RDRAM + gSP.vertexColorBase, color, texbase, useTex, gDP.otherMode.texturePersp != 0, 4); if (useTex) RSP.PC[RSP.PCi] += 16; @@ -326,9 +1186,6 @@ void F3DSWRS_MoveWord(u32 _w0, u32 _w1) { DebugMsg(DEBUG_NORMAL, "F3DSWRS_MoveWord (0x%08x, 0x%08x)\n", _w0, _w1); switch (_SHIFTR(_w0, 0, 8)){ -// case 0x58C: // This PC is used after a texrect in naboo -// State.NabooPCAfterTexRect = Segment[Command.dl.segment] + Command.dl.addr; -// break; case G_MW_CLIP: gSPClipRatio( _w1 ); break; @@ -388,7 +1245,7 @@ void F3DSWRS_Init() GBI_SetGBI( G_RESERVED0, F3DSWRS_VTXCOLOR, F3DSWRS_VertexColor ); GBI_SetGBI( G_MOVEMEM, F3DSWRS_MOVEMEM, F3DSWRS_MoveMem ); GBI_SetGBI( G_VTX, F3DSWRS_VTX, F3DSWRS_Vtx ); - GBI_SetGBI( G_RESERVED1, F3DSWRS_JUMP3, F3DSWRS_Jump3 ); + GBI_SetGBI( G_RESERVED1, F3DSWRS_TRI_GEN, F3DSWRS_TriGen ); GBI_SetGBI( G_DL, F3DSWRS_DL, F3DSWRS_DList ); GBI_SetGBI( G_RESERVED2, F3DSWRS_BRANCHDL, F3DSWRS_BranchDList ); GBI_SetGBI( G_RESERVED3, F3D_RESERVED3, F3D_Reserved3 ); @@ -403,7 +1260,7 @@ void F3DSWRS_Init() GBI_SetGBI( G_ENDDL, F3DSWRS_ENDDL, F3DSWRS_EndDisplayList ); GBI_SetGBI( G_SETGEOMETRYMODE, F3D_SETGEOMETRYMODE, F3D_SetGeometryMode ); GBI_SetGBI( G_CLEARGEOMETRYMODE, F3D_CLEARGEOMETRYMODE, F3D_ClearGeometryMode ); - GBI_SetGBI( G_QUAD, F3DSWRS_JUMPSWDL, F3DSWRS_JumpSWDL ); - GBI_SetGBI( G_RDPHALF_1, F3DSWRS_TRI2, F3DSWRS_Tri2 ); + GBI_SetGBI( G_JUMPSWDL, F3DSWRS_JUMPSWDL, F3DSWRS_JumpSWDL ); + GBI_SetGBI( G_TRI2, F3DSWRS_TRI2, F3DSWRS_Tri2 ); GBI_SetGBI( G_SETOTHERMODE_L_EX, F3DSWRS_SETOTHERMODE_L_EX, F3DSWRS_SetOtherMode_L_EX ); } diff --git a/src/GraphicsDrawer.cpp b/src/GraphicsDrawer.cpp index 04bf5e9b..408105fe 100644 --- a/src/GraphicsDrawer.cpp +++ b/src/GraphicsDrawer.cpp @@ -666,11 +666,6 @@ void GraphicsDrawer::drawTriangles() _prepareDrawTriangle(); - if (gSP.swrs_special) { - CombinerInfo::get().setCombine(EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, 1, 0, 0, 0, SHADE, 0, 0, 0, 1)); - currentCombiner()->update(true); - } - Context::DrawTriangleParameters triParams; triParams.mode = drawmode::TRIANGLES; triParams.flatColors = m_bFlatColors; diff --git a/src/gSP.h b/src/gSP.h index d859a52d..5f1f7379 100644 --- a/src/gSP.h +++ b/src/gSP.h @@ -140,7 +140,6 @@ struct gSPInfo u32 textureCoordScaleOrg; u32 textureCoordScale[2]; - bool swrs_special; }; extern gSPInfo gSP;