From a8021084f25b6c4b91f39e466cff815f44c2443c Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Tue, 7 Oct 2014 17:59:54 +0700 Subject: [PATCH] Implement LLE triangles. --- F3D.cpp | 16 +- OpenGL.cpp | 53 ++++- OpenGL.h | 2 + PluginAPI.h | 3 +- RDP.cpp | 267 +++++++++++++++++++++++- RDP.h | 12 ++ RSP.cpp | 1 + RSP.h | 1 + common/CommonAPIImpl_common.cpp | 14 ++ gDP.cpp | 353 ++++++++++++++++++++++++++++++++ gDP.h | 11 +- 11 files changed, 701 insertions(+), 32 deletions(-) diff --git a/F3D.cpp b/F3D.cpp index 222c340b..36fde62d 100644 --- a/F3D.cpp +++ b/F3D.cpp @@ -310,22 +310,8 @@ void F3D_Quad( u32 w0, u32 w1 ) void F3D_RDPHalf_1( u32 w0, u32 w1 ) { -/* if (_SHIFTR( w1, 24, 8 ) == 0xCE) - { - u32 w2 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; - RSP.PC[RSP.PCi] += 8; - - gDPTextureRectangle( gDP.scissor.ulx, // ulx - _FIXED2FLOAT( _SHIFTR( w2, 0, 16 ), 2 ), // uly - gDP.scissor.lrx, // lrx - _FIXED2FLOAT( _SHIFTR( w2, 16, 16 ), 2 ), // lry - 0, // tile - 0, // s - 0, // t - 1, // dsdx - 1 ); // dsdy - }*/ gDP.half_1 = w1; + RDP_Half_1(w1); } void F3D_RDPHalf_2( u32 w0, u32 w1 ) diff --git a/OpenGL.cpp b/OpenGL.cpp index b714bfcf..4c620b16 100644 --- a/OpenGL.cpp +++ b/OpenGL.cpp @@ -605,10 +605,8 @@ void OGLRender::_setTexCoordArrays() const glDisableVertexAttribArray(SC_STSCALED); } -void OGLRender::drawTriangles() +void OGLRender::_prepareDrawTriangle() { - if (triangles.num == 0) return; - #ifndef GLES2 if (m_bImageTexture) glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); @@ -641,8 +639,53 @@ void OGLRender::drawTriangles() currentCombiner()->updateRenderState(); } - currentCombiner()->updateColors(true); - currentCombiner()->updateLight(true); + currentCombiner()->updateColors(); + currentCombiner()->updateLight(); +} + +void OGLRender::drawLLETriangle(u32 _numVtx) +{ + if (_numVtx == 0) + return; + + _prepareDrawTriangle(); + glDisable(GL_CULL_FACE); + + FrameBufferList & fbList = frameBufferList(); + FrameBuffer* pBuffer = fbList.getCurrent(); + OGLVideo & ogl = video(); + if (!fbList.isFboMode()) + glViewport( 0, ogl.getHeightOffset(), ogl.getScreenWidth(), ogl.getScreenHeight()); + else + glViewport(0, 0, pBuffer->m_width*pBuffer->m_scaleX, pBuffer->m_height*pBuffer->m_scaleY); + + const float scaleX = fbList.isFboMode() ? 1.0f / pBuffer->m_width : VI.rwidth; + const float scaleY = fbList.isFboMode() ? 1.0f / pBuffer->m_height : VI.rheight; + + for (u32 i = 0; i < _numVtx; ++i) { + triangles.vertices[i].HWLight = 0; + triangles.vertices[i].st_scaled = 0; + triangles.vertices[i].x = triangles.vertices[i].x * (2.0f * scaleX) - 1.0f; + triangles.vertices[i].x *= triangles.vertices[i].w; + triangles.vertices[i].y = triangles.vertices[i].y * (-2.0f * scaleY) + 1.0f; + triangles.vertices[i].y *= triangles.vertices[i].w; + } + + glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVtx); + triangles.num = 0; + + gSP.changed != CHANGED_VIEWPORT | CHANGED_GEOMETRYMODE; + +#ifdef __TRIBUFFER_OPT + _indexmap_clear(); +#endif +} + +void OGLRender::drawTriangles() +{ + if (triangles.num == 0) return; + + _prepareDrawTriangle(); glDrawElements(GL_TRIANGLES, triangles.num, GL_UNSIGNED_BYTE, triangles.elements); triangles.num = 0; diff --git a/OpenGL.h b/OpenGL.h index 9d98062a..fd14374b 100644 --- a/OpenGL.h +++ b/OpenGL.h @@ -34,6 +34,7 @@ class OGLRender public: void addTriangle(int _v0, int _v1, int _v2); void drawTriangles(); + void drawLLETriangle(u32 _numVtx); void drawLine(int _v0, int _v1, float _width); void drawRect(int _ulx, int _uly, int _lrx, int _lry, float * _pColor); void drawTexturedRect( @@ -84,6 +85,7 @@ private: void _updateViewport() const; void _updateDepthUpdate() const; void _updateStates() const; + void _prepareDrawTriangle(); #ifdef __TRIBUFFER_OPT void _indexmap_init(); diff --git a/PluginAPI.h b/PluginAPI.h index 566d95e4..5c803614 100644 --- a/PluginAPI.h +++ b/PluginAPI.h @@ -14,6 +14,7 @@ enum API_COMMAND { acNone = 0, acProcessDList, + acProcessRDPList, acUpdateScreen, acRomClosed }; @@ -31,11 +32,11 @@ public: // Common void MoveScreen(int /*_xpos*/, int /*_ypos*/) {} - void ProcessRDPList() {} void ViStatusChanged() {} void ViWidthChanged() {} void ProcessDList(); + void ProcessRDPList(); void RomClosed(); void RomOpen(); void ShowCFB(); diff --git a/RDP.cpp b/RDP.cpp index 7169e0a1..4b5fdef8 100644 --- a/RDP.cpp +++ b/RDP.cpp @@ -1,5 +1,6 @@ #include "N64.h" #include "RSP.h" +#include "RDP.h" #include "GBI.h" #include "gDP.h" #include "Debug.h" @@ -214,12 +215,17 @@ void RDP_LoadSync( u32 w0, u32 w1 ) void RDP_TexRectFlip( u32 w0, u32 w1 ) { - u32 w2 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; - RSP.PC[RSP.PCi] += 8; - - u32 w3 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; - RSP.PC[RSP.PCi] += 8; + u32 w2, w3; + if (RSP.bLLE) { + w2 = RDP.w2; + w3 = RDP.w3; + } else { + w2 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; + RSP.PC[RSP.PCi] += 8; + w3 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; + RSP.PC[RSP.PCi] += 8; + } gDPTextureRectangleFlip( _FIXED2FLOAT( _SHIFTR( w1, 12, 12 ), 2 ), // ulx _FIXED2FLOAT( _SHIFTR( w1, 0, 12 ), 2 ), // uly _FIXED2FLOAT( _SHIFTR( w0, 12, 12 ), 2 ), // lrx @@ -233,12 +239,17 @@ void RDP_TexRectFlip( u32 w0, u32 w1 ) void RDP_TexRect( u32 w0, u32 w1 ) { - u32 w2 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; - RSP.PC[RSP.PCi] += 8; - - u32 w3 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; - RSP.PC[RSP.PCi] += 8; + u32 w2, w3; + if (RSP.bLLE) { + w2 = RDP.w2; + w3 = RDP.w3; + } else { + w2 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; + RSP.PC[RSP.PCi] += 8; + w3 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; + RSP.PC[RSP.PCi] += 8; + } gDPTextureRectangle( _FIXED2FLOAT( _SHIFTR( w1, 12, 12 ), 2 ), // ulx _FIXED2FLOAT( _SHIFTR( w1, 0, 12 ), 2 ), // uly _FIXED2FLOAT( _SHIFTR( w0, 12, 12 ), 2 ), // lrx @@ -250,6 +261,48 @@ void RDP_TexRect( u32 w0, u32 w1 ) _FIXED2FLOAT( (s16)_SHIFTR( w3, 0, 16 ), 10 ) ); // dsdy } +void RDP_TriFill( u32 _w0, u32 _w1 ) +{ + gDPTriFill(_w0, _w1); +} + +void RDP_TriShade( u32 _w0, u32 _w1 ) +{ + gDPTriShade(_w0, _w1); +} + +void RDP_TriTxtr( u32 _w0, u32 _w1 ) +{ + gDPTriTxtr(_w0, _w1); +} + +void RDP_TriShadeTxtr( u32 _w0, u32 _w1 ) +{ + gDPTriShadeTxtr(_w0, _w1); +} + +void RDP_TriFillZ( u32 _w0, u32 _w1 ) +{ + gDPTriFillZ(_w0, _w1); +} + +void RDP_TriShadeZ( u32 _w0, u32 _w1 ) +{ + gDPTriShadeZ(_w0, _w1); +} + +void RDP_TriTxtrZ( u32 _w0, u32 _w1 ) +{ + gDPTriTxtrZ(_w0, _w1); +} + +void RDP_TriShadeTxtrZ( u32 _w0, u32 _w1 ) +{ + gDPTriShadeTxtrZ(_w0, _w1); +} + +RDPInfo RDP; + void RDP_Init() { // Initialize RDP commands to RDP_UNKNOWN @@ -289,5 +342,199 @@ void RDP_Init() GBI.cmd[G_RDPLOADSYNC] = RDP_LoadSync; GBI.cmd[G_TEXRECTFLIP] = RDP_TexRectFlip; GBI.cmd[G_TEXRECT] = RDP_TexRect; + + RDP.w2 = RDP.w3 = 0; + RDP.cmd_ptr = RDP.cmd_cur = 0; } +static +GBIFunc LLEcmd[64] = { + /* 0x00 */ + RDP_NoOp, RDP_Unknown, RDP_Unknown, RDP_Unknown, + RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown, + RDP_TriFill, RDP_TriFillZ, RDP_TriTxtr, RDP_TriTxtrZ, + RDP_TriShade, RDP_TriShadeZ, RDP_TriShadeTxtr, RDP_TriShadeTxtrZ, + /* 0x10 */ + RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown, + RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown, + RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown, + RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown, + /* 0x20 */ + RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown, + RDP_TexRect, RDP_TexRectFlip, RDP_LoadSync, RDP_PipeSync, + RDP_TileSync, RDP_FullSync, RDP_SetKeyGB, RDP_SetKeyR, + RDP_SetConvert, RDP_SetScissor, RDP_SetPrimDepth, RDP_SetOtherMode, + /* 0x30 */ + RDP_LoadTLUT, RDP_Unknown, RDP_SetTileSize, RDP_LoadBlock, + RDP_LoadTile, RDP_SetTile, RDP_FillRect, RDP_SetFillColor, + RDP_SetFogColor, RDP_SetBlendColor, RDP_SetPrimColor, RDP_SetEnvColor, + RDP_SetCombine, RDP_SetTImg, RDP_SetZImg, RDP_SetCImg +}; + +static +const u32 CmdLength[64] = +{ + 8, // 0x00, No Op + 8, // 0x01, ??? + 8, // 0x02, ??? + 8, // 0x03, ??? + 8, // 0x04, ??? + 8, // 0x05, ??? + 8, // 0x06, ??? + 8, // 0x07, ??? + 32, // 0x08, Non-Shaded Triangle + 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle + 32+64, // 0x0a, Textured Triangle + 32+64+16, // 0x0b, Textured, Z-Buffered Triangle + 32+64, // 0x0c, Shaded Triangle + 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle + 32+64+64, // 0x0e, Shaded+Textured Triangle + 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle + 8, // 0x10, ??? + 8, // 0x11, ??? + 8, // 0x12, ??? + 8, // 0x13, ??? + 8, // 0x14, ??? + 8, // 0x15, ??? + 8, // 0x16, ??? + 8, // 0x17, ??? + 8, // 0x18, ??? + 8, // 0x19, ??? + 8, // 0x1a, ??? + 8, // 0x1b, ??? + 8, // 0x1c, ??? + 8, // 0x1d, ??? + 8, // 0x1e, ??? + 8, // 0x1f, ??? + 8, // 0x20, ??? + 8, // 0x21, ??? + 8, // 0x22, ??? + 8, // 0x23, ??? + 16, // 0x24, Texture_Rectangle + 16, // 0x25, Texture_Rectangle_Flip + 8, // 0x26, Sync_Load + 8, // 0x27, Sync_Pipe + 8, // 0x28, Sync_Tile + 8, // 0x29, Sync_Full + 8, // 0x2a, Set_Key_GB + 8, // 0x2b, Set_Key_R + 8, // 0x2c, Set_Convert + 8, // 0x2d, Set_Scissor + 8, // 0x2e, Set_Prim_Depth + 8, // 0x2f, Set_Other_Modes + 8, // 0x30, Load_TLUT + 8, // 0x31, ??? + 8, // 0x32, Set_Tile_Size + 8, // 0x33, Load_Block + 8, // 0x34, Load_Tile + 8, // 0x35, Set_Tile + 8, // 0x36, Fill_Rectangle + 8, // 0x37, Set_Fill_Color + 8, // 0x38, Set_Fog_Color + 8, // 0x39, Set_Blend_Color + 8, // 0x3a, Set_Prim_Color + 8, // 0x3b, Set_Env_Color + 8, // 0x3c, Set_Combine + 8, // 0x3d, Set_Texture_Image + 8, // 0x3e, Set_Mask_Image + 8 // 0x3f, Set_Color_Image +}; + +void RDP_Half_1( u32 _c ) +{ + u32 w0 = 0, w1 = _c; + u32 cmd = _SHIFTR( _c, 24, 8 ); + if (cmd >= 0xc8 && cmd <=0xcf) {//triangle command + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPHalf_1 LLE Triangle\n"); + RDP.cmd_ptr = 0; + RDP.cmd_cur = 0; + do { + RDP.cmd_data[RDP.cmd_ptr++] = w1; + RSP_CheckDLCounter(); + + w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]]; + w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; + RSP.cmd = _SHIFTR( w0, 24, 8 ); + + DebugRSPState( RSP.PCi, RSP.PC[RSP.PCi], _SHIFTR( w0, 24, 8 ), w0, w1 ); + DebugMsg( DEBUG_LOW | DEBUG_HANDLED, "0x%08lX: CMD=0x%02lX W0=0x%08lX W1=0x%08lX\n", RSP.PC[RSP.PCi], _SHIFTR( w0, 24, 8 ), w0, w1 ); + + RSP.PC[RSP.PCi] += 8; + // RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 ); + } while (RSP.cmd != 0xb3); + RDP.cmd_data[RDP.cmd_ptr++] = w1; + RSP.cmd = (RDP.cmd_data[RDP.cmd_cur] >> 24) & 0x3f; + w0 = RDP.cmd_data[RDP.cmd_cur+0]; + w1 = RDP.cmd_data[RDP.cmd_cur+1]; + LLEcmd[RSP.cmd](w0, w1); + } else { + DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPHalf_1()\n" ); + } +} + +#define rdram ((u32*)RDRAM) +#define rsp_dmem ((u32*)DMEM) + +#define dp_start (*(u32*)REG.DPC_START) +#define dp_end (*(u32*)REG.DPC_END) +#define dp_current (*(u32*)REG.DPC_CURRENT) +#define dp_status (*(u32*)REG.DPC_STATUS) + +inline u32 READ_RDP_DATA(u32 address) +{ + if (dp_status & 0x1) // XBUS_DMEM_DMA enabled + return rsp_dmem[(address & 0xfff)>>2]; + else + return rdram[address>>2]; +} + +void RDP_ProcessRDPList() +{ + DebugMsg(DEBUG_HIGH | DEBUG_HANDLED, "ProcessRDPList()\n"); + + u32 i; + u32 cmd, length, cmd_length; + RDP.cmd_ptr = 0; + RDP.cmd_cur = 0; + + if (dp_end <= dp_current) return; + length = dp_end - dp_current; + + // load command data + for (i = 0; i < length; i += 4) { + RDP.cmd_data[RDP.cmd_ptr++] = READ_RDP_DATA(dp_current + i); + if (RDP.cmd_ptr >= 0x1000) { + DebugMsg(DEBUG_HIGH | DEBUG_ERROR, "rdp_process_list: RDP.cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end); + } + } + + dp_current = dp_end; + + cmd = (RDP.cmd_data[0] >> 24) & 0x3f; + cmd_length = (RDP.cmd_ptr + 1) * 4; + + // check if more data is needed + if (cmd_length < CmdLength[cmd]) + return; + RSP.bLLE = true; + while (RDP.cmd_cur < RDP.cmd_ptr) { + cmd = (RDP.cmd_data[RDP.cmd_cur] >> 24) & 0x3f; + + if (((RDP.cmd_ptr-RDP.cmd_cur) * 4) < CmdLength[cmd]) + return; + + // execute the command + u32 w0 = RDP.cmd_data[RDP.cmd_cur+0]; + u32 w1 = RDP.cmd_data[RDP.cmd_cur+1]; + RDP.w2 = RDP.cmd_data[RDP.cmd_cur+2]; + RDP.w3 = RDP.cmd_data[RDP.cmd_cur+3]; + LLEcmd[cmd](w0, w1); + + RDP.cmd_cur += CmdLength[cmd] / 4; + }; + RSP.bLLE = false; + + dp_start = dp_end; + + dp_status &= ~0x0002; +} diff --git a/RDP.h b/RDP.h index 73e970b7..6ad87e6a 100644 --- a/RDP.h +++ b/RDP.h @@ -1,7 +1,19 @@ #ifndef RDP_H #define RDP_H +typedef struct +{ + u32 w2, w3; + u32 cmd_ptr; + u32 cmd_cur; + u32 cmd_data[0x1000]; +} RDPInfo; + +extern RDPInfo RDP; + void RDP_Init(); +void RDP_Half_1(u32 _c); +void RDP_ProcessRDPList(); #endif diff --git a/RSP.cpp b/RSP.cpp index 6f94962b..eefe5365 100644 --- a/RSP.cpp +++ b/RSP.cpp @@ -261,6 +261,7 @@ void RSP_Init() RSP.DList = 0; RSP.uc_start = RSP.uc_dstart = 0; + RSP.bLLE = false; gDP.loadTile = &gDP.tiles[7]; gSP.textureTile[0] = &gDP.tiles[0]; diff --git a/RSP.h b/RSP.h index 795a5222..06ef3fb2 100644 --- a/RSP.h +++ b/RSP.h @@ -7,6 +7,7 @@ typedef struct { u32 PC[18], PCi, busy, halt, close, DList, uc_start, uc_dstart, cmd, nextCmd; s32 count; + bool bLLE; } RSPInfo; extern RSPInfo RSP; diff --git a/common/CommonAPIImpl_common.cpp b/common/CommonAPIImpl_common.cpp index 2462d641..89f83f99 100644 --- a/common/CommonAPIImpl_common.cpp +++ b/common/CommonAPIImpl_common.cpp @@ -11,6 +11,7 @@ #include "../GLideN64.h" #include "../OpenGL.h" #include "../RSP.h" +#include "../RDP.h" #include "../VI.h" #include "../Debug.h" #include "../Log.h" @@ -33,6 +34,9 @@ void RSP_ThreadProc(std::mutex * _pRspThreadMtx, std::mutex * _pPluginThreadMtx, case acProcessDList: RSP_ProcessDList(); break; + case acProcessRDPList: + RDP_ProcessRDPList(); + break; case acUpdateScreen: VI_UpdateScreen(); break; @@ -73,6 +77,16 @@ void PluginAPI::ProcessDList() #endif } +void PluginAPI::ProcessRDPList() +{ + LOG(LOG_APIFUNC, "ProcessRDPList\n"); +#ifdef RSPTHREAD + _callAPICommand(acProcessRDPList); +#else + RDP_ProcessRDPList(); +#endif +} + void PluginAPI::RomClosed() { LOG(LOG_APIFUNC, "RomClosed\n"); diff --git a/gDP.cpp b/gDP.cpp index 01b78ec7..89a5f774 100644 --- a/gDP.cpp +++ b/gDP.cpp @@ -4,6 +4,7 @@ #include "N64.h" #include "GBI.h" #include "RSP.h" +#include "RDP.h" #include "gDP.h" #include "gSP.h" #include "Types.h" @@ -952,3 +953,355 @@ void gDPNoOp() DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPNoOp();\n" ); #endif } + +/******************************************* + * Low level triangle * + ******************************************* + * based on sources of ziggy's z64 * + *******************************************/ + +void gDPLLETriangle(u32 _w1, u32 _w2, int _shade, int _texture, int _zbuffer, u32 * _pRdpCmd) +{ + const u32 tile = _SHIFTR(_w1, 16, 3); + gDPTile *textureTileOrg[2]; + textureTileOrg[0] = gSP.textureTile[0]; + textureTileOrg[1] = gSP.textureTile[1]; + gSP.textureTile[0] = &gDP.tiles[tile]; + gSP.textureTile[1] = &gDP.tiles[tile < 7 ? tile + 1 : tile]; + + int j; + int xleft, xright, xleft_inc, xright_inc; + int r, g, b, a, z, s, t, w; + int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0; + int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0; + int flip = (_w1 & 0x800000) ? 1 : 0; + + s32 yl, ym, yh; + s32 xl, xm, xh; + s32 dxldy, dxhdy, dxmdy; + u32 w3, w4, w5, w6, w7, w8; + + u32 * shade_base = _pRdpCmd + 8; + u32 * texture_base = _pRdpCmd + 8; + u32 * zbuffer_base = _pRdpCmd + 8; + + if (_shade != 0) { + texture_base += 16; + zbuffer_base += 16; + } + if (_texture != 0) { + zbuffer_base += 16; + } + + w3 = _pRdpCmd[2]; + w4 = _pRdpCmd[3]; + w5 = _pRdpCmd[4]; + w6 = _pRdpCmd[5]; + w7 = _pRdpCmd[6]; + w8 = _pRdpCmd[7]; + + yl = (_w1 & 0x3fff); + ym = ((_w2 >> 16) & 0x3fff); + yh = ((_w2 >> 0) & 0x3fff); + xl = (s32)(w3); + xh = (s32)(w5); + xm = (s32)(w7); + dxldy = (s32)(w4); + dxhdy = (s32)(w6); + dxmdy = (s32)(w8); + + if (yl & (0x800<<2)) yl |= 0xfffff000<<2; + if (ym & (0x800<<2)) ym |= 0xfffff000<<2; + if (yh & (0x800<<2)) yh |= 0xfffff000<<2; + + yh &= ~3; + + r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000; + + if (_shade != 0) { + r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff); + g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff); + b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff); + a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff); + drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff); + dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff); + dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff); + dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff); + drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff); + dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff); + dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff); + dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff); + } + if (_texture != 0) { + s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff); + t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff); + w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff); + // w = abs(w); + dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff); + dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff); + dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff); + dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff); + dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff); + dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff); + } + if (_zbuffer != 0) { + z = zbuffer_base[0]; + dzdx = zbuffer_base[1]; + dzde = zbuffer_base[2]; + } + + xh <<= 2; xm <<= 2; xl <<= 2; + r <<= 2; g <<= 2; b <<= 2; a <<= 2; + dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2; + dzdx >>= 2; dzde >>= 2; + dwdx >>= 2; dwde >>= 2; + +#define XSCALE(x) (float(x)/(1<<18)) +#define YSCALE(y) (float(y)/(1<<2)) +#define ZSCALE(z) ((gDP.otherMode.depthSource == G_ZS_PRIM)? gDP.primDepth.z : float(u32(z))/0xffff0000) + //#define WSCALE(w) (bPerspEnabled? (float(u32(w) + 0x10000)/0xffff0000) : 1.0f) + //#define WSCALE(w) (bPerspEnabled? 4294901760.0/(w + 65536) : 1.0f) +#define PERSP_EN (gDP.otherMode.texturePersp != 0) +#define WSCALE(w) (PERSP_EN? 65536.0f/float((w+ 0xffff)>>16) : 1.0f) +#define CSCALE(c) ((((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)*0.0039215689f) +#define _PERSP(w) ( w ) +#define PERSP(s, w) ( ((s64)(s) << 20) / (_PERSP(w)? _PERSP(w):1) ) +#define SSCALE(s, _w) (PERSP_EN? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21)) +#define TSCALE(s, w) (PERSP_EN? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21)) + + u32 nbVtxs = 0; + OGLRender & render = video().getRender(); + SPVertex * vtx = &render.getVertex(nbVtxs++); + + xleft = xm; + xright = xh; + xleft_inc = dxmdy; + xright_inc = dxhdy; + + while (yh xright-0x10000))) { + xleft += xleft_inc; + xright += xright_inc; + s += dsde; t += dtde; w += dwde; + r += drde; g += dgde; b += dbde; a += dade; + z += dzde; + yh++; + } + + j = ym-yh; + if (j > 0) { + int dx = (xleft-xright)>>16; + if ((!flip && xleft < xright) || + (flip/* && xleft > xright*/)) + { + if (_shade != 0) { + vtx->r = CSCALE(r+drdx*dx); + vtx->g = CSCALE(g+dgdx*dx); + vtx->b = CSCALE(b+dbdx*dx); + vtx->a = CSCALE(a+dadx*dx); + } + if (_texture != 0) { + vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx); + vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx); + } + vtx->x = XSCALE(xleft); + vtx->y = YSCALE(yh); + vtx->z = ZSCALE(z+dzdx*dx); + vtx->w = WSCALE(w+dwdx*dx); + vtx = &render.getVertex(nbVtxs++); + } + if ((!flip/* && xleft < xright*/) || + (flip && xleft > xright)) + { + if (_shade != 0) { + vtx->r = CSCALE(r); + vtx->g = CSCALE(g); + vtx->b = CSCALE(b); + vtx->a = CSCALE(a); + } + if (_texture != 0) { + vtx->s = SSCALE(s, w); + vtx->t = TSCALE(t, w); + } + vtx->x = XSCALE(xright); + vtx->y = YSCALE(yh); + vtx->z = ZSCALE(z); + vtx->w = WSCALE(w); + vtx = &render.getVertex(nbVtxs++); + } + xleft += xleft_inc*j; xright += xright_inc*j; + s += dsde*j; t += dtde*j; + if (w + dwde*j) w += dwde*j; + else w += dwde*(j-1); + r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; + z += dzde*j; + // render ... + } + + if (xl != xh) + xleft = xl; + + //if (yl-ym > 0) + { + int dx = (xleft-xright)>>16; + if ((!flip && xleft <= xright) || + (flip/* && xleft >= xright*/)) + { + if (_shade != 0) { + vtx->r = CSCALE(r+drdx*dx); + vtx->g = CSCALE(g+dgdx*dx); + vtx->b = CSCALE(b+dbdx*dx); + vtx->a = CSCALE(a+dadx*dx); + } + if (_texture != 0) { + vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx); + vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx); + } + vtx->x = XSCALE(xleft); + vtx->y = YSCALE(ym); + vtx->z = ZSCALE(z+dzdx*dx); + vtx->w = WSCALE(w+dwdx*dx); + vtx = &render.getVertex(nbVtxs++); + } + if ((!flip/* && xleft <= xright*/) || + (flip && xleft >= xright)) + { + if (_shade != 0) { + vtx->r = CSCALE(r); + vtx->g = CSCALE(g); + vtx->b = CSCALE(b); + vtx->a = CSCALE(a); + } + if (_texture != 0) { + vtx->s = SSCALE(s, w); + vtx->t = TSCALE(t, w); + } + vtx->x = XSCALE(xright); + vtx->y = YSCALE(ym); + vtx->z = ZSCALE(z); + vtx->w = WSCALE(w); + vtx = &render.getVertex(nbVtxs++); + } + } + xleft_inc = dxldy; + xright_inc = dxhdy; + + j = yl-ym; + //j--; // ? + xleft += xleft_inc*j; xright += xright_inc*j; + s += dsde*j; t += dtde*j; w += dwde*j; + r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; + z += dzde*j; + + while (yl>ym && + !((!flip && xleft < xright+0x10000) || + (flip && xleft > xright-0x10000))) { + xleft -= xleft_inc; xright -= xright_inc; + s -= dsde; t -= dtde; w -= dwde; + r -= drde; g -= dgde; b -= dbde; a -= dade; + z -= dzde; + --j; + --yl; + } + + // render ... + if (j >= 0) { + int dx = (xleft-xright)>>16; + if ((!flip && xleft <= xright) || + (flip/* && xleft >= xright*/)) + { + if (_shade != 0) { + vtx->r = CSCALE(r+drdx*dx); + vtx->g = CSCALE(g+dgdx*dx); + vtx->b = CSCALE(b+dbdx*dx); + vtx->a = CSCALE(a+dadx*dx); + } + if (_texture != 0) { + vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx); + vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx); + } + vtx->x = XSCALE(xleft); + vtx->y = YSCALE(yl); + vtx->z = ZSCALE(z+dzdx*dx); + vtx->w = WSCALE(w+dwdx*dx); + vtx = &render.getVertex(nbVtxs++); + } + if ((!flip/* && xleft <= xright*/) || + (flip && xleft >= xright)) + { + if (_shade != 0) { + vtx->r = CSCALE(r); + vtx->g = CSCALE(g); + vtx->b = CSCALE(b); + vtx->a = CSCALE(a); + } + if (_texture != 0) { + vtx->s = SSCALE(s, w); + vtx->t = TSCALE(t, w); + } + vtx->x = XSCALE(xright); + vtx->y = YSCALE(yl); + vtx->z = ZSCALE(z); + vtx->w = WSCALE(w); + vtx = &render.getVertex(nbVtxs++); + } + } + + render.drawLLETriangle(nbVtxs - 1); + gSP.textureTile[0] = textureTileOrg[0]; + gSP.textureTile[1] = textureTileOrg[1]; +} + +static void gDPTriangle(u32 _w1, u32 _w2, int shade, int texture, int zbuffer) +{ + gDPLLETriangle(_w1, _w2, shade, texture, zbuffer, RDP.cmd_data + RDP.cmd_cur); +} + +void gDPTriFill(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 0, 0, 0); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trifill\n"); +} + +void gDPTriShade(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 1, 0, 0); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishade\n"); +} + +void gDPTriTxtr(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 0, 1, 0); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "tritxtr\n"); +} + +void gDPTriShadeTxtr(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 1, 1, 0); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishadetxtr\n"); +} + +void gDPTriFillZ(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 0, 0, 1); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trifillz\n"); +} + +void gDPTriShadeZ(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 1, 0, 1); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishadez\n"); +} + +void gDPTriTxtrZ(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 0, 1, 1); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "tritxtrz\n"); +} + +void gDPTriShadeTxtrZ(u32 w0, u32 w1) +{ + gDPTriangle(w0, w1, 1, 1, 1); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishadetxtrz\n"); +} diff --git a/gDP.h b/gDP.h index b22e21b7..91813e31 100644 --- a/gDP.h +++ b/gDP.h @@ -138,7 +138,7 @@ struct gDPInfo unsigned int blendMask : 4; unsigned int alphaDither : 2; unsigned int colorDither : 2; - + unsigned int combineKey : 1; unsigned int textureConvert : 3; unsigned int textureFilter : 2; @@ -282,6 +282,15 @@ void gDPPipeSync(); void gDPLoadSync(); void gDPNoOp(); +void gDPTriFill( u32 w0, u32 w1 ); +void gDPTriShade( u32 w0, u32 w1 ); +void gDPTriTxtr( u32 w0, u32 w1 ); +void gDPTriShadeTxtr( u32 w0, u32 w1 ); +void gDPTriFillZ( u32 w0, u32 w1 ); +void gDPTriShadeZ( u32 w0, u32 w1 ); +void gDPTriTxtrZ( u32 w0, u32 w1 ); +void gDPTriShadeTxtrZ( u32 w0, u32 w1 ); + void gDPFillRDRAM( u32 address, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 width, u32 size, u32 color ); #endif