mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 09:11:52 +01:00
Refactor Comments + Other Minor Fixes
This commit is contained in:
parent
429af1990a
commit
4070686897
@ -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)};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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},
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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 §ion, 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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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{};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {}
|
||||
|
||||
/**
|
||||
|
@ -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) {}
|
||||
};
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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) {};
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <asm/unistd.h>
|
||||
#include <nce.h>
|
||||
#include <os.h>
|
||||
#include "KProcess.h"
|
||||
#include "KTransferMemory.h"
|
||||
|
||||
namespace skyline::kernel::type {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <nce.h>
|
||||
#include <os.h>
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include <kernel/memory.h>
|
||||
#include "loader.h"
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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(
|
||||
|
@ -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:
|
||||
|
@ -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")};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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)};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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{};
|
||||
|
@ -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{};
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user