diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-01-21 03:36:14 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-01-21 03:36:14 +0100 |
commit | 14f1cec955980752604cb573927ed04e8a31673c (patch) | |
tree | 64060ee1c1896c8292177e1515abf6cdf9b54523 | |
parent | 711375c0be60bb3bba679dfff44e5ccebe501f52 (diff) |
some beginning of sprite support: 16bit tiled sprites, not rotated or anything fancy
also give it a version number
-rw-r--r-- | GPU2D.cpp | 203 | ||||
-rw-r--r-- | GPU2D.h | 5 | ||||
-rw-r--r-- | main.cpp | 7 | ||||
-rw-r--r-- | melonDS.depend | 8 |
4 files changed, 213 insertions, 10 deletions
@@ -183,6 +183,11 @@ void GPU2D::DrawScanline_Mode1(u32 line, u16* dst) for (int i = 0; i < 256>>1; i++) ((u32*)dst)[i] = backdrop; + // prerender sprites + u32 spritebuf[256]; + memset(spritebuf, 0, 256*4); + if (DispCnt & 0x1000) DrawSprites(line, spritebuf); + switch (DispCnt & 0x7) { case 0: @@ -192,22 +197,22 @@ void GPU2D::DrawScanline_Mode1(u32 line, u16* dst) if ((BGCnt[3] & 0x3) == i) { if (DispCnt & 0x0800) DrawBG_Text_4bpp(line, dst, 3); - // todo: sprites + if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x38000, dst); } if ((BGCnt[2] & 0x3) == i) { if (DispCnt & 0x0400) DrawBG_Text_4bpp(line, dst, 2); - // todo: sprites + if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x28000, dst); } if ((BGCnt[1] & 0x3) == i) { if (DispCnt & 0x0200) DrawBG_Text_4bpp(line, dst, 1); - // todo: sprites + if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x18000, dst); } if ((BGCnt[0] & 0x3) == i) { if (DispCnt & 0x0100) DrawBG_Text_4bpp(line, dst, 0); - // todo: sprites + if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x08000, dst); } } break; @@ -301,3 +306,193 @@ void GPU2D::DrawBG_Text_4bpp(u32 line, u16* dst, u32 bgnum) xoff++; } } + +void GPU2D::InterleaveSprites(u32* buf, u32 prio, u16* dst) +{ + for (u32 i = 0; i < 256; i++) + { + if ((buf[i] & 0xF8000) == prio) + dst[i] = buf[i] & 0x7FFF; + } +} + +void GPU2D::DrawSprites(u32 line, u32* dst) +{ + u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0]; + + const s32 spritewidth[16] = + { + 8, 16, 8, 0, + 16, 32, 8, 0, + 32, 32, 16, 0, + 64, 64, 32, 0 + }; + const s32 spriteheight[16] = + { + 8, 8, 16, 0, + 16, 8, 32, 0, + 32, 16, 32, 0, + 64, 32, 64, 0 + }; + + for (int bgnum = 0x0C00; bgnum >= 0x0000; bgnum -= 0x0400) + { + for (int sprnum = 127; sprnum >= 0; sprnum--) + { + u16* attrib = &oam[sprnum*4]; + + if ((attrib[2] & 0x0C00) != bgnum) + continue; + + if (attrib[0] & 0x0100) + { + u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12); + s32 width = spritewidth[sizeparam]; + s32 height = spriteheight[sizeparam]; + s32 boundwidth = width; + s32 boundheight = height; + + if (attrib[0] & 0x0200) + { + boundwidth <<= 1; + boundheight <<= 1; + } +//printf("sprite%d %04X %04X %04X %dx%d\n", sprnum, attrib[0], attrib[1], attrib[2], boundwidth, boundheight); + u32 ypos = attrib[0] & 0xFF; + ypos = (line - ypos) & 0xFF; + if (ypos >= (u32)boundheight) + continue; + + s32 xpos = (s32)(attrib[1] << 23) >> 23; + if (xpos <= -boundwidth) + continue; + + //DrawSprite_Normal(attrib, width, xpos, ypos, dst); + } + else + { + if (attrib[0] & 0x0200) + continue; + + u32 sizeparam = (attrib[0] >> 14) | ((attrib[1] & 0xC000) >> 12); + s32 width = spritewidth[sizeparam]; + s32 height = spriteheight[sizeparam]; + + u32 ypos = attrib[0] & 0xFF; + ypos = (line - ypos) & 0xFF; + if (ypos >= (u32)height) + continue; + + s32 xpos = (s32)(attrib[1] << 23) >> 23; + if (xpos <= -width) + continue; + + // yflip + if (attrib[1] & 0x2000) + ypos = height-1 - ypos; + + DrawSprite_Normal(attrib, width, xpos, ypos, dst); + } + } + } +} + +void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst) +{ + u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000; + u32 tilenum = attrib[2] & 0x03FF; + if (DispCnt & 0x10) + { + tilenum <<= ((DispCnt >> 20) & 0x3); + tilenum += ((ypos >> 3) * (width >> 3)); + } + else + { + tilenum += ((ypos >> 3) * 0x20); + } + + u32 wmask = width - 8; // really ((width - 1) & ~0x7) + + u32 xoff; + if (xpos >= 0) + { + xoff = 0; + if ((xpos+width) > 256) + width = 256-xpos; + } + else + { + xoff = -xpos; + xpos = 0; + } + + if (attrib[0] & 0x2000) + { + // 256-color + } + else + { + // 16-color + tilenum <<= 5; + u8* pixels = (Num ? GPU::VRAM_BOBJ : GPU::VRAM_AOBJ)[tilenum >> 14]; + pixels += (tilenum & 0x3FFF); + pixels += ((ypos & 0x7) << 2); + + u16* curpal; + u16* pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + pal += (attrib[2] & 0xF000) >> 8; + + if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works + { + pixels += (((width-1 - xoff) & wmask) << 2); + pixels += (((width-1 - xoff) & 0x7) >> 1); + + for (; xoff < width;) + { + u8 color; + if (xoff & 0x1) + { + color = *pixels & 0x0F; + pixels--; + } + else + { + color = *pixels >> 4; + } + + if (color) + dst[xpos] = pal[color] | prio; + + xoff++; + xpos++; + if (!(xoff & 0x7)) pixels -= 28; + } + } + else + { + pixels += ((xoff & wmask) << 2); + pixels += ((xoff & 0x7) >> 1); + + for (; xoff < width;) + { + u8 color; + if (xoff & 0x1) + { + color = *pixels >> 4; + pixels++; + } + else + { + color = *pixels & 0x0F; + } + + if (color) + dst[xpos] = pal[color] | prio; + + xoff++; + xpos++; + if (!(xoff & 0x7)) pixels += 28; + } + } + } +} @@ -49,7 +49,12 @@ private: u16 BGYPos[4]; void DrawScanline_Mode1(u32 line, u16* dst); + void DrawBG_Text_4bpp(u32 line, u16* dst, u32 num); + + void InterleaveSprites(u32* buf, u32 prio, u16* dst); + void DrawSprites(u32 line, u32* dst); + void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, u32 ypos, u32* dst); }; #endif @@ -22,6 +22,9 @@ #include "GPU.h" +#define VERSION "0.1" + + HINSTANCE instance; HWND melon; BITMAPV4HEADER bmp; @@ -112,7 +115,7 @@ int main() AdjustWindowRect(&rekt, WS_OVERLAPPEDWINDOW, FALSE); melon = CreateWindow("v0ltmeters", - "melonDS", + "melonDS " VERSION, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rekt.right-rekt.left, rekt.bottom-rekt.top, @@ -173,7 +176,7 @@ int main() nframes = 0; char melontitle[100]; - sprintf(melontitle, "melonDS | %d FPS", fps); + sprintf(melontitle, "melonDS " VERSION " | %d FPS", fps); SetWindowText(melon, melontitle); } } diff --git a/melonDS.depend b/melonDS.depend index 00d1b5d..1a93329 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -1,5 +1,5 @@ # depslib dependency file v1.0 -1484878707 source:c:\documents\sources\melonds\main.cpp +1484954918 source:c:\documents\sources\melonds\main.cpp <stdio.h> <windows.h> "NDS.h" @@ -83,13 +83,13 @@ "NDS.h" "SPI.h" -1484922144 source:c:\documents\sources\melonds\gpu2d.cpp +1484962517 source:c:\documents\sources\melonds\gpu2d.cpp <stdio.h> <string.h> "NDS.h" "GPU.h" -1484922330 c:\documents\sources\melonds\gpu2d.h +1484960542 c:\documents\sources\melonds\gpu2d.h 1481040524 c:\documents\sources\melonds\wifi.h @@ -125,7 +125,7 @@ 1484848282 c:\documents\sources\melonds\rtc.h "types.h" -1484870861 source:c:\documents\sources\melonds\rtc.cpp +1484922235 source:c:\documents\sources\melonds\rtc.cpp <stdio.h> <string.h> "RTC.h" |