Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fssrv::impl {
class AllocatorForServiceFramework {
public:
using Policy = ams::sf::StatelessAllocationPolicy<AllocatorForServiceFramework>;
void *Allocate(size_t size) {
return fs::impl::Allocate(size);
}
void Deallocate(void *ptr, size_t size) {
return fs::impl::Deallocate(ptr, size);
}
};
using FileSystemObjectFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "fssrv_allocator_for_service_framework.hpp"
namespace ams::fssrv::impl {
namespace {
using FileSystemProxyServiceFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
using ProgramRegistryServiceFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
using FileSystemProxyForLoaderServiceFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
}
ams::sf::EmplacedRef<fssrv::sf::IFileSystemProxy, fssrv::FileSystemProxyImpl> GetFileSystemProxyServiceObject() {
return FileSystemProxyServiceFactory::CreateSharedEmplaced<fssrv::sf::IFileSystemProxy, fssrv::FileSystemProxyImpl>();
}
ams::sf::SharedPointer<fssrv::sf::IProgramRegistry> GetProgramRegistryServiceObject() {
return ProgramRegistryServiceFactory::CreateSharedEmplaced<fssrv::sf::IProgramRegistry, fssrv::ProgramRegistryImpl>();
}
ams::sf::SharedPointer<fssrv::sf::IProgramRegistry> GetInvalidProgramRegistryServiceObject() {
return ProgramRegistryServiceFactory::CreateSharedEmplaced<fssrv::sf::IProgramRegistry, fssrv::InvalidProgramRegistryImpl>();
}
ams::sf::SharedPointer<fssrv::sf::IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject() {
return FileSystemProxyForLoaderServiceFactory ::CreateSharedEmplaced<fssrv::sf::IFileSystemProxyForLoader, fssrv::FileSystemProxyImpl>();
}
ams::sf::SharedPointer<fssrv::sf::IFileSystemProxyForLoader> GetInvalidFileSystemProxyForLoaderServiceObject() {
return FileSystemProxyForLoaderServiceFactory ::CreateSharedEmplaced<fssrv::sf::IFileSystemProxyForLoader, fssrv::InvalidFileSystemProxyImplForLoader>();
}
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "fssrv_program_info.hpp"
namespace ams::fssrv::impl {
namespace {
alignas(0x10) constinit std::byte g_static_buffer_for_program_info_for_initial_process[0x80] = {};
template<typename T>
class StaticAllocatorForProgramInfoForInitialProcess : public std::allocator<T> {
public:
StaticAllocatorForProgramInfoForInitialProcess() { /* ... */ }
template<typename U>
StaticAllocatorForProgramInfoForInitialProcess(const StaticAllocatorForProgramInfoForInitialProcess<U> &) { /* ... */ }
template<typename U>
struct rebind {
using other = StaticAllocatorForProgramInfoForInitialProcess<U>;
};
[[nodiscard]] T *allocate(::std::size_t n) {
AMS_ABORT_UNLESS(sizeof(T) * n <= sizeof(g_static_buffer_for_program_info_for_initial_process));
return reinterpret_cast<T *>(std::addressof(g_static_buffer_for_program_info_for_initial_process));
}
void deallocate(T *p, ::std::size_t n) {
AMS_UNUSED(p, n);
}
};
constexpr const u32 FileAccessControlForInitialProgram[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
constexpr const u32 FileAccessControlDescForInitialProgram[0x2C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
#if defined(ATMOSPHERE_OS_HORIZON)
constinit os::SdkMutex g_mutex;
constinit bool g_initialized = false;
constinit u64 g_initial_process_id_min = 0;
constinit u64 g_initial_process_id_max = 0;
constinit u64 g_current_process_id = 0;
ALWAYS_INLINE void InitializeInitialAndCurrentProcessId() {
if (AMS_UNLIKELY(!g_initialized)) {
std::scoped_lock lk(g_mutex);
if (AMS_LIKELY(!g_initialized)) {
/* Get initial process id range. */
R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_initial_process_id_min), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Minimum));
R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_initial_process_id_max), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Maximum));
AMS_ABORT_UNLESS(0 < g_initial_process_id_min);
AMS_ABORT_UNLESS(g_initial_process_id_min <= g_initial_process_id_max);
/* Get current procss id. */
R_ABORT_UNLESS(svc::GetProcessId(std::addressof(g_current_process_id), svc::PseudoHandle::CurrentProcess));
/* Set initialized. */
g_initialized = true;
}
}
}
#endif
}
std::shared_ptr<ProgramInfo> ProgramInfo::GetProgramInfoForInitialProcess() {
class ProgramInfoHelper : public ProgramInfo {
public:
ProgramInfoHelper(const void *data, s64 data_size, const void *desc, s64 desc_size) : ProgramInfo(data, data_size, desc, desc_size) { /* ... */ }
};
AMS_FUNCTION_LOCAL_STATIC(std::shared_ptr<ProgramInfo>, s_initial_program_info, std::allocate_shared<ProgramInfoHelper>(StaticAllocatorForProgramInfoForInitialProcess<char>{}, FileAccessControlForInitialProgram, sizeof(FileAccessControlForInitialProgram), FileAccessControlDescForInitialProgram, sizeof(FileAccessControlDescForInitialProgram)));
return s_initial_program_info;
}
bool IsInitialProgram(u64 process_id) {
#if defined(ATMOSPHERE_OS_HORIZON)
/* Initialize/sanity check. */
InitializeInitialAndCurrentProcessId();
AMS_ABORT_UNLESS(g_initial_process_id_min > 0);
/* Check process id in range. */
return g_initial_process_id_min <= process_id && process_id <= g_initial_process_id_max;
#elif defined(ATMOSPHERE_OS_WINDOWS) || defined(ATMOSPHERE_OS_LINUX) || defined(ATMOSPHERE_OS_MACOS)
AMS_UNUSED(process_id);
return true;
#else
#error "Unknown os for fssrv::impl::IsInitialProgram"
#endif
}
bool IsCurrentProcess(u64 process_id) {
#if defined(ATMOSPHERE_OS_HORIZON)
/* Initialize. */
InitializeInitialAndCurrentProcessId();
return process_id == g_current_process_id;
#elif defined(ATMOSPHERE_OS_WINDOWS) || defined(ATMOSPHERE_OS_LINUX) || defined(ATMOSPHERE_OS_MACOS)
AMS_UNUSED(process_id);
return true;
#else
#error "Unknown os for fssrv::impl::IsCurrentProcess"
#endif
}
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fssrv::impl {
class ProgramInfo : public ::ams::fs::impl::Newable {
private:
u64 m_process_id;
ncm::ProgramId m_program_id;
ncm::StorageId m_storage_id;
/* TODO: AccessControl m_access_control; */
public:
ProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) : m_process_id(process_id) /* TODO: m_access_control */ {
m_program_id.value = program_id;
m_storage_id = static_cast<ncm::StorageId>(storage_id);
/* TODO */
AMS_UNUSED(data, data_size, desc, desc_size);
}
bool Contains(u64 process_id) const { return m_process_id == process_id; }
u64 GetProcessId() const { return m_process_id; }
ncm::ProgramId GetProgramId() const { return m_program_id; }
u64 GetProgramIdValue() const { return m_program_id.value; }
ncm::StorageId GetStorageId() const { return m_storage_id; }
public:
static std::shared_ptr<ProgramInfo> GetProgramInfoForInitialProcess();
private:
ProgramInfo(const void *data, s64 data_size, const void *desc, s64 desc_size) : m_process_id(os::InvalidProcessId), m_program_id(ncm::InvalidProgramId), m_storage_id(static_cast<ncm::StorageId>(0)) /* TODO: m_access_control */ {
/* TODO */
AMS_UNUSED(data, data_size, desc, desc_size);
}
};
struct ProgramInfoNode : public util::IntrusiveListBaseNode<ProgramInfoNode>, public ::ams::fs::impl::Newable {
std::shared_ptr<ProgramInfo> program_info;
};
bool IsInitialProgram(u64 process_id);
bool IsCurrentProcess(u64 process_id);
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "fssrv_program_registry_manager.hpp"
namespace ams::fssrv::impl {
Result ProgramRegistryManager::RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) {
/* Allocate a new node. */
std::unique_ptr<ProgramInfoNode> new_node(new ProgramInfoNode());
R_UNLESS(new_node != nullptr, fs::ResultAllocationMemoryFailedInProgramRegistryManagerA());
/* Create a new program info. */
{
/* Allocate the new info. */
auto new_info = fssystem::AllocateShared<ProgramInfo>(process_id, program_id, storage_id, data, data_size, desc, desc_size);
R_UNLESS(new_info != nullptr, fs::ResultAllocationMemoryFailedInProgramRegistryManagerA());
/* Set the info in the node. */
new_node->program_info = std::move(new_info);
}
/* Acquire exclusive access to the registry. */
std::scoped_lock lk(m_mutex);
/* Check that the process isn't already in the registry. */
for (const auto &node : m_program_info_list) {
R_UNLESS(!node.program_info->Contains(process_id), fs::ResultInvalidArgument());
}
/* Add the node to the registry. */
m_program_info_list.push_back(*new_node.release());
R_SUCCEED();
}
Result ProgramRegistryManager::UnregisterProgram(u64 process_id) {
/* Acquire exclusive access to the registry. */
std::scoped_lock lk(m_mutex);
/* Try to find and remove the process's node. */
for (auto &node : m_program_info_list) {
if (node.program_info->Contains(process_id)) {
m_program_info_list.erase(m_program_info_list.iterator_to(node));
delete std::addressof(node);
R_SUCCEED();
}
}
/* We couldn't find/unregister the process's node. */
R_THROW(fs::ResultInvalidArgument());
}
Result ProgramRegistryManager::GetProgramInfo(std::shared_ptr<ProgramInfo> *out, u64 process_id) {
/* Acquire exclusive access to the registry. */
std::scoped_lock lk(m_mutex);
/* Check if we're getting permissions for an initial program. */
if (IsInitialProgram(process_id)) {
*out = ProgramInfo::GetProgramInfoForInitialProcess();
R_SUCCEED();
}
/* Find a matching node. */
for (const auto &node : m_program_info_list) {
if (node.program_info->Contains(process_id)) {
*out = node.program_info;
R_SUCCEED();
}
}
/* We didn't find the program info. */
R_THROW(fs::ResultProgramInfoNotFound());
}
Result ProgramRegistryManager::GetProgramInfoByProgramId(std::shared_ptr<ProgramInfo> *out, u64 program_id) {
/* Acquire exclusive access to the registry. */
std::scoped_lock lk(m_mutex);
/* Find a matching node. */
for (const auto &node : m_program_info_list) {
if (node.program_info->GetProgramIdValue() == program_id) {
*out = node.program_info;
R_SUCCEED();
}
}
/* We didn't find the program info. */
R_THROW(fs::ResultProgramInfoNotFound());
}
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
#include "fssrv_program_info.hpp"
namespace ams::fssrv::impl {
class ProgramRegistryManager {
NON_COPYABLE(ProgramRegistryManager);
NON_MOVEABLE(ProgramRegistryManager);
private:
using ProgramInfoList = util::IntrusiveListBaseTraits<ProgramInfoNode>::ListType;
private:
ProgramInfoList m_program_info_list{};
os::SdkMutex m_mutex{};
public:
constexpr ProgramRegistryManager() = default;
Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size);
Result UnregisterProgram(u64 process_id);
Result GetProgramInfo(std::shared_ptr<ProgramInfo> *out, u64 process_id);
Result GetProgramInfoByProgramId(std::shared_ptr<ProgramInfo> *out, u64 program_id);
};
}
AMS_FSSYSTEM_ENABLE_PIMPL(::ams::fssrv::impl::ProgramRegistryManager);

