mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
wip
This commit is contained in:
parent
ae934021e5
commit
3256e054fa
@ -1534,31 +1534,57 @@ u32 SoftRenderer::CalculateFogDensity(const GPU3D& gpu3d, u32 pixeladdr) const
|
|||||||
return density;
|
return density;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftRenderer::ScanlineFinalPass(const GPU3D& gpu3d, s32 y)
|
bool SoftRenderer::CheckEdgeMarkingPixel(u32 polyid, u32 z, u32 pixeladdr)
|
||||||
|
{
|
||||||
|
if ((polyid != AttrBuffer[pixeladdr] >> 24) && (z < DepthBuffer[pixeladdr])) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckEdgeMarkingClearPlane(const GPU3D& gpu3d, u32 polyid, u32 z, u32 pixeladdr)
|
||||||
|
{
|
||||||
|
if (gpu3d.RenderDispCnt & (1<<14))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 clearz = ((gpu3d.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||||
|
|
||||||
|
if ((polyid != gpu3d.RenderClearAttr1>>24) && (z < clearz)) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftRenderer::ScanlineFinalPass(const GPU3D& gpu3d, s32 y, bool checkprev, bool checknext)
|
||||||
{
|
{
|
||||||
// to consider:
|
// to consider:
|
||||||
// clearing all polygon fog flags if the master flag isn't set?
|
// clearing all polygon fog flags if the master flag isn't set?
|
||||||
// merging all final pass loops into one?
|
// merging all final pass loops into one?
|
||||||
|
|
||||||
/*if (gpu3d.RenderDispCnt & (1<<5))
|
if (gpu3d.RenderDispCnt & (1<<5))
|
||||||
{
|
{
|
||||||
// edge marking
|
// edge marking
|
||||||
// only applied to topmost pixels
|
// only applied to topmost pixels
|
||||||
|
|
||||||
for (int x = 0; x < 256; x++)
|
for (int x = 0; x < 256; x++)
|
||||||
{
|
{
|
||||||
u32 pixeladdr = (tempoffset * ScanlineWidth) + x;
|
u32 pixeladdr = (y * ScanlineWidth) + x;
|
||||||
|
|
||||||
u32 attr = AttrBuffer[pixeladdr];
|
u32 attr = AttrBuffer[pixeladdr];
|
||||||
if (!(attr & 0xF)) continue;
|
if (!(attr & 0xF)) continue;
|
||||||
|
|
||||||
u32 polyid = attr >> 24; // opaque polygon IDs are used for edgemarking
|
u32 polyid = attr >> 24; // opaque polygon IDs are used for edgemarking
|
||||||
u32 z = DepthBuffer[pixeladdr];
|
u32 z = DepthBuffer[pixeladdr];
|
||||||
|
bool doit = false;
|
||||||
|
|
||||||
if (((polyid != (AttrBuffer[pixeladdr-1] >> 24)) && (z < DepthBuffer[pixeladdr-1])) ||
|
if ((checkprev && (x == 0) && CheckEdgeMarkingClearPlane(gpu3d, polyid, z, pixeladdr+1)) ||
|
||||||
((polyid != (AttrBuffer[pixeladdr+1] >> 24)) && (z < DepthBuffer[pixeladdr+1])) ||
|
(checknext && (x == 255) && CheckEdgeMarkingClearPlane(gpu3d, polyid, z, pixeladdr+1)) ||
|
||||||
((polyid != (AttrBuffer[pixeladdr-ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr-ScanlineWidth])) ||
|
((y == 0) && CheckEdgeMarkingClearPlane(gpu3d, polyid, z, pixeladdr-ScanlineWidth)) ||
|
||||||
((polyid != (AttrBuffer[pixeladdr+ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr+ScanlineWidth])))
|
((y == 191) && CheckEdgeMarkingClearPlane(gpu3d, polyid, z, pixeladdr+ScanlineWidth)) ||
|
||||||
|
((x != 0) && CheckEdgeMarkingPixel(polyid, z, pixeladdr-1)) ||
|
||||||
|
((x != 255) && CheckEdgeMarkingPixel(polyid, z, pixeladdr+1)) ||
|
||||||
|
((y != 0) && CheckEdgeMarkingPixel(polyid, z, pixeladdr-ScanlineWidth)) ||
|
||||||
|
((y != 191) && CheckEdgeMarkingPixel(polyid, z, pixeladdr+ScanlineWidth)))
|
||||||
{
|
{
|
||||||
u16 edgecolor = gpu3d.RenderEdgeTable[polyid >> 3];
|
u16 edgecolor = gpu3d.RenderEdgeTable[polyid >> 3];
|
||||||
u32 edgeR = (edgecolor << 1) & 0x3E; if (edgeR) edgeR++;
|
u32 edgeR = (edgecolor << 1) & 0x3E; if (edgeR) edgeR++;
|
||||||
@ -1571,7 +1597,7 @@ void SoftRenderer::ScanlineFinalPass(const GPU3D& gpu3d, s32 y)
|
|||||||
AttrBuffer[pixeladdr] = (AttrBuffer[pixeladdr] & 0xFFFFE0FF) | 0x00001000;
|
AttrBuffer[pixeladdr] = (AttrBuffer[pixeladdr] & 0xFFFFE0FF) | 0x00001000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
if (gpu3d.RenderDispCnt & (1<<7))
|
if (gpu3d.RenderDispCnt & (1<<7))
|
||||||
{
|
{
|
||||||
@ -1706,7 +1732,6 @@ void SoftRenderer::ScanlineFinalPass(const GPU3D& gpu3d, s32 y)
|
|||||||
|
|
||||||
void SoftRenderer::ClearBuffers(const GPU& gpu)
|
void SoftRenderer::ClearBuffers(const GPU& gpu)
|
||||||
{
|
{
|
||||||
u32 clearz = ((gpu.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
|
||||||
u32 polyid = gpu.GPU3D.RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
|
u32 polyid = gpu.GPU3D.RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
|
||||||
|
|
||||||
// clear the screen
|
// clear the screen
|
||||||
@ -1745,6 +1770,8 @@ void SoftRenderer::ClearBuffers(const GPU& gpu)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
u32 clearz = ((gpu.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||||
|
|
||||||
// TODO: confirm color conversion
|
// TODO: confirm color conversion
|
||||||
u32 r = (gpu.GPU3D.RenderClearAttr1 << 1) & 0x3E; if (r) r++;
|
u32 r = (gpu.GPU3D.RenderClearAttr1 << 1) & 0x3E; if (r) r++;
|
||||||
u32 g = (gpu.GPU3D.RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
|
u32 g = (gpu.GPU3D.RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
|
||||||
@ -1839,8 +1866,13 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
s16 scanlineswaitingforread = 0;
|
s16 scanlineswaitingforread = 0;
|
||||||
u8 nextevent;
|
u8 nextevent;
|
||||||
u16 leftovers;
|
u16 leftovers;
|
||||||
|
bool evenread = false;
|
||||||
|
s32 timespent = 0;
|
||||||
|
s32 prevtimespent = 0;
|
||||||
|
bool edgebug = false;
|
||||||
|
bool prevedgebug = false;
|
||||||
|
|
||||||
// until all scanlines have been pushed and read continue looping... CHECKME: unless its time for the next 3d frame should begin
|
// until all scanlines have been pushed and read continue looping... CHECKME: unless its time for the next 3d frame to begin
|
||||||
while ((scanlinesread < 192 || scanlinespushed2 < 192) && (RasterTiming < (FrameLength-RastDelay)))
|
while ((scanlinesread < 192 || scanlinespushed2 < 192) && (RasterTiming < (FrameLength-RastDelay)))
|
||||||
{
|
{
|
||||||
// check all events to find the earliest scheduled one
|
// check all events to find the earliest scheduled one
|
||||||
@ -1871,7 +1903,8 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
scanlinesinit += 2;
|
scanlinesinit += 2;
|
||||||
|
|
||||||
// a new scanline pair cannot begin until both scanlines are finished.
|
// a new scanline pair cannot begin until both scanlines are finished.
|
||||||
s32 timespent = std::max(rastertimingeven, rastertimingodd);
|
prevtimespent = timespent;
|
||||||
|
timespent = std::max(rastertimingeven, rastertimingodd);
|
||||||
|
|
||||||
// a new scanline pair cannot begin until the finishing pass + push is done.
|
// a new scanline pair cannot begin until the finishing pass + push is done.
|
||||||
if ((RasterTiming + timespent) < (RasterTiming+FinalPassLen))
|
if ((RasterTiming + timespent) < (RasterTiming+FinalPassLen))
|
||||||
@ -1881,10 +1914,13 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
|
|
||||||
// 12 cycles at the end of the scanline are always used, unless the scanline got within 12 cycles of timing out. Don't ask why, it just does.
|
// 12 cycles at the end of the scanline are always used, unless the scanline got within 12 cycles of timing out. Don't ask why, it just does.
|
||||||
s32 timeoutdist = ScanlineTimeout - RasterTiming;
|
s32 timeoutdist = ScanlineTimeout - RasterTiming;
|
||||||
|
prevedgebug = edgebug;
|
||||||
|
if (timeoutdist < 49385) edgebug = true;
|
||||||
|
else edgebug = false;
|
||||||
RasterTiming += std::clamp(timeoutdist, 0, 12);
|
RasterTiming += std::clamp(timeoutdist, 0, 12);
|
||||||
|
|
||||||
//set next scanline timeout
|
//set next scanline timeout
|
||||||
if (ScanlineTimeout == FrameLength) ScanlineTimeout = rasterevents[ScanlineRead] - (ScanlineReadSpeed+RastDelay);
|
if (ScanlineTimeout == FrameLength) ScanlineTimeout = rasterevents[ScanlineRead] - FinalPassLen + (ScanlineReadInc*evenread);//(ScanlineReadSpeed+RastDelay);
|
||||||
else ScanlineTimeout += TimeoutIncrement;
|
else ScanlineTimeout += TimeoutIncrement;
|
||||||
|
|
||||||
// schedule next scanline pair + the final pass of the latest pair
|
// schedule next scanline pair + the final pass of the latest pair
|
||||||
@ -1903,7 +1939,7 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
// if the first scanline pair was just finished only render one scanline
|
// if the first scanline pair was just finished only render one scanline
|
||||||
if (scanlinesfin > 0)
|
if (scanlinesfin > 0)
|
||||||
{
|
{
|
||||||
ScanlineFinalPass(gpu.GPU3D, scanlinesfin);
|
ScanlineFinalPass(gpu.GPU3D, scanlinesfin, timespent+4 < 501 || edgebug, prevtimespent+4 < 501 || prevedgebug);
|
||||||
scanlineswaitingforpush++;
|
scanlineswaitingforpush++;
|
||||||
scanlinesfin++;
|
scanlinesfin++;
|
||||||
}
|
}
|
||||||
@ -1911,7 +1947,7 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
// if the last scanline pair was just finished only render one scanline
|
// if the last scanline pair was just finished only render one scanline
|
||||||
if (scanlinesfin < 191)
|
if (scanlinesfin < 191)
|
||||||
{
|
{
|
||||||
ScanlineFinalPass(gpu.GPU3D, scanlinesfin);
|
ScanlineFinalPass(gpu.GPU3D, scanlinesfin, timespent+4 < 501 || edgebug, prevtimespent+4 < 501 || prevedgebug);
|
||||||
scanlineswaitingforpush++;
|
scanlineswaitingforpush++;
|
||||||
scanlinesfin++;
|
scanlinesfin++;
|
||||||
}
|
}
|
||||||
@ -1923,7 +1959,7 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// push scanlines to the intermediary "frame buffer" for the 2d engine to read them. (fixed length of ??? cycles)
|
// push scanlines to the intermediary "frame buffer" for the 2d engine to read them. (fixed length of ??? cycles) 256?
|
||||||
case PushScanline:
|
case PushScanline:
|
||||||
{
|
{
|
||||||
// reschedule events if buffer is full
|
// reschedule events if buffer is full
|
||||||
@ -1973,6 +2009,7 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys)
|
|||||||
|
|
||||||
scanlinesread++;
|
scanlinesread++;
|
||||||
scanlineswaitingforread--;
|
scanlineswaitingforread--;
|
||||||
|
evenread = !evenread;
|
||||||
|
|
||||||
// reschedule event for one scanline later unless all scanlines have been read
|
// reschedule event for one scanline later unless all scanlines have been read
|
||||||
if (scanlinesread < 192) rasterevents[ScanlineRead] += ScanlineReadInc;
|
if (scanlinesread < 192) rasterevents[ScanlineRead] += ScanlineReadInc;
|
||||||
|
@ -471,7 +471,8 @@ private:
|
|||||||
bool RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y, s32* timingcounter);
|
bool RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y, s32* timingcounter);
|
||||||
void RenderScanline(const GPU& gpu, s32 y, int npolys, s32* timingcounter);
|
void RenderScanline(const GPU& gpu, s32 y, int npolys, s32* timingcounter);
|
||||||
u32 CalculateFogDensity(const GPU3D& gpu3d, u32 pixeladdr) const;
|
u32 CalculateFogDensity(const GPU3D& gpu3d, u32 pixeladdr) const;
|
||||||
void ScanlineFinalPass(const GPU3D& gpu3d, s32 y);
|
bool CheckEdgeMarkingPixel(u32 polyid, u32 z, u32 pixeladdr);
|
||||||
|
void ScanlineFinalPass(const GPU3D& gpu3d, s32 y, bool checkprev, bool checknext);
|
||||||
void ClearBuffers(const GPU& gpu);
|
void ClearBuffers(const GPU& gpu);
|
||||||
u16 BeginPushScanline(s32 y, s32 pixelstodraw);
|
u16 BeginPushScanline(s32 y, s32 pixelstodraw);
|
||||||
void ReadScanline(s32 y);
|
void ReadScanline(s32 y);
|
||||||
|
Loading…
Reference in New Issue
Block a user