diff options
| author | StapleButter <thetotalworm@gmail.com> | 2017-08-16 22:20:53 +0200 | 
|---|---|---|
| committer | StapleButter <thetotalworm@gmail.com> | 2017-08-16 22:20:53 +0200 | 
| commit | bc1385e905ecf7c659e88c0ae0d137155d3668b8 (patch) | |
| tree | df089989dc625bddd3ba9d3a970694dbc03554af /src | |
| parent | 0106406aff0f7aada992a9f27b68a20deafbc5e4 (diff) | |
3D: revise fog calculation to match hardware (emulate precision loss and overflow with big shifts)
Diffstat (limited to 'src')
| -rw-r--r-- | src/GPU3D_Soft.cpp | 21 | ||||
| -rw-r--r-- | src/NDSCart.cpp | 2 | 
2 files changed, 14 insertions, 9 deletions
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index cce5d70..3cbb71e 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -185,6 +185,8 @@ public:              // TODO: hardware tests show that this method is too precise              // I haven't yet figured out what the hardware does, though +            if (w1factor==0 || w0factor==0) { yfactor = 0; return; } +              s64 num = ((s64)x << (shift + 40)) / w1factor;              s64 denw0 = ((s64)(xdiff-x) << 40) / w0factor;              s64 denw1 = num >> shift; @@ -1590,25 +1592,28 @@ void ScanlineFinalPass(s32 y)                  }                  else                  { -                    // technically: Z difference is shifted left by fog shift -                    // then bit 0-18 are the fractional part and bit 19-23 are the density index -                    // things are a little different here to avoid overflow in 32-bit range +                    // technically: Z difference is shifted right by two, then shifted left by fog shift +                    // then bit 0-16 are the fractional part and bit 17-31 are the density index +                    // on hardware, the final value can overflow the 32-bit range with a shift big enough, +                    // causing fog to 'wrap around' and accidentally apply to larger Z ranges                      z -= fogoffset; -                    densityid = z >> (19-fogshift); +                    z = (z >> 2) << fogshift; + +                    densityid = z >> 17;                      if (densityid >= 32)                      {                          densityid = 32;                          densityfrac = 0;                      }                      else -                        densityfrac = (z << fogshift) & 0x7FFFF; +                        densityfrac = z & 0x1FFFF;                  } -                // checkme +                // checkme (may be too precise?)                  u32 density = -                    ((RenderFogDensityTable[densityid] * (0x80000-densityfrac)) + -                     (RenderFogDensityTable[densityid+1] * densityfrac)) >> 19; +                    ((RenderFogDensityTable[densityid] * (0x20000-densityfrac)) + +                     (RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;                  if (density >= 127) density = 128;                  u32 srccolor = ColorBuffer[pixeladdr]; diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 12cc9c8..216b3fb 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -618,7 +618,7 @@ void Write(u8 val, u32 hold)      default:          if (DataPos==0) -            printf("unknown save SPI command %02X %02X\n", CurCmd, val); +            printf("unknown save SPI command %02X %02X %d\n", CurCmd, val, islast);          break;      }  |