Merge pull request #8 from flashshare/pandemonium-homebrodot

Pandemonium homebrodot
This commit is contained in:
Nguyen Truong An 2025-02-28 14:00:05 +01:00 committed by GitHub
commit 710d617e99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1039 additions and 333 deletions

View File

@ -17,7 +17,10 @@ jobs:
name: Template (target=release, tools=no)
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive # Fetch all submodules
- name: Set up Java 17
uses: actions/setup-java@v4

View File

@ -18,7 +18,10 @@ jobs:
name: Template (target=release, tools=no)
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive # Fetch all submodules
- name: Set up Emscripten latest
uses: mymindstorm/setup-emsdk@v14

40
.github/workflows/switch_builds.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: 🔄 Switch Builds
on: [push, pull_request]
# Global Cache Settings
env:
GODOT_BASE_BRANCH: 3.5
SCONSFLAGS: verbose=no warnings=no werror=no debug_symbols=no use_rtti=True disable_gles3=False
jobs:
switch-template:
runs-on: ubuntu-latest
container: devkitpro/devkita64
name: Template (target=release, tools=no)
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive # Fetch all submodules
- name: Restore Pandemonium build cache
uses: ./.github/actions/godot-cache-restore
continue-on-error: true
- name: Install scons from pip
run: |
sudo apt-get update
sudo apt-get -y install python3-pip
sudo python3 -m pip install scons
- name: Compilation
run: |
scons -j2 verbose=yes warnings=all werror=no platform=switch target=release tools=no
- uses: actions/upload-artifact@v4
with:
name: ${{ github.job }}
path: bin/*
retention-days: 14

View File

@ -14,19 +14,14 @@ concurrency:
jobs:
vita-template:
runs-on: "ubuntu-20.04"
runs-on: "ubuntu-24.04"
name: Template (target=release, tools=no)
steps:
- uses: actions/checkout@v4
# Azure repositories are not reliable, we need to prevent azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories
run: |
sudo rm -f /etc/apt/sources.list.d/*
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
sudo apt-get update
sudo apt-get install gcc-multilib
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive # Fetch all submodules
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
@ -64,4 +59,4 @@ jobs:
continue-on-error: true
- name: Upload artifact
uses: ./.github/actions/upload-artifact
uses: ./.github/actions/upload-artifact

View File

@ -34,7 +34,10 @@ jobs:
tools: false
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive # Fetch all submodules
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "platform/switch"]
path = platform/switch
url = https://github.com/Homebrodot/platform-switch

View File

@ -399,6 +399,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 // HORIZON_ENABLED
if (!found) {
String crl = OS::get_singleton()->get_custom_platform_resource_pack_location();

View File

@ -92,6 +92,11 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
// enable extensions manually for android and ios
#if defined IPHONE_ENABLED || defined ANDROID_ENABLED
#include <dlfcn.h> // needed to load extensions
#endif // IPHONE_ENABLED || ANDROID_ENABLED
#ifdef IPHONE_ENABLED
#include <dlfcn.h> // needed to load extensions
@ -101,9 +106,7 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
//void *glResolveMultisampleFramebufferAPPLE;
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE
#elif defined(ANDROID_ENABLED)
#include <dlfcn.h> // needed to load extensions
#elif defined(ANDROID_ENABLED) || defined(HORIZON_ENABLED)
#include <GLES2/gl2ext.h>
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
@ -6354,7 +6357,7 @@ void RasterizerStorageGLES2::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) || defined(VITA_ENABLED) || defined(S3TC_NOT_SUPPORTED)
#if defined(ANDROID_ENABLED) || defined(IPHONE_ENABLED) || defined(VITA_ENABLED) || defined(S3TC_NOT_SUPPORTED) || defined(HORIZON_ENABLED)
config.s3tc_supported = false;
#endif

View File

@ -56,450 +56,457 @@
#endif
Error DirAccessUnix::list_dir_begin() {
list_dir_end(); //close any previous dir opening!
list_dir_end(); //close any previous dir opening!
//char real_current_dir_name[2048]; //is this enough?!
//getcwd(real_current_dir_name,2048);
//chdir(current_path.utf8().get_data());
dir_stream = opendir(current_dir.utf8().get_data());
//chdir(real_current_dir_name);
if (!dir_stream) {
return ERR_CANT_OPEN; //error!
}
//char real_current_dir_name[2048]; //is this enough?!
//getcwd(real_current_dir_name,2048);
//chdir(current_path.utf8().get_data());
dir_stream = opendir(current_dir.utf8().get_data());
//chdir(real_current_dir_name);
if (!dir_stream) {
return ERR_CANT_OPEN; //error!
}
return OK;
return OK;
}
bool DirAccessUnix::file_exists(String p_file) {
GLOBAL_LOCK_FUNCTION
GLOBAL_LOCK_FUNCTION
if (p_file.is_rel_path()) {
p_file = current_dir.plus_file(p_file);
}
if (p_file.is_rel_path()) {
p_file = current_dir.plus_file(p_file);
}
p_file = fix_path(p_file);
p_file = fix_path(p_file);
struct stat flags;
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
struct stat flags;
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
if (success && S_ISDIR(flags.st_mode)) {
success = false;
}
if (success && S_ISDIR(flags.st_mode)) {
success = false;
}
return success;
return success;
}
bool DirAccessUnix::dir_exists(String p_dir) {
GLOBAL_LOCK_FUNCTION
GLOBAL_LOCK_FUNCTION
if (p_dir.is_rel_path()) {
p_dir = get_current_dir().plus_file(p_dir);
}
if (p_dir.is_rel_path()) {
p_dir = get_current_dir().plus_file(p_dir);
}
p_dir = fix_path(p_dir);
p_dir = fix_path(p_dir);
struct stat flags;
bool success = (stat(p_dir.utf8().get_data(), &flags) == 0);
struct stat flags;
bool success = (stat(p_dir.utf8().get_data(), &flags) == 0);
return (success && S_ISDIR(flags.st_mode));
return (success && S_ISDIR(flags.st_mode));
}
uint64_t DirAccessUnix::get_modified_time(String p_file) {
if (p_file.is_rel_path()) {
p_file = current_dir.plus_file(p_file);
}
if (p_file.is_rel_path()) {
p_file = current_dir.plus_file(p_file);
}
p_file = fix_path(p_file);
p_file = fix_path(p_file);
struct stat flags;
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
struct stat flags;
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
if (success) {
return flags.st_mtime;
} else {
ERR_FAIL_V(0);
};
return 0;
if (success) {
return flags.st_mtime;
} else {
ERR_FAIL_V(0);
};
return 0;
};
String DirAccessUnix::get_next() {
if (!dir_stream) {
return "";
}
if (!dir_stream) {
return "";
}
dirent *entry = readdir(dir_stream);
dirent *entry = readdir(dir_stream);
if (entry == nullptr) {
list_dir_end();
return "";
}
if (entry == nullptr) {
list_dir_end();
return "";
}
String fname = fix_unicode_name(entry->d_name);
String fname = fix_unicode_name(entry->d_name);
// Look at d_type to determine if the entry is a directory, unless
// its type is unknown (the file system does not support it) or if
// the type is a link, in that case we want to resolve the link to
// known if it points to a directory. stat() will resolve the link
// for us.
// Look at d_type to determine if the entry is a directory, unless
// its type is unknown (the file system does not support it) or if
// the type is a link, in that case we want to resolve the link to
// known if it points to a directory. stat() will resolve the link
// for us.
#ifdef VITA_ENABLED
#define SCE_SO_ISDIR(m) (((m)&SCE_SO_IFMT) == SCE_SO_IFDIR)
_cisdir = SCE_SO_ISDIR(entry->d_stat.st_attr);
#define SCE_SO_ISDIR(m) (((m)&SCE_SO_IFMT) == SCE_SO_IFDIR)
_cisdir = SCE_SO_ISDIR(entry->d_stat.st_attr);
#else
if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) {
String f = current_dir.plus_file(fname);
if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) {
String f = current_dir.plus_file(fname);
struct stat flags;
if (stat(f.utf8().get_data(), &flags) == 0) {
_cisdir = S_ISDIR(flags.st_mode);
} else {
_cisdir = false;
}
} else {
_cisdir = (entry->d_type == DT_DIR);
}
struct stat flags;
if (stat(f.utf8().get_data(), &flags) == 0) {
_cisdir = S_ISDIR(flags.st_mode);
} else {
_cisdir = false;
}
} else {
_cisdir = (entry->d_type == DT_DIR);
}
#endif
_cishidden = is_hidden(fname);
_cishidden = is_hidden(fname);
return fname;
return fname;
}
bool DirAccessUnix::current_is_dir() const {
return _cisdir;
return _cisdir;
}
bool DirAccessUnix::current_is_hidden() const {
return _cishidden;
return _cishidden;
}
void DirAccessUnix::list_dir_end() {
if (dir_stream) {
closedir(dir_stream);
}
dir_stream = nullptr;
_cisdir = false;
if (dir_stream) {
closedir(dir_stream);
}
dir_stream = nullptr;
_cisdir = false;
}
#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
static bool _filter_drive(struct mntent *mnt) {
// Ignore devices that don't point to /dev
if (strncmp(mnt->mnt_fsname, "/dev", 4) != 0) {
return false;
}
// Ignore devices that don't point to /dev
if (strncmp(mnt->mnt_fsname, "/dev", 4) != 0) {
return false;
}
// Accept devices mounted at common locations
if (strncmp(mnt->mnt_dir, "/media", 6) == 0 ||
strncmp(mnt->mnt_dir, "/mnt", 4) == 0 ||
strncmp(mnt->mnt_dir, "/home", 5) == 0 ||
strncmp(mnt->mnt_dir, "/run/media", 10) == 0) {
return true;
}
// Accept devices mounted at common locations
if (strncmp(mnt->mnt_dir, "/media", 6) == 0 ||
strncmp(mnt->mnt_dir, "/mnt", 4) == 0 ||
strncmp(mnt->mnt_dir, "/home", 5) == 0 ||
strncmp(mnt->mnt_dir, "/run/media", 10) == 0) {
return true;
}
// Ignore everything else
return false;
// Ignore everything else
return false;
}
#endif
static void _get_drives(List<String> *list) {
list->push_back("/");
list->push_back("/");
#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
// Check /etc/mtab for the list of mounted partitions
FILE *mtab = setmntent("/etc/mtab", "r");
if (mtab) {
struct mntent mnt;
char strings[4096];
// Check /etc/mtab for the list of mounted partitions
FILE *mtab = setmntent("/etc/mtab", "r");
if (mtab) {
struct mntent mnt;
char strings[4096];
while (getmntent_r(mtab, &mnt, strings, sizeof(strings))) {
if (mnt.mnt_dir != nullptr && _filter_drive(&mnt)) {
// Avoid duplicates
if (!list->find(mnt.mnt_dir)) {
list->push_back(mnt.mnt_dir);
}
}
}
while (getmntent_r(mtab, &mnt, strings, sizeof(strings))) {
if (mnt.mnt_dir != nullptr && _filter_drive(&mnt)) {
// Avoid duplicates
if (!list->find(mnt.mnt_dir)) {
list->push_back(mnt.mnt_dir);
}
}
}
endmntent(mtab);
}
endmntent(mtab);
}
#endif
// Add $HOME
const char *home = getenv("HOME");
if (home) {
// Only add if it's not a duplicate
if (!list->find(home)) {
list->push_back(home);
}
// Add $HOME
const char *home = getenv("HOME");
if (home) {
// Only add if it's not a duplicate
if (!list->find(home)) {
list->push_back(home);
}
// Check $HOME/.config/gtk-3.0/bookmarks
char path[1024];
snprintf(path, 1024, "%s/.config/gtk-3.0/bookmarks", home);
FILE *fd = fopen(path, "r");
if (fd) {
char string[1024];
while (fgets(string, 1024, fd)) {
// Parse only file:// links
if (strncmp(string, "file://", 7) == 0) {
// Strip any unwanted edges on the strings and push_back if it's not a duplicate
String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode();
if (!list->find(fpath)) {
list->push_back(fpath);
}
}
}
// Check $HOME/.config/gtk-3.0/bookmarks
char path[1024];
snprintf(path, 1024, "%s/.config/gtk-3.0/bookmarks", home);
FILE *fd = fopen(path, "r");
if (fd) {
char string[1024];
while (fgets(string, 1024, fd)) {
// Parse only file:// links
if (strncmp(string, "file://", 7) == 0) {
// Strip any unwanted edges on the strings and push_back if it's not a duplicate
String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode();
if (!list->find(fpath)) {
list->push_back(fpath);
}
}
}
fclose(fd);
}
}
fclose(fd);
}
}
list->sort();
list->sort();
}
int DirAccessUnix::get_drive_count() {
List<String> list;
_get_drives(&list);
List<String> list;
_get_drives(&list);
return list.size();
return list.size();
}
String DirAccessUnix::get_drive(int p_drive) {
List<String> list;
_get_drives(&list);
List<String> list;
_get_drives(&list);
ERR_FAIL_INDEX_V(p_drive, list.size(), "");
ERR_FAIL_INDEX_V(p_drive, list.size(), "");
return list[p_drive];
return list[p_drive];
}
int DirAccessUnix::get_current_drive() {
int drive = 0;
int max_length = -1;
const String path = get_current_dir().to_lower();
for (int i = 0; i < get_drive_count(); i++) {
const String d = get_drive(i).to_lower();
if (max_length < d.length() && path.begins_with(d)) {
max_length = d.length();
drive = i;
}
}
return drive;
int drive = 0;
int max_length = -1;
const String path = get_current_dir().to_lower();
for (int i = 0; i < get_drive_count(); i++) {
const String d = get_drive(i).to_lower();
if (max_length < d.length() && path.begins_with(d)) {
max_length = d.length();
drive = i;
}
}
return drive;
}
bool DirAccessUnix::drives_are_shortcuts() {
return true;
return true;
}
Error DirAccessUnix::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
GLOBAL_LOCK_FUNCTION
if (p_dir.is_rel_path()) {
p_dir = get_current_dir().plus_file(p_dir);
}
if (p_dir.is_rel_path()) {
p_dir = get_current_dir().plus_file(p_dir);
}
p_dir = fix_path(p_dir);
p_dir = fix_path(p_dir);
bool success = (mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0);
int err = errno;
bool success = (mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0);
int err = errno;
if (success) {
return OK;
};
if (success) {
return OK;
};
if (err == EEXIST) {
return ERR_ALREADY_EXISTS;
};
if (err == EEXIST) {
return ERR_ALREADY_EXISTS;
};
return ERR_CANT_CREATE;
return ERR_CANT_CREATE;
}
Error DirAccessUnix::change_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
GLOBAL_LOCK_FUNCTION
p_dir = fix_path(p_dir);
p_dir = fix_path(p_dir);
// prev_dir is the directory we are changing out of
String prev_dir;
char real_current_dir_name[2048];
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
if (prev_dir.parse_utf8(real_current_dir_name)) {
prev_dir = real_current_dir_name; //no utf8, maybe latin?
}
// prev_dir is the directory we are changing out of
String prev_dir;
char real_current_dir_name[2048];
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
if (prev_dir.parse_utf8(real_current_dir_name)) {
prev_dir = real_current_dir_name; //no utf8, maybe latin?
}
// try_dir is the directory we are trying to change into
String try_dir = "";
if (p_dir.is_rel_path()) {
String next_dir = current_dir.plus_file(p_dir);
next_dir = next_dir.simplify_path();
try_dir = next_dir;
} else {
try_dir = p_dir;
}
// try_dir is the directory we are trying to change into
String try_dir = "";
if (p_dir.is_rel_path()) {
String next_dir = current_dir.plus_file(p_dir);
next_dir = next_dir.simplify_path();
try_dir = next_dir;
} else {
try_dir = p_dir;
}
bool worked = (chdir(try_dir.utf8().get_data()) == 0); // we can only give this utf8
if (!worked) {
return ERR_INVALID_PARAMETER;
}
bool worked = (chdir(try_dir.utf8().get_data()) == 0); // we can only give this utf8
if (!worked) {
return ERR_INVALID_PARAMETER;
}
String base = _get_root_path();
if (base != String() && !try_dir.begins_with(base)) {
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
String new_dir;
new_dir.parse_utf8(real_current_dir_name);
String base = _get_root_path();
if (base != String() && !try_dir.begins_with(base)) {
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
String new_dir;
new_dir.parse_utf8(real_current_dir_name);
if (!new_dir.begins_with(base)) {
try_dir = current_dir; //revert
}
}
if (!new_dir.begins_with(base)) {
try_dir = current_dir; //revert
}
}
// the directory exists, so set current_dir to try_dir
current_dir = try_dir;
ERR_FAIL_COND_V(chdir(prev_dir.utf8().get_data()) != 0, ERR_BUG);
return OK;
// the directory exists, so set current_dir to try_dir
current_dir = try_dir;
ERR_FAIL_COND_V(chdir(prev_dir.utf8().get_data()) != 0, ERR_BUG);
return OK;
}
String DirAccessUnix::get_current_dir() {
String base = _get_root_path();
if (base != "") {
String bd = current_dir.replace_first(base, "");
if (bd.begins_with("/")) {
return _get_root_string() + bd.substr(1, bd.length());
} else {
return _get_root_string() + bd;
}
}
return current_dir;
String base = _get_root_path();
if (base != "") {
String bd = current_dir.replace_first(base, "");
if (bd.begins_with("/")) {
return _get_root_string() + bd.substr(1, bd.length());
} else {
return _get_root_string() + bd;
}
}
return current_dir;
}
Error DirAccessUnix::rename(String p_path, String p_new_path) {
if (p_path.is_rel_path()) {
p_path = get_current_dir().plus_file(p_path);
}
if (p_path.is_rel_path()) {
p_path = get_current_dir().plus_file(p_path);
}
p_path = fix_path(p_path);
p_path = fix_path(p_path);
if (p_new_path.is_rel_path()) {
p_new_path = get_current_dir().plus_file(p_new_path);
}
if (p_new_path.is_rel_path()) {
p_new_path = get_current_dir().plus_file(p_new_path);
}
p_new_path = fix_path(p_new_path);
p_new_path = fix_path(p_new_path);
return ::rename(p_path.utf8().get_data(), p_new_path.utf8().get_data()) == 0 ? OK : FAILED;
return ::rename(p_path.utf8().get_data(), p_new_path.utf8().get_data()) == 0 ? OK : FAILED;
}
Error DirAccessUnix::remove(String p_path) {
if (p_path.is_rel_path()) {
p_path = get_current_dir().plus_file(p_path);
}
if (p_path.is_rel_path()) {
p_path = get_current_dir().plus_file(p_path);
}
p_path = fix_path(p_path);
p_path = fix_path(p_path);
struct stat flags;
if ((stat(p_path.utf8().get_data(), &flags) != 0)) {
return FAILED;
}
struct stat flags;
if ((stat(p_path.utf8().get_data(), &flags) != 0)) {
return FAILED;
}
if (S_ISDIR(flags.st_mode)) {
return ::rmdir(p_path.utf8().get_data()) == 0 ? OK : FAILED;
} else {
return ::unlink(p_path.utf8().get_data()) == 0 ? OK : FAILED;
}
if (S_ISDIR(flags.st_mode)) {
return ::rmdir(p_path.utf8().get_data()) == 0 ? OK : FAILED;
} else {
return ::unlink(p_path.utf8().get_data()) == 0 ? OK : FAILED;
}
}
bool DirAccessUnix::is_link(String p_file) {
#ifdef VITA_ENABLED
return false;
return false;
#else
if (p_file.is_rel_path())
p_file = get_current_dir().plus_file(p_file);
if (p_file.is_rel_path())
p_file = get_current_dir().plus_file(p_file);
p_file = fix_path(p_file);
p_file = fix_path(p_file);
struct stat flags;
if ((lstat(p_file.utf8().get_data(), &flags) != 0))
return FAILED;
struct stat flags;
if ((lstat(p_file.utf8().get_data(), &flags) != 0))
return FAILED;
return S_ISLNK(flags.st_mode);
return S_ISLNK(flags.st_mode);
#endif
}
String DirAccessUnix::read_link(String p_file) {
#ifdef VITA_ENABLED
return p_file;
return p_file;
#else
if (p_file.is_rel_path())
p_file = get_current_dir().plus_file(p_file);
if (p_file.is_rel_path())
p_file = get_current_dir().plus_file(p_file);
p_file = fix_path(p_file);
p_file = fix_path(p_file);
char buf[256];
memset(buf, 0, 256);
ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf));
String link;
if (len > 0) {
link.parse_utf8(buf, len);
}
return link;
#ifdef HORIZON_ENABLED
return p_file;
#else // HORIZON_ENABLED
char buf[256];
memset(buf, 0, 256);
ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf));
String link;
if (len > 0) {
link.parse_utf8(buf, len);
}
return link;
#endif
#endif
}
Error DirAccessUnix::create_link(String p_source, String p_target) {
#ifdef VITA_ENABLED
return FAILED;
return FAILED;
#elif defined(HORIZON_ENABLED)
return FAILED;
#else
if (p_target.is_rel_path())
p_target = get_current_dir().plus_file(p_target);
if (p_target.is_rel_path()) {
p_target = get_current_dir().plus_file(p_target);
}
p_source = fix_path(p_source);
p_target = fix_path(p_target);
p_source = fix_path(p_source);
p_target = fix_path(p_target);
if (symlink(p_source.utf8().get_data(), p_target.utf8().get_data()) == 0) {
return OK;
} else {
return FAILED;
}
if (symlink(p_source.utf8().get_data(), p_target.utf8().get_data()) == 0) {
return OK;
} else {
return FAILED;
}
#endif
}
uint64_t DirAccessUnix::get_space_left() {
#ifndef NO_STATVFS
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
};
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
};
return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
#else
// FIXME: Implement this.
return 0;
// FIXME: Implement this.
return 0;
#endif
};
String DirAccessUnix::get_filesystem_type() const {
return ""; //TODO this should be implemented
return ""; //TODO this should be implemented
}
bool DirAccessUnix::is_hidden(const String &p_name) {
return p_name != "." && p_name != ".." && p_name.begins_with(".");
return p_name != "." && p_name != ".." && p_name.begins_with(".");
}
DirAccessUnix::DirAccessUnix() {
dir_stream = nullptr;
_cisdir = false;
dir_stream = nullptr;
_cisdir = false;
/* determine drive count */
/* determine drive count */
// set current directory to an absolute path of the current directory
char real_current_dir_name[2048];
ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == nullptr);
if (current_dir.parse_utf8(real_current_dir_name)) {
current_dir = real_current_dir_name;
}
// set current directory to an absolute path of the current directory
char real_current_dir_name[2048];
ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == nullptr);
if (current_dir.parse_utf8(real_current_dir_name)) {
current_dir = real_current_dir_name;
}
change_dir(current_dir);
change_dir(current_dir);
}
DirAccessUnix::~DirAccessUnix() {
list_dir_end();
list_dir_end();
}
#endif //posix_enabled
#endif //posix_enabled

