some beginning of sprite support: 16bit tiled sprites, not rotated or anything fancy

also give it a version number
This commit is contained in:
StapleButter 2017-01-21 03:36:14 +01:00
parent 711375c0be
commit 14f1cec955
4 changed files with 213 additions and 10 deletions

203
GPU2D.cpp
View File

@ -183,6 +183,11 @@ void GPU2D::DrawScanline_Mode1(u32 line, u16* dst)
for (int i = 0; i < 256>>1; i++) for (int i = 0; i < 256>>1; i++)
((u32*)dst)[i] = backdrop; ((u32*)dst)[i] = backdrop;
// prerender sprites
u32 spritebuf[256];
memset(spritebuf, 0, 256*4);
if (DispCnt & 0x1000) DrawSprites(line, spritebuf);
switch (DispCnt & 0x7) switch (DispCnt & 0x7)
{ {
case 0: case 0:
@ -192,22 +197,22 @@ void GPU2D::DrawScanline_Mode1(u32 line, u16* dst)
if ((BGCnt[3] & 0x3) == i) if ((BGCnt[3] & 0x3) == i)
{ {
if (DispCnt & 0x0800) DrawBG_Text_4bpp(line, dst, 3); if (DispCnt & 0x0800) DrawBG_Text_4bpp(line, dst, 3);
// todo: sprites if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x38000, dst);
} }
if ((BGCnt[2] & 0x3) == i) if ((BGCnt[2] & 0x3) == i)
{ {
if (DispCnt & 0x0400) DrawBG_Text_4bpp(line, dst, 2); if (DispCnt & 0x0400) DrawBG_Text_4bpp(line, dst, 2);
// todo: sprites if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x28000, dst);
} }
if ((BGCnt[1] & 0x3) == i) if ((BGCnt[1] & 0x3) == i)
{ {
if (DispCnt & 0x0200) DrawBG_Text_4bpp(line, dst, 1); if (DispCnt & 0x0200) DrawBG_Text_4bpp(line, dst, 1);
// todo: sprites if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x18000, dst);
} }
if ((BGCnt[0] & 0x3) == i) if ((BGCnt[0] & 0x3) == i)
{ {
if (DispCnt & 0x0100) DrawBG_Text_4bpp(line, dst, 0); if (DispCnt & 0x0100) DrawBG_Text_4bpp(line, dst, 0);
// todo: sprites if (DispCnt & 0x1000) InterleaveSprites(spritebuf, 0x08000, dst);
} }
} }
break; break;
@ -301,3 +306,193 @@ void GPU2D::DrawBG_Text_4bpp(u32 line, u16* dst, u32 bgnum)
xoff++; 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;
}
}
}
}

View File

@ -49,7 +49,12 @@ private:
u16 BGYPos[4]; u16 BGYPos[4];
void DrawScanline_Mode1(u32 line, u16* dst); void DrawScanline_Mode1(u32 line, u16* dst);
void DrawBG_Text_4bpp(u32 line, u16* dst, u32 num); 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 #endif

View File

@ -22,6 +22,9 @@
#include "GPU.h" #include "GPU.h"
#define VERSION "0.1"
HINSTANCE instance; HINSTANCE instance;
HWND melon; HWND melon;
BITMAPV4HEADER bmp; BITMAPV4HEADER bmp;
@ -112,7 +115,7 @@ int main()
AdjustWindowRect(&rekt, WS_OVERLAPPEDWINDOW, FALSE); AdjustWindowRect(&rekt, WS_OVERLAPPEDWINDOW, FALSE);
melon = CreateWindow("v0ltmeters", melon = CreateWindow("v0ltmeters",
"melonDS", "melonDS " VERSION,
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
rekt.right-rekt.left, rekt.bottom-rekt.top, rekt.right-rekt.left, rekt.bottom-rekt.top,
@ -173,7 +176,7 @@ int main()
nframes = 0; nframes = 0;
char melontitle[100]; char melontitle[100];
sprintf(melontitle, "melonDS | %d FPS", fps); sprintf(melontitle, "melonDS " VERSION " | %d FPS", fps);
SetWindowText(melon, melontitle); SetWindowText(melon, melontitle);
} }
} }

View File

@ -1,5 +1,5 @@
# depslib dependency file v1.0 # depslib dependency file v1.0
1484878707 source:c:\documents\sources\melonds\main.cpp 1484954918 source:c:\documents\sources\melonds\main.cpp
<stdio.h> <stdio.h>
<windows.h> <windows.h>
"NDS.h" "NDS.h"
@ -83,13 +83,13 @@
"NDS.h" "NDS.h"
"SPI.h" "SPI.h"
1484922144 source:c:\documents\sources\melonds\gpu2d.cpp 1484962517 source:c:\documents\sources\melonds\gpu2d.cpp
<stdio.h> <stdio.h>
<string.h> <string.h>
"NDS.h" "NDS.h"
"GPU.h" "GPU.h"
1484922330 c:\documents\sources\melonds\gpu2d.h 1484960542 c:\documents\sources\melonds\gpu2d.h
1481040524 c:\documents\sources\melonds\wifi.h 1481040524 c:\documents\sources\melonds\wifi.h
@ -125,7 +125,7 @@
1484848282 c:\documents\sources\melonds\rtc.h 1484848282 c:\documents\sources\melonds\rtc.h
"types.h" "types.h"
1484870861 source:c:\documents\sources\melonds\rtc.cpp 1484922235 source:c:\documents\sources\melonds\rtc.cpp
<stdio.h> <stdio.h>
<string.h> <string.h>
"RTC.h" "RTC.h"