From 3b0b103eb3fa9ce65ed33adf0a170a5b8ab35a40 Mon Sep 17 00:00:00 2001 From: TobiD7 Date: Sat, 21 Mar 2026 10:18:01 +0100 Subject: [PATCH] Add nintendo switch support --- backends/CMakeLists.txt | 85 +++++++++++++++++++--------------- tests/CMakeLists.txt | 3 +- tests/assets/icon.jpg | Bin 0 -> 7918 bytes tests/assets/icon.png | Bin 0 -> 21910 bytes tests/assets/icon48.png | Bin 0 -> 1895 bytes tests/cmake/targets.cmake | 45 ++++++++++++++++++ tests/gfx/CMakeLists.txt | 38 +++++++++++++-- tests/gfx/source/main.cpp | 94 ++++++++++++++++++++++++++++---------- vendor/CMakeLists.txt | 25 +++++----- 9 files changed, 214 insertions(+), 76 deletions(-) create mode 100644 tests/assets/icon.jpg create mode 100644 tests/assets/icon.png create mode 100644 tests/assets/icon48.png create mode 100644 tests/cmake/targets.cmake diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index 997d027..15d475d 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -9,44 +9,49 @@ option(PD_ENABLE_CITRO3D "Enable Citro3D Support (3DS)" OFF) option(PD_ENABLE_VULKAN "Not implemented yet" OFF) if(NOT WIN32) # cause we are not on windows... - set(PD_ENABLE_DIRECTX9 OFF) + set(PD_ENABLE_DIRECTX9 OFF) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS") - set(PD_ENABLE_OPENGL2 OFF) - set(PD_ENABLE_OPENGL3 OFF) - set(PD_ENABLE_VULKAN OFF) - set(PD_ENABLE_CITRO3D ON) + set(PD_ENABLE_OPENGL2 OFF) + set(PD_ENABLE_OPENGL3 OFF) + set(PD_ENABLE_VULKAN OFF) + set(PD_ENABLE_CITRO3D ON) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch") + set(PD_ENABLE_OPENGL2 OFF) + set(PD_ENABLE_OPENGL3 ON) + set(PD_ENABLE_VULKAN OFF) + set(PD_ENABLE_CITRO3D OFF) endif() add_library(pd-system STATIC - ${CMAKE_CURRENT_SOURCE_DIR}/source/gl-helper.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl2.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/gl-helper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.cpp ) target_include_directories(pd-system - PUBLIC - $ - $ + PUBLIC + $ + $ ) target_compile_options(palladium - PUBLIC $<$: + PUBLIC $<$: -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/source=source -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/include=include > ) target_compile_definitions(pd-system - PUBLIC - $<$:PD_ENABLE_OPENGL2> - $<$:PD_ENABLE_OPENGL3> - $<$:PD_ENABLE_VULKAN> - $<$:PD_ENABLE_DIRECTX9> - $<$:PD_ENABLE_CITRO3D> + PUBLIC + $<$:PD_ENABLE_OPENGL2> + $<$:PD_ENABLE_OPENGL3> + $<$:PD_ENABLE_VULKAN> + $<$:PD_ENABLE_DIRECTX9> + $<$:PD_ENABLE_CITRO3D> ) # Palladium @@ -54,30 +59,34 @@ target_link_libraries(pd-system PUBLIC palladium::palladium) # glad (if we have any OpenGL version included) if(PD_ENABLE_OPENGL2 OR PD_ENABLE_OPENGL3) - target_link_libraries(pd-system - PUBLIC glad - ) + target_link_libraries(pd-system + PUBLIC glad + ) endif() # DirectX9 if(PD_ENABLE_DIRECTX9) - target_link_libraries(pd-system - PUBLIC - d3d9 - d3dcompiler - ) + target_link_libraries(pd-system + PUBLIC + d3d9 + d3dcompiler + ) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS") - target_link_libraries(pd-system - PUBLIC - pica::pica - citro3d - ctru - ) + target_link_libraries(pd-system + PUBLIC + pica::pica + citro3d + ctru + ) else() - target_link_libraries(pd-system - PUBLIC - spirv-helper - ) + if(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch") + target_include_directories(pd-system + PUBLIC $ENV{DEVKITPRO}/portlibs/switch/include + ) + endif() + target_link_libraries(pd-system + PUBLIC spirv-helper + ) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b0e7a20..d57dd75 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.22) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/targets.cmake) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/core) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/gfx) \ No newline at end of file +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/gfx) diff --git a/tests/assets/icon.jpg b/tests/assets/icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c3cc218a1ef8dfa5630cdaa87446b3ecf72a863 GIT binary patch literal 7918 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 I_mDGR07g1A{r~^~ literal 0 HcmV?d00001 diff --git a/tests/assets/icon48.png b/tests/assets/icon48.png new file mode 100644 index 0000000000000000000000000000000000000000..399ecb36328fca9ea14d791ebcb2569635399d42 GIT binary patch literal 1895 zcmV-t2blPYP)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy32;bRa{vG?BLDy{BLR4&KXw2B00(qQO+^Rl0~HAn6a=NRng9R> zy-7qtRA}DqSzky~dmR7lk8}PxX{C#5)tY49yhW5qkwmPwBFdK<5&Z+fhq{T-L-!#e zq#lYMO1eZ8h7pxn5G0X=4+d>nDbgypEH~S9&P`L#Hn(%m_deX~$>aW=bssLlJ}}t% zo_&A6^ZEY&ohgWj@C!qUUmO_%83Gvs83Gvs83MmF)N?N)kqEqAFY@y8uxQaD06;Jp zgx~LnLZN_4rGi?mhDM`7PEHOq8ckZ8@jMTY$0M%AFbwkZ^8o;3V`B)1!?M>ZE-prP zb~ZqB;C8zS0BzW?fyTzhh=?c<2$0ceBmm-vVHhecEv4GpT54%&A-mm9au5gvBNx@pcosKr-UQ3C0D#@QcPDh^o;`c8bLUQIG#Uf~0bILw z4WUpdVF=BI)9FMc5&-}d6cnTtjw+SvpD%MQG%zqAVcFT)Nkl|~AW%a?LyQ#|hN1TM zb_#_;5>K5zeOk2aTzEVliN0R1r;(8nA|iVA>XmHk8;wRWY$ZuN|7g(M+>EVTw<0?` z8+CPc*tKgHg25oBr>Eg^xeyMAQBhF=tyT+%!+|qr&Hw-|Uc89n;$qa-*Z;5-fWpE; zbar-PX68q-DijI;Kv`KCIyyT3^%8;S1qgzGJ9qBj{{8!s=Q?)m7<4*atOpzpM+{qw z#S%B3d7dYhWr^o`ibkV!^5n@F-Ip(4(tp9|=%}QC7>!1%si`5W)k-|i$0l(+0yQ-? z6p2KVZZtSJNDRZo=$g%DS;?IUZ{ED2zy7*Lj~+cDi^W1tr<44CzZkMH1U`TM95?1t zl}SMm=)#2yadrFp`hJ=K&+`-tg^1(0gujv1i4#?oxpBOA@7}og`uh5QeoRm*q19@^ z^E}*cHwFdfE!!Y1D4r;Yp_Jc>G zQS|imz~OM<-Me>q_UsuxeE5LY)>f=sxe{4fS@8)dmCBzcpw(*8*7guer3wodE<{dF z4zjYckd>7ssYG(n-QA6C+qOw$n>KC2#*G^#4rhoyg|f0T==FLmUAh#@mMxRD`Q+pzd_Et%UN44*hS1;N zk8j_;p{c1!_TZ;fDslYyaj-0ld-v`E02qeB_U+rn!4LDAmxyRIN?xy*0)YUrEGrIL za&i9r`IstXGMQ*%Vj}Gd#Ih{Cc=3YFW;4~-*NemDd`LW?R;zz>H~<{SVR(2LMMXt1 zu@?_6mn%l5)9GY~kl*je^z<}Vty+cL++3JUCT!WV1tTLP31=nc{Oo`K{ym;Nd4k5q zMwm<{tX;bnU%q@vxjDer(jJ%|zM0Re?%*9T|M@vgfjGSQ@l$V#w3cuM>Tvb&C0GOJZ!ri-fF+M&n|4htroaE-wqeroM^X8Nl z#AdVM>eZ_;@*_u%z+f<>Rf;PrD#YuC-3b z?(U}Bw{KHhTbroc-rg>W{d4Eek~_02vnNAWR~G>wo6SZ##c{{8!t642>%^!4jk@mw%5F(J!xL_{{5O=5^y zJ*U$tyY$A4)2B}Tfzr}as8lL+baddsg9mYQ$7nR7va%ADm6Zqt0x%d1P$(2>y6&zNCaA~7Asb)klno%bN}QEg+lQA{aC(yITQ*7hK7bPJUk3R5I{swDiu(v z{&_Q3P*8yU{CsG&T4=S}v?p0X5b*KiM@&vm{yW4e@Y`?euwcQ0^rqm #include const u32 DisplayTransferFlags = @@ -6,6 +6,22 @@ const u32 DisplayTransferFlags = GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)); +#elif defined(__SWITCH__) +#define GLFW_INCLUDE_NONE +#include +#include +#include +#include + +static void errorCallback(int errorCode, const char* description) { + printf("Glfw Error %d: %s\n", errorCode, description); +} + +#define PASSERT(x) \ + if (!x) { \ + printf("%s: %s", __PRETTY_FUNCTION__, #x); \ + exit(0); \ + } #else #include ////////////////////////// @@ -44,7 +60,32 @@ class App { public: App(Driver d = Driver::OpenGL3) : pDriver(d) { PD::Os::UseDriver(); -#ifndef __3DS__ +#if defined(__3DS__) + romfsInit(); + gfxInitDefault(); + consoleInit(GFX_BOTTOM, nullptr); + C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); + Top = + C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + Bottom = + C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(Top, GFX_TOP, GFX_LEFT, DisplayTransferFlags); + C3D_RenderTargetSetOutput(Bottom, GFX_BOTTOM, GFX_LEFT, + DisplayTransferFlags); + PD::Gfx::UseDriver(); +#elif defined(__SWITCH__) + PASSERT(glfwInit()); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + window = + glfwCreateWindow(1280, 720, "gfx_test (OpenGL3)", nullptr, nullptr); + PASSERT(window); + glfwMakeContextCurrent(window); + PASSERT(gladLoadGL()); + glfwSwapInterval(1); + PD::Gfx::UseDriver(); +#else glfwInit(); std::string winname = "gfx_test"; if (d == Driver::OpenGL2) { @@ -94,22 +135,10 @@ class App { } #endif glfwSwapInterval(1); -#else - gfxInitDefault(); - consoleInit(GFX_BOTTOM, nullptr); - C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); - Top = - C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - Bottom = - C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - C3D_RenderTargetSetOutput(Top, GFX_TOP, GFX_LEFT, DisplayTransferFlags); - C3D_RenderTargetSetOutput(Bottom, GFX_BOTTOM, GFX_LEFT, - DisplayTransferFlags); - PD::Gfx::UseDriver(); #endif PD::Gfx::Init(); -#ifdef __3DS__ - pTex = LoadTex("sdmc:/icon.png"); +#if defined(__3DS__) || defined(__SWITCH__) + pTex = LoadTex("romfs:/icon.png"); #else pTex = LoadTex("icon.png"); #endif @@ -124,19 +153,30 @@ class App { ~App() { PD::Gfx::DeleteTexture(pTex); PD::Gfx::Deinit(); -#ifndef __3DS__ - glfwDestroyWindow(window); +#if !defined(__3DS__) glfwTerminate(); #endif } void Run() { -#ifdef __3DS__ +#if defined(__3DS__) while (aptMainLoop()) { PD::Gfx::SetViewPort(400, 240); C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C3D_FrameDrawOn(Top); C3D_RenderTargetClear(Top, C3D_CLEAR_ALL, PD::Color(25, 25, 25, 25), 0); +#elif defined(__SWITCH__) + while (!glfwWindowShouldClose(window)) { + GLFWgamepadstate _gs; + if (glfwGetGamepadState(GLFW_JOYSTICK_1, &_gs)) { + if (_gs.buttons[GLFW_GAMEPAD_BUTTON_START] == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GLFW_TRUE); + } + } + PD::Gfx::SetViewPort(1280, 720); + glClearColor(0.1, 0.1, 0.1, 0.1); + glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, 1280, 720); #else while (!glfwWindowShouldClose(window)) { int ww, wh; @@ -159,7 +199,7 @@ class App { PD::Gfx::Reset(); PD::Gfx::Draw(pList); -#ifdef __3DS__ +#if defined(__3DS__) C3D_FrameEnd(0); #else glfwPollEvents(); @@ -178,7 +218,7 @@ class App { } private: -#ifdef __3DS__ +#if defined(__3DS__) C3D_RenderTarget* Top = nullptr; C3D_RenderTarget* Bottom = nullptr; #else @@ -194,6 +234,13 @@ class App { }; int main(int argc, char** argv) { +#if defined(__SWITCH__) + socketInitializeDefault(); + nxlinkStdio(); + romfsInit(); + printf("Starting Palladium GFX Tests...\n"); + glfwSetErrorCallback(errorCallback); +#endif Driver drv = Driver::OpenGL3; if (argc == 2) { if (std::string(argv[1]) == "gl2") { @@ -204,7 +251,8 @@ int main(int argc, char** argv) { drv = Driver::DirectX9; } } - App app(drv); - app.Run(); + App* app = new App(drv); + app->Run(); + delete app; return 0; } \ No newline at end of file diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 7bde67d..b7d6cb9 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,22 +1,25 @@ cmake_minimum_required(VERSION 3.22) if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libpicasso) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libpicasso) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch") + # SPIRV-Helper + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spirv-helper) else() - # GLAD - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glad) - # SPIRV-Helper - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spirv-helper) + # GLAD + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glad) + # SPIRV-Helper + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spirv-helper) endif() # STB add_library(stb INTERFACE) target_include_directories(stb INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/stb) -if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS") - # GLFW - set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "") - set(GLFW_BUILD_TESTS OFF CACHE BOOL "") - set(GLFW_BUILD_DOCS OFF CACHE BOOL "") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glfw) +if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch") + # GLFW + set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "") + set(GLFW_BUILD_TESTS OFF CACHE BOOL "") + set(GLFW_BUILD_DOCS OFF CACHE BOOL "") + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glfw) endif()