aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GPU3D.cpp193
-rw-r--r--src/NDS.cpp19
-rw-r--r--src/NDSCart.cpp70
-rw-r--r--src/NDSCart.h1
-rw-r--r--src/Savestate.h2
-rw-r--r--src/libui_sdl/CMakeLists.txt18
-rw-r--r--src/libui_sdl/MelonCap.cpp4
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;
}
}