View File

@@ -1,202 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "fssrv_utility.hpp"
#if defined(ATMOSPHERE_OS_WINDOWS)
#include <stratosphere/windows.hpp>
#elif defined(ATMOSPHERE_OS_LINUX)
#include <unistd.h>
#elif defined(ATMOSPHERE_OS_MACOS)
#include <unistd.h>
#include <mach-o/dyld.h>
#include <sys/param.h>
#endif
namespace ams::fssystem {
class PathOnExecutionDirectory {
private:
char m_path[fs::EntryNameLengthMax + 1];
public:
PathOnExecutionDirectory() {
#if defined(ATMOSPHERE_OS_WINDOWS)
{
/* Get the module file name. */
wchar_t module_file_name[fs::EntryNameLengthMax + 1];
if (::GetModuleFileNameW(0, module_file_name, util::size(module_file_name)) == 0) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryA());
}
/* Split the path. */
wchar_t drive_name[3];
wchar_t dir_name[fs::EntryNameLengthMax + 1];
::_wsplitpath_s(module_file_name, drive_name, util::size(drive_name), dir_name, util::size(dir_name), nullptr, 0, nullptr, 0);
/* Print the drive and directory. */
wchar_t path[fs::EntryNameLengthMax + 1];
::swprintf_s(path, util::size(path), L"%s%s", drive_name, dir_name);
/* Convert to utf-8. */
const auto res = ::WideCharToMultiByte(CP_UTF8, 0, path, -1, m_path, util::size(m_path), nullptr, nullptr);
if (res == 0) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
}
#elif defined(ATMOSPHERE_OS_LINUX)
{
char full_path[PATH_MAX] = {};
if (::readlink("/proc/self/exe", full_path, sizeof(full_path)) == -1) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryA());
}
const int len = std::strlen(full_path);
if (len >= static_cast<int>(sizeof(m_path))) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
std::memcpy(m_path, full_path, len + 1);
for (int i = len - 1; i >= 0; --i) {
if (m_path[i] == '/') {
m_path[i + 1] = 0;
break;
}
}
}
#elif defined(ATMOSPHERE_OS_MACOS)
{
char full_path[MAXPATHLEN] = {};
uint32_t size = sizeof(full_path);
if (_NSGetExecutablePath(full_path, std::addressof(size)) != 0) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryA());
}
const int len = std::strlen(full_path);
if (len >= static_cast<int>(sizeof(m_path))) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
std::memcpy(m_path, full_path, len + 1);
for (int i = len - 1; i >= 0; --i) {
if (m_path[i] == '/') {
m_path[i + 1] = 0;
break;
}
}
}
#else
AMS_ABORT("TODO: Unknown OS for PathOnExecutionDirectory");
#endif
const auto len = std::strlen(m_path);
if (m_path[len - 1] != '/' && m_path[len - 1] != '\\') {
if (len + 1 >= sizeof(m_path)) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
m_path[len] = '/';
m_path[len + 1] = 0;
}
}
const char *Get() const {
return m_path;
}
};
class PathOnWorkingDirectory {
private:
char m_path[fs::EntryNameLengthMax + 1];
public:
PathOnWorkingDirectory() {
#if defined(ATMOSPHERE_OS_WINDOWS)
{
/* Get the current directory. */
wchar_t current_directory[fs::EntryNameLengthMax + 1];
if (::GetCurrentDirectoryW(util::size(current_directory), current_directory) == 0) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
/* Convert to utf-8. */
const auto res = ::WideCharToMultiByte(CP_UTF8, 0, current_directory, -1, m_path, util::size(m_path), nullptr, nullptr);
if (res == 0) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
}
#elif defined(ATMOSPHERE_OS_LINUX)
{
char full_path[PATH_MAX] = {};
if (::getcwd(full_path, sizeof(full_path)) == nullptr) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
const int len = std::strlen(full_path);
if (len >= static_cast<int>(sizeof(m_path))) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
std::memcpy(m_path, full_path, len + 1);
}
#elif defined(ATMOSPHERE_OS_MACOS)
{
char full_path[MAXPATHLEN] = {};
if (::getcwd(full_path, sizeof(full_path)) == nullptr) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
const int len = std::strlen(full_path);
if (len >= static_cast<int>(sizeof(m_path))) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
std::memcpy(m_path, full_path, len + 1);
}
#else
AMS_ABORT("TODO: Unknown OS for PathOnWorkingDirectory");
#endif
const auto len = std::strlen(m_path);
if (m_path[len - 1] != '/' && m_path[len - 1] != '\\') {
if (len + 1 >= sizeof(m_path)) {
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
}
m_path[len] = '/';
m_path[len + 1] = 0;
}
}
const char *Get() const {
return m_path;
}
};
}
namespace ams::fssrv::impl {
const char *GetExecutionDirectoryPath() {
AMS_FUNCTION_LOCAL_STATIC(fssystem::PathOnExecutionDirectory, s_path_on_execution_directory);
return s_path_on_execution_directory.Get();
}
const char *GetWorkingDirectoryPath() {
AMS_FUNCTION_LOCAL_STATIC(fssystem::PathOnWorkingDirectory, s_path_on_working_directory);
return s_path_on_working_directory.Get();
}
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::fssrv::impl {
const char *GetExecutionDirectoryPath();
const char *GetWorkingDirectoryPath();
}