Refactor Comments + Other Minor Fixes

This commit is contained in:
◱ PixelyIon 2020-09-28 15:35:17 +05:30 committed by ◱ PixelyIon
parent 429af1990a
commit 4070686897
167 changed files with 1376 additions and 1433 deletions

View File

@ -46,7 +46,7 @@ namespace skyline::audio {
std::lock_guard bufferGuard(track->bufferLock); std::lock_guard bufferGuard(track->bufferLock);
auto trackSamples{track->samples.Read(destBuffer, streamSamples, [](i16 *source, i16 *destination) { auto trackSamples{track->samples.Read(span(destBuffer, streamSamples), [](i16 *source, i16 *destination) {
*destination = Saturate<i16, i32>(static_cast<u32>(*destination) + static_cast<u32>(*source)); *destination = Saturate<i16, i32>(static_cast<u32>(*destination) + static_cast<u32>(*source));
}, writtenSamples)}; }, writtenSamples)};

View File

@ -11,10 +11,10 @@ namespace skyline::audio {
*/ */
class Audio : public oboe::AudioStreamCallback { class Audio : public oboe::AudioStreamCallback {
private: private:
oboe::AudioStreamBuilder builder; //!< The audio stream builder, used to open oboe::AudioStreamBuilder builder;
oboe::ManagedStream outputStream; //!< The output oboe audio stream oboe::ManagedStream outputStream;
std::vector<std::shared_ptr<AudioTrack>> audioTracks; //!< A vector of shared_ptr to every open audio track std::vector<std::shared_ptr<AudioTrack>> audioTracks;
Mutex trackLock; //!< This mutex is used to ensure that audioTracks isn't modified while it is being used Mutex trackLock; //!< Synchronizes modifications to the audio tracks
public: public:
Audio(const DeviceState &state); Audio(const DeviceState &state);
@ -30,7 +30,6 @@ namespace skyline::audio {
/** /**
* @brief Closes a track and frees its data * @brief Closes a track and frees its data
* @param track The track to close
*/ */
void CloseTrack(std::shared_ptr<AudioTrack> &track); void CloseTrack(std::shared_ptr<AudioTrack> &track);

View File

@ -7,13 +7,10 @@
namespace skyline::audio { namespace skyline::audio {
/** /**
* @brief The AdpcmDecoder class handles decoding single channel adaptive differential PCM data * @brief The AdpcmDecoder class handles decoding single channel ADPCM (Adaptive Differential Pulse-Code Modulation) data
*/ */
class AdpcmDecoder { class AdpcmDecoder {
private: private:
/**
* @brief This struct holds a single ADPCM frame header
*/
union FrameHeader { union FrameHeader {
u8 raw; u8 raw;
@ -25,16 +22,14 @@ namespace skyline::audio {
}; };
static_assert(sizeof(FrameHeader) == 0x1); static_assert(sizeof(FrameHeader) == 0x1);
std::array<i32, 2> history{}; //!< This contains the history for decoding the ADPCM stream std::array<i32, 2> history{}; //!< The previous samples for decoding the ADPCM stream
std::vector<std::array<i16, 2>> coefficients; //!< This contains the coefficients for decoding the ADPCM stream std::vector<std::array<i16, 2>> coefficients; //!< The coefficients for decoding the ADPCM stream
public: public:
AdpcmDecoder(const std::vector<std::array<i16, 2>> &coefficients); AdpcmDecoder(const std::vector<std::array<i16, 2>> &coefficients);
/** /**
* @brief This decodes a buffer of ADPCM data into I16 PCM * @brief Decodes a buffer of ADPCM data into I16 PCM
* @param adpcmData A buffer containing the raw ADPCM data
* @return A buffer containing decoded single channel I16 PCM data
*/ */
std::vector<i16> Decode(span<u8> adpcmData); std::vector<i16> Decode(span<u8> adpcmData);
}; };

View File

@ -7,9 +7,10 @@
namespace skyline::audio { namespace skyline::audio {
/** /**
* @brief This class is used to abstract an array into a circular buffer * @brief An abstraction of an array into a circular buffer
* @tparam Type The type of elements stored in the buffer * @tparam Type The type of elements stored in the buffer
* @tparam Size The maximum size of the circular buffer * @tparam Size The maximum size of the circular buffer
* @url https://en.wikipedia.org/wiki/Circular_buffer
*/ */
template<typename Type, size_t Size> template<typename Type, size_t Size>
class CircularBuffer { class CircularBuffer {
@ -17,24 +18,25 @@ namespace skyline::audio {
std::array<Type, Size> array{}; //!< The internal array holding the circular buffer std::array<Type, Size> array{}; //!< The internal array holding the circular buffer
Type *start{array.begin()}; //!< The start/oldest element of the internal array Type *start{array.begin()}; //!< The start/oldest element of the internal array
Type *end{array.begin()}; //!< The end/newest element of the internal array Type *end{array.begin()}; //!< The end/newest element of the internal array
bool empty{true}; //!< This boolean is used to differentiate between the buffer being full or empty bool empty{true}; //!< If the buffer is full or empty, as start == end can mean either
Mutex mtx; //!< The mutex ensures that the buffer operations don't overlap Mutex mtx; //!< Synchronizes buffer operations so they don't overlap
public: public:
/** /**
* @brief This reads data from this buffer into the specified buffer * @brief Reads data from this buffer into the specified buffer
* @param address The address to write buffer data into * @param address The address to write buffer data into
* @param maxSize The maximum amount of data to write in units of Type * @param maxSize The maximum amount of data to write in units of Type
* @param copyFunction If this is specified, then this is called rather than memcpy * @param copyFunction If this is specified, then this is called rather than memcpy
* @return The amount of data written into the input buffer in units of Type * @return The amount of data written into the input buffer in units of Type
*/ */
inline size_t Read(Type *address, ssize_t maxSize, void copyFunction(Type *, Type *) = {}, ssize_t copyOffset = -1) { inline size_t Read(span<Type> buffer, void copyFunction(Type *, Type *) = {}, ssize_t copyOffset = -1) {
std::lock_guard guard(mtx); std::lock_guard guard(mtx);
if (empty) if (empty)
return 0; return 0;
ssize_t size{}, sizeBegin{}, sizeEnd{}; Type* pointer{buffer.data()};
ssize_t maxSize{static_cast<ssize_t>(buffer.size())}, size{}, sizeBegin{}, sizeEnd{};
if (start < end) { if (start < end) {
sizeEnd = std::min(end - start, maxSize); sizeEnd = std::min(end - start, maxSize);
@ -50,30 +52,30 @@ namespace skyline::audio {
if (copyFunction && copyOffset) { if (copyFunction && copyOffset) {
auto sourceEnd{start + ((copyOffset != -1) ? copyOffset : sizeEnd)}; auto sourceEnd{start + ((copyOffset != -1) ? copyOffset : sizeEnd)};
for (auto source{start}, destination{address}; source < sourceEnd; source++, destination++) for (auto source{start}, destination{pointer}; source < sourceEnd; source++, destination++)
copyFunction(source, destination); copyFunction(source, destination);
if (copyOffset != -1) { if (copyOffset != -1) {
std::memcpy(address + copyOffset, start + copyOffset, (sizeEnd - copyOffset) * sizeof(Type)); std::memcpy(pointer + copyOffset, start + copyOffset, (sizeEnd - copyOffset) * sizeof(Type));
copyOffset -= sizeEnd; copyOffset -= sizeEnd;
} }
} else { } else {
std::memcpy(address, start, sizeEnd * sizeof(Type)); std::memcpy(pointer, start, sizeEnd * sizeof(Type));
} }
address += sizeEnd; pointer += sizeEnd;
if (sizeBegin) { if (sizeBegin) {
if (copyFunction && copyOffset) { if (copyFunction && copyOffset) {
auto sourceEnd{array.begin() + ((copyOffset != -1) ? copyOffset : sizeBegin)}; auto sourceEnd{array.begin() + ((copyOffset != -1) ? copyOffset : sizeBegin)};
for (auto source{array.begin()}, destination{address}; source < sourceEnd; source++, destination++) for (auto source{array.begin()}, destination{pointer}; source < sourceEnd; source++, destination++)
copyFunction(source, destination); copyFunction(source, destination);
if (copyOffset != -1) if (copyOffset != -1)
std::memcpy(array.begin() + copyOffset, address + copyOffset, (sizeBegin - copyOffset) * sizeof(Type)); std::memcpy(array.begin() + copyOffset, pointer + copyOffset, (sizeBegin - copyOffset) * sizeof(Type));
} else { } else {
std::memcpy(address, array.begin(), sizeBegin * sizeof(Type)); std::memcpy(pointer, array.begin(), sizeBegin * sizeof(Type));
} }
start = array.begin() + sizeBegin; start = array.begin() + sizeBegin;
@ -88,19 +90,19 @@ namespace skyline::audio {
} }
/** /**
* @brief This appends data from the specified buffer into this buffer * @brief Appends data from the specified buffer into this buffer
* @param address The address of the buffer
* @param size The size of the buffer in units of Type
*/ */
inline void Append(Type *address, ssize_t size) { inline void Append(span<Type> buffer) {
std::lock_guard guard(mtx); std::lock_guard guard(mtx);
Type* pointer{buffer.data()};
ssize_t size{static_cast<ssize_t>(buffer.size())};
while (size) { while (size) {
if (start <= end && end != array.end()) { if (start <= end && end != array.end()) {
auto sizeEnd{std::min(array.end() - end, size)}; auto sizeEnd{std::min(array.end() - end, size)};
std::memcpy(end, address, sizeEnd * sizeof(Type)); std::memcpy(end, pointer, sizeEnd * sizeof(Type));
address += sizeEnd; pointer += sizeEnd;
size -= sizeEnd; size -= sizeEnd;
end += sizeEnd; end += sizeEnd;
@ -109,18 +111,18 @@ namespace skyline::audio {
auto sizePostStart{std::min(array.end() - start, size - sizePreStart)}; auto sizePostStart{std::min(array.end() - start, size - sizePreStart)};
if (sizePreStart) if (sizePreStart)
std::memcpy((end == array.end()) ? array.begin() : end, address, sizePreStart * sizeof(Type)); std::memcpy((end == array.end()) ? array.begin() : end, pointer, sizePreStart * sizeof(Type));
if (end == array.end()) if (end == array.end())
end = array.begin() + sizePreStart; end = array.begin() + sizePreStart;
else else
end += sizePreStart; end += sizePreStart;
address += sizePreStart; pointer += sizePreStart;
size -= sizePreStart; size -= sizePreStart;
if (sizePostStart) if (sizePostStart)
std::memcpy(end, address, sizePostStart * sizeof(Type)); std::memcpy(end, pointer, sizePostStart * sizeof(Type));
if (start == array.end()) if (start == array.end())
start = array.begin() + sizePostStart; start = array.begin() + sizePostStart;
@ -132,20 +134,12 @@ namespace skyline::audio {
else else
end += sizePostStart; end += sizePostStart;
address += sizePostStart; pointer += sizePostStart;
size -= sizePostStart; size -= sizePostStart;
} }
empty = false; empty = false;
} }
} }
/**
* @brief This appends data from a span to the buffer
* @param data A span containing the data to be appended
*/
inline void Append(span<Type> data) {
Append(data.data(), data.size());
}
}; };
} }

View File

@ -15,9 +15,6 @@ namespace skyline {
}; };
namespace audio { namespace audio {
/**
* @brief The available PCM stream formats
*/
enum class AudioFormat : u8 { enum class AudioFormat : u8 {
Invalid = 0, //!< An invalid PCM format Invalid = 0, //!< An invalid PCM format
Int8 = 1, //!< 8 bit integer PCM Int8 = 1, //!< 8 bit integer PCM
@ -25,21 +22,15 @@ namespace skyline {
Int24 = 3, //!< 24 bit integer PCM Int24 = 3, //!< 24 bit integer PCM
Int32 = 4, //!< 32 bit integer PCM Int32 = 4, //!< 32 bit integer PCM
Float = 5, //!< Floating point PCM Float = 5, //!< Floating point PCM
ADPCM = 6 //!< Adaptive differential PCM ADPCM = 6, //!< Adaptive differential PCM
}; };
/**
* @brief The state of an audio track
*/
enum class AudioOutState : u8 { enum class AudioOutState : u8 {
Started = 0, //!< Stream is started and is playing Started = 0, //!< Stream is started and is playing
Stopped = 1, //!< Stream is stopped, there are no samples left to play Stopped = 1, //!< Stream is stopped, there are no samples left to play
Paused = 2 //!< Stream is paused, some samples may not have been played yet Paused = 2, //!< Stream is paused, some samples may not have been played yet
}; };
/**
* @brief This stores information about pushed buffers
*/
struct BufferIdentifier { struct BufferIdentifier {
u64 tag; u64 tag;
u64 finalSample; //!< The final sample this buffer will be played in, after that the buffer can be safely released u64 finalSample; //!< The final sample this buffer will be played in, after that the buffer can be safely released
@ -47,12 +38,9 @@ namespace skyline {
}; };
/** /**
* @brief This saturates the specified value according to the numeric limits of Out * @brief Saturates the specified value according to the numeric limits of Out
* @tparam Out The return value type and the numeric limit clamp * @tparam Out The return value type and the numeric limit clamp
* @tparam Intermediate The intermediate type that is converted to from In before clamping * @tparam Intermediate The intermediate type that is converted to from In before clamping
* @tparam In The input value type
* @param value The value to saturate
* @return The saturated value
*/ */
template<typename Out, typename Intermediate, typename In> template<typename Out, typename Intermediate, typename In>
inline Out Saturate(In value) { inline Out Saturate(In value) {

View File

@ -6,7 +6,7 @@
namespace skyline::audio { namespace skyline::audio {
/** /**
* @brief This holds the coefficients for each index of a single output frame * @brief The coefficients for each index of a single output frame
*/ */
struct LutEntry { struct LutEntry {
i32 a; i32 a;
@ -16,7 +16,7 @@ namespace skyline::audio {
}; };
// @fmt:off // @fmt:off
constexpr std::array<LutEntry, 128> CurveLut0 = {{ constexpr std::array<LutEntry, 128> CurveLut0{{
{6600, 19426, 6722, 3}, {6479, 19424, 6845, 9}, {6359, 19419, 6968, 15}, {6239, 19412, 7093, 22}, {6600, 19426, 6722, 3}, {6479, 19424, 6845, 9}, {6359, 19419, 6968, 15}, {6239, 19412, 7093, 22},
{6121, 19403, 7219, 28}, {6004, 19391, 7345, 34}, {5888, 19377, 7472, 41}, {5773, 19361, 7600, 48}, {6121, 19403, 7219, 28}, {6004, 19391, 7345, 34}, {5888, 19377, 7472, 41}, {5773, 19361, 7600, 48},
{5659, 19342, 7728, 55}, {5546, 19321, 7857, 62}, {5434, 19298, 7987, 69}, {5323, 19273, 8118, 77}, {5659, 19342, 7728, 55}, {5546, 19321, 7857, 62}, {5434, 19298, 7987, 69}, {5323, 19273, 8118, 77},

View File

@ -20,7 +20,7 @@ namespace skyline::audio {
public: public:
CircularBuffer<i16, constant::SampleRate * constant::ChannelCount * 10> samples; //!< A circular buffer with all appended audio samples CircularBuffer<i16, constant::SampleRate * constant::ChannelCount * 10> samples; //!< A circular buffer with all appended audio samples
Mutex bufferLock; //!< This mutex ensures that appending to buffers doesn't overlap Mutex bufferLock; //!< Synchronizes appending to audio buffers
AudioOutState playbackState{AudioOutState::Stopped}; //!< The current state of playback AudioOutState playbackState{AudioOutState::Stopped}; //!< The current state of playback
u64 sampleCounter{}; //!< A counter used for tracking when buffers have been played and can be released u64 sampleCounter{}; //!< A counter used for tracking when buffers have been played and can be released
@ -40,7 +40,7 @@ namespace skyline::audio {
} }
/** /**
* @brief Stops audio playback. This waits for audio playback to finish before returning. * @brief Stops audio playback, this waits for audio playback to finish before returning
*/ */
void Stop(); void Stop();

View File

@ -146,7 +146,7 @@ namespace skyline {
character = '\\'; character = '\\';
std::lock_guard guard(mtx); std::lock_guard guard(mtx);
logFile << "1|" << levelStr[static_cast<u8>(level)] << "|" << str << "\n"; logFile << "1|" << levelCharacter[static_cast<u8>(level)] << "|" << str << "\n";
} }
DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &process, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger) DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &process, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger)

View File

@ -65,11 +65,11 @@ namespace skyline {
constexpr u16 DockedResolutionW{1920}; //!< The width component of the docked resolution constexpr u16 DockedResolutionW{1920}; //!< The width component of the docked resolution
constexpr u16 DockedResolutionH{1080}; //!< The height component of the docked resolution constexpr u16 DockedResolutionH{1080}; //!< The height component of the docked resolution
// Time // Time
constexpr u64 NsInSecond{1000000000}; //!< This is the amount of nanoseconds in a second constexpr u64 NsInSecond{1000000000}; //!< The amount of nanoseconds in a second
} }
/** /**
* @brief This is a std::runtime_error with libfmt formatting * @brief A wrapper over std::runtime_error with libfmt formatting
*/ */
class exception : public std::runtime_error { class exception : public std::runtime_error {
public: public:
@ -110,7 +110,7 @@ namespace skyline {
* @note The multiple needs to be a power of 2 * @note The multiple needs to be a power of 2
*/ */
template<typename TypeVal, typename TypeMul> template<typename TypeVal, typename TypeMul>
constexpr inline TypeVal AlignUp(TypeVal value, TypeMul multiple) { constexpr TypeVal AlignUp(TypeVal value, TypeMul multiple) {
multiple--; multiple--;
return (value + multiple) & ~(multiple); return (value + multiple) & ~(multiple);
} }
@ -120,7 +120,7 @@ namespace skyline {
* @note The multiple needs to be a power of 2 * @note The multiple needs to be a power of 2
*/ */
template<typename TypeVal, typename TypeMul> template<typename TypeVal, typename TypeMul>
constexpr inline TypeVal AlignDown(TypeVal value, TypeMul multiple) { constexpr TypeVal AlignDown(TypeVal value, TypeMul multiple) {
return value & ~(multiple - 1); return value & ~(multiple - 1);
} }
@ -128,7 +128,7 @@ namespace skyline {
* @return If the address is aligned with the multiple * @return If the address is aligned with the multiple
*/ */
template<typename TypeVal, typename TypeMul> template<typename TypeVal, typename TypeMul>
constexpr inline bool IsAligned(TypeVal value, TypeMul multiple) { constexpr bool IsAligned(TypeVal value, TypeMul multiple) {
if ((multiple & (multiple - 1)) == 0) if ((multiple & (multiple - 1)) == 0)
return !(value & (multiple - 1U)); return !(value & (multiple - 1U));
else else
@ -138,14 +138,14 @@ namespace skyline {
/** /**
* @return If the value is page aligned * @return If the value is page aligned
*/ */
constexpr inline bool PageAligned(u64 value) { constexpr bool PageAligned(u64 value) {
return IsAligned(value, PAGE_SIZE); return IsAligned(value, PAGE_SIZE);
} }
/** /**
* @return If the value is word aligned * @return If the value is word aligned
*/ */
constexpr inline bool WordAligned(u64 value) { constexpr bool WordAligned(u64 value) {
return IsAligned(value, WORD_BIT / 8); return IsAligned(value, WORD_BIT / 8);
} }
@ -301,7 +301,7 @@ namespace skyline {
span(const Container &) -> span<const typename Container::value_type>; span(const Container &) -> span<const typename Container::value_type>;
/** /**
* @brief The Mutex class is a wrapper around an atomic bool used for synchronization * @brief The Mutex class is a wrapper around an atomic bool used for low-contention synchronization
*/ */
class Mutex { class Mutex {
std::atomic_flag flag = ATOMIC_FLAG_INIT; //!< An atomic flag to hold the state of the mutex std::atomic_flag flag = ATOMIC_FLAG_INIT; //!< An atomic flag to hold the state of the mutex
@ -334,12 +334,12 @@ namespace skyline {
class GroupMutex { class GroupMutex {
public: public:
/** /**
* @brief This enumeration holds all the possible owners of the mutex * @brief All the possible owners of the mutex
*/ */
enum class Group : u8 { enum class Group : u8 {
None = 0, //!< No group owns this mutex None = 0, //!< No group owns this mutex
Group1 = 1, //!< Group 1 owns this mutex Group1 = 1, //!< Group 1 owns this mutex
Group2 = 2 //!< Group 2 owns this mutex Group2 = 2, //!< Group 2 owns this mutex
}; };
/** /**
@ -366,13 +366,18 @@ namespace skyline {
class Logger { class Logger {
private: private:
std::ofstream logFile; //!< An output stream to the log file std::ofstream logFile; //!< An output stream to the log file
const char *levelStr[4] = {"0", "1", "2", "3"}; //!< This is used to denote the LogLevel when written out to a file std::array<char, 4> levelCharacter{'0', '1', '2', '3'}; //!< The LogLevel as written out to a file
static constexpr int levelSyslog[4] = {LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG}; //!< This corresponds to LogLevel and provides it's equivalent for syslog static constexpr std::array<int, 4> levelSyslog{LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG}; //!< This corresponds to LogLevel and provides it's equivalent for syslog
Mutex mtx; //!< A mutex to lock before logging anything Mutex mtx; //!< A mutex to lock before logging anything
public: public:
enum class LogLevel { Error, Warn, Info, Debug }; //!< The level of a particular log enum class LogLevel {
LogLevel configLevel; //!< The level of logs to write Error,
Warn,
Info,
Debug,
};
LogLevel configLevel; //!< The minimum level of logs to write
/** /**
* @param path The path of the log file * @param path The path of the log file
@ -484,7 +489,7 @@ namespace skyline {
int GetInt(const std::string &key); int GetInt(const std::string &key);
/** /**
* @brief Writes all settings keys and values to syslog. This function is for development purposes. * @brief Writes all settings keys and values to syslog, this function is for development purposes
*/ */
void List(const std::shared_ptr<Logger> &logger); void List(const std::shared_ptr<Logger> &logger);
}; };
@ -512,22 +517,22 @@ namespace skyline {
} }
/** /**
* @brief This struct is used to hold the state of a device * @brief The state of the entire emulator is contained within this class, all objects related to emulation are tied into it
*/ */
struct DeviceState { struct DeviceState {
DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &process, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger); DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &process, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger);
kernel::OS *os; //!< This holds a reference to the OS class kernel::OS *os;
std::shared_ptr<kernel::type::KProcess> &process; //!< This holds a reference to the process object std::shared_ptr<kernel::type::KProcess> &process;
thread_local static std::shared_ptr<kernel::type::KThread> thread; //!< This holds a reference to the current thread object thread_local static std::shared_ptr<kernel::type::KThread> thread; //!< The KThread of the thread which accesses this object
thread_local static ThreadContext *ctx; //!< This holds the context of the thread thread_local static ThreadContext *ctx; //!< The context of the guest thread for the corresponding host thread
std::shared_ptr<NCE> nce; //!< This holds a reference to the NCE class std::shared_ptr<NCE> nce;
std::shared_ptr<gpu::GPU> gpu; //!< This holds a reference to the GPU class std::shared_ptr<gpu::GPU> gpu;
std::shared_ptr<audio::Audio> audio; //!< This holds a reference to the Audio class std::shared_ptr<audio::Audio> audio;
std::shared_ptr<input::Input> input; //!< This holds a reference to the Input class std::shared_ptr<input::Input> input;
std::shared_ptr<loader::Loader> loader; //!< This holds a reference to the Loader class std::shared_ptr<loader::Loader> loader;
std::shared_ptr<JvmManager> jvm; //!< This holds a reference to the JvmManager class std::shared_ptr<JvmManager> jvm;
std::shared_ptr<Settings> settings; //!< This holds a reference to the Settings class std::shared_ptr<Settings> settings;
std::shared_ptr<Logger> logger; //!< This holds a reference to the Logger class std::shared_ptr<Logger> logger;
}; };
} }

View File

@ -13,14 +13,10 @@ namespace skyline::crypto {
class AesCipher { class AesCipher {
private: private:
mbedtls_cipher_context_t decryptContext; mbedtls_cipher_context_t decryptContext;
std::vector<u8> buffer; //!< A buffer used to avoid constant memory allocation
/** /**
* @brief Buffer declared as class variable to avoid constant memory allocation * @brief Calculates IV for XTS, basically just big to little endian conversion
*/
std::vector<u8> buffer;
/**
* @brief Calculates IV for XTS, basically just big to little endian conversion.
*/ */
inline static std::array<u8, 0x10> GetTweak(size_t sector) { inline static std::array<u8, 0x10> GetTweak(size_t sector) {
std::array<u8, 0x10> tweak{}; std::array<u8, 0x10> tweak{};
@ -35,24 +31,25 @@ namespace skyline::crypto {
~AesCipher(); ~AesCipher();
/** /**
* @brief Sets initilization vector * @brief Sets the Initialization Vector
*/ */
void SetIV(const std::array<u8, 0x10> &iv); void SetIV(const std::array<u8, 0x10> &iv);
/** /**
* @note destination and source can be the same * @brief Decrypts the supplied buffer and outputs the result into the destination buffer
* @note The destination and source buffers can be the same
*/ */
void Decrypt(u8 *destination, u8 *source, size_t size); void Decrypt(u8 *destination, u8 *source, size_t size);
/** /**
* @brief Decrypts data and writes back to it * @brief Decrypts the supplied data in-place
*/ */
inline void Decrypt(span<u8> data) { inline void Decrypt(span<u8> data) {
Decrypt(data.data(), data.data(), data.size()); Decrypt(data.data(), data.data(), data.size());
} }
/** /**
* @brief Decrypts data with XTS. IV will get calculated with the given sector * @brief Decrypts data with XTS, IV will get calculated with the given sector
*/ */
void XtsDecrypt(u8 *destination, u8 *source, size_t size, size_t sector, size_t sectorSize); void XtsDecrypt(u8 *destination, u8 *source, size_t size, size_t sector, size_t sectorSize);

View File

@ -4,22 +4,19 @@
#pragma once #pragma once
#include <android/native_window.h> #include <android/native_window.h>
#include <kernel/types/KEvent.h> #include "services/nvdrv/devices/nvmap.h"
#include <services/nvdrv/devices/nvmap.h>
#include "gpu/memory_manager.h"
#include "gpu/gpfifo.h" #include "gpu/gpfifo.h"
#include "gpu/syncpoint.h" #include "gpu/syncpoint.h"
#include "gpu/engines/maxwell_3d.h" #include "gpu/engines/maxwell_3d.h"
namespace skyline::gpu { namespace skyline::gpu {
/** /**
* @brief This is used to converge all of the interfaces to the GPU and send the results to a GPU API * @brief A common interfaces to the GPU where all objects relevant to it are present
* @note We opted for just supporting a single layer and display as it's what basically all games use and wasting cycles on it is pointless
*/ */
class GPU { class GPU {
private: private:
ANativeWindow *window; //!< The ANativeWindow to render to ANativeWindow *window; //!< The ANativeWindow that is presented to
const DeviceState &state; //!< The state of the device const DeviceState &state;
bool surfaceUpdate{}; //!< If the surface needs to be updated bool surfaceUpdate{}; //!< If the surface needs to be updated
u64 frameTimestamp{}; //!< The timestamp of the last frame being shown u64 frameTimestamp{}; //!< The timestamp of the last frame being shown
@ -38,19 +35,10 @@ namespace skyline::gpu {
gpfifo::GPFIFO gpfifo; gpfifo::GPFIFO gpfifo;
std::array<Syncpoint, constant::MaxHwSyncpointCount> syncpoints{}; std::array<Syncpoint, constant::MaxHwSyncpointCount> syncpoints{};
/**
* @param window The ANativeWindow to render to
*/
GPU(const DeviceState &state); GPU(const DeviceState &state);
/**
* @brief The destructor for the GPU class
*/
~GPU(); ~GPU();
/**
* @brief The loop that executes routine GPU functions
*/
void Loop(); void Loop();
}; };
} }

View File

@ -8,9 +8,6 @@
#define U32_OFFSET(regs, field) (offsetof(regs, field) / sizeof(u32)) #define U32_OFFSET(regs, field) (offsetof(regs, field) / sizeof(u32))
namespace skyline::gpu { namespace skyline::gpu {
/**
* @brief This enumerates the identifiers used to label a specific engine
*/
enum class EngineID { enum class EngineID {
Fermi2D = 0x902D, Fermi2D = 0x902D,
KeplerMemory = 0xA140, KeplerMemory = 0xA140,
@ -20,7 +17,7 @@ namespace skyline::gpu {
}; };
/** /**
* @brief This holds the parameters of a GPU engine method call * @brief The parameters of a GPU engine method call
*/ */
struct MethodParams { struct MethodParams {
u16 method; u16 method;

View File

@ -18,7 +18,6 @@ namespace skyline {
class GPFIFO : public Engine { class GPFIFO : public Engine {
private: private:
/** /**
* @brief This holds the GPFIFO engine's registers
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L65 * @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L65
*/ */
#pragma pack(push, 1) #pragma pack(push, 1)
@ -30,22 +29,22 @@ namespace skyline {
Release = 2, Release = 2,
AcqGeq = 4, AcqGeq = 4,
AcqAnd = 8, AcqAnd = 8,
Reduction = 16 Reduction = 16,
}; };
enum class SemaphoreAcquireSwitch : u8 { enum class SemaphoreAcquireSwitch : u8 {
Disabled = 0, Disabled = 0,
Enabled = 1 Enabled = 1,
}; };
enum class SemaphoreReleaseWfi : u8 { enum class SemaphoreReleaseWfi : u8 {
En = 0, En = 0,
Dis = 1 Dis = 1,
}; };
enum class SemaphoreReleaseSize : u8 { enum class SemaphoreReleaseSize : u8 {
SixteenBytes = 0, SixteenBytes = 0,
FourBytes = 1 FourBytes = 1,
}; };
enum class SemaphoreReduction : u8 { enum class SemaphoreReduction : u8 {
@ -56,39 +55,39 @@ namespace skyline {
Or = 4, Or = 4,
Add = 5, Add = 5,
Inc = 6, Inc = 6,
Dec = 7 Dec = 7,
}; };
enum class SemaphoreFormat : u8 { enum class SemaphoreFormat : u8 {
Signed = 0, Signed = 0,
Unsigned = 1 Unsigned = 1,
}; };
enum class MemOpTlbInvalidatePdb : u8 { enum class MemOpTlbInvalidatePdb : u8 {
One = 0, One = 0,
All = 1 All = 1,
}; };
enum class SyncpointOperation : u8 { enum class SyncpointOperation : u8 {
Wait = 0, Wait = 0,
Incr = 1 Incr = 1,
}; };
enum class SyncpointWaitSwitch : u8 { enum class SyncpointWaitSwitch : u8 {
Dis = 0, Dis = 0,
En = 1 En = 1,
}; };
enum class WfiScope : u8 { enum class WfiScope : u8 {
CurrentScgType = 0, CurrentScgType = 0,
All = 1 All = 1,
}; };
enum class YieldOp : u8 { enum class YieldOp : u8 {
Nop = 0, Nop = 0,
PbdmaTimeslice = 1, PbdmaTimeslice = 1,
RunlistTimeslice = 2, RunlistTimeslice = 2,
Tsg = 3 Tsg = 3,
}; };
struct { struct {

View File

@ -20,12 +20,12 @@ namespace skyline {
*/ */
class Maxwell3D : public Engine { class Maxwell3D : public Engine {
private: private:
std::array<size_t, 0x80> macroPositions{}; //!< This holds the positions of each individual macro in macro memory, there can be a maximum of 0x80 macros at any one time std::array<size_t, 0x80> macroPositions{}; //!< The positions of each individual macro in macro memory, there can be a maximum of 0x80 macros at any one time
struct { struct {
u32 index; u32 index;
std::vector<u32> arguments; std::vector<u32> arguments;
} macroInvocation{}; //!< This hold the index and arguments of the macro that is pending execution } macroInvocation{}; //!< Data for a macro that is pending execution
MacroInterpreter macroInterpreter; MacroInterpreter macroInterpreter;
@ -35,7 +35,6 @@ namespace skyline {
public: public:
/** /**
* @brief This holds the Maxwell3D engine's register space
* @url https://github.com/devkitPro/deko3d/blob/master/source/maxwell/engine_3d.def#L478 * @url https://github.com/devkitPro/deko3d/blob/master/source/maxwell/engine_3d.def#L478
*/ */
#pragma pack(push, 1) #pragma pack(push, 1)
@ -56,7 +55,7 @@ namespace skyline {
MethodTrack = 0, MethodTrack = 0,
MethodTrackWithFilter = 1, MethodTrackWithFilter = 1,
MethodPassthrough = 2, MethodPassthrough = 2,
MethodReplay = 3 MethodReplay = 3,
}; };
struct ViewportTransform { struct ViewportTransform {
@ -196,7 +195,7 @@ namespace skyline {
SubtractGL = 0x8007, SubtractGL = 0x8007,
ReverseSubtractGL = 0x8008, ReverseSubtractGL = 0x8008,
MinimumGL = 0x800A, MinimumGL = 0x800A,
MaximumGL = 0x800B MaximumGL = 0x800B,
}; };
enum class Factor : u32 { enum class Factor : u32 {
@ -293,7 +292,7 @@ namespace skyline {
Release = 0, Release = 0,
Acquire = 1, Acquire = 1,
Counter = 2, Counter = 2,
Trap = 3 Trap = 3,
}; };
enum class ReductionOp : u8 { enum class ReductionOp : u8 {
@ -348,7 +347,7 @@ namespace skyline {
TransformFeedbackOffset = 0x1A, TransformFeedbackOffset = 0x1A,
TessControlShaderInvocations = 0x1B, TessControlShaderInvocations = 0x1B,
TessEvaluationShaderInvocations = 0x1D, TessEvaluationShaderInvocations = 0x1D,
TessEvaluationShaderPrimitives = 0x1F TessEvaluationShaderPrimitives = 0x1F,
}; };
enum class StructureSize : u8 { enum class StructureSize : u8 {
@ -375,7 +374,7 @@ namespace skyline {
enum class CoordOrigin : u8 { enum class CoordOrigin : u8 {
LowerLeft = 0, LowerLeft = 0,
UpperLeft = 1 UpperLeft = 1,
}; };
struct { struct {
@ -559,10 +558,10 @@ namespace skyline {
static_assert(sizeof(Registers) == (constant::Maxwell3DRegisterCounter * sizeof(u32))); static_assert(sizeof(Registers) == (constant::Maxwell3DRegisterCounter * sizeof(u32)));
#pragma pack(pop) #pragma pack(pop)
Registers registers{}; //!< The Maxwell 3D register space Registers registers{};
Registers shadowRegisters{}; //!< The shadow registers, their function is controlled by the 'shadowRamControl' register Registers shadowRegisters{}; //!< The shadow registers, their function is controlled by the 'shadowRamControl' register
std::array<u32, 0x10000> macroCode{}; //!< This is used to store GPU macros, the 256kb size is from Ryujinx std::array<u32, 0x10000> macroCode{}; //!< This stores GPU macros, the 256kb size is from Ryujinx
Maxwell3D(const DeviceState &state); Maxwell3D(const DeviceState &state);

View File

@ -4,14 +4,13 @@
#pragma once #pragma once
#include <queue> #include <queue>
#include "engines/engine.h"
#include "engines/gpfifo.h" #include "engines/gpfifo.h"
#include "memory_manager.h" #include "memory_manager.h"
namespace skyline::gpu { namespace skyline::gpu {
namespace gpfifo { namespace gpfifo {
/** /**
* @brief This contains a single GPFIFO entry that is submitted through 'SubmitGpfifo' * @brief A GPFIFO entry as submitted through 'SubmitGpfifo'
* @url https://nvidia.github.io/open-gpu-doc/manuals/volta/gv100/dev_pbdma.ref.txt * @url https://nvidia.github.io/open-gpu-doc/manuals/volta/gv100/dev_pbdma.ref.txt
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L155 * @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L155
*/ */
@ -72,7 +71,7 @@ namespace skyline::gpu {
static_assert(sizeof(GpEntry) == sizeof(u64)); static_assert(sizeof(GpEntry) == sizeof(u64));
/** /**
* @brief This holds a single pushbuffer method header that describes a compressed method sequence * @brief A single pushbuffer method header that describes a compressed method sequence
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/manuals/volta/gv100/dev_ram.ref.txt#L850 * @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/manuals/volta/gv100/dev_ram.ref.txt#L850
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L179 * @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L179
*/ */
@ -84,7 +83,7 @@ namespace skyline::gpu {
Grp0SetSubDevMask = 1, Grp0SetSubDevMask = 1,
Grp0StoreSubDevMask = 2, Grp0StoreSubDevMask = 2,
Grp0UseSubDevMask = 3, Grp0UseSubDevMask = 3,
Grp2NonIncMethod = 0 Grp2NonIncMethod = 0,
}; };
enum class SecOp : u8 { enum class SecOp : u8 {
@ -95,7 +94,7 @@ namespace skyline::gpu {
ImmdDataMethod = 4, ImmdDataMethod = 4,
OneInc = 5, OneInc = 5,
Reserved6 = 6, Reserved6 = 6,
EndPbSegment = 7 EndPbSegment = 7,
}; };
u16 methodAddress : 12; u16 methodAddress : 12;
@ -128,7 +127,7 @@ namespace skyline::gpu {
class GPFIFO { class GPFIFO {
private: private:
/** /**
* @brief This is used to hold a pushbuffer's GPFIFO entry and contents, pushbuffers are made up of several 32-bit words * @brief A pushbuffer is a descriptor of tasks that need to be executed for a specific client
*/ */
struct PushBuffer { struct PushBuffer {
GpEntry gpEntry; GpEntry gpEntry;
@ -149,7 +148,7 @@ namespace skyline::gpu {
engine::GPFIFO gpfifoEngine; //!< The engine for processing GPFIFO method calls engine::GPFIFO gpfifoEngine; //!< The engine for processing GPFIFO method calls
std::array<std::shared_ptr<engine::Engine>, 8> subchannels; std::array<std::shared_ptr<engine::Engine>, 8> subchannels;
std::queue<PushBuffer> pushBufferQueue; std::queue<PushBuffer> pushBufferQueue;
skyline::Mutex pushBufferQueueLock; //!< This is used to lock pushbuffer queue insertions as the GPU runs on a seperate thread skyline::Mutex pushBufferQueueLock; //!< Synchronizes pushbuffer queue insertions as the GPU is multi-threaded
/** /**
* @brief Processes a pushbuffer segment, calling methods as needed * @brief Processes a pushbuffer segment, calling methods as needed
@ -157,7 +156,7 @@ namespace skyline::gpu {
void Process(const std::vector<u32> &segment); void Process(const std::vector<u32> &segment);
/** /**
* @brief This sends a method call to the GPU hardware * @brief Sends a method call to the GPU hardware
*/ */
void Send(MethodParams params); void Send(MethodParams params);

View File

@ -15,9 +15,6 @@ namespace skyline::gpu {
*/ */
class MacroInterpreter { class MacroInterpreter {
private: private:
/**
* @brief This holds a single macro opcode
*/
#pragma pack(push, 1) #pragma pack(push, 1)
union Opcode { union Opcode {
u32 raw; u32 raw;
@ -98,11 +95,10 @@ namespace skyline::gpu {
static_assert(sizeof(Opcode) == sizeof(u32)); static_assert(sizeof(Opcode) == sizeof(u32));
/** /**
* @brief This holds information about the Maxwell 3D method to be called in 'Send' * @brief Metadata about the Maxwell 3D method to be called in 'Send'
*/ */
union MethodAddress { union MethodAddress {
u32 raw; u32 raw;
struct { struct {
u16 address : 12; u16 address : 12;
u8 increment : 6; u8 increment : 6;

View File

@ -11,23 +11,23 @@ namespace skyline::gpu::vmm {
// Create the initial chunk that will be split to create new chunks // Create the initial chunk that will be split to create new chunks
ChunkDescriptor baseChunk(GpuAddressSpaceBase, GpuAddressSpaceSize, 0, ChunkState::Unmapped); ChunkDescriptor baseChunk(GpuAddressSpaceBase, GpuAddressSpaceSize, 0, ChunkState::Unmapped);
chunkList.push_back(baseChunk); chunks.push_back(baseChunk);
} }
std::optional<ChunkDescriptor> MemoryManager::FindChunk(u64 size, ChunkState state) { std::optional<ChunkDescriptor> MemoryManager::FindChunk(u64 size, ChunkState state) {
auto chunk{std::find_if(chunkList.begin(), chunkList.end(), [size, state](const ChunkDescriptor &chunk) -> bool { auto chunk{std::find_if(chunks.begin(), chunks.end(), [size, state](const ChunkDescriptor &chunk) -> bool {
return chunk.size > size && chunk.state == state; return chunk.size > size && chunk.state == state;
})}; })};
if (chunk != chunkList.end()) if (chunk != chunks.end())
return *chunk; return *chunk;
return std::nullopt; return std::nullopt;
} }
u64 MemoryManager::InsertChunk(const ChunkDescriptor &newChunk) { u64 MemoryManager::InsertChunk(const ChunkDescriptor &newChunk) {
auto chunkEnd{chunkList.end()}; auto chunkEnd{chunks.end()};
for (auto chunk{chunkList.begin()}; chunk != chunkEnd; chunk++) { for (auto chunk{chunks.begin()}; chunk != chunkEnd; chunk++) {
if (chunk->CanContain(newChunk)) { if (chunk->CanContain(newChunk)) {
auto oldChunk{*chunk}; auto oldChunk{*chunk};
u64 newSize{newChunk.address - chunk->address}; u64 newSize{newChunk.address - chunk->address};
@ -38,11 +38,11 @@ namespace skyline::gpu::vmm {
} else { } else {
chunk->size = newSize; chunk->size = newSize;
chunk = chunkList.insert(std::next(chunk), newChunk); chunk = chunks.insert(std::next(chunk), newChunk);
} }
if (extension) if (extension)
chunkList.insert(std::next(chunk), ChunkDescriptor(newChunk.address + newChunk.size, extension, (oldChunk.state == ChunkState::Mapped) ? (oldChunk.cpuAddress + newSize + newChunk.size) : 0, oldChunk.state)); chunks.insert(std::next(chunk), ChunkDescriptor(newChunk.address + newChunk.size, extension, (oldChunk.state == ChunkState::Mapped) ? (oldChunk.cpuAddress + newSize + newChunk.size) : 0, oldChunk.state));
return newChunk.address; return newChunk.address;
} else if (chunk->address + chunk->size > newChunk.address) { } else if (chunk->address + chunk->size > newChunk.address) {
@ -54,8 +54,8 @@ namespace skyline::gpu::vmm {
if (tailChunk->address + tailChunk->size >= newChunk.address + newChunk.size) if (tailChunk->address + tailChunk->size >= newChunk.address + newChunk.size)
break; break;
tailChunk = chunkList.erase(tailChunk); tailChunk = chunks.erase(tailChunk);
chunkEnd = chunkList.end(); chunkEnd = chunks.end();
} }
// The given chunk is too large to fit into existing chunks // The given chunk is too large to fit into existing chunks
@ -74,7 +74,7 @@ namespace skyline::gpu::vmm {
if (headChunk->size == 0) if (headChunk->size == 0)
*headChunk = newChunk; *headChunk = newChunk;
else else
chunkList.insert(std::next(headChunk), newChunk); chunks.insert(std::next(headChunk), newChunk);
return newChunk.address; return newChunk.address;
} }
@ -132,11 +132,11 @@ namespace skyline::gpu::vmm {
if (!util::IsAligned(address, constant::GpuPageSize)) if (!util::IsAligned(address, constant::GpuPageSize))
return false; return false;
auto chunk{std::find_if(chunkList.begin(), chunkList.end(), [address](const ChunkDescriptor &chunk) -> bool { auto chunk{std::find_if(chunks.begin(), chunks.end(), [address](const ChunkDescriptor &chunk) -> bool {
return chunk.address == address; return chunk.address == address;
})}; })};
if (chunk == chunkList.end()) if (chunk == chunks.end())
return false; return false;
chunk->state = ChunkState::Reserved; chunk->state = ChunkState::Reserved;
@ -146,11 +146,11 @@ namespace skyline::gpu::vmm {
} }
void MemoryManager::Read(u8 *destination, u64 address, u64 size) const { void MemoryManager::Read(u8 *destination, u64 address, u64 size) const {
auto chunk{std::upper_bound(chunkList.begin(), chunkList.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool { auto chunk{std::upper_bound(chunks.begin(), chunks.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
return address < chunk.address; return address < chunk.address;
})}; })};
if (chunk == chunkList.end() || chunk->state != ChunkState::Mapped) if (chunk == chunks.end() || chunk->state != ChunkState::Mapped)
throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size); throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
chunk--; chunk--;
@ -166,7 +166,7 @@ namespace skyline::gpu::vmm {
size -= readSize; size -= readSize;
if (size) { if (size) {
if (++chunk == chunkList.end() || chunk->state != ChunkState::Mapped) if (++chunk == chunks.end() || chunk->state != ChunkState::Mapped)
throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size); throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
readAddress = chunk->cpuAddress; readAddress = chunk->cpuAddress;
@ -176,11 +176,11 @@ namespace skyline::gpu::vmm {
} }
void MemoryManager::Write(u8 *source, u64 address, u64 size) const { void MemoryManager::Write(u8 *source, u64 address, u64 size) const {
auto chunk{std::upper_bound(chunkList.begin(), chunkList.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool { auto chunk{std::upper_bound(chunks.begin(), chunks.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
return address < chunk.address; return address < chunk.address;
})}; })};
if (chunk == chunkList.end() || chunk->state != ChunkState::Mapped) if (chunk == chunks.end() || chunk->state != ChunkState::Mapped)
throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size); throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
chunk--; chunk--;
@ -196,7 +196,7 @@ namespace skyline::gpu::vmm {
size -= writeSize; size -= writeSize;
if (size) { if (size) {
if (++chunk == chunkList.end() || chunk->state != ChunkState::Mapped) if (++chunk == chunks.end() || chunk->state != ChunkState::Mapped)
throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size); throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
writeAddress = chunk->cpuAddress; writeAddress = chunk->cpuAddress;

View File

@ -11,28 +11,21 @@ namespace skyline {
} }
namespace gpu::vmm { namespace gpu::vmm {
/**
* @brief This enumerates the possible states of a memory chunk
*/
enum ChunkState { enum ChunkState {
Unmapped, //!< The chunk is unmapped Unmapped, //!< The chunk is unmapped
Reserved, //!< The chunk is reserved Reserved, //!< The chunk is reserved
Mapped //!< The chunk is mapped and a CPU side address is present Mapped //!< The chunk is mapped and a CPU side address is present
}; };
/**
* @brief This describes a chunk of memory and all of it's individual attributes
*/
struct ChunkDescriptor { struct ChunkDescriptor {
u64 address; //!< The address of the chunk in the GPU address space u64 address; //!< The address of the chunk in the GPU address space
u64 size; //!< The size of the chunk in bytes u64 size; //!< The size of the chunk in bytes
u64 cpuAddress; //!< The address of the chunk in the CPU address space (if mapped) u64 cpuAddress; //!< The address of the chunk in the CPU address space (if mapped)
ChunkState state; //!< The state of the chunk ChunkState state;
ChunkDescriptor(u64 address, u64 size, u64 cpuAddress, ChunkState state) : address(address), size(size), cpuAddress(cpuAddress), state(state) {} ChunkDescriptor(u64 address, u64 size, u64 cpuAddress, ChunkState state) : address(address), size(size), cpuAddress(cpuAddress), state(state) {}
/** /**
* @param chunk The chunk to check
* @return If the given chunk can be contained wholly within this chunk * @return If the given chunk can be contained wholly within this chunk
*/ */
inline bool CanContain(const ChunkDescriptor &chunk) { inline bool CanContain(const ChunkDescriptor &chunk) {
@ -46,9 +39,10 @@ namespace skyline {
class MemoryManager { class MemoryManager {
private: private:
const DeviceState &state; const DeviceState &state;
std::vector<ChunkDescriptor> chunks;
/** /**
* @brief This finds a chunk of the specified type in the GPU address space that is larger than the given size * @brief Finds a chunk of the specified type in the GPU address space that is larger than the given size
* @param size The minimum size of the chunk to find * @param size The minimum size of the chunk to find
* @param state The state desired state of the chunk to find * @param state The state desired state of the chunk to find
* @return The first unmapped chunk in the GPU address space that fits the requested size * @return The first unmapped chunk in the GPU address space that fits the requested size
@ -56,7 +50,7 @@ namespace skyline {
std::optional<ChunkDescriptor> FindChunk(u64 size, ChunkState state); std::optional<ChunkDescriptor> FindChunk(u64 size, ChunkState state);
/** /**
* @brief This inserts a chunk into the chunk list, resizing and splitting as necessary * @brief Inserts a chunk into the chunk list, resizing and splitting as necessary
* @param newChunk The chunk to insert * @param newChunk The chunk to insert
* @return The base virtual GPU address of the inserted chunk * @return The base virtual GPU address of the inserted chunk
*/ */
@ -64,17 +58,16 @@ namespace skyline {
public: public:
MemoryManager(const DeviceState &state); MemoryManager(const DeviceState &state);
std::vector<ChunkDescriptor> chunkList; //!< This vector holds all the chunk descriptors
/** /**
* @brief This reserves a region of the GPU address space so it will not be chosen automatically when mapping * @brief Reserves a region of the GPU address space so it will not be chosen automatically when mapping
* @param size The size of the region to reserve * @param size The size of the region to reserve
* @return The virtual GPU base address of the region base * @return The virtual GPU base address of the region base
*/ */
u64 ReserveSpace(u64 size); u64 ReserveSpace(u64 size);
/** /**
* @brief This reserves a fixed region of the GPU address space so it will not be chosen automatically when mapping * @brief Reserves a fixed region of the GPU address space so it will not be chosen automatically when mapping
* @param address The virtual base address of the region to allocate * @param address The virtual base address of the region to allocate
* @param size The size of the region to allocate * @param size The size of the region to allocate
* @return The virtual address of the region base * @return The virtual address of the region base
@ -82,7 +75,7 @@ namespace skyline {
u64 ReserveFixed(u64 address, u64 size); u64 ReserveFixed(u64 address, u64 size);
/** /**
* @brief This maps a physical CPU memory region to an automatically chosen virtual memory region * @brief Maps a physical CPU memory region to an automatically chosen virtual memory region
* @param address The physical CPU address of the region to be mapped into the GPU's address space * @param address The physical CPU address of the region to be mapped into the GPU's address space
* @param size The size of the region to map * @param size The size of the region to map
* @return The virtual address of the region base * @return The virtual address of the region base
@ -90,7 +83,7 @@ namespace skyline {
u64 MapAllocate(u64 address, u64 size); u64 MapAllocate(u64 address, u64 size);
/** /**
* @brief This maps a physical CPU memory region to a fixed virtual memory region * @brief Maps a physical CPU memory region to a fixed virtual memory region
* @param address The target virtual address of the region * @param address The target virtual address of the region
* @param cpuAddress The physical CPU address of the region to be mapped into the GPU's address space * @param cpuAddress The physical CPU address of the region to be mapped into the GPU's address space
* @param size The size of the region to map * @param size The size of the region to map
@ -99,7 +92,7 @@ namespace skyline {
u64 MapFixed(u64 address, u64 cpuAddress, u64 size); u64 MapFixed(u64 address, u64 cpuAddress, u64 size);
/** /**
* @brief This unmaps the chunk that starts at 'offset' from the GPU address space * @brief Unmaps the chunk that starts at 'offset' from the GPU address space
* @return Whether the operation succeeded * @return Whether the operation succeeded
*/ */
bool Unmap(u64 address); bool Unmap(u64 address);
@ -108,7 +101,6 @@ namespace skyline {
/** /**
* @brief Reads in a span from a region of the GPU virtual address space * @brief Reads in a span from a region of the GPU virtual address space
* @tparam T The type of span to read into
*/ */
template<typename T> template<typename T>
void Read(span<T> destination, u64 address) const { void Read(span<T> destination, u64 address) const {
@ -138,7 +130,6 @@ namespace skyline {
/** /**
* @brief Reads in an object from a region of the GPU virtual address space * @brief Reads in an object from a region of the GPU virtual address space
* @tparam T The type of object to return
*/ */
template<typename T> template<typename T>
void Write(T source, u64 address) const { void Write(T source, u64 address) const {

View File

@ -16,15 +16,12 @@ namespace skyline {
*/ */
class Syncpoint { class Syncpoint {
private: private:
/**
* @brief This holds information about a single waiter on a syncpoint
*/
struct Waiter { struct Waiter {
u32 threshold; u32 threshold; //!< The syncpoint value to wait on to be reached
std::function<void()> callback; std::function<void()> callback; //!< The callback to do after the wait has ended
}; };
Mutex waiterLock; //!< Locks insertions and deletions of waiters Mutex waiterLock; //!< Synchronizes insertions and deletions of waiters
std::map<u64, Waiter> waiterMap; std::map<u64, Waiter> waiterMap;
u64 nextWaiterId{1}; u64 nextWaiterId{1};

View File

@ -9,6 +9,22 @@
namespace skyline::gpu { namespace skyline::gpu {
GuestTexture::GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tiling, texture::TileConfig layout) : state(state), address(address), dimensions(dimensions), format(format), tileMode(tiling), tileConfig(layout) {} GuestTexture::GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tiling, texture::TileConfig layout) : state(state), address(address), dimensions(dimensions), format(format), tileMode(tiling), tileConfig(layout) {}
std::shared_ptr<Texture> GuestTexture::InitializeTexture(std::optional<texture::Format> format, std::optional<texture::Dimensions> dimensions, texture::Swizzle swizzle) {
if (!host.expired())
throw exception("Trying to create multiple Texture objects from a single GuestTexture");
auto sharedHost{std::make_shared<Texture>(state, shared_from_this(), dimensions ? *dimensions : this->dimensions, format ? *format : this->format, swizzle)};
host = sharedHost;
return sharedHost;
}
std::shared_ptr<PresentationTexture> GuestTexture::InitializePresentationTexture() {
if (!host.expired())
throw exception("Trying to create multiple PresentationTexture objects from a single GuestTexture");
auto presentation{std::make_shared<PresentationTexture>(state, shared_from_this(), dimensions, format)};
host = std::static_pointer_cast<Texture>(presentation);
return presentation;
}
Texture::Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle) : state(state), guest(guest), dimensions(dimensions), format(format), swizzle(swizzle) { Texture::Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle) : state(state), guest(guest), dimensions(dimensions), format(format), swizzle(swizzle) {
SynchronizeHost(); SynchronizeHost();
} }

View File

@ -12,13 +12,10 @@ namespace skyline {
} }
namespace gpu { namespace gpu {
namespace texture { namespace texture {
/*
* @brief This is used to hold the dimensions of a surface
*/
struct Dimensions { struct Dimensions {
u32 width; //!< The width of the surface u32 width;
u32 height; //!< The height of the surface u32 height;
u32 depth; //!< The depth of the surface u32 depth;
constexpr Dimensions() : width(0), height(0), depth(0) {} constexpr Dimensions() : width(0), height(0), depth(0) {}
@ -26,34 +23,25 @@ namespace skyline {
constexpr Dimensions(u32 width, u32 height, u32 depth) : width(width), height(height), depth(depth) {} constexpr Dimensions(u32 width, u32 height, u32 depth) : width(width), height(height), depth(depth) {}
/** constexpr bool operator==(const Dimensions &dimensions) {
* @return If the specified dimension is equal to this one
*/
constexpr inline bool operator==(const Dimensions &dimensions) {
return (width == dimensions.width) && (height == dimensions.height) && (depth == dimensions.depth); return (width == dimensions.width) && (height == dimensions.height) && (depth == dimensions.depth);
} }
/** constexpr bool operator!=(const Dimensions &dimensions) {
* @return If the specified dimension is not equal to this one
*/
constexpr inline bool operator!=(const Dimensions &dimensions) {
return (width != dimensions.width) || (height != dimensions.height) || (depth != dimensions.depth); return (width != dimensions.width) || (height != dimensions.height) || (depth != dimensions.depth);
} }
}; };
/** /**
* @brief This is used to hold the attributes of a texture format * @note Blocks refers to the atomic unit of a compressed format (IE: The minimum amount of data that can be decompressed)
*/ */
struct Format { struct Format {
u8 bpb; //!< Bytes Per Block, this is to accommodate compressed formats u8 bpb; //!< Bytes Per Block, this is used instead of bytes per pixel as that might not be a whole number for compressed formats
u16 blockHeight; //!< The height of a single block u16 blockHeight; //!< The height of a block in pixels
u16 blockWidth; //!< The width of a single block u16 blockWidth; //!< The width of a block in pixels
vk::Format vkFormat; //!< The underlying Vulkan type of the format vk::Format vkFormat;
/** constexpr bool IsCompressed() {
* @return If this is a compressed texture format or not
*/
inline constexpr bool IsCompressed() {
return (blockHeight != 1) || (blockWidth != 1); return (blockHeight != 1) || (blockWidth != 1);
} }
@ -63,42 +51,32 @@ namespace skyline {
* @param depth The depth of the texture in layers * @param depth The depth of the texture in layers
* @return The size of the texture in bytes * @return The size of the texture in bytes
*/ */
inline constexpr size_t GetSize(u32 width, u32 height, u32 depth = 1) { constexpr size_t GetSize(u32 width, u32 height, u32 depth = 1) {
return (((width / blockWidth) * (height / blockHeight)) * bpb) * depth; return (((width / blockWidth) * (height / blockHeight)) * bpb) * depth;
} }
/** constexpr size_t GetSize(Dimensions dimensions) {
* @param dimensions The dimensions of a texture
* @return The size of the texture in bytes
*/
inline constexpr size_t GetSize(Dimensions dimensions) {
return GetSize(dimensions.width, dimensions.height, dimensions.depth); return GetSize(dimensions.width, dimensions.height, dimensions.depth);
} }
/** constexpr bool operator==(const Format &format) {
* @return If the specified format is equal to this one
*/
inline constexpr bool operator==(const Format &format) {
return vkFormat == format.vkFormat; return vkFormat == format.vkFormat;
} }
/** constexpr bool operator!=(const Format &format) {
* @return If the specified format is not equal to this one
*/
inline constexpr bool operator!=(const Format &format) {
return vkFormat != format.vkFormat; return vkFormat != format.vkFormat;
} }
/** /**
* @return If this format is actually valid or not * @return If this format is actually valid or not
*/ */
inline constexpr operator bool() { constexpr operator bool() {
return bpb; return bpb;
} }
}; };
/** /**
* @brief This describes the linearity of a texture. Refer to Chapter 20.1 of the Tegra X1 TRM for information. * @brief The linearity of a texture, refer to Chapter 20.1 of the Tegra X1 TRM for information
*/ */
enum class TileMode { enum class TileMode {
Linear, //!< This is a purely linear texture Linear, //!< This is a purely linear texture
@ -107,7 +85,7 @@ namespace skyline {
}; };
/** /**
* @brief This holds the parameters of the tiling mode, covered in Table 76 in the Tegra X1 TRM * @brief The parameters of the tiling mode, covered in Table 76 in the Tegra X1 TRM
*/ */
union TileConfig { union TileConfig {
struct { struct {
@ -118,9 +96,6 @@ namespace skyline {
u32 pitch; //!< The pitch of the texture if it's pitch linear u32 pitch; //!< The pitch of the texture if it's pitch linear
}; };
/**
* @brief This enumerates all of the channel swizzle options
*/
enum class SwizzleChannel { enum class SwizzleChannel {
Zero, //!< Write 0 to the channel Zero, //!< Write 0 to the channel
One, //!< Write 1 to the channel One, //!< Write 1 to the channel
@ -130,9 +105,6 @@ namespace skyline {
Alpha, //!< Alpha channel Alpha, //!< Alpha channel
}; };
/**
* @brief This holds all of the texture swizzles on each color channel
*/
struct Swizzle { struct Swizzle {
SwizzleChannel red{SwizzleChannel::Red}; //!< Swizzle for the red channel SwizzleChannel red{SwizzleChannel::Red}; //!< Swizzle for the red channel
SwizzleChannel green{SwizzleChannel::Green}; //!< Swizzle for the green channel SwizzleChannel green{SwizzleChannel::Green}; //!< Swizzle for the green channel
@ -145,109 +117,95 @@ namespace skyline {
class PresentationTexture; class PresentationTexture;
/** /**
* @brief This class is used to hold metadata about a guest texture and can be used to create a host Texture object * @brief A texture present in guest memory, it can be used to create a corresponding Texture object for usage on the host
*/ */
class GuestTexture : public std::enable_shared_from_this<GuestTexture> { class GuestTexture : public std::enable_shared_from_this<GuestTexture> {
private: private:
const DeviceState &state; //!< The state of the device const DeviceState &state;
public: public:
u64 address; //!< The address of the texture in guest memory u64 address; //!< The address of the texture in guest memory
std::shared_ptr<Texture> host; //!< The corresponding host texture object std::weak_ptr<Texture> host; //!< A host texture (if any) that was created from this guest texture
texture::Dimensions dimensions; //!< The dimensions of the texture texture::Dimensions dimensions;
texture::Format format; //!< The format of the texture texture::Format format;
texture::TileMode tileMode; //!< The tiling mode of the texture texture::TileMode tileMode;
texture::TileConfig tileConfig; //!< The tiling configuration of the texture texture::TileConfig tileConfig;
GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tileMode = texture::TileMode::Linear, texture::TileConfig tileConfig = {}); GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tileMode = texture::TileMode::Linear, texture::TileConfig tileConfig = {});
inline constexpr size_t Size() { constexpr size_t Size() {
return format.GetSize(dimensions); return format.GetSize(dimensions);
} }
/** /**
* @brief This creates a corresponding host texture object for this guest texture * @brief Creates a corresponding host texture object for this guest texture
* @param format The format of the host texture (Defaults to the format of the guest texture) * @param format The format of the host texture (Defaults to the format of the guest texture)
* @param dimensions The dimensions of the host texture (Defaults to the dimensions of the host texture) * @param dimensions The dimensions of the host texture (Defaults to the dimensions of the host texture)
* @param swizzle The channel swizzle of the host texture (Defaults to no channel swizzling) * @param swizzle The channel swizzle of the host texture (Defaults to no channel swizzling)
* @return A shared pointer to the host texture object * @return A shared pointer to the host texture object
* @note There can only be one host texture for a corresponding guest texture * @note There can only be one host texture for a corresponding guest texture
*/ */
std::shared_ptr<Texture> InitializeTexture(std::optional<texture::Format> format = std::nullopt, std::optional<texture::Dimensions> dimensions = std::nullopt, texture::Swizzle swizzle = {}) { std::shared_ptr<Texture> InitializeTexture(std::optional<texture::Format> format = std::nullopt, std::optional<texture::Dimensions> dimensions = std::nullopt, texture::Swizzle swizzle = {});
if (host)
throw exception("Trying to create multiple Texture objects from a single GuestTexture");
host = std::make_shared<Texture>(state, shared_from_this(), dimensions ? *dimensions : this->dimensions, format ? *format : this->format, swizzle);
return host;
}
protected: protected:
std::shared_ptr<PresentationTexture> InitializePresentationTexture() { std::shared_ptr<PresentationTexture> InitializePresentationTexture();
if (host)
throw exception("Trying to create multiple PresentationTexture objects from a single GuestTexture");
auto presentation{std::make_shared<PresentationTexture>(state, shared_from_this(), dimensions, format)};
host = std::static_pointer_cast<Texture>(presentation);
return presentation;
}
friend service::hosbinder::GraphicBufferProducer; friend service::hosbinder::GraphicBufferProducer;
}; };
/** /**
* @brief This class is used to store a texture which is backed by host objects * @brief A texture which is backed by host constructs while being synchronized with the underlying guest texture
*/ */
class Texture { class Texture {
private: private:
const DeviceState &state; //!< The state of the device const DeviceState &state;
public: public:
std::vector<u8> backing; //!< The object that holds a host copy of the guest texture (Will be replaced with a vk::Image) std::vector<u8> backing; //!< The object that holds a host copy of the guest texture (Will be replaced with a vk::Image)
std::shared_ptr<GuestTexture> guest; //!< The corresponding guest texture object std::shared_ptr<GuestTexture> guest; //!< The guest texture from which this was created, it is required for syncing
texture::Dimensions dimensions; //!< The dimensions of the texture texture::Dimensions dimensions;
texture::Format format; //!< The format of the host texture texture::Format format;
texture::Swizzle swizzle; //!< The swizzle of the host texture texture::Swizzle swizzle;
public: public:
Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle); Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle);
public: public:
/** /**
* @brief This convert this texture to the specified tiling mode * @brief Convert this texture to the specified tiling mode
* @param tileMode The tiling mode to convert it to * @param tileMode The tiling mode to convert it to
* @param tileConfig The configuration for the tiling mode (Can be default argument for Linear) * @param tileConfig The configuration for the tiling mode (Can be default argument for Linear)
*/ */
void ConvertTileMode(texture::TileMode tileMode, texture::TileConfig tileConfig = {}); void ConvertTileMode(texture::TileMode tileMode, texture::TileConfig tileConfig = {});
/** /**
* @brief This sets the texture dimensions to the specified ones (As long as they are within the GuestTexture's range) * @brief Converts the texture dimensions to the specified ones (As long as they are within the GuestTexture's range)
* @param dimensions The dimensions to adjust the texture to
*/ */
void SetDimensions(texture::Dimensions dimensions); void SetDimensions(texture::Dimensions dimensions);
/** /**
* @brief This sets the format to the specified one * @brief Converts the texture to have the specified format
* @param format The format to change the texture to
*/ */
void SetFormat(texture::Format format); void SetFormat(texture::Format format);
/** /**
* @brief This sets the channel swizzle to the specified one * @brief Change the texture channel swizzle to the specified one
* @param swizzle The channel swizzle to the change the texture to
*/ */
void SetSwizzle(texture::Swizzle swizzle); void SetSwizzle(texture::Swizzle swizzle);
/** /**
* @brief This synchronizes the host texture with the guest after it has been modified * @brief Synchronizes the host texture with the guest after it has been modified
*/ */
void SynchronizeHost(); void SynchronizeHost();
/** /**
* @brief This synchronizes the guest texture with the host texture after it has been modified * @brief Synchronizes the guest texture with the host texture after it has been modified
*/ */
void SynchronizeGuest(); void SynchronizeGuest();
}; };
/** /**
* @brief This class is used to hold a texture object alongside a release callback used for display presentation * @brief A texture object alongside a release callback used for display presentation
*/ */
class PresentationTexture : public Texture { class PresentationTexture : public Texture {
public: public:

View File

@ -11,7 +11,7 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The Input class manages translating host input to guest input * @brief The Input class manages components responsible for translating host input to guest input
*/ */
class Input { class Input {
private: private:

View File

@ -16,7 +16,7 @@ namespace skyline::input {
}; };
/** /**
* @brief This class is used to manage all NPad devices and their allocations to Player objects * @brief All NPad devices and their allocations to Player objects are managed by this class
*/ */
class NpadManager { class NpadManager {
private: private:
@ -26,11 +26,11 @@ namespace skyline::input {
friend NpadDevice; friend NpadDevice;
/** /**
* @brief This translates an NPad's ID into it's index in the array * @brief Translates an NPad's ID into it's index in the array
* @param id The ID of the NPad to translate * @param id The ID of the NPad to translate
* @return The corresponding index of the NPad in the array * @return The corresponding index of the NPad in the array
*/ */
static constexpr inline size_t Translate(NpadId id) { static constexpr size_t Translate(NpadId id) {
switch (id) { switch (id) {
case NpadId::Handheld: case NpadId::Handheld:
return 8; return 8;
@ -45,7 +45,7 @@ namespace skyline::input {
std::recursive_mutex mutex; //!< This mutex must be locked before any modifications to class members std::recursive_mutex mutex; //!< This mutex must be locked before any modifications to class members
std::array<NpadDevice, constant::NpadCount> npads; std::array<NpadDevice, constant::NpadCount> npads;
std::array<GuestController, constant::ControllerCount> controllers; std::array<GuestController, constant::ControllerCount> controllers;
std::vector<NpadId> supportedIds; //!< The NpadId(s) that are supported by the application std::vector<NpadId> supportedIds; //!< The NPadId(s) that are supported by the application
NpadStyleSet styles; //!< The styles that are supported by the application NpadStyleSet styles; //!< The styles that are supported by the application
NpadJoyOrientation orientation{}; //!< The orientation all of Joy-Cons are in (This affects stick transformation for them) NpadJoyOrientation orientation{}; //!< The orientation all of Joy-Cons are in (This affects stick transformation for them)
@ -57,30 +57,30 @@ namespace skyline::input {
/** /**
* @return A reference to the NPad with the specified ID * @return A reference to the NPad with the specified ID
*/ */
constexpr inline NpadDevice &at(NpadId id) { constexpr NpadDevice &at(NpadId id) {
return npads.at(Translate(id)); return npads.at(Translate(id));
} }
/** /**
* @return A reference to the NPad with the specified ID * @return A reference to the NPad with the specified ID
*/ */
constexpr inline NpadDevice &operator[](NpadId id) noexcept { constexpr NpadDevice &operator[](NpadId id) noexcept {
return npads.operator[](Translate(id)); return npads.operator[](Translate(id));
} }
/** /**
* @brief This deduces all the mappings from guest controllers -> players based on the configuration supplied by HID services and available controllers * @brief Deduces all the mappings from guest controllers -> players based on the configuration supplied by HID services and available controllers
* @note If any class members were edited, the mutex shouldn't be released till this is called * @note If any class members were edited, the mutex shouldn't be released till this is called
*/ */
void Update(); void Update();
/** /**
* @brief This activates the mapping between guest controllers -> players, a call to this is required for function * @brief Activates the mapping between guest controllers -> players, a call to this is required for function
*/ */
void Activate(); void Activate();
/** /**
* @brief This disables any activate mappings from guest controllers -> players till Activate has been called * @brief Disables any activate mappings from guest controllers -> players till Activate has been called
*/ */
void Deactivate(); void Deactivate();
}; };

View File

@ -14,7 +14,7 @@ namespace skyline::constant {
namespace skyline::input { namespace skyline::input {
/** /**
* @brief This enumerates the orientations the Joy-Con(s) can be held in * @brief The orientations the Joy-Con(s) can be held in
*/ */
enum class NpadJoyOrientation : i64 { enum class NpadJoyOrientation : i64 {
Vertical = 0, Vertical = 0,
@ -22,7 +22,7 @@ namespace skyline::input {
}; };
/** /**
* @brief A union of all the NPad styles (https://switchbrew.org/wiki/HID_services#NpadStyleTag) * @url https://switchbrew.org/wiki/HID_services#NpadStyleTag
*/ */
union NpadStyleSet { union NpadStyleSet {
u32 raw; u32 raw;
@ -41,9 +41,6 @@ namespace skyline::input {
}; };
static_assert(sizeof(NpadStyleSet) == 0x4); static_assert(sizeof(NpadStyleSet) == 0x4);
/**
* @brief This enumerates all of the axis on NPads
*/
enum class NpadAxisId { enum class NpadAxisId {
LX, //!< Left Stick X LX, //!< Left Stick X
LY, //!< Left Stick Y LY, //!< Left Stick Y
@ -52,7 +49,7 @@ namespace skyline::input {
}; };
/** /**
* @brief This enumerates all the possible IDs for an NPad (https://switchbrew.org/wiki/HID_services#NpadIdType) * @url https://switchbrew.org/wiki/HID_services#NpadIdType
*/ */
enum class NpadId : u32 { enum class NpadId : u32 {
Player1 = 0x0, Player1 = 0x0,
@ -114,7 +111,7 @@ namespace skyline::input {
class NpadManager; class NpadManager;
/** /**
* @brief This class abstracts a single NPad device that controls it's own state and shared memory section * @brief An easy to use interface for a NPad which abstracts away the complicated details
*/ */
class NpadDevice { class NpadDevice {
private: private:
@ -124,7 +121,7 @@ namespace skyline::input {
u64 globalTimestamp{}; //!< An incrementing timestamp that's common across all sections u64 globalTimestamp{}; //!< An incrementing timestamp that's common across all sections
/** /**
* @brief This updates the headers and creates a new entry in HID Shared Memory * @brief Updates the headers and creates a new entry in HID Shared Memory
* @param info The controller info of the NPad that needs to be updated * @param info The controller info of the NPad that needs to be updated
* @return The next entry that has been created with values from the last entry * @return The next entry that has been created with values from the last entry
*/ */
@ -147,41 +144,33 @@ namespace skyline::input {
NpadDevice(NpadManager &manager, NpadSection &section, NpadId id); NpadDevice(NpadManager &manager, NpadSection &section, NpadId id);
/**
* @brief This sets a Joy-Con's Assignment Mode
* @param assignment The assignment mode to set this controller to
*/
inline void SetAssignment(NpadJoyAssignment assignment) { inline void SetAssignment(NpadJoyAssignment assignment) {
section.header.assignment = assignment; section.header.assignment = assignment;
} }
/**
* @return The assignment mode of this Joy-Con
*/
inline NpadJoyAssignment GetAssignment() { inline NpadJoyAssignment GetAssignment() {
return section.header.assignment; return section.header.assignment;
} }
/** /**
* @brief This connects this controller to the guest * @brief Connects this controller to the guest
* @param newType The type of controller to connect as
*/ */
void Connect(NpadControllerType newType); void Connect(NpadControllerType newType);
/** /**
* @brief This disconnects this controller from the guest * @brief Disconnects this controller from the guest
*/ */
void Disconnect(); void Disconnect();
/** /**
* @brief This changes the state of buttons to the specified state * @brief Changes the state of buttons to the specified state
* @param mask A bit-field mask of all the buttons to change * @param mask A bit-field mask of all the buttons to change
* @param pressed If the buttons were pressed or released * @param pressed If the buttons were pressed or released
*/ */
void SetButtonState(NpadButton mask, bool pressed); void SetButtonState(NpadButton mask, bool pressed);
/** /**
* @brief This sets the value of an axis to the specified value * @brief Sets the value of an axis to the specified value
* @param axis The axis to set the value of * @param axis The axis to set the value of
* @param value The value to set * @param value The value to set
*/ */

View File

@ -7,7 +7,7 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The structure of an entry for BasicXpad (https://switchbrew.org/wiki/HID_Shared_Memory#BasicXpadState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#BasicXpadState
*/ */
struct BasicXpadState { struct BasicXpadState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +16,7 @@ namespace skyline::input {
static_assert(sizeof(BasicXpadState) == 0x28); static_assert(sizeof(BasicXpadState) == 0x28);
/** /**
* @brief The structure of the BasicXpad section (https://switchbrew.org/wiki/HID_Shared_Memory#BasicXpad) * @url https://switchbrew.org/wiki/HID_Shared_Memory#BasicXpad
*/ */
struct BasicXpadSection { struct BasicXpadSection {
CommonHeader header; CommonHeader header;

View File

@ -7,7 +7,9 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The state structure for all Button sections (HomeButton, SleepButton, CaptureButton) * @url https://switchbrew.org/wiki/HID_Shared_Memory#HomeButtonState
* @url https://switchbrew.org/wiki/HID_Shared_Memory#SleepButtonState
* @url https://switchbrew.org/wiki/HID_Shared_Memory#CaptureButtonState
*/ */
struct ButtonState { struct ButtonState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +18,9 @@ namespace skyline::input {
static_assert(sizeof(ButtonState) == 0x18); static_assert(sizeof(ButtonState) == 0x18);
/** /**
* @brief The section structure for all Button sections (HomeButton, SleepButton, CaptureButton) * @url https://switchbrew.org/wiki/HID_Shared_Memory#HomeButton
* @url https://switchbrew.org/wiki/HID_Shared_Memory#SleepButton
* @url https://switchbrew.org/wiki/HID_Shared_Memory#CaptureButton
*/ */
struct ButtonSection { struct ButtonSection {
CommonHeader header; CommonHeader header;

View File

@ -7,7 +7,8 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The structure of the ConsoleSixAxisSensor (SevenSixAxisSensor) section (https://switchbrew.org/wiki/HID_Shared_Memory#ConsoleSixAxisSensor) * @url https://switchbrew.org/wiki/HID_Shared_Memory#ConsoleSixAxisSensor
* @note Referred to as SevenSixAxisSensor in HID Services
* @note This is seemingly used to calibrate the gyroscope bias values over time * @note This is seemingly used to calibrate the gyroscope bias values over time
*/ */
struct ConsoleSixAxisSensorSection { struct ConsoleSixAxisSensorSection {

View File

@ -7,7 +7,7 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The structure of an entry for DebugPad (https://switchbrew.org/wiki/HID_Shared_Memory#DebugPadState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#DebugPadState
*/ */
struct DebugPadState { struct DebugPadState {
u64 timestamp; //!< The total timestamp in ticks u64 timestamp; //!< The total timestamp in ticks
@ -16,7 +16,7 @@ namespace skyline::input {
static_assert(sizeof(DebugPadState) == 0x28); static_assert(sizeof(DebugPadState) == 0x28);
/** /**
* @brief The structure of the DebugPad section (https://switchbrew.org/wiki/HID_Shared_Memory#DebugPad) * @url https://switchbrew.org/wiki/HID_Shared_Memory#DebugPad
*/ */
struct DebugPadSection { struct DebugPadSection {
CommonHeader header; CommonHeader header;

View File

@ -7,7 +7,7 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The structure of an entry for Gesture (https://switchbrew.org/wiki/HID_Shared_Memory#GestureState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#GestureState
*/ */
struct GestureState { struct GestureState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +16,7 @@ namespace skyline::input {
static_assert(sizeof(GestureState) == 0x68); static_assert(sizeof(GestureState) == 0x68);
/** /**
* @brief The structure of the Gesture section (https://switchbrew.org/wiki/HID_Shared_Memory#Gesture) * @url https://switchbrew.org/wiki/HID_Shared_Memory#Gesture
*/ */
struct GestureSection { struct GestureSection {
CommonHeader header; CommonHeader header;

View File

@ -7,7 +7,7 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The structure of an entry for InputDetector (https://switchbrew.org/wiki/HID_Shared_Memory#InputDetectorState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#InputDetectorState
*/ */
struct InputDetectorState { struct InputDetectorState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +16,7 @@ namespace skyline::input {
static_assert(sizeof(InputDetectorState) == 0x18); static_assert(sizeof(InputDetectorState) == 0x18);
/** /**
* @brief The structure of the InputDetector section (https://switchbrew.org/wiki/HID_Shared_Memory#InputDetector) * @url https://switchbrew.org/wiki/HID_Shared_Memory#InputDetector
*/ */
struct InputDetectorSection { struct InputDetectorSection {
CommonHeader header; CommonHeader header;

View File

@ -6,9 +6,6 @@
#include "common.h" #include "common.h"
namespace skyline::input { namespace skyline::input {
/**
* @brief This enumerates all the modifier keys that can be used
*/
union ModifierKey { union ModifierKey {
u64 raw; u64 raw;
struct { struct {
@ -27,7 +24,7 @@ namespace skyline::input {
}; };
/** /**
* @brief The structure of an entry for Keyboard (https://switchbrew.org/wiki/HID_Shared_Memory#KeyboardState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#KeyboardState
*/ */
struct KeyboardState { struct KeyboardState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -39,7 +36,7 @@ namespace skyline::input {
static_assert(sizeof(KeyboardState) == 0x38); static_assert(sizeof(KeyboardState) == 0x38);
/** /**
* @brief The structure of the Keyboard section (https://switchbrew.org/wiki/HID_Shared_Memory#Keyboard) * @url https://switchbrew.org/wiki/HID_Shared_Memory#Keyboard
*/ */
struct KeyboardSection { struct KeyboardSection {
CommonHeader header; CommonHeader header;

View File

@ -7,7 +7,7 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief The structure of an entry for Mouse (https://switchbrew.org/wiki/HID_Shared_Memory#MouseState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#MouseState
*/ */
struct MouseState { struct MouseState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -27,7 +27,7 @@ namespace skyline::input {
static_assert(sizeof(MouseState) == 0x30); static_assert(sizeof(MouseState) == 0x30);
/** /**
* @brief The structure of the Mouse section (https://switchbrew.org/wiki/HID_Shared_Memory#Mouse) * @url https://switchbrew.org/wiki/HID_Shared_Memory#Mouse
*/ */
struct MouseSection { struct MouseSection {
CommonHeader header; CommonHeader header;

View File

@ -7,9 +7,6 @@
namespace skyline::input { namespace skyline::input {
// @fmt:off // @fmt:off
/**
* @brief This enumerates all of the types of an NPad controller
*/
enum class NpadControllerType : u32 { enum class NpadControllerType : u32 {
None = 0, None = 0,
ProController = 0b1, ProController = 0b1,
@ -20,26 +17,17 @@ namespace skyline::input {
}; };
// @fmt:on // @fmt:on
/**
* @brief This enumerates all the possible assignments of the Joy-Con(s)
*/
enum class NpadJoyAssignment : u32 { enum class NpadJoyAssignment : u32 {
Dual = 0, //!< Dual Joy-Cons (A pair of Joy-Cons are combined into a single player, if possible) Dual = 0, //!< Dual Joy-Cons (A pair of Joy-Cons are combined into a single player, if possible)
Single = 1, //!< Single Joy-Con (A single Joy-Con translates into a single player) Single = 1, //!< Single Joy-Con (A single Joy-Con translates into a single player)
}; };
/**
* @brief This enumerates the status codes for reading NPad colors
*/
enum class NpadColorReadStatus : u32 { enum class NpadColorReadStatus : u32 {
Success = 0, //!< The color was read successfully Success = 0, //!< The color was read successfully
Invalid = 1, //!< The color read in wasn't valid Invalid = 1, //!< The color read in wasn't valid
Disconnected = 2 //!< The controller isn't connected Disconnected = 2, //!< The controller isn't connected
}; };
/**
* @brief This structure stores the color of a controller
*/
struct NpadColor { struct NpadColor {
u32 bodyColor; //!< The color of the controller's body (This isn't always accurate and sometimes has magic values, especially with the Pro Controller) u32 bodyColor; //!< The color of the controller's body (This isn't always accurate and sometimes has magic values, especially with the Pro Controller)
u32 buttonColor; //!< The color of the controller's buttons (Same as above) u32 buttonColor; //!< The color of the controller's buttons (Same as above)
@ -47,7 +35,7 @@ namespace skyline::input {
static_assert(sizeof(NpadColor) == 0x8); static_assert(sizeof(NpadColor) == 0x8);
/** /**
* @brief The structure of the NPad headers (https://switchbrew.org/wiki/HID_Shared_Memory#NpadStateHeader) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadStateHeader
*/ */
struct NpadHeader { struct NpadHeader {
NpadControllerType type; NpadControllerType type;
@ -63,7 +51,7 @@ namespace skyline::input {
static_assert(sizeof(NpadHeader) == 0x28); static_assert(sizeof(NpadHeader) == 0x28);
/** /**
* @brief This is a bit-field of all the buttons on an NPad (https://switchbrew.org/wiki/HID_Shared_Memory#NpadButton) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadButton
*/ */
union NpadButton { union NpadButton {
u64 raw; u64 raw;
@ -100,9 +88,6 @@ namespace skyline::input {
}; };
static_assert(sizeof(NpadButton) == 0x8); static_assert(sizeof(NpadButton) == 0x8);
/**
* @brief This structure holds data about the state of the connection with the controller
*/
union NpadConnectionState { union NpadConnectionState {
u64 raw; u64 raw;
struct { struct {
@ -117,7 +102,7 @@ namespace skyline::input {
static_assert(sizeof(NpadConnectionState) == 0x8); static_assert(sizeof(NpadConnectionState) == 0x8);
/** /**
* @brief This structure contains data about the controller's current state (https://switchbrew.org/wiki/HID_Shared_Memory#NpadHandheldState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadHandheldState
*/ */
struct NpadControllerState { struct NpadControllerState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -135,9 +120,6 @@ namespace skyline::input {
}; };
static_assert(sizeof(NpadControllerState) == 0x30); static_assert(sizeof(NpadControllerState) == 0x30);
/**
* @brief This structure contains the header and entries for the controller input
*/
struct NpadControllerInfo { struct NpadControllerInfo {
CommonHeader header; CommonHeader header;
std::array<NpadControllerState, constant::HidEntryCount> state; std::array<NpadControllerState, constant::HidEntryCount> state;
@ -145,7 +127,7 @@ namespace skyline::input {
static_assert(sizeof(NpadControllerInfo) == 0x350); static_assert(sizeof(NpadControllerInfo) == 0x350);
/** /**
* @brief This structure is used to hold a single sample of 3D data from the IMU * @brief A single sample of 3D data from the IMU
*/ */
struct SixAxisVector { struct SixAxisVector {
float x; //!< The data in the X-axis float x; //!< The data in the X-axis
@ -155,7 +137,7 @@ namespace skyline::input {
static_assert(sizeof(SixAxisVector) == 0xC); static_assert(sizeof(SixAxisVector) == 0xC);
/** /**
* @brief This structure contains data about the state of the controller's IMU (Six-Axis) (https://switchbrew.org/wiki/HID_Shared_Memory#NpadSixAxisSensorHandheldState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadSixAxisSensorHandheldState
*/ */
struct NpadSixAxisState { struct NpadSixAxisState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -167,13 +149,10 @@ namespace skyline::input {
SixAxisVector rotation; SixAxisVector rotation;
std::array<SixAxisVector, 3> orientation; //!< The orientation basis data as a matrix std::array<SixAxisVector, 3> orientation; //!< The orientation basis data as a matrix
u64 _unk2_; //!< This is always 1 u64 _unk2_; //!< Always 1
}; };
static_assert(sizeof(NpadSixAxisState) == 0x68); static_assert(sizeof(NpadSixAxisState) == 0x68);
/**
* @brief This structure contains header and entries for the IMU (Six-Axis) data
*/
struct NpadSixAxisInfo { struct NpadSixAxisInfo {
CommonHeader header; CommonHeader header;
std::array<NpadSixAxisState, constant::HidEntryCount> state; std::array<NpadSixAxisState, constant::HidEntryCount> state;
@ -181,7 +160,7 @@ namespace skyline::input {
static_assert(sizeof(NpadSixAxisInfo) == 0x708); static_assert(sizeof(NpadSixAxisInfo) == 0x708);
/** /**
* @brief This is a bit-field of all the device types (https://switchbrew.org/wiki/HID_services#DeviceType) * @url https://switchbrew.org/wiki/HID_services#DeviceType
*/ */
union NpadDeviceType { union NpadDeviceType {
u32 raw; u32 raw;
@ -209,7 +188,7 @@ namespace skyline::input {
static_assert(sizeof(NpadDeviceType) == 0x4); static_assert(sizeof(NpadDeviceType) == 0x4);
/** /**
* @brief This structure holds the system properties of this NPad (https://switchbrew.org/wiki/HID_Shared_Memory#NpadSystemProperties) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadSystemProperties
*/ */
union NpadSystemProperties { union NpadSystemProperties {
u64 raw; u64 raw;
@ -233,7 +212,8 @@ namespace skyline::input {
static_assert(sizeof(NpadSystemProperties) == 0x8); static_assert(sizeof(NpadSystemProperties) == 0x8);
/** /**
* @brief This structure holds properties regarding the System Buttons (Home, Sleep and Capture) on an NPad (https://switchbrew.org/wiki/HID_Shared_Memory#NpadSystemButtonProperties) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadSystemButtonProperties
* @note System Buttons = Home + Capture
*/ */
union NpadSystemButtonProperties { union NpadSystemButtonProperties {
u32 raw; u32 raw;
@ -243,9 +223,6 @@ namespace skyline::input {
}; };
static_assert(sizeof(NpadSystemButtonProperties) == 0x4); static_assert(sizeof(NpadSystemButtonProperties) == 0x4);
/**
* @brief This enumerates all the possible values for the NPad's battery level
*/
enum class NpadBatteryLevel : u32 { enum class NpadBatteryLevel : u32 {
Empty = 0, Empty = 0,
Low = 1, Low = 1,
@ -255,7 +232,7 @@ namespace skyline::input {
}; };
/** /**
* @brief The structure of the Npad section (https://switchbrew.org/wiki/HID_Shared_Memory#NpadState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#NpadState
*/ */
struct NpadSection { struct NpadSection {
NpadHeader header; NpadHeader header;

View File

@ -7,7 +7,8 @@
namespace skyline::input { namespace skyline::input {
/** /**
* @brief This structure holds information about a single touch point * @brief A descriptor for a single point on the touch screen
* @url https://switchbrew.org/wiki/HID_Shared_Memory#TouchScreenStateData
*/ */
struct TouchScreenStateData { struct TouchScreenStateData {
u64 timestamp; //!< The timestamp in samples u64 timestamp; //!< The timestamp in samples
@ -21,13 +22,13 @@ namespace skyline::input {
u32 minorAxis; //!< The diameter of the touch cross-section on the minor-axis in pixels u32 minorAxis; //!< The diameter of the touch cross-section on the minor-axis in pixels
u32 majorAxis; //!< The diameter of the touch cross-section on the major-axis in pixels u32 majorAxis; //!< The diameter of the touch cross-section on the major-axis in pixels
i32 angle; //!< The angle of the touch in degrees (from -89 to 90 [-90 and 90 aren't distinguishable]. On the Switch, this has limited resolution with only 90, -67, -45, 0, 45, 67, 90 being values) i32 angle; //!< The angle of the touch in degrees (from -89 to 90 [-90 and 90 aren't distinguishable], while on the Switch this has limited resolution with only 90, -67, -45, 0, 45, 67, 90 being values)
u32 _pad1_; u32 _pad1_;
}; };
static_assert(sizeof(TouchScreenStateData) == 0x28); static_assert(sizeof(TouchScreenStateData) == 0x28);
/** /**
* @brief The structure of an entry for TouchScreen (https://switchbrew.org/wiki/HID_Shared_Memory#TouchScreenState) * @url https://switchbrew.org/wiki/HID_Shared_Memory#TouchScreenState
*/ */
struct TouchScreenState { struct TouchScreenState {
u64 globalTimestamp; //!< The global timestamp in samples u64 globalTimestamp; //!< The global timestamp in samples
@ -39,7 +40,7 @@ namespace skyline::input {
static_assert(sizeof(TouchScreenState) == 0x298); static_assert(sizeof(TouchScreenState) == 0x298);
/** /**
* @brief The structure of the TouchScreen section (https://switchbrew.org/wiki/HID_Shared_Memory#TouchScreen) * @url https://switchbrew.org/wiki/HID_Shared_Memory#TouchScreen
*/ */
struct TouchScreenSection { struct TouchScreenSection {
CommonHeader header; CommonHeader header;

View File

@ -15,7 +15,7 @@ namespace skyline {
namespace input { namespace input {
/** /**
* @brief This is the common part of the header for all sections * @brief A common part of the header for all sections
*/ */
struct CommonHeader { struct CommonHeader {
u64 timestamp; //!< The timestamp of the latest entry in ticks u64 timestamp; //!< The timestamp of the latest entry in ticks

View File

@ -17,7 +17,7 @@
namespace skyline { namespace skyline {
namespace input { namespace input {
/** /**
* @brief This encapsulates HID Shared Memory (https://switchbrew.org/wiki/HID_Shared_Memory) * @url https://switchbrew.org/wiki/HID_Shared_Memory
*/ */
struct HidSharedMemory { struct HidSharedMemory {
DebugPadSection debugPad; //!< The DebugPad section (https://switchbrew.org/wiki/HID_Shared_Memory#DebugPad) DebugPadSection debugPad; //!< The DebugPad section (https://switchbrew.org/wiki/HID_Shared_Memory#DebugPad)

View File

@ -13,21 +13,31 @@ namespace skyline {
namespace kernel::ipc { namespace kernel::ipc {
/** /**
* @brief This reflects the value in CommandStruct::type * @url https://switchbrew.org/wiki/IPC_Marshalling#Type
*/ */
enum class CommandType : u16 { enum class CommandType : u16 {
Invalid = 0, LegacyRequest = 1, Close = 2, LegacyControl = 3, Request = 4, Control = 5, RequestWithContext = 6, ControlWithContext = 7 Invalid = 0,
LegacyRequest = 1,
Close = 2, //!< Closes the IPC Session
LegacyControl = 3,
Request = 4, //!< A normal IPC transaction between the server and client process
Control = 5, //!< A transaction between the client and IPC Manager
RequestWithContext = 6, //!< Request with Token
ControlWithContext = 7, //!< Control with Token
}; };
/** /**
* @brief This reflects the value in CommandStruct::c_flags * @url https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_C_.22ReceiveList.22
* @note Any values beyond this are the amount of C-Buffers present (Which is calculated as value - 2)
*/ */
enum class BufferCFlag : u8 { enum class BufferCFlag : u8 {
None = 0, InlineDescriptor = 1, SingleDescriptor = 2 None = 0, //!< No C-Buffers present
InlineDescriptor = 1, //!< An inlined C-Buffer which is written after the raw data section
SingleDescriptor = 2, //!< A single C-Buffer
}; };
/** /**
* @brief This bit-field structure holds the header of an IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#IPC_Command_Structure) * @url https://switchbrew.org/wiki/IPC_Marshalling#IPC_Command_Structure
*/ */
struct CommandHeader { struct CommandHeader {
CommandType type : 16; CommandType type : 16;
@ -43,7 +53,7 @@ namespace skyline {
static_assert(sizeof(CommandHeader) == 8); static_assert(sizeof(CommandHeader) == 8);
/** /**
* @brief This bit-field structure holds the handle descriptor of a received IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#Handle_descriptor) * @url https://switchbrew.org/wiki/IPC_Marshalling#Handle_descriptor
*/ */
struct HandleDescriptor { struct HandleDescriptor {
bool sendPid : 1; bool sendPid : 1;
@ -54,10 +64,18 @@ namespace skyline {
static_assert(sizeof(HandleDescriptor) == 4); static_assert(sizeof(HandleDescriptor) == 4);
/** /**
* @brief This bit-field structure holds the domain's header of an IPC request command. (https://switchbrew.org/wiki/IPC_Marshalling#Domains) * @brief Commands which can be issued via a domain request
*/
enum class DomainCommand : u8 {
SendMessage = 1,
CloseVHandle = 2,
};
/**
* @url https://switchbrew.org/wiki/IPC_Marshalling#Domains
*/ */
struct DomainHeaderRequest { struct DomainHeaderRequest {
u8 command; DomainCommand command;
u8 inputCount; u8 inputCount;
u16 payloadSz; u16 payloadSz;
u32 objectId; u32 objectId;
@ -67,14 +85,7 @@ namespace skyline {
static_assert(sizeof(DomainHeaderRequest) == 16); static_assert(sizeof(DomainHeaderRequest) == 16);
/** /**
* @brief This reflects the value of DomainHeaderRequest::command * @url https://switchbrew.org/wiki/IPC_Marshalling#Domains
*/
enum class DomainCommand : u8 {
SendMessage = 1, CloseVHandle = 2
};
/**
* @brief This bit-field structure holds the domain's header of an IPC response command. (https://switchbrew.org/wiki/IPC_Marshalling#Domains)
*/ */
struct DomainHeaderResponse { struct DomainHeaderResponse {
u32 outputCount; u32 outputCount;
@ -84,7 +95,7 @@ namespace skyline {
static_assert(sizeof(DomainHeaderResponse) == 16); static_assert(sizeof(DomainHeaderResponse) == 16);
/** /**
* @brief This bit-field structure holds the data payload of an IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#Data_payload) * @url https://switchbrew.org/wiki/IPC_Marshalling#Data_payload
*/ */
struct PayloadHeader { struct PayloadHeader {
u32 magic; u32 magic;
@ -96,14 +107,19 @@ namespace skyline {
/** /**
* @brief This reflects which function PayloadHeader::value refers to when a control request is sent (https://switchbrew.org/wiki/IPC_Marshalling#Control) * @brief The IPC Control commands as encoded into the payload value
* @url https://switchbrew.org/wiki/IPC_Marshalling#Control
*/ */
enum class ControlCommand : u32 { enum class ControlCommand : u32 {
ConvertCurrentObjectToDomain = 0, CopyFromCurrentDomain = 1, CloneCurrentObject = 2, QueryPointerBufferSize = 3, CloneCurrentObjectEx = 4 ConvertCurrentObjectToDomain = 0, //!< Converts a regular IPC session into a domain session
CopyFromCurrentDomain = 1,
CloneCurrentObject = 2, //!< Creates a duplicate of the current session
QueryPointerBufferSize = 3, //!< The size of the X buffers written by the servers (and by extension C-buffers supplied by the client)
CloneCurrentObjectEx = 4, //!< Same as CloneCurrentObject
}; };
/** /**
* @brief This is a buffer descriptor for X buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_X_.22Pointer.22 * @url https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_X_.22Pointer.22
*/ */
struct BufferDescriptorX { struct BufferDescriptorX {
u16 counter0_5 : 6; //!< The first 5 bits of the counter u16 counter0_5 : 6; //!< The first 5 bits of the counter
@ -121,16 +137,10 @@ namespace skyline {
counter9_11 = static_cast<u16>(address & 0x38); counter9_11 = static_cast<u16>(address & 0x38);
} }
/**
* @return The address of the buffer
*/
inline u64 Address() { inline u64 Address() {
return static_cast<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(address36_38) << 36; return static_cast<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(address36_38) << 36;
} }
/**
* @return The counter index of the buffer
*/
inline u16 Counter() { inline u16 Counter() {
return static_cast<u16>(counter0_5) | static_cast<u16>(counter9_11) << 9; return static_cast<u16>(counter0_5) | static_cast<u16>(counter9_11) << 9;
} }
@ -138,7 +148,7 @@ namespace skyline {
static_assert(sizeof(BufferDescriptorX) == 8); static_assert(sizeof(BufferDescriptorX) == 8);
/** /**
* @brief This is a buffer descriptor for A/B/W buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_A.2FB.2FW_.22Send.22.2F.22Receive.22.2F.22Exchange.22 * @url https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_A.2FB.2FW_.22Send.22.2F.22Receive.22.2F.22Exchange.22
*/ */
struct BufferDescriptorABW { struct BufferDescriptorABW {
u32 size0_31 : 32; //!< The first 32 bits of the size u32 size0_31 : 32; //!< The first 32 bits of the size
@ -157,16 +167,10 @@ namespace skyline {
size32_35 = static_cast<u8>(size & 0x78000000); size32_35 = static_cast<u8>(size & 0x78000000);
} }
/**
* @return The address of the buffer
*/
inline u64 Address() { inline u64 Address() {
return static_cast<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(address36_38) << 36; return static_cast<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(address36_38) << 36;
} }
/**
* @return The size of the buffer
*/
inline u64 Size() { inline u64 Size() {
return static_cast<u64>(size0_31) | static_cast<u64>(size32_35) << 32; return static_cast<u64>(size0_31) | static_cast<u64>(size32_35) << 32;
} }
@ -174,7 +178,7 @@ namespace skyline {
static_assert(sizeof(BufferDescriptorABW) == 12); static_assert(sizeof(BufferDescriptorABW) == 12);
/** /**
* @brief This is a buffer descriptor for C buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_C_.22ReceiveList.22 * @url https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_C_.22ReceiveList.22
*/ */
struct BufferDescriptorC { struct BufferDescriptorC {
u64 address : 48; //!< The 48-bit address of the buffer u64 address : 48; //!< The 48-bit address of the buffer
@ -184,47 +188,40 @@ namespace skyline {
}; };
static_assert(sizeof(BufferDescriptorC) == 8); static_assert(sizeof(BufferDescriptorC) == 8);
/**
* @brief This enumerates the types of IPC buffers
*/
enum class IpcBufferType { enum class IpcBufferType {
X, //!< This is a type-X buffer X, //!< Type-X buffer (BufferDescriptorX)
A, //!< This is a type-A buffer A, //!< Type-A buffer (BufferDescriptorABW)
B, //!< This is a type-B buffer B, //!< Type-B buffer (BufferDescriptorABW)
W, //!< This is a type-W buffer W, //!< Type-W buffer (BufferDescriptorABW)
C //!< This is a type-C buffer C, //!< Type-C buffer (BufferDescriptorC)
}; };
/** /**
* @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling) * @brief A wrapper over an IPC Request which allows it to be parsed and used effectively
* @url https://switchbrew.org/wiki/IPC_Marshalling
*/ */
class IpcRequest { class IpcRequest {
private: private:
u8 *payloadOffset; //!< This is the offset of the data read from the payload u8 *payloadOffset; //!< The offset of the data read from the payload
public: public:
CommandHeader *header{}; //!< The header of the request CommandHeader *header{};
HandleDescriptor *handleDesc{}; //!< The handle descriptor in case CommandHeader::handle_desc is true in the header HandleDescriptor *handleDesc{};
bool isDomain{}; //!< If this is a domain request bool isDomain{}; //!< If this is a domain request
DomainHeaderRequest *domain{}; //!< In case this is a domain request, this holds data regarding it DomainHeaderRequest *domain{};
PayloadHeader *payload{}; //!< This is the header of the payload PayloadHeader *payload{};
u8 *cmdArg{}; //!< This is a pointer to the data payload (End of PayloadHeader) u8 *cmdArg{}; //!< A pointer to the data payload
u64 cmdArgSz{}; //!< This is the size of the data payload u64 cmdArgSz{}; //!< The size of the data payload
std::vector<KHandle> copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles) std::vector<KHandle> copyHandles; //!< The handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles)
std::vector<KHandle> moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied std::vector<KHandle> moveHandles; //!< The handles that should be moved from the server to the client process rather than copied
std::vector<KHandle> domainObjects; //!< A vector of all input domain objects std::vector<KHandle> domainObjects;
std::vector<span<u8>> inputBuf; //!< This is a vector of input buffers std::vector<span<u8>> inputBuf;
std::vector<span<u8>> outputBuf; //!< This is a vector of output buffers std::vector<span<u8>> outputBuf;
/**
* @param isDomain If the following request is a domain request
* @param state The state of the device
*/
IpcRequest(bool isDomain, const DeviceState &state); IpcRequest(bool isDomain, const DeviceState &state);
/** /**
* @brief This returns a reference to an item from the top of the payload * @brief Returns a reference to an item from the top of the payload
* @tparam ValueType The type of the object to read
*/ */
template<typename ValueType> template<typename ValueType>
inline ValueType &Pop() { inline ValueType &Pop() {
@ -234,7 +231,7 @@ namespace skyline {
} }
/** /**
* @brief This returns a std::string_view from the payload * @brief Returns a std::string_view from the payload
* @param size The length of the string (0 means the string is null terminated) * @param size The length of the string (0 means the string is null terminated)
*/ */
inline std::string_view PopString(size_t size = 0) { inline std::string_view PopString(size_t size = 0) {
@ -244,8 +241,7 @@ namespace skyline {
} }
/** /**
* @brief This skips an object to pop off the top * @brief Skips an object to pop off the top
* @tparam ValueType The type of the object to skip
*/ */
template<typename ValueType> template<typename ValueType>
inline void Skip() { inline void Skip() {
@ -254,23 +250,20 @@ namespace skyline {
}; };
/** /**
* @brief This class encapsulates an IPC Response (https://switchbrew.org/wiki/IPC_Marshalling) * @brief A wrapper over an IPC Response which allows it to be defined and serialized efficiently
* @url https://switchbrew.org/wiki/IPC_Marshalling
*/ */
class IpcResponse { class IpcResponse {
private: private:
const DeviceState &state; //!< The state of the device const DeviceState &state;
std::vector<u8> payload; //!< This holds all of the contents to be pushed to the payload std::vector<u8> payload; //!< The contents to be pushed to the data payload
public: public:
Result errorCode{}; //!< The error code to respond with, it is 0 (Success) by default Result errorCode{}; //!< The error code to respond with, it is 0 (Success) by default
std::vector<KHandle> copyHandles; //!< A vector of handles to copy std::vector<KHandle> copyHandles;
std::vector<KHandle> moveHandles; //!< A vector of handles to move std::vector<KHandle> moveHandles;
std::vector<KHandle> domainObjects; //!< A vector of domain objects to write std::vector<KHandle> domainObjects;
/**
* @param isDomain If the following request is a domain request
* @param state The state of the device
*/
IpcResponse(const DeviceState &state); IpcResponse(const DeviceState &state);
/** /**
@ -282,7 +275,6 @@ namespace skyline {
inline void Push(const ValueType &value) { inline void Push(const ValueType &value) {
auto size{payload.size()}; auto size{payload.size()};
payload.resize(size + sizeof(ValueType)); payload.resize(size + sizeof(ValueType));
std::memcpy(payload.data() + size, reinterpret_cast<const u8 *>(&value), sizeof(ValueType)); std::memcpy(payload.data() + size, reinterpret_cast<const u8 *>(&value), sizeof(ValueType));
} }
@ -290,11 +282,9 @@ namespace skyline {
* @brief Writes a string to the payload * @brief Writes a string to the payload
* @param string The string to write to the payload * @param string The string to write to the payload
*/ */
template<> inline void Push(std::string_view string) {
inline void Push(const std::string &string) {
auto size{payload.size()}; auto size{payload.size()};
payload.resize(size + string.size()); payload.resize(size + string.size());
std::memcpy(payload.data() + size, string.data(), string.size()); std::memcpy(payload.data() + size, string.data(), string.size());
} }

View File

@ -6,11 +6,11 @@
namespace skyline::kernel { namespace skyline::kernel {
ChunkDescriptor *MemoryManager::GetChunk(u64 address) { ChunkDescriptor *MemoryManager::GetChunk(u64 address) {
auto chunk{std::upper_bound(chunkList.begin(), chunkList.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool { auto chunk{std::upper_bound(chunks.begin(), chunks.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
return address < chunk.address; return address < chunk.address;
})}; })};
if (chunk-- != chunkList.begin()) { if (chunk-- != chunks.begin()) {
if ((chunk->address + chunk->size) > address) if ((chunk->address + chunk->size) > address)
return chunk.base(); return chunk.base();
} }
@ -37,24 +37,24 @@ namespace skyline::kernel {
} }
void MemoryManager::InsertChunk(const ChunkDescriptor &chunk) { void MemoryManager::InsertChunk(const ChunkDescriptor &chunk) {
auto upperChunk{std::upper_bound(chunkList.begin(), chunkList.end(), chunk.address, [](const u64 address, const ChunkDescriptor &chunk) -> bool { auto upperChunk{std::upper_bound(chunks.begin(), chunks.end(), chunk.address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
return address < chunk.address; return address < chunk.address;
})}; })};
if (upperChunk != chunkList.begin()) { if (upperChunk != chunks.begin()) {
auto lowerChunk{std::prev(upperChunk)}; auto lowerChunk{std::prev(upperChunk)};
if (lowerChunk->address + lowerChunk->size > chunk.address) if (lowerChunk->address + lowerChunk->size > chunk.address)
throw exception("InsertChunk: Descriptors are colliding: 0x{:X} - 0x{:X} and 0x{:X} - 0x{:X}", lowerChunk->address, lowerChunk->address + lowerChunk->size, chunk.address, chunk.address + chunk.size); throw exception("InsertChunk: Descriptors are colliding: 0x{:X} - 0x{:X} and 0x{:X} - 0x{:X}", lowerChunk->address, lowerChunk->address + lowerChunk->size, chunk.address, chunk.address + chunk.size);
} }
chunkList.insert(upperChunk, chunk); chunks.insert(upperChunk, chunk);
} }
void MemoryManager::DeleteChunk(u64 address) { void MemoryManager::DeleteChunk(u64 address) {
for (auto chunk{chunkList.begin()}, end{chunkList.end()}; chunk != end;) { for (auto chunk{chunks.begin()}, end{chunks.end()}; chunk != end;) {
if (chunk->address <= address && (chunk->address + chunk->size) > address) if (chunk->address <= address && (chunk->address + chunk->size) > address)
chunk = chunkList.erase(chunk); chunk = chunks.erase(chunk);
else else
chunk++; chunk++;
} }
@ -176,17 +176,17 @@ namespace skyline::kernel {
// If the requested address is in the address space but no chunks are present then we return a new unmapped region // If the requested address is in the address space but no chunks are present then we return a new unmapped region
if (addressSpace.IsInside(address) && !requireMapped) { if (addressSpace.IsInside(address) && !requireMapped) {
auto upperChunk{std::upper_bound(chunkList.begin(), chunkList.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool { auto upperChunk{std::upper_bound(chunks.begin(), chunks.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
return address < chunk.address; return address < chunk.address;
})}; })};
u64 upperAddress{}; u64 upperAddress{};
u64 lowerAddress{}; u64 lowerAddress{};
if (upperChunk != chunkList.end()) { if (upperChunk != chunks.end()) {
upperAddress = upperChunk->address; upperAddress = upperChunk->address;
if (upperChunk == chunkList.begin()) { if (upperChunk == chunks.begin()) {
lowerAddress = addressSpace.address; lowerAddress = addressSpace.address;
} else { } else {
upperChunk--; upperChunk--;
@ -194,7 +194,7 @@ namespace skyline::kernel {
} }
} else { } else {
upperAddress = addressSpace.address + addressSpace.size; upperAddress = addressSpace.address + addressSpace.size;
lowerAddress = chunkList.back().address + chunkList.back().size; lowerAddress = chunks.back().address + chunks.back().size;
} }
u64 size{upperAddress - lowerAddress}; u64 size{upperAddress - lowerAddress};
@ -217,7 +217,7 @@ namespace skyline::kernel {
size_t MemoryManager::GetProgramSize() { size_t MemoryManager::GetProgramSize() {
size_t size{}; size_t size{};
for (const auto &chunk : chunkList) for (const auto &chunk : chunks)
size += chunk.size; size += chunk.size;
return size; return size;
} }

View File

@ -53,7 +53,7 @@ namespace skyline {
}; };
/** /**
* @brief This holds certain attributes of a chunk of memory: https://switchbrew.org/wiki/SVC#MemoryAttribute * @url https://switchbrew.org/wiki/SVC#MemoryAttribute
*/ */
union MemoryAttribute { union MemoryAttribute {
struct { struct {
@ -66,7 +66,7 @@ namespace skyline {
}; };
/** /**
* @brief This contains information about a chunk of memory: https://switchbrew.org/wiki/SVC#MemoryInfo * @url https://switchbrew.org/wiki/SVC#MemoryInfo
*/ */
struct MemoryInfo { struct MemoryInfo {
u64 address; //!< The base address of the mapping u64 address; //!< The base address of the mapping
@ -74,14 +74,15 @@ namespace skyline {
u32 type; //!< The MemoryType of the mapping u32 type; //!< The MemoryType of the mapping
u32 attributes; //!< The attributes of the mapping u32 attributes; //!< The attributes of the mapping
u32 permissions; //!< The permissions of the mapping u32 permissions; //!< The permissions of the mapping
u32 ipcRefCount; //!< The IPC reference count (This is always 0) u32 ipcRefCount; //!< The IPC reference count (Always 0)
u32 deviceRefCount; //!< The device reference count (This is always 0) u32 deviceRefCount; //!< The device reference count (Always 0)
u32 _pad0_; u32 _pad0_;
}; };
static_assert(sizeof(MemoryInfo) == 0x28); static_assert(sizeof(MemoryInfo) == 0x28);
/** /**
* @brief These are specific markers for the type of a memory region (https://switchbrew.org/wiki/SVC#MemoryType) * @brief These are specific markers for the type of a memory region
* @url https://switchbrew.org/wiki/SVC#MemoryType
*/ */
enum class MemoryType : u8 { enum class MemoryType : u8 {
Unmapped = 0x0, Unmapped = 0x0,
@ -105,11 +106,12 @@ namespace skyline {
NonDeviceIpc = 0x12, NonDeviceIpc = 0x12,
KernelStack = 0x13, KernelStack = 0x13,
CodeReadOnly = 0x14, CodeReadOnly = 0x14,
CodeWritable = 0x15 CodeWritable = 0x15,
}; };
/** /**
* @brief This structure is used to hold the state of a certain block of memory (https://switchbrew.org/wiki/SVC#MemoryState) * @brief The state of a certain block of memory
* @url https://switchbrew.org/wiki/SVC#MemoryState
*/ */
union MemoryState { union MemoryState {
constexpr MemoryState(const u32 value) : value(value) {} constexpr MemoryState(const u32 value) : value(value) {}
@ -142,7 +144,8 @@ namespace skyline {
static_assert(sizeof(MemoryState) == sizeof(u32)); static_assert(sizeof(MemoryState) == sizeof(u32));
/** /**
* @brief The preset states that different regions are set to (https://switchbrew.org/wiki/SVC#MemoryType) * @brief The preset states that different regions are set to
* @url https://switchbrew.org/wiki/SVC#MemoryType
*/ */
namespace states { namespace states {
constexpr MemoryState Unmapped{0x00000000}; constexpr MemoryState Unmapped{0x00000000};
@ -168,9 +171,6 @@ namespace skyline {
constexpr MemoryState CodeWritable{0x00402015}; constexpr MemoryState CodeWritable{0x00402015};
}; };
/**
* @brief This struct is used to hold the location and size of a memory region
*/
struct Region { struct Region {
u64 address; //!< The base address of the region u64 address; //!< The base address of the region
u64 size; //!< The size of the region in bytes u64 size; //!< The size of the region in bytes
@ -215,7 +215,7 @@ namespace skyline {
} }
/** /**
* @brief This describes a single block of memory and all of it's individual attributes * @brief A single block of memory and all of it's individual attributes
*/ */
struct BlockDescriptor { struct BlockDescriptor {
u64 address; //!< The address of the current block u64 address; //!< The address of the current block
@ -225,18 +225,18 @@ namespace skyline {
}; };
/** /**
* @brief This describes a single chunk of memory, this is owned by a memory backing * @brief A single chunk of memory, this is owned by a memory backing
*/ */
struct ChunkDescriptor { struct ChunkDescriptor {
u64 address; //!< The address of the current chunk u64 address; //!< The address of the current chunk
u64 size; //!< The size of the current chunk in bytes u64 size; //!< The size of the current chunk in bytes
u64 host; //!< The address of the chunk in the host u64 host; //!< The address of the chunk in the host
memory::MemoryState state; //!< The MemoryState for the current block memory::MemoryState state; //!< The MemoryState for the current block
std::vector<BlockDescriptor> blockList; //!< This vector holds the block descriptors for all the children blocks of this Chunk std::vector<BlockDescriptor> blockList; //!< The block descriptors for all the children blocks of this Chunk
}; };
/** /**
* @brief This contains both of the descriptors for a specific address * @brief A pack of both the descriptors for a specific address
*/ */
struct DescriptorPack { struct DescriptorPack {
const BlockDescriptor block; //!< The block descriptor at the address const BlockDescriptor block; //!< The block descriptor at the address
@ -248,8 +248,8 @@ namespace skyline {
*/ */
class MemoryManager { class MemoryManager {
private: private:
const DeviceState &state; //!< The state of the device const DeviceState &state;
std::vector<ChunkDescriptor> chunkList; //!< This vector holds all the chunk descriptors std::vector<ChunkDescriptor> chunks;
/** /**
* @param address The address to find a chunk at * @param address The address to find a chunk at
@ -290,7 +290,7 @@ namespace skyline {
static void InsertBlock(ChunkDescriptor *chunk, BlockDescriptor block); static void InsertBlock(ChunkDescriptor *chunk, BlockDescriptor block);
/** /**
* @brief This initializes all of the regions in the address space * @brief Initializes all of the regions in the address space
* @param address The starting address of the code region * @param address The starting address of the code region
* @param size The size of the code region * @param size The size of the code region
* @param type The type of the address space * @param type The type of the address space
@ -322,7 +322,7 @@ namespace skyline {
/** /**
* @param address The address to query in the memory map * @param address The address to query in the memory map
* @param requireMapped This specifies if only mapped regions should be returned otherwise unmapped but valid regions will also be returned * @param requireMapped If only mapped regions should be returned otherwise unmapped but valid regions will also be returned
* @return A DescriptorPack retrieved from the memory map * @return A DescriptorPack retrieved from the memory map
*/ */
std::optional<DescriptorPack> Get(u64 address, bool requireMapped = true); std::optional<DescriptorPack> Get(u64 address, bool requireMapped = true);

View File

@ -2,6 +2,7 @@
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <os.h> #include <os.h>
#include <kernel/types/KProcess.h>
#include "results.h" #include "results.h"
#include "svc.h" #include "svc.h"
@ -170,7 +171,7 @@ namespace skyline::kernel::svc {
if (!sourceObject) if (!sourceObject)
throw exception("svcUnmapMemory: Cannot find source memory object in handle table for address 0x{:X}", source); throw exception("svcUnmapMemory: Cannot find source memory object in handle table for address 0x{:X}", source);
state.process->DeleteHandle(sourceObject->handle); state.process->CloseHandle(sourceObject->handle);
state.logger->Debug("svcUnmapMemory: Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size); state.logger->Debug("svcUnmapMemory: Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
state.ctx->registers.w0 = Result{}; state.ctx->registers.w0 = Result{};
@ -375,7 +376,7 @@ namespace skyline::kernel::svc {
void CloseHandle(DeviceState &state) { void CloseHandle(DeviceState &state) {
auto handle{static_cast<KHandle>(state.ctx->registers.w0)}; auto handle{static_cast<KHandle>(state.ctx->registers.w0)};
try { try {
state.process->DeleteHandle(handle); state.process->CloseHandle(handle);
state.logger->Debug("svcCloseHandle: Closing handle: 0x{:X}", handle); state.logger->Debug("svcCloseHandle: Closing handle: 0x{:X}", handle);
state.ctx->registers.w0 = Result{}; state.ctx->registers.w0 = Result{};
} catch (const std::exception &) { } catch (const std::exception &) {
@ -583,8 +584,7 @@ namespace skyline::kernel::svc {
} }
void ConnectToNamedPort(DeviceState &state) { void ConnectToNamedPort(DeviceState &state) {
constexpr u8 portSize{0x8}; //!< The size of a port name string std::string_view port(state.process->GetPointer<char>(state.ctx->registers.x1), sizeof(service::ServiceName));
std::string_view port(state.process->GetPointer<char>(state.ctx->registers.x1), portSize);
KHandle handle{}; KHandle handle{};
if (port.compare("sm:") >= 0) { if (port.compare("sm:") >= 0) {
@ -607,7 +607,7 @@ namespace skyline::kernel::svc {
} }
void GetThreadId(DeviceState &state) { void GetThreadId(DeviceState &state) {
constexpr KHandle threadSelf{0xFFFF8000}; // This is the handle used by threads to refer to themselves constexpr KHandle threadSelf{0xFFFF8000}; // The handle used by threads to refer to themselves
auto handle{state.ctx->registers.w1}; auto handle{state.ctx->registers.w1};
pid_t pid{}; pid_t pid{};

View File

@ -40,147 +40,176 @@ namespace skyline {
namespace kernel::svc { namespace kernel::svc {
/** /**
* @brief Sets the process heap to a given Size. It can both extend and shrink the heap. (https://switchbrew.org/wiki/SVC#SetHeapSize) * @brief Sets the process heap to a given size, it can both extend and shrink the heap
* @url https://switchbrew.org/wiki/SVC#SetHeapSize
*/ */
void SetHeapSize(DeviceState &state); void SetHeapSize(DeviceState &state);
/** /**
* @brief Change attribute of page-aligned memory region. This is used to turn on/off caching for a given memory area. (https://switchbrew.org/wiki/SVC#SetMemoryAttribute) * @brief Change attribute of page-aligned memory region, this is used to turn on/off caching for a given memory area
* @url https://switchbrew.org/wiki/SVC#SetMemoryAttribute
*/ */
void SetMemoryAttribute(DeviceState &state); void SetMemoryAttribute(DeviceState &state);
/** /**
* @brief Maps a memory range into a different range. Mainly used for adding guard pages around stack. (https://switchbrew.org/wiki/SVC#SetMemoryAttribute) * @brief Maps a memory range into a different range, mainly used for adding guard pages around stack
* @url https://switchbrew.org/wiki/SVC#SetMemoryAttribute
*/ */
void MapMemory(DeviceState &state); void MapMemory(DeviceState &state);
/** /**
* @brief Unmaps a region that was previously mapped with #MapMemory. (https://switchbrew.org/wiki/SVC#UnmapMemory) * @brief Unmaps a region that was previously mapped with #MapMemory
* @url https://switchbrew.org/wiki/SVC#UnmapMemory
*/ */
void UnmapMemory(DeviceState &state); void UnmapMemory(DeviceState &state);
/** /**
* @brief Query information about an address (https://switchbrew.org/wiki/SVC#QueryMemory) * @brief Query information about an address
* @url https://switchbrew.org/wiki/SVC#QueryMemory
*/ */
void QueryMemory(DeviceState &state); void QueryMemory(DeviceState &state);
/** /**
* @brief Exits the current process (https://switchbrew.org/wiki/SVC#ExitProcess) * @brief Exits the current process
* @url https://switchbrew.org/wiki/SVC#ExitProcess
*/ */
void ExitProcess(DeviceState &state); void ExitProcess(DeviceState &state);
/** /**
* @brief Create a thread in the current process (https://switchbrew.org/wiki/SVC#CreateThread) * @brief Create a thread in the current process
* @url https://switchbrew.org/wiki/SVC#CreateThread
*/ */
void CreateThread(DeviceState &state); void CreateThread(DeviceState &state);
/** /**
* @brief Starts the thread for the provided handle (https://switchbrew.org/wiki/SVC#StartThread) * @brief Starts the thread for the provided handle
* @url https://switchbrew.org/wiki/SVC#StartThread
*/ */
void StartThread(DeviceState &state); void StartThread(DeviceState &state);
/** /**
* @brief Exits the current thread (https://switchbrew.org/wiki/SVC#ExitThread) * @brief Exits the current thread
* @url https://switchbrew.org/wiki/SVC#ExitThread
*/ */
void ExitThread(DeviceState &state); void ExitThread(DeviceState &state);
/** /**
* @brief Sleep for a specified amount of time, or yield thread (https://switchbrew.org/wiki/SVC#SleepThread) * @brief Sleep for a specified amount of time, or yield thread
* @url https://switchbrew.org/wiki/SVC#SleepThread
*/ */
void SleepThread(DeviceState &state); void SleepThread(DeviceState &state);
/** /**
* @brief Get priority of provided thread handle (https://switchbrew.org/wiki/SVC#GetThreadPriority) * @brief Get priority of provided thread handle
* @url https://switchbrew.org/wiki/SVC#GetThreadPriority
*/ */
void GetThreadPriority(DeviceState &state); void GetThreadPriority(DeviceState &state);
/** /**
* @brief Set priority of provided thread handle (https://switchbrew.org/wiki/SVC#SetThreadPriority) * @brief Set priority of provided thread handle
* @url https://switchbrew.org/wiki/SVC#SetThreadPriority
*/ */
void SetThreadPriority(DeviceState &state); void SetThreadPriority(DeviceState &state);
/** /**
* @brief Clears a KEvent of it's signal (https://switchbrew.org/wiki/SVC#ClearEvent) * @brief Clears a KEvent of it's signal
* @url https://switchbrew.org/wiki/SVC#ClearEvent
*/ */
void ClearEvent(DeviceState &state); void ClearEvent(DeviceState &state);
/** /**
* @brief Maps the block supplied by the handle (https://switchbrew.org/wiki/SVC#MapSharedMemory) * @brief Maps the block supplied by the handle
* @url https://switchbrew.org/wiki/SVC#MapSharedMemory
*/ */
void MapSharedMemory(DeviceState &state); void MapSharedMemory(DeviceState &state);
/** /**
* @brief Returns a handle to a KSharedMemory object (https://switchbrew.org/wiki/SVC#CreateTransferMemory) * @brief Returns a handle to a KSharedMemory object
* @url https://switchbrew.org/wiki/SVC#CreateTransferMemory
*/ */
void CreateTransferMemory(DeviceState &state); void CreateTransferMemory(DeviceState &state);
/** /**
* @brief Closes the specified handle (https://switchbrew.org/wiki/SVC#CloseHandle) * @brief Closes the specified handle
* @url https://switchbrew.org/wiki/SVC#CloseHandle
*/ */
void CloseHandle(DeviceState &state); void CloseHandle(DeviceState &state);
/** /**
* @brief This resets a particular KEvent or KProcess which is signalled (https://switchbrew.org/wiki/SVC#ResetSignal) * @brief Resets a particular KEvent or KProcess which is signalled
* @url https://switchbrew.org/wiki/SVC#ResetSignal
*/ */
void ResetSignal(DeviceState &state); void ResetSignal(DeviceState &state);
/** /**
* @brief Stalls a thread till a KSyncObject signals or the timeout has ended (https://switchbrew.org/wiki/SVC#WaitSynchronization) * @brief Stalls a thread till a KSyncObject signals or the timeout has ended
* @url https://switchbrew.org/wiki/SVC#WaitSynchronization
*/ */
void WaitSynchronization(DeviceState &state); void WaitSynchronization(DeviceState &state);
/** /**
* @brief If the referenced thread is currently in a synchronization call, that call will be interrupted (https://switchbrew.org/wiki/SVC#CancelSynchronization) * @brief If the referenced thread is currently in a synchronization call, that call will be interrupted
* @url https://switchbrew.org/wiki/SVC#CancelSynchronization
*/ */
void CancelSynchronization(DeviceState &state); void CancelSynchronization(DeviceState &state);
/** /**
* @brief Locks a specified mutex (https://switchbrew.org/wiki/SVC#ArbitrateLock) * @brief Locks a specified mutex
* @url https://switchbrew.org/wiki/SVC#ArbitrateLock
*/ */
void ArbitrateLock(DeviceState &state); void ArbitrateLock(DeviceState &state);
/** /**
* @brief Unlocks a specified mutex (https://switchbrew.org/wiki/SVC#ArbitrateUnlock) * @brief Unlocks a specified mutex
* @url https://switchbrew.org/wiki/SVC#ArbitrateUnlock
*/ */
void ArbitrateUnlock(DeviceState &state); void ArbitrateUnlock(DeviceState &state);
/** /**
* @brief Waits on a process-wide key (Conditional-Variable) (https://switchbrew.org/wiki/SVC#WaitProcessWideKeyAtomic) * @brief Waits on a process-wide key (Conditional-Variable)
* @url https://switchbrew.org/wiki/SVC#WaitProcessWideKeyAtomic
*/ */
void WaitProcessWideKeyAtomic(DeviceState &state); void WaitProcessWideKeyAtomic(DeviceState &state);
/** /**
* @brief Signals a process-wide key (Conditional-Variable) (https://switchbrew.org/wiki/SVC#SignalProcessWideKey) * @brief Signals a process-wide key (Conditional-Variable)
* @url https://switchbrew.org/wiki/SVC#SignalProcessWideKey
*/ */
void SignalProcessWideKey(DeviceState &state); void SignalProcessWideKey(DeviceState &state);
/** /**
* @brief This returns the value of CNTPCT_EL0 on the Switch (https://switchbrew.org/wiki/SVC#GetSystemTick) * @brief Returns the value of CNTPCT_EL0 on the Switch
* @url https://switchbrew.org/wiki/SVC#GetSystemTick
*/ */
void GetSystemTick(DeviceState &state); void GetSystemTick(DeviceState &state);
/** /**
* @brief Connects to a named IPC port (https://switchbrew.org/wiki/SVC#ConnectToNamedPort) * @brief Connects to a named IPC port
* @url https://switchbrew.org/wiki/SVC#ConnectToNamedPort
*/ */
void ConnectToNamedPort(DeviceState &state); void ConnectToNamedPort(DeviceState &state);
/** /**
* @brief Send a synchronous IPC request to a service (https://switchbrew.org/wiki/SVC#SendSyncRequest) * @brief Send a synchronous IPC request to a service
* @url https://switchbrew.org/wiki/SVC#SendSyncRequest
*/ */
void SendSyncRequest(DeviceState &state); void SendSyncRequest(DeviceState &state);
/** /**
* @brief Retrieves the PID of a specific thread (https://switchbrew.org/wiki/SVC#GetThreadId) * @brief Retrieves the PID of a specific thread
* @url https://switchbrew.org/wiki/SVC#GetThreadId
*/ */
void GetThreadId(DeviceState &state); void GetThreadId(DeviceState &state);
/** /**
* @brief Outputs a debug string (https://switchbrew.org/wiki/SVC#OutputDebugString) * @brief Outputs a debug string
* @url https://switchbrew.org/wiki/SVC#OutputDebugString
*/ */
void OutputDebugString(DeviceState &state); void OutputDebugString(DeviceState &state);
/** /**
* @brief Retrieves a piece of information (https://switchbrew.org/wiki/SVC#GetInfo) * @brief Retrieves a piece of information
* @url https://switchbrew.org/wiki/SVC#GetInfo
*/ */
void GetInfo(DeviceState &state); void GetInfo(DeviceState &state);

View File

@ -7,13 +7,11 @@
namespace skyline::kernel::type { namespace skyline::kernel::type {
/** /**
* @brief KEvent is an object that's signalled on an repeatable event occurring (https://switchbrew.org/wiki/Kernel_objects#KEvent) * @brief KEvent is an object that's signalled on an repeatable event occurring
* @url https://switchbrew.org/wiki/Kernel_objects#KEvent
*/ */
class KEvent : public KSyncObject { class KEvent : public KSyncObject {
public: public:
/**
* @param state The state of the device
*/
KEvent(const DeviceState &state) : KSyncObject(state, KType::KEvent) {} KEvent(const DeviceState &state) : KSyncObject(state, KType::KEvent) {}
/** /**

View File

@ -10,7 +10,13 @@ namespace skyline::kernel::type {
* @brief These types are used to perform runtime evaluation of a kernel object's type when converting from base class * @brief These types are used to perform runtime evaluation of a kernel object's type when converting from base class
*/ */
enum class KType { enum class KType {
KThread, KProcess, KSharedMemory, KTransferMemory, KPrivateMemory, KSession, KEvent KThread,
KProcess,
KSharedMemory,
KTransferMemory,
KPrivateMemory,
KSession,
KEvent,
}; };
/** /**
@ -18,13 +24,9 @@ namespace skyline::kernel::type {
*/ */
class KObject { class KObject {
public: public:
const DeviceState &state; //!< The state of the device const DeviceState &state;
KType objectType; //!< The type of this object KType objectType;
/**
* @param state The state of the device
* @param objectType The type of the object
*/
KObject(const DeviceState &state, KType objectType) : state(state), objectType(objectType) {} KObject(const DeviceState &state, KType objectType) : state(state), objectType(objectType) {}
}; };
} }

View File

@ -18,7 +18,6 @@ namespace skyline::kernel::type {
size_t size{}; //!< The size of the allocated memory size_t size{}; //!< The size of the allocated memory
/** /**
* @param state The state of the device
* @param address The address to map to (If NULL then an arbitrary address is picked) * @param address The address to map to (If NULL then an arbitrary address is picked)
* @param size The size of the allocation * @param size The size of the allocation
* @param permission The permissions for the allocated memory * @param permission The permissions for the allocated memory

View File

@ -14,7 +14,7 @@ namespace skyline {
namespace constant { namespace constant {
constexpr u16 TlsSlotSize{0x200}; //!< The size of a single TLS slot constexpr u16 TlsSlotSize{0x200}; //!< The size of a single TLS slot
constexpr u8 TlsSlots{PAGE_SIZE / TlsSlotSize}; //!< The amount of TLS slots in a single page constexpr u8 TlsSlots{PAGE_SIZE / TlsSlotSize}; //!< The amount of TLS slots in a single page
constexpr KHandle BaseHandleIndex{0xD000}; // The index of the base handle constexpr KHandle BaseHandleIndex{0xD000}; //!< The index of the base handle
constexpr u32 MtxOwnerMask{0xBFFFFFFF}; //!< The mask of values which contain the owner of a mutex constexpr u32 MtxOwnerMask{0xBFFFFFFF}; //!< The mask of values which contain the owner of a mutex
} }
@ -24,14 +24,13 @@ namespace skyline {
*/ */
class KProcess : public KSyncObject { class KProcess : public KSyncObject {
private: private:
KHandle handleIndex{constant::BaseHandleIndex}; //!< This is used to keep track of what to map as an handle KHandle handleIndex{constant::BaseHandleIndex}; //!< The index of the handle that will be allocated next
/** /**
* @brief This class holds a single TLS page's status * @brief The status of a single TLS page (A page is 4096 bytes on ARMv8)
* @details tls_page_t holds the status of a single TLS page (A page is 4096 bytes on ARMv8). * Each TLS page has 8 slots, each 0x200 (512) bytes in size
* Each TLS page has 8 slots, each 0x200 (512) bytes in size. * The first slot of the first page is reserved for user-mode exception handling
* The first slot of the first page is reserved for user-mode exception handling. * @url https://switchbrew.org/wiki/Thread_Local_Storage
* Read more about TLS here: https://switchbrew.org/wiki/Thread_Local_Storage
*/ */
struct TlsPage { struct TlsPage {
u64 address; //!< The address of the page allocated for TLS u64 address; //!< The address of the page allocated for TLS
@ -64,13 +63,12 @@ namespace skyline {
}; };
/** /**
* @brief Returns a TLS slot from an arbitrary TLS page
* @return The address of a free TLS slot * @return The address of a free TLS slot
*/ */
u64 GetTlsSlot(); u64 GetTlsSlot();
/** /**
* @brief This initializes heap and the initial TLS page * @brief Initializes heap and the initial TLS page
*/ */
void InitializeMemory(); void InitializeMemory();
@ -78,7 +76,7 @@ namespace skyline {
friend OS; friend OS;
/** /**
* @brief This is used as the output for functions that return created kernel objects * @brief The output for functions that return created kernel objects
* @tparam objectClass The class of the kernel object * @tparam objectClass The class of the kernel object
*/ */
template<typename objectClass> template<typename objectClass>
@ -87,17 +85,14 @@ namespace skyline {
KHandle handle; //!< The handle of the object in the process KHandle handle; //!< The handle of the object in the process
}; };
/**
* @brief This enum is used to describe the current status of the process
*/
enum class Status { enum class Status {
Created, //!< The process was created but the main thread has not started yet Created, //!< The process was created but the main thread has not started yet
Started, //!< The process has been started Started, //!< The process has been started
Exiting //!< The process is exiting Exiting, //!< The process is exiting
} status = Status::Created; //!< The state of the process } status = Status::Created;
/** /**
* @brief This is used to hold information about a single waiting thread for mutexes and conditional variables * @brief Metadata on a thread waiting for mutexes or conditional variables
*/ */
struct WaitStatus { struct WaitStatus {
std::atomic_bool flag{false}; //!< The underlying atomic flag of the thread std::atomic_bool flag{false}; //!< The underlying atomic flag of the thread
@ -119,12 +114,11 @@ namespace skyline {
std::vector<std::shared_ptr<TlsPage>> tlsPages; //!< A vector of all allocated TLS pages std::vector<std::shared_ptr<TlsPage>> tlsPages; //!< A vector of all allocated TLS pages
std::shared_ptr<type::KSharedMemory> stack; //!< The shared memory used to hold the stack of the main thread std::shared_ptr<type::KSharedMemory> stack; //!< The shared memory used to hold the stack of the main thread
std::shared_ptr<KPrivateMemory> heap; //!< The kernel memory object backing the allocated heap std::shared_ptr<KPrivateMemory> heap; //!< The kernel memory object backing the allocated heap
Mutex mutexLock; //!< This mutex is to prevent concurrent mutex operations to happen at once Mutex mutexLock; //!< Synchronizes all concurrent guest mutex operations
Mutex conditionalLock; //!< This mutex is to prevent concurrent conditional variable operations to happen at once Mutex conditionalLock; //!< Synchronizes all concurrent guest conditional variable operations
/** /**
* @brief Creates a KThread object for the main thread and opens the process's memory file * @brief Creates a KThread object for the main thread and opens the process's memory file
* @param state The state of the device
* @param pid The PID of the main thread * @param pid The PID of the main thread
* @param entryPoint The address to start execution at * @param entryPoint The address to start execution at
* @param stack The KSharedMemory object for Stack memory allocated by the guest process * @param stack The KSharedMemory object for Stack memory allocated by the guest process
@ -148,7 +142,7 @@ namespace skyline {
std::shared_ptr<KThread> CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, i8 priority); std::shared_ptr<KThread> CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, i8 priority);
/** /**
* @brief This returns the host address for a specific address in guest memory * @brief Returns the host address for a specific address in guest memory
* @param address The corresponding guest address * @param address The corresponding guest address
* @return The corresponding host address * @return The corresponding host address
*/ */
@ -158,7 +152,7 @@ namespace skyline {
* @tparam Type The type of the pointer to return * @tparam Type The type of the pointer to return
* @param address The address on the guest * @param address The address on the guest
* @return A pointer corresponding to a certain address on the guest * @return A pointer corresponding to a certain address on the guest
* @note This can return a nullptr if the address is invalid * @note If the address is invalid then nullptr will be returned
*/ */
template<typename Type> template<typename Type>
inline Type *GetPointer(u64 address) { inline Type *GetPointer(u64 address) {
@ -167,9 +161,6 @@ namespace skyline {
/** /**
* @brief Returns a reference to an object from guest memory * @brief Returns a reference to an object from guest memory
* @tparam Type The type of the object to be read
* @param address The address of the object
* @return A reference to object with type T
*/ */
template<typename Type> template<typename Type>
inline Type &GetReference(u64 address) { inline Type &GetReference(u64 address) {
@ -250,7 +241,7 @@ namespace skyline {
* @param destination The address to the location where the process memory is written * @param destination The address to the location where the process memory is written
* @param offset The address to read from in process memory * @param offset The address to read from in process memory
* @param size The amount of memory to be read * @param size The amount of memory to be read
* @param forceGuest This flag forces the write to be performed in guest address space * @param forceGuest Forces the write to be performed in guest address space
*/ */
void ReadMemory(void *destination, u64 offset, size_t size, bool forceGuest = false); void ReadMemory(void *destination, u64 offset, size_t size, bool forceGuest = false);
@ -259,7 +250,7 @@ namespace skyline {
* @param source The address of where the data to be written is present * @param source The address of where the data to be written is present
* @param offset The address to write to in process memory * @param offset The address to write to in process memory
* @param size The amount of memory to be written * @param size The amount of memory to be written
* @param forceGuest This flag forces the write to be performed in guest address space * @param forceGuest Forces the write to be performed in guest address space
*/ */
void WriteMemory(const void *source, u64 offset, size_t size, bool forceGuest = false); void WriteMemory(const void *source, u64 offset, size_t size, bool forceGuest = false);
@ -345,15 +336,14 @@ namespace skyline {
std::optional<HandleOut<KMemory>> GetMemoryObject(u64 address); std::optional<HandleOut<KMemory>> GetMemoryObject(u64 address);
/** /**
* @brief This deletes a certain handle from the handle table * @brief Closes a handle in the handle table
* @param handle The handle to delete
*/ */
inline void DeleteHandle(KHandle handle) { inline void CloseHandle(KHandle handle) {
handles.at(handle - constant::BaseHandleIndex) = nullptr; handles.at(handle - constant::BaseHandleIndex) = nullptr;
} }
/** /**
* @brief This locks the Mutex at the specified address * @brief Locks the Mutex at the specified address
* @param address The address of the mutex * @param address The address of the mutex
* @param owner The handle of the current mutex owner * @param owner The handle of the current mutex owner
* @return If the mutex was successfully locked * @return If the mutex was successfully locked
@ -361,7 +351,7 @@ namespace skyline {
bool MutexLock(u64 address, KHandle owner); bool MutexLock(u64 address, KHandle owner);
/** /**
* @brief This unlocks the Mutex at the specified address * @brief Unlocks the Mutex at the specified address
* @param address The address of the mutex * @param address The address of the mutex
* @return If the mutex was successfully unlocked * @return If the mutex was successfully unlocked
*/ */
@ -376,14 +366,14 @@ namespace skyline {
bool ConditionalVariableWait(u64 conditionalAddress, u64 mutexAddress, u64 timeout); bool ConditionalVariableWait(u64 conditionalAddress, u64 mutexAddress, u64 timeout);
/** /**
* @brief This signals a number of conditional variable waiters * @brief Signals a number of conditional variable waiters
* @param address The address of the conditional variable * @param address The address of the conditional variable
* @param amount The amount of waiters to signal * @param amount The amount of waiters to signal
*/ */
void ConditionalVariableSignal(u64 address, u64 amount); void ConditionalVariableSignal(u64 address, u64 amount);
/** /**
* @brief This resets the object to an unsignalled state * @brief Resets the object to an unsignalled state
*/ */
inline void ResetSignal() { inline void ResetSignal() {
signalled = false; signalled = false;

View File

@ -15,20 +15,20 @@ namespace skyline::kernel::type {
*/ */
class KSession : public KSyncObject { class KSession : public KSyncObject {
public: public:
std::shared_ptr<service::BaseService> serviceObject; //!< A shared pointer to the service class std::shared_ptr<service::BaseService> serviceObject;
std::unordered_map<KHandle, std::shared_ptr<service::BaseService>> domainTable; //!< This maps from a virtual handle to it's service std::unordered_map<KHandle, std::shared_ptr<service::BaseService>> domainTable; //!< A map from a virtual handle to it's service
KHandle handleIndex{0x1}; //!< The currently allocated handle index KHandle handleIndex{0x1}; //!< The currently allocated handle index
enum class ServiceStatus { Open, Closed } serviceStatus{ServiceStatus::Open}; //!< If the session is open or closed bool isOpen{true}; //!< If the session is open or not
bool isDomain{}; //!< Holds if this is a domain session or not bool isDomain{}; //!< If this is a domain session or not
/** /**
* @param state The state of the device
* @param serviceObject A shared pointer to the service class * @param serviceObject A shared pointer to the service class
*/ */
KSession(const DeviceState &state, std::shared_ptr<service::BaseService> &serviceObject) : serviceObject(serviceObject), KSyncObject(state, KType::KSession) {} KSession(const DeviceState &state, std::shared_ptr<service::BaseService> &serviceObject) : serviceObject(serviceObject), KSyncObject(state, KType::KSession) {}
/** /**
* This converts this session into a domain session (https://switchbrew.org/wiki/IPC_Marshalling#Domains) * @brief Converts this session into a domain session
* @url https://switchbrew.org/wiki/IPC_Marshalling#Domains
* @return The virtual handle of this service in the domain * @return The virtual handle of this service in the domain
*/ */
KHandle ConvertDomain() { KHandle ConvertDomain() {

View File

@ -12,26 +12,20 @@ namespace skyline::kernel::type {
class KSharedMemory : public KMemory { class KSharedMemory : public KMemory {
private: private:
int fd; //!< A file descriptor to the underlying shared memory int fd; //!< A file descriptor to the underlying shared memory
memory::MemoryState initialState; //!< This is to hold the initial state for the Map call memory::MemoryState initialState; //!< The initial state is stored for the Map call
public: public:
/**
* @brief This holds the address and size of a process's mapping
*/
struct MapInfo { struct MapInfo {
u64 address; u64 address;
size_t size; size_t size;
memory::Permission permission; memory::Permission permission;
/** constexpr bool Valid() {
* @brief Returns if the object is valid return address && size && permission.Get();
* @return If the MapInfo object is valid }
*/
inline bool Valid() { return address && size && permission.Get(); }
} kernel, guest; } kernel, guest;
/** /**
* @param state The state of the device
* @param address The address of the allocation on the kernel (If NULL then an arbitrary address is picked) * @param address The address of the allocation on the kernel (If NULL then an arbitrary address is picked)
* @param size The size of the allocation on the kernel * @param size The size of the allocation on the kernel
* @param permission The permission of the kernel process * @param permission The permission of the kernel process

View File

@ -13,10 +13,6 @@ namespace skyline::kernel::type {
public: public:
std::atomic<bool> signalled{false}; //!< If the current object is signalled (Used as object stays signalled till the signal is consumed) std::atomic<bool> signalled{false}; //!< If the current object is signalled (Used as object stays signalled till the signal is consumed)
/**
* @param state The state of the device
* @param type The type of the object
*/
KSyncObject(const DeviceState &state, skyline::kernel::type::KType type) : KObject(state, type) {}; KSyncObject(const DeviceState &state, skyline::kernel::type::KType type) : KObject(state, type) {};
/** /**

View File

@ -17,7 +17,7 @@ namespace skyline::kernel::type {
u64 entryArg; //!< An argument to pass to the process on entry u64 entryArg; //!< An argument to pass to the process on entry
/** /**
* @brief This holds a range of priorities for a corresponding system * @brief A range of priorities for a corresponding system
*/ */
struct Priority { struct Priority {
i8 low; //!< The low range of priority i8 low; //!< The low range of priority
@ -28,7 +28,7 @@ namespace skyline::kernel::type {
* @param value The priority value to rescale * @param value The priority value to rescale
* @return The rescaled priority value according to this range * @return The rescaled priority value according to this range
*/ */
constexpr inline i8 Rescale(const Priority &priority, i8 value) { constexpr i8 Rescale(const Priority &priority, i8 value) {
return static_cast<i8>(priority.low + ((static_cast<float>(priority.high - priority.low) / static_cast<float>(priority.low - priority.high)) * (static_cast<float>(value) - priority.low))); return static_cast<i8>(priority.low + ((static_cast<float>(priority.high - priority.low) / static_cast<float>(priority.low - priority.high)) * (static_cast<float>(value) - priority.low)));
} }
@ -36,7 +36,7 @@ namespace skyline::kernel::type {
* @param value The priority value to check for validity * @param value The priority value to check for validity
* @return If the supplied priority value is valid * @return If the supplied priority value is valid
*/ */
constexpr inline bool Valid(i8 value) { constexpr bool Valid(i8 value) {
return (value >= low) && (value <= high); return (value >= low) && (value <= high);
} }
}; };
@ -45,12 +45,12 @@ namespace skyline::kernel::type {
enum class Status { enum class Status {
Created, //!< The thread has been created but has not been started yet Created, //!< The thread has been created but has not been started yet
Running, //!< The thread is running currently Running, //!< The thread is running currently
Dead //!< The thread is dead and not running Dead, //!< The thread is dead and not running
} status = Status::Created; //!< The state of the thread } status = Status::Created;
std::atomic<bool> cancelSync{false}; //!< This is to flag to a thread to cancel a synchronization call it currently is in std::atomic<bool> cancelSync{false}; //!< This is to flag to a thread to cancel a synchronization call it currently is in
std::shared_ptr<type::KSharedMemory> ctxMemory; //!< The KSharedMemory of the shared memory allocated by the guest process TLS std::shared_ptr<type::KSharedMemory> ctxMemory; //!< The KSharedMemory of the shared memory allocated by the guest process TLS
KHandle handle; // The handle of the object in the handle table KHandle handle; // The handle of the object in the handle table
pid_t tid; //!< The TID of the current thread pid_t tid; //!< The Linux Thread ID of the current thread
u64 stackTop; //!< The top of the stack (Where it starts growing downwards from) u64 stackTop; //!< The top of the stack (Where it starts growing downwards from)
u64 tls; //!< The address of TLS (Thread Local Storage) slot assigned to the current thread u64 tls; //!< The address of TLS (Thread Local Storage) slot assigned to the current thread
i8 priority; //!< The priority of a thread in Nintendo format i8 priority; //!< The priority of a thread in Nintendo format
@ -59,7 +59,6 @@ namespace skyline::kernel::type {
Priority switchPriority{0, 63}; //!< The range of priorities for the Nintendo Switch Priority switchPriority{0, 63}; //!< The range of priorities for the Nintendo Switch
/** /**
* @param state The state of the device
* @param handle The handle of the current thread * @param handle The handle of the current thread
* @param selfTid The TID of this thread * @param selfTid The TID of this thread
* @param entryPoint The address to start execution at * @param entryPoint The address to start execution at
@ -78,12 +77,12 @@ namespace skyline::kernel::type {
~KThread(); ~KThread();
/** /**
* @brief This starts this thread process * @brief Starts this thread process
*/ */
void Start(); void Start();
/** /**
* @brief This kills the thread * @brief Kills the thread process
*/ */
void Kill(); void Kill();

View File

@ -4,6 +4,7 @@
#include <asm/unistd.h> #include <asm/unistd.h>
#include <nce.h> #include <nce.h>
#include <os.h> #include <os.h>
#include "KProcess.h"
#include "KTransferMemory.h" #include "KTransferMemory.h"
namespace skyline::kernel::type { namespace skyline::kernel::type {

View File

@ -18,7 +18,6 @@ namespace skyline::kernel::type {
size_t size; //!< The current size of the allocated memory size_t size; //!< The current size of the allocated memory
/** /**
* @param state The state of the device
* @param host If to map the memory on host or guest * @param host If to map the memory on host or guest
* @param address The address to map to (If NULL an arbitrary address is picked) * @param address The address to map to (If NULL an arbitrary address is picked)
* @param size The size of the allocation * @param size The size of the allocation

View File

@ -7,11 +7,11 @@
namespace skyline::loader { namespace skyline::loader {
/** /**
* @brief The Executable struct encapsulates the segments of an executable * @brief The contents of an executable binary abstracted away from the derivatives of Loader
*/ */
struct Executable { struct Executable {
/** /**
* @brief This holds the contents and offset of an executable segment * @brief The contents and offset of an executable segment
*/ */
struct Segment { struct Segment {
std::vector<u8> contents; //!< The raw contents of the segment std::vector<u8> contents; //!< The raw contents of the segment

View File

@ -3,6 +3,7 @@
#include <nce.h> #include <nce.h>
#include <os.h> #include <os.h>
#include <kernel/types/KProcess.h>
#include <kernel/memory.h> #include <kernel/memory.h>
#include "loader.h" #include "loader.h"

View File

@ -8,7 +8,7 @@
namespace skyline::loader { namespace skyline::loader {
/** /**
* @brief This enumerates the types of ROM files * @brief The types of ROM files
* @note This needs to be synchronized with emu.skyline.loader.BaseLoader.RomFormat * @note This needs to be synchronized with emu.skyline.loader.BaseLoader.RomFormat
*/ */
enum class RomFormat { enum class RomFormat {
@ -20,7 +20,7 @@ namespace skyline::loader {
}; };
/** /**
* @brief This enumerates all possible results when parsing ROM files * @brief All possible results when parsing ROM files
* @note This needs to be synchronized with emu.skyline.loader.LoaderResult * @note This needs to be synchronized with emu.skyline.loader.LoaderResult
*/ */
enum class LoaderResult : int8_t { enum class LoaderResult : int8_t {
@ -29,7 +29,7 @@ namespace skyline::loader {
MissingHeaderKey, MissingHeaderKey,
MissingTitleKey, MissingTitleKey,
MissingTitleKek, MissingTitleKek,
MissingKeyArea MissingKeyArea,
}; };
/** /**
@ -48,7 +48,7 @@ namespace skyline::loader {
class Loader { class Loader {
protected: protected:
/** /**
* @brief This contains information about the placement of an executable in memory * @brief Information about the placement of an executable in memory
*/ */
struct ExecutableLoadInfo { struct ExecutableLoadInfo {
size_t base; //!< The base of the loaded executable size_t base; //!< The base of the loaded executable
@ -56,7 +56,7 @@ namespace skyline::loader {
}; };
/** /**
* @brief This loads an executable into memory * @brief Loads an executable into memory
* @param process The process to load the executable into * @param process The process to load the executable into
* @param executable The executable itself * @param executable The executable itself
* @param offset The offset from the base address that the executable should be placed at * @param offset The offset from the base address that the executable should be placed at
@ -78,9 +78,8 @@ namespace skyline::loader {
} }
/** /**
* @brief This loads in the data of the main process * @brief Loads in the data of the main process
* @param process The process to load in the data * @param process The process to load in the data
* @param state The state of the device
*/ */
virtual void LoadProcessData(const std::shared_ptr<kernel::type::KProcess> process, const DeviceState &state) = 0; virtual void LoadProcessData(const std::shared_ptr<kernel::type::KProcess> process, const DeviceState &state) = 0;
}; };

View File

@ -8,7 +8,8 @@
namespace skyline::loader { namespace skyline::loader {
/** /**
* @brief The NcaLoader class allows loading an NCA's ExeFS through the Loader interface (https://switchbrew.org/wiki/NSO) * @brief The NcaLoader class allows loading an NCA's ExeFS through the Loader interface
* @url https://switchbrew.org/wiki/NSO
*/ */
class NcaLoader : public Loader { class NcaLoader : public Loader {
private: private:
@ -18,7 +19,7 @@ namespace skyline::loader {
NcaLoader(const std::shared_ptr<vfs::Backing> &backing, const std::shared_ptr<crypto::KeyStore> &keyStore); NcaLoader(const std::shared_ptr<vfs::Backing> &backing, const std::shared_ptr<crypto::KeyStore> &keyStore);
/** /**
* @brief This loads an ExeFS into memory * @brief Loads an ExeFS into memory
* @param exefs A filesystem object containing the ExeFS filesystem to load into memory * @param exefs A filesystem object containing the ExeFS filesystem to load into memory
* @param process The process to load the ExeFS into * @param process The process to load the ExeFS into
*/ */

View File

@ -7,21 +7,16 @@
namespace skyline::loader { namespace skyline::loader {
/** /**
* @brief The NroLoader class abstracts access to an NRO file through the Loader interface (https://switchbrew.org/wiki/NRO) * @brief The NroLoader class abstracts access to an NRO file through the Loader interface
* @url https://switchbrew.org/wiki/NRO
*/ */
class NroLoader : public Loader { class NroLoader : public Loader {
private: private:
/**
* @brief This holds a single data segment's offset and size
*/
struct NroSegmentHeader { struct NroSegmentHeader {
u32 offset; //!< The offset of the region u32 offset;
u32 size; //!< The size of the region u32 size;
}; };
/**
* @brief This holds the header of an NRO file
*/
struct NroHeader { struct NroHeader {
u32 _pad0_; u32 _pad0_;
u32 modOffset; //!< The offset of the MOD metadata u32 modOffset; //!< The offset of the MOD metadata
@ -38,7 +33,7 @@ namespace skyline::loader {
u32 bssSize; //!< The size of the bss segment u32 bssSize; //!< The size of the bss segment
u32 _pad2_; u32 _pad2_;
u64 buildId[4]; //!< The build ID of the NRO std::array<u64, 4> buildId; //!< The build ID of the NRO
u64 _pad3_; u64 _pad3_;
NroSegmentHeader apiInfo; //!< The .apiInfo segment header NroSegmentHeader apiInfo; //!< The .apiInfo segment header
@ -46,29 +41,27 @@ namespace skyline::loader {
NroSegmentHeader dynsym; //!< The .dynsym segment header NroSegmentHeader dynsym; //!< The .dynsym segment header
} header{}; } header{};
/**
* @brief This holds a single asset section's offset and size
*/
struct NroAssetSection { struct NroAssetSection {
u64 offset; //!< The offset of the region u64 offset;
u64 size; //!< The size of the region u64 size;
}; };
/** /**
* @brief This holds various metadata about an NRO, it is only used by homebrew * @brief The asset section was created by homebrew developers to store additional data for their applications to use
* @note This would actually be retrieved by NRO homebrew by reading the NRO file itself (reading it's own binary) but libnx homebrew wrongly detects the images to be running in NSO mode where the RomFS is handled by HOS, this allows us to just provide the parsed data from the asset section to it directly
*/ */
struct NroAssetHeader { struct NroAssetHeader {
u32 magic; //!< The asset section magic "ASET" u32 magic; //!< "ASET"
u32 version; //!< The format version u32 version;
NroAssetSection icon; //!< The header describing the location of the icon NroAssetSection icon;
NroAssetSection nacp; //!< The header describing the location of the NACP NroAssetSection nacp;
NroAssetSection romFs; //!< The header describing the location of the RomFS NroAssetSection romFs;
} assetHeader{}; } assetHeader{};
std::shared_ptr<vfs::Backing> backing; //!< The backing of the NRO loader std::shared_ptr<vfs::Backing> backing;
/** /**
* @brief This reads the data of the specified segment * @brief Reads the data of the specified segment
* @param segment The header of the segment to read * @param segment The header of the segment to read
* @return A buffer containing the data of the requested segment * @return A buffer containing the data of the requested segment
*/ */

View File

@ -7,10 +7,13 @@
namespace skyline::loader { namespace skyline::loader {
/** /**
* @brief The NsoLoader class abstracts access to an NSO file through the Loader interface (https://switchbrew.org/wiki/NSO) * @brief The NsoLoader class abstracts access to an NSO file through the Loader interface
* @url https://switchbrew.org/wiki/NSO
*/ */
class NsoLoader : public Loader { class NsoLoader : public Loader {
private: private:
std::shared_ptr<vfs::Backing> backing;
union NsoFlags { union NsoFlags {
struct { struct {
bool textCompressed : 1; //!< .text is compressed bool textCompressed : 1; //!< .text is compressed
@ -20,13 +23,10 @@ namespace skyline::loader {
bool roHash : 1; //!< .rodata hash should be checked before loading bool roHash : 1; //!< .rodata hash should be checked before loading
bool dataHash : 1; //!< .data hash should be checked before loading bool dataHash : 1; //!< .data hash should be checked before loading
}; };
u32 raw; //!< The raw value of the flags u32 raw;
}; };
static_assert(sizeof(NsoFlags) == 0x4); static_assert(sizeof(NsoFlags) == 0x4);
/**
* @brief This holds a single data segment's offset, loading offset and size
*/
struct NsoSegmentHeader { struct NsoSegmentHeader {
u32 fileOffset; //!< The offset of the segment in the NSO u32 fileOffset; //!< The offset of the segment in the NSO
u32 memoryOffset; //!< The memory offset where the region should be loaded u32 memoryOffset; //!< The memory offset where the region should be loaded
@ -34,9 +34,6 @@ namespace skyline::loader {
}; };
static_assert(sizeof(NsoSegmentHeader) == 0xC); static_assert(sizeof(NsoSegmentHeader) == 0xC);
/**
* @brief This holds the header of an NSO file
*/
struct NsoHeader { struct NsoHeader {
u32 magic; //!< The NSO magic "NSO0" u32 magic; //!< The NSO magic "NSO0"
u32 version; //!< The version of the application u32 version; //!< The version of the application
@ -50,7 +47,7 @@ namespace skyline::loader {
NsoSegmentHeader data; //!< The .data segment header NsoSegmentHeader data; //!< The .data segment header
u32 bssSize; //!< The size of the .bss segment u32 bssSize; //!< The size of the .bss segment
u64 buildId[4]; //!< The build ID of the NSO std::array<u64, 4> buildId; //!< The build ID of the NSO
u32 textCompressedSize; //!< The size of the compressed .text segment u32 textCompressedSize; //!< The size of the compressed .text segment
u32 roCompressedSize; //!< The size of the compressed .rodata segment u32 roCompressedSize; //!< The size of the compressed .rodata segment
@ -62,14 +59,12 @@ namespace skyline::loader {
u64 dynstr; //!< The .rodata-relative offset of .dynstr u64 dynstr; //!< The .rodata-relative offset of .dynstr
u64 dynsym; //!< The .rodata-relative offset of .dynsym u64 dynsym; //!< The .rodata-relative offset of .dynsym
u64 segmentHashes[3][4]; //!< The SHA256 checksums of the .text, .rodata and .data segments std::array<std::array<u64, 4>, 3> segmentHashes; //!< The SHA256 checksums of the .text, .rodata and .data segments
}; };
static_assert(sizeof(NsoHeader) == 0x100); static_assert(sizeof(NsoHeader) == 0x100);
std::shared_ptr<vfs::Backing> backing; //!< The backing of the NSO loader
/** /**
* @brief This reads the specified segment from the backing and decompresses it if needed * @brief Reads the specified segment from the backing and decompresses it if needed
* @param segment The header of the segment to read * @param segment The header of the segment to read
* @param compressedSize The compressed size of the segment, 0 if the segment is not compressed * @param compressedSize The compressed size of the segment, 0 if the segment is not compressed
* @return A buffer containing the data of the requested segment * @return A buffer containing the data of the requested segment
@ -80,7 +75,7 @@ namespace skyline::loader {
NsoLoader(const std::shared_ptr<vfs::Backing> &backing); NsoLoader(const std::shared_ptr<vfs::Backing> &backing);
/** /**
* @brief This loads an NSO into memory, offset by the given amount * @brief Loads an NSO into memory, offset by the given amount
* @param backing The backing of the NSO * @param backing The backing of the NSO
* @param process The process to load the NSO into * @param process The process to load the NSO into
* @param offset The offset from the base address to place the NSO * @param offset The offset from the base address to place the NSO

View File

@ -11,12 +11,13 @@
namespace skyline::loader { namespace skyline::loader {
/** /**
* @brief The NspLoader class consolidates all the data in an NSP providing a simple way to load an application and access its metadata (https://switchbrew.org/wiki/NCA_Format#PFS0) * @brief The NspLoader class consolidates all the data in an NSP providing a simple way to load an application and access its metadata
* @url https://switchbrew.org/wiki/NCA_Format#PFS0
*/ */
class NspLoader : public Loader { class NspLoader : public Loader {
private: private:
std::shared_ptr<vfs::PartitionFileSystem> nsp; //!< A shared pointer to the NSP's PFS0 std::shared_ptr<vfs::PartitionFileSystem> nsp; //!< A shared pointer to the NSP's PFS0
std::shared_ptr<vfs::RomFileSystem> controlRomFs; //!< A pointer to the control NCA's RomFS std::shared_ptr<vfs::RomFileSystem> controlRomFs; //!< A shared pointer to the control NCA's RomFS
std::optional<vfs::NCA> programNca; //!< The main program NCA within the NSP std::optional<vfs::NCA> programNca; //!< The main program NCA within the NSP
std::optional<vfs::NCA> controlNca; //!< The main control NCA within the NSP std::optional<vfs::NCA> controlNca; //!< The main control NCA within the NSP

View File

@ -4,10 +4,12 @@
#include <sched.h> #include <sched.h>
#include <unistd.h> #include <unistd.h>
#include "os.h" #include "os.h"
#include "gpu.h"
#include "jvm.h" #include "jvm.h"
#include "kernel/types/KProcess.h"
#include "kernel/svc.h"
#include "nce/guest.h" #include "nce/guest.h"
#include "nce/instructions.h" #include "nce/instructions.h"
#include "kernel/svc.h"
#include "nce.h" #include "nce.h"
extern bool Halt; extern bool Halt;
@ -194,7 +196,6 @@ namespace skyline {
regStr += fmt::format("\nStack Pointer: 0x{:X}", ctx->sp); regStr += fmt::format("\nStack Pointer: 0x{:X}", ctx->sp);
constexpr u8 numRegisters{31}; //!< The amount of general-purpose registers in ARMv8 constexpr u8 numRegisters{31}; //!< The amount of general-purpose registers in ARMv8
for (u8 index{}; index < numRegisters - 2; index += 2) { for (u8 index{}; index < numRegisters - 2; index += 2) {
auto xStr{index < 10 ? " X" : "X"}; auto xStr{index < 10 ? " X" : "X"};
regStr += fmt::format("\n{}{}: 0x{:<16X} {}{}: 0x{:X}", xStr, index, ctx->registers.regs[index], xStr, index + 1, ctx->registers.regs[index + 1]); regStr += fmt::format("\n{}{}: 0x{:<16X} {}{}: 0x{:X}", xStr, index, ctx->registers.regs[index], xStr, index + 1, ctx->registers.regs[index + 1]);

View File

@ -3,8 +3,8 @@
#pragma once #pragma once
#include "common.h"
#include <sys/wait.h> #include <sys/wait.h>
#include "kernel/types/KSharedMemory.h"
namespace skyline { namespace skyline {
/** /**
@ -12,11 +12,11 @@ namespace skyline {
*/ */
class NCE { class NCE {
private: private:
DeviceState &state; //!< The state of the device DeviceState &state;
std::unordered_map<pid_t, std::shared_ptr<std::thread>> threadMap; //!< This maps all of the host threads to their corresponding kernel thread std::unordered_map<pid_t, std::shared_ptr<std::thread>> threadMap; //!< This maps all of the host threads to their corresponding kernel thread
/** /**
* @brief This function is the event loop of a kernel thread managing a guest thread * @brief The event loop of a kernel thread managing a guest thread
* @param thread The PID of the thread to manage * @param thread The PID of the thread to manage
*/ */
void KernelThread(pid_t thread); void KernelThread(pid_t thread);
@ -30,7 +30,7 @@ namespace skyline {
~NCE(); ~NCE();
/** /**
* @brief This function is the main event loop of the program * @brief The main event loop of the program
*/ */
void Execute(); void Execute();
@ -65,14 +65,14 @@ namespace skyline {
void StartThread(u64 entryArg, u32 handle, std::shared_ptr<kernel::type::KThread> &thread); void StartThread(u64 entryArg, u32 handle, std::shared_ptr<kernel::type::KThread> &thread);
/** /**
* @brief This prints out a trace and the CPU context * @brief Prints out a trace and the CPU context
* @param numHist The amount of previous instructions to print (Can be 0) * @param numHist The amount of previous instructions to print (Can be 0)
* @param ctx The ThreadContext of the thread to log * @param ctx The ThreadContext of the thread to log
*/ */
void ThreadTrace(u16 numHist = 10, ThreadContext *ctx = nullptr); void ThreadTrace(u16 numHist = 10, ThreadContext *ctx = nullptr);
/** /**
* @brief This patches specific parts of the code * @brief Patches specific parts of the code
* @param code A vector with the code to be patched * @param code A vector with the code to be patched
* @param baseAddress The address at which the code is mapped * @param baseAddress The address at which the code is mapped
* @param offset The offset of the code block from the base address * @param offset The offset of the code block from the base address

View File

@ -17,28 +17,28 @@ namespace skyline {
#endif #endif
/** /**
* @brief This is the entry point for all guest threads * @brief The entry point for all guest threads
* @param address The address of the actual thread entry point * @param address The address of the actual thread entry point
*/ */
void GuestEntry(u64 address); void GuestEntry(u64 address);
/** /**
* @brief This saves the context from CPU registers into TLS * @brief Saves the context from CPU registers into TLS
*/ */
extern "C" void SaveCtx(void); extern "C" void SaveCtx(void);
/** /**
* @brief This loads the context from TLS into CPU registers * @brief Loads the context from TLS into CPU registers
*/ */
extern "C" void LoadCtx(void); extern "C" void LoadCtx(void);
/** /**
* @brief This rescales the clock to Tegra X1 levels and puts the output on stack * @brief Rescales the clock to Tegra X1 levels and puts the output on stack
*/ */
extern "C" __noreturn void RescaleClock(void); extern "C" __noreturn void RescaleClock(void);
/** /**
* @brief This is used to handle all SVC calls * @brief Handles all SVC calls
* @param pc The address of PC when the call was being done * @param pc The address of PC when the call was being done
* @param svc The SVC ID of the SVC being called * @param svc The SVC ID of the SVC being called
*/ */

View File

@ -20,7 +20,7 @@ namespace skyline {
using i8 = __int8_t; //!< Signed 8-bit integer using i8 = __int8_t; //!< Signed 8-bit integer
/** /**
* @brief This union holds the state of all the general purpose registers in the guest * @brief The state of all the general purpose registers in the guest
* @note Read about ARMv8 registers here: https://developer.arm.com/docs/100878/latest/registers * @note Read about ARMv8 registers here: https://developer.arm.com/docs/100878/latest/registers
* @note X30 or LR is not provided as it is reserved for other uses * @note X30 or LR is not provided as it is reserved for other uses
*/ */
@ -122,9 +122,6 @@ namespace skyline {
}; };
}; };
/**
* @brief This enumeration is used to convey the state of a thread to the kernel
*/
enum class ThreadState : u8 { enum class ThreadState : u8 {
NotReady = 0, //!< The thread hasn't yet entered the entry handler NotReady = 0, //!< The thread hasn't yet entered the entry handler
Running = 1, //!< The thread is currently executing code Running = 1, //!< The thread is currently executing code
@ -136,7 +133,7 @@ namespace skyline {
}; };
/** /**
* @brief This enumeration holds the functions that can be run on the guest process * @brief The functions that can be run on the guest process
*/ */
enum class ThreadCall : u8 { enum class ThreadCall : u8 {
Syscall = 1, //!< A linux syscall needs to be called from the guest Syscall = 1, //!< A linux syscall needs to be called from the guest
@ -145,7 +142,7 @@ namespace skyline {
}; };
/** /**
* @brief This structure holds the context of a thread during kernel calls * @brief The context of a thread during kernel calls, it is stored in TLS on each guest thread
*/ */
struct ThreadContext { struct ThreadContext {
ThreadState state; //!< The state of the guest ThreadState state; //!< The state of the guest

View File

@ -7,29 +7,24 @@ namespace skyline {
namespace regs { namespace regs {
enum X { X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30 }; enum X { X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30 };
enum W { W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30 }; enum W { W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30 };
enum S { Sp, Pc };
} }
namespace instr { namespace instr {
/** /**
* @brief A bit-field struct that encapsulates a BRK instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/brk-breakpoint-instruction. * @url https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/brk-breakpoint-instruction
*/ */
struct Brk { struct Brk {
/** /**
* @brief Creates a BRK instruction with a specific immediate value, used for generating BRK opcodes * @brief Creates a BRK instruction with a specific immediate value, used for generating BRK opcodes
* @param value The immediate value of the instruction * @param value The immediate value of the instruction
*/ */
inline constexpr Brk(u16 value) { constexpr Brk(u16 value) {
sig0 = 0x0; sig0 = 0x0;
this->value = value; this->value = value;
sig1 = 0x6A1; sig1 = 0x6A1;
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid BRK instruction
*/
inline constexpr bool Verify() {
return (sig0 == 0x0 && sig1 == 0x6A1); return (sig0 == 0x0 && sig1 == 0x6A1);
} }
@ -39,20 +34,16 @@ namespace skyline {
u32 value : 16; //!< 16-bit immediate value u32 value : 16; //!< 16-bit immediate value
u16 sig1 : 11; //!< 11-bit signature (0x6A1) u16 sig1 : 11; //!< 11-bit signature (0x6A1)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Brk) == sizeof(u32)); static_assert(sizeof(Brk) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a SVC instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/svc-supervisor-call. * @url https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/svc-supervisor-call
*/ */
struct Svc { struct Svc {
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid SVC instruction
*/
inline constexpr bool Verify() {
return (sig0 == 0x1 && sig1 == 0x6A0); return (sig0 == 0x1 && sig1 == 0x6A0);
} }
@ -62,31 +53,26 @@ namespace skyline {
u32 value : 16; //!< 16-bit immediate value u32 value : 16; //!< 16-bit immediate value
u16 sig1 : 11; //!< 11-bit signature (0x6A1) u16 sig1 : 11; //!< 11-bit signature (0x6A1)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Svc) == sizeof(u32)); static_assert(sizeof(Svc) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a MRS instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/mrs-move-system-register. * @url https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/mrs-move-system-register
*/ */
struct Mrs { struct Mrs {
/** /**
* @brief Creates a MRS instruction, used for generating BRK opcodes
* @param srcReg The source system register * @param srcReg The source system register
* @param dstReg The destination Xn register * @param dstReg The destination Xn register
*/ */
inline constexpr Mrs(u32 srcReg, regs::X dstReg) { constexpr Mrs(u32 srcReg, regs::X dstReg) {
this->srcReg = srcReg; this->srcReg = srcReg;
this->destReg = dstReg; this->destReg = dstReg;
sig = 0xD53; sig = 0xD53;
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MRS instruction
*/
inline constexpr bool Verify() {
return (sig == 0xD53); return (sig == 0xD53);
} }
@ -96,20 +82,16 @@ namespace skyline {
u32 srcReg : 15; //!< 15-bit source register u32 srcReg : 15; //!< 15-bit source register
u16 sig : 12; //!< 16-bit signature (0xD53) u16 sig : 12; //!< 16-bit signature (0xD53)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Mrs) == sizeof(u32)); static_assert(sizeof(Mrs) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a MSR instruction. See https://developer.arm.com/docs/ddi0596/g/base-instructions-alphabetic-order/msr-register-move-general-purpose-register-to-system-register. * @url https://developer.arm.com/docs/ddi0596/g/base-instructions-alphabetic-order/msr-register-move-general-purpose-register-to-system-register
*/ */
struct Msr { struct Msr {
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MSR instruction
*/
inline constexpr bool Verify() {
return (sig == 0xD51); return (sig == 0xD51);
} }
@ -119,38 +101,32 @@ namespace skyline {
u32 destReg : 15; //!< 15-bit source register u32 destReg : 15; //!< 15-bit source register
u16 sig : 12; //!< 16-bit signature (0xD51) u16 sig : 12; //!< 16-bit signature (0xD51)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Msr) == sizeof(u32)); static_assert(sizeof(Msr) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a B instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch. * @url https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch
*/ */
struct B { struct B {
public: public:
/** /**
* @brief Creates a B instruction with a specific offset * @param offset The relative offset to branch to (Should be 32-bit aligned)
* @param offset The offset to encode in the instruction (Should be 32-bit aligned)
*/ */
inline constexpr B(i64 offset) { constexpr B(i64 offset) {
this->offset = static_cast<i32>(offset / 4); this->offset = static_cast<i32>(offset / sizeof(u32));
sig = 0x5; sig = 0x5;
} }
/** /**
* @brief Returns the offset of the instruction * @return The offset encoded within the instruction in bytes
* @return The offset encoded within the instruction
*/ */
inline constexpr i32 Offset() { constexpr i32 Offset() {
return offset * 4; return offset * sizeof(u32);
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid Branch instruction
*/
inline constexpr bool Verify() {
return (sig == 0x5); return (sig == 0x5);
} }
@ -159,38 +135,32 @@ namespace skyline {
i32 offset : 26; //!< 26-bit branch offset i32 offset : 26; //!< 26-bit branch offset
u8 sig : 6; //!< 6-bit signature (0x5) u8 sig : 6; //!< 6-bit signature (0x5)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(B) == sizeof(u32)); static_assert(sizeof(B) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a BL instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch. * @url https://developer.arm.com/docs/ddi0596/h/base-instructions-alphabetic-order/bl-branch-with-link
*/ */
struct BL { struct BL {
public: public:
/** /**
* @brief Creates a BL instruction with a specific offset * @param offset The relative offset to branch to (Should be 32-bit aligned)
* @param offset The offset to encode in the instruction (Should be 32-bit aligned)
*/ */
inline constexpr BL(i64 offset) { constexpr BL(i64 offset) {
this->offset = static_cast<i32>(offset / 4); this->offset = static_cast<i32>(offset / sizeof(u32));
sig = 0x25; sig = 0x25;
} }
/** /**
* @brief Returns the offset of the instruction * @return The offset encoded within the instruction in bytes
* @return The offset encoded within the instruction
*/ */
inline constexpr i32 Offset() { constexpr i32 Offset() {
return offset * 4; return offset * sizeof(u32);
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid Branch Linked instruction
*/
inline constexpr bool Verify() {
return (sig == 0x25); return (sig == 0x25);
} }
@ -199,23 +169,22 @@ namespace skyline {
i32 offset : 26; //!< 26-bit branch offset i32 offset : 26; //!< 26-bit branch offset
u8 sig : 6; //!< 6-bit signature (0x25) u8 sig : 6; //!< 6-bit signature (0x25)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(BL) == sizeof(u32)); static_assert(sizeof(BL) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a MOVZ instruction. See https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/movz-move-wide-with-zero. * @url https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/movz-move-wide-with-zero
*/ */
struct Movz { struct Movz {
public: public:
/** /**
* @brief Creates a MOVZ instruction
* @param destReg The destination Xn register to store the value in * @param destReg The destination Xn register to store the value in
* @param imm16 The 16-bit value to store * @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at * @param shift The offset (in units of 16-bits) in the register to store the value at
*/ */
inline constexpr Movz(regs::X destReg, u16 imm16, u8 shift = 0) { constexpr Movz(regs::X destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg); this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16; this->imm16 = imm16;
hw = shift; hw = shift;
@ -224,12 +193,11 @@ namespace skyline {
} }
/** /**
* @brief Creates a MOVZ instruction
* @param destReg The destination Wn register to store the value in * @param destReg The destination Wn register to store the value in
* @param imm16 The 16-bit value to store * @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at * @param shift The offset (in units of 16-bits) in the register to store the value at
*/ */
inline constexpr Movz(regs::W destReg, u16 imm16, u8 shift = 0) { constexpr Movz(regs::W destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg); this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16; this->imm16 = imm16;
hw = shift; hw = shift;
@ -238,18 +206,13 @@ namespace skyline {
} }
/** /**
* @brief Returns the offset of the instruction * @return The shift encoded within the instruction in bytes
* @return The offset encoded within the instruction (In Bytes)
*/ */
inline constexpr u8 Shift() { constexpr u8 Shift() {
return static_cast<u8>(hw * sizeof(u16)); return static_cast<u8>(hw * sizeof(u16));
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVZ instruction
*/
inline constexpr bool Verify() {
return (sig == 0xA5); return (sig == 0xA5);
} }
@ -261,23 +224,22 @@ namespace skyline {
u8 sig : 8; //!< 8-bit signature (0xA5) u8 sig : 8; //!< 8-bit signature (0xA5)
u8 sf : 1; //!< 1-bit register type u8 sf : 1; //!< 1-bit register type
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Movz) == sizeof(u32)); static_assert(sizeof(Movz) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a MOVK instruction. See https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/movk-move-wide-with-keep. * @url https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/movk-move-wide-with-keep
*/ */
struct Movk { struct Movk {
public: public:
/** /**
* @brief Creates a MOVK instruction
* @param destReg The destination Xn register to store the value in * @param destReg The destination Xn register to store the value in
* @param imm16 The 16-bit value to store * @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at * @param shift The offset (in units of 16-bits) in the register to store the value at
*/ */
inline constexpr Movk(regs::X destReg, u16 imm16, u8 shift = 0) { constexpr Movk(regs::X destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg); this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16; this->imm16 = imm16;
hw = shift; hw = shift;
@ -286,12 +248,11 @@ namespace skyline {
} }
/** /**
* @brief Creates a MOVK instruction
* @param destReg The destination Wn register to store the value in * @param destReg The destination Wn register to store the value in
* @param imm16 The 16-bit value to store * @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at * @param shift The offset (in units of 16-bits) in the register to store the value at
*/ */
inline constexpr Movk(regs::W destReg, u16 imm16, u8 shift = 0) { constexpr Movk(regs::W destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg); this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16; this->imm16 = imm16;
hw = shift; hw = shift;
@ -300,18 +261,13 @@ namespace skyline {
} }
/** /**
* @brief Returns the offset of the instruction * @return The shift encoded within the instruction in bytes
* @return The offset encoded within the instruction (In Bytes)
*/ */
inline constexpr u8 Shift() { constexpr u8 Shift() {
return static_cast<u8>(hw * sizeof(u16)); return static_cast<u8>(hw * sizeof(u16));
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVK instruction
*/
inline constexpr bool Verify() {
return (sig == 0xE5); return (sig == 0xE5);
} }
@ -323,7 +279,7 @@ namespace skyline {
u8 sig : 8; //!< 8-bit signature (0xA5) u8 sig : 8; //!< 8-bit signature (0xA5)
u8 sf : 1; //!< 1-bit register type u8 sf : 1; //!< 1-bit register type
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Movk) == sizeof(u32)); static_assert(sizeof(Movk) == sizeof(u32));
@ -334,7 +290,7 @@ namespace skyline {
* @return A array with the instructions to insert the value * @return A array with the instructions to insert the value
*/ */
template<typename Type> template<typename Type>
inline constexpr std::array<u32, sizeof(Type) / sizeof(u16)> MoveRegister(regs::X destination, Type value) { constexpr std::array<u32, sizeof(Type) / sizeof(u16)> MoveRegister(regs::X destination, Type value) {
std::array<u32, sizeof(Type) / sizeof(u16)> instructions; std::array<u32, sizeof(Type) / sizeof(u16)> instructions;
auto valuePointer{reinterpret_cast<u16 *>(&value)}; auto valuePointer{reinterpret_cast<u16 *>(&value)};
@ -353,7 +309,7 @@ namespace skyline {
} }
/** /**
* @brief A bit-field struct that encapsulates a MOV (Register) instruction. See https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/mov-register-move-register-an-alias-of-orr-shifted-register. * @url https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/mov-register-move-register-an-alias-of-orr-shifted-register
*/ */
struct Mov { struct Mov {
public: public:
@ -362,10 +318,10 @@ namespace skyline {
* @param destReg The destination Xn register to store the value in * @param destReg The destination Xn register to store the value in
* @param srcReg The source Xn register to retrieve the value from * @param srcReg The source Xn register to retrieve the value from
*/ */
inline constexpr Mov(regs::X destReg, regs::X srcReg) { constexpr Mov(regs::X destReg, regs::X srcReg) {
this->destReg = static_cast<u8>(destReg); this->destReg = static_cast<u8>(destReg);
sig0 = 0x1F; sig0 = 0x1F;
imm6 = 0; imm = 0;
this->srcReg = static_cast<u8>(srcReg); this->srcReg = static_cast<u8>(srcReg);
sig1 = 0x150; sig1 = 0x150;
sf = 1; sf = 1;
@ -376,20 +332,16 @@ namespace skyline {
* @param destReg The destination Wn register to store the value in * @param destReg The destination Wn register to store the value in
* @param srcReg The source Wn register to retrieve the value from * @param srcReg The source Wn register to retrieve the value from
*/ */
inline constexpr Mov(regs::W destReg, regs::W srcReg) { constexpr Mov(regs::W destReg, regs::W srcReg) {
this->destReg = static_cast<u8>(destReg); this->destReg = static_cast<u8>(destReg);
sig0 = 0x1F; sig0 = 0x1F;
imm6 = 0; imm = 0;
this->srcReg = static_cast<u8>(srcReg); this->srcReg = static_cast<u8>(srcReg);
sig1 = 0x150; sig1 = 0x150;
sf = 0; sf = 0;
} }
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVZ instruction
*/
inline constexpr bool Verify() {
return (sig0 == 0x1F) && (sig1 == 0x150); return (sig0 == 0x1F) && (sig1 == 0x150);
} }
@ -397,32 +349,27 @@ namespace skyline {
struct __attribute__((packed)) { struct __attribute__((packed)) {
u8 destReg : 5; //!< 5-bit destination register u8 destReg : 5; //!< 5-bit destination register
u8 sig0 : 5; //!< 5-bit signature (0x1F) u8 sig0 : 5; //!< 5-bit signature (0x1F)
u8 imm6 : 6; //!< 6-bit immediate value u8 imm : 6; //!< 6-bit immediate value
u8 srcReg : 5; //!< 5-bit source register u8 srcReg : 5; //!< 5-bit source register
u16 sig1 : 10; //!< 10-bit signature (0x150) u16 sig1 : 10; //!< 10-bit signature (0x150)
u8 sf : 1; //!< 1-bit register type u8 sf : 1; //!< 1-bit register type
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Mov) == sizeof(u32)); static_assert(sizeof(Mov) == sizeof(u32));
/** /**
* @brief A bit-field struct that encapsulates a LDR (immediate) instruction. See https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/ldr-immediate-load-register-immediate. * @url https://developer.arm.com/docs/ddi0596/e/base-instructions-alphabetic-order/ldr-immediate-load-register-immediate
*/ */
struct Ldr { struct Ldr {
public: public:
/** /**
* @brief Creates a LDR (immediate) instruction
* @param raw The raw value of the whole instruction * @param raw The raw value of the whole instruction
*/ */
inline constexpr Ldr(u32 raw) : raw(raw) {} constexpr Ldr(u32 raw) : raw(raw) {}
/** constexpr bool Verify() {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid FCVTZU instruction
*/
inline constexpr bool Verify() {
return (sig0 == 0x0 && sig1 == 0x1CA && sig2 == 0x1); return (sig0 == 0x0 && sig1 == 0x1CA && sig2 == 0x1);
} }
@ -436,7 +383,7 @@ namespace skyline {
u8 sf : 1; //!< 1-bit register type u8 sf : 1; //!< 1-bit register type
u8 sig2 : 1; //!< 1-bit signature (0x1) u8 sig2 : 1; //!< 1-bit signature (0x1)
}; };
u32 raw{}; //!< The raw value of the instruction u32 raw{};
}; };
}; };
static_assert(sizeof(Ldr) == sizeof(u32)); static_assert(sizeof(Ldr) == sizeof(u32));

View File

@ -1,13 +1,15 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include "nce.h"
#include "nce/guest.h"
#include "kernel/memory.h"
#include "kernel/types/KProcess.h"
#include "vfs/os_backing.h" #include "vfs/os_backing.h"
#include "loader/nro.h" #include "loader/nro.h"
#include "loader/nso.h" #include "loader/nso.h"
#include "loader/nca.h" #include "loader/nca.h"
#include "loader/nsp.h" #include "loader/nsp.h"
#include "nce.h"
#include "nce/guest.h"
#include "os.h" #include "os.h"
namespace skyline::kernel { namespace skyline::kernel {

View File

@ -3,24 +3,20 @@
#pragma once #pragma once
#include "common.h" #include "kernel/memory.h"
#include "loader/loader.h" #include "loader/loader.h"
#include "kernel/ipc.h"
#include "kernel/types/KProcess.h"
#include "kernel/types/KThread.h"
#include "services/serviceman.h" #include "services/serviceman.h"
#include "gpu.h"
namespace skyline::kernel { namespace skyline::kernel {
/** /**
* @brief The OS class manages the interaction between Skyline components and the underlying OS in NCE * @brief The OS class manages the interaction between the various Skyline components
*/ */
class OS { class OS {
public: public:
DeviceState state; //!< The state of the device DeviceState state;
std::shared_ptr<type::KProcess> process; //!< The KProcess object for the emulator, representing the guest process std::shared_ptr<type::KProcess> process;
service::ServiceManager serviceManager; //!< This manages all of the service functions service::ServiceManager serviceManager;
MemoryManager memory; //!< The MemoryManager object for this process MemoryManager memory;
std::string appFilesPath; //!< The full path to the app's files directory std::string appFilesPath; //!< The full path to the app's files directory
/** /**

View File

@ -21,17 +21,18 @@ namespace skyline {
u64 upper; //!< The upper 64 bits of the user ID u64 upper; //!< The upper 64 bits of the user ID
u64 lower; //!< The lower 64 bits of the user ID u64 lower; //!< The lower 64 bits of the user ID
inline constexpr bool operator==(const UserId &userId) { constexpr bool operator==(const UserId &userId) {
return upper == userId.upper && lower == userId.lower; return upper == userId.upper && lower == userId.lower;
} }
inline constexpr bool operator!=(const UserId &userId) { constexpr bool operator!=(const UserId &userId) {
return !(*this == userId); return !(*this == userId);
} }
}; };
/** /**
* @brief IAccountServiceForApplication or acc:u0 provides functions for reading user information (https://switchbrew.org/wiki/Account_services#acc:u0) * @brief IAccountServiceForApplication or acc:u0 provides functions for reading user information
* @url https://switchbrew.org/wiki/Account_services#acc:u0
*/ */
class IAccountServiceForApplication : public BaseService { class IAccountServiceForApplication : public BaseService {
private: private:
@ -44,37 +45,38 @@ namespace skyline {
IAccountServiceForApplication(const DeviceState &state, ServiceManager &manager); IAccountServiceForApplication(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This checks if the given user ID exists * @brief Checks if the given user ID exists
*/ */
Result GetUserExistence(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetUserExistence(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns a list of all user accounts on the console * @brief Returns a list of all user accounts on the console
*/ */
Result ListAllUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result ListAllUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns a list of all open user accounts on the console * @brief Returns a list of all open user accounts on the console
*/ */
Result ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the user ID of the last active user on the console * @brief Returns the user ID of the last active user on the console
*/ */
Result GetLastOpenedUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetLastOpenedUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This provides information about the running application for account services to use (https://switchbrew.org/wiki/Account_services#InitializeApplicationInfoV0) * @brief Provides information about the running application for account services to use
* @url https://switchbrew.org/wiki/Account_services#InitializeApplicationInfoV0
*/ */
Result InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns a handle to an IProfile which can be used for reading user information * @brief Returns a handle to an IProfile which can be used for reading user information
*/ */
Result GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns a handle to an IManagerForApplication which can be used for reading Nintendo Online info * @brief Returns a handle to an IManagerForApplication which can be used for reading Nintendo Online info
*/ */
Result GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::account { namespace skyline::service::account {
/** /**
* @brief IManagerForApplication provides functions for reading Nintendo Online user information (https://switchbrew.org/wiki/Account_services#IManagerForApplication) * @brief IManagerForApplication provides functions for reading Nintendo Online user information
* @url https://switchbrew.org/wiki/Account_services#IManagerForApplication
*/ */
class IManagerForApplication : public BaseService { class IManagerForApplication : public BaseService {
public: public:

View File

@ -27,7 +27,7 @@ namespace skyline::service::account {
u64 lastEditTimestamp; //!< A POSIX UTC timestamp denoting the last account edit u64 lastEditTimestamp; //!< A POSIX UTC timestamp denoting the last account edit
std::array<char, 0x20> nickname; //!< UTF-8 Nickname std::array<char, 0x20> nickname; //!< UTF-8 Nickname
} accountProfileBase = { } accountProfileBase = {
.uid = userId .uid = userId,
}; };
auto username{state.settings->GetString("username_value")}; auto username{state.settings->GetString("username_value")};

View File

@ -8,7 +8,8 @@
namespace skyline::service::account { namespace skyline::service::account {
/** /**
* @brief IProfile provides functions for reading user profile (https://switchbrew.org/wiki/Account_services#IProfile) * @brief IProfile provides functions for reading user profile
* @url https://switchbrew.org/wiki/Account_services#IProfile
*/ */
class IProfile : public BaseService { class IProfile : public BaseService {
public: public:
@ -18,12 +19,12 @@ namespace skyline::service::account {
UserId userId; UserId userId;
/** /**
* @brief This returns AccountUserData and AccountProfileBase objects that describe the user's information * @brief Returns AccountUserData and AccountProfileBase objects that describe the user's information
*/ */
Result Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns an AccountProfileBase object that describe the user's information * @brief Returns an AccountProfileBase object that describe the user's information
*/ */
Result GetBase(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetBase(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,29 +7,34 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief IAllSystemAppletProxiesService is used to open proxies (https://switchbrew.org/wiki/Applet_Manager_services#appletAE) * @brief IAllSystemAppletProxiesService is used to open proxies
* @url https://switchbrew.org/wiki/Applet_Manager_services#appletAE
*/ */
class IAllSystemAppletProxiesService : public BaseService { class IAllSystemAppletProxiesService : public BaseService {
public: public:
IAllSystemAppletProxiesService(const DeviceState &state, ServiceManager &manager); IAllSystemAppletProxiesService(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns #ILibraryAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenLibraryAppletProxy) * @brief Returns #ILibraryAppletProxy
* @url https://switchbrew.org/wiki/Applet_Manager_services#OpenLibraryAppletProxy
*/ */
Result OpenLibraryAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenLibraryAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IApplicationProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy) * @brief Returns #IApplicationProxy
* @url https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy
*/ */
Result OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IOverlayAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenOverlayAppletProxy) * @brief Returns #IOverlayAppletProxy
* @url https://switchbrew.org/wiki/Applet_Manager_services#OpenOverlayAppletProxy
*/ */
Result OpenOverlayAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenOverlayAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #ISystemAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenSystemAppletProxy) * @brief Returns #ISystemAppletProxy
* @url https://switchbrew.org/wiki/Applet_Manager_services#OpenSystemAppletProxy
*/ */
Result OpenSystemAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenSystemAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,14 +7,16 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief IApplicationProxyService is used to open an application proxy (https://switchbrew.org/wiki/Applet_Manager_services#appletOE) * @brief IApplicationProxyService is used to open an application proxy
* @url https://switchbrew.org/wiki/Applet_Manager_services#appletOE
*/ */
class IApplicationProxyService : public BaseService { class IApplicationProxyService : public BaseService {
public: public:
IApplicationProxyService(const DeviceState &state, ServiceManager &manager); IApplicationProxyService(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns #IApplicationProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy) * @brief Returns #IApplicationProxy
* @url https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy
*/ */
Result OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -32,8 +32,8 @@ namespace skyline::service::am {
} }
Result ILibraryAppletAccessor::PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { Result ILibraryAppletAccessor::PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< This is the magic of the application launch parameters constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters
constexpr size_t LaunchParameterSize{0x88}; //!< This is the size of the launch parameter IStorage constexpr size_t LaunchParameterSize{0x88}; //!< The size of the launch parameter IStorage
auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)}; auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)};

View File

@ -8,7 +8,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief ILibraryAppletAccessor is used to communicate with the library applet (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletAccessor) * @brief ILibraryAppletAccessor is used to communicate with the library applet
* @url https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletAccessor
*/ */
class ILibraryAppletAccessor : public BaseService { class ILibraryAppletAccessor : public BaseService {
private: private:
@ -18,27 +19,31 @@ namespace skyline::service::am {
ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager); ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This function returns a handle to the library applet state change event * @brief Returns a handle to the library applet state change event
*/ */
Result GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function starts the library applet (https://switchbrew.org/wiki/Applet_Manager_services#Start) * @brief Starts the library applet
* @url https://switchbrew.org/wiki/Applet_Manager_services#Start
*/ */
Result Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function returns the exit code of the library applet (https://switchbrew.org/wiki/Applet_Manager_services#GetResult) * @brief Returns the exit code of the library applet
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetResult
*/ */
Result GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function pushes in data to the library applet (https://switchbrew.org/wiki/Applet_Manager_services#PushInData) * @brief Pushes in data to the library applet
* @url https://switchbrew.org/wiki/Applet_Manager_services#PushInData
*/ */
Result PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function receives data from the library applet (https://switchbrew.org/wiki/Applet_Manager_services#PopOutData) * @brief Receives data from the library applet
* @url https://switchbrew.org/wiki/Applet_Manager_services#PopOutData
*/ */
Result PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This contains common various functions (https://switchbrew.org/wiki/Applet_Manager_services#IAppletCommonFunctions) * @brief This contains common various functions
* @url https://switchbrew.org/wiki/Applet_Manager_services#IAppletCommonFunctions
*/ */
class IAppletCommonFunctions : public BaseService { class IAppletCommonFunctions : public BaseService {
public: public:

View File

@ -10,8 +10,8 @@ namespace skyline::service::am {
IApplicationFunctions::IApplicationFunctions(const DeviceState &state, ServiceManager &manager) : gpuErrorEvent(std::make_shared<type::KEvent>(state)), BaseService(state, manager) {} IApplicationFunctions::IApplicationFunctions(const DeviceState &state, ServiceManager &manager) : gpuErrorEvent(std::make_shared<type::KEvent>(state)), BaseService(state, manager) {}
Result IApplicationFunctions::PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { Result IApplicationFunctions::PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< This is the magic of the application launch parameters constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters
constexpr size_t LaunchParameterSize{0x88}; //!< This is the size of the launch parameter IStorage constexpr size_t LaunchParameterSize{0x88}; //!< The size of the launch parameter IStorage
auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)}; auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)};

View File

@ -8,7 +8,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This has functions that are used to notify an application about it's state (https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions) * @brief This is used to notify an application about it's own state
* @url https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions
*/ */
class IApplicationFunctions : public BaseService { class IApplicationFunctions : public BaseService {
private: private:
@ -18,42 +19,50 @@ namespace skyline::service::am {
IApplicationFunctions(const DeviceState &state, ServiceManager &manager); IApplicationFunctions(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns an Applet Manager IStorage containing the application's launch parameters (https://switchbrew.org/wiki/Applet_Manager_services#PopLaunchParameter) * @brief Returns an Applet Manager IStorage containing the application's launch parameters
* @url https://switchbrew.org/wiki/Applet_Manager_services#PopLaunchParameter
*/ */
Result PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This creates a save data folder for the requesting application (https://switchbrew.org/wiki/Applet_Manager_services#EnsureSaveData) * @brief Creates a save data folder for the requesting application
* @url https://switchbrew.org/wiki/Applet_Manager_services#EnsureSaveData
*/ */
Result EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the desired language for the application (https://switchbrew.org/wiki/Applet_Manager_services#GetDesiredLanguage) * @brief Returns the desired language for the application
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetDesiredLanguage
*/ */
Result GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns if the application is running or not, always returns true (https://switchbrew.org/wiki/Applet_Manager_services#NotifyRunning) * @brief Returns if the application is running or not, always returns true
* @url https://switchbrew.org/wiki/Applet_Manager_services#NotifyRunning
*/ */
Result NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns a UUID, however what it refers to is currently unknown (https://switchbrew.org/wiki/Applet_Manager_services#GetPseudoDeviceId) * @brief Returns a UUID, however what it refers to is currently unknown
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetPseudoDeviceId
*/ */
Result GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This initializes gameplay recording (https://switchbrew.org/wiki/Applet_Manager_services#InitializeGamePlayRecording) * @brief Initializes gameplay recording
* @url https://switchbrew.org/wiki/Applet_Manager_services#InitializeGamePlayRecording
*/ */
Result InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This controls the gameplay recording state (https://switchbrew.org/wiki/Applet_Manager_services#SetGamePlayRecordingState) * @brief Sets the gameplay recording state
* @url https://switchbrew.org/wiki/Applet_Manager_services#SetGamePlayRecordingState
*/ */
Result SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This obtains a handle to the system GPU error KEvent (https://switchbrew.org/wiki/Applet_Manager_services#GetGpuErrorDetectedSystemEvent) * @brief Obtains a handle to the system GPU error KEvent
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetGpuErrorDetectedSystemEvent
*/ */
Result GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This has functions relating to volume control (https://switchbrew.org/wiki/Applet_Manager_services#IAudioController) * @brief This is used to control the audio's volume
* @url https://switchbrew.org/wiki/Applet_Manager_services#IAudioController
*/ */
class IAudioController : public BaseService { class IAudioController : public BaseService {
private: private:
@ -18,17 +19,20 @@ namespace skyline::service::am {
IAudioController(const DeviceState &state, ServiceManager &manager); IAudioController(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This sets the expected volumes for an application (https://switchbrew.org/wiki/Applet_Manager_services#SetExpectedMasterVolume) * @brief Sets the expected volumes for an application
* @url https://switchbrew.org/wiki/Applet_Manager_services#SetExpectedMasterVolume
*/ */
Result SetExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the main applet volume that is expected by the application (https://switchbrew.org/wiki/Applet_Manager_services#GetMainAppletExpectedMasterVolume) * @brief Returns the main applet volume that is expected by the application
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetMainAppletExpectedMasterVolume
*/ */
Result GetMainAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetMainAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the library applet volume that is expected by the application (https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletExpectedMasterVolume) * @brief Returns the library applet volume that is expected by the application
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletExpectedMasterVolume
*/ */
Result GetLibraryAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetLibraryAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -18,7 +18,8 @@ namespace skyline::service::am {
class ICommonStateGetter : public BaseService { class ICommonStateGetter : public BaseService {
private: private:
/** /**
* @brief This enumerates all the possible contents of a #AppletMessage (https://switchbrew.org/wiki/Applet_Manager_services#AppletMessage) * @brief All the possible contents of a #AppletMessage
* @url https://switchbrew.org/wiki/Applet_Manager_services#AppletMessage
*/ */
enum class Message : u32 { enum class Message : u32 {
ExitRequested = 0x4, //!< The applet has been requested to exit ExitRequested = 0x4, //!< The applet has been requested to exit
@ -26,9 +27,9 @@ namespace skyline::service::am {
ExecutionResumed = 0x10, //!< The execution of the applet has resumed ExecutionResumed = 0x10, //!< The execution of the applet has resumed
OperationModeChange = 0x1E, //!< There was a change in the operation mode OperationModeChange = 0x1E, //!< There was a change in the operation mode
PerformanceModeChange = 0x1F, //!< There was a change in the performance mode PerformanceModeChange = 0x1F, //!< There was a change in the performance mode
RequestToDisplay = 0x33, //!< This indicates that ApproveToDisplay should be used RequestToDisplay = 0x33, //!< Indicates that ApproveToDisplay should be used
CaptureButtonShortPressed = 0x5A, //!< The Capture button was short pressed CaptureButtonShortPressed = 0x5A, //!< The Capture button was short pressed
ScreenshotTaken = 0x5C //!< A screenshot was taken ScreenshotTaken = 0x5C, //!< A screenshot was taken
}; };
std::shared_ptr<type::KEvent> messageEvent; //!< The event signalled when there is a message available std::shared_ptr<type::KEvent> messageEvent; //!< The event signalled when there is a message available
@ -36,16 +37,16 @@ namespace skyline::service::am {
enum class FocusState : u8 { enum class FocusState : u8 {
InFocus = 1, //!< The application is in foreground InFocus = 1, //!< The application is in foreground
OutOfFocus = 2 //!< The application is in the background OutOfFocus = 2, //!< The application is in the background
} focusState{FocusState::InFocus}; } focusState{FocusState::InFocus};
enum class OperationMode : u8 { enum class OperationMode : u8 {
Handheld = 0, //!< The device is in handheld mode Handheld = 0, //!< The device is in handheld mode
Docked = 1 //!< The device is in docked mode Docked = 1, //!< The device is in docked mode
} operationMode; } operationMode;
/** /**
* @brief This queues a message for the application to read via ReceiveMessage * @brief Queues a message for the application to read via ReceiveMessage
* @param message The message to queue * @param message The message to queue
*/ */
void QueueMessage(Message message); void QueueMessage(Message message);
@ -54,32 +55,38 @@ namespace skyline::service::am {
ICommonStateGetter(const DeviceState &state, ServiceManager &manager); ICommonStateGetter(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns the handle to a KEvent object that is signalled whenever RecieveMessage has a message (https://switchbrew.org/wiki/Applet_Manager_services#GetEventHandle) * @brief Returns the handle to a KEvent object that is signalled whenever RecieveMessage has a message
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetEventHandle
*/ */
Result GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns an #AppletMessage or 0x680 to indicate the lack of a message (https://switchbrew.org/wiki/Applet_Manager_services#ReceiveMessage) * @brief Returns an #AppletMessage or 0x680 to indicate the lack of a message
* @url https://switchbrew.org/wiki/Applet_Manager_services#ReceiveMessage
*/ */
Result ReceiveMessage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result ReceiveMessage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns if an application is in focus or not. It always returns in focus on the emulator (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState) * @brief Returns if an application is in focus or not. It always returns in focus on the emulator
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState
*/ */
Result GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the current OperationMode (https://switchbrew.org/wiki/Applet_Manager_services#GetOperationMode) * @brief Returns the current OperationMode
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetOperationMode
*/ */
Result GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the current PerformanceMode (Same as operationMode but u32) (https://switchbrew.org/wiki/Applet_Manager_services#GetPerformanceMode) * @brief Returns the current PerformanceMode (Same as operationMode but u32)
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetPerformanceMode
*/ */
Result GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the current display width and height in two u32s (https://switchbrew.org/wiki/Applet_Manager_services#GetDefaultDisplayResolution) * @brief Returns the current display width and height in two u32s
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetDefaultDisplayResolution
*/ */
Result GetDefaultDisplayResolution(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetDefaultDisplayResolution(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This has functions that are used for debugging purposes (https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions) * @brief This is used for debugging purposes
* @url https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions
*/ */
class IDebugFunctions : public BaseService { class IDebugFunctions : public BaseService {
public: public:

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This has functions used to capture the contents of a display (https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController) * @brief This is used to capture the contents of a display
* @url https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController
*/ */
class IDisplayController : public BaseService { class IDisplayController : public BaseService {
public: public:

View File

@ -14,12 +14,14 @@ namespace skyline::service::am {
ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager); ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This function returns a handle to a library applet accessor (https://switchbrew.org/wiki/Applet_Manager_services#CreateLibraryApplet) * @brief Returns a handle to a library applet accessor
* @url https://switchbrew.org/wiki/Applet_Manager_services#CreateLibraryApplet
*/ */
Result CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function creates an IStorage that can be used by the application (https://switchbrew.org/wiki/Applet_Manager_services#CreateStorage) * @brief Creates an IStorage that can be used by the application
* @url https://switchbrew.org/wiki/Applet_Manager_services#CreateStorage
*/ */
Result CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This has functions relating to an application's own current status (https://switchbrew.org/wiki/Applet_Manager_services#ISelfController) * @brief This has functions relating to an application's own current status
* @url https://switchbrew.org/wiki/Applet_Manager_services#ISelfController
*/ */
class ISelfController : public BaseService { class ISelfController : public BaseService {
private: private:
@ -18,52 +19,62 @@ namespace skyline::service::am {
ISelfController(const DeviceState &state, ServiceManager &manager); ISelfController(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This function prevents the running application from being quit via the home button (https://switchbrew.org/wiki/Applet_Manager_services#LockExit) * @brief Function prevents the running application from being quit via the home button
* @url https://switchbrew.org/wiki/Applet_Manager_services#LockExit
*/ */
Result LockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result LockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function allows the running application to be quit via the home button (https://switchbrew.org/wiki/Applet_Manager_services#UnlockExit) * @brief Function allows the running application to be quit via the home button
* @url https://switchbrew.org/wiki/Applet_Manager_services#UnlockExit
*/ */
Result UnlockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result UnlockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function obtains a handle to the library applet launchable event (https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletLaunchableEvent) * @brief Function obtains a handle to the library applet launchable event
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletLaunchableEvent
*/ */
Result GetLibraryAppletLaunchableEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetLibraryAppletLaunchableEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function takes a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOperationModeChangedNotification) * @brief This function takes a u8 bool flag and no output (Stubbed)
* @url https://switchbrew.org/wiki/Applet_Manager_services#SetOperationModeChangedNotification
*/ */
Result SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function takes a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetPerformanceModeChangedNotification) * @brief This function takes a u8 bool flag and no output (Stubbed)
* @url https://switchbrew.org/wiki/Applet_Manager_services#SetPerformanceModeChangedNotification
*/ */
Result SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function takes 3 unknown u8 values and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState) * @brief This function takes 3 unknown u8 values and has no output (Stubbed)
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState
*/ */
Result SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function toggles whether a restart message should be sent (https://switchbrew.org/wiki/Applet_Manager_services#SetRestartMessageEnabled) * @brief Toggles whether a restart message should be sent or not
* @url https://switchbrew.org/wiki/Applet_Manager_services#SetRestartMessageEnabled
*/ */
Result SetRestartMessageEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetRestartMessageEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function takes a u8 bool flag and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOutOfFocusSuspendingEnabled) * @brief This function takes a u8 bool flag and has no output (Stubbed)
* @url https://switchbrew.org/wiki/Applet_Manager_services#SetOutOfFocusSuspendingEnabled
*/ */
Result SetOutOfFocusSuspendingEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetOutOfFocusSuspendingEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function returns an output u64 LayerId (https://switchbrew.org/wiki/Applet_Manager_services#CreateManagedDisplayLayer) * @brief Returns an output u64 LayerId
* @url https://switchbrew.org/wiki/Applet_Manager_services#CreateManagedDisplayLayer
*/ */
Result CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This obtains a handle to the system sleep time change KEvent (https://switchbrew.org/wiki/Applet_Manager_services#GetAccumulatedSuspendedTickChangedEvent) * @brief Returns a handle to the system sleep time change KEvent
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetAccumulatedSuspendedTickChangedEvent
*/ */
Result GetAccumulatedSuspendedTickChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetAccumulatedSuspendedTickChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,19 +7,22 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief This has functions used to retrieve the status of the application's window (https://switchbrew.org/wiki/Applet_Manager_services#IWindowController) * @brief This has functions used to retrieve the status of the application's window
* @url https://switchbrew.org/wiki/Applet_Manager_services#IWindowController
*/ */
class IWindowController : public BaseService { class IWindowController : public BaseService {
public: public:
IWindowController(const DeviceState &state, ServiceManager &manager); IWindowController(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns the PID of the current application (https://switchbrew.org/wiki/Applet_Manager_services#GetAppletResourceUserId) * @brief Returns the PID of the current application
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetAppletResourceUserId
*/ */
Result GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function has mo inputs or outputs (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#AcquireForegroundRights) * @brief This function has no inputs or outputs (Stubbed)
* @url https://switchbrew.org/wiki/Applet_Manager_services#AcquireForegroundRights
*/ */
Result AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,14 +7,16 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief IApplicationProxy returns handles to various services (https://switchbrew.org/wiki/Applet_Manager_services#IApplicationProxy) * @brief IApplicationProxy returns handles to various services
* @url https://switchbrew.org/wiki/Applet_Manager_services#IApplicationProxy
*/ */
class IApplicationProxy : public BaseProxy { class IApplicationProxy : public BaseProxy {
public: public:
IApplicationProxy(const DeviceState &state, ServiceManager &manager); IApplicationProxy(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns #IApplicationFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions) * @brief Returns #IApplicationFunctions
* @url https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions
*/ */
Result GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief ILibraryAppletProxy returns handles to various services (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletProxy) * @brief ILibraryAppletProxy returns handles to various services
* @url https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletProxy
*/ */
class ILibraryAppletProxy : public BaseProxy { class ILibraryAppletProxy : public BaseProxy {
public: public:

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief IOverlayAppletProxy returns handles to various services (https://switchbrew.org/wiki/Applet_Manager_services#IOverlayAppletProxy) * @brief IOverlayAppletProxy returns handles to various services
* @url https://switchbrew.org/wiki/Applet_Manager_services#IOverlayAppletProxy
*/ */
class IOverlayAppletProxy : public BaseProxy { class IOverlayAppletProxy : public BaseProxy {
public: public:

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief ISystemAppletProxy returns handles to various services (https://switchbrew.org/wiki/Applet_Manager_services#ISystemAppletProxy) * @brief ISystemAppletProxy returns handles to various services
* @url https://switchbrew.org/wiki/Applet_Manager_services#ISystemAppletProxy
*/ */
class ISystemAppletProxy : public BaseProxy { class ISystemAppletProxy : public BaseProxy {
public: public:

View File

@ -14,42 +14,50 @@ namespace skyline::service::am {
BaseProxy(const DeviceState &state, ServiceManager &manager); BaseProxy(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns #ICommonStateGetter (https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter) * @brief Returns #ICommonStateGetter
* @url https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter
*/ */
Result GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #ISelfController (https://switchbrew.org/wiki/Applet_Manager_services#ISelfController) * @brief Returns #ISelfController
* @url https://switchbrew.org/wiki/Applet_Manager_services#ISelfController
*/ */
Result GetSelfController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetSelfController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IWindowController (https://switchbrew.org/wiki/Applet_Manager_services#IWindowController) * @brief Returns #IWindowController
* @url https://switchbrew.org/wiki/Applet_Manager_services#IWindowController
*/ */
Result GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IAudioController (https://switchbrew.org/wiki/Applet_Manager_services#IAudioController) * @brief Returns #IAudioController
* @url https://switchbrew.org/wiki/Applet_Manager_services#IAudioController
*/ */
Result GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IDisplayController (https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController) * @brief Returns #IDisplayController
* @url https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController
*/ */
Result GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #ILibraryAppletCreator (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletCreator) * @brief Returns #ILibraryAppletCreator
* @url https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletCreator
*/ */
Result GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IDebugFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions) * @brief Returns #IDebugFunctions
* @url https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions
*/ */
Result GetDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns #IAppletCommonFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IAppletCommonFunctions) * @brief Returns #IAppletCommonFunctions
* @url https://switchbrew.org/wiki/Applet_Manager_services#IAppletCommonFunctions
*/ */
Result GetAppletCommonFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetAppletCommonFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
}; };

View File

@ -7,7 +7,8 @@
namespace skyline::service::am { namespace skyline::service::am {
/** /**
* @brief IStorage is used to open an IStorageAccessor to access a region of memory (https://switchbrew.org/wiki/Applet_Manager_services#IStorage) * @brief IStorage is used to open an IStorageAccessor to access a region of memory
* @url https://switchbrew.org/wiki/Applet_Manager_services#IStorage
*/ */
class IStorage : public BaseService, public std::enable_shared_from_this<IStorage> { class IStorage : public BaseService, public std::enable_shared_from_this<IStorage> {
private: private:
@ -19,14 +20,12 @@ namespace skyline::service::am {
IStorage(const DeviceState &state, ServiceManager &manager, size_t size); IStorage(const DeviceState &state, ServiceManager &manager, size_t size);
/** /**
* @brief This returns an IStorageAccessor that can read and write data to an IStorage * @brief Returns an IStorageAccessor that can read and write data to an IStorage
*/ */
Result Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This function writes an object to the storage * @brief Writes an object to the storage
* @tparam ValueType The type of the object to write
* @param value A reference to the object to be written
*/ */
template<typename ValueType> template<typename ValueType>
inline void Push(const ValueType &value) { inline void Push(const ValueType &value) {

View File

@ -13,7 +13,8 @@ namespace skyline::service::am {
class IStorage; class IStorage;
/** /**
* @brief IStorageAccessor is used read and write to an IStorage (https://switchbrew.org/wiki/Applet_Manager_services#IStorageAccessor) * @brief IStorageAccessor is used read and write to an IStorage
* @url https://switchbrew.org/wiki/Applet_Manager_services#IStorageAccessor
*/ */
class IStorageAccessor : public BaseService { class IStorageAccessor : public BaseService {
private: private:
@ -23,17 +24,17 @@ namespace skyline::service::am {
IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr<IStorage> parent); IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr<IStorage> parent);
/** /**
* @brief This returns the size of the storage in bytes * @brief Returns the size of the storage in bytes
*/ */
Result GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This writes a buffer to the storage at the specified offset * @brief Writes a buffer to the storage at the specified offset
*/ */
Result Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns a buffer containing the contents of the storage at the specified offset * @brief Returns a buffer containing the contents of the storage at the specified offset
*/ */
Result Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::aocsrv { namespace skyline::service::aocsrv {
/** /**
* @brief IAddOnContentManager or aoc:u is used by applications to access add-on content information (https://switchbrew.org/wiki/NS_Services#aoc:u) * @brief IAddOnContentManager or aoc:u is used by applications to access add-on content information
* @url https://switchbrew.org/wiki/NS_Services#aoc:u
*/ */
class IAddOnContentManager : public BaseService { class IAddOnContentManager : public BaseService {
public: public:

View File

@ -7,14 +7,15 @@
namespace skyline::service::apm { namespace skyline::service::apm {
/** /**
* @brief IManager is mostly only used to open an ISession (https://switchbrew.org/wiki/PPC_services#apm) * @brief IManager is mostly only used to open an ISession
* @url https://switchbrew.org/wiki/PPC_services#apm
*/ */
class IManager : public BaseService { class IManager : public BaseService {
public: public:
IManager(const DeviceState &state, ServiceManager &manager); IManager(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns an handle to ISession * @brief Returns an handle to ISession
*/ */
Result OpenSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -11,18 +11,20 @@ namespace skyline::service::apm {
*/ */
class ISession : public BaseService { class ISession : public BaseService {
private: private:
std::array<u32, 2> performanceConfig = {0x00010000, 0x00020001}; //!< This holds the performance config for both handheld(0) and docked(1) mode std::array<u32, 2> performanceConfig{0x00010000, 0x00020001}; //!< The performance config for both handheld(0) and docked(1) mode
public: public:
ISession(const DeviceState &state, ServiceManager &manager); ISession(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This sets performanceConfig to the given arguments, it doesn't affect anything else (https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration) * @brief Sets PerformanceConfig to the given arguments, it doesn't affect anything else
* @url https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration
*/ */
Result SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This retrieves the particular performanceConfig for a mode and returns it to the client (https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration) * @brief Retrieves the particular PerformanceConfig for a mode and returns it to the client
* @url https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration
*/ */
Result GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -7,7 +7,8 @@
namespace skyline::service::audio { namespace skyline::service::audio {
/** /**
* @brief IAudioDevice is used by applications to query audio device info (https://switchbrew.org/wiki/Audio_services#IAudioDevice) * @brief IAudioDevice is used by applications to query audio device info
* @url https://switchbrew.org/wiki/Audio_services#IAudioDevice
*/ */
class IAudioDevice : public BaseService { class IAudioDevice : public BaseService {
private: private:
@ -17,27 +18,29 @@ namespace skyline::service::audio {
IAudioDevice(const DeviceState &state, ServiceManager &manager); IAudioDevice(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief This returns a list of the available audio devices (https://switchbrew.org/wiki/Audio_services#ListAudioDeviceName) * @brief Returns a list of the available audio devices
* @url https://switchbrew.org/wiki/Audio_services#ListAudioDeviceName
*/ */
Result ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This sets the volume of an audio output (https://switchbrew.org/wiki/Audio_services#SetAudioDeviceOutputVolume) * @brief Sets the volume of an audio output
* @url https://switchbrew.org/wiki/Audio_services#SetAudioDeviceOutputVolume
*/ */
Result SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the active audio output device * @brief Returns the active audio output device
*/ */
Result GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the audio device system event * @brief Returns the audio device system event
*/ */
Result QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief This returns the current output devices channel count * @brief Returns the current output devices channel count
*/ */
Result GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -9,7 +9,8 @@
namespace skyline::service::audio { namespace skyline::service::audio {
/** /**
* @brief IAudioOut is a service opened when OpenAudioOut is called by IAudioOutManager (https://switchbrew.org/wiki/Audio_services#IAudioOut) * @brief IAudioOut is a service opened when OpenAudioOut is called by IAudioOutManager
* @url https://switchbrew.org/wiki/Audio_services#IAudioOut
*/ */
class IAudioOut : public BaseService { class IAudioOut : public BaseService {
private: private:
@ -33,37 +34,44 @@ namespace skyline::service::audio {
~IAudioOut(); ~IAudioOut();
/** /**
* @brief Returns the playback state of the audio output (https://switchbrew.org/wiki/Audio_services#GetAudioOutState) * @brief Returns the playback state of the audio output
* @url https://switchbrew.org/wiki/Audio_services#GetAudioOutState
*/ */
Result GetAudioOutState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetAudioOutState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Starts playback using data from appended samples (https://switchbrew.org/wiki/Audio_services#StartAudioOut) * @brief Starts playback using data from appended samples
* @url https://switchbrew.org/wiki/Audio_services#StartAudioOut
*/ */
Result StartAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result StartAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Stops playback of audio, waits for all samples to be released (https://switchbrew.org/wiki/Audio_services#StartAudioOut) * @brief Stops playback of audio, waits for all samples to be released
* @url https://switchbrew.org/wiki/Audio_services#StartAudioOut
*/ */
Result StopAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result StopAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Appends sample data to the output buffer (https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer) * @brief Appends sample data to the output buffer
* @url https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer
*/ */
Result AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Returns a handle to the sample release KEvent (https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer) * @brief Returns a handle to the sample release KEvent
* @url https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer
*/ */
Result RegisterBufferEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result RegisterBufferEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Returns the IDs of all pending released buffers (https://switchbrew.org/wiki/Audio_services#GetReleasedAudioOutBuffer) * @brief Returns the IDs of all pending released buffers
* @url https://switchbrew.org/wiki/Audio_services#GetReleasedAudioOutBuffer
*/ */
Result GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Checks if the given buffer ID is in the playback queue (https://switchbrew.org/wiki/Audio_services#ContainsAudioOutBuffer) * @brief Checks if the given buffer ID is in the playback queue
* @url https://switchbrew.org/wiki/Audio_services#ContainsAudioOutBuffer
*/ */
Result ContainsAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result ContainsAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -13,19 +13,22 @@ namespace skyline {
namespace service::audio { namespace service::audio {
/** /**
* @brief IAudioOutManager or audout:u is used to manage audio outputs (https://switchbrew.org/wiki/Audio_services#audout:u) * @brief IAudioOutManager or audout:u is used to manage audio outputs
* @url https://switchbrew.org/wiki/Audio_services#audout:u
*/ */
class IAudioOutManager : public BaseService { class IAudioOutManager : public BaseService {
public: public:
IAudioOutManager(const DeviceState &state, ServiceManager &manager); IAudioOutManager(const DeviceState &state, ServiceManager &manager);
/** /**
* @brief Returns a list of all available audio outputs (https://switchbrew.org/wiki/Audio_services#ListAudioOuts) * @brief Returns a list of all available audio outputs
* @url https://switchbrew.org/wiki/Audio_services#ListAudioOuts
*/ */
Result ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Creates a new audoutU::IAudioOut object and returns a handle to it (https://switchbrew.org/wiki/Audio_services#OpenAudioOut) * @brief Creates a new audoutU::IAudioOut object and returns a handle to it
* @url https://switchbrew.org/wiki/Audio_services#OpenAudioOut
*/ */
Result OpenAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result OpenAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -57,7 +57,8 @@ namespace skyline {
static_assert(sizeof(UpdateDataHeader) == 0x40); static_assert(sizeof(UpdateDataHeader) == 0x40);
/** /**
* @brief IAudioRenderer is used to control an audio renderer output (https://switchbrew.org/wiki/Audio_services#IAudioRenderer) * @brief IAudioRenderer is used to control an audio renderer output
* @url https://switchbrew.org/wiki/Audio_services#IAudioRenderer
*/ */
class IAudioRenderer : public BaseService { class IAudioRenderer : public BaseService {
private: private:
@ -94,22 +95,26 @@ namespace skyline {
~IAudioRenderer(); ~IAudioRenderer();
/** /**
* @brief Returns the sample rate (https://switchbrew.org/wiki/Audio_services#GetSampleRate) * @brief Returns the sample rate
* @url https://switchbrew.org/wiki/Audio_services#GetSampleRate
*/ */
Result GetSampleRate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetSampleRate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Returns the sample count (https://switchbrew.org/wiki/Audio_services#GetSampleCount) * @brief Returns the sample count
* @url https://switchbrew.org/wiki/Audio_services#GetSampleCount
*/ */
Result GetSampleCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetSampleCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Returns the number of mix buffers (https://switchbrew.org/wiki/Audio_services#GetMixBufferCount) * @brief Returns the number of mix buffers
* @url https://switchbrew.org/wiki/Audio_services#GetMixBufferCount
*/ */
Result GetMixBufferCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetMixBufferCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/** /**
* @brief Returns the state of the renderer (https://switchbrew.org/wiki/Audio_services#GetAudioRendererState) (stubbed)? * @brief Returns the state of the renderer
* @url https://switchbrew.org/wiki/Audio_services#GetAudioRendererState (stubbed)?
*/ */
Result GetState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); Result GetState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -6,16 +6,13 @@
#include <common.h> #include <common.h>
namespace skyline::service::audio::IAudioRenderer { namespace skyline::service::audio::IAudioRenderer {
/**
* @brief This enumerates various states an effect can be in
*/
enum class EffectState : u8 { enum class EffectState : u8 {
None = 0, //!< The effect isn't being used None = 0, //!< The effect isn't being used
New = 1, New = 1,
}; };
/** /**
* @brief This is in input containing information on what effects to use on an audio stream * @brief Input containing information on what effects to use on an audio stream
*/ */
struct EffectIn { struct EffectIn {
u8 _unk0_; u8 _unk0_;
@ -25,7 +22,7 @@ namespace skyline::service::audio::IAudioRenderer {
static_assert(sizeof(EffectIn) == 0xC0); static_assert(sizeof(EffectIn) == 0xC0);
/** /**
* @brief This is returned to inform the guest of the state of an effect * @brief Returned to inform the guest of the state of an effect
*/ */
struct EffectOut { struct EffectOut {
EffectState state; EffectState state;

View File

@ -6,9 +6,6 @@
#include <common.h> #include <common.h>
namespace skyline::service::audio::IAudioRenderer { namespace skyline::service::audio::IAudioRenderer {
/**
* @brief This enumerates various states a memory pool can be in
*/
enum class MemoryPoolState : u32 { enum class MemoryPoolState : u32 {
Invalid = 0, Invalid = 0,
Unknown = 1, Unknown = 1,
@ -19,9 +16,6 @@ namespace skyline::service::audio::IAudioRenderer {
Released = 6, Released = 6,
}; };
/**
* @brief This is in input containing information about a memory pool for use by the dsp
*/
struct MemoryPoolIn { struct MemoryPoolIn {
u64 address; u64 address;
u64 size; u64 size;
@ -31,9 +25,6 @@ namespace skyline::service::audio::IAudioRenderer {
}; };
static_assert(sizeof(MemoryPoolIn) == 0x20); static_assert(sizeof(MemoryPoolIn) == 0x20);
/**
* @brief This is returned to inform the guest of the state of a memory pool
*/
struct MemoryPoolOut { struct MemoryPoolOut {
MemoryPoolState state{MemoryPoolState::Detached}; MemoryPoolState state{MemoryPoolState::Detached};
u32 _unk0_; u32 _unk0_;

View File

@ -8,9 +8,6 @@
#include <audio.h> #include <audio.h>
namespace skyline::service::audio::IAudioRenderer { namespace skyline::service::audio::IAudioRenderer {
/**
* @brief This stores data for configuring a biquadratic filter
*/
struct BiquadFilter { struct BiquadFilter {
u8 enable; u8 enable;
u8 _pad0_; u8 _pad0_;
@ -22,9 +19,6 @@ namespace skyline::service::audio::IAudioRenderer {
}; };
static_assert(sizeof(BiquadFilter) == 0xC); static_assert(sizeof(BiquadFilter) == 0xC);
/**
* @brief This stores information of a wave buffer of samples
*/
struct WaveBuffer { struct WaveBuffer {
u64 address; u64 address;
u64 size; u64 size;
@ -40,9 +34,6 @@ namespace skyline::service::audio::IAudioRenderer {
}; };
static_assert(sizeof(WaveBuffer) == 0x38); static_assert(sizeof(WaveBuffer) == 0x38);
/**
* @brief This is in input containing the configuration of a voice
*/
struct VoiceIn { struct VoiceIn {
u32 slot; u32 slot;
u32 nodeId; u32 nodeId;
@ -71,9 +62,6 @@ namespace skyline::service::audio::IAudioRenderer {
static_assert(sizeof(VoiceIn) == 0x170); static_assert(sizeof(VoiceIn) == 0x170);
/**
* @brief This is returned to inform the guest of the state of a voice
*/
struct VoiceOut { struct VoiceOut {
u64 playedSamplesCount; u64 playedSamplesCount;
u32 playedWaveBuffersCount; u32 playedWaveBuffersCount;
@ -102,7 +90,7 @@ namespace skyline::service::audio::IAudioRenderer {
skyline::audio::AudioFormat format{skyline::audio::AudioFormat::Invalid}; skyline::audio::AudioFormat format{skyline::audio::AudioFormat::Invalid};
/** /**
* @brief This updates the sample buffer with data from the current wave buffer and processes it * @brief Updates the sample buffer with data from the current wave buffer and processes it
*/ */
void UpdateBuffers(); void UpdateBuffers();
@ -119,13 +107,13 @@ namespace skyline::service::audio::IAudioRenderer {
Voice(const DeviceState &state); Voice(const DeviceState &state);
/** /**
* @brief This reads the input voice data from the guest and sets internal data based off it * @brief Reads the input voice data from the guest and sets internal data based off it
* @param input The input data struct from guest * @param input The input data struct from guest
*/ */
void ProcessInput(const VoiceIn &input); void ProcessInput(const VoiceIn &input);
/** /**
* @brief This obtains the voices audio sample data, updating it if required * @brief Obtains the voices audio sample data, updating it if required
* @param maxSamples The maximum amount of samples the output buffer should contain * @param maxSamples The maximum amount of samples the output buffer should contain
* @return A vector of I16 PCM sample data * @return A vector of I16 PCM sample data
*/ */

Some files were not shown because too many files have changed in this diff Show More