aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-01-21 03:36:14 +0100
committerStapleButter <thetotalworm@gmail.com>2017-01-21 03:36:14 +0100
commit14f1cec955980752604cb573927ed04e8a31673c (patch)
tree64060ee1c1896c8292177e1515abf6cdf9b54523
parent711375c0be60bb3bba679dfff44e5ccebe501f52 (diff)
some beginning of sprite support: 16bit tiled sprites, not rotated or anything fancy
also give it a version number
-rw-r--r--GPU2D.cpp203
-rw-r--r--GPU2D.h5
-rw-r--r--main.cpp7
-rw-r--r--melonDS.depend8
4 files changed, 213 insertions, 10 deletions
diff --git a/GPU2D.cpp b/GPU2D.cpp
index 663a97d..fb90415 100644
--- a/GPU2D.cpp
+++ b/GPU2D.cpp
@@ -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;
+ }
+ }
+ }
+}
diff --git a/GPU2D.h b/GPU2D.h
index 324ca64..f44f512 100644
--- a/GPU2D.h
+++ b/GPU2D.h
@@ -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
diff --git a/main.cpp b/main.cpp
index 76700e6..00e4834 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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"