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);
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));
}, writtenSamples)};

View File

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

View File

@ -7,13 +7,10 @@
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 {
private:
/**
* @brief This struct holds a single ADPCM frame header
*/
union FrameHeader {
u8 raw;
@ -25,16 +22,14 @@ namespace skyline::audio {
};
static_assert(sizeof(FrameHeader) == 0x1);
std::array<i32, 2> history{}; //!< This contains the history for decoding the ADPCM stream
std::vector<std::array<i16, 2>> coefficients; //!< This contains the coefficients 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; //!< The coefficients for decoding the ADPCM stream
public:
AdpcmDecoder(const std::vector<std::array<i16, 2>> &coefficients);
/**
* @brief This 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
* @brief Decodes a buffer of ADPCM data into I16 PCM
*/
std::vector<i16> Decode(span<u8> adpcmData);
};

View File

@ -7,9 +7,10 @@
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 Size The maximum size of the circular buffer
* @url https://en.wikipedia.org/wiki/Circular_buffer
*/
template<typename Type, size_t Size>
class CircularBuffer {
@ -17,24 +18,25 @@ namespace skyline::audio {
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 *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
Mutex mtx; //!< The mutex ensures that the buffer operations don't overlap
bool empty{true}; //!< If the buffer is full or empty, as start == end can mean either
Mutex mtx; //!< Synchronizes buffer operations so they don't overlap
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 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
* @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);
if (empty)
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) {
sizeEnd = std::min(end - start, maxSize);
@ -50,30 +52,30 @@ namespace skyline::audio {
if (copyFunction && copyOffset) {
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);
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;
}
} else {
std::memcpy(address, start, sizeEnd * sizeof(Type));
std::memcpy(pointer, start, sizeEnd * sizeof(Type));
}
address += sizeEnd;
pointer += sizeEnd;
if (sizeBegin) {
if (copyFunction && copyOffset) {
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);
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 {
std::memcpy(address, array.begin(), sizeBegin * sizeof(Type));
std::memcpy(pointer, array.begin(), sizeBegin * sizeof(Type));
}
start = array.begin() + sizeBegin;
@ -88,19 +90,19 @@ namespace skyline::audio {
}
/**
* @brief This 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
* @brief Appends data from the specified buffer into this buffer
*/
inline void Append(Type *address, ssize_t size) {
inline void Append(span<Type> buffer) {
std::lock_guard guard(mtx);
Type* pointer{buffer.data()};
ssize_t size{static_cast<ssize_t>(buffer.size())};
while (size) {
if (start <= end && end != array.end()) {
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;
end += sizeEnd;
@ -109,18 +111,18 @@ namespace skyline::audio {
auto sizePostStart{std::min(array.end() - start, size - 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())
end = array.begin() + sizePreStart;
else
end += sizePreStart;
address += sizePreStart;
pointer += sizePreStart;
size -= sizePreStart;
if (sizePostStart)
std::memcpy(end, address, sizePostStart * sizeof(Type));
std::memcpy(end, pointer, sizePostStart * sizeof(Type));
if (start == array.end())
start = array.begin() + sizePostStart;
@ -132,20 +134,12 @@ namespace skyline::audio {
else
end += sizePostStart;
address += sizePostStart;
pointer += sizePostStart;
size -= sizePostStart;
}
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,31 +15,22 @@ namespace skyline {
};
namespace audio {
/**
* @brief The available PCM stream formats
*/
enum class AudioFormat : u8 {
Invalid = 0, //!< An invalid PCM format
Int8 = 1, //!< 8 bit integer PCM
Int16 = 2, //!< 16 bit integer PCM
Int24 = 3, //!< 24 bit integer PCM
Int32 = 4, //!< 32 bit integer PCM
Float = 5, //!< Floating point PCM
ADPCM = 6 //!< Adaptive differential PCM
Int8 = 1, //!< 8 bit integer PCM
Int16 = 2, //!< 16 bit integer PCM
Int24 = 3, //!< 24 bit integer PCM
Int32 = 4, //!< 32 bit integer PCM
Float = 5, //!< Floating point PCM
ADPCM = 6, //!< Adaptive differential PCM
};
/**
* @brief The state of an audio track
*/
enum class AudioOutState : u8 {
Started = 0, //!< Stream is started and is playing
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 {
u64 tag;
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 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>
inline Out Saturate(In value) {

View File

@ -6,7 +6,7 @@
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 {
i32 a;
@ -16,7 +16,7 @@ namespace skyline::audio {
};
// @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},
{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},

View File

@ -20,7 +20,7 @@ namespace skyline::audio {
public:
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
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();

View File

@ -146,7 +146,7 @@ namespace skyline {
character = '\\';
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)

View File

@ -65,11 +65,11 @@ namespace skyline {
constexpr u16 DockedResolutionW{1920}; //!< The width component of the docked resolution
constexpr u16 DockedResolutionH{1080}; //!< The height component of the docked resolution
// 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 {
public:
@ -110,7 +110,7 @@ namespace skyline {
* @note The multiple needs to be a power of 2
*/
template<typename TypeVal, typename TypeMul>
constexpr inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
constexpr TypeVal AlignUp(TypeVal value, TypeMul multiple) {
multiple--;
return (value + multiple) & ~(multiple);
}
@ -120,7 +120,7 @@ namespace skyline {
* @note The multiple needs to be a power of 2
*/
template<typename TypeVal, typename TypeMul>
constexpr inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
constexpr TypeVal AlignDown(TypeVal value, TypeMul multiple) {
return value & ~(multiple - 1);
}
@ -128,7 +128,7 @@ namespace skyline {
* @return If the address is aligned with the multiple
*/
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)
return !(value & (multiple - 1U));
else
@ -138,14 +138,14 @@ namespace skyline {
/**
* @return If the value is page aligned
*/
constexpr inline bool PageAligned(u64 value) {
constexpr bool PageAligned(u64 value) {
return IsAligned(value, PAGE_SIZE);
}
/**
* @return If the value is word aligned
*/
constexpr inline bool WordAligned(u64 value) {
constexpr bool WordAligned(u64 value) {
return IsAligned(value, WORD_BIT / 8);
}
@ -301,7 +301,7 @@ namespace skyline {
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 {
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 {
public:
/**
* @brief This enumeration holds all the possible owners of the mutex
* @brief All the possible owners of the mutex
*/
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
Group2 = 2 //!< Group 2 owns this mutex
Group2 = 2, //!< Group 2 owns this mutex
};
/**
@ -366,13 +366,18 @@ namespace skyline {
class Logger {
private:
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
static constexpr int levelSyslog[4] = {LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG}; //!< This corresponds to LogLevel and provides it's equivalent for syslog
std::array<char, 4> levelCharacter{'0', '1', '2', '3'}; //!< The LogLevel as written out to a file
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
public:
enum class LogLevel { Error, Warn, Info, Debug }; //!< The level of a particular log
LogLevel configLevel; //!< The level of logs to write
enum class LogLevel {
Error,
Warn,
Info,
Debug,
};
LogLevel configLevel; //!< The minimum level of logs to write
/**
* @param path The path of the log file
@ -484,7 +489,7 @@ namespace skyline {
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);
};
@ -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 {
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
std::shared_ptr<kernel::type::KProcess> &process; //!< This holds a reference to the process object
thread_local static std::shared_ptr<kernel::type::KThread> thread; //!< This holds a reference to the current thread object
thread_local static ThreadContext *ctx; //!< This holds the context of the thread
std::shared_ptr<NCE> nce; //!< This holds a reference to the NCE class
std::shared_ptr<gpu::GPU> gpu; //!< This holds a reference to the GPU class
std::shared_ptr<audio::Audio> audio; //!< This holds a reference to the Audio class
std::shared_ptr<input::Input> input; //!< This holds a reference to the Input class
std::shared_ptr<loader::Loader> loader; //!< This holds a reference to the Loader class
std::shared_ptr<JvmManager> jvm; //!< This holds a reference to the JvmManager class
std::shared_ptr<Settings> settings; //!< This holds a reference to the Settings class
std::shared_ptr<Logger> logger; //!< This holds a reference to the Logger class
kernel::OS *os;
std::shared_ptr<kernel::type::KProcess> &process;
thread_local static std::shared_ptr<kernel::type::KThread> thread; //!< The KThread of the thread which accesses this object
thread_local static ThreadContext *ctx; //!< The context of the guest thread for the corresponding host thread
std::shared_ptr<NCE> nce;
std::shared_ptr<gpu::GPU> gpu;
std::shared_ptr<audio::Audio> audio;
std::shared_ptr<input::Input> input;
std::shared_ptr<loader::Loader> loader;
std::shared_ptr<JvmManager> jvm;
std::shared_ptr<Settings> settings;
std::shared_ptr<Logger> logger;
};
}

View File

@ -13,14 +13,10 @@ namespace skyline::crypto {
class AesCipher {
private:
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
*/
std::vector<u8> buffer;
/**
* @brief Calculates IV for XTS, basically just big to little endian conversion.
* @brief Calculates IV for XTS, basically just big to little endian conversion
*/
inline static std::array<u8, 0x10> GetTweak(size_t sector) {
std::array<u8, 0x10> tweak{};
@ -35,24 +31,25 @@ namespace skyline::crypto {
~AesCipher();
/**
* @brief Sets initilization vector
* @brief Sets the Initialization Vector
*/
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);
/**
* @brief Decrypts data and writes back to it
* @brief Decrypts the supplied data in-place
*/
inline void Decrypt(span<u8> data) {
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);

View File

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

View File

@ -8,9 +8,6 @@
#define U32_OFFSET(regs, field) (offsetof(regs, field) / sizeof(u32))
namespace skyline::gpu {
/**
* @brief This enumerates the identifiers used to label a specific engine
*/
enum class EngineID {
Fermi2D = 0x902D,
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 {
u16 method;
@ -31,8 +28,8 @@ namespace skyline::gpu {
namespace engine {
/**
* @brief The Engine class provides an interface that can be used to communicate with the GPU's internal engines
*/
* @brief The Engine class provides an interface that can be used to communicate with the GPU's internal engines
*/
class Engine {
protected:
const DeviceState &state;
@ -43,8 +40,8 @@ namespace skyline::gpu {
virtual ~Engine() = default;
/**
* @brief Calls an engine method with the given parameters
*/
* @brief Calls an engine method with the given parameters
*/
virtual void CallMethod(MethodParams params) {
state.logger->Warn("Called method in unimplemented engine: 0x{:X} args: 0x{:X}", params.method, params.argument);
};

View File

@ -18,9 +18,8 @@ namespace skyline {
class GPFIFO : public Engine {
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)
union Registers {
std::array<u32, constant::GpfifoRegisterCount> raw;
@ -30,22 +29,22 @@ namespace skyline {
Release = 2,
AcqGeq = 4,
AcqAnd = 8,
Reduction = 16
Reduction = 16,
};
enum class SemaphoreAcquireSwitch : u8 {
Disabled = 0,
Enabled = 1
Enabled = 1,
};
enum class SemaphoreReleaseWfi : u8 {
En = 0,
Dis = 1
Dis = 1,
};
enum class SemaphoreReleaseSize : u8 {
SixteenBytes = 0,
FourBytes = 1
FourBytes = 1,
};
enum class SemaphoreReduction : u8 {
@ -56,39 +55,39 @@ namespace skyline {
Or = 4,
Add = 5,
Inc = 6,
Dec = 7
Dec = 7,
};
enum class SemaphoreFormat : u8 {
Signed = 0,
Unsigned = 1
Unsigned = 1,
};
enum class MemOpTlbInvalidatePdb : u8 {
One = 0,
All = 1
All = 1,
};
enum class SyncpointOperation : u8 {
Wait = 0,
Incr = 1
Incr = 1,
};
enum class SyncpointWaitSwitch : u8 {
Dis = 0,
En = 1
En = 1,
};
enum class WfiScope : u8 {
CurrentScgType = 0,
All = 1
All = 1,
};
enum class YieldOp : u8 {
Nop = 0,
PbdmaTimeslice = 1,
RunlistTimeslice = 2,
Tsg = 3
Tsg = 3,
};
struct {

View File

@ -16,16 +16,16 @@ namespace skyline {
namespace gpu::engine {
/**
* @brief The Maxwell 3D engine handles processing 3D graphics
*/
* @brief The Maxwell 3D engine handles processing 3D graphics
*/
class Maxwell3D : public Engine {
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 {
u32 index;
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;
@ -35,9 +35,8 @@ namespace skyline {
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)
union Registers {
std::array<u32, constant::Maxwell3DRegisterCounter> raw;
@ -56,7 +55,7 @@ namespace skyline {
MethodTrack = 0,
MethodTrackWithFilter = 1,
MethodPassthrough = 2,
MethodReplay = 3
MethodReplay = 3,
};
struct ViewportTransform {
@ -196,7 +195,7 @@ namespace skyline {
SubtractGL = 0x8007,
ReverseSubtractGL = 0x8008,
MinimumGL = 0x800A,
MaximumGL = 0x800B
MaximumGL = 0x800B,
};
enum class Factor : u32 {
@ -293,7 +292,7 @@ namespace skyline {
Release = 0,
Acquire = 1,
Counter = 2,
Trap = 3
Trap = 3,
};
enum class ReductionOp : u8 {
@ -348,7 +347,7 @@ namespace skyline {
TransformFeedbackOffset = 0x1A,
TessControlShaderInvocations = 0x1B,
TessEvaluationShaderInvocations = 0x1D,
TessEvaluationShaderPrimitives = 0x1F
TessEvaluationShaderPrimitives = 0x1F,
};
enum class StructureSize : u8 {
@ -375,7 +374,7 @@ namespace skyline {
enum class CoordOrigin : u8 {
LowerLeft = 0,
UpperLeft = 1
UpperLeft = 1,
};
struct {
@ -559,10 +558,10 @@ namespace skyline {
static_assert(sizeof(Registers) == (constant::Maxwell3DRegisterCounter * sizeof(u32)));
#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
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);

View File

@ -4,14 +4,13 @@
#pragma once
#include <queue>
#include "engines/engine.h"
#include "engines/gpfifo.h"
#include "memory_manager.h"
namespace skyline::gpu {
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://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));
/**
* @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/classes/host/clb06f.h#L179
*/
@ -84,7 +83,7 @@ namespace skyline::gpu {
Grp0SetSubDevMask = 1,
Grp0StoreSubDevMask = 2,
Grp0UseSubDevMask = 3,
Grp2NonIncMethod = 0
Grp2NonIncMethod = 0,
};
enum class SecOp : u8 {
@ -95,7 +94,7 @@ namespace skyline::gpu {
ImmdDataMethod = 4,
OneInc = 5,
Reserved6 = 6,
EndPbSegment = 7
EndPbSegment = 7,
};
u16 methodAddress : 12;
@ -128,7 +127,7 @@ namespace skyline::gpu {
class GPFIFO {
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 {
GpEntry gpEntry;
@ -149,7 +148,7 @@ namespace skyline::gpu {
engine::GPFIFO gpfifoEngine; //!< The engine for processing GPFIFO method calls
std::array<std::shared_ptr<engine::Engine>, 8> subchannels;
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
@ -157,7 +156,7 @@ namespace skyline::gpu {
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);

View File

@ -15,9 +15,6 @@ namespace skyline::gpu {
*/
class MacroInterpreter {
private:
/**
* @brief This holds a single macro opcode
*/
#pragma pack(push, 1)
union Opcode {
u32 raw;
@ -98,11 +95,10 @@ namespace skyline::gpu {
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 {
u32 raw;
struct {
u16 address : 12;
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
ChunkDescriptor baseChunk(GpuAddressSpaceBase, GpuAddressSpaceSize, 0, ChunkState::Unmapped);
chunkList.push_back(baseChunk);
chunks.push_back(baseChunk);
}
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;
})};
if (chunk != chunkList.end())
if (chunk != chunks.end())
return *chunk;
return std::nullopt;
}
u64 MemoryManager::InsertChunk(const ChunkDescriptor &newChunk) {
auto chunkEnd{chunkList.end()};
for (auto chunk{chunkList.begin()}; chunk != chunkEnd; chunk++) {
auto chunkEnd{chunks.end()};
for (auto chunk{chunks.begin()}; chunk != chunkEnd; chunk++) {
if (chunk->CanContain(newChunk)) {
auto oldChunk{*chunk};
u64 newSize{newChunk.address - chunk->address};
@ -38,11 +38,11 @@ namespace skyline::gpu::vmm {
} else {
chunk->size = newSize;
chunk = chunkList.insert(std::next(chunk), newChunk);
chunk = chunks.insert(std::next(chunk), newChunk);
}
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;
} 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)
break;
tailChunk = chunkList.erase(tailChunk);
chunkEnd = chunkList.end();
tailChunk = chunks.erase(tailChunk);
chunkEnd = chunks.end();
}
// The given chunk is too large to fit into existing chunks
@ -74,7 +74,7 @@ namespace skyline::gpu::vmm {
if (headChunk->size == 0)
*headChunk = newChunk;
else
chunkList.insert(std::next(headChunk), newChunk);
chunks.insert(std::next(headChunk), newChunk);
return newChunk.address;
}
@ -132,11 +132,11 @@ namespace skyline::gpu::vmm {
if (!util::IsAligned(address, constant::GpuPageSize))
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;
})};
if (chunk == chunkList.end())
if (chunk == chunks.end())
return false;
chunk->state = ChunkState::Reserved;
@ -146,11 +146,11 @@ namespace skyline::gpu::vmm {
}
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;
})};
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);
chunk--;
@ -166,7 +166,7 @@ namespace skyline::gpu::vmm {
size -= readSize;
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);
readAddress = chunk->cpuAddress;
@ -176,11 +176,11 @@ namespace skyline::gpu::vmm {
}
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;
})};
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);
chunk--;
@ -196,7 +196,7 @@ namespace skyline::gpu::vmm {
size -= writeSize;
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);
writeAddress = chunk->cpuAddress;

View File

@ -11,44 +11,38 @@ namespace skyline {
}
namespace gpu::vmm {
/**
* @brief This enumerates the possible states of a memory chunk
*/
enum ChunkState {
Unmapped, //!< The chunk is unmapped
Reserved, //!< The chunk is reserved
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 {
u64 address; //!< The address of the chunk in the GPU address space
u64 size; //!< The size of the chunk in bytes
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) {}
/**
* @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) {
return (chunk.address >= this->address) && ((this->size + this->address) >= (chunk.size + chunk.address));
}
};
/**
* @brief The MemoryManager class handles the mapping of the GPU address space
*/
* @brief The MemoryManager class handles the mapping of the GPU address space
*/
class MemoryManager {
private:
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 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
@ -56,7 +50,7 @@ namespace skyline {
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
* @return The base virtual GPU address of the inserted chunk
*/
@ -64,17 +58,16 @@ namespace skyline {
public:
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
* @return The virtual GPU base address of the region base
*/
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 size The size of the region to allocate
* @return The virtual address of the region base
@ -82,7 +75,7 @@ namespace skyline {
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 size The size of the region to map
* @return The virtual address of the region base
@ -90,7 +83,7 @@ namespace skyline {
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 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
@ -99,7 +92,7 @@ namespace skyline {
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
*/
bool Unmap(u64 address);
@ -108,7 +101,6 @@ namespace skyline {
/**
* @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>
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
* @tparam T The type of object to return
*/
template<typename T>
void Write(T source, u64 address) const {

View File

@ -16,15 +16,12 @@ namespace skyline {
*/
class Syncpoint {
private:
/**
* @brief This holds information about a single waiter on a syncpoint
*/
struct Waiter {
u32 threshold;
std::function<void()> callback;
u32 threshold; //!< The syncpoint value to wait on to be reached
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;
u64 nextWaiterId{1};

View File

@ -9,6 +9,22 @@
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) {}
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) {
SynchronizeHost();
}

View File

@ -12,13 +12,10 @@ namespace skyline {
}
namespace gpu {
namespace texture {
/*
* @brief This is used to hold the dimensions of a surface
*/
struct Dimensions {
u32 width; //!< The width of the surface
u32 height; //!< The height of the surface
u32 depth; //!< The depth of the surface
u32 width;
u32 height;
u32 depth;
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) {}
/**
* @return If the specified dimension is equal to this one
*/
constexpr inline bool operator==(const Dimensions &dimensions) {
constexpr bool operator==(const Dimensions &dimensions) {
return (width == dimensions.width) && (height == dimensions.height) && (depth == dimensions.depth);
}
/**
* @return If the specified dimension is not equal to this one
*/
constexpr inline bool operator!=(const Dimensions &dimensions) {
constexpr bool operator!=(const Dimensions &dimensions) {
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 {
u8 bpb; //!< Bytes Per Block, this is to accommodate compressed formats
u16 blockHeight; //!< The height of a single block
u16 blockWidth; //!< The width of a single block
vk::Format vkFormat; //!< The underlying Vulkan type of the format
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 block in pixels
u16 blockWidth; //!< The width of a block in pixels
vk::Format vkFormat;
/**
* @return If this is a compressed texture format or not
*/
inline constexpr bool IsCompressed() {
constexpr bool IsCompressed() {
return (blockHeight != 1) || (blockWidth != 1);
}
@ -63,42 +51,32 @@ namespace skyline {
* @param depth The depth of the texture in layers
* @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;
}
/**
* @param dimensions The dimensions of a texture
* @return The size of the texture in bytes
*/
inline constexpr size_t GetSize(Dimensions dimensions) {
constexpr size_t GetSize(Dimensions dimensions) {
return GetSize(dimensions.width, dimensions.height, dimensions.depth);
}
/**
* @return If the specified format is equal to this one
*/
inline constexpr bool operator==(const Format &format) {
constexpr bool operator==(const Format &format) {
return vkFormat == format.vkFormat;
}
/**
* @return If the specified format is not equal to this one
*/
inline constexpr bool operator!=(const Format &format) {
constexpr bool operator!=(const Format &format) {
return vkFormat != format.vkFormat;
}
/**
* @return If this format is actually valid or not
*/
inline constexpr operator bool() {
constexpr operator bool() {
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 {
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 {
struct {
@ -118,9 +96,6 @@ namespace skyline {
u32 pitch; //!< The pitch of the texture if it's pitch linear
};
/**
* @brief This enumerates all of the channel swizzle options
*/
enum class SwizzleChannel {
Zero, //!< Write 0 to the channel
One, //!< Write 1 to the channel
@ -130,9 +105,6 @@ namespace skyline {
Alpha, //!< Alpha channel
};
/**
* @brief This holds all of the texture swizzles on each color channel
*/
struct Swizzle {
SwizzleChannel red{SwizzleChannel::Red}; //!< Swizzle for the red channel
SwizzleChannel green{SwizzleChannel::Green}; //!< Swizzle for the green channel
@ -145,109 +117,95 @@ namespace skyline {
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> {
private:
const DeviceState &state; //!< The state of the device
const DeviceState &state;
public:
u64 address; //!< The address of the texture in guest memory
std::shared_ptr<Texture> host; //!< The corresponding host texture object
texture::Dimensions dimensions; //!< The dimensions of the texture
texture::Format format; //!< The format of the texture
texture::TileMode tileMode; //!< The tiling mode of the texture
texture::TileConfig tileConfig; //!< The tiling configuration of the texture
std::weak_ptr<Texture> host; //!< A host texture (if any) that was created from this guest texture
texture::Dimensions dimensions;
texture::Format format;
texture::TileMode tileMode;
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);
}
/**
* @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 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)
* @return A shared pointer to the host texture object
* @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 = {}) {
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;
}
std::shared_ptr<Texture> InitializeTexture(std::optional<texture::Format> format = std::nullopt, std::optional<texture::Dimensions> dimensions = std::nullopt, texture::Swizzle swizzle = {});
protected:
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;
}
std::shared_ptr<PresentationTexture> InitializePresentationTexture();
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 {
private:
const DeviceState &state; //!< The state of the device
const DeviceState &state;
public:
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
texture::Dimensions dimensions; //!< The dimensions of the texture
texture::Format format; //!< The format of the host texture
texture::Swizzle swizzle; //!< The swizzle of the host texture
std::shared_ptr<GuestTexture> guest; //!< The guest texture from which this was created, it is required for syncing
texture::Dimensions dimensions;
texture::Format format;
texture::Swizzle swizzle;
public:
Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle);
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 tileConfig The configuration for the tiling mode (Can be default argument for Linear)
*/
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)
* @param dimensions The dimensions to adjust the texture to
* @brief Converts the texture dimensions to the specified ones (As long as they are within the GuestTexture's range)
*/
void SetDimensions(texture::Dimensions dimensions);
/**
* @brief This sets the format to the specified one
* @param format The format to change the texture to
* @brief Converts the texture to have the specified format
*/
void SetFormat(texture::Format format);
/**
* @brief This sets the channel swizzle to the specified one
* @param swizzle The channel swizzle to the change the texture to
* @brief Change the texture channel swizzle to the specified one
*/
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();
/**
* @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();
};
/**
* @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 {
public:

View File

@ -11,7 +11,7 @@
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 {
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 {
private:
@ -26,11 +26,11 @@ namespace skyline::input {
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
* @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) {
case NpadId::Handheld:
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::array<NpadDevice, constant::NpadCount> npads;
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
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
*/
constexpr inline NpadDevice &at(NpadId id) {
constexpr NpadDevice &at(NpadId id) {
return npads.at(Translate(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));
}
/**
* @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
*/
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();
/**
* @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();
};

View File

@ -14,7 +14,7 @@ namespace skyline::constant {
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 {
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 {
u32 raw;
@ -41,9 +41,6 @@ namespace skyline::input {
};
static_assert(sizeof(NpadStyleSet) == 0x4);
/**
* @brief This enumerates all of the axis on NPads
*/
enum class NpadAxisId {
LX, //!< Left Stick X
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 {
Player1 = 0x0,
@ -114,7 +111,7 @@ namespace skyline::input {
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 {
private:
@ -124,15 +121,15 @@ namespace skyline::input {
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
* @return The next entry that has been created with values from the last entry
*/
NpadControllerState &GetNextEntry(NpadControllerInfo &info);
/**
* @return The NpadControllerInfo for this controller based on it's type
*/
* @return The NpadControllerInfo for this controller based on it's type
*/
NpadControllerInfo &GetControllerInfo();
public:
@ -147,41 +144,33 @@ namespace skyline::input {
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) {
section.header.assignment = assignment;
}
/**
* @return The assignment mode of this Joy-Con
*/
inline NpadJoyAssignment GetAssignment() {
return section.header.assignment;
}
/**
* @brief This connects this controller to the guest
* @param newType The type of controller to connect as
* @brief Connects this controller to the guest
*/
void Connect(NpadControllerType newType);
/**
* @brief This disconnects this controller from the guest
* @brief Disconnects this controller from the guest
*/
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 pressed If the buttons were pressed or released
*/
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 value The value to set
*/

View File

@ -7,7 +7,7 @@
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +16,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -7,7 +7,9 @@
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +18,9 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -7,7 +7,8 @@
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
*/
struct ConsoleSixAxisSensorSection {

View File

@ -7,7 +7,7 @@
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 {
u64 timestamp; //!< The total timestamp in ticks
@ -16,7 +16,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -7,7 +7,7 @@
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +16,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -7,7 +7,7 @@
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -16,7 +16,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -6,9 +6,6 @@
#include "common.h"
namespace skyline::input {
/**
* @brief This enumerates all the modifier keys that can be used
*/
union ModifierKey {
u64 raw;
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -39,7 +36,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -7,7 +7,7 @@
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -27,7 +27,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -7,9 +7,6 @@
namespace skyline::input {
// @fmt:off
/**
* @brief This enumerates all of the types of an NPad controller
*/
enum class NpadControllerType : u32 {
None = 0,
ProController = 0b1,
@ -20,26 +17,17 @@ namespace skyline::input {
};
// @fmt:on
/**
* @brief This enumerates all the possible assignments of the Joy-Con(s)
*/
enum class NpadJoyAssignment : u32 {
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)
};
/**
* @brief This enumerates the status codes for reading NPad colors
*/
enum class NpadColorReadStatus : u32 {
Success = 0, //!< The color was read successfully
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 {
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)
@ -47,8 +35,8 @@ namespace skyline::input {
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 {
NpadControllerType type;
NpadJoyAssignment assignment;
@ -63,7 +51,7 @@ namespace skyline::input {
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 {
u64 raw;
@ -100,9 +88,6 @@ namespace skyline::input {
};
static_assert(sizeof(NpadButton) == 0x8);
/**
* @brief This structure holds data about the state of the connection with the controller
*/
union NpadConnectionState {
u64 raw;
struct {
@ -117,8 +102,8 @@ namespace skyline::input {
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 {
u64 globalTimestamp; //!< The global timestamp in samples
u64 localTimestamp; //!< The local timestamp in samples
@ -135,9 +120,6 @@ namespace skyline::input {
};
static_assert(sizeof(NpadControllerState) == 0x30);
/**
* @brief This structure contains the header and entries for the controller input
*/
struct NpadControllerInfo {
CommonHeader header;
std::array<NpadControllerState, constant::HidEntryCount> state;
@ -145,7 +127,7 @@ namespace skyline::input {
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 {
float x; //!< The data in the X-axis
@ -155,8 +137,8 @@ namespace skyline::input {
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 {
u64 globalTimestamp; //!< The global timestamp in samples
u64 _unk0_;
@ -167,13 +149,10 @@ namespace skyline::input {
SixAxisVector rotation;
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);
/**
* @brief This structure contains header and entries for the IMU (Six-Axis) data
*/
struct NpadSixAxisInfo {
CommonHeader header;
std::array<NpadSixAxisState, constant::HidEntryCount> state;
@ -181,8 +160,8 @@ namespace skyline::input {
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 {
u32 raw;
struct {
@ -209,8 +188,8 @@ namespace skyline::input {
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 {
u64 raw;
struct {
@ -233,7 +212,8 @@ namespace skyline::input {
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 {
u32 raw;
@ -243,9 +223,6 @@ namespace skyline::input {
};
static_assert(sizeof(NpadSystemButtonProperties) == 0x4);
/**
* @brief This enumerates all the possible values for the NPad's battery level
*/
enum class NpadBatteryLevel : u32 {
Empty = 0,
Low = 1,
@ -255,8 +232,8 @@ 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 {
NpadHeader header;

View File

@ -7,7 +7,8 @@
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 {
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 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_;
};
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 {
u64 globalTimestamp; //!< The global timestamp in samples
@ -39,7 +40,7 @@ namespace skyline::input {
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 {
CommonHeader header;

View File

@ -15,7 +15,7 @@ namespace skyline {
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 {
u64 timestamp; //!< The timestamp of the latest entry in ticks

View File

@ -17,7 +17,7 @@
namespace skyline {
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 {
DebugPadSection debugPad; //!< The DebugPad section (https://switchbrew.org/wiki/HID_Shared_Memory#DebugPad)

View File

@ -13,21 +13,31 @@ namespace skyline {
namespace kernel::ipc {
/**
* @brief This reflects the value in CommandStruct::type
* @url https://switchbrew.org/wiki/IPC_Marshalling#Type
*/
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 {
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 {
CommandType type : 16;
@ -43,7 +53,7 @@ namespace skyline {
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 {
bool sendPid : 1;
@ -54,10 +64,18 @@ namespace skyline {
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 {
u8 command;
DomainCommand command;
u8 inputCount;
u16 payloadSz;
u32 objectId;
@ -67,14 +85,7 @@ namespace skyline {
static_assert(sizeof(DomainHeaderRequest) == 16);
/**
* @brief This reflects the value of DomainHeaderRequest::command
*/
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)
* @url https://switchbrew.org/wiki/IPC_Marshalling#Domains
*/
struct DomainHeaderResponse {
u32 outputCount;
@ -84,7 +95,7 @@ namespace skyline {
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 {
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 {
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 {
u16 counter0_5 : 6; //!< The first 5 bits of the counter
@ -121,16 +137,10 @@ namespace skyline {
counter9_11 = static_cast<u16>(address & 0x38);
}
/**
* @return The address of the buffer
*/
inline u64 Address() {
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() {
return static_cast<u16>(counter0_5) | static_cast<u16>(counter9_11) << 9;
}
@ -138,7 +148,7 @@ namespace skyline {
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 {
u32 size0_31 : 32; //!< The first 32 bits of the size
@ -157,16 +167,10 @@ namespace skyline {
size32_35 = static_cast<u8>(size & 0x78000000);
}
/**
* @return The address of the buffer
*/
inline u64 Address() {
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() {
return static_cast<u64>(size0_31) | static_cast<u64>(size32_35) << 32;
}
@ -174,7 +178,7 @@ namespace skyline {
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 {
u64 address : 48; //!< The 48-bit address of the buffer
@ -184,47 +188,40 @@ namespace skyline {
};
static_assert(sizeof(BufferDescriptorC) == 8);
/**
* @brief This enumerates the types of IPC buffers
*/
enum class IpcBufferType {
X, //!< This is a type-X buffer
A, //!< This is a type-A buffer
B, //!< This is a type-B buffer
W, //!< This is a type-W buffer
C //!< This is a type-C buffer
X, //!< Type-X buffer (BufferDescriptorX)
A, //!< Type-A buffer (BufferDescriptorABW)
B, //!< Type-B buffer (BufferDescriptorABW)
W, //!< Type-W buffer (BufferDescriptorABW)
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 {
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:
CommandHeader *header{}; //!< The header of the request
HandleDescriptor *handleDesc{}; //!< The handle descriptor in case CommandHeader::handle_desc is true in the header
CommandHeader *header{};
HandleDescriptor *handleDesc{};
bool isDomain{}; //!< If this is a domain request
DomainHeaderRequest *domain{}; //!< In case this is a domain request, this holds data regarding it
PayloadHeader *payload{}; //!< This is the header of the payload
u8 *cmdArg{}; //!< This is a pointer to the data payload (End of PayloadHeader)
u64 cmdArgSz{}; //!< This is 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> moveHandles; //!< A vector of 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<span<u8>> inputBuf; //!< This is a vector of input buffers
std::vector<span<u8>> outputBuf; //!< This is a vector of output buffers
DomainHeaderRequest *domain{};
PayloadHeader *payload{};
u8 *cmdArg{}; //!< A pointer to the data payload
u64 cmdArgSz{}; //!< The size of the data payload
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; //!< The handles that should be moved from the server to the client process rather than copied
std::vector<KHandle> domainObjects;
std::vector<span<u8>> inputBuf;
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);
/**
* @brief This returns a reference to an item from the top of the payload
* @tparam ValueType The type of the object to read
* @brief Returns a reference to an item from the top of the payload
*/
template<typename ValueType>
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)
*/
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
* @tparam ValueType The type of the object to skip
* @brief Skips an object to pop off the top
*/
template<typename ValueType>
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 {
private:
const DeviceState &state; //!< The state of the device
std::vector<u8> payload; //!< This holds all of the contents to be pushed to the payload
const DeviceState &state;
std::vector<u8> payload; //!< The contents to be pushed to the data payload
public:
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> moveHandles; //!< A vector of handles to move
std::vector<KHandle> domainObjects; //!< A vector of domain objects to write
std::vector<KHandle> copyHandles;
std::vector<KHandle> moveHandles;
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);
/**
@ -282,7 +275,6 @@ namespace skyline {
inline void Push(const ValueType &value) {
auto size{payload.size()};
payload.resize(size + 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
* @param string The string to write to the payload
*/
template<>
inline void Push(const std::string &string) {
inline void Push(std::string_view string) {
auto size{payload.size()};
payload.resize(size + string.size());
std::memcpy(payload.data() + size, string.data(), string.size());
}

View File

@ -6,11 +6,11 @@
namespace skyline::kernel {
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;
})};
if (chunk-- != chunkList.begin()) {
if (chunk-- != chunks.begin()) {
if ((chunk->address + chunk->size) > address)
return chunk.base();
}
@ -37,24 +37,24 @@ namespace skyline::kernel {
}
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;
})};
if (upperChunk != chunkList.begin()) {
if (upperChunk != chunks.begin()) {
auto lowerChunk{std::prev(upperChunk)};
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);
}
chunkList.insert(upperChunk, chunk);
chunks.insert(upperChunk, chunk);
}
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)
chunk = chunkList.erase(chunk);
chunk = chunks.erase(chunk);
else
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 (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;
})};
u64 upperAddress{};
u64 lowerAddress{};
if (upperChunk != chunkList.end()) {
if (upperChunk != chunks.end()) {
upperAddress = upperChunk->address;
if (upperChunk == chunkList.begin()) {
if (upperChunk == chunks.begin()) {
lowerAddress = addressSpace.address;
} else {
upperChunk--;
@ -194,7 +194,7 @@ namespace skyline::kernel {
}
} else {
upperAddress = addressSpace.address + addressSpace.size;
lowerAddress = chunkList.back().address + chunkList.back().size;
lowerAddress = chunks.back().address + chunks.back().size;
}
u64 size{upperAddress - lowerAddress};
@ -217,7 +217,7 @@ namespace skyline::kernel {
size_t MemoryManager::GetProgramSize() {
size_t size{};
for (const auto &chunk : chunkList)
for (const auto &chunk : chunks)
size += chunk.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 {
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 {
u64 address; //!< The base address of the mapping
@ -74,14 +74,15 @@ namespace skyline {
u32 type; //!< The MemoryType of the mapping
u32 attributes; //!< The attributes of the mapping
u32 permissions; //!< The permissions of the mapping
u32 ipcRefCount; //!< The IPC reference count (This is always 0)
u32 deviceRefCount; //!< The device reference count (This is always 0)
u32 ipcRefCount; //!< The IPC reference count (Always 0)
u32 deviceRefCount; //!< The device reference count (Always 0)
u32 _pad0_;
};
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 {
Unmapped = 0x0,
@ -105,11 +106,12 @@ namespace skyline {
NonDeviceIpc = 0x12,
KernelStack = 0x13,
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 {
constexpr MemoryState(const u32 value) : value(value) {}
@ -142,7 +144,8 @@ namespace skyline {
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 {
constexpr MemoryState Unmapped{0x00000000};
@ -168,9 +171,6 @@ namespace skyline {
constexpr MemoryState CodeWritable{0x00402015};
};
/**
* @brief This struct is used to hold the location and size of a memory region
*/
struct Region {
u64 address; //!< The base address of the region
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 {
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 {
u64 address; //!< The address of the current chunk
u64 size; //!< The size of the current chunk in bytes
u64 host; //!< The address of the chunk in the host
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 {
const BlockDescriptor block; //!< The block descriptor at the address
@ -248,8 +248,8 @@ namespace skyline {
*/
class MemoryManager {
private:
const DeviceState &state; //!< The state of the device
std::vector<ChunkDescriptor> chunkList; //!< This vector holds all the chunk descriptors
const DeviceState &state;
std::vector<ChunkDescriptor> chunks;
/**
* @param address The address to find a chunk at
@ -290,7 +290,7 @@ namespace skyline {
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 size The size of the code region
* @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 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
*/
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/)
#include <os.h>
#include <kernel/types/KProcess.h>
#include "results.h"
#include "svc.h"
@ -170,7 +171,7 @@ namespace skyline::kernel::svc {
if (!sourceObject)
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.ctx->registers.w0 = Result{};
@ -375,7 +376,7 @@ namespace skyline::kernel::svc {
void CloseHandle(DeviceState &state) {
auto handle{static_cast<KHandle>(state.ctx->registers.w0)};
try {
state.process->DeleteHandle(handle);
state.process->CloseHandle(handle);
state.logger->Debug("svcCloseHandle: Closing handle: 0x{:X}", handle);
state.ctx->registers.w0 = Result{};
} catch (const std::exception &) {
@ -583,8 +584,7 @@ namespace skyline::kernel::svc {
}
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), portSize);
std::string_view port(state.process->GetPointer<char>(state.ctx->registers.x1), sizeof(service::ServiceName));
KHandle handle{};
if (port.compare("sm:") >= 0) {
@ -607,7 +607,7 @@ namespace skyline::kernel::svc {
}
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};
pid_t pid{};

View File

@ -40,147 +40,176 @@ namespace skyline {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -7,13 +7,11 @@
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 {
public:
/**
* @param state The state of the device
*/
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
*/
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 {
public:
const DeviceState &state; //!< The state of the device
KType objectType; //!< The type of this object
const DeviceState &state;
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) {}
};
}

View File

@ -18,7 +18,6 @@ namespace skyline::kernel::type {
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 size The size of the allocation
* @param permission The permissions for the allocated memory

View File

@ -14,24 +14,23 @@ namespace skyline {
namespace constant {
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 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
}
namespace kernel::type {
/**
* @brief The KProcess class is responsible for holding the state of a process
*/
* @brief The KProcess class is responsible for holding the state of a process
*/
class KProcess : public KSyncObject {
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
* @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.
* The first slot of the first page is reserved for user-mode exception handling.
* Read more about TLS here: https://switchbrew.org/wiki/Thread_Local_Storage
* @brief 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
* The first slot of the first page is reserved for user-mode exception handling
* @url https://switchbrew.org/wiki/Thread_Local_Storage
*/
struct TlsPage {
u64 address; //!< The address of the page allocated for TLS
@ -39,8 +38,8 @@ namespace skyline {
bool slot[constant::TlsSlots]{}; //!< An array of booleans denoting which TLS slots are reserved
/**
* @param address The address of the allocated page
*/
* @param address The address of the allocated page
*/
TlsPage(u64 address);
/**
@ -64,21 +63,20 @@ 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();
/**
* @brief This initializes heap and the initial TLS page
*/
* @brief Initializes heap and the initial TLS page
*/
void InitializeMemory();
public:
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
*/
template<typename objectClass>
@ -87,18 +85,15 @@ namespace skyline {
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 {
Created, //!< The process was created but the main thread has not started yet
Started, //!< The process has been started
Exiting //!< The process is exiting
} status = Status::Created; //!< The state of the process
Exiting, //!< The process is exiting
} 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 {
std::atomic_bool flag{false}; //!< The underlying atomic flag of the thread
u8 priority; //!< The priority of the thread
@ -119,12 +114,11 @@ namespace skyline {
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<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 conditionalLock; //!< This mutex is to prevent concurrent conditional variable operations to happen at once
Mutex mutexLock; //!< Synchronizes all concurrent guest mutex operations
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
* @param state The state of the device
* @param pid The PID of the main thread
* @param entryPoint The address to start execution at
* @param stack The KSharedMemory object for Stack memory allocated by the guest process
@ -133,8 +127,8 @@ namespace skyline {
KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, std::shared_ptr<type::KSharedMemory> &stack, std::shared_ptr<type::KSharedMemory> &tlsMemory);
/**
* Close the file descriptor to the process's memory
*/
* Close the file descriptor to the process's memory
*/
~KProcess();
/**
@ -148,7 +142,7 @@ namespace skyline {
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
* @return The corresponding host address
*/
@ -158,7 +152,7 @@ namespace skyline {
* @tparam Type The type of the pointer to return
* @param address The 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>
inline Type *GetPointer(u64 address) {
@ -166,11 +160,8 @@ namespace skyline {
}
/**
* @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
*/
* @brief Returns a reference to an object from guest memory
*/
template<typename Type>
inline Type &GetReference(u64 address) {
auto source{GetPointer<Type>(address)};
@ -250,7 +241,7 @@ namespace skyline {
* @param destination The address to the location where the process memory is written
* @param offset The address to read from in process memory
* @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);
@ -259,7 +250,7 @@ namespace skyline {
* @param source The address of where the data to be written is present
* @param offset The address to write to in process memory
* @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);
@ -345,15 +336,14 @@ namespace skyline {
std::optional<HandleOut<KMemory>> GetMemoryObject(u64 address);
/**
* @brief This deletes a certain handle from the handle table
* @param handle The handle to delete
*/
inline void DeleteHandle(KHandle handle) {
* @brief Closes a handle in the handle table
*/
inline void CloseHandle(KHandle handle) {
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 owner The handle of the current mutex owner
* @return If the mutex was successfully locked
@ -361,7 +351,7 @@ namespace skyline {
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
* @return If the mutex was successfully unlocked
*/
@ -376,15 +366,15 @@ namespace skyline {
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 amount The amount of waiters to signal
*/
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() {
signalled = false;
}

View File

@ -15,20 +15,20 @@ namespace skyline::kernel::type {
*/
class KSession : public KSyncObject {
public:
std::shared_ptr<service::BaseService> serviceObject; //!< A shared pointer to the service class
std::unordered_map<KHandle, std::shared_ptr<service::BaseService>> domainTable; //!< This maps from a virtual handle to it's service
std::shared_ptr<service::BaseService> serviceObject;
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
enum class ServiceStatus { Open, Closed } serviceStatus{ServiceStatus::Open}; //!< If the session is open or closed
bool isDomain{}; //!< Holds if this is a domain session or not
bool isOpen{true}; //!< If the session is open 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
*/
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
*/
KHandle ConvertDomain() {

View File

@ -12,26 +12,20 @@ namespace skyline::kernel::type {
class KSharedMemory : public KMemory {
private:
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:
/**
* @brief This holds the address and size of a process's mapping
*/
struct MapInfo {
u64 address;
size_t size;
memory::Permission permission;
/**
* @brief Returns if the object is valid
* @return If the MapInfo object is valid
*/
inline bool Valid() { return address && size && permission.Get(); }
constexpr bool Valid() {
return address && size && permission.Get();
}
} 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 size The size of the allocation on the kernel
* @param permission The permission of the kernel process

View File

@ -13,10 +13,6 @@ namespace skyline::kernel::type {
public:
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) {};
/**

View File

@ -17,7 +17,7 @@ namespace skyline::kernel::type {
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 {
i8 low; //!< The low range of priority
@ -28,7 +28,7 @@ namespace skyline::kernel::type {
* @param value The priority value to rescale
* @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)));
}
@ -36,7 +36,7 @@ namespace skyline::kernel::type {
* @param value The priority value to check for validity
* @return If the supplied priority value is valid
*/
constexpr inline bool Valid(i8 value) {
constexpr bool Valid(i8 value) {
return (value >= low) && (value <= high);
}
};
@ -45,12 +45,12 @@ namespace skyline::kernel::type {
enum class Status {
Created, //!< The thread has been created but has not been started yet
Running, //!< The thread is running currently
Dead //!< The thread is dead and not running
} status = Status::Created; //!< The state of the thread
Dead, //!< The thread is dead and not running
} 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::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
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 tls; //!< The address of TLS (Thread Local Storage) slot assigned to the current thread
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
/**
* @param state The state of the device
* @param handle The handle of the current thread
* @param selfTid The TID of this thread
* @param entryPoint The address to start execution at
@ -78,12 +77,12 @@ namespace skyline::kernel::type {
~KThread();
/**
* @brief This starts this thread process
* @brief Starts this thread process
*/
void Start();
/**
* @brief This kills the thread
* @brief Kills the thread process
*/
void Kill();

View File

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

View File

@ -18,7 +18,6 @@ namespace skyline::kernel::type {
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 address The address to map to (If NULL an arbitrary address is picked)
* @param size The size of the allocation

View File

@ -7,11 +7,11 @@
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 {
/**
* @brief This holds the contents and offset of an executable segment
* @brief The contents and offset of an executable segment
*/
struct Segment {
std::vector<u8> contents; //!< The raw contents of the segment

View File

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

View File

@ -8,7 +8,7 @@
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
*/
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
*/
enum class LoaderResult : int8_t {
@ -29,7 +29,7 @@ namespace skyline::loader {
MissingHeaderKey,
MissingTitleKey,
MissingTitleKek,
MissingKeyArea
MissingKeyArea,
};
/**
@ -48,7 +48,7 @@ namespace skyline::loader {
class Loader {
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 {
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 executable The executable itself
* @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 state The state of the device
*/
virtual void LoadProcessData(const std::shared_ptr<kernel::type::KProcess> process, const DeviceState &state) = 0;
};

View File

@ -8,7 +8,8 @@
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 {
private:
@ -18,7 +19,7 @@ namespace skyline::loader {
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 process The process to load the ExeFS into
*/

View File

@ -7,21 +7,16 @@
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 {
private:
/**
* @brief This holds a single data segment's offset and size
*/
struct NroSegmentHeader {
u32 offset; //!< The offset of the region
u32 size; //!< The size of the region
u32 offset;
u32 size;
};
/**
* @brief This holds the header of an NRO file
*/
struct NroHeader {
u32 _pad0_;
u32 modOffset; //!< The offset of the MOD metadata
@ -38,7 +33,7 @@ namespace skyline::loader {
u32 bssSize; //!< The size of the bss segment
u32 _pad2_;
u64 buildId[4]; //!< The build ID of the NRO
std::array<u64, 4> buildId; //!< The build ID of the NRO
u64 _pad3_;
NroSegmentHeader apiInfo; //!< The .apiInfo segment header
@ -46,29 +41,27 @@ namespace skyline::loader {
NroSegmentHeader dynsym; //!< The .dynsym segment header
} header{};
/**
* @brief This holds a single asset section's offset and size
*/
struct NroAssetSection {
u64 offset; //!< The offset of the region
u64 size; //!< The size of the region
u64 offset;
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 {
u32 magic; //!< The asset section magic "ASET"
u32 version; //!< The format version
NroAssetSection icon; //!< The header describing the location of the icon
NroAssetSection nacp; //!< The header describing the location of the NACP
NroAssetSection romFs; //!< The header describing the location of the RomFS
u32 magic; //!< "ASET"
u32 version;
NroAssetSection icon;
NroAssetSection nacp;
NroAssetSection romFs;
} 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
* @return A buffer containing the data of the requested segment
*/

View File

@ -7,10 +7,13 @@
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 {
private:
std::shared_ptr<vfs::Backing> backing;
union NsoFlags {
struct {
bool textCompressed : 1; //!< .text is compressed
@ -20,13 +23,10 @@ namespace skyline::loader {
bool roHash : 1; //!< .rodata 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);
/**
* @brief This holds a single data segment's offset, loading offset and size
*/
struct NsoSegmentHeader {
u32 fileOffset; //!< The offset of the segment in the NSO
u32 memoryOffset; //!< The memory offset where the region should be loaded
@ -34,9 +34,6 @@ namespace skyline::loader {
};
static_assert(sizeof(NsoSegmentHeader) == 0xC);
/**
* @brief This holds the header of an NSO file
*/
struct NsoHeader {
u32 magic; //!< The NSO magic "NSO0"
u32 version; //!< The version of the application
@ -50,7 +47,7 @@ namespace skyline::loader {
NsoSegmentHeader data; //!< The .data segment header
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 roCompressedSize; //!< The size of the compressed .rodata segment
@ -62,14 +59,12 @@ namespace skyline::loader {
u64 dynstr; //!< The .rodata-relative offset of .dynstr
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);
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 compressedSize The compressed size of the segment, 0 if the segment is not compressed
* @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);
/**
* @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 process The process to load the NSO into
* @param offset The offset from the base address to place the NSO

View File

@ -11,12 +11,13 @@
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 {
private:
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> controlNca; //!< The main control NCA within the NSP

View File

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

View File

@ -3,8 +3,8 @@
#pragma once
#include "common.h"
#include <sys/wait.h>
#include "kernel/types/KSharedMemory.h"
namespace skyline {
/**
@ -12,11 +12,11 @@ namespace skyline {
*/
class NCE {
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
/**
* @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
*/
void KernelThread(pid_t thread);
@ -30,7 +30,7 @@ namespace skyline {
~NCE();
/**
* @brief This function is the main event loop of the program
* @brief The main event loop of the program
*/
void Execute();
@ -65,14 +65,14 @@ namespace skyline {
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 ctx The ThreadContext of the thread to log
*/
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 baseAddress The address at which the code is mapped
* @param offset The offset of the code block from the base address

View File

@ -17,28 +17,28 @@ namespace skyline {
#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
*/
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);
/**
* @brief This loads the context from TLS into CPU registers
* @brief Loads the context from TLS into CPU registers
*/
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);
/**
* @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 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
/**
* @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 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 {
NotReady = 0, //!< The thread hasn't yet entered the entry handler
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 {
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 {
ThreadState state; //!< The state of the guest

View File

@ -7,29 +7,24 @@ namespace skyline {
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 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 {
/**
* @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 {
/**
* @brief Creates a BRK instruction with a specific immediate value, used for generating BRK opcodes
* @param value The immediate value of the instruction
*/
inline constexpr Brk(u16 value) {
constexpr Brk(u16 value) {
sig0 = 0x0;
this->value = value;
sig1 = 0x6A1;
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid BRK instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig0 == 0x0 && sig1 == 0x6A1);
}
@ -39,20 +34,16 @@ namespace skyline {
u32 value : 16; //!< 16-bit immediate value
u16 sig1 : 11; //!< 11-bit signature (0x6A1)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid SVC instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig0 == 0x1 && sig1 == 0x6A0);
}
@ -62,31 +53,26 @@ namespace skyline {
u32 value : 16; //!< 16-bit immediate value
u16 sig1 : 11; //!< 11-bit signature (0x6A1)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
/**
* @brief Creates a MRS instruction, used for generating BRK opcodes
* @param srcReg The source system 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->destReg = dstReg;
sig = 0xD53;
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MRS instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig == 0xD53);
}
@ -96,20 +82,16 @@ namespace skyline {
u32 srcReg : 15; //!< 15-bit source register
u16 sig : 12; //!< 16-bit signature (0xD53)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MSR instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig == 0xD51);
}
@ -119,38 +101,32 @@ namespace skyline {
u32 destReg : 15; //!< 15-bit source register
u16 sig : 12; //!< 16-bit signature (0xD51)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
public:
/**
* @brief Creates a B instruction with a specific offset
* @param offset The offset to encode in the instruction (Should be 32-bit aligned)
* @param offset The relative offset to branch to (Should be 32-bit aligned)
*/
inline constexpr B(i64 offset) {
this->offset = static_cast<i32>(offset / 4);
constexpr B(i64 offset) {
this->offset = static_cast<i32>(offset / sizeof(u32));
sig = 0x5;
}
/**
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction
* @return The offset encoded within the instruction in bytes
*/
inline constexpr i32 Offset() {
return offset * 4;
constexpr i32 Offset() {
return offset * sizeof(u32);
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid Branch instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig == 0x5);
}
@ -159,38 +135,32 @@ namespace skyline {
i32 offset : 26; //!< 26-bit branch offset
u8 sig : 6; //!< 6-bit signature (0x5)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
public:
/**
* @brief Creates a BL instruction with a specific offset
* @param offset The offset to encode in the instruction (Should be 32-bit aligned)
* @param offset The relative offset to branch to (Should be 32-bit aligned)
*/
inline constexpr BL(i64 offset) {
this->offset = static_cast<i32>(offset / 4);
constexpr BL(i64 offset) {
this->offset = static_cast<i32>(offset / sizeof(u32));
sig = 0x25;
}
/**
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction
* @return The offset encoded within the instruction in bytes
*/
inline constexpr i32 Offset() {
return offset * 4;
constexpr i32 Offset() {
return offset * sizeof(u32);
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid Branch Linked instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig == 0x25);
}
@ -199,23 +169,22 @@ namespace skyline {
i32 offset : 26; //!< 26-bit branch offset
u8 sig : 6; //!< 6-bit signature (0x25)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
public:
/**
* @brief Creates a MOVZ instruction
* @param destReg The destination Xn register to store the value in
* @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
*/
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->imm16 = imm16;
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 imm16 The 16-bit value to store
* @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->imm16 = imm16;
hw = shift;
@ -238,18 +206,13 @@ namespace skyline {
}
/**
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction (In Bytes)
* @return The shift encoded within the instruction in bytes
*/
inline constexpr u8 Shift() {
constexpr u8 Shift() {
return static_cast<u8>(hw * sizeof(u16));
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVZ instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig == 0xA5);
}
@ -261,23 +224,22 @@ namespace skyline {
u8 sig : 8; //!< 8-bit signature (0xA5)
u8 sf : 1; //!< 1-bit register type
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
public:
/**
* @brief Creates a MOVK instruction
* @param destReg The destination Xn register to store the value in
* @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
*/
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->imm16 = imm16;
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 imm16 The 16-bit value to store
* @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->imm16 = imm16;
hw = shift;
@ -300,18 +261,13 @@ namespace skyline {
}
/**
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction (In Bytes)
* @return The shift encoded within the instruction in bytes
*/
inline constexpr u8 Shift() {
constexpr u8 Shift() {
return static_cast<u8>(hw * sizeof(u16));
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVK instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig == 0xE5);
}
@ -323,7 +279,7 @@ namespace skyline {
u8 sig : 8; //!< 8-bit signature (0xA5)
u8 sf : 1; //!< 1-bit register type
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
static_assert(sizeof(Movk) == sizeof(u32));
@ -334,7 +290,7 @@ namespace skyline {
* @return A array with the instructions to insert the value
*/
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;
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 {
public:
@ -362,10 +318,10 @@ namespace skyline {
* @param destReg The destination Xn register to store the value in
* @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);
sig0 = 0x1F;
imm6 = 0;
imm = 0;
this->srcReg = static_cast<u8>(srcReg);
sig1 = 0x150;
sf = 1;
@ -376,20 +332,16 @@ namespace skyline {
* @param destReg The destination Wn register to store the value in
* @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);
sig0 = 0x1F;
imm6 = 0;
imm = 0;
this->srcReg = static_cast<u8>(srcReg);
sig1 = 0x150;
sf = 0;
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVZ instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig0 == 0x1F) && (sig1 == 0x150);
}
@ -397,32 +349,27 @@ namespace skyline {
struct __attribute__((packed)) {
u8 destReg : 5; //!< 5-bit destination register
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
u16 sig1 : 10; //!< 10-bit signature (0x150)
u8 sf : 1; //!< 1-bit register type
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
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 {
public:
/**
* @brief Creates a LDR (immediate) instruction
* @param raw The raw value of the whole instruction
*/
inline constexpr Ldr(u32 raw) : raw(raw) {}
constexpr Ldr(u32 raw) : raw(raw) {}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid FCVTZU instruction
*/
inline constexpr bool Verify() {
constexpr bool Verify() {
return (sig0 == 0x0 && sig1 == 0x1CA && sig2 == 0x1);
}
@ -436,7 +383,7 @@ namespace skyline {
u8 sf : 1; //!< 1-bit register type
u8 sig2 : 1; //!< 1-bit signature (0x1)
};
u32 raw{}; //!< The raw value of the instruction
u32 raw{};
};
};
static_assert(sizeof(Ldr) == sizeof(u32));

View File

@ -1,13 +1,15 @@
// SPDX-License-Identifier: MPL-2.0
// 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 "loader/nro.h"
#include "loader/nso.h"
#include "loader/nca.h"
#include "loader/nsp.h"
#include "nce.h"
#include "nce/guest.h"
#include "os.h"
namespace skyline::kernel {

View File

@ -3,24 +3,20 @@
#pragma once
#include "common.h"
#include "kernel/memory.h"
#include "loader/loader.h"
#include "kernel/ipc.h"
#include "kernel/types/KProcess.h"
#include "kernel/types/KThread.h"
#include "services/serviceman.h"
#include "gpu.h"
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 {
public:
DeviceState state; //!< The state of the device
std::shared_ptr<type::KProcess> process; //!< The KProcess object for the emulator, representing the guest process
service::ServiceManager serviceManager; //!< This manages all of the service functions
MemoryManager memory; //!< The MemoryManager object for this process
DeviceState state;
std::shared_ptr<type::KProcess> process;
service::ServiceManager serviceManager;
MemoryManager memory;
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 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;
}
inline constexpr bool operator!=(const UserId &userId) {
constexpr bool operator!=(const UserId &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 {
private:
@ -44,38 +45,39 @@ namespace skyline {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
SERVICE_DECL(

View File

@ -7,7 +7,8 @@
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 {
public:

View File

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

View File

@ -8,7 +8,8 @@
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 {
public:
@ -18,12 +19,12 @@ namespace skyline::service::account {
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);
/**
* @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);

View File

@ -7,29 +7,34 @@
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 {
public:
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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -7,14 +7,16 @@
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 {
public:
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);

View File

@ -32,8 +32,8 @@ namespace skyline::service::am {
}
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 size_t LaunchParameterSize{0x88}; //!< This is the size of the launch parameter IStorage
constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters
constexpr size_t LaunchParameterSize{0x88}; //!< The size of the launch parameter IStorage
auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)};

View File

@ -8,7 +8,8 @@
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 {
private:
@ -18,27 +19,31 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -7,7 +7,8 @@
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 {
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) {}
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 size_t LaunchParameterSize{0x88}; //!< This is the size of the launch parameter IStorage
constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters
constexpr size_t LaunchParameterSize{0x88}; //!< The size of the launch parameter IStorage
auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)};

View File

@ -8,7 +8,8 @@
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 {
private:
@ -18,42 +19,50 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -7,7 +7,8 @@
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 {
private:
@ -18,17 +19,20 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);

View File

@ -18,34 +18,35 @@ namespace skyline::service::am {
class ICommonStateGetter : public BaseService {
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 {
ExitRequested = 0x4, //!< The applet has been requested to exit
FocusStateChange = 0xF, //!< There was a change in the focus state of the applet
ExecutionResumed = 0x10, //!< The execution of the applet has resumed
OperationModeChange = 0x1E, //!< There was a change in the operation mode
PerformanceModeChange = 0x1F, //!< There was a change in the performance mode
RequestToDisplay = 0x33, //!< This indicates that ApproveToDisplay should be used
ExitRequested = 0x4, //!< The applet has been requested to exit
FocusStateChange = 0xF, //!< There was a change in the focus state of the applet
ExecutionResumed = 0x10, //!< The execution of the applet has resumed
OperationModeChange = 0x1E, //!< There was a change in the operation mode
PerformanceModeChange = 0x1F, //!< There was a change in the performance mode
RequestToDisplay = 0x33, //!< Indicates that ApproveToDisplay should be used
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::queue<Message> messageQueue; //!< A queue of all the messages that the program is yet to consume
enum class FocusState : u8 {
InFocus = 1, //!< The application is in foreground
OutOfFocus = 2 //!< The application is in the background
InFocus = 1, //!< The application is in foreground
OutOfFocus = 2, //!< The application is in the background
} focusState{FocusState::InFocus};
enum class OperationMode : u8 {
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;
/**
* @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
*/
void QueueMessage(Message message);
@ -54,32 +55,38 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -7,7 +7,8 @@
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 {
public:

View File

@ -7,7 +7,8 @@
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 {
public:

View File

@ -14,12 +14,14 @@ namespace skyline::service::am {
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);
/**
* @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);

View File

@ -7,7 +7,8 @@
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 {
private:
@ -18,52 +19,62 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -7,19 +7,22 @@
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 {
public:
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);
/**
* @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);

View File

@ -7,14 +7,16 @@
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 {
public:
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);

View File

@ -7,7 +7,8 @@
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 {
public:

View File

@ -7,7 +7,8 @@
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 {
public:

View File

@ -7,7 +7,8 @@
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 {
public:

View File

@ -14,42 +14,50 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
};

View File

@ -7,7 +7,8 @@
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> {
private:
@ -19,14 +20,12 @@ namespace skyline::service::am {
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);
/**
* @brief This function 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
* @brief Writes an object to the storage
*/
template<typename ValueType>
inline void Push(const ValueType &value) {

View File

@ -13,7 +13,8 @@ namespace skyline::service::am {
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 {
private:
@ -23,17 +24,17 @@ namespace skyline::service::am {
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);
/**
* @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);
/**
* @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);

View File

@ -7,7 +7,8 @@
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 {
public:

View File

@ -7,14 +7,15 @@
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 {
public:
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);

View File

@ -11,18 +11,20 @@ namespace skyline::service::apm {
*/
class ISession : public BaseService {
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:
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);
/**
* @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);

View File

@ -7,7 +7,8 @@
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 {
private:
@ -17,27 +18,29 @@ namespace skyline::service::audio {
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -9,7 +9,8 @@
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 {
private:
@ -33,37 +34,44 @@ namespace skyline::service::audio {
~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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);

View File

@ -13,19 +13,22 @@ namespace skyline {
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 {
public:
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);
/**
* @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);

View File

@ -57,7 +57,8 @@ namespace skyline {
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 {
private:
@ -94,43 +95,47 @@ namespace skyline {
~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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @brief Updates the audio renderer state and appends new data to playback buffers
*/
* @brief Updates the audio renderer state and appends new data to playback buffers
*/
Result RequestUpdate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Start the audio stream from the renderer
*/
* @brief Start the audio stream from the renderer
*/
Result Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Stop the audio stream from the renderer
*/
* @brief Stop the audio stream from the renderer
*/
Result Stop(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Returns a handle to the sample release KEvent
*/
* @brief Returns a handle to the sample release KEvent
*/
Result QuerySystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
SERVICE_DECL(

View File

@ -6,16 +6,13 @@
#include <common.h>
namespace skyline::service::audio::IAudioRenderer {
/**
* @brief This enumerates various states an effect can be in
*/
enum class EffectState : u8 {
None = 0, //!< The effect isn't being used
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 {
u8 _unk0_;
@ -25,7 +22,7 @@ namespace skyline::service::audio::IAudioRenderer {
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 {
EffectState state;
@ -34,8 +31,8 @@ namespace skyline::service::audio::IAudioRenderer {
static_assert(sizeof(EffectOut) == 0x10);
/**
* @brief The Effect class stores the state of audio post processing effects
*/
* @brief The Effect class stores the state of audio post processing effects
*/
class Effect {
public:
EffectOut output{};

View File

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

View File

@ -31,8 +31,8 @@ namespace skyline {
}
/**
* @brief The RevisionInfo class is used to query the supported features of various audren revisions
*/
* @brief The RevisionInfo class is used to query the supported features of various audren revisions
*/
class RevisionInfo {
private:
u32 userRevision; //!< The current audren revision of the guest

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