View File

@ -41,7 +41,7 @@
#include <errno.h>
#if defined(UNIX_ENABLED)
#if defined(UNIX_ENABLED) || defined(HORIZON_ENABLED)
#include <unistd.h>
#endif
@ -131,6 +131,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);
@ -143,6 +144,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
fcntl(fd, F_SETFD, opts | FD_CLOEXEC);
#endif
}
#endif // !HORIZON_ENABLED
last_error = OK;
flags = p_mode_flags;
@ -281,7 +283,7 @@ bool FileAccessUnix::file_exists(const String &p_path) {
}
#ifndef VITA_ENABLED
#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;

View File

@ -31,7 +31,7 @@
#include "ip_unix.h"
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(VITA_ENABLED)
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(VITA_ENABLED) || defined(HORIZON_ENABLED)
#include <string.h>
@ -55,8 +55,10 @@
#include <sys/types.h>
#endif
#ifndef VITA_ENABLED
#ifndef HORIZON_ENABLED
#include <ifaddrs.h>
#endif
#endif // !HORIZON_ENABLED
#endif
#include <arpa/inet.h>
#include <sys/socket.h>
@ -221,6 +223,9 @@ void IP_Unix::get_local_interfaces(RBMap<String, Interface_Info> *r_interfaces)
void IP_Unix::get_local_interfaces(RBMap<String, Interface_Info> *r_interfaces) const {
struct ifaddrs *ifAddrStruct = nullptr;
struct ifaddrs *ifa = nullptr;
#ifdef HORIZON_ENABLED
// todo: nifm
#else // HORIZON_ENABLED
int family;
getifaddrs(&ifAddrStruct);
@ -253,6 +258,7 @@ void IP_Unix::get_local_interfaces(RBMap<String, Interface_Info> *r_interfaces)
if (ifAddrStruct != nullptr) {
freeifaddrs(ifAddrStruct);
}
#endif // !HORIZON_ENABLED
}
#endif
#endif

