diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 5a119aa680..c8481301ba 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -173,10 +173,7 @@ struct GPUgstate { blend, blendfixa, blendfixb, - dith1, - dith2, - dith3, - dith4, + dithmtx[4], lop, // 0xE6 zmsk, pmskc, @@ -249,6 +246,11 @@ struct GPUgstate { // Dither bool isDitherEnabled() const { return ditherEnable & 1; } + int getDitherValue(int x, int y) const { + u8 raw = (dithmtx[y & 3] >> ((x & 3) * 4)) & 0xF; + // Apply sign extension to make 8-F negative, 0-7 positive. + return ((s8)(raw << 4)) >> 4; + } // Color Mask u32 getColorMask() const { return (pmskc & 0xFFFFFF) | ((pmska & 0xFF) << 24); } diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 27783c86d3..5db77b9407 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -895,12 +895,24 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4 dst = Vec4::FromRGBA(old_color); + Vec3 blended = AlphaBlendingResult(prim_color, dst); + if (gstate.isDitherEnabled()) { + blended += Vec3::AssignToAll(gstate.getDitherValue(p.x, p.y)); + } + // ToRGB() always automatically clamps. - new_color = AlphaBlendingResult(prim_color, dst).ToRGB(); + new_color = blended.ToRGB(); new_color |= stencil << 24; } else { + if (gstate.isDitherEnabled()) { + // We'll discard alpha anyway. + prim_color += Vec4::AssignToAll(gstate.getDitherValue(p.x, p.y)); + } + #if defined(_M_SSE) new_color = Vec3(prim_color.ivec).ToRGB(); new_color |= stencil << 24; @@ -920,7 +932,6 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4