diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/GPU3D.cpp | 193 | ||||
-rw-r--r-- | src/NDS.cpp | 19 | ||||
-rw-r--r-- | src/NDSCart.cpp | 70 | ||||
-rw-r--r-- | src/NDSCart.h | 1 | ||||
-rw-r--r-- | src/Savestate.h | 2 | ||||
-rw-r--r-- | src/libui_sdl/CMakeLists.txt | 18 | ||||
-rw-r--r-- | src/libui_sdl/MelonCap.cpp | 4 |
7 files changed, 211 insertions, 96 deletions
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 52bc10f..4f146ae 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -181,6 +181,8 @@ u8 RenderFogDensityTable[34]; u32 RenderClearAttr1, RenderClearAttr2; +u32 ZeroDotWLimit; + u32 GXStat; u32 ExecParams[32]; @@ -332,6 +334,8 @@ void Reset() DispCnt = 0; AlphaRef = 0; + ZeroDotWLimit = 0; // CHECKME + GXStat = 0; memset(ExecParams, 0, 32*4); @@ -409,6 +413,8 @@ void DoSavestate(Savestate* file) file->Var32(&DispCnt); file->Var8(&AlphaRef); + file->Var32(&ZeroDotWLimit); + file->Var32(&GXStat); file->VarArray(ExecParams, 32*4); @@ -569,27 +575,12 @@ void DoSavestate(Savestate* file) // probably not worth storing the vblank-latched Renderxxxxxx variables - if (file->IsAtleastVersion(2, 1)) - { - // command stall queue, only in version 2.1 and up - CmdStallQueue->DoSavestate(file); - file->Var32((u32*)&VertexPipeline); - file->Var32((u32*)&NormalPipeline); - file->Var32((u32*)&PolygonPipeline); - file->Var32((u32*)&VertexSlotCounter); - file->Var32(&VertexSlotsFree); - } - else - { - // for version 2.0, just clear it. not having it doesn't matter - // if this comes from older melonDS revisions. - CmdStallQueue->Clear(); - VertexPipeline = 0; - NormalPipeline = 0; - PolygonPipeline = 0; - VertexSlotCounter = 0; - VertexSlotsFree = 1; - } + CmdStallQueue->DoSavestate(file); + file->Var32((u32*)&VertexPipeline); + file->Var32((u32*)&NormalPipeline); + file->Var32((u32*)&PolygonPipeline); + file->Var32((u32*)&VertexSlotCounter); + file->Var32(&VertexSlotsFree); if (!file->Saving) { @@ -888,7 +879,7 @@ void StallPolygonPipeline(s32 delay, s32 nonstalldelay) template<int comp, s32 plane, bool attribs> -void ClipSegment(Vertex* outbuf, Vertex* vout, Vertex* vin) +void ClipSegment(Vertex* outbuf, Vertex* vin, Vertex* vout) { s64 factor_num = vin->Position[3] - (plane*vin->Position[comp]); s32 factor_den = factor_num - (vout->Position[3] - (plane*vout->Position[comp])); @@ -1170,6 +1161,104 @@ void SubmitPolygon() return; } + // reject the polygon if it's not going to fit in polygon/vertex RAM + + if (NumPolygons >= 2048 || NumVertices+nverts > 6144) + { + LastStripPolygon = NULL; + DispCnt |= (1<<13); + return; + } + + // compute screen coordinates + + for (int i = clipstart; i < nverts; i++) + { + Vertex* vtx = &clippedvertices[i]; + + // W is truncated to 24 bits at this point + // if this W is zero, the polygon isn't rendered + vtx->Position[3] &= 0x00FFFFFF; + + // viewport transform + // note: the DS performs these divisions using a 32-bit divider + // thus, if W is greater than 0xFFFF, some precision is sacrificed + // to make the numbers fit into the divider + u32 posX, posY; + u32 w = vtx->Position[3]; + if (w == 0) + { + posX = 0; + posY = 0; + } + else + { + posX = vtx->Position[0] + w; + posY = -vtx->Position[1] + w; + u32 den = w; + + if (w > 0xFFFF) + { + posX >>= 1; + posY >>= 1; + den >>= 1; + } + + den <<= 1; + posX = ((posX * Viewport[4]) / den) + Viewport[0]; + posY = ((posY * Viewport[5]) / den) + Viewport[3]; + } + + vtx->FinalPosition[0] = posX & 0x1FF; + vtx->FinalPosition[1] = posY & 0xFF; + + // hi-res positions + // to consider: only do this when using the GL renderer? apply the aforementioned quirk to this? + if (w != 0) + { + posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4); + posY = ((((s64)(-vtx->Position[1] + w) * Viewport[5]) << 4) / (((s64)w) << 1)) + (Viewport[3] << 4); + + vtx->HiresPosition[0] = posX & 0x1FFF; + vtx->HiresPosition[1] = posY & 0xFFF; + } + } + + // zero-dot W check: + // * if the polygon's vertices all have the same screen coordinates, it is considered to be zero-dot + // * if all the vertices have a W greater than the threshold defined in register 0x04000610, + // the polygon is rejected, unless bit13 in the polygon attributes is set + + if (!(CurPolygonAttr & (1<<13))) + { + bool zerodot = true; + bool allbehind = true; + + for (int i = 0; i < nverts; i++) + { + Vertex* vtx = &clippedvertices[i]; + + if (vtx->FinalPosition[0] != clippedvertices[0].FinalPosition[0] || + vtx->FinalPosition[1] != clippedvertices[0].FinalPosition[1]) + { + zerodot = false; + break; + } + + if (vtx->Position[3] <= ZeroDotWLimit) + { + allbehind = false; + break; + } + } + + if (zerodot && allbehind) + { + LastStripPolygon = NULL; + return; + } + } + // build the actual polygon if (nverts == 4) @@ -1187,13 +1276,6 @@ void SubmitPolygon() else VertexSlotsFree = 0b1110; } - if (NumPolygons >= 2048 || NumVertices+nverts > 6144) - { - LastStripPolygon = NULL; - DispCnt |= (1<<13); - return; - } - Polygon* poly = &CurPolygonRAM[NumPolygons++]; poly->NumVertices = 0; @@ -1248,37 +1330,6 @@ void SubmitPolygon() NumVertices++; poly->NumVertices++; - // W is truncated to 24 bits at this point - // if this W is zero, the polygon isn't rendered - vtx->Position[3] &= 0x00FFFFFF; - - // viewport transform - s32 posX, posY; - s32 w = vtx->Position[3]; - if (w == 0) - { - posX = 0; - posY = 0; - } - else - { - posX = (((s64)(vtx->Position[0] + w) * Viewport[4]) / (((s64)w) << 1)) + Viewport[0]; - posY = (((s64)(-vtx->Position[1] + w) * Viewport[5]) / (((s64)w) << 1)) + Viewport[3]; - } - - vtx->FinalPosition[0] = posX & 0x1FF; - vtx->FinalPosition[1] = posY & 0xFF; - - // hi-res positions - if (w != 0) - { - posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4); - posY = ((((s64)(-vtx->Position[1] + w) * Viewport[5]) << 4) / (((s64)w) << 1)) + (Viewport[3] << 4); - - vtx->HiresPosition[0] = posX & 0x1FFF; - vtx->HiresPosition[1] = posY & 0xFFF; - } - vtx->FinalColor[0] = vtx->Color[0] >> 12; if (vtx->FinalColor[0]) vtx->FinalColor[0] = ((vtx->FinalColor[0] << 4) + 0xF); vtx->FinalColor[1] = vtx->Color[1] >> 12; @@ -2716,12 +2767,24 @@ void Write8(u32 addr, u8 val) return; } + if (addr >= 0x04000330 && addr < 0x04000340) + { + ((u8*)EdgeTable)[addr - 0x04000330] = val; + return; + } + if (addr >= 0x04000360 && addr < 0x04000380) { FogDensityTable[addr - 0x04000360] = val & 0x7F; return; } + if (addr >= 0x04000380 && addr < 0x040003C0) + { + ((u8*)ToonTable)[addr - 0x04000380] = val; + return; + } + printf("unknown GPU3D write8 %08X %02X\n", addr, val); } @@ -2782,6 +2845,11 @@ void Write16(u32 addr, u16 val) GXStat |= (val << 16); CheckFIFOIRQ(); return; + + case 0x04000610: + val &= 0x7FFF; + ZeroDotWLimit = (val * 0x200) + 0x1FF; + return; } if (addr >= 0x04000330 && addr < 0x04000340) @@ -2853,6 +2921,11 @@ void Write32(u32 addr, u32 val) GXStat |= val; CheckFIFOIRQ(); return; + + case 0x04000610: + val &= 0x7FFF; + ZeroDotWLimit = (val * 0x200) + 0x1FF; + return; } if (addr >= 0x04000400 && addr < 0x04000440) diff --git a/src/NDS.cpp b/src/NDS.cpp index 09d255d..a2ab6ce 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -318,7 +318,24 @@ void SetupDirectBoot() MapSharedWRAM(3); - for (u32 i = 0; i < bootparams[3]; i+=4) + u32 arm9start = 0; + + // load the ARM9 secure area + if (bootparams[0] >= 0x4000 && bootparams[0] < 0x8000) + { + u8 securearea[0x800]; + NDSCart::DecryptSecureArea(securearea); + + for (u32 i = 0; i < 0x800; i+=4) + { + ARM9Write32(bootparams[2]+i, *(u32*)&securearea[i]); + arm9start += 4; + } + } + + // CHECKME: firmware seems to load this in 0x200 byte chunks + + for (u32 i = arm9start; i < bootparams[3]; i+=4) { u32 tmp = *(u32*)&NDSCart::CartROM[bootparams[0]+i]; ARM9Write32(bootparams[2]+i, tmp); diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index c313011..5a2a0d0 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -865,6 +865,35 @@ bool ReadROMParams(u32 gamecode, u32* params) } +void DecryptSecureArea(u8* out) +{ + u32 gamecode = *(u32*)&CartROM[0x0C]; + u32 arm9base = *(u32*)&CartROM[0x20]; + + memcpy(out, &CartROM[arm9base], 0x800); + + Key1_InitKeycode(gamecode, 2, 2); + Key1_Decrypt((u32*)&out[0]); + + Key1_InitKeycode(gamecode, 3, 2); + for (u32 i = 0; i < 0x800; i += 8) + Key1_Decrypt((u32*)&out[i]); + + if (!strncmp((const char*)out, "encryObj", 8)) + { + printf("Secure area decryption OK\n"); + *(u32*)&out[0] = 0xE7FFDEFF; + *(u32*)&out[4] = 0xE7FFDEFF; + } + else + { + printf("Secure area decryption failed\n"); + for (u32 i = 0; i < 0x800; i += 4) + *(u32*)&out[i] = 0xE7FFDEFF; + } +} + + bool LoadROM(const char* path, const char* sram, bool direct) { // TODO: streaming mode? for really big ROMs or systems with limited RAM @@ -933,28 +962,8 @@ bool LoadROM(const char* path, const char* sram, bool direct) printf("Cart ID: %08X\n", CartID); - if (*(u32*)&CartROM[0x20] < 0x4000) - { - //ApplyDLDIPatch(); - } - - if (direct) - { - // TODO: in the case of an already-encrypted secure area, direct boot - // needs it decrypted - NDS::SetupDirectBoot(); - CmdEncMode = 2; - } - - CartInserted = true; - - // TODO: support more fancy cart types (homebrew?, flashcarts, etc) - if (CartID & 0x08000000) - ROMCommandHandler = ROMCommand_RetailNAND; - else - ROMCommandHandler = ROMCommand_Retail; - u32 arm9base = *(u32*)&CartROM[0x20]; + if (arm9base < 0x8000) { if (arm9base >= 0x4000) @@ -975,9 +984,28 @@ bool LoadROM(const char* path, const char* sram, bool direct) } } else + { CartIsHomebrew = true; + //ApplyDLDIPatch(); + } + } + + if (direct) + { + // TODO: in the case of an already-encrypted secure area, direct boot + // needs it decrypted + NDS::SetupDirectBoot(); + CmdEncMode = 2; } + CartInserted = true; + + // TODO: support more fancy cart types (homebrew?, flashcarts, etc) + if (CartID & 0x08000000) + ROMCommandHandler = ROMCommand_RetailNAND; + else + ROMCommandHandler = ROMCommand_Retail; + // encryption Key1_InitKeycode(gamecode, 2, 2); diff --git a/src/NDSCart.h b/src/NDSCart.h index 4167aa6..f19aea1 100644 --- a/src/NDSCart.h +++ b/src/NDSCart.h @@ -44,6 +44,7 @@ void Reset(); void DoSavestate(Savestate* file); +void DecryptSecureArea(u8* out); bool LoadROM(const char* path, const char* sram, bool direct); void RelocateSave(const char* path, bool write); diff --git a/src/Savestate.h b/src/Savestate.h index 4793b77..a5447b3 100644 --- a/src/Savestate.h +++ b/src/Savestate.h @@ -22,7 +22,7 @@ #include <stdio.h> #include "types.h" -#define SAVESTATE_MAJOR 5 +#define SAVESTATE_MAJOR 6 #define SAVESTATE_MINOR 0 class Savestate diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 8c8467b..a3a7f8a 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -22,13 +22,12 @@ option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static set(BUILD_SHARED_LIBS OFF) add_subdirectory(libui) -find_package(SDL2 REQUIRED) -include_directories(${SDL2_INCLUDE_DIR}) -#string(STRIP ${SDL2_LIBRARIES} SDL2_LIBRARIES) +find_package(PkgConfig REQUIRED) +pkg_check_modules(SDL2 REQUIRED sdl2) add_executable(melonDS ${SOURCES_LIBUI}) -target_link_libraries(melonDS - core ${SDL2_LIBRARIES} libui) +target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) +target_link_libraries(melonDS core libui ${SDL2_LIBRARIES}) if (UNIX) option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) @@ -38,12 +37,9 @@ if (UNIX) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk+-3.0) - pkg_check_modules(SDL2 REQUIRED sdl2) - target_include_directories(melonDS - PRIVATE ${GTK3_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS} - ) - target_link_libraries(melonDS ${GTK3_LIBRARIES} ${SDL2_LIBRARIES}) + target_include_directories(melonDS PRIVATE ${GTK3_INCLUDE_DIRS}) + target_link_libraries(melonDS ${GTK3_LIBRARIES}) ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) @@ -63,7 +59,7 @@ if (UNIX) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi) + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) endif () install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp index 6e45bf5..2658b66 100644 --- a/src/libui_sdl/MelonCap.cpp +++ b/src/libui_sdl/MelonCap.cpp @@ -336,8 +336,8 @@ void Update() colA &= mask; colB &= mask; - if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF00FF00; - else WinBitmapData[(y*768) + x + 512] = 0xFFFF0000; + if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF000000;//0xFF00FF00; + else WinBitmapData[(y*768) + x + 512] = 0xFFFFFFFF;//0xFFFF0000; } } |