View File

@ -1,6 +1,3 @@
#ifndef IP_UNIX_H
#define IP_UNIX_H
/*************************************************************************/
/* ip_unix.h */
/*************************************************************************/
@ -32,9 +29,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IP_UNIX_H
#define IP_UNIX_H
#include "core/io/ip.h"
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(VITA_ENABLED)
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) || defined(VITA_ENABLED) || defined(HORIZON_ENABLED)
class IP_Unix : public IP {
GDCLASS(IP_Unix, IP);

View File

@ -32,7 +32,7 @@
#include "net_socket_posix.h"
#ifndef UNIX_SOCKET_UNAVAILABLE
#if defined(UNIX_ENABLED) || defined(VITA_ENABLED)
#if defined(UNIX_ENABLED) || defined(VITA_ENABLED) || defined(HORIZON_ENABLED)
#include <errno.h>
#include <netdb.h>
@ -53,7 +53,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#if defined(JAVASCRIPT_ENABLED) || defined(VITA_ENABLED)
#if defined(JAVASCRIPT_ENABLED) || defined(VITA_ENABLED) || defined(HORIZON_ENABLED)
#define IPPROTO_IPV6 41
#define IPV6_V6ONLY 26
#include <arpa/inet.h>
@ -282,15 +282,18 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St
memcpy(&greq.imr_multiaddr, p_ip.get_ipv4(), 4);
memcpy(&greq.imr_interface, if_ip.get_ipv4(), 4);
ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq));
} else {
#ifndef VITA_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 // VITA_ENABLED
}
#ifndef VITA_ENABLED
#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
#endif
}
ERR_FAIL_COND_V(ret != 0, FAILED);
return OK;

