merge moar

This commit is contained in:
Arisotura 2020-05-30 03:04:14 +02:00
commit b44570eba1
7 changed files with 311 additions and 180 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
build
bin
obj
*.depend

View File

@ -212,7 +212,8 @@ public:
void UpdateDTCMSetting();
void UpdateITCMSetting();
void UpdatePURegions();
void UpdatePURegion(u32 n);
void UpdatePURegions(bool update_all);
u32 RandomLineIndex();

View File

@ -60,7 +60,7 @@ void ARMv5::CP15Reset()
PU_DataRW = 0;
memset(PU_Region, 0, 8*sizeof(u32));
UpdatePURegions();
UpdatePURegions(true);
CurICacheLine = NULL;
}
@ -90,7 +90,7 @@ void ARMv5::CP15DoSavestate(Savestate* file)
{
UpdateDTCMSetting();
UpdateITCMSetting();
UpdatePURegions();
UpdatePURegions(true);
}
}
@ -126,7 +126,103 @@ void ARMv5::UpdateITCMSetting()
}
void ARMv5::UpdatePURegions()
// covers updates to a specific PU region's cache/etc settings
// (not to the region range/enabled status)
void ARMv5::UpdatePURegion(u32 n)
{
u32 coderw = (PU_CodeRW >> (4*n)) & 0xF;
u32 datarw = (PU_DataRW >> (4*n)) & 0xF;
u32 codecache, datacache, datawrite;
// datacache/datawrite
// 0/0: goes to memory
// 0/1: goes to memory
// 1/0: goes to memory and cache
// 1/1: goes to cache
if (CP15Control & (1<<12))
codecache = (PU_CodeCacheable >> n) & 0x1;
else
codecache = 0;
if (CP15Control & (1<<2))
{
datacache = (PU_DataCacheable >> n) & 0x1;
datawrite = (PU_DataCacheWrite >> n) & 0x1;
}
else
{
datacache = 0;
datawrite = 0;
}
u32 rgn = PU_Region[n];
if (!(rgn & (1<<0)))
{
return;
}
u32 start = rgn >> 12;
u32 sz = 2 << ((rgn >> 1) & 0x1F);
u32 end = start + (sz >> 12);
// TODO: check alignment of start
u8 usermask = 0;
u8 privmask = 0;
switch (datarw)
{
case 0: break;
case 1: privmask |= 0x03; break;
case 2: privmask |= 0x03; usermask |= 0x01; break;
case 3: privmask |= 0x03; usermask |= 0x03; break;
case 5: privmask |= 0x01; break;
case 6: privmask |= 0x01; usermask |= 0x01; break;
default: printf("!! BAD DATARW VALUE %d\n", datarw&0xF);
}
switch (coderw)
{
case 0: break;
case 1: privmask |= 0x04; break;
case 2: privmask |= 0x04; usermask |= 0x04; break;
case 3: privmask |= 0x04; usermask |= 0x04; break;
case 5: privmask |= 0x04; break;
case 6: privmask |= 0x04; usermask |= 0x04; break;
default: printf("!! BAD CODERW VALUE %d\n", datarw&0xF);
}
if (datacache & 0x1)
{
privmask |= 0x10;
usermask |= 0x10;
if (datawrite & 0x1)
{
privmask |= 0x20;
usermask |= 0x20;
}
}
if (codecache & 0x1)
{
privmask |= 0x40;
usermask |= 0x40;
}
//printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask);
for (u32 i = start; i < end; i++)
{
PU_UserMap[i] = usermask;
PU_PrivMap[i] = privmask;
}
UpdateRegionTimings(start<<12, end<<12);
}
void ARMv5::UpdatePURegions(bool update_all)
{
if (!(CP15Control & (1<<0)))
{
@ -139,121 +235,24 @@ void ARMv5::UpdatePURegions()
memset(PU_UserMap, mask, 0x100000);
memset(PU_PrivMap, mask, 0x100000);
UpdateRegionTimings(0x00000000, 0xFFFFFFFF);
return;
}
memset(PU_UserMap, 0, 0x100000);
memset(PU_PrivMap, 0, 0x100000);
u32 coderw = PU_CodeRW;
u32 datarw = PU_DataRW;
u32 codecache, datacache, datawrite;
// datacache/datawrite
// 0/0: goes to memory
// 0/1: goes to memory
// 1/0: goes to memory and cache
// 1/1: goes to cache
if (CP15Control & (1<<12))
codecache = PU_CodeCacheable;
else
codecache = 0;
if (CP15Control & (1<<2))
if (update_all)
{
datacache = PU_DataCacheable;
datawrite = PU_DataCacheWrite;
}
else
{
datacache = 0;
datawrite = 0;
memset(PU_UserMap, 0, 0x100000);
memset(PU_PrivMap, 0, 0x100000);
}
for (int n = 0; n < 8; n++)
{
u32 rgn = PU_Region[n];
if (!(rgn & (1<<0)))
{
coderw >>= 4;
datarw >>= 4;
codecache >>= 1;
datacache >>= 1;
datawrite >>= 1;
continue;
}
u32 start = rgn >> 12;
u32 sz = 2 << ((rgn >> 1) & 0x1F);
u32 end = start + (sz >> 12);
// TODO: check alignment of start
u8 usermask = 0;
u8 privmask = 0;
switch (datarw & 0xF)
{
case 0: break;
case 1: privmask |= 0x03; break;
case 2: privmask |= 0x03; usermask |= 0x01; break;
case 3: privmask |= 0x03; usermask |= 0x03; break;
case 5: privmask |= 0x01; break;
case 6: privmask |= 0x01; usermask |= 0x01; break;
default: printf("!! BAD DATARW VALUE %d\n", datarw&0xF);
}
switch (coderw & 0xF)
{
case 0: break;
case 1: privmask |= 0x04; break;
case 2: privmask |= 0x04; usermask |= 0x04; break;
case 3: privmask |= 0x04; usermask |= 0x04; break;
case 5: privmask |= 0x04; break;
case 6: privmask |= 0x04; usermask |= 0x04; break;
default: printf("!! BAD CODERW VALUE %d\n", datarw&0xF);
}
if (datacache & 0x1)
{
privmask |= 0x10;
usermask |= 0x10;
if (datawrite & 0x1)
{
privmask |= 0x20;
usermask |= 0x20;
}
}
if (codecache & 0x1)
{
privmask |= 0x40;
usermask |= 0x40;
}
printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask);
for (u32 i = start; i < end; i++)
{
PU_UserMap[i] = usermask;
PU_PrivMap[i] = privmask;
}
coderw >>= 4;
datarw >>= 4;
codecache >>= 1;
datacache >>= 1;
datawrite >>= 1;
// TODO: this will not be enough if they change their PU regions after the intial setup
//UpdateRegionTimings(start<<12, end<<12);
UpdatePURegion(n);
}
// TODO: this is way unoptimized
// should be okay unless the game keeps changing shit, tho
UpdateRegionTimings(0x00000000, 0xFFFFFFFF);
if (update_all) UpdateRegionTimings(0x00000000, 0xFFFFFFFF);
}
void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
@ -303,7 +302,6 @@ u32 ARMv5::RandomLineIndex()
return (RNGSeed >> 17) & 0x3;
}
int zog=1;
void ARMv5::ICacheLookup(u32 addr)
{
u32 tag = addr & 0xFFFFF800;
@ -312,25 +310,25 @@ void ARMv5::ICacheLookup(u32 addr)
id <<= 2;
if (ICacheTags[id+0] == tag)
{
CodeCycles = 1;zog=1;
CodeCycles = 1;
CurICacheLine = &ICache[(id+0) << 5];
return;
}
if (ICacheTags[id+1] == tag)
{
CodeCycles = 1;zog=2;
CodeCycles = 1;
CurICacheLine = &ICache[(id+1) << 5];
return;
}
if (ICacheTags[id+2] == tag)
{
CodeCycles = 1;zog=3;
CodeCycles = 1;
CurICacheLine = &ICache[(id+2) << 5];
return;
}
if (ICacheTags[id+3] == tag)
{
CodeCycles = 1;zog=4;
CodeCycles = 1;
CurICacheLine = &ICache[(id+3) << 5];
return;
}
@ -418,10 +416,13 @@ void ARMv5::CP15Write(u32 id, u32 val)
val &= 0x000FF085;
CP15Control &= ~0x000FF085;
CP15Control |= val;
printf("CP15Control = %08X (%08X->%08X)\n", CP15Control, old, val);
//printf("CP15Control = %08X (%08X->%08X)\n", CP15Control, old, val);
UpdateDTCMSetting();
UpdateITCMSetting();
if ((old & 0x1005) != (val & 0x1005)) UpdatePURegions();
if ((old & 0x1005) != (val & 0x1005))
{
UpdatePURegions((old & 0x1) != (val & 0x1));
}
if (val & (1<<7)) printf("!!!! ARM9 BIG ENDIAN MODE. VERY BAD. SHIT GONNA ASPLODE NOW\n");
if (val & (1<<13)) ExceptionBase = 0xFFFF0000;
else ExceptionBase = 0x00000000;
@ -430,63 +431,100 @@ void ARMv5::CP15Write(u32 id, u32 val)
case 0x200: // data cacheable
PU_DataCacheable = val;
printf("PU: DataCacheable=%08X\n", val);
UpdatePURegions();
{
u32 diff = PU_DataCacheable ^ val;
PU_DataCacheable = val;
for (u32 i = 0; i < 8; i++)
{
if (diff & (1<<i)) UpdatePURegion(i);
}
}
return;
case 0x201: // code cacheable
PU_CodeCacheable = val;
printf("PU: CodeCacheable=%08X\n", val);
UpdatePURegions();
{
u32 diff = PU_CodeCacheable ^ val;
PU_CodeCacheable = val;
for (u32 i = 0; i < 8; i++)
{
if (diff & (1<<i)) UpdatePURegion(i);
}
}
return;
case 0x300: // data cache write-buffer
PU_DataCacheWrite = val;
printf("PU: DataCacheWrite=%08X\n", val);
UpdatePURegions();
{
u32 diff = PU_DataCacheWrite ^ val;
PU_DataCacheWrite = val;
for (u32 i = 0; i < 8; i++)
{
if (diff & (1<<i)) UpdatePURegion(i);
}
}
return;
case 0x500: // legacy data permissions
PU_DataRW = 0;
PU_DataRW |= (val & 0x0003);
PU_DataRW |= ((val & 0x000C) << 2);
PU_DataRW |= ((val & 0x0030) << 4);
PU_DataRW |= ((val & 0x00C0) << 6);
PU_DataRW |= ((val & 0x0300) << 8);
PU_DataRW |= ((val & 0x0C00) << 10);
PU_DataRW |= ((val & 0x3000) << 12);
PU_DataRW |= ((val & 0xC000) << 14);
printf("PU: DataRW=%08X (legacy %08X)\n", PU_DataRW, val);
UpdatePURegions();
{
u32 old = PU_DataRW;
PU_DataRW = 0;
PU_DataRW |= (val & 0x0003);
PU_DataRW |= ((val & 0x000C) << 2);
PU_DataRW |= ((val & 0x0030) << 4);
PU_DataRW |= ((val & 0x00C0) << 6);
PU_DataRW |= ((val & 0x0300) << 8);
PU_DataRW |= ((val & 0x0C00) << 10);
PU_DataRW |= ((val & 0x3000) << 12);
PU_DataRW |= ((val & 0xC000) << 14);
u32 diff = old ^ PU_DataRW;
for (u32 i = 0; i < 8; i++)
{
if (diff & (0xF<<(i*4))) UpdatePURegion(i);
}
}
return;
case 0x501: // legacy code permissions
PU_CodeRW = 0;
PU_CodeRW |= (val & 0x0003);
PU_CodeRW |= ((val & 0x000C) << 2);
PU_CodeRW |= ((val & 0x0030) << 4);
PU_CodeRW |= ((val & 0x00C0) << 6);
PU_CodeRW |= ((val & 0x0300) << 8);
PU_CodeRW |= ((val & 0x0C00) << 10);
PU_CodeRW |= ((val & 0x3000) << 12);
PU_CodeRW |= ((val & 0xC000) << 14);
printf("PU: CodeRW=%08X (legacy %08X)\n", PU_CodeRW, val);
UpdatePURegions();
{
u32 old = PU_CodeRW;
PU_CodeRW = 0;
PU_CodeRW |= (val & 0x0003);
PU_CodeRW |= ((val & 0x000C) << 2);
PU_CodeRW |= ((val & 0x0030) << 4);
PU_CodeRW |= ((val & 0x00C0) << 6);
PU_CodeRW |= ((val & 0x0300) << 8);
PU_CodeRW |= ((val & 0x0C00) << 10);
PU_CodeRW |= ((val & 0x3000) << 12);
PU_CodeRW |= ((val & 0xC000) << 14);
u32 diff = old ^ PU_CodeRW;
for (u32 i = 0; i < 8; i++)
{
if (diff & (0xF<<(i*4))) UpdatePURegion(i);
}
}
return;
case 0x502: // data permissions
PU_DataRW = val;
printf("PU: DataRW=%08X\n", PU_DataRW);
UpdatePURegions();
{
u32 diff = PU_DataRW ^ val;
PU_DataRW = val;
for (u32 i = 0; i < 8; i++)
{
if (diff & (0xF<<(i*4))) UpdatePURegion(i);
}
}
return;
case 0x503: // code permissions
PU_CodeRW = val;
printf("PU: CodeRW=%08X\n", PU_CodeRW);
UpdatePURegions();
{
u32 diff = PU_CodeRW ^ val;
PU_CodeRW = val;
for (u32 i = 0; i < 8; i++)
{
if (diff & (0xF<<(i*4))) UpdatePURegion(i);
}
}
return;
@ -511,7 +549,8 @@ void ARMv5::CP15Write(u32 id, u32 val)
printf("%s, ", val&1 ? "enabled":"disabled");
printf("%08X-", val&0xFFFFF000);
printf("%08X\n", (val&0xFFFFF000)+(2<<((val&0x3E)>>1)));
UpdatePURegions();
// TODO: smarter region update for this?
UpdatePURegions(true);
return;

View File

@ -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++;

View File

@ -78,6 +78,7 @@ private:
u8 WindowMask[256] __attribute__((aligned (8)));
u32 OBJLine[256] __attribute__((aligned (8)));
u8 OBJWindow[256] __attribute__((aligned (8)));
u8 OBJIndex[256] __attribute__((aligned (8)));
u32 NumSprites;
@ -156,8 +157,8 @@ private:
void ApplySpriteMosaicX();
void InterleaveSprites(u32 prio);
template<bool window> void DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos);
template<bool window> void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos);
template<bool window> void DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos);
template<bool window> void DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos);
void DoCapture(u32 line, u32 width);

