From 776968e0f510979c2f86f61ea7d70ea3ce8c756e Mon Sep 17 00:00:00 2001 From: gocha Date: Fri, 24 Dec 2010 13:59:19 +0000 Subject: [PATCH] 0.9.6: line hack --- desmume/src/OGLRender.cpp | 60 +----------------------------------- desmume/src/gfx3d.cpp | 57 ++++++++++++++++++++++++++++++++++ desmume/src/gfx3d.h | 2 ++ desmume/src/rasterize.cpp | 65 +++++++++++++++++++-------------------- 4 files changed, 91 insertions(+), 93 deletions(-) diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index cde0a9a89..9cc50522c 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -813,64 +813,6 @@ static void GL_ReadFramebuffer() } -// "Workaround" for line poly -static bool isLinePoly(POLY *poly) -{ - int type = poly->type; - VERT *vert1, *vert2; - - if (type <= 2) - return true; - else if (type > 4) - return false; - - // Method 1: - // Castlevania Portrait of Ruin - trajectory of ricochet - bool duplicatedVert[4] = { false, false, false, false }; - for(int i = 0; i < type - 1; i++) - { - vert1 = &gfx3d.vertlist->list[poly->vertIndexes[i]]; - for(int j = i + 1; j < type; j++) - { - vert2 = &gfx3d.vertlist->list[poly->vertIndexes[j]]; - if (vert1->x == vert2->x && vert1->y == vert2->y) - { - duplicatedVert[j] = true; - } - } - } - int vertCount = type; - for(int i = 0; i < type; i++) - { - if (duplicatedVert[i]) - vertCount--; - } - if (vertCount <= 2) - return true; - - // Method 2: - // Castlevania Portrait of Ruin - warp stone - bool horizontalLine = true; - bool verticalLine = true; - vert1 = &gfx3d.vertlist->list[poly->vertIndexes[0]]; - for(int i = 1; i < type && (horizontalLine || verticalLine); i++) - { - vert2 = &gfx3d.vertlist->list[poly->vertIndexes[i]]; - if (vert1->coord[0] != vert2->coord[0]) - { - verticalLine = false; - } - if (vert1->coord[1] != vert2->coord[1]) - { - horizontalLine = false; - } - } - if (horizontalLine || verticalLine) - return true; - - return false; -} - static void OGLRender() { if(!BEGINGL()) return; @@ -971,7 +913,7 @@ static void OGLRender() lastViewport = poly->viewport; } - if (isLinePoly(poly)) + if (gfx3d_IsLinePoly(poly)) glBegin(GL_LINE_LOOP); else glBegin(GL_TRIANGLES); diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 0d9109c0c..4635f4a3c 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -2760,3 +2760,60 @@ void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts) } #endif +// "Workaround" for line poly +bool gfx3d_IsLinePoly(POLY *poly) +{ + int type = poly->type; + VERT *vert1, *vert2; + + if (type <= 2) + return true; + else if (type > 4) + return false; + + // Method 1: + // Castlevania Portrait of Ruin - trajectory of ricochet + bool duplicatedVert[4] = { false, false, false, false }; + for(int i = 0; i < type - 1; i++) + { + vert1 = &gfx3d.vertlist->list[poly->vertIndexes[i]]; + for(int j = i + 1; j < type; j++) + { + vert2 = &gfx3d.vertlist->list[poly->vertIndexes[j]]; + if (vert1->x == vert2->x && vert1->y == vert2->y) + { + duplicatedVert[j] = true; + } + } + } + int vertCount = type; + for(int i = 0; i < type; i++) + { + if (duplicatedVert[i]) + vertCount--; + } + if (vertCount <= 2) + return true; + + // Method 2: + // Castlevania Portrait of Ruin - warp stone + bool horizontalLine = true; + bool verticalLine = true; + vert1 = &gfx3d.vertlist->list[poly->vertIndexes[0]]; + for(int i = 1; i < type && (horizontalLine || verticalLine); i++) + { + vert2 = &gfx3d.vertlist->list[poly->vertIndexes[i]]; + if (vert1->coord[0] != vert2->coord[0]) + { + verticalLine = false; + } + if (vert1->coord[1] != vert2->coord[1]) + { + horizontalLine = false; + } + } + if (horizontalLine || verticalLine) + return true; + + return false; +} diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index 90cc19c6e..7459c192d 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -446,4 +446,6 @@ bool gfx3d_loadstate(EMUFILE* is, int size); void gfx3d_ClearStack(); +bool gfx3d_IsLinePoly(POLY *poly); + #endif //_GFX3D_H_ diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index e67ed1110..3189b9eb8 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -245,7 +245,6 @@ FORCEINLINE edge_fx_fl::edge_fx_fl(int Top, int Bottom, VERT** verts, bool& fail Numerator = 0; ErrorTerm = 0; Denominator = 1; - failure = false; } float YPrestep = Fixed28_4ToFloat((fixed28_4)(Y*16 - verts[Top]->y)); @@ -691,26 +690,22 @@ public: } //draws a single scanline - FORCEINLINE void drawscanline(edge_fx_fl *pLeft, edge_fx_fl *pRight) + FORCEINLINE void drawscanline(edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack) { int XStart = pLeft->X; int width = pRight->X - XStart; - // workaround for vertical/slant line poly - // it seems to cause another issue though - //if (width == 0) - //{ - // int leftWidth = pLeft->XStep; - // if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator) - // leftWidth++; - // int rightWidth = pRight->XStep; - // if (pRight->ErrorTerm + pRight->Numerator >= pRight->Denominator) - // rightWidth++; - // width = max(1, min(abs(leftWidth), abs(rightWidth))); - // - // if (XStart + width > 256) - // width = max(0, 256 - XStart); - //} + // HACK: workaround for vertical/slant line poly + if (lineHack && width == 0) + { + int leftWidth = pLeft->XStep; + if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator) + leftWidth++; + int rightWidth = pRight->XStep; + if (pRight->ErrorTerm + pRight->Numerator >= pRight->Denominator) + rightWidth++; + width = max(1, max(abs(leftWidth), abs(rightWidth))); + } //these are the starting values, taken from the left edge float invw = pLeft->invw.curr; @@ -750,15 +745,18 @@ public: while(width-- > 0) { - if(RENDERER && (x<0 || x>255)) { + bool outOfRange = false; + if(RENDERER && (x<0 || x>255)) + outOfRange = true; + if(!RENDERER && (x<0 || x>=engine->width)) + outOfRange = true; + if(!lineHack && outOfRange) + { printf("rasterizer rendering at x=%d! oops!\n",x); return; } - if(!RENDERER && (x<0 || x>=engine->width)) { - printf("rasterizer rendering at x=%d! oops!\n",x); - return; - } - pixel(adr,color[0],color[1],color[2],u,v,1.0f/invw,z); + if(!outOfRange) + pixel(adr,color[0],color[1],color[2],u,v,1.0f/invw,z); adr++; x++; @@ -774,7 +772,7 @@ public: //runs several scanlines, until an edge is finished template - void runscanlines(edge_fx_fl *left, edge_fx_fl *right,bool horizontal) + void runscanlines(edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack) { //oh lord, hack city for edge drawing @@ -785,16 +783,15 @@ public: runctr++; //HACK: special handling for horizontal line poly - //Instead of line, this will cause other notable issue. - //if (left->Height == 0 && right->Height == 0) - //{ - // bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); - // if(draw) drawscanline(left,right); - //} + if (lineHack && left->Height == 0 && right->Height == 0) + { + bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); + if(draw) drawscanline(left,right,lineHack); + } while(Height--) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); - if(draw) drawscanline(left,right); + if(draw) drawscanline(left,right,lineHack); const int xl = left->X; const int xr = right->X; const int y = left->Y; @@ -897,7 +894,7 @@ public: //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. //Maybe it is like crow's algorithm template - void shape_engine(int type, bool backwards) + void shape_engine(int type, bool backwards, bool lineHack) { bool failure = false; @@ -935,7 +932,7 @@ public: return; bool horizontal = left.Y == right.Y; - runscanlines(&left,&right,horizontal); + runscanlines(&left,&right,horizontal,lineHack); //if we ran out of an edge, step to the next one if(right.Height == 0) { @@ -1005,7 +1002,7 @@ public: polyAttr.backfacing = engine->polyBackfacing[i]; - shape_engine(type,!polyAttr.backfacing); + shape_engine(type,!polyAttr.backfacing, gfx3d_IsLinePoly(poly)); } }