diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 8504a2e60..80d52d732 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -1749,10 +1749,21 @@ static void gfx3d_glVecTest(u32 v) void VIEWPORT::decode(const u32 v) { - this->x = (v & 0xFF); - this->y = std::min(191, (v >> 8) & 0xFF); - this->width = ((v >> 16) & 0xFF) + 1 - this->x; - this->height = std::min(191, (v >> 24) & 0xFF) + 1 - this->y; + //test: homie rollerz character select chooses nonsense for Y. they did the math backwards. their goal was a fullscreen viewport, they just messed up. + //they also messed up the width... + + u8 x1 = (v>> 0)&0xFF; + u8 y1 = (v>> 8)&0xFF; + u8 x2 = (v>>16)&0xFF; + u8 y2 = (v>>24)&0xFF; + + //I'm 100% sure this is basically 99% correct + //the modular math is right. the details of how the +1 is handled may be wrong (this might should be dealt with in the viewport transformation instead) + //Its an off by one error in any event so we may never know + width = (u8)(x2-x1)+1; + height = (u8)(y2-y1)+1; + x = x1; + y = y1; } void gfx3d_glFogColor(u32 v) diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 14a460b63..787a6363a 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -1519,11 +1519,22 @@ template void SoftRasterizerRenderer::performViewportTransforms() vert.coord[1] *= viewport.height * yfactor; vert.coord[1] += viewport.y * yfactor; vert.coord[1] = ymax - vert.coord[1]; + + //this is required to fix Homie Rollerz character select. + //this was also a better fix for Princess Debut's giant out of range polys. + //Basically, invalid viewports are blithely used here, and the math overflows and wraps around + //NOTE: this is a crude approximation of the correct fixed point modular arithmetic + if(vert.coord[0] >= 256) vert.coord[0] -= 256; + if(vert.coord[1] >= 256) vert.coord[1] -= 256; + if(vert.coord[0] < 0) vert.coord[0] += 256; + if(vert.coord[1] < 0) vert.coord[1] += 256; - //well, i guess we need to do this to keep Princess Debut from rendering huge polys. - //there must be something strange going on - vert.coord[0] = max(0.0f,min(xmax,vert.coord[0])); - vert.coord[1] = max(0.0f,min(ymax,vert.coord[1])); + //now, this is really lame. probably the rasterizer should be dealing with this, but + //1. its easier here + //2. its more likely reusable in opengl this way (well, this is a bunch more calculations that should be earlier in the pipeline and obligatorily shared) + //I do have some evidence that this wrecks the hardware extremely, but nothing's likely to use that effect. + //This is a sanity check only. + if(vert.coord[1] >= 192) vert.coord[1] = 192; } } }