diff options
author | Arisotura <thetotalworm@gmail.com> | 2020-05-30 03:04:14 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2020-05-30 03:04:14 +0200 |
commit | b44570eba1aab5903ff99aac044dc3e777c264d3 (patch) | |
tree | 11a05b343c764c71f564a3774212a7e58818819d | |
parent | 61799c35bdf26a5754ca760ac92d4f07d6a9396b (diff) | |
parent | 9381b531cd4544cc68998f604211bcbffb90cd3c (diff) |
merge moar
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/ARM.h | 3 | ||||
-rw-r--r-- | src/CP15.cpp | 307 | ||||
-rw-r--r-- | src/GPU2D.cpp | 99 | ||||
-rw-r--r-- | src/GPU2D.h | 5 | ||||
-rw-r--r-- | src/GPU3D_OpenGL.cpp | 3 | ||||
-rw-r--r-- | src/libui_sdl/main.cpp | 39 |
7 files changed, 294 insertions, 163 deletions
@@ -1,3 +1,4 @@ +build bin obj *.depend @@ -212,7 +212,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 4654a2a..d412db6 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -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,27 +126,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; @@ -157,14 +142,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 { @@ -172,88 +157,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) @@ -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; diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index b510767..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) { @@ -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++; 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<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); 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); diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 08d38b2..3d894f4 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -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) |