diff --git a/CMakeLists.txt b/CMakeLists.txt index 330b411b7..0cf33b754 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,9 @@ if(WIN32) elseif(APPLE) # OSX set(TARGET_OS "osx") +elseif(NINTENDO_SWITCH) + # Switch + set(TARGET_OS "nswitch") elseif(UNIX) # Generic *nix; assume Linux set(TARGET_OS "linux") @@ -184,19 +187,31 @@ set(LIBS ) # SDL2 find_package(SDL2 REQUIRED) +if(NINTENDO_SWITCH) + if(NOT SDL2_LIBRARY OR NOT SDL2_INCLUDE_DIR) + # sometimes FindSDL2 just wants us to suffer and does not set these + set(SDL2_LIBRARY "SDL2") + set(SDL2_INCLUDE_DIR "${DEVKITPRO}/portlibs/switch/include/SDL2") + endif() +endif() include_directories(SYSTEM "${SDL2_INCLUDE_DIR}") list(APPEND LIBS "${SDL2_LIBRARY}") # ZLib find_package(ZLIB REQUIRED) +if(ZLIB_INCLUDE_DIR) + include_directories(SYSTEM "${ZLIB_INCLUDE_DIR}") +endif() list(APPEND LIBS "${ZLIB_LIBRARY}") # GL if(NOT GL_LIBRARY) if(WIN32) - set(GL_LIBRARY "opengl32") + set(GL_LIBRARY opengl32) + elseif(NINTENDO_SWITCH) + set(GL_LIBRARY EGL glapi drm_nouveau) else() - set(GL_LIBRARY "GL") + set(GL_LIBRARY GL) endif() endif() list(APPEND LIBS "${GL_LIBRARY}") @@ -205,6 +220,8 @@ list(APPEND LIBS "${GL_LIBRARY}") if(NOT EXTRA_LIBRARIES) if(WIN32) set(EXTRA_LIBRARIES dbghelp -static-libstdc++) + elseif(NINTENDO_SWITCH) + set(EXTRA_LIBRARIES stdc++ pthread) else() set(EXTRA_LIBRARIES stdc++ m dl) endif() @@ -296,10 +313,21 @@ add_custom_target(pd_headers ALL DEPENDS ${JSON_HEADERS}) # Game target +set(BIN_NAME "pd${BIN_REGION}.${TARGET_ARCH}") add_executable(pd ${SRC}) add_dependencies(pd pd_headers) target_link_libraries(pd ${LIBS}) -set_target_properties(pd PROPERTIES OUTPUT_NAME "pd${BIN_REGION}.${TARGET_ARCH}") +set_target_properties(pd PROPERTIES OUTPUT_NAME "${BIN_NAME}") if(WIN32) set_target_properties(pd PROPERTIES WIN32_EXECUTABLE TRUE) endif() + +# Additional commands for specific platforms. + +if(NINTENDO_SWITCH) + add_custom_command(TARGET pd POST_BUILD + COMMAND nacptool --create "Perfect Dark" "fgsfds & contributors" "${VERSION_ROMID}/${VERSION_BRANCH}/${VERSION_HASH}" "${BIN_NAME}.nacp" + COMMAND aarch64-none-elf-strip -o ${CMAKE_BINARY_DIR}/${BIN_NAME}.stripped.elf ${CMAKE_BINARY_DIR}/${BIN_NAME}.elf + COMMAND elf2nro ${CMAKE_BINARY_DIR}/${BIN_NAME}.stripped.elf ${CMAKE_BINARY_DIR}/${BIN_NAME}.nro --icon=${CMAKE_SOURCE_DIR}/dist/nswitch/icon.jpg --nacp=${BIN_NAME}.nacp + ) +endif() diff --git a/README.md b/README.md index 8e508b465..42a3bd8d6 100644 --- a/README.md +++ b/README.md @@ -111,8 +111,8 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows: 5. Run `cmake -G"Unix Makefiles" -Bbuild .`. * Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.\ 6. Run `cmake --build build -j4 -- -O`. -6. The resulting executable will be at `build/pd.x86_64.exe` (or at `build/pd.i686.exe` if building for i686). -7. If you don't know where you downloaded the source to, you can run `explorer .` to open the current directory. +7. The resulting executable will be at `build/pd.x86_64.exe` (or at `build/pd.i686.exe` if building for i686). +8. If you don't know where you downloaded the source to, you can run `explorer .` to open the current directory. ### Linux @@ -125,7 +125,31 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows: * Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively. * Add ` -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32` at the end of the command if you want to crosscompile from x86_64 to x86. 4. Run `cmake --build build -j4`. -4. The resulting executable will be at `build/pd.` (for example `build/pd.x86_64`). +5. The resulting executable will be at `build/pd.` (for example `build/pd.x86_64`). + +### Nintendo Switch + +1. Set up the [devkitA64 environment](https://devkitpro.org/wiki/Getting_Started). + * On Windows you can do it under MSYS2 or WSL, usually MSYS2 is recommended. + * If using MSYS2, make sure to use the **MSYS2** shell, **not** MINGW32 or MINGW64. +2. Install host dependencies: + * On MSYS2: `pacman -Syuu && pacman -S git make cmake python3` + * On Linux: use your package manager as normal to install the above dependencies. +3. Install Switch toolchain and dependencies: + * ``` + dkp-pacman -Syuu + dkp-pacman -S devkitA64 switch-libnx switch-zlib switch-sdl2 switch-cmake dkp-toolchain-vars + ``` + * If in MSYS2 or `dkp-pacman` doesn't work, replace it with just `pacman`. +4. Ensure devkitA64 environment variables are set: + * `source /opt/devkitpro/switchvars.sh` + * If your `$DEVKITPRO` path is different, substitute that instead or set the variables manually. +5. Configure: + * `aarch64-none-elf-cmake -G"Unix Makefiles" -Bbuild .` + * Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively. +6. Build: + * `make -C build -j4` +7. The resulting executable will be at `build/pd.arm64.nro`. ### Notes diff --git a/dist/nswitch/gamecontrollerdb.txt b/dist/nswitch/gamecontrollerdb.txt new file mode 100644 index 000000000..7dcba6b02 --- /dev/null +++ b/dist/nswitch/gamecontrollerdb.txt @@ -0,0 +1,2 @@ +# Switch (SDL_GetPlatform is not changed in switch-sdl2) +000038f853776974636820436f6e7400,Switch Controller,a:b0,b:b1,back:b11,dpdown:b15,dpleft:b12,dpright:b14,dpup:b13,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Unknown (see SDL_platform.h), diff --git a/dist/nswitch/icon.jpg b/dist/nswitch/icon.jpg new file mode 100644 index 000000000..2adc6f6c8 Binary files /dev/null and b/dist/nswitch/icon.jpg differ diff --git a/port/fast3d/glad/glad.c b/port/fast3d/glad/glad.c index 08d76207d..2c4624e31 100644 --- a/port/fast3d/glad/glad.c +++ b/port/fast3d/glad/glad.c @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.36 on Thu Oct 5 16:07:54 2023. + OpenGL loader generated by glad 0.1.36 on Wed Nov 13 09:35:45 2024. Language/Generator: C/C++ Specification: gl @@ -17,15 +17,15 @@ GL_EXT_gpu_shader4, GL_KHR_debug, GL_NV_depth_clamp - Loader: True + Loader: False Local files: True Omit khrplatform: False Reproducible: False Commandline: - --profile="compatibility" --api="gl=3.2" --generator="c" --spec="gl" --local-files --extensions="GL_ARB_depth_clamp,GL_ARB_framebuffer_object,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_vertex_array_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_gpu_shader4,GL_KHR_debug,GL_NV_depth_clamp" + --profile="compatibility" --api="gl=3.2" --generator="c" --spec="gl" --no-loader --local-files --extensions="GL_ARB_depth_clamp,GL_ARB_framebuffer_object,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_vertex_array_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_gpu_shader4,GL_KHR_debug,GL_NV_depth_clamp" Online: - https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.2&extensions=GL_ARB_depth_clamp&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_texture_mirror_clamp_to_edge&extensions=GL_ARB_vertex_array_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_EXT_gpu_shader4&extensions=GL_KHR_debug&extensions=GL_NV_depth_clamp + https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&api=gl%3D3.2&extensions=GL_ARB_depth_clamp&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_texture_mirror_clamp_to_edge&extensions=GL_ARB_vertex_array_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_EXT_gpu_shader4&extensions=GL_KHR_debug&extensions=GL_NV_depth_clamp */ #include @@ -33,138 +33,6 @@ #include #include "glad.h" -static void* get_proc(const char *namez); - -#if defined(_WIN32) || defined(__CYGWIN__) -#ifndef _WINDOWS_ -#undef APIENTRY -#endif -#include -static HMODULE libGL; - -typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*); -static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; - -#ifdef _MSC_VER -#ifdef __has_include - #if __has_include() - #define HAVE_WINAPIFAMILY 1 - #endif -#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ - #define HAVE_WINAPIFAMILY 1 -#endif -#endif - -#ifdef HAVE_WINAPIFAMILY - #include - #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) - #define IS_UWP 1 - #endif -#endif - -static -int open_gl(void) { -#ifndef IS_UWP - libGL = LoadLibraryW(L"opengl32.dll"); - if(libGL != NULL) { - void (* tmp)(void); - tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); - gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; - return gladGetProcAddressPtr != NULL; - } -#endif - - return 0; -} - -static -void close_gl(void) { - if(libGL != NULL) { - FreeLibrary((HMODULE) libGL); - libGL = NULL; - } -} -#else -#include -static void* libGL; - -#if !defined(__APPLE__) && !defined(__HAIKU__) -typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*); -static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; -#endif - -static -int open_gl(void) { -#ifdef __APPLE__ - static const char *NAMES[] = { - "../Frameworks/OpenGL.framework/OpenGL", - "/Library/Frameworks/OpenGL.framework/OpenGL", - "/System/Library/Frameworks/OpenGL.framework/OpenGL", - "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" - }; -#else - static const char *NAMES[] = {"libGL.so.1", "libGL.so"}; -#endif - - unsigned int index = 0; - for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) { - libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL); - - if(libGL != NULL) { -#if defined(__APPLE__) || defined(__HAIKU__) - return 1; -#else - gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL, - "glXGetProcAddressARB"); - return gladGetProcAddressPtr != NULL; -#endif - } - } - - return 0; -} - -static -void close_gl(void) { - if(libGL != NULL) { - dlclose(libGL); - libGL = NULL; - } -} -#endif - -static -void* get_proc(const char *namez) { - void* result = NULL; - if(libGL == NULL) return NULL; - -#if !defined(__APPLE__) && !defined(__HAIKU__) - if(gladGetProcAddressPtr != NULL) { - result = gladGetProcAddressPtr(namez); - } -#endif - if(result == NULL) { -#if defined(_WIN32) || defined(__CYGWIN__) - result = (void*)GetProcAddress((HMODULE) libGL, namez); -#else - result = dlsym(libGL, namez); -#endif - } - - return result; -} - -int gladLoadGL(void) { - int status = 0; - - if(open_gl()) { - status = gladLoadGLLoader(&get_proc); - close_gl(); - } - - return status; -} - struct gladGLversionStruct GLVersion = { 0, 0 }; #if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) @@ -185,7 +53,7 @@ static int get_exts(void) { exts = (const char *)glGetString(GL_EXTENSIONS); #ifdef _GLAD_IS_SOME_NEW_VERSION } else { - unsigned int index; + int index; num_exts_i = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i); @@ -197,7 +65,7 @@ static int get_exts(void) { return 0; } - for(index = 0; index < (unsigned)num_exts_i; index++) { + for(index = 0; index < num_exts_i; index++) { const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index); size_t len = strlen(gl_str_tmp); diff --git a/port/fast3d/glad/glad.h b/port/fast3d/glad/glad.h index e096abac2..e0b55c5c2 100644 --- a/port/fast3d/glad/glad.h +++ b/port/fast3d/glad/glad.h @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.36 on Thu Oct 5 16:07:54 2023. + OpenGL loader generated by glad 0.1.36 on Wed Nov 13 09:35:45 2024. Language/Generator: C/C++ Specification: gl @@ -17,15 +17,15 @@ GL_EXT_gpu_shader4, GL_KHR_debug, GL_NV_depth_clamp - Loader: True + Loader: False Local files: True Omit khrplatform: False Reproducible: False Commandline: - --profile="compatibility" --api="gl=3.2" --generator="c" --spec="gl" --local-files --extensions="GL_ARB_depth_clamp,GL_ARB_framebuffer_object,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_vertex_array_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_gpu_shader4,GL_KHR_debug,GL_NV_depth_clamp" + --profile="compatibility" --api="gl=3.2" --generator="c" --spec="gl" --no-loader --local-files --extensions="GL_ARB_depth_clamp,GL_ARB_framebuffer_object,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_vertex_array_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_gpu_shader4,GL_KHR_debug,GL_NV_depth_clamp" Online: - https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.2&extensions=GL_ARB_depth_clamp&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_texture_mirror_clamp_to_edge&extensions=GL_ARB_vertex_array_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_EXT_gpu_shader4&extensions=GL_KHR_debug&extensions=GL_NV_depth_clamp + https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&api=gl%3D3.2&extensions=GL_ARB_depth_clamp&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_texture_mirror_clamp_to_edge&extensions=GL_ARB_vertex_array_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_EXT_gpu_shader4&extensions=GL_KHR_debug&extensions=GL_NV_depth_clamp */ @@ -90,9 +90,6 @@ typedef void* (* GLADloadproc)(const char *name); #endif GLAPI struct gladGLversionStruct GLVersion; - -GLAPI int gladLoadGL(void); - GLAPI int gladLoadGLLoader(GLADloadproc); #include "khrplatform.h" diff --git a/port/include/fs.h b/port/include/fs.h index 24858460d..bfb21b3ec 100644 --- a/port/include/fs.h +++ b/port/include/fs.h @@ -19,7 +19,7 @@ s32 fsFileSize(const char *name); FILE *fsFileOpenWrite(const char *name); FILE *fsFileOpenRead(const char *name); -void fsFileClose(FILE *f); +void fsFileFree(FILE *f); const char *fsGetModDir(void); diff --git a/port/src/config.c b/port/src/config.c index b37c2e955..6be6f0d9f 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -228,7 +228,7 @@ s32 configSave(const char *fname) configSaveEntry(cfg, f); } - fsFileClose(f); + fsFileFree(f); return 1; } @@ -282,7 +282,7 @@ s32 configLoad(const char *fname) } } - fsFileClose(f); + fsFileFree(f); return 1; } diff --git a/port/src/fs.c b/port/src/fs.c index bb863af09..cbcec8782 100644 --- a/port/src/fs.c +++ b/port/src/fs.c @@ -276,7 +276,7 @@ FILE *fsFileOpenRead(const char *name) return fopen(fsFullPath(name), "rb"); } -void fsFileClose(FILE *f) +void fsFileFree(FILE *f) { fclose(f); } diff --git a/port/src/libultra.c b/port/src/libultra.c index 708f97bd5..465a1e62c 100644 --- a/port/src/libultra.c +++ b/port/src/libultra.c @@ -277,7 +277,7 @@ static inline void osEeepromLoad(const char *fname) FILE *fp = fsFileOpenRead(fname); if (fp) { fread(eeprom, 1, EEPROM_SIZE, fp); - fsFileClose(fp); + fsFileFree(fp); } else { sysLogPrintf(LOG_NOTE, "could not read EEPROM from `%s`: %s", fsFullPath(fname), strerror(errno)); } @@ -289,7 +289,7 @@ static inline void osEeepromSave(const char *fname) FILE* fp = fsFileOpenWrite(fname); if (fp) { fwrite(eeprom, 1, EEPROM_SIZE, fp); - fsFileClose(fp); + fsFileFree(fp); } else { sysLogPrintf(LOG_ERROR, "could not save EEPROM to `%s`: %s", fsFullPath(fname), strerror(errno)); } diff --git a/port/src/video.c b/port/src/video.c index 63be72f54..52eafc228 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -12,16 +12,28 @@ #include "../fast3d/gfx_sdl.h" #include "../fast3d/gfx_opengl.h" +#ifdef PLATFORM_NSWITCH +#define DEFAULT_VID_WIDTH 1280 +#define DEFAULT_VID_HEIGHT 720 +#define DEFAULT_VID_FULLSCREEN true +#define DEFAULT_VID_FULLSCREEN_EXCLUSIVE true +#else +#define DEFAULT_VID_WIDTH 640 +#define DEFAULT_VID_HEIGHT 480 +#define DEFAULT_VID_FULLSCREEN false +#define DEFAULT_VID_FULLSCREEN_EXCLUSIVE false +#endif + static struct GfxWindowManagerAPI *wmAPI; static struct GfxRenderingAPI *renderingAPI; static bool initDone = false; -static s32 vidWidth = 640; -static s32 vidHeight = 480; +static s32 vidWidth = DEFAULT_VID_WIDTH; +static s32 vidHeight = DEFAULT_VID_HEIGHT; static s32 vidFramebuffers = true; -static s32 vidFullscreen = false; -static s32 vidFullscreenExclusive = false; +static s32 vidFullscreen = DEFAULT_VID_FULLSCREEN; +static s32 vidFullscreenExclusive = DEFAULT_VID_FULLSCREEN_EXCLUSIVE; static s32 vidMaximize = false; static s32 vidAllowHiDpi = false; static s32 vidVsync = 1; diff --git a/src/include/platform.h b/src/include/platform.h index 949ff31a6..176fd83db 100644 --- a/src/include/platform.h +++ b/src/include/platform.h @@ -4,6 +4,9 @@ // detect OS #if defined(_WIN32) #define PLATFORM_WIN32 1 +#elif defined(__SWITCH__) + #define PLATFORM_POSIX 1 + #define PLATFORM_NSWITCH 1 #elif defined(__linux__) #define PLATFORM_POSIX 1 #define PLATFORM_LINUX 1