View File

@ -807,7 +807,6 @@ void RenderSceneChunk(int y, int h)
else
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE);
UseRenderShader(flags | RenderFlag_Trans);
glLineWidth(1.0);
if (NumOpaqueFinalPolys > -1)
@ -843,6 +842,8 @@ void RenderSceneChunk(int y, int h)
}
else if (rp->PolyData->Translucent)
{
UseRenderShader(flags | RenderFlag_Trans);
// zorp
glDepthFunc(GL_LESS);

View File

@ -2662,6 +2662,45 @@ int main(int argc, char** argv)
SDL_Quit();
return 0;
}
if (!Platform::LocalFileExists("firmware.bin.bak"))
{
// verify the firmware
//
// there are dumps of an old hacked firmware floating around on the internet
// and those are problematic
// the hack predates WFC, and, due to this, any game that alters the WFC
// access point data will brick that firmware due to it having critical
// data in the same area. it has the same problem on hardware.
//
// but this should help stop users from reporting that issue over and over
// again, when the issue is not from melonDS but from their firmware dump.
//
// I don't know about all the firmware hacks in existence, but the one I
// looked at has 0x180 bytes from the header repeated at 0x3FC80, but
// bytes 0x0C-0x14 are different.
FILE* f = Platform::OpenLocalFile("firmware.bin", "rb");
u8 chk1[0x180], chk2[0x180];
fseek(f, 0, SEEK_SET);
fread(chk1, 1, 0x180, f);
fseek(f, -0x380, SEEK_END);
fread(chk2, 1, 0x180, f);
memset(&chk1[0x0C], 0, 8);
memset(&chk2[0x0C], 0, 8);
fclose(f);
if (!memcmp(chk1, chk2, 0x180))
{
uiMsgBoxError(NULL,
"Problematic firmware dump",
"You are using an old hacked firmware dump.\n"
"Firmware boot will stop working if you run any game that alters WFC settings.\n\n"
"Note that the issue is not from melonDS, it would also happen on an actual DS.");
}
}
{
FILE* f = Platform::OpenLocalFile("romlist.bin", "rb");
if (f)