View File

@ -0,0 +1,381 @@
#include "sqlite3.h"
#include <switch.h>
// Important points:
// - There is no file truncation
// -> journal_mode=truncate won't work
// - There is no file locking
// -> as far as I know Horizon doesn't support it?
// - Doesn't support temp files
// - Doesn't support dynamic libraries (not my fault)
// FsFileSystem used to interact with files on SD Card
static FsFileSystem fs;
// Size of write buffer (in bytes)
#define SQLITE_NXVFS_BUFFERSZ 8192
// sqlite3_file * actually points to this structure
typedef struct nxFile nxFile;
struct nxFile {
sqlite3_file base; // Base class
FsFile file; // NX (Horizon) file object
char * buf; // Buffer for writes
int bufSize; // Number of bytes in buffer
sqlite3_int64 bufOffset; // Offset of bytes in buffer from buf[0]
};
// Close a file
static int nxClose(sqlite3_file * pFile) {
nxFile * file = (nxFile *) pFile;
fsFileClose(&file->file);
return SQLITE_OK;
}
// Read data from a file
static int nxRead(sqlite3_file * pFile, void * buf, int bytes, sqlite_int64 offset) {
// Bytes read and result code
u64 read = 0;
Result rc;
// Read from file
nxFile * file = (nxFile *) pFile;
rc = fsFileRead(&file->file, offset, buf, bytes, FsReadOption_None, &read);
// Return IO error if result isn't good
if (R_FAILED(rc)) {
return SQLITE_IOERR_READ;
}
// Check if we read the right amount of bytes
if (read == bytes) {
return SQLITE_OK;
// Zero-pad the remaining buffer if not enough bytes were read
} else if (read >= 0) {
if (read < bytes) {
memset(&((char *) buf)[read], 0, bytes-read);
}
return SQLITE_IOERR_SHORT_READ;
}
// Don't think this should be reached?
return SQLITE_IOERR_READ;
}
// Write to a file (and flush immediately)
static int nxDirectWrite(nxFile * file, const void * buf, int bytes, sqlite_int64 offset) {
Result rc = fsFileWrite(&file->file, offset, buf, bytes, FsWriteOption_Flush);
// Return IO error if result is not good
if (R_FAILED(rc)) {
return SQLITE_IOERR_WRITE;
}
return SQLITE_OK;
}
// Flush file's buffer to disk (no-op if buffer is empty)
static int nxFlushBuffer(nxFile * file) {
int rc = SQLITE_OK;
if (file->buf) {
rc = nxDirectWrite(file, file->buf, file->bufSize, file->bufOffset);
file->buf = NULL;
}
return rc;
}
// Write to a file (without flushing)
static int nxWrite(sqlite3_file * pFile, const void * buf, int bytes, sqlite_int64 offset) {
nxFile * file = (nxFile *) pFile;
// If the buffer exists
if (file->buf) {
char * buf2 = (char *) buf; // Pointer to remaining data in write buffer
int bytes2 = bytes; // Remaining number of bytes in write buffer
sqlite3_int64 offset2 = offset; // File offset to write to
// While there's still bytes to write
while (bytes2 > 0) {
int copy; // Number of bytes to copy into file buffer
// If the buffer is full or not being used - flush the buffer
if (file->bufSize == SQLITE_NXVFS_BUFFERSZ || file->bufOffset + file->bufSize != offset2) {
int rc = nxFlushBuffer(file);
if (rc != SQLITE_OK) {
return rc;
}
}
file->bufOffset = offset2 - file->bufSize;
// Copy as much data as possible into the buffer
copy = SQLITE_NXVFS_BUFFERSZ - file->bufSize;
if (copy > bytes2) {
copy = bytes2;
}
memcpy(&file->buf[file->bufSize], buf2, copy);
file->bufSize += copy;
// Update variables
bytes2 -= copy;
offset2 += copy;
buf2 += copy;
}
// Otherwise if there's no buffer just write to file
} else {
return nxDirectWrite(file, buf, bytes, offset);
}
return SQLITE_OK;
}
// This is meant to truncate a file (maybe I'll get to it later)
// This means that journal_mode=truncate is not supported
static int nxTruncate(sqlite3_file * pFile, sqlite_int64 size) {
return SQLITE_OK;
}
// Sync contents of file to the disk
static int nxSync(sqlite3_file * pFile, int flags) {
nxFile * file = (nxFile *) pFile;
// Flush buffer to disk
int tmp = nxFlushBuffer(file);
if (tmp != SQLITE_OK) {
return tmp;
}
// Call system to flush it's cache
Result rc = fsFileFlush(&file->file);
return (R_SUCCEEDED(rc) ? SQLITE_OK : SQLITE_IOERR_FSYNC);
}
// Get the size of the file and write to pointer
static int nxFileSize(sqlite3_file * pFile, sqlite_int64 * size) {
nxFile * file = (nxFile *) pFile;
// Flush buffer to disk first
int tmp = nxFlushBuffer(file);
if (tmp != SQLITE_OK) {
return tmp;
}
// Query using system call
s64 sz;
Result rc = fsFileGetSize(&file->file, &sz);
if (R_FAILED(rc)) {
return SQLITE_IOERR_FSTAT;
}
*(size) = sz;
return SQLITE_OK;
}
// All locking functions do nothing
static int nxLock(sqlite3_file * pFile, int lock) {
return SQLITE_OK;
}
static int nxUnlock(sqlite3_file * pFile, int lock) {
return SQLITE_OK;
}
static int nxCheckReservedLock(sqlite3_file * pFile, int lock) {
return SQLITE_OK;
}
// File control also does nothing
static int nxFileControl(sqlite3_file * pFile, int op, void * arg) {
return SQLITE_NOTFOUND;
}
// Don't return any info about device
static int nxSectorSize(sqlite3_file * pFile) {
return 0;
}
static int nxDeviceCharacteristics(sqlite3_file * pFile) {
return 0;
}
// Open a file
static int nxOpen(sqlite3_vfs * vfs, const char * path, sqlite3_file * pFile, int flags, int * outFlags) {
// Set file's IO methods to the ones above
static const sqlite3_io_methods nxIO = {
1, // iVersion
nxClose, // xClose
nxRead, // xRead
nxWrite, // xWrite
nxTruncate, // xTruncate
nxSync, // xSync
nxFileSize, // xFileSize
nxLock, // xLock
nxUnlock, // xUnlock
nxCheckReservedLock, // xCheckReservedLock
nxFileControl, // xFileControl
nxSectorSize, // xSectorSize
nxDeviceCharacteristics // xDeviceCharacteristics
};
nxFile * file = (nxFile *) pFile;
Result rc;
char * tmpBuf = NULL; // Temporary pointer to potential file buffer
// Don't support temp files
if (path == NULL) {
return SQLITE_IOERR;
}
// Create file buffer if it's a journal file
if (flags & SQLITE_OPEN_MAIN_JOURNAL) {
tmpBuf = (char *) sqlite3_malloc(SQLITE_NXVFS_BUFFERSZ);
if (!tmpBuf) {
return SQLITE_NOMEM;
}
}
// Create file if flag is set
if (flags & SQLITE_OPEN_CREATE) {
rc = fsFsCreateFile(&fs, path, 0, 0);
}
// Choose mode based on flags
u32 mode = 0;
if (flags & SQLITE_OPEN_READONLY) {
mode |= FsOpenMode_Read;
} else if (flags & SQLITE_OPEN_READWRITE) {
mode |= FsOpenMode_Read;
mode |= FsOpenMode_Write;
}
// Allocate memory for file object and open
memset(pFile, 0, sizeof(nxFile));
rc = fsFsOpenFile(&fs, path, mode, &file->file);
printf("%s: %i %i\n", path, R_MODULE(rc), R_DESCRIPTION(rc));
if (R_FAILED(rc)) {
file->base.pMethods = NULL; // Prevents nxClose being called
sqlite3_free(tmpBuf);
return SQLITE_CANTOPEN;
}
file->buf = tmpBuf;
// Set output flags
if (outFlags) {
*(outFlags) = flags;
}
file->base.pMethods = &nxIO;
return SQLITE_OK;
}
// Delete the given file
static int nxDelete(sqlite3_vfs * vfs, const char * path, int sync) {
Result rc = fsFsDeleteFile(&fs, path);
// Commit changes if flag set
if (R_SUCCEEDED(rc) && sync) {
fsFsCommit(&fs);
}
return (R_SUCCEEDED(rc) ? SQLITE_OK : SQLITE_IOERR_DELETE);
}
// Check if the file exists
static int nxAccess(sqlite3_vfs * vfs, const char * path, int flags, int * out) {
// Only check exists flag, fake the other ones
if (flags & SQLITE_ACCESS_EXISTS) {
FsDirEntryType type = FsDirEntryType_Dir;
Result rc = fsFsGetEntryType(&fs, path, &type);
if (R_FAILED(rc) || type != FsDirEntryType_File) {
return SQLITE_IOERR_ACCESS;
}
}
return SQLITE_OK;
}
// Simply returns the given path (should return full path though)
static int nxFullPathname(sqlite3_vfs * vfs, const char * path, int outBytes, char * outPath) {
int num = strlen(path);
if (outBytes > num) {
num = outBytes;
}
memcpy(outPath, path, num);
return SQLITE_OK;
}
// All dynamic library related functions do nothing due to no support
static void * nxDlOpen(sqlite3_vfs * vfs, const char * path){
return NULL;
}
static void nxDlError(sqlite3_vfs * vfs, int bytes, char * err){
sqlite3_snprintf(bytes, err, "Loadable extensions are not supported");
err[bytes-1] = '\0';
}
static void (*nxDlSym(sqlite3_vfs * vfs, void * handle, const char * z))(void){
return NULL;
}
static void nxDlClose(sqlite3_vfs * vfs, void * handle){
return;
}
// Fill the provided buffer with pseudo-random bytes
static int nxRandomness(sqlite3_vfs * vfs, int bytes, char * buf) {
randomGet((void *) buf, bytes);
return SQLITE_OK;
}
// Sleep for the given number of microseconds
static int nxSleep(sqlite3_vfs * vfs, int mSecs) {
svcSleepThread(mSecs * 1000);
return mSecs;
}
// Returns the current time as UTC in Julian days
static int nxCurrentTime(sqlite3_vfs * vfs, double * time) {
u64 ts;
Result rc = timeGetCurrentTime(TimeType_Default, &ts);
if (R_FAILED(rc)) {
return SQLITE_ERROR;
}
*(time) = ts/86400.0 + 2440587.5;
return SQLITE_OK;
}
// Returns a pointer to this VFS so it can be used
sqlite3_vfs * sqlite3_nxvfs() {
static sqlite3_vfs nxvfs = {
1, // iVersion
sizeof(nxFile), // szOsFile
FS_MAX_PATH, // mxPathname
0, // pNext
"nx", // zName
0, // pAppData
nxOpen, // xOpen
nxDelete, // xDelete
nxAccess, // xAccess
nxFullPathname, // xFullPathname
nxDlOpen, // xDlOpen
nxDlError, // xDlError
nxDlSym, // xDlSym
nxDlClose, // xDlClose
nxRandomness, // xRandomness
nxSleep, // xSleep
nxCurrentTime, // xCurrentTime
};
return &nxvfs;
}
// Opens the FsFileSystem and registers the VFS
SQLITE_API int sqlite3_os_init() {
Result rc = fsOpenImageDirectoryFileSystem(&fs, FsImageDirectoryId_Sd);
if (R_FAILED(rc)) {
return SQLITE_ERROR;
}
sqlite3_vfs_register(sqlite3_nxvfs(), 1);
return SQLITE_OK;
}
// Closes the FsFileSystem
SQLITE_API int sqlite3_os_end() {
fsFsClose(&fs);
return SQLITE_OK;
}

