diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index cdc9f05de..85370a164 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -817,63 +817,6 @@ static void GL_ReadFramebuffer() #endif } -// "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() { @@ -952,7 +895,7 @@ static void OGLRender() float alpha = poly->getAlpha()/31.0f; if(wireframe) alpha = 1.0; - if (isLinePoly(poly)) + if (gfx3d_IsLinePoly(poly)) glBegin(GL_LINE_LOOP); else if (type == 4) glBegin(GL_QUADS); diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index dfbd24cdf..8a28d689a 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -2801,3 +2801,62 @@ 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 > 10) + return false; + + // Method 1: + // Castlevania Portrait of Ruin - trajectory of ricochet + bool duplicatedVert[10]; + for(int i = 0; i < type; i++) + duplicatedVert[i] = 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 9cf07dcf7..05622c6a3 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -450,4 +450,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 5b0429f2c..bb7833bc6 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)); @@ -702,26 +701,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; @@ -761,15 +756,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++; @@ -785,7 +783,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 @@ -796,16 +794,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; @@ -908,7 +905,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; @@ -946,7 +943,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) { @@ -1016,7 +1013,7 @@ public: polyAttr.backfacing = engine->polyBackfacing[i]; - shape_engine(type,!polyAttr.backfacing); + shape_engine(type,!polyAttr.backfacing, gfx3d_IsLinePoly(poly)); } }