diff options
author | Arisotura <thetotalworm@gmail.com> | 2020-05-30 03:04:14 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2020-05-30 03:04:14 +0200 |
commit | b44570eba1aab5903ff99aac044dc3e777c264d3 (patch) | |
tree | 11a05b343c764c71f564a3774212a7e58818819d /src/GPU2D.cpp | |
parent | 61799c35bdf26a5754ca760ac92d4f07d6a9396b (diff) | |
parent | 9381b531cd4544cc68998f604211bcbffb90cd3c (diff) |
merge moar
Diffstat (limited to 'src/GPU2D.cpp')
-rw-r--r-- | src/GPU2D.cpp | 99 |
1 files changed, 74 insertions, 25 deletions
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index b510767..30a6d45 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -943,8 +943,8 @@ void GPU2D::VBlankEnd() BGMosaicYMax = BGMosaicSize[1]; //OBJMosaicY = 0; //OBJMosaicYMax = OBJMosaicSize[1]; - OBJMosaicY = 0; - OBJMosaicYCount = 0; + //OBJMosaicY = 0; + //OBJMosaicYCount = 0; if (Accelerated) { @@ -2238,6 +2238,13 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2 BGYRefInternal[0] += rotD; } +// OBJ line buffer: +// * bit0-15: color (bit15=1: direct color, bit15=0: palette index, bit12=0 to indicate extpal) +// * bit16-17: BG-relative priority +// * bit18: non-transparent sprite pixel exists here +// * bit19: X mosaic should be applied here +// * bit24-31: compositor flags + void GPU2D::ApplySpriteMosaicX() { // apply X mosaic if needed @@ -2255,7 +2262,7 @@ void GPU2D::ApplySpriteMosaicX() continue; } - if ((!(OBJLine[i-1] & 0x100000)) || (CurOBJXMosaicTable[i] == 0)) + if ((OBJIndex[i] != OBJIndex[i-1]) || (CurOBJXMosaicTable[i] == 0)) lastcolor = OBJLine[i]; else OBJLine[i] = lastcolor; @@ -2322,11 +2329,25 @@ void GPU2D::InterleaveSprites(u32 prio) void GPU2D::DrawSprites(u32 line) { + if (line == 0) + { + // reset those counters here + // TODO: find out when those are supposed to be reset + // it would make sense to reset them at the end of VBlank + // however, sprites are rendered one scanline in advance + // so they need to be reset a bit earlier + + OBJMosaicY = 0; + OBJMosaicYCount = 0; + } + NumSprites = 0; memset(OBJLine, 0, 256*4); memset(OBJWindow, 0, 256); if (!(DispCnt & 0x1000)) return; + memset(OBJIndex, 0xFF, 256); + u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0]; const s32 spritewidth[16] = @@ -2355,6 +2376,15 @@ void GPU2D::DrawSprites(u32 line) bool iswin = (((attrib[0] >> 10) & 0x3) == 2); + u32 sprline; + if ((attrib[0] & 0x1000) && !iswin) + { + // apply Y mosaic + sprline = OBJMosaicY; + } + else + sprline = line; + if (attrib[0] & 0x0100) { u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12); @@ -2370,7 +2400,7 @@ void GPU2D::DrawSprites(u32 line) } u32 ypos = attrib[0] & 0xFF; - ypos = (line - ypos) & 0xFF; + ypos = (sprline - ypos) & 0xFF; if (ypos >= (u32)boundheight) continue; @@ -2380,7 +2410,7 @@ void GPU2D::DrawSprites(u32 line) u32 rotparamgroup = (attrib[1] >> 9) & 0x1F; - DoDrawSprite(Rotscale, attrib, &oam[(rotparamgroup*16) + 3], boundwidth, boundheight, width, height, xpos, ypos); + DoDrawSprite(Rotscale, sprnum, boundwidth, boundheight, width, height, xpos, ypos); NumSprites++; } @@ -2394,7 +2424,7 @@ void GPU2D::DrawSprites(u32 line) s32 height = spriteheight[sizeparam]; u32 ypos = attrib[0] & 0xFF; - ypos = (line - ypos) & 0xFF; + ypos = (sprline - ypos) & 0xFF; if (ypos >= (u32)height) continue; @@ -2402,11 +2432,7 @@ void GPU2D::DrawSprites(u32 line) if (xpos <= -width) continue; - // yflip - if (attrib[1] & 0x2000) - ypos = height-1 - ypos; - - DoDrawSprite(Normal, attrib, width, xpos, ypos); + DoDrawSprite(Normal, sprnum, width, height, xpos, ypos); NumSprites++; } @@ -2415,8 +2441,12 @@ void GPU2D::DrawSprites(u32 line) } template<bool window> -void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos) +void GPU2D::DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos) { + u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0]; + u16* attrib = &oam[num * 4]; + u16* rotparams = &oam[(((attrib[1] >> 9) & 0x1F) * 16) + 3]; + u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000; u32 tilenum = attrib[2] & 0x03FF; u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3); @@ -2429,9 +2459,6 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if ((attrib[0] & 0x1000) && !window) { // apply Y mosaic - ypos = OBJMosaicY - (attrib[0] & 0xFF); - if (ypos < 0) ypos = 0; - pixelattr |= 0x100000; } @@ -2509,12 +2536,15 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | pixelattr; + else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; } } else if (!window) { if (OBJLine[xpos] == 0) + { OBJLine[xpos] = pixelattr & 0x180000; + OBJIndex[xpos] = num; + } } } @@ -2563,12 +2593,15 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | pixelattr; + else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; } } else if (!window) { if (OBJLine[xpos] == 0) + { OBJLine[xpos] = pixelattr & 0x180000; + OBJIndex[xpos] = num; + } } } @@ -2604,12 +2637,15 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | pixelattr; + else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; } } else if (!window) { if (OBJLine[xpos] == 0) + { OBJLine[xpos] = pixelattr & 0x180000; + OBJIndex[xpos] = num; + } } } @@ -2623,8 +2659,11 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 } template<bool window> -void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) +void GPU2D::DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos) { + u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0]; + u16* attrib = &oam[num * 4]; + u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0xC0000; u32 tilenum = attrib[2] & 0x03FF; u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3); @@ -2634,12 +2673,13 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if ((attrib[0] & 0x1000) && !window) { // apply Y mosaic - ypos = OBJMosaicY - (attrib[0] & 0xFF); - if (ypos < 0) ypos = 0; - pixelattr |= 0x100000; } + // yflip + if (attrib[1] & 0x2000) + ypos = height-1 - ypos; + u32 xoff; u32 xend = width; if (xpos >= 0) @@ -2719,12 +2759,15 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | pixelattr; + else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; } } else if (!window) { if (OBJLine[xpos] == 0) + { OBJLine[xpos] = pixelattr & 0x180000; + OBJIndex[xpos] = num; + } } xoff++; @@ -2786,12 +2829,15 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | pixelattr; + else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; } } else if (!window) { if (OBJLine[xpos] == 0) + { OBJLine[xpos] = pixelattr & 0x180000; + OBJIndex[xpos] = num; + } } xoff++; @@ -2847,12 +2893,15 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | pixelattr; + else { OBJLine[xpos] = color | pixelattr; OBJIndex[xpos] = num; } } else if (!window) { if (OBJLine[xpos] == 0) + { OBJLine[xpos] = pixelattr & 0x180000; + OBJIndex[xpos] = num; + } } xoff++; |