diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-03-02 19:00:19 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-03-02 19:00:19 +0100 |
commit | e0fa57fbf28c0cfa3c38b81b697fa991879844de (patch) | |
tree | c110c3288d82b8e98f347810656a6c72eb53bbb7 | |
parent | 464717602f2d69c558644368d7930f6bd4601f17 (diff) |
* color special effects (fade, blending)
* sprite blending
not optimized, but works
-rw-r--r-- | GPU2D.cpp | 281 | ||||
-rw-r--r-- | GPU2D.h | 4 | ||||
-rw-r--r-- | melonDS.depend | 6 |
3 files changed, 208 insertions, 83 deletions
@@ -83,6 +83,11 @@ void GPU2D::Reset() memset(BGRotC, 0, 2*2); memset(BGRotD, 0, 2*2); + BlendCnt = 0; + EVA = 16; + EVB = 0; + EVY = 0; + CaptureCnt = 0; MasterBrightness = 0; @@ -175,6 +180,18 @@ void GPU2D::Write16(u32 addr, u16 val) case 0x034: BGRotC[1] = val; return; case 0x036: BGRotD[1] = val; return; + case 0x050: BlendCnt = val; return; + case 0x052: + EVA = val & 0x1F; + if (EVA > 16) EVA = 16; + EVB = (val >> 8) & 0x1F; + if (EVB > 16) EVB = 16; + return; + case 0x54: + EVY = val & 0x1F; + if (EVY > 16) EVY = 16; + return; + case 0x06C: MasterBrightness = val; return; } @@ -633,6 +650,8 @@ void GPU2D::DrawScanlineBGMode(u32 line, u32* spritebuf, u32* dst) void GPU2D::DrawScanline_Mode1(u32 line, u32* dst) { + u32 linebuf[256*2]; + u32 backdrop; if (Num) backdrop = *(u16*)&GPU::Palette[0x400]; else backdrop = *(u16*)&GPU::Palette[0]; @@ -642,12 +661,10 @@ void GPU2D::DrawScanline_Mode1(u32 line, u32* dst) u8 g = (backdrop & 0x03E0) >> 4; u8 b = (backdrop & 0x7C00) >> 9; - // TODO: color effect for backdrop - backdrop = r | (g << 8) | (b << 16) | 0x20000000; for (int i = 0; i < 256; i++) - dst[i] = backdrop; + linebuf[i] = backdrop; } // prerender sprites @@ -657,29 +674,121 @@ void GPU2D::DrawScanline_Mode1(u32 line, u32* dst) switch (DispCnt & 0x7) { - case 0: DrawScanlineBGMode<0>(line, spritebuf, dst); break; - case 1: DrawScanlineBGMode<1>(line, spritebuf, dst); break; - case 2: DrawScanlineBGMode<2>(line, spritebuf, dst); break; - case 3: DrawScanlineBGMode<3>(line, spritebuf, dst); break; - case 4: DrawScanlineBGMode<4>(line, spritebuf, dst); break; - case 5: DrawScanlineBGMode<5>(line, spritebuf, dst); break; + case 0: DrawScanlineBGMode<0>(line, spritebuf, linebuf); break; + case 1: DrawScanlineBGMode<1>(line, spritebuf, linebuf); break; + case 2: DrawScanlineBGMode<2>(line, spritebuf, linebuf); break; + case 3: DrawScanlineBGMode<3>(line, spritebuf, linebuf); break; + case 4: DrawScanlineBGMode<4>(line, spritebuf, linebuf); break; + case 5: DrawScanlineBGMode<5>(line, spritebuf, linebuf); break; } - // debug crap - //for (int i = 0; i < 256; i++) - // dst[i] = *(u16*)&GPU::Palette[Num*0x400 + (i>>4)*2 + (line>>4)*32]; -} + // color special effects + // can likely be optimized + + u32 bldcnteffect = (BlendCnt >> 6) & 0x3; + + for (int i = 0; i < 256; i++) + { + u32 val1 = linebuf[i]; + u32 val2 = linebuf[256+i]; + + u32 coloreffect, eva, evb; + + u32 flag1 = val1 >> 24; + if (flag1 & 0x80) + { + // sprite blending + + coloreffect = 1; + + if (flag1 & 0x40) + { + eva = flag1 & 0x1F; + evb = 16 - eva; + } + else + { + eva = EVA; + evb = EVB; + } + } + else if (BlendCnt & flag1) + { + if ((bldcnteffect == 1) && (BlendCnt & ((val2 >> 16) & 0xFF00))) + { + coloreffect = 1; + eva = EVA; + evb = EVB; + } + else if (bldcnteffect >= 2) + coloreffect = bldcnteffect; + else + coloreffect = 0; + } + else + coloreffect = 0; + + switch (coloreffect) + { + case 0: + dst[i] = val1; + break; + case 1: + { + u32 r = (((val1 & 0x00003F) * eva) + ((val2 & 0x00003F) * evb)) >> 4; + u32 g = ((((val1 & 0x003F00) * eva) + ((val2 & 0x003F00) * evb)) >> 4) & 0x007F00; + u32 b = ((((val1 & 0x3F0000) * eva) + ((val2 & 0x3F0000) * evb)) >> 4) & 0x7F0000; + + if (r > 0x00003F) r = 0x00003F; + if (g > 0x003F00) g = 0x003F00; + if (b > 0x3F0000) b = 0x3F0000; + + dst[i] = r | g | b | 0xFF000000; + } + break; + + case 2: + { + u32 r = val1 & 0x00003F; + u32 g = val1 & 0x003F00; + u32 b = val1 & 0x3F0000; + + // TODO: confirm (or not) that it's 63 and not 62 + r += ((0x00003F - r) * EVY) >> 4; + g += (((0x003F00 - g) * EVY) >> 4) & 0x003F00; + b += (((0x3F0000 - b) * EVY) >> 4) & 0x3F0000; + + dst[i] = r | g | b | 0xFF000000; + } + break; + + case 3: + { + u32 r = val1 & 0x00003F; + u32 g = val1 & 0x003F00; + u32 b = val1 & 0x3F0000; + + r -= (r * EVY) >> 4; + g -= ((g * EVY) >> 4) & 0x003F00; + b -= ((b * EVY) >> 4) & 0x3F0000; + + dst[i] = r | g | b | 0xFF000000; + } + break; + } + } +} -typedef void (*DrawPixelFunc)(u32 bgnum, u32* dst, u16 color, u32 blendfunc); -void GPU2D::DrawPixel_Normal(u32 bgnum, u32* dst, u16 color, u32 blendfunc) +void GPU2D::DrawPixel(u32* dst, u16 color, u32 flag) { u8 r = (color & 0x001F) << 1; u8 g = (color & 0x03E0) >> 4; u8 b = (color & 0x7C00) >> 9; - *dst = r | (g << 8) | (b << 16) | (0x01000000 << bgnum); + *(dst+256) = *dst; + *dst = r | (g << 8) | (b << 16) | flag; } void GPU2D::DrawBG_3D(u32 line, u32* dst) @@ -698,7 +807,8 @@ void GPU2D::DrawBG_3D(u32 line, u32* dst) // TODO: blending // alpha is 6bit too....? - dst[i] = r | (g << 8) | (b << 16); + dst[i+256] = dst[i]; + dst[i] = r | (g << 8) | (b << 16) | 0x01000000; } } @@ -715,8 +825,6 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum) u32 widexmask = (bgcnt & 0x4000) ? 0x100 : 0; - DrawPixelFunc drawpixelfn = DrawPixel_Normal; - extpal = (DispCnt & 0x40000000); if (extpal) extpalslot = ((bgnum<2) && (bgcnt&0x2000)) ? (2+bgnum) : bgnum; @@ -786,7 +894,7 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum) color = GPU::ReadVRAM_BG<u8>(pixelsaddr + tilexoff); if (color) - drawpixelfn(bgnum, &dst[i], curpal[color], BlendFunc); + DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum); xoff++; } @@ -830,7 +938,7 @@ void GPU2D::DrawBG_Text(u32 line, u32* dst, u32 bgnum) } if (color) - drawpixelfn(bgnum, &dst[i], curpal[color], BlendFunc); + DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum); xoff++; } @@ -859,8 +967,6 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) if (bgcnt & 0x2000) overflowmask = 0; else overflowmask = ~(coordmask | 0x7FF); - DrawPixelFunc drawpixelfn = DrawPixel_Normal; - extpal = (DispCnt & 0x40000000); s16 rotA = BGRotA[bgnum-2]; @@ -895,7 +1001,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) u16 color = GPU::ReadVRAM_BG<u16>(tilemapaddr + (((((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)) << 1)); if (color & 0x8000) - drawpixelfn(bgnum, &dst[i], color, BlendFunc); + DrawPixel(&dst[i], color, 0x01000000<<bgnum); } rotX += rotA; @@ -916,7 +1022,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) u8 color = GPU::ReadVRAM_BG<u8>(tilemapaddr + (((rotY & coordmask) >> 8) << yshift) + ((rotX & coordmask) >> 8)); if (color) - drawpixelfn(bgnum, &dst[i], pal[color], BlendFunc); + DrawPixel(&dst[i], pal[color], 0x01000000<<bgnum); } rotX += rotA; @@ -968,7 +1074,7 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) color = GPU::ReadVRAM_BG<u8>(tilesetaddr + ((curtile & 0x03FF) << 6) + (tileyoff << 3) + tilexoff); if (color) - drawpixelfn(bgnum, &dst[i], curpal[color], BlendFunc); + DrawPixel(&dst[i], curpal[color], 0x01000000<<bgnum); } rotX += rotA; @@ -982,14 +1088,12 @@ void GPU2D::DrawBG_Extended(u32 line, u32* dst, u32 bgnum) void GPU2D::InterleaveSprites(u32* buf, u32 prio, u32* dst) { - DrawPixelFunc drawpixelfn = DrawPixel_Normal; - for (u32 i = 0; i < 256; i++) { if ((buf[i] & 0xF8000) == prio) { u32 blendfunc = 0; - drawpixelfn(4, &dst[i], buf[i], blendfunc); + DrawPixel(&dst[i], buf[i] & 0x7FFF, buf[i] & 0xFF000000); } } } @@ -1121,72 +1225,88 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 width <<= 8; height <<= 8; - //if (spritemode == 3) printf("BAKA"); - - if (attrib[0] & 0x2000) + if (spritemode == 3) { - // 256-color - tilenum <<= 5; - ytilefactor <<= 5; - u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; + // TODO - u32 extpal = (DispCnt & 0x80000000); + u32 alpha = attrib[2] >> 12; + if (!alpha) return; + alpha++; - u16* pal; - if (extpal) pal = GetOBJExtPal(attrib[2] >> 12); - else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + prio |= (0xC0000000 | (alpha << 24)); - for (; xoff < boundwidth;) + // TODO + } + else + { + if (spritemode == 1) prio |= 0x80000000; + else prio |= 0x10000000; + + if (attrib[0] & 0x2000) { - if ((u32)rotX < width && (u32)rotY < height) + // 256-color + tilenum <<= 5; + ytilefactor <<= 5; + u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; + + u32 extpal = (DispCnt & 0x80000000); + + u16* pal; + if (extpal) pal = GetOBJExtPal(attrib[2] >> 12); + else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + + for (; xoff < boundwidth;) { - u8 color; + if ((u32)rotX < width && (u32)rotY < height) + { + u8 color; - // blaaaarg - color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8)); + // blaaaarg + color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>5) + ((rotX>>11)*64) + ((rotX&0x700)>>8)); - if (color) - dst[xpos] = pal[color] | prio; - } + if (color) + dst[xpos] = pal[color] | prio; + } - rotX += rotA; - rotY += rotC; - xoff++; - xpos++; + rotX += rotA; + rotY += rotC; + xoff++; + xpos++; + } } - } - else - { - // 16-color - tilenum <<= 5; - ytilefactor <<= 5; - u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; + else + { + // 16-color + tilenum <<= 5; + ytilefactor <<= 5; + u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; - u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; - pal += (attrib[2] & 0xF000) >> 8; + u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + pal += (attrib[2] & 0xF000) >> 8; - for (; xoff < boundwidth;) - { - if ((u32)rotX < width && (u32)rotY < height) + for (; xoff < boundwidth;) { - u8 color; + if ((u32)rotX < width && (u32)rotY < height) + { + u8 color; - // blaaaarg - color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9)); + // blaaaarg + color = GPU::ReadVRAM_OBJ<u8>(pixelsaddr + ((rotY>>11)*ytilefactor) + ((rotY&0x700)>>6) + ((rotX>>11)*32) + ((rotX&0x700)>>9)); - if (rotX & 0x100) - color >>= 4; - else - color &= 0x0F; + if (rotX & 0x100) + color >>= 4; + else + color &= 0x0F; - if (color) - dst[xpos] = pal[color] | prio; - } + if (color) + dst[xpos] = pal[color] | prio; + } - rotX += rotA; - rotY += rotC; - xoff++; - xpos++; + rotX += rotA; + rotY += rotC; + xoff++; + xpos++; + } } } } @@ -1247,6 +1367,8 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d if (!alpha) return; alpha++; + prio |= (0xC0000000 | (alpha << 24)); + u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; pixelsaddr += (xoff << 1); @@ -1274,6 +1396,9 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* d tilenum += ((ypos >> 3) * 0x20); } + if (spritemode == 1) prio |= 0x80000000; + else prio |= 0x10000000; + if (attrib[0] & 0x2000) { // 256-color @@ -62,7 +62,7 @@ private: s16 BGRotC[2]; s16 BGRotD[2]; - u32 BlendFunc; + u16 BlendCnt; u8 EVA, EVB; u8 EVY; @@ -78,7 +78,7 @@ private: template<u32 bgmode> void DrawScanlineBGMode(u32 line, u32* spritebuf, u32* dst); void DrawScanline_Mode1(u32 line, u32* dst); - static void DrawPixel_Normal(u32 bgnum, u32* dst, u16 color, u32 blendfunc); + void DrawPixel(u32* dst, u16 color, u32 flag); void DrawBG_3D(u32 line, u32* dst); void DrawBG_Text(u32 line, u32* dst, u32 num); diff --git a/melonDS.depend b/melonDS.depend index d1e6fb3..9816700 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -10,7 +10,7 @@ 1481161027 c:\documents\sources\melonds\types.h -1488415700 source:c:\documents\sources\melonds\nds.cpp +1488477261 source:c:\documents\sources\melonds\nds.cpp <stdio.h> <string.h> "NDS.h" @@ -87,13 +87,13 @@ "NDS.h" "SPI.h" -1488415860 source:c:\documents\sources\melonds\gpu2d.cpp +1488477220 source:c:\documents\sources\melonds\gpu2d.cpp <stdio.h> <string.h> "NDS.h" "GPU.h" -1488398363 c:\documents\sources\melonds\gpu2d.h +1488475640 c:\documents\sources\melonds\gpu2d.h 1481040524 c:\documents\sources\melonds\wifi.h |