From e117da235e939a47e4dd08fbded68abc3165271d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 21 Oct 2019 23:14:34 +0200 Subject: smarter CP15 PU region updates. disable some useless logging. fixes #528 --- src/ARM.h | 3 +- src/CP15.cpp | 307 +++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 175 insertions(+), 135 deletions(-) diff --git a/src/ARM.h b/src/ARM.h index d13d535..dcff477 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -211,7 +211,8 @@ public: void UpdateDTCMSetting(); void UpdateITCMSetting(); - void UpdatePURegions(); + void UpdatePURegion(u32 n); + void UpdatePURegions(bool update_all); u32 RandomLineIndex(); diff --git a/src/CP15.cpp b/src/CP15.cpp index a4db5f3..cf0ece9 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -59,7 +59,7 @@ void ARMv5::CP15Reset() PU_DataRW = 0; memset(PU_Region, 0, 8*sizeof(u32)); - UpdatePURegions(); + UpdatePURegions(true); CurICacheLine = NULL; } @@ -89,7 +89,7 @@ void ARMv5::CP15DoSavestate(Savestate* file) { UpdateDTCMSetting(); UpdateITCMSetting(); - UpdatePURegions(); + UpdatePURegions(true); } } @@ -125,27 +125,12 @@ 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) { - if (!(CP15Control & (1<<0))) - { - // PU disabled - - u8 mask = 0x07; - if (CP15Control & (1<<2)) mask |= 0x30; - if (CP15Control & (1<<12)) mask |= 0x40; - - memset(PU_UserMap, mask, 0x100000); - memset(PU_PrivMap, mask, 0x100000); - - return; - } - - memset(PU_UserMap, 0, 0x100000); - memset(PU_PrivMap, 0, 0x100000); - - u32 coderw = PU_CodeRW; - u32 datarw = PU_DataRW; + u32 coderw = (PU_CodeRW >> (4*n)) & 0xF; + u32 datarw = (PU_DataRW >> (4*n)) & 0xF; u32 codecache, datacache, datawrite; @@ -156,14 +141,14 @@ void ARMv5::UpdatePURegions() // 1/1: goes to cache if (CP15Control & (1<<12)) - codecache = PU_CodeCacheable; + codecache = (PU_CodeCacheable >> n) & 0x1; else codecache = 0; if (CP15Control & (1<<2)) { - datacache = PU_DataCacheable; - datawrite = PU_DataCacheWrite; + datacache = (PU_DataCacheable >> n) & 0x1; + datawrite = (PU_DataCacheWrite >> n) & 0x1; } else { @@ -171,88 +156,102 @@ void ARMv5::UpdatePURegions() datawrite = 0; } - for (int n = 0; n < 8; n++) + u32 rgn = PU_Region[n]; + if (!(rgn & (1<<0))) { - u32 rgn = PU_Region[n]; - if (!(rgn & (1<<0))) - { - coderw >>= 4; - datarw >>= 4; - codecache >>= 1; - datacache >>= 1; - datawrite >>= 1; - continue; - } + return; + } - u32 start = rgn >> 12; - u32 sz = 2 << ((rgn >> 1) & 0x1F); - u32 end = start + (sz >> 12); - // TODO: check alignment of start + 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; + 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 (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 & 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) { - 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); + privmask |= 0x20; + usermask |= 0x20; } + } - if (datacache & 0x1) - { - privmask |= 0x10; - usermask |= 0x10; + if (codecache & 0x1) + { + privmask |= 0x40; + usermask |= 0x40; + } - if (datawrite & 0x1) - { - privmask |= 0x20; - usermask |= 0x20; - } - } + //printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask); - if (codecache & 0x1) - { - privmask |= 0x40; - usermask |= 0x40; - } + for (u32 i = start; i < end; i++) + { + PU_UserMap[i] = usermask; + PU_PrivMap[i] = privmask; + } - printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask); + UpdateRegionTimings(start<<12, end<<12); +} - for (u32 i = start; i < end; i++) - { - PU_UserMap[i] = usermask; - PU_PrivMap[i] = privmask; - } +void ARMv5::UpdatePURegions(bool update_all) +{ + if (!(CP15Control & (1<<0))) + { + // PU disabled - coderw >>= 4; - datarw >>= 4; - codecache >>= 1; - datacache >>= 1; - datawrite >>= 1; + u8 mask = 0x07; + if (CP15Control & (1<<2)) mask |= 0x30; + if (CP15Control & (1<<12)) mask |= 0x40; + + memset(PU_UserMap, mask, 0x100000); + memset(PU_PrivMap, mask, 0x100000); + + UpdateRegionTimings(0x00000000, 0xFFFFFFFF); + return; + } + + if (update_all) + { + memset(PU_UserMap, 0, 0x100000); + memset(PU_PrivMap, 0, 0x100000); + } - // TODO: this will not be enough if they change their PU regions after the intial setup - //UpdateRegionTimings(start<<12, end<<12); + for (int n = 0; n < 8; n++) + { + 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) @@ -302,7 +301,6 @@ u32 ARMv5::RandomLineIndex() return (RNGSeed >> 17) & 0x3; } -int zog=1; void ARMv5::ICacheLookup(u32 addr) { u32 tag = addr & 0xFFFFF800; @@ -311,25 +309,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; } @@ -417,10 +415,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; @@ -429,63 +430,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<>1))); - UpdatePURegions(); + // TODO: smarter region update for this? + UpdatePURegions(true); return; -- cgit v1.2.3 From 3561e93bf6b72debe61380e277b40b07d1fd22c3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 3 Nov 2019 04:32:47 +0100 Subject: fix sprite y-flip also, meaningless shenanigans --- src/GPU2D.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++------------ src/GPU2D.h | 5 +++-- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index b510767..52c7be2 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -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; @@ -2327,6 +2334,8 @@ void GPU2D::DrawSprites(u32 line) memset(OBJWindow, 0, 256); if (!(DispCnt & 0x1000)) return; + memset(OBJIndex, 0xFF, 256); + u16* oam = (u16*)&GPU::OAM[Num ? 0x400 : 0]; const s32 spritewidth[16] = @@ -2380,7 +2389,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++; } @@ -2403,10 +2412,10 @@ void GPU2D::DrawSprites(u32 line) continue; // yflip - if (attrib[1] & 0x2000) - ypos = height-1 - ypos; + //if (attrib[1] & 0x2000) + // ypos = height-1 - ypos; - DoDrawSprite(Normal, attrib, width, xpos, ypos); + DoDrawSprite(Normal, sprnum, width, height, xpos, ypos); NumSprites++; } @@ -2415,8 +2424,12 @@ void GPU2D::DrawSprites(u32 line) } template -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); @@ -2509,12 +2522,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 +2579,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 +2623,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 +2645,11 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 } template -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); @@ -2640,6 +2665,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) pixelattr |= 0x100000; } + // yflip + if (attrib[1] & 0x2000) + ypos = height-1 - ypos; + u32 xoff; u32 xend = width; if (xpos >= 0) @@ -2719,12 +2748,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 +2818,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 +2882,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++; diff --git a/src/GPU2D.h b/src/GPU2D.h index 8c6ec27..6675ce7 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -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 void DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos); - template void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos); + template void DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos); + template void DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos); void DoCapture(u32 line, u32 width); -- cgit v1.2.3 From b641ccaf35b68cfe465257c57cb2a6dda039bc46 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 3 Nov 2019 04:53:11 +0100 Subject: fix remaining sprite y-coord bugs. fixes #531 --- src/GPU2D.cpp | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 52c7be2..30a6d45 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -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) { @@ -2329,6 +2329,18 @@ 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); @@ -2364,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); @@ -2379,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; @@ -2403,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; @@ -2411,10 +2432,6 @@ void GPU2D::DrawSprites(u32 line) if (xpos <= -width) continue; - // yflip - //if (attrib[1] & 0x2000) - // ypos = height-1 - ypos; - DoDrawSprite(Normal, sprnum, width, height, xpos, ypos); NumSprites++; @@ -2442,9 +2459,6 @@ void GPU2D::DrawSprite_Rotscale(u32 num, u32 boundwidth, u32 boundheight, u32 wi if ((attrib[0] & 0x1000) && !window) { // apply Y mosaic - ypos = OBJMosaicY - (attrib[0] & 0xFF); - if (ypos < 0) ypos = 0; - pixelattr |= 0x100000; } @@ -2659,9 +2673,6 @@ void GPU2D::DrawSprite_Normal(u32 num, u32 width, u32 height, s32 xpos, s32 ypos if ((attrib[0] & 0x1000) && !window) { // apply Y mosaic - ypos = OBJMosaicY - (attrib[0] & 0xFF); - if (ypos < 0) ypos = 0; - pixelattr |= 0x100000; } -- cgit v1.2.3 From c064f738ea55502a6aa2babf8e56ce915cffb80e Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 3 Nov 2019 09:55:52 +0100 Subject: OpenGL: fix bug when rendering translucent polygons coming after shadow polygons, against a zero-alpha clear-plane (would use wrong shader, resulting in broken transparency) --- src/GPU3D_OpenGL.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index d616e1c..6abb1ab 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -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); -- cgit v1.2.3 From 3f7bc1a6c19dc502bfe00f26d0720961cf130363 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 8 Nov 2019 21:55:13 +0100 Subject: add warning against hacked firmware dumps --- src/libui_sdl/main.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 13778ec..d6aa460 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -2664,6 +2664,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) -- cgit v1.2.3 From 9381b531cd4544cc68998f604211bcbffb90cd3c Mon Sep 17 00:00:00 2001 From: Raphaƫl Zumer Date: Sat, 7 Dec 2019 15:26:58 -0500 Subject: Ignore the build directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bd1d485..dd81614 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +build bin obj *.depend -- cgit v1.2.3