View File

@ -1,6 +1,3 @@
#ifndef GDNATIVE_H
#define GDNATIVE_H
/*************************************************************************/
/* gdnative.h */
/*************************************************************************/
@ -32,6 +29,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GDNATIVE_H
#define GDNATIVE_H
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/object/resource.h"

View File

@ -1,6 +1,3 @@
#ifndef GDNATIVE_GDNATIVE_H
#define GDNATIVE_GDNATIVE_H
/*************************************************************************/
/* gdnative.h */
/*************************************************************************/
@ -32,11 +29,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GDNATIVE_GDNATIVE_H
#define GDNATIVE_GDNATIVE_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32) || defined(__ANDROID__) || defined(GDNATIVE_LINUX_BSD_WEB)
#if defined(_WIN32) || defined(__ANDROID__) || defined(GDNATIVE_LINUX_BSD_WEB) || defined(__SWITCH__)
#define GDCALLINGCONV
#elif defined(__APPLE__)
#include "TargetConditionals.h"
@ -45,7 +45,7 @@ extern "C" {
#elif TARGET_OS_MAC
#define GDCALLINGCONV __attribute__((sysv_abi))
#endif
#else // Linux/BSD/Web
#else // !_WIN32 && !__APPLE__ && !__SWITCH__
#if defined(__aarch64__) || defined(__arm__) || defined(__riscv)
#define GDCALLINGCONV
#else

1
platform/switch Submodule

@ -0,0 +1 @@
Subproject commit 5638f1f138228ba619ca3f51170aea36528bb613

View File

@ -1,10 +1,10 @@
#ifndef __ENET_PANDEMONIUM_H__
#define __ENET_PANDEMONIUM_H__
/*************************************************************************/
/* pandemonium.h */
/* pandemonium.h */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* PANDEMONIUM ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
@ -29,19 +29,17 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
/**
@file pandemonium.h
@brief ENet Pandemonium header
*/
#ifdef WINDOWS_ENABLED
#include <stdint.h>
#include <winsock2.h>
#endif
#if defined(UNIX_ENABLED) || defined(ENET_UNIX_ENABLED) || defined(VITA_ENABLED)
#if defined(UNIX_ENABLED) || defined(ENET_UNIX_ENABLED) || defined(VITA_ENABLED) || defined(HORIZON_ENABLED)
#include <arpa/inet.h>
#endif

95
thirdparty/libnx/nacp.h vendored Normal file
View File

@ -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);

55
thirdparty/libnx/nro.h vendored Normal file
View File

@ -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;

92
thirdparty/libnx/types.h vendored Normal file
View File

@ -0,0 +1,92 @@
/**
* @file switch/types.h
* @brief Various system types.
* @copyright libnx Authors
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdalign.h>
#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)

View File

@ -58,7 +58,15 @@ struct sockaddr_un {
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/time.h>
#ifndef __SWITCH__
#include <sys/un.h>
#else // __SWITCH__
#define UNIX_PATH_LEN 108
struct sockaddr_un {
uint16_t sun_family;
char sun_path[UNIX_PATH_LEN];
};
#endif // __SWITCH__
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>