diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..b28167aa9d77 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "platform/switch"] + path = platform/switch + url = https://github.com/Homebrodot/platform-switch diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 03f0ef840d7f..a39b60b94e61 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -420,6 +420,14 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b } #endif +#ifdef HORIZON_ENABLED + if (!found) { + if (_load_resource_pack("romfs:/game.pck")) { + found = true; + } + } +#endif + if (!found) { // Try to load data pack at the location of the executable. // As mentioned above, we have two potential names to attempt. diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 366dcf767543..8d0d845920f0 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -89,10 +89,12 @@ GLuint RasterizerStorageGLES2::system_fbo = 0; #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf +#if defined IPHONE_ENABLED || defined ANDROID_ENABLED // enable extensions manually for android and ios #ifndef UWP_ENABLED #include // needed to load extensions #endif +#endif #ifdef IPHONE_ENABLED @@ -100,7 +102,7 @@ GLuint RasterizerStorageGLES2::system_fbo = 0; //void *glRenderbufferStorageMultisampleAPPLE; //void *glResolveMultisampleFramebufferAPPLE; #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE -#elif defined(ANDROID_ENABLED) +#elif defined ANDROID_ENABLED || defined HORIZON_ENABLED #include PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; @@ -6294,6 +6296,17 @@ void RasterizerStorageGLES2::initialize() { config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod"); #endif + // If the desktop build is using S3TC, and you export / run from the IDE for android, if the device supports + // S3TC it will crash trying to load these textures, as they are not exported in the APK. This is a simple way + // to prevent Android devices trying to load S3TC, by faking lack of hardware support. + + // Switch: this happens on Horizon too. +#ifndef TOOLS_ENABLED +#if defined ANDROID_ENABLED || defined HORIZON_ENABLED + config.s3tc_supported = false; +#endif +#endif + #ifdef GLES_OVER_GL config.use_rgba_2d_shadows = false; config.support_depth_texture = true; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 2938d2f953a9..ada941621398 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -8086,7 +8086,7 @@ void RasterizerStorageGLES3::initialize() { // If the desktop build is using S3TC, and you export / run from the IDE for android, if the device supports // S3TC it will crash trying to load these textures, as they are not exported in the APK. This is a simple way // to prevent Android devices trying to load S3TC, by faking lack of hardware support. -#if defined(ANDROID_ENABLED) || defined(IPHONE_ENABLED) +#if defined(ANDROID_ENABLED) || defined(IPHONE_ENABLED) || defined(HORIZON_ENABLED) config.s3tc_supported = false; #endif #endif diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 3e8112136254..b9ff9be255a3 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -413,6 +413,9 @@ String DirAccessUnix::read_link(String p_file) { p_file = fix_path(p_file); +#ifdef HORIZON_ENABLED + return p_file; +#else char buf[256]; memset(buf, 0, 256); ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf)); @@ -421,9 +424,13 @@ String DirAccessUnix::read_link(String p_file) { link.parse_utf8(buf, len); } return link; +#endif } Error DirAccessUnix::create_link(String p_source, String p_target) { +#ifdef HORIZON_ENABLED + return FAILED; +#else if (p_target.is_rel_path()) p_target = get_current_dir().plus_file(p_target); @@ -435,6 +442,7 @@ Error DirAccessUnix::create_link(String p_source, String p_target) { } else { return FAILED; } +#endif } uint64_t DirAccessUnix::get_space_left() { diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 529cd5078154..65d72a708682 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -40,7 +40,7 @@ #include -#if defined(UNIX_ENABLED) +#if defined(UNIX_ENABLED) || defined(HORIZON_ENABLED) #include #endif @@ -130,6 +130,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) { return last_error; } +#ifndef HORIZON_ENABLED // Set close on exec to avoid leaking it to subprocesses. int fd = fileno(f); @@ -142,7 +143,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) { fcntl(fd, F_SETFD, opts | FD_CLOEXEC); #endif } - +#endif last_error = OK; flags = p_mode_flags; return OK; @@ -279,7 +280,7 @@ bool FileAccessUnix::file_exists(const String &p_path) { return false; } -#ifdef UNIX_ENABLED +#if defined(UNIX_ENABLED) || defined(HORIZON_ENABLED) // See if we have access to the file if (access(filename.utf8().get_data(), F_OK)) { return false; diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index d4ff3d70aae3..69bec7cdf55a 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -30,7 +30,7 @@ #include "ip_unix.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(HORIZON_ENABLED) #include @@ -53,8 +53,10 @@ #ifdef __FreeBSD__ #include #endif +#ifndef HORIZON_ENABLED #include #endif +#endif #include #include #ifdef __FreeBSD__ @@ -210,7 +212,12 @@ void IP_Unix::get_local_interfaces(Map *r_interfaces) co #else // UNIX void IP_Unix::get_local_interfaces(Map *r_interfaces) const { +#ifdef HORIZON_ENABLED struct ifaddrs *ifAddrStruct = nullptr; + struct ifaddrs *ifa = nullptr; + // todo: nifm +#else // HORIZON_ENABLED + struct ifaddrs *ifAddrStruct = nullptr; struct ifaddrs *ifa = nullptr; int family; @@ -244,6 +251,7 @@ void IP_Unix::get_local_interfaces(Map *r_interfaces) co if (ifAddrStruct != nullptr) { freeifaddrs(ifAddrStruct); } +#endif // !HORIZON_ENABLED } #endif diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index c1d708a6b561..a3cfb4b3ae76 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -33,7 +33,7 @@ #include "core/io/ip.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(HORIZON_ENABLED) class IP_Unix : public IP { GDCLASS(IP_Unix, IP); diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index fa235d3e146e..3c0b6fee8752 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -31,7 +31,7 @@ #include "net_socket_posix.h" #ifndef UNIX_SOCKET_UNAVAILABLE -#if defined(UNIX_ENABLED) +#if defined(UNIX_ENABLED) || defined(HORIZON_ENABLED) #include #include @@ -50,7 +50,7 @@ #include #include -#ifdef JAVASCRIPT_ENABLED +#if defined(JAVASCRIPT_ENABLED) || defined(HORIZON_ENABLED) #include #endif @@ -276,11 +276,13 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St memcpy(&greq.imr_interface, if_ip.get_ipv4(), 4); ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq)); } else { +#ifndef HORIZON_ENABLED struct ipv6_mreq greq; int sock_opt = p_add ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP; memcpy(&greq.ipv6mr_multiaddr, p_ip.get_ipv6(), 16); greq.ipv6mr_interface = if_v6id; ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq)); +#endif } ERR_FAIL_COND_V(ret != 0, FAILED); diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index 81b3ddb9c406..cf7451d02ed5 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -200,6 +200,11 @@ if env["builtin_bullet"]: thirdparty_sources = [thirdparty_dir + file for file in bullet2_src] env_bullet.Prepend(CPPPATH=[thirdparty_dir]) + # Treat Bullet headers as system headers to avoid raising warnings. Not supported on MSVC. (TODO SWITCH: devkitA64 issue prevents this from working) + if not env.msvc and env["platform"] != "switch": + env_bullet.Append(CPPFLAGS=["-isystem", Dir(thirdparty_dir).path]) + else: + env_bullet.Prepend(CPPPATH=[thirdparty_dir]) env_bullet.Append(CPPDEFINES=["BT_USE_OLD_DAMPING_METHOD", "BT_THREADSAFE"]) diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index c0573d21b5d7..198e71e1c88e 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -35,7 +35,7 @@ extern "C" { #endif -#if defined(_WIN32) || defined(__ANDROID__) +#if defined(_WIN32) || defined(__ANDROID__) || defined(__SWITCH__) #define GDCALLINGCONV #define GDAPI GDCALLINGCONV #elif defined(__APPLE__) @@ -47,7 +47,7 @@ extern "C" { #define GDCALLINGCONV __attribute__((sysv_abi)) #define GDAPI GDCALLINGCONV #endif -#else // !_WIN32 && !__APPLE__ +#else // !_WIN32 && !__APPLE__ && !__SWITCH__ #define GDCALLINGCONV __attribute__((sysv_abi)) #define GDAPI GDCALLINGCONV #endif diff --git a/platform/switch b/platform/switch new file mode 160000 index 000000000000..31761d94814c --- /dev/null +++ b/platform/switch @@ -0,0 +1 @@ +Subproject commit 31761d94814c1e35efda11fbc7bbb5d59b6fbcbf diff --git a/thirdparty/enet/enet/godot.h b/thirdparty/enet/enet/godot.h index b8bea6692a27..f11b9ce2d33d 100644 --- a/thirdparty/enet/enet/godot.h +++ b/thirdparty/enet/enet/godot.h @@ -39,7 +39,7 @@ #include #include #endif -#ifdef UNIX_ENABLED +#if defined(UNIX_ENABLED) || defined(HORIZON_ENABLED) #include #endif diff --git a/thirdparty/libnx/nacp.h b/thirdparty/libnx/nacp.h new file mode 100644 index 000000000000..98364f2336d6 --- /dev/null +++ b/thirdparty/libnx/nacp.h @@ -0,0 +1,95 @@ +/** +* @file nacp.h +* @brief Control.nacp structure / related code for nacp. +* @copyright libnx Authors +*/ + +#pragma once + +#include "thirdparty/libnx/types.h" + +/// Language entry. These strings are UTF-8. +typedef struct { + char name[0x200]; + char author[0x100]; +} NacpLanguageEntry; + +/// ApplicationNeighborDetectionGroupConfiguration +typedef struct { + u64 group_id; ///< GroupId + u8 key[0x10]; +} NacpApplicationNeighborDetectionGroupConfiguration; + +/// NeighborDetectionClientConfiguration +typedef struct { + NacpApplicationNeighborDetectionGroupConfiguration send_group_configuration; ///< SendGroupConfiguration + NacpApplicationNeighborDetectionGroupConfiguration receivable_group_configurations[0x10]; ///< ReceivableGroupConfigurations +} NacpNeighborDetectionClientConfiguration; + +/// ApplicationJitConfiguration +typedef struct { + u64 flags; ///< Flags + u64 memory_size; ///< MemorySize +} NacpApplicationJitConfiguration; + +/// ns ApplicationControlProperty +typedef struct { + NacpLanguageEntry lang[16]; ///< \ref NacpLanguageEntry + u8 isbn[0x25]; ///< Isbn + u8 startup_user_account; ///< StartupUserAccount + u8 user_account_switch_lock; ///< UserAccountSwitchLock + u8 add_on_content_registration_type; ///< AddOnContentRegistrationType + u32 attribute_flag; ///< AttributeFlag + u32 supported_language_flag; ///< SupportedLanguageFlag + u32 parental_control_flag; ///< ParentalControlFlag + u8 screenshot; ///< Screenshot + u8 video_capture; ///< VideoCapture + u8 data_loss_confirmation; ///< DataLossConfirmation + u8 play_log_policy; ///< PlayLogPolicy + u64 presence_group_id; ///< PresenceGroupId + s8 rating_age[0x20]; ///< RatingAge + char display_version[0x10]; ///< DisplayVersion + u64 add_on_content_base_id; ///< AddOnContentBaseId + u64 save_data_owner_id; ///< SaveDataOwnerId + u64 user_account_save_data_size; ///< UserAccountSaveDataSize + u64 user_account_save_data_journal_size; ///< UserAccountSaveDataJournalSize + u64 device_save_data_size; ///< DeviceSaveDataSize + u64 device_save_data_journal_size; ///< DeviceSaveDataJournalSize + u64 bcat_delivery_cache_storage_size; ///< BcatDeliveryCacheStorageSize + u64 application_error_code_category; ///< ApplicationErrorCodeCategory + u64 local_communication_id[0x8]; ///< LocalCommunicationId + u8 logo_type; ///< LogoType + u8 logo_handling; ///< LogoHandling + u8 runtime_add_on_content_install; ///< RuntimeAddOnContentInstall + u8 runtime_parameter_delivery; ///< RuntimeParameterDelivery + u8 reserved_x30f4[0x2]; ///< Reserved + u8 crash_report; ///< CrashReport + u8 hdcp; ///< Hdcp + u64 pseudo_device_id_seed; ///< SeedForPseudoDeviceId + char bcat_passphrase[0x41]; ///< BcatPassphrase + u8 startup_user_account_option; ///< StartupUserAccountOption + u8 reserved_for_user_account_save_data_operation[0x6]; ///< ReservedForUserAccountSaveDataOperation + u64 user_account_save_data_size_max; ///< UserAccountSaveDataSizeMax + u64 user_account_save_data_journal_size_max; ///< UserAccountSaveDataJournalSizeMax + u64 device_save_data_size_max; ///< DeviceSaveDataSizeMax + u64 device_save_data_journal_size_max; ///< DeviceSaveDataJournalSizeMax + u64 temporary_storage_size; ///< TemporaryStorageSize + u64 cache_storage_size; ///< CacheStorageSize + u64 cache_storage_journal_size; ///< CacheStorageJournalSize + u64 cache_storage_data_and_journal_size_max; ///< CacheStorageDataAndJournalSizeMax + u16 cache_storage_index_max; ///< CacheStorageIndexMax + u8 reserved_x318a[0x6]; ///< Reserved + u64 play_log_queryable_application_id[0x10]; ///< PlayLogQueryableApplicationId + u8 play_log_query_capability; ///< PlayLogQueryCapability + u8 repair_flag; ///< RepairFlag + u8 program_index; ///< ProgramIndex + u8 required_network_service_license_on_launch; ///< RequiredNetworkServiceLicenseOnLaunchFlag + u32 reserved_x3214; ///< Reserved + NacpNeighborDetectionClientConfiguration neighbor_detection_client_configuration; ///< NeighborDetectionClientConfiguration + NacpApplicationJitConfiguration jit_configuration; ///< JitConfiguration + u8 reserved_x33c0[0xc40]; ///< Reserved +} NacpStruct; + +/// Get the NacpLanguageEntry from the input nacp corresponding to the current system language (this may fallback to other languages when needed). Output langentry is NULL if none found / content of entry is empty. +/// If you're using ns you may want to use \ref nsGetApplicationDesiredLanguage instead. +Result nacpGetLanguageEntry(NacpStruct* nacp, NacpLanguageEntry** langentry); diff --git a/thirdparty/libnx/nro.h b/thirdparty/libnx/nro.h new file mode 100644 index 000000000000..64bac0e82ea2 --- /dev/null +++ b/thirdparty/libnx/nro.h @@ -0,0 +1,55 @@ +/** +* @file nro.h +* @brief NRO headers. +* @copyright libnx Authors +*/ + +#pragma once + +#include "thirdparty/libnx/types.h" + +#define NROHEADER_MAGIC 0x304f524e + +#define NROASSETHEADER_MAGIC 0x54455341 +#define NROASSETHEADER_VERSION 0 + +/// Entry for each segment in the codebin. +typedef struct { + u32 file_off; + u32 size; +} NroSegment; + +/// Offset 0x0 in the NRO. +typedef struct { + u32 unused; + u32 mod_offset; + u8 padding[8]; +} NroStart; + +/// This follows NroStart, the actual nro-header. +typedef struct { + u32 magic; + u32 unk1; + u32 size; + u32 unk2; + NroSegment segments[3]; + u32 bss_size; + u32 unk3; + u8 build_id[0x20]; + u8 padding[0x20]; +} NroHeader; + +/// Custom asset section. +typedef struct { + u64 offset; + u64 size; +} NroAssetSection; + +/// Custom asset header. +typedef struct { + u32 magic; + u32 version; + NroAssetSection icon; + NroAssetSection nacp; + NroAssetSection romfs; +} NroAssetHeader; diff --git a/thirdparty/libnx/types.h b/thirdparty/libnx/types.h new file mode 100644 index 000000000000..2e7b30ee2d68 --- /dev/null +++ b/thirdparty/libnx/types.h @@ -0,0 +1,92 @@ +/** +* @file switch/types.h +* @brief Various system types. +* @copyright libnx Authors +*/ +#pragma once + +#include +#include +#include +#include + +#ifndef SSIZE_MAX +#ifdef SIZE_MAX +#define SSIZE_MAX ((SIZE_MAX) >> 1) +#endif // SIZE_MAX +#endif // SSIZE_MAX + +typedef uint8_t u8; ///< 8-bit unsigned integer. +typedef uint16_t u16; ///< 16-bit unsigned integer. +typedef uint32_t u32; ///< 32-bit unsigned integer. +typedef uint64_t u64; ///< 64-bit unsigned integer. + +typedef int8_t s8; ///< 8-bit signed integer. +typedef int16_t s16; ///< 16-bit signed integer. +typedef int32_t s32; ///< 32-bit signed integer. +typedef int64_t s64; ///< 64-bit signed integer. + +typedef volatile u8 vu8; ///< 8-bit volatile unsigned integer. +typedef volatile u16 vu16; ///< 16-bit volatile unsigned integer. +typedef volatile u32 vu32; ///< 32-bit volatile unsigned integer. +typedef volatile u64 vu64; ///< 64-bit volatile unsigned integer. + +typedef volatile s8 vs8; ///< 8-bit volatile signed integer. +typedef volatile s16 vs16; ///< 16-bit volatile signed integer. +typedef volatile s32 vs32; ///< 32-bit volatile signed integer. +typedef volatile s64 vs64; ///< 64-bit volatile signed integer. + +typedef u32 Handle; ///< Kernel object handle. +typedef u32 Result; ///< Function error code result type. +typedef void (*ThreadFunc)(void *); ///< Thread entrypoint function. +typedef void (*VoidFn)(void); ///< Function without arguments nor return value. + +typedef struct { u8 uuid[0x10]; } Uuid; ///< Unique identifier. + +typedef struct { float value[3]; } UtilFloat3; ///< 3 floats. + +/// Creates a bitmask from a bit number. +#ifndef BIT +#define BIT(n) (1U<<(n)) +#endif // BIT + +#ifndef BITL +#define BITL(n) (1UL<<(n)) +#endif // BITL + +/// Packs a struct so that it won't include padding bytes. +#ifndef PACKED +#define PACKED __attribute__((packed)) +#endif // PACKED + +/// Marks a function as not returning, for the purposes of compiler optimization. +#ifndef NORETURN +#define NORETURN __attribute__((noreturn)) +#endif // NORETURN + +/// Performs a dummy operation on the specified argument in order to silence compiler warnings about unused arguments. +#ifndef IGNORE_ARG +#define IGNORE_ARG(x) (void)(x) +#endif // IGNORE_ARG + +/// Flags a function as deprecated. +#ifndef DEPRECATED +#ifndef LIBNX_NO_DEPRECATION +#define DEPRECATED __attribute__ ((deprecated)) +#else // LIBNX_NO_DEPRECATION +#define DEPRECATED +#endif // LIBNX_NO_DEPRECATION +#endif // DEPRECATED + +/// Flags a function as (always) inline. +#define NX_INLINE __attribute__((always_inline)) static inline + +/// Flags a function as constexpr in C++14 and above; or as (always) inline otherwise. +#if __cplusplus >= 201402L +#define NX_CONSTEXPR NX_INLINE constexpr +#else // __cplusplus >= 201402 +#define NX_CONSTEXPR NX_INLINE +#endif // __cplusplus >= 201402 + +/// Invalid handle. +#define INVALID_HANDLE ((Handle) 0) diff --git a/thirdparty/miniupnpc/src/minissdpc.c b/thirdparty/miniupnpc/src/minissdpc.c index edebb1600a03..0c1c5ea66cd0 100644 --- a/thirdparty/miniupnpc/src/minissdpc.c +++ b/thirdparty/miniupnpc/src/minissdpc.c @@ -58,7 +58,16 @@ struct sockaddr_un { #include #include #include +#if !defined(__SWITCH__) #include +#endif +#if defined(__SWITCH__) +#define UNIX_PATH_LEN 108 +struct sockaddr_un { + uint16_t sun_family; + char sun_path[UNIX_PATH_LEN]; +}; +#endif #include #include #include