diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index eb8821ea..18efdd7a 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -2,16 +2,21 @@ \ No newline at end of file diff --git a/.idea/copyright/C__.xml b/.idea/copyright/Skyline_MPL_2_0.xml similarity index 76% rename from .idea/copyright/C__.xml rename to .idea/copyright/Skyline_MPL_2_0.xml index 43ff0203..6159e020 100644 --- a/.idea/copyright/C__.xml +++ b/.idea/copyright/Skyline_MPL_2_0.xml @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml index 05f0b553..0b06fe4b 100644 --- a/.idea/copyright/profiles_settings.xml +++ b/.idea/copyright/profiles_settings.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a37b624f..afb30f59 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,7 +46,8 @@ Use doxygen style comments for: * Enumerations - Use a `/**` block comment with a brief for the enum itself and a `//!<` single-line comment for all the individual items Notes: -* The DeviceState object can be skipped from function argument documentation as well as class members in the constructor +* The `DeviceState` object or other objects which are systematically used throughout multiple classes such as `ServiceManager` can be skipped from function argument documentation as well as class members in the constructor +* The `KSession`, `IpcRequest` and `IpcResponse` objects in IPC command function arguments and other such objects (Such as `IoctlData`) can be skipped from function argument documentation if used in those contexts, they will need to be documented if they're used as a class member or something on those lines * Any class members don't need to be redundantly documented in the constructor ### Spacing @@ -190,17 +191,23 @@ void ClassConstructor(const Class& class) : class(class) {} // Make a copy direc Use C++ range-based iterators for any C++ container iteration unless it can be performed better with functional programming (After C++20 when they are merged with the container). In addition, stick to using references/const references using them ### Usage of auto -Use `auto` unless a variable needs to be a specific type that isn't automatically deducible. +Use `auto` to assign a variable the type of the value it's being assigned to, but not where a different type is desired. So, as a rule of thumb always specify the type when setting something from a number rather than depending on `auto`. In addition, prefer not to use `auto` in cases where it's hard to determine the return type due to assigned value being complex. ```cpp -u16 a = 20; // Only if `a` is required to specifically be 16-bit, otherwise integers should be auto -Handle b = 0x10; // Handle is a specific type that won't be automatically assigned +u8 a = 20; // `20` won't be stored in a `u8` but rather in a `int` (i32, generally) if `auto` is used +auto b = std::make_shared(); // In this case `auto` is used to avoid typing out `std::shared_ptr` ``` +### Primitive Types +We generally use `in` and `un` where `n = {8, 16, 32, 64}` for our integer primitives in which `i` represents signed integers and `u` represents unsigned integers. In addition, we have some other types such as `KHandle` that are used to make certain operations more clear, use these depending on the context. + ### Constants If a variable is constant at compile time use `constexpr`, if it's only used in a local function then place it in the function but if it's used throughout a class then in the corresponding header add the variable to the `skyline::constant` namespace. If a constant is used throughout the codebase, add it to `common.h`. In addition, try to `constexpr` as much as possible including constructors and functions so that they may be initialized at compile-time and have lesser runtime overhead during usage and certain values can be pre-calculated in advance. +We should also mention that this isn't promoting the usage of `const`, it's use is actually discouraged out of references, in which case it is extremely encouraged. In addition, pointers are a general exception to this, using `const` with them isn't encouraged nor discouraged. Another exception are class functions, they can be made `const` if used from a `const` reference/pointer and don't + modify any members but do not do this preemptively. + ## Kotlin ### Naming rules * Enumerator: `PascalCase` **(1)** diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index b0ab51f9..64d45c81 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -34,7 +34,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( std::signal(SIGABRT, signalHandler); std::signal(SIGFPE, signalHandler); - setpriority(PRIO_PROCESS, static_cast(getpid()), skyline::constant::AndroidPriority.second); + setpriority(PRIO_PROCESS, static_cast(gettid()), -8); // Set the priority of this process to the highest value auto jvmManager = std::make_shared(env, instance); auto settings = std::make_shared(preferenceFd); @@ -45,7 +45,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( try { skyline::kernel::OS os(jvmManager, logger, settings); - const char *romUri = env->GetStringUTFChars(romUriJstring, nullptr); + auto romUri = env->GetStringUTFChars(romUriJstring, nullptr); logger->Info("Launching ROM {}", romUri); env->ReleaseStringUTFChars(romUriJstring, romUri); os.Execute(romFd, static_cast(romType)); diff --git a/app/src/main/cpp/skyline/audio.cpp b/app/src/main/cpp/skyline/audio.cpp index eb430617..afb502af 100644 --- a/app/src/main/cpp/skyline/audio.cpp +++ b/app/src/main/cpp/skyline/audio.cpp @@ -16,7 +16,7 @@ namespace skyline::audio { outputStream->requestStart(); } - std::shared_ptr Audio::OpenTrack(const int channelCount, const int sampleRate, const std::function &releaseCallback) { + std::shared_ptr Audio::OpenTrack(u8 channelCount, u32 sampleRate, const std::function &releaseCallback) { std::lock_guard trackGuard(trackLock); auto track = std::make_shared(channelCount, sampleRate, releaseCallback); @@ -33,8 +33,8 @@ namespace skyline::audio { } oboe::DataCallbackResult Audio::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) { - i16 *destBuffer = static_cast(audioData); - size_t streamSamples = static_cast(numFrames) * audioStream->getChannelCount(); + auto destBuffer = static_cast(audioData); + auto streamSamples = static_cast(numFrames) * audioStream->getChannelCount(); size_t writtenSamples = 0; std::unique_lock trackGuard(trackLock); diff --git a/app/src/main/cpp/skyline/audio.h b/app/src/main/cpp/skyline/audio.h index 7792e36d..47deb678 100644 --- a/app/src/main/cpp/skyline/audio.h +++ b/app/src/main/cpp/skyline/audio.h @@ -32,7 +32,7 @@ namespace skyline::audio { * @param releaseCallback The callback to call when a buffer has been released * @return A shared pointer to a new AudioTrack object */ - std::shared_ptr OpenTrack(const int channelCount, const int sampleRate, const std::function &releaseCallback); + std::shared_ptr OpenTrack(u8 channelCount, u32 sampleRate, const std::function &releaseCallback); /** * @brief Closes a track and frees its data diff --git a/app/src/main/cpp/skyline/audio/common.h b/app/src/main/cpp/skyline/audio/common.h index 60b8c8cf..228b2182 100644 --- a/app/src/main/cpp/skyline/audio/common.h +++ b/app/src/main/cpp/skyline/audio/common.h @@ -8,10 +8,10 @@ namespace skyline { namespace constant { - constexpr auto SampleRate = 48000; //!< The common sampling rate to use for audio output - constexpr auto ChannelCount = 2; //!< The common amount of channels to use for audio output + constexpr u16 SampleRate = 48000; //!< The common sampling rate to use for audio output + constexpr u8 ChannelCount = 2; //!< The common amount of channels to use for audio output + constexpr u16 MixBufferSize = 960; //!< The size of the mix buffer by default constexpr auto PcmFormat = oboe::AudioFormat::I16; //!< The common PCM data format to use for audio output - constexpr size_t MixBufferSize = 960; //!< The size of the mix buffer by default }; namespace audio { diff --git a/app/src/main/cpp/skyline/audio/resampler.cpp b/app/src/main/cpp/skyline/audio/resampler.cpp index 677edd40..c3ec7cdc 100644 --- a/app/src/main/cpp/skyline/audio/resampler.cpp +++ b/app/src/main/cpp/skyline/audio/resampler.cpp @@ -6,117 +6,122 @@ #include "resampler.h" namespace skyline::audio { + /** + * @brief This holds the coefficients of a single output frame + */ struct LutEntry { - i32 a; - i32 b; - i32 c; - i32 d; + i32 a; //!< The coefficient for the first index + i32 b; //!< The coefficient for the second index + i32 c; //!< The coefficient for the third index + i32 d; //!< The coefficient for the fourth index }; + // @formatter:off constexpr std::array 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}, - {5213, 19245, 8249, 84}, {5104, 19215, 8381, 92}, {4997, 19183, 8513, 101}, {4890, 19148, 8646, 109}, - {4785, 19112, 8780, 118}, {4681, 19073, 8914, 127}, {4579, 19031, 9048, 137}, {4477, 18988, 9183, 147}, - {4377, 18942, 9318, 157}, {4277, 18895, 9454, 168}, {4179, 18845, 9590, 179}, {4083, 18793, 9726, 190}, - {3987, 18738, 9863, 202}, {3893, 18682, 10000, 215}, {3800, 18624, 10137, 228}, {3709, 18563, 10274, 241}, - {3618, 18500, 10411, 255}, {3529, 18436, 10549, 270}, {3441, 18369, 10687, 285}, {3355, 18300, 10824, 300}, - {3269, 18230, 10962, 317}, {3186, 18157, 11100, 334}, {3103, 18082, 11238, 351}, {3022, 18006, 11375, 369}, - {2942, 17927, 11513, 388}, {2863, 17847, 11650, 408}, {2785, 17765, 11788, 428}, {2709, 17681, 11925, 449}, - {2635, 17595, 12062, 471}, {2561, 17507, 12198, 494}, {2489, 17418, 12334, 517}, {2418, 17327, 12470, 541}, - {2348, 17234, 12606, 566}, {2280, 17140, 12741, 592}, {2213, 17044, 12876, 619}, {2147, 16946, 13010, 647}, - {2083, 16846, 13144, 675}, {2020, 16745, 13277, 704}, {1958, 16643, 13409, 735}, {1897, 16539, 13541, 766}, - {1838, 16434, 13673, 798}, {1780, 16327, 13803, 832}, {1723, 16218, 13933, 866}, {1667, 16109, 14062, 901}, - {1613, 15998, 14191, 937}, {1560, 15885, 14318, 975}, {1508, 15772, 14445, 1013}, {1457, 15657, 14571, 1052}, - {1407, 15540, 14695, 1093}, {1359, 15423, 14819, 1134}, {1312, 15304, 14942, 1177}, {1266, 15185, 15064, 1221}, - {1221, 15064, 15185, 1266}, {1177, 14942, 15304, 1312}, {1134, 14819, 15423, 1359}, {1093, 14695, 15540, 1407}, - {1052, 14571, 15657, 1457}, {1013, 14445, 15772, 1508}, {975, 14318, 15885, 1560}, {937, 14191, 15998, 1613}, - {901, 14062, 16109, 1667}, {866, 13933, 16218, 1723}, {832, 13803, 16327, 1780}, {798, 13673, 16434, 1838}, - {766, 13541, 16539, 1897}, {735, 13409, 16643, 1958}, {704, 13277, 16745, 2020}, {675, 13144, 16846, 2083}, - {647, 13010, 16946, 2147}, {619, 12876, 17044, 2213}, {592, 12741, 17140, 2280}, {566, 12606, 17234, 2348}, - {541, 12470, 17327, 2418}, {517, 12334, 17418, 2489}, {494, 12198, 17507, 2561}, {471, 12062, 17595, 2635}, - {449, 11925, 17681, 2709}, {428, 11788, 17765, 2785}, {408, 11650, 17847, 2863}, {388, 11513, 17927, 2942}, - {369, 11375, 18006, 3022}, {351, 11238, 18082, 3103}, {334, 11100, 18157, 3186}, {317, 10962, 18230, 3269}, - {300, 10824, 18300, 3355}, {285, 10687, 18369, 3441}, {270, 10549, 18436, 3529}, {255, 10411, 18500, 3618}, - {241, 10274, 18563, 3709}, {228, 10137, 18624, 3800}, {215, 10000, 18682, 3893}, {202, 9863, 18738, 3987}, - {190, 9726, 18793, 4083}, {179, 9590, 18845, 4179}, {168, 9454, 18895, 4277}, {157, 9318, 18942, 4377}, - {147, 9183, 18988, 4477}, {137, 9048, 19031, 4579}, {127, 8914, 19073, 4681}, {118, 8780, 19112, 4785}, - {109, 8646, 19148, 4890}, {101, 8513, 19183, 4997}, {92, 8381, 19215, 5104}, {84, 8249, 19245, 5213}, - {77, 8118, 19273, 5323}, {69, 7987, 19298, 5434}, {62, 7857, 19321, 5546}, {55, 7728, 19342, 5659}, - {48, 7600, 19361, 5773}, {41, 7472, 19377, 5888}, {34, 7345, 19391, 6004}, {28, 7219, 19403, 6121}, - {22, 7093, 19412, 6239}, {15, 6968, 19419, 6359}, {9, 6845, 19424, 6479}, {3, 6722, 19426, 6600}}}; + {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}, + {5213, 19245, 8249, 84}, {5104, 19215, 8381, 92}, {4997, 19183, 8513, 101}, {4890, 19148, 8646, 109}, + {4785, 19112, 8780, 118}, {4681, 19073, 8914, 127}, {4579, 19031, 9048, 137}, {4477, 18988, 9183, 147}, + {4377, 18942, 9318, 157}, {4277, 18895, 9454, 168}, {4179, 18845, 9590, 179}, {4083, 18793, 9726, 190}, + {3987, 18738, 9863, 202}, {3893, 18682, 10000, 215}, {3800, 18624, 10137, 228}, {3709, 18563, 10274, 241}, + {3618, 18500, 10411, 255}, {3529, 18436, 10549, 270}, {3441, 18369, 10687, 285}, {3355, 18300, 10824, 300}, + {3269, 18230, 10962, 317}, {3186, 18157, 11100, 334}, {3103, 18082, 11238, 351}, {3022, 18006, 11375, 369}, + {2942, 17927, 11513, 388}, {2863, 17847, 11650, 408}, {2785, 17765, 11788, 428}, {2709, 17681, 11925, 449}, + {2635, 17595, 12062, 471}, {2561, 17507, 12198, 494}, {2489, 17418, 12334, 517}, {2418, 17327, 12470, 541}, + {2348, 17234, 12606, 566}, {2280, 17140, 12741, 592}, {2213, 17044, 12876, 619}, {2147, 16946, 13010, 647}, + {2083, 16846, 13144, 675}, {2020, 16745, 13277, 704}, {1958, 16643, 13409, 735}, {1897, 16539, 13541, 766}, + {1838, 16434, 13673, 798}, {1780, 16327, 13803, 832}, {1723, 16218, 13933, 866}, {1667, 16109, 14062, 901}, + {1613, 15998, 14191, 937}, {1560, 15885, 14318, 975}, {1508, 15772, 14445, 1013}, {1457, 15657, 14571, 1052}, + {1407, 15540, 14695, 1093}, {1359, 15423, 14819, 1134}, {1312, 15304, 14942, 1177}, {1266, 15185, 15064, 1221}, + {1221, 15064, 15185, 1266}, {1177, 14942, 15304, 1312}, {1134, 14819, 15423, 1359}, {1093, 14695, 15540, 1407}, + {1052, 14571, 15657, 1457}, {1013, 14445, 15772, 1508}, {975, 14318, 15885, 1560}, {937, 14191, 15998, 1613}, + {901, 14062, 16109, 1667}, {866, 13933, 16218, 1723}, {832, 13803, 16327, 1780}, {798, 13673, 16434, 1838}, + {766, 13541, 16539, 1897}, {735, 13409, 16643, 1958}, {704, 13277, 16745, 2020}, {675, 13144, 16846, 2083}, + {647, 13010, 16946, 2147}, {619, 12876, 17044, 2213}, {592, 12741, 17140, 2280}, {566, 12606, 17234, 2348}, + {541, 12470, 17327, 2418}, {517, 12334, 17418, 2489}, {494, 12198, 17507, 2561}, {471, 12062, 17595, 2635}, + {449, 11925, 17681, 2709}, {428, 11788, 17765, 2785}, {408, 11650, 17847, 2863}, {388, 11513, 17927, 2942}, + {369, 11375, 18006, 3022}, {351, 11238, 18082, 3103}, {334, 11100, 18157, 3186}, {317, 10962, 18230, 3269}, + {300, 10824, 18300, 3355}, {285, 10687, 18369, 3441}, {270, 10549, 18436, 3529}, {255, 10411, 18500, 3618}, + {241, 10274, 18563, 3709}, {228, 10137, 18624, 3800}, {215, 10000, 18682, 3893}, {202, 9863, 18738, 3987}, + {190, 9726, 18793, 4083}, {179, 9590, 18845, 4179}, {168, 9454, 18895, 4277}, {157, 9318, 18942, 4377}, + {147, 9183, 18988, 4477}, {137, 9048, 19031, 4579}, {127, 8914, 19073, 4681}, {118, 8780, 19112, 4785}, + {109, 8646, 19148, 4890}, {101, 8513, 19183, 4997}, {92, 8381, 19215, 5104}, {84, 8249, 19245, 5213}, + {77, 8118, 19273, 5323}, {69, 7987, 19298, 5434}, {62, 7857, 19321, 5546}, {55, 7728, 19342, 5659}, + {48, 7600, 19361, 5773}, {41, 7472, 19377, 5888}, {34, 7345, 19391, 6004}, {28, 7219, 19403, 6121}, + {22, 7093, 19412, 6239}, {15, 6968, 19419, 6359}, {9, 6845, 19424, 6479}, {3, 6722, 19426, 6600}}}; constexpr std::array CurveLut1 = {{ - {-68, 32639, 69, -5}, {-200, 32630, 212, -15}, {-328, 32613, 359, -26}, {-450, 32586, 512, -36}, - {-568, 32551, 669, -47}, {-680, 32507, 832, -58}, {-788, 32454, 1000, -69}, {-891, 32393, 1174, -80}, - {-990, 32323, 1352, -92}, {-1084, 32244, 1536, -103}, {-1173, 32157, 1724, -115}, {-1258, 32061, 1919, -128}, - {-1338, 31956, 2118, -140}, {-1414, 31844, 2322, -153}, {-1486, 31723, 2532, -167}, {-1554, 31593, 2747, -180}, - {-1617, 31456, 2967, -194}, {-1676, 31310, 3192, -209}, {-1732, 31157, 3422, -224}, {-1783, 30995, 3657, -240}, - {-1830, 30826, 3897, -256}, {-1874, 30649, 4143, -272}, {-1914, 30464, 4393, -289}, {-1951, 30272, 4648, -307}, - {-1984, 30072, 4908, -325}, {-2014, 29866, 5172, -343}, {-2040, 29652, 5442, -362}, {-2063, 29431, 5716, -382}, - {-2083, 29203, 5994, -403}, {-2100, 28968, 6277, -424}, {-2114, 28727, 6565, -445}, {-2125, 28480, 6857, -468}, - {-2133, 28226, 7153, -490}, {-2139, 27966, 7453, -514}, {-2142, 27700, 7758, -538}, {-2142, 27428, 8066, -563}, - {-2141, 27151, 8378, -588}, {-2136, 26867, 8694, -614}, {-2130, 26579, 9013, -641}, {-2121, 26285, 9336, -668}, - {-2111, 25987, 9663, -696}, {-2098, 25683, 9993, -724}, {-2084, 25375, 10326, -753}, {-2067, 25063, 10662, -783}, - {-2049, 24746, 11000, -813}, {-2030, 24425, 11342, -844}, {-2009, 24100, 11686, -875}, {-1986, 23771, 12033, -907}, - {-1962, 23438, 12382, -939}, {-1937, 23103, 12733, -972}, {-1911, 22764, 13086, -1005}, {-1883, 22422, 13441, -1039}, - {-1855, 22077, 13798, -1072}, {-1825, 21729, 14156, -1107}, {-1795, 21380, 14516, -1141}, {-1764, 21027, 14877, -1176}, - {-1732, 20673, 15239, -1211}, {-1700, 20317, 15602, -1246}, {-1667, 19959, 15965, -1282}, {-1633, 19600, 16329, -1317}, - {-1599, 19239, 16694, -1353}, {-1564, 18878, 17058, -1388}, {-1530, 18515, 17423, -1424}, {-1495, 18151, 17787, -1459}, - {-1459, 17787, 18151, -1495}, {-1424, 17423, 18515, -1530}, {-1388, 17058, 18878, -1564}, {-1353, 16694, 19239, -1599}, - {-1317, 16329, 19600, -1633}, {-1282, 15965, 19959, -1667}, {-1246, 15602, 20317, -1700}, {-1211, 15239, 20673, -1732}, - {-1176, 14877, 21027, -1764}, {-1141, 14516, 21380, -1795}, {-1107, 14156, 21729, -1825}, {-1072, 13798, 22077, -1855}, - {-1039, 13441, 22422, -1883}, {-1005, 13086, 22764, -1911}, {-972, 12733, 23103, -1937}, {-939, 12382, 23438, -1962}, - {-907, 12033, 23771, -1986}, {-875, 11686, 24100, -2009}, {-844, 11342, 24425, -2030}, {-813, 11000, 24746, -2049}, - {-783, 10662, 25063, -2067}, {-753, 10326, 25375, -2084}, {-724, 9993, 25683, -2098}, {-696, 9663, 25987, -2111}, - {-668, 9336, 26285, -2121}, {-641, 9013, 26579, -2130}, {-614, 8694, 26867, -2136}, {-588, 8378, 27151, -2141}, - {-563, 8066, 27428, -2142}, {-538, 7758, 27700, -2142}, {-514, 7453, 27966, -2139}, {-490, 7153, 28226, -2133}, - {-468, 6857, 28480, -2125}, {-445, 6565, 28727, -2114}, {-424, 6277, 28968, -2100}, {-403, 5994, 29203, -2083}, - {-382, 5716, 29431, -2063}, {-362, 5442, 29652, -2040}, {-343, 5172, 29866, -2014}, {-325, 4908, 30072, -1984}, - {-307, 4648, 30272, -1951}, {-289, 4393, 30464, -1914}, {-272, 4143, 30649, -1874}, {-256, 3897, 30826, -1830}, - {-240, 3657, 30995, -1783}, {-224, 3422, 31157, -1732}, {-209, 3192, 31310, -1676}, {-194, 2967, 31456, -1617}, - {-180, 2747, 31593, -1554}, {-167, 2532, 31723, -1486}, {-153, 2322, 31844, -1414}, {-140, 2118, 31956, -1338}, - {-128, 1919, 32061, -1258}, {-115, 1724, 32157, -1173}, {-103, 1536, 32244, -1084}, {-92, 1352, 32323, -990}, - {-80, 1174, 32393, -891}, {-69, 1000, 32454, -788}, {-58, 832, 32507, -680}, {-47, 669, 32551, -568}, - {-36, 512, 32586, -450}, {-26, 359, 32613, -328}, {-15, 212, 32630, -200}, {-5, 69, 32639, -68}}}; + {-68, 32639, 69, -5}, {-200, 32630, 212, -15}, {-328, 32613, 359, -26}, {-450, 32586, 512, -36}, + {-568, 32551, 669, -47}, {-680, 32507, 832, -58}, {-788, 32454, 1000, -69}, {-891, 32393, 1174, -80}, + {-990, 32323, 1352, -92}, {-1084, 32244, 1536, -103}, {-1173, 32157, 1724, -115}, {-1258, 32061, 1919, -128}, + {-1338, 31956, 2118, -140}, {-1414, 31844, 2322, -153}, {-1486, 31723, 2532, -167}, {-1554, 31593, 2747, -180}, + {-1617, 31456, 2967, -194}, {-1676, 31310, 3192, -209}, {-1732, 31157, 3422, -224}, {-1783, 30995, 3657, -240}, + {-1830, 30826, 3897, -256}, {-1874, 30649, 4143, -272}, {-1914, 30464, 4393, -289}, {-1951, 30272, 4648, -307}, + {-1984, 30072, 4908, -325}, {-2014, 29866, 5172, -343}, {-2040, 29652, 5442, -362}, {-2063, 29431, 5716, -382}, + {-2083, 29203, 5994, -403}, {-2100, 28968, 6277, -424}, {-2114, 28727, 6565, -445}, {-2125, 28480, 6857, -468}, + {-2133, 28226, 7153, -490}, {-2139, 27966, 7453, -514}, {-2142, 27700, 7758, -538}, {-2142, 27428, 8066, -563}, + {-2141, 27151, 8378, -588}, {-2136, 26867, 8694, -614}, {-2130, 26579, 9013, -641}, {-2121, 26285, 9336, -668}, + {-2111, 25987, 9663, -696}, {-2098, 25683, 9993, -724}, {-2084, 25375, 10326, -753}, {-2067, 25063, 10662, -783}, + {-2049, 24746, 11000, -813}, {-2030, 24425, 11342, -844}, {-2009, 24100, 11686, -875}, {-1986, 23771, 12033, -907}, + {-1962, 23438, 12382, -939}, {-1937, 23103, 12733, -972}, {-1911, 22764, 13086, -1005}, {-1883, 22422, 13441, -1039}, + {-1855, 22077, 13798, -1072}, {-1825, 21729, 14156, -1107}, {-1795, 21380, 14516, -1141}, {-1764, 21027, 14877, -1176}, + {-1732, 20673, 15239, -1211}, {-1700, 20317, 15602, -1246}, {-1667, 19959, 15965, -1282}, {-1633, 19600, 16329, -1317}, + {-1599, 19239, 16694, -1353}, {-1564, 18878, 17058, -1388}, {-1530, 18515, 17423, -1424}, {-1495, 18151, 17787, -1459}, + {-1459, 17787, 18151, -1495}, {-1424, 17423, 18515, -1530}, {-1388, 17058, 18878, -1564}, {-1353, 16694, 19239, -1599}, + {-1317, 16329, 19600, -1633}, {-1282, 15965, 19959, -1667}, {-1246, 15602, 20317, -1700}, {-1211, 15239, 20673, -1732}, + {-1176, 14877, 21027, -1764}, {-1141, 14516, 21380, -1795}, {-1107, 14156, 21729, -1825}, {-1072, 13798, 22077, -1855}, + {-1039, 13441, 22422, -1883}, {-1005, 13086, 22764, -1911}, {-972, 12733, 23103, -1937}, {-939, 12382, 23438, -1962}, + {-907, 12033, 23771, -1986}, {-875, 11686, 24100, -2009}, {-844, 11342, 24425, -2030}, {-813, 11000, 24746, -2049}, + {-783, 10662, 25063, -2067}, {-753, 10326, 25375, -2084}, {-724, 9993, 25683, -2098}, {-696, 9663, 25987, -2111}, + {-668, 9336, 26285, -2121}, {-641, 9013, 26579, -2130}, {-614, 8694, 26867, -2136}, {-588, 8378, 27151, -2141}, + {-563, 8066, 27428, -2142}, {-538, 7758, 27700, -2142}, {-514, 7453, 27966, -2139}, {-490, 7153, 28226, -2133}, + {-468, 6857, 28480, -2125}, {-445, 6565, 28727, -2114}, {-424, 6277, 28968, -2100}, {-403, 5994, 29203, -2083}, + {-382, 5716, 29431, -2063}, {-362, 5442, 29652, -2040}, {-343, 5172, 29866, -2014}, {-325, 4908, 30072, -1984}, + {-307, 4648, 30272, -1951}, {-289, 4393, 30464, -1914}, {-272, 4143, 30649, -1874}, {-256, 3897, 30826, -1830}, + {-240, 3657, 30995, -1783}, {-224, 3422, 31157, -1732}, {-209, 3192, 31310, -1676}, {-194, 2967, 31456, -1617}, + {-180, 2747, 31593, -1554}, {-167, 2532, 31723, -1486}, {-153, 2322, 31844, -1414}, {-140, 2118, 31956, -1338}, + {-128, 1919, 32061, -1258}, {-115, 1724, 32157, -1173}, {-103, 1536, 32244, -1084}, {-92, 1352, 32323, -990}, + {-80, 1174, 32393, -891}, {-69, 1000, 32454, -788}, {-58, 832, 32507, -680}, {-47, 669, 32551, -568}, + {-36, 512, 32586, -450}, {-26, 359, 32613, -328}, {-15, 212, 32630, -200}, {-5, 69, 32639, -68}}}; constexpr std::array CurveLut2 = {{ - {3195, 26287, 3329, -32}, {3064, 26281, 3467, -34}, {2936, 26270, 3608, -38}, {2811, 26253, 3751, -42}, - {2688, 26230, 3897, -46}, {2568, 26202, 4046, -50}, {2451, 26169, 4199, -54}, {2338, 26130, 4354, -58}, - {2227, 26085, 4512, -63}, {2120, 26035, 4673, -67}, {2015, 25980, 4837, -72}, {1912, 25919, 5004, -76}, - {1813, 25852, 5174, -81}, {1716, 25780, 5347, -87}, {1622, 25704, 5522, -92}, {1531, 25621, 5701, -98}, - {1442, 25533, 5882, -103}, {1357, 25440, 6066, -109}, {1274, 25342, 6253, -115}, {1193, 25239, 6442, -121}, - {1115, 25131, 6635, -127}, {1040, 25018, 6830, -133}, {967, 24899, 7027, -140}, {897, 24776, 7227, -146}, - {829, 24648, 7430, -153}, {764, 24516, 7635, -159}, {701, 24379, 7842, -166}, {641, 24237, 8052, -174}, - {583, 24091, 8264, -181}, {526, 23940, 8478, -187}, {472, 23785, 8695, -194}, {420, 23626, 8914, -202}, - {371, 23462, 9135, -209}, {324, 23295, 9358, -215}, {279, 23123, 9583, -222}, {236, 22948, 9809, -230}, - {194, 22769, 10038, -237}, {154, 22586, 10269, -243}, {117, 22399, 10501, -250}, {81, 22208, 10735, -258}, - {47, 22015, 10970, -265}, {15, 21818, 11206, -271}, {-16, 21618, 11444, -277}, {-44, 21415, 11684, -283}, - {-71, 21208, 11924, -290}, {-97, 20999, 12166, -296}, {-121, 20786, 12409, -302}, {-143, 20571, 12653, -306}, - {-163, 20354, 12898, -311}, {-183, 20134, 13143, -316}, {-201, 19911, 13389, -321}, {-218, 19686, 13635, -325}, - {-234, 19459, 13882, -328}, {-248, 19230, 14130, -332}, {-261, 18998, 14377, -335}, {-273, 18765, 14625, -337}, - {-284, 18531, 14873, -339}, {-294, 18295, 15121, -341}, {-302, 18057, 15369, -341}, {-310, 17817, 15617, -341}, - {-317, 17577, 15864, -340}, {-323, 17335, 16111, -340}, {-328, 17092, 16357, -338}, {-332, 16848, 16603, -336}, - {-336, 16603, 16848, -332}, {-338, 16357, 17092, -328}, {-340, 16111, 17335, -323}, {-340, 15864, 17577, -317}, - {-341, 15617, 17817, -310}, {-341, 15369, 18057, -302}, {-341, 15121, 18295, -294}, {-339, 14873, 18531, -284}, - {-337, 14625, 18765, -273}, {-335, 14377, 18998, -261}, {-332, 14130, 19230, -248}, {-328, 13882, 19459, -234}, - {-325, 13635, 19686, -218}, {-321, 13389, 19911, -201}, {-316, 13143, 20134, -183}, {-311, 12898, 20354, -163}, - {-306, 12653, 20571, -143}, {-302, 12409, 20786, -121}, {-296, 12166, 20999, -97}, {-290, 11924, 21208, -71}, - {-283, 11684, 21415, -44}, {-277, 11444, 21618, -16}, {-271, 11206, 21818, 15}, {-265, 10970, 22015, 47}, - {-258, 10735, 22208, 81}, {-250, 10501, 22399, 117}, {-243, 10269, 22586, 154}, {-237, 10038, 22769, 194}, - {-230, 9809, 22948, 236}, {-222, 9583, 23123, 279}, {-215, 9358, 23295, 324}, {-209, 9135, 23462, 371}, - {-202, 8914, 23626, 420}, {-194, 8695, 23785, 472}, {-187, 8478, 23940, 526}, {-181, 8264, 24091, 583}, - {-174, 8052, 24237, 641}, {-166, 7842, 24379, 701}, {-159, 7635, 24516, 764}, {-153, 7430, 24648, 829}, - {-146, 7227, 24776, 897}, {-140, 7027, 24899, 967}, {-133, 6830, 25018, 1040}, {-127, 6635, 25131, 1115}, - {-121, 6442, 25239, 1193}, {-115, 6253, 25342, 1274}, {-109, 6066, 25440, 1357}, {-103, 5882, 25533, 1442}, - {-98, 5701, 25621, 1531}, {-92, 5522, 25704, 1622}, {-87, 5347, 25780, 1716}, {-81, 5174, 25852, 1813}, - {-76, 5004, 25919, 1912}, {-72, 4837, 25980, 2015}, {-67, 4673, 26035, 2120}, {-63, 4512, 26085, 2227}, - {-58, 4354, 26130, 2338}, {-54, 4199, 26169, 2451}, {-50, 4046, 26202, 2568}, {-46, 3897, 26230, 2688}, - {-42, 3751, 26253, 2811}, {-38, 3608, 26270, 2936}, {-34, 3467, 26281, 3064}, {-32, 3329, 26287, 3195}}}; + {3195, 26287, 3329, -32}, {3064, 26281, 3467, -34}, {2936, 26270, 3608, -38}, {2811, 26253, 3751, -42}, + {2688, 26230, 3897, -46}, {2568, 26202, 4046, -50}, {2451, 26169, 4199, -54}, {2338, 26130, 4354, -58}, + {2227, 26085, 4512, -63}, {2120, 26035, 4673, -67}, {2015, 25980, 4837, -72}, {1912, 25919, 5004, -76}, + {1813, 25852, 5174, -81}, {1716, 25780, 5347, -87}, {1622, 25704, 5522, -92}, {1531, 25621, 5701, -98}, + {1442, 25533, 5882, -103}, {1357, 25440, 6066, -109}, {1274, 25342, 6253, -115}, {1193, 25239, 6442, -121}, + {1115, 25131, 6635, -127}, {1040, 25018, 6830, -133}, {967, 24899, 7027, -140}, {897, 24776, 7227, -146}, + {829, 24648, 7430, -153}, {764, 24516, 7635, -159}, {701, 24379, 7842, -166}, {641, 24237, 8052, -174}, + {583, 24091, 8264, -181}, {526, 23940, 8478, -187}, {472, 23785, 8695, -194}, {420, 23626, 8914, -202}, + {371, 23462, 9135, -209}, {324, 23295, 9358, -215}, {279, 23123, 9583, -222}, {236, 22948, 9809, -230}, + {194, 22769, 10038, -237}, {154, 22586, 10269, -243}, {117, 22399, 10501, -250}, {81, 22208, 10735, -258}, + {47, 22015, 10970, -265}, {15, 21818, 11206, -271}, {-16, 21618, 11444, -277}, {-44, 21415, 11684, -283}, + {-71, 21208, 11924, -290}, {-97, 20999, 12166, -296}, {-121, 20786, 12409, -302}, {-143, 20571, 12653, -306}, + {-163, 20354, 12898, -311}, {-183, 20134, 13143, -316}, {-201, 19911, 13389, -321}, {-218, 19686, 13635, -325}, + {-234, 19459, 13882, -328}, {-248, 19230, 14130, -332}, {-261, 18998, 14377, -335}, {-273, 18765, 14625, -337}, + {-284, 18531, 14873, -339}, {-294, 18295, 15121, -341}, {-302, 18057, 15369, -341}, {-310, 17817, 15617, -341}, + {-317, 17577, 15864, -340}, {-323, 17335, 16111, -340}, {-328, 17092, 16357, -338}, {-332, 16848, 16603, -336}, + {-336, 16603, 16848, -332}, {-338, 16357, 17092, -328}, {-340, 16111, 17335, -323}, {-340, 15864, 17577, -317}, + {-341, 15617, 17817, -310}, {-341, 15369, 18057, -302}, {-341, 15121, 18295, -294}, {-339, 14873, 18531, -284}, + {-337, 14625, 18765, -273}, {-335, 14377, 18998, -261}, {-332, 14130, 19230, -248}, {-328, 13882, 19459, -234}, + {-325, 13635, 19686, -218}, {-321, 13389, 19911, -201}, {-316, 13143, 20134, -183}, {-311, 12898, 20354, -163}, + {-306, 12653, 20571, -143}, {-302, 12409, 20786, -121}, {-296, 12166, 20999, -97}, {-290, 11924, 21208, -71}, + {-283, 11684, 21415, -44}, {-277, 11444, 21618, -16}, {-271, 11206, 21818, 15}, {-265, 10970, 22015, 47}, + {-258, 10735, 22208, 81}, {-250, 10501, 22399, 117}, {-243, 10269, 22586, 154}, {-237, 10038, 22769, 194}, + {-230, 9809, 22948, 236}, {-222, 9583, 23123, 279}, {-215, 9358, 23295, 324}, {-209, 9135, 23462, 371}, + {-202, 8914, 23626, 420}, {-194, 8695, 23785, 472}, {-187, 8478, 23940, 526}, {-181, 8264, 24091, 583}, + {-174, 8052, 24237, 641}, {-166, 7842, 24379, 701}, {-159, 7635, 24516, 764}, {-153, 7430, 24648, 829}, + {-146, 7227, 24776, 897}, {-140, 7027, 24899, 967}, {-133, 6830, 25018, 1040}, {-127, 6635, 25131, 1115}, + {-121, 6442, 25239, 1193}, {-115, 6253, 25342, 1274}, {-109, 6066, 25440, 1357}, {-103, 5882, 25533, 1442}, + {-98, 5701, 25621, 1531}, {-92, 5522, 25704, 1622}, {-87, 5347, 25780, 1716}, {-81, 5174, 25852, 1813}, + {-76, 5004, 25919, 1912}, {-72, 4837, 25980, 2015}, {-67, 4673, 26035, 2120}, {-63, 4512, 26085, 2227}, + {-58, 4354, 26130, 2338}, {-54, 4199, 26169, 2451}, {-50, 4046, 26202, 2568}, {-46, 3897, 26230, 2688}, + {-42, 3751, 26253, 2811}, {-38, 3608, 26270, 2936}, {-34, 3467, 26281, 3064}, {-32, 3329, 26287, 3195}}}; + // @formatter:on std::vector Resampler::ResampleBuffer(const std::vector &inputBuffer, double ratio, u8 channelCount) { - auto step = static_cast(ratio * 0x8000); + auto step = static_cast(ratio * 0x8000); auto outputSize = static_cast(inputBuffer.size() / ratio); std::vector outputBuffer(outputSize); @@ -129,7 +134,7 @@ namespace skyline::audio { return CurveLut2; }(); - for (auto outIndex = 0, inIndex = 0; outIndex < outputBuffer.size(); outIndex += channelCount) { + for (size_t outIndex = 0, inIndex = 0; outIndex < outputSize; outIndex += channelCount) { auto lutIndex = (fraction >> 8) << 2; for (u8 channel = 0; channel < channelCount; channel++) { diff --git a/app/src/main/cpp/skyline/audio/track.cpp b/app/src/main/cpp/skyline/audio/track.cpp index b5cdaaf4..e87968eb 100644 --- a/app/src/main/cpp/skyline/audio/track.cpp +++ b/app/src/main/cpp/skyline/audio/track.cpp @@ -4,7 +4,7 @@ #include "track.h" namespace skyline::audio { - AudioTrack::AudioTrack(const u8 channelCount, const u32 sampleRate, const std::function &releaseCallback) : channelCount(channelCount), sampleRate(sampleRate), releaseCallback(releaseCallback) { + AudioTrack::AudioTrack(u8 channelCount, u32 sampleRate, const std::function &releaseCallback) : channelCount(channelCount), sampleRate(sampleRate), releaseCallback(releaseCallback) { if (sampleRate != constant::SampleRate) throw exception("Unsupported audio sample rate: {}", sampleRate); @@ -33,7 +33,7 @@ namespace skyline::audio { std::vector AudioTrack::GetReleasedBuffers(u32 max) { std::vector bufferIds; - for (auto index = 0; index < max; index++) { + for (u32 index = 0; index < max; index++) { if (!identifiers.back().released) break; bufferIds.push_back(identifiers.back().tag); diff --git a/app/src/main/cpp/skyline/audio/track.h b/app/src/main/cpp/skyline/audio/track.h index 041ce45b..05616190 100644 --- a/app/src/main/cpp/skyline/audio/track.h +++ b/app/src/main/cpp/skyline/audio/track.h @@ -15,11 +15,11 @@ namespace skyline::audio { */ class AudioTrack { private: - const std::function releaseCallback; //!< Callback called when a buffer has been played + std::function releaseCallback; //!< Callback called when a buffer has been played std::deque identifiers; //!< Queue of all appended buffer identifiers - const u8 channelCount; //!< The amount channels present in the track - const u32 sampleRate; //!< The sample rate of the track + u8 channelCount; //!< The amount channels present in the track + u32 sampleRate; //!< The sample rate of the track public: CircularBuffer samples; //!< A vector of all appended audio samples @@ -33,7 +33,7 @@ namespace skyline::audio { * @param sampleRate The sample rate to use for the track * @param releaseCallback A callback to call when a buffer has been played */ - AudioTrack(const u8 channelCount, const u32 sampleRate, const std::function &releaseCallback); + AudioTrack(u8 channelCount, u32 sampleRate, const std::function &releaseCallback); /** * @brief Starts audio playback using data from appended buffers diff --git a/app/src/main/cpp/skyline/common.cpp b/app/src/main/cpp/skyline/common.cpp index a8f1243e..d14ff8b7 100644 --- a/app/src/main/cpp/skyline/common.cpp +++ b/app/src/main/cpp/skyline/common.cpp @@ -64,10 +64,10 @@ namespace skyline { flag.exchange(next); } - Settings::Settings(const int preferenceFd) { + Settings::Settings(int fd) { tinyxml2::XMLDocument pref; - if (pref.LoadFile(fdopen(preferenceFd, "r"))) + if (pref.LoadFile(fdopen(fd, "r"))) throw exception("TinyXML2 Error: " + std::string(pref.ErrorStr())); tinyxml2::XMLElement *elem = pref.LastChild()->FirstChild()->ToElement(); @@ -120,8 +120,8 @@ namespace skyline { logger->Info("Key: {}, Value: {}, Type: Bool", iter.first, GetBool(iter.first)); } - Logger::Logger(const int logFd, LogLevel configLevel) : configLevel(configLevel) { - logFile.__open(logFd, std::ios::app); + Logger::Logger(int fd, LogLevel configLevel) : configLevel(configLevel) { + logFile.__open(fd, std::ios::app); WriteHeader("Logging started"); } @@ -137,7 +137,7 @@ namespace skyline { logFile << "0|" << str << "\n"; } - void Logger::Write(const LogLevel level, std::string str) { + void Logger::Write(LogLevel level, std::string str) { syslog(levelSyslog[static_cast(level)], "%s", str.c_str()); for (auto &character : str) diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h index a497ab39..9792dba0 100644 --- a/app/src/main/cpp/skyline/common.h +++ b/app/src/main/cpp/skyline/common.h @@ -26,16 +26,15 @@ namespace skyline { namespace constant { // Memory - constexpr auto BaseAddress = 0x8000000; //!< The address space base - constexpr auto DefStackSize = 0x1E8480; //!< The default amount of stack: 2 MB - // Kernel - constexpr std::pair AndroidPriority = {19, -8}; //!< The range of priority for Android - constexpr std::pair SwitchPriority = {0, 63}; //!< The range of priority for the Nintendo Switch + constexpr u64 BaseAddress = 0x8000000; //!< The address space base + constexpr u64 DefStackSize = 0x1E8480; //!< The default amount of stack: 2 MB // Display - constexpr auto HandheldResolutionW = 1280; //!< The width component of the handheld resolution - constexpr auto HandheldResolutionH = 720; //!< The height component of the handheld resolution - constexpr auto DockedResolutionW = 1920; //!< The width component of the docked resolution - constexpr auto DockedResolutionH = 1080; //!< The height component of the docked resolution + constexpr u16 HandheldResolutionW = 1280; //!< The width component of the handheld resolution + constexpr u16 HandheldResolutionH = 720; //!< The height component of the handheld resolution + 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 // Status codes namespace status { constexpr u32 Success = 0x0; //!< "Success" @@ -74,13 +73,12 @@ namespace skyline { * @return The current time in nanoseconds */ inline u64 GetTimeNs() { - constexpr uint64_t nsInSecond = 1000000000; static u64 frequency{}; if (!frequency) asm("MRS %0, CNTFRQ_EL0" : "=r"(frequency)); u64 ticks; asm("MRS %0, CNTVCT_EL0" : "=r"(ticks)); - return ((ticks / frequency) * nsInSecond) + (((ticks % frequency) * nsInSecond + (frequency / 2)) / frequency); + return ((ticks / frequency) * constant::NsInSecond) + (((ticks % frequency) * constant::NsInSecond + (frequency / 2)) / frequency); } /** @@ -114,19 +112,28 @@ namespace skyline { } /** - * @param address The address to check for alignment - * @return If the address is page aligned + * @param value The value to check for alignment + * @param multiple The multiple to check alignment with + * @return If the address is aligned with the multiple */ - constexpr inline bool PageAligned(u64 address) { - return !(address & (PAGE_SIZE - 1U)); + constexpr inline bool IsAligned(u64 value, u64 multiple) { + return !(value & (multiple - 1U)); } /** - * @param address The address to check for alignment - * @return If the address is word aligned + * @param value The value to check for alignment + * @return If the value is page aligned */ - constexpr inline bool WordAligned(u64 address) { - return !(address & 3U); + constexpr inline bool PageAligned(u64 value) { + return IsAligned(value, PAGE_SIZE); + } + + /** + * @param value The value to check for alignment + * @return If the value is word aligned + */ + constexpr inline bool WordAligned(u64 value) { + return IsAligned(value, WORD_BIT / 8); } /** @@ -222,10 +229,10 @@ namespace skyline { LogLevel configLevel; //!< The level of logs to write /** - * @param logFd A FD to the log file + * @param fd A FD to the log file * @param configLevel The minimum level of logs to write */ - Logger(const int logFd, LogLevel configLevel); + Logger(int fd, LogLevel configLevel); /** * @brief Writes the termination message to the log file @@ -243,7 +250,7 @@ namespace skyline { * @param level The level of the log * @param str The value to be written */ - void Write(const LogLevel level, std::string str); + void Write(LogLevel level, std::string str); /** * @brief Write an error log with libfmt formatting @@ -305,9 +312,9 @@ namespace skyline { public: /** - * @param preferenceFd An FD to the preference XML file + * @param fd An FD to the preference XML file */ - Settings(const int preferenceFd); + Settings(int fd); /** * @brief Retrieves a particular setting as a string diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 89d0944e..1b423899 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -62,8 +62,8 @@ namespace skyline::gpu { if (frameTimestamp) { auto now = util::GetTimeNs(); - frametime = static_cast((now - frameTimestamp) / 10000); // frametime / 100 is the real ms value, this is to retain the first two decimals - fps = static_cast(1000000000 / (now - frameTimestamp)); + frametime = static_cast((now - frameTimestamp) / (constant::NsInSecond / 100)); // frametime / 100 is the real ms value, this is to retain the first two decimals + fps = static_cast(constant::NsInSecond / (now - frameTimestamp)); frameTimestamp = now; } else { diff --git a/app/src/main/cpp/skyline/gpu/format.h b/app/src/main/cpp/skyline/gpu/format.h new file mode 100644 index 00000000..666b64f0 --- /dev/null +++ b/app/src/main/cpp/skyline/gpu/format.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include "texture.h" + +namespace skyline::gpu::format { + using Format = gpu::texture::Format; + + constexpr Format RGBA8888Unorm{sizeof(u8) * 4, 1, 1, vk::Format::eR8G8B8A8Unorm}; //!< 8-bits per channel 4-channel pixels + constexpr Format RGB565Unorm{sizeof(u8) * 2, 1, 1, vk::Format::eR5G6B5UnormPack16}; //!< Red channel: 5-bit, Green channel: 6-bit, Blue channel: 5-bit +} diff --git a/app/src/main/cpp/skyline/gpu/texture.cpp b/app/src/main/cpp/skyline/gpu/texture.cpp index b88b1093..ddf0decf 100644 --- a/app/src/main/cpp/skyline/gpu/texture.cpp +++ b/app/src/main/cpp/skyline/gpu/texture.cpp @@ -20,10 +20,10 @@ namespace skyline::gpu { if (guest->tileMode == texture::TileMode::Block) { // Reference on Block-linear tiling: https://gist.github.com/PixelyIon/d9c35050af0ef5690566ca9f0965bc32 - constexpr auto sectorWidth = 16; // The width of a sector in bytes - constexpr auto sectorHeight = 2; // The height of a sector in lines - constexpr auto gobWidth = 64; // The width of a GOB in bytes - constexpr auto gobHeight = 8; // The height of a GOB in lines + constexpr u8 sectorWidth = 16; // The width of a sector in bytes + constexpr u8 sectorHeight = 2; // The height of a sector in lines + constexpr u8 gobWidth = 64; // The width of a GOB in bytes + constexpr u8 gobHeight = 8; // The height of a GOB in lines auto robHeight = gobHeight * guest->tileConfig.blockHeight; // The height of a single ROB (Row of Blocks) in lines auto surfaceHeightRobs = util::AlignUp(dimensions.height / format.blockHeight, robHeight) / robHeight; // The height of the surface in ROBs (Row Of Blocks) @@ -41,8 +41,8 @@ namespace skyline::gpu { auto outputGob = outputBlock; // We iterate through a GOB independently of the block for (u32 gobY = 0; gobY < guest->tileConfig.blockHeight; gobY++) { // Every Block contains `blockHeight` Y-axis GOBs for (u32 index = 0; index < sectorWidth * sectorHeight; index++) { // Every Y-axis GOB contains `sectorWidth * sectorHeight` sectors - const u32 xT = ((index << 3) & 0b10000) | ((index << 1) & 0b100000); // Morton-Swizzle on the X-axis - const u32 yT = ((index >> 1) & 0b110) | (index & 0b1); // Morton-Swizzle on the Y-axis + u32 xT = ((index << 3) & 0b10000) | ((index << 1) & 0b100000); // Morton-Swizzle on the X-axis + u32 yT = ((index >> 1) & 0b110) | (index & 0b1); // Morton-Swizzle on the Y-axis std::memcpy(outputGob + (yT * robWidthBytes) + xT, inputSector, sectorWidth); inputSector += sectorWidth; // `sectorWidth` bytes are of sequential image data } @@ -59,7 +59,7 @@ namespace skyline::gpu { auto inputLine = texture; // The address of the input line auto outputLine = output; // The address of the output line - for (auto line = 0; line < dimensions.height; line++) { + for (u32 line = 0; line < dimensions.height; line++) { std::memcpy(outputLine, inputLine, sizeLine); inputLine += sizeStride; outputLine += sizeLine; diff --git a/app/src/main/cpp/skyline/gpu/texture.h b/app/src/main/cpp/skyline/gpu/texture.h index ff3dfda8..a7bb9c0b 100644 --- a/app/src/main/cpp/skyline/gpu/texture.h +++ b/app/src/main/cpp/skyline/gpu/texture.h @@ -97,11 +97,6 @@ namespace skyline { } }; - namespace format { - constexpr Format RGBA8888Unorm{sizeof(u8) * 4, 1, 1, vk::Format::eR8G8B8A8Unorm}; //!< 8-bits per channel 4-channel pixels - constexpr Format RGB565Unorm{sizeof(u8) * 2, 1, 1, vk::Format::eR5G6B5UnormPack16}; //!< Red channel: 5-bit, Green channel: 6-bit, Blue channel: 5-bit - } - /** * @brief This describes the linearity of a texture. Refer to Chapter 20.1 of the Tegra X1 TRM for information. */ diff --git a/app/src/main/cpp/skyline/kernel/ipc.h b/app/src/main/cpp/skyline/kernel/ipc.h index d1d33bdd..34b8cfd9 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.h +++ b/app/src/main/cpp/skyline/kernel/ipc.h @@ -125,14 +125,14 @@ namespace skyline { /** * @return The address of the buffer */ - inline u64 Address() const { + inline u64 Address() { return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; } /** - * @return The buffer counter + * @return The counter index of the buffer */ - inline u16 Counter() const { + inline u16 Counter() { return static_cast(counter0_5) | static_cast(counter9_11) << 9; } }; @@ -161,14 +161,14 @@ namespace skyline { /** * @return The address of the buffer */ - inline u64 Address() const { + inline u64 Address() { return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; } /** * @return The size of the buffer */ - inline u64 Size() const { + inline u64 Size() { return static_cast(size0_31) | static_cast(size32_35) << 32; } }; diff --git a/app/src/main/cpp/skyline/kernel/memory.cpp b/app/src/main/cpp/skyline/kernel/memory.cpp index 77503a61..3fcc6618 100644 --- a/app/src/main/cpp/skyline/kernel/memory.cpp +++ b/app/src/main/cpp/skyline/kernel/memory.cpp @@ -92,7 +92,7 @@ namespace skyline::kernel { chunk->size = size; } - void MemoryManager::InsertBlock(ChunkDescriptor *chunk, const BlockDescriptor block) { + void MemoryManager::InsertBlock(ChunkDescriptor *chunk, BlockDescriptor block) { if (chunk->address + chunk->size < block.address + block.size) throw exception("InsertBlock: Inserting block past chunk end is not allowed"); @@ -118,7 +118,7 @@ namespace skyline::kernel { throw exception("InsertBlock: Block offset not present within current block list"); } - void MemoryManager::InitializeRegions(u64 address, u64 size, const memory::AddressSpaceType type) { + void MemoryManager::InitializeRegions(u64 address, u64 size, memory::AddressSpaceType type) { switch (type) { case memory::AddressSpaceType::AddressSpace32Bit: throw exception("32-bit address spaces are not supported"); diff --git a/app/src/main/cpp/skyline/kernel/memory.h b/app/src/main/cpp/skyline/kernel/memory.h index 84ca825d..229fd087 100644 --- a/app/src/main/cpp/skyline/kernel/memory.h +++ b/app/src/main/cpp/skyline/kernel/memory.h @@ -16,29 +16,29 @@ namespace skyline { /** * @brief This constructor initializes all permissions to false */ - Permission() : r(), w(), x() {}; + constexpr Permission() : r(), w(), x() {} /** * @param read If memory has read permission * @param write If memory has write permission * @param execute If memory has execute permission */ - Permission(bool read, bool write, bool execute) : r(read), w(write), x(execute) {}; + constexpr Permission(bool read, bool write, bool execute) : r(read), w(write), x(execute) {} /** * @brief Equality operator between two Permission objects */ - inline bool operator==(const Permission &rhs) const { return (this->r == rhs.r && this->w == rhs.w && this->x == rhs.x); }; + inline bool operator==(const Permission &rhs) const { return (this->r == rhs.r && this->w == rhs.w && this->x == rhs.x); } /** * @brief Inequality operator between two Permission objects */ - inline bool operator!=(const Permission &rhs) const { return !operator==(rhs); }; + inline bool operator!=(const Permission &rhs) const { return !operator==(rhs); } /** * @return The value of the permission struct in Linux format */ - int Get() const { + constexpr int Get() const { int perm = 0; if (r) perm |= PROT_READ; @@ -47,7 +47,7 @@ namespace skyline { if (x) perm |= PROT_EXEC; return perm; - }; + } bool r; //!< The permission to read bool w; //!< The permission to write @@ -114,9 +114,9 @@ namespace skyline { * @brief This structure is used to hold the state of a certain block of memory (https://switchbrew.org/wiki/SVC#MemoryState) */ union MemoryState { - constexpr MemoryState(const u32 value) : value(value) {}; + constexpr MemoryState(const u32 value) : value(value) {} - constexpr MemoryState() : value(0) {}; + constexpr MemoryState() : value(0) {} struct { MemoryType type; //!< The MemoryType of this memory block @@ -304,9 +304,9 @@ namespace skyline { /** * @brief Insert a block into a chunk * @param chunk The chunk to insert the block into - * @param block The block to insert + * @param block The block to insert into the chunk */ - static void InsertBlock(ChunkDescriptor *chunk, const BlockDescriptor block); + static void InsertBlock(ChunkDescriptor *chunk, BlockDescriptor block); /** * @brief This initializes all of the regions in the address space @@ -314,7 +314,7 @@ namespace skyline { * @param size The size of the code region * @param type The type of the address space */ - void InitializeRegions(u64 address, u64 size, const memory::AddressSpaceType type); + void InitializeRegions(u64 address, u64 size, memory::AddressSpaceType type); public: friend class type::KPrivateMemory; diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index 24b5e5cf..1e9cfae5 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -6,10 +6,9 @@ namespace skyline::kernel::svc { void SetHeapSize(DeviceState &state) { - constexpr auto heapSizeAlign = 0x200000; // The heap size has to be a multiple of this value auto size = state.ctx->registers.w1; - if (size % heapSizeAlign != 0) { + if (!util::IsAligned(size, 0x200000)) { state.ctx->registers.w0 = constant::status::InvSize; state.ctx->registers.x1 = 0; @@ -219,19 +218,19 @@ namespace skyline::kernel::svc { } void CreateThread(DeviceState &state) { - u64 entryAddress = state.ctx->registers.x1; - u64 entryArgument = state.ctx->registers.x2; - u64 stackTop = state.ctx->registers.x3; - u8 priority = static_cast(state.ctx->registers.w4); + auto entryAddress = state.ctx->registers.x1; + auto entryArgument = state.ctx->registers.x2; + auto stackTop = state.ctx->registers.x3; + auto priority = static_cast(state.ctx->registers.w4); - if ((priority < constant::SwitchPriority.first) || (priority > constant::SwitchPriority.second)) { + if (!state.thread->switchPriority.Valid(priority)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcCreateThread: 'priority' invalid: {}", priority); return; } auto thread = state.process->CreateThread(entryAddress, entryArgument, stackTop, priority); - state.logger->Debug("svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, PID: {})", thread->handle, entryAddress, entryArgument, stackTop, priority, thread->tid); + state.logger->Debug("svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, TID: {})", thread->handle, entryAddress, entryArgument, stackTop, priority, thread->tid); state.ctx->registers.w1 = thread->handle; state.ctx->registers.w0 = constant::status::Success; @@ -305,7 +304,7 @@ namespace skyline::kernel::svc { void MapSharedMemory(DeviceState &state) { try { auto object = state.process->GetHandle(state.ctx->registers.w0); - u64 address = state.ctx->registers.x1; + auto address = state.ctx->registers.x1; if (!util::PageAligned(address)) { state.ctx->registers.w0 = constant::status::InvAddress; @@ -320,8 +319,7 @@ namespace skyline::kernel::svc { return; } - u32 perm = state.ctx->registers.w3; - memory::Permission permission = *reinterpret_cast(&perm); + memory::Permission permission = *reinterpret_cast(&state.ctx->registers.w3); if ((permission.w && !permission.r) || (permission.x && !permission.r)) { state.logger->Warn("svcMapSharedMemory: 'permission' invalid: {}{}{}", permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-"); state.ctx->registers.w0 = constant::status::InvPermission; @@ -340,22 +338,21 @@ namespace skyline::kernel::svc { } void CreateTransferMemory(DeviceState &state) { - u64 address = state.ctx->registers.x1; + auto address = state.ctx->registers.x1; if (!util::PageAligned(address)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcCreateTransferMemory: 'address' not page aligned: 0x{:X}", address); return; } - u64 size = state.ctx->registers.x2; + auto size = state.ctx->registers.x2; if (!util::PageAligned(size)) { state.ctx->registers.w0 = constant::status::InvSize; state.logger->Warn("svcCreateTransferMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; } - u32 perm = state.ctx->registers.w3; - memory::Permission permission = *reinterpret_cast(&perm); + memory::Permission permission = *reinterpret_cast(&state.ctx->registers.w3); if ((permission.w && !permission.r) || (permission.x && !permission.r)) { state.logger->Warn("svcCreateTransferMemory: 'permission' invalid: {}{}{}", permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-"); state.ctx->registers.w0 = constant::status::InvPermission; @@ -387,11 +384,11 @@ namespace skyline::kernel::svc { try { auto &object = state.process->handles.at(handle); switch (object->objectType) { - case (type::KType::KEvent): + case type::KType::KEvent: std::static_pointer_cast(object)->ResetSignal(); break; - case (type::KType::KProcess): + case type::KType::KProcess: std::static_pointer_cast(object)->ResetSignal(); break; diff --git a/app/src/main/cpp/skyline/kernel/types/KMemory.h b/app/src/main/cpp/skyline/kernel/types/KMemory.h index 34f4dd7a..f300d66f 100644 --- a/app/src/main/cpp/skyline/kernel/types/KMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KMemory.h @@ -27,7 +27,7 @@ namespace skyline::kernel::type { * @param size The size of the partition to change the permissions of * @param permission The new permissions to be set for the memory */ - virtual void UpdatePermission(const u64 address, const u64 size, memory::Permission permission) = 0; + virtual void UpdatePermission(u64 address, u64 size, memory::Permission permission) = 0; /** * @brief Updates the permissions of a chunk of mapped memory diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp index 042eafe0..8ab73650 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp @@ -9,7 +9,7 @@ #include "KProcess.h" namespace skyline::kernel::type { - KPrivateMemory::KPrivateMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, const memory::MemoryState memState) : size(size), KMemory(state, KType::KPrivateMemory) { + KPrivateMemory::KPrivateMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, memory::MemoryState memState) : size(size), KMemory(state, KType::KPrivateMemory) { if (address && !util::PageAligned(address)) throw exception("KPrivateMemory was created with non-page-aligned address: 0x{:X}", address); @@ -113,7 +113,7 @@ namespace skyline::kernel::type { size = nSize; } - void KPrivateMemory::UpdatePermission(const u64 address, const u64 size, memory::Permission permission) { + void KPrivateMemory::UpdatePermission(u64 address, u64 size, memory::Permission permission) { Registers fregs{ .x0 = address, .x1 = size, diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h index 62457a21..c5f2a27c 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h @@ -24,7 +24,7 @@ namespace skyline::kernel::type { * @param permission The permissions for the allocated memory * @param memState The MemoryState of the chunk of memory */ - KPrivateMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, const memory::MemoryState memState); + KPrivateMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, memory::MemoryState memState); /** * @brief Remap a chunk of memory as to change the size occupied by it @@ -39,7 +39,7 @@ namespace skyline::kernel::type { * @param size The size of the partition to change the permissions of * @param permission The new permissions to be set for the memory */ - virtual void UpdatePermission(const u64 address, const u64 size, memory::Permission permission); + virtual void UpdatePermission(u64 address, u64 size, memory::Permission permission); /** * @brief Updates the permissions of a chunk of mapped memory diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp index d049afc6..c78f04c6 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp @@ -78,7 +78,7 @@ namespace skyline::kernel::type { status = Status::Exiting; } - std::shared_ptr KProcess::CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, u8 priority) { + std::shared_ptr KProcess::CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, i8 priority) { auto size = (sizeof(ThreadContext) + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); auto tlsMem = std::make_shared(state, 0, size, memory::Permission{true, true, false}, memory::states::Reserved); @@ -102,12 +102,12 @@ namespace skyline::kernel::type { return process; } - u64 KProcess::GetHostAddress(u64 address) const { + u64 KProcess::GetHostAddress(u64 address) { auto chunk = state.os->memory.GetChunk(address); return (chunk && chunk->host) ? chunk->host + (address - chunk->address) : 0; } - void KProcess::ReadMemory(void *destination, const u64 offset, const size_t size, const bool forceGuest) const { + void KProcess::ReadMemory(void *destination, u64 offset, size_t size, bool forceGuest) { if (!forceGuest) { auto source = GetHostAddress(offset); @@ -131,7 +131,7 @@ namespace skyline::kernel::type { pread64(memFd, destination, size, offset); } - void KProcess::WriteMemory(const void *source, const u64 offset, const size_t size, const bool forceGuest) const { + void KProcess::WriteMemory(const void *source, u64 offset, size_t size, bool forceGuest) { if (!forceGuest) { auto destination = GetHostAddress(offset); @@ -155,7 +155,7 @@ namespace skyline::kernel::type { pwrite64(memFd, source, size, offset); } - void KProcess::CopyMemory(u64 source, u64 destination, size_t size) const { + void KProcess::CopyMemory(u64 source, u64 destination, size_t size) { auto sourceHost = GetHostAddress(source); auto destinationHost = GetHostAddress(destination); diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.h b/app/src/main/cpp/skyline/kernel/types/KProcess.h index c047012b..92fd1451 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.h +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.h @@ -146,14 +146,14 @@ namespace skyline { * @param priority The priority of the thread * @return An instance of KThread class for the corresponding thread */ - std::shared_ptr CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, u8 priority); + std::shared_ptr CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, i8 priority); /** * @brief This returns the host address for a specific address in guest memory * @param address The corresponding guest address * @return The corresponding host address */ - u64 GetHostAddress(const u64 address) const; + u64 GetHostAddress(u64 address); /** * @tparam Type The type of the pointer to return @@ -162,7 +162,7 @@ namespace skyline { * @note This can return a nullptr if the address is invalid */ template - inline Type *GetPointer(const u64 address) const { + inline Type *GetPointer(u64 address) { return reinterpret_cast(GetHostAddress(address)); } @@ -173,7 +173,7 @@ namespace skyline { * @return A reference to object with type T */ template - inline Type &GetReference(u64 address) const { + inline Type &GetReference(u64 address) { auto source = GetPointer(address); if (source) return *source; @@ -188,7 +188,7 @@ namespace skyline { * @return A copy of the object from guest memory */ template - inline Type GetObject(u64 address) const { + inline Type GetObject(u64 address) { auto source = GetPointer(address); if (source) { return *source; @@ -205,7 +205,7 @@ namespace skyline { * @param maxSize The maximum size of the string * @return A copy of a string in guest memory */ - inline std::string GetString(u64 address, const size_t maxSize) const { + inline std::string GetString(u64 address, size_t maxSize) { auto source = GetPointer(address); if (source) return std::string(source, maxSize); @@ -221,7 +221,7 @@ namespace skyline { * @param address The address of the object */ template - inline void WriteMemory(Type &item, u64 address) const { + inline void WriteMemory(Type &item, u64 address) { auto destination = GetPointer(address); if (destination) { *destination = item; @@ -237,7 +237,7 @@ namespace skyline { * @param address The address of the object */ template - inline void WriteMemory(const Type &item, u64 address) const { + inline void WriteMemory(const Type &item, u64 address) { auto destination = GetPointer(address); if (destination) { *destination = item; @@ -253,7 +253,7 @@ namespace skyline { * @param size The amount of memory to be read * @param forceGuest This flag forces the write to be performed in guest address space */ - void ReadMemory(void *destination, const u64 offset, const size_t size, const bool forceGuest = false) const; + void ReadMemory(void *destination, u64 offset, size_t size, bool forceGuest = false); /** * @brief Write to the guest's memory @@ -262,7 +262,7 @@ namespace skyline { * @param size The amount of memory to be written * @param forceGuest This flag forces the write to be performed in guest address space */ - void WriteMemory(const void *source, const u64 offset, const size_t size, const bool forceGuest = false) const; + void WriteMemory(const void *source, u64 offset, size_t size, bool forceGuest = false); /** * @brief Copy one chunk to another in the guest's memory @@ -270,7 +270,7 @@ namespace skyline { * @param destination The address to write the read data to * @param size The amount of memory to be copied */ - void CopyMemory(const u64 source, const u64 destination, const size_t size) const; + void CopyMemory(u64 source, u64 destination, size_t size); /** * @brief Creates a new handle to a KObject and adds it to the process handle_table diff --git a/app/src/main/cpp/skyline/kernel/types/KSession.h b/app/src/main/cpp/skyline/kernel/types/KSession.h index d66200d5..3d5fc3ab 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSession.h +++ b/app/src/main/cpp/skyline/kernel/types/KSession.h @@ -13,10 +13,10 @@ namespace skyline::kernel::type { */ class KSession : public KSyncObject { public: - const std::shared_ptr serviceObject; //!< A shared pointer to the service class + std::shared_ptr serviceObject; //!< A shared pointer to the service class std::unordered_map> domainTable; //!< This maps from a virtual handle to it's service KHandle handleIndex{0x1}; //!< The currently allocated handle index - const service::Service serviceType; //!< The type of the service + service::Service serviceType; //!< The type of the service 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 diff --git a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp index d5d47296..75601c69 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp @@ -9,7 +9,7 @@ #include "KProcess.h" namespace skyline::kernel::type { - KSharedMemory::KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState, int mmapFlags) : initialState(memState), KMemory(state, KType::KSharedMemory) { + KSharedMemory::KSharedMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, memory::MemoryState memState, int mmapFlags) : initialState(memState), KMemory(state, KType::KSharedMemory) { if (address && !util::PageAligned(address)) throw exception("KSharedMemory was created with non-page-aligned address: 0x{:X}", address); diff --git a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h index 0b3b10ec..da325d56 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h @@ -38,7 +38,7 @@ namespace skyline::kernel::type { * @param memState The MemoryState of the chunk of memory * @param mmapFlags Additional flags to pass to mmap */ - KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState = memory::states::SharedMemory, int mmapFlags = 0); + KSharedMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::SharedMemory, int mmapFlags = 0); /** * @brief Maps the shared memory in the guest @@ -47,7 +47,7 @@ namespace skyline::kernel::type { * @param permission The permission of the kernel process * @return The address of the allocation */ - u64 Map(const u64 address, const u64 size, memory::Permission permission); + u64 Map(u64 address, u64 size, memory::Permission permission); /** * @brief Resize a chunk of memory as to change the size occupied by it diff --git a/app/src/main/cpp/skyline/kernel/types/KThread.cpp b/app/src/main/cpp/skyline/kernel/types/KThread.cpp index 547d2039..39b8e944 100644 --- a/app/src/main/cpp/skyline/kernel/types/KThread.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KThread.cpp @@ -7,8 +7,8 @@ #include "KProcess.h" namespace skyline::kernel::type { - KThread::KThread(const DeviceState &state, KHandle handle, pid_t selfTid, u64 entryPoint, u64 entryArg, u64 stackTop, u64 tls, u8 priority, KProcess *parent, std::shared_ptr &tlsMemory) - : handle(handle), tid(selfTid), entryPoint(entryPoint), entryArg(entryArg), stackTop(stackTop), tls(tls), priority(priority), parent(parent), ctxMemory(tlsMemory), KSyncObject(state, KType::KThread) { + KThread::KThread(const DeviceState &state, KHandle handle, pid_t selfTid, u64 entryPoint, u64 entryArg, u64 stackTop, u64 tls, i8 priority, KProcess *parent, const std::shared_ptr &tlsMemory) : handle(handle), tid(selfTid), entryPoint(entryPoint), entryArg(entryArg), stackTop(stackTop), tls(tls), priority(priority), parent(parent), ctxMemory(tlsMemory), KSyncObject(state, + KType::KThread) { UpdatePriority(priority); } @@ -30,16 +30,16 @@ namespace skyline::kernel::type { if (status != Status::Dead) { status = Status::Dead; Signal(); - tgkill(parent->pid, tid, SIGKILL); + + tgkill(parent->pid, tid, SIGTERM); } } - void KThread::UpdatePriority(u8 priority) { + void KThread::UpdatePriority(i8 priority) { this->priority = priority; - auto linuxPriority = - static_cast(constant::AndroidPriority.first + ((static_cast(constant::AndroidPriority.second - constant::AndroidPriority.first) / static_cast(constant::SwitchPriority.second - constant::SwitchPriority.first)) * (static_cast(priority) - constant::SwitchPriority.first))); // Resize range SwitchPriority (Nintendo Priority) to AndroidPriority (Android Priority) + auto priorityValue = androidPriority.Rescale(switchPriority, priority); - if (setpriority(PRIO_PROCESS, static_cast(tid), linuxPriority) == -1) - throw exception("Couldn't set process priority to {} for PID: {}", linuxPriority, tid); + if (setpriority(PRIO_PROCESS, static_cast(tid), priorityValue) == -1) + throw exception("Couldn't set process priority to {} for PID: {}", priorityValue, tid); } } diff --git a/app/src/main/cpp/skyline/kernel/types/KThread.h b/app/src/main/cpp/skyline/kernel/types/KThread.h index 42ca2e9d..7be65d58 100644 --- a/app/src/main/cpp/skyline/kernel/types/KThread.h +++ b/app/src/main/cpp/skyline/kernel/types/KThread.h @@ -16,6 +16,31 @@ namespace skyline::kernel::type { u64 entryPoint; //!< The address to start execution at u64 entryArg; //!< An argument to pass to the process on entry + /** + * @brief This holds a range of priorities for a corresponding system + */ + struct Priority { + i8 low; //!< The low range of priority + i8 high; //!< The high range of priority + + /** + * @param priority The priority range of the value + * @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) { + return static_cast(priority.low + ((static_cast(priority.high - priority.low) / static_cast(priority.low - priority.high)) * (static_cast(value) - priority.low))); + } + + /** + * @param value The priority value to check for validity + * @return If the supplied priority value is valid + */ + constexpr inline bool Valid(i8 value) { + return (value >= low) && (value <= high); + } + }; + public: enum class Status { Created, //!< The thread has been created but has not been started yet @@ -28,7 +53,10 @@ namespace skyline::kernel::type { pid_t tid; //!< The TID 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 - u8 priority; //!< The priority of a thread in Nintendo format + i8 priority; //!< The priority of a thread in Nintendo format + + Priority androidPriority{19, -8}; //!< The range of priorities for Android + Priority switchPriority{0, 63}; //!< The range of priorities for the Nintendo Switch /** * @param state The state of the device @@ -42,7 +70,7 @@ namespace skyline::kernel::type { * @param parent The parent process of this thread * @param tlsMemory The KSharedMemory object for TLS memory allocated by the guest process */ - KThread(const DeviceState &state, KHandle handle, pid_t selfTid, u64 entryPoint, u64 entryArg, u64 stackTop, u64 tls, u8 priority, KProcess *parent, std::shared_ptr &tlsMemory); + KThread(const DeviceState &state, KHandle handle, pid_t selfTid, u64 entryPoint, u64 entryArg, u64 stackTop, u64 tls, i8 priority, KProcess *parent, const std::shared_ptr &tlsMemory); /** * @brief Kills the thread and deallocates the memory allocated for stack. @@ -64,6 +92,6 @@ namespace skyline::kernel::type { * @details Set the priority of the current thread to `priority` using setpriority [https://linux.die.net/man/3/setpriority]. We rescale the priority from Nintendo scale to that of Android. * @param priority The priority of the thread in Nintendo format */ - void UpdatePriority(u8 priority); + void UpdatePriority(i8 priority); }; } diff --git a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp index 5eb542b4..aabddb6d 100644 --- a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp @@ -7,7 +7,7 @@ #include "KTransferMemory.h" namespace skyline::kernel::type { - KTransferMemory::KTransferMemory(const DeviceState &state, bool host, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState) : host(host), size(size), KMemory(state, KType::KTransferMemory) { + KTransferMemory::KTransferMemory(const DeviceState &state, bool host, u64 address, size_t size, memory::Permission permission, memory::MemoryState memState) : host(host), size(size), KMemory(state, KType::KTransferMemory) { if (address && !util::PageAligned(address)) throw exception("KTransferMemory was created with non-page-aligned address: 0x{:X}", address); @@ -172,7 +172,7 @@ namespace skyline::kernel::type { } } - void KTransferMemory::UpdatePermission(const u64 address, const u64 size, memory::Permission permission) { + void KTransferMemory::UpdatePermission(u64 address, u64 size, memory::Permission permission) { BlockDescriptor block{ .address = address, .size = size, diff --git a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h index 685c85f2..dfdc0e11 100644 --- a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h @@ -26,7 +26,7 @@ namespace skyline::kernel::type { * @param type The type of the memory * @param memState The MemoryState of the chunk of memory */ - KTransferMemory(const DeviceState &state, bool host, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory); + KTransferMemory(const DeviceState &state, bool host, u64 address, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory); /** * @brief Transfers this piece of memory to another process @@ -50,7 +50,7 @@ namespace skyline::kernel::type { * @param size The size of the partition to change the permissions of * @param permission The new permissions to be set for the memory */ - virtual void UpdatePermission(const u64 address, const u64 size, memory::Permission permission); + virtual void UpdatePermission(u64 address, u64 size, memory::Permission permission); /** * @brief Updates the permissions of a chunk of mapped memory diff --git a/app/src/main/cpp/skyline/loader/loader.h b/app/src/main/cpp/skyline/loader/loader.h index ccf43aca..942803d9 100644 --- a/app/src/main/cpp/skyline/loader/loader.h +++ b/app/src/main/cpp/skyline/loader/loader.h @@ -10,7 +10,7 @@ namespace skyline::loader { class Loader { protected: - const int romFd; //!< An FD to the ROM file + int fd; //!< An FD to the ROM file /** * @brief Read the file at a particular offset @@ -21,14 +21,14 @@ namespace skyline::loader { */ template inline void ReadOffset(T *output, u64 offset, size_t size) { - pread64(romFd, output, size, offset); + pread64(fd, output, size, offset); } public: /** * @param filePath The path to the ROM file */ - Loader(const int romFd) : romFd(romFd) {} + Loader(int fd) : fd(fd) {} /** * This loads in the data of the main process diff --git a/app/src/main/cpp/skyline/loader/nro.cpp b/app/src/main/cpp/skyline/loader/nro.cpp index 18327ec3..493b6fca 100644 --- a/app/src/main/cpp/skyline/loader/nro.cpp +++ b/app/src/main/cpp/skyline/loader/nro.cpp @@ -6,7 +6,7 @@ #include "nro.h" namespace skyline::loader { - NroLoader::NroLoader(const int romFd) : Loader(romFd) { + NroLoader::NroLoader(int fd) : Loader(fd) { ReadOffset((u32 *) &header, 0x0, sizeof(NroHeader)); if (header.magic != util::MakeMagic("NRO0")) @@ -27,6 +27,10 @@ namespace skyline::loader { u64 textSize = text.size(); u64 rodataSize = rodata.size(); u64 dataSize = data.size(); + + if (!util::IsAligned(textSize, PAGE_SIZE) || !util::IsAligned(rodataSize, PAGE_SIZE) || !util::IsAligned(dataSize, PAGE_SIZE)) + throw exception("LoadProcessData: Sections are not aligned with page size: 0x{:X}, 0x{:X}, 0x{:X}", textSize, rodataSize, dataSize); + u64 patchSize = patch.size() * sizeof(u32); u64 padding = util::AlignUp(textSize + rodataSize + dataSize + header.bssSize + patchSize, PAGE_SIZE) - (textSize + rodataSize + dataSize + header.bssSize + patchSize); diff --git a/app/src/main/cpp/skyline/loader/nro.h b/app/src/main/cpp/skyline/loader/nro.h index 9406207d..9e56f718 100644 --- a/app/src/main/cpp/skyline/loader/nro.h +++ b/app/src/main/cpp/skyline/loader/nro.h @@ -46,12 +46,12 @@ namespace skyline::loader { public: /** - * @param filePath The path to the ROM file + * @param fd A file descriptor to the ROM */ - NroLoader(const int romFd); + NroLoader(int fd); /** - * This loads in the data of the main process + * @brief This loads in the data of the main process * @param process The process to load in the data * @param state The state of the device */ diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp index 76f5a638..560564e8 100644 --- a/app/src/main/cpp/skyline/nce.cpp +++ b/app/src/main/cpp/skyline/nce.cpp @@ -36,7 +36,7 @@ namespace skyline { if (__predict_false(!Surface)) continue; - const u16 svc = static_cast(state.ctx->commandId); + auto svc = state.ctx->svc; try { if (kernel::svc::SvcTable[svc]) { @@ -51,7 +51,7 @@ namespace skyline { state.ctx->state = ThreadState::WaitRun; } else if (__predict_false(state.ctx->state == ThreadState::GuestCrash)) { - state.logger->Warn("Thread with PID {} has crashed due to signal: {}", thread, strsignal(state.ctx->commandId)); + state.logger->Warn("Thread with PID {} has crashed due to signal: {}", thread, strsignal(state.ctx->svc)); ThreadTrace(); state.ctx->state = ThreadState::WaitRun; @@ -115,7 +115,7 @@ namespace skyline { * So, we opted to use the hacky solution and disable optimizations for this single function. */ void ExecuteFunctionCtx(ThreadCall call, Registers &funcRegs, ThreadContext *ctx) __attribute__ ((optnone)) { - ctx->commandId = static_cast(call); + ctx->threadCall = call; Registers registers = ctx->registers; while (ctx->state != ThreadState::WaitInit && ctx->state != ThreadState::WaitKernel); @@ -192,9 +192,9 @@ namespace skyline { if (ctx->sp) regStr += fmt::format("\nStack Pointer: 0x{:X}", ctx->sp); - constexpr auto numRegisters = 31; //!< The amount of general-purpose registers in ARMv8 + constexpr u8 numRegisters = 31; //!< The amount of general-purpose registers in ARMv8 - for (u16 index = 0; index < numRegisters - 2; index += 2) { + for (u8 index = 0; 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]); } @@ -209,11 +209,11 @@ namespace skyline { } std::vector NCE::PatchCode(std::vector &code, u64 baseAddress, i64 offset) { - constexpr auto TpidrroEl0 = 0x5E83; // ID of TPIDRRO_EL0 in MRS - constexpr auto CntfrqEl0 = 0x5F00; // ID of CNTFRQ_EL0 in MRS - constexpr auto CntpctEl0 = 0x5F01; // ID of CNTPCT_EL0 in MRS - constexpr auto CntvctEl0 = 0x5F02; // ID of CNTVCT_EL0 in MRS - constexpr auto TegraX1Freq = 19200000; // The clock frequency of the Tegra X1 (19.2 MHz) + constexpr u32 TpidrroEl0 = 0x5E83; // ID of TPIDRRO_EL0 in MRS + constexpr u32 CntfrqEl0 = 0x5F00; // ID of CNTFRQ_EL0 in MRS + constexpr u32 CntpctEl0 = 0x5F01; // ID of CNTPCT_EL0 in MRS + constexpr u32 CntvctEl0 = 0x5F02; // ID of CNTVCT_EL0 in MRS + constexpr u32 TegraX1Freq = 19200000; // The clock frequency of the Tegra X1 (19.2 MHz) u32 *start = reinterpret_cast(code.data()); u32 *end = start + (code.size() / sizeof(u32)); @@ -239,23 +239,30 @@ namespace skyline { auto instrMrs = reinterpret_cast(address); if (instrSvc->Verify()) { + // If this is an SVC we need to branch to saveCtx then to the SVC Handler after putting the PC + SVC into X0 and W1 and finally loadCtx before returning to where we were before instr::B bJunc(offset); + constexpr u32 strLr = 0xF81F0FFE; // STR LR, [SP, #-16]! offset += sizeof(strLr); + instr::BL bSvCtx(patchOffset - offset); offset += sizeof(bSvCtx); - auto movPc = instr::MoveU64Reg(regs::X0, baseAddress + (address - start)); + auto movPc = instr::MoveRegister(regs::X0, baseAddress + (address - start)); offset += sizeof(u32) * movPc.size(); + instr::Movz movCmd(regs::W1, static_cast(instrSvc->value)); offset += sizeof(movCmd); + instr::BL bSvcHandler((patchOffset + guest::SaveCtxSize + guest::LoadCtxSize) - offset); offset += sizeof(bSvcHandler); instr::BL bLdCtx((patchOffset + guest::SaveCtxSize) - offset); offset += sizeof(bLdCtx); + constexpr u32 ldrLr = 0xF84107FE; // LDR LR, [SP], #16 offset += sizeof(ldrLr); + instr::B bret(-offset + sizeof(u32)); offset += sizeof(bret); @@ -271,24 +278,31 @@ namespace skyline { patch.push_back(bret.raw); } else if (instrMrs->Verify()) { if (instrMrs->srcReg == TpidrroEl0) { + // If this moves TPIDRRO_EL0 into a register then we retrieve the value of our virtual TPIDRRO_EL0 from TLS and write it to the register instr::B bJunc(offset); + u32 strX0{}; if (instrMrs->destReg != regs::X0) { strX0 = 0xF81F0FE0; // STR X0, [SP, #-16]! offset += sizeof(strX0); } - const u32 mrsX0 = 0xD53BD040; // MRS X0, TPIDR_EL0 + + constexpr u32 mrsX0 = 0xD53BD040; // MRS X0, TPIDR_EL0 offset += sizeof(mrsX0); - const u32 ldrTls = 0xF9408000; // LDR X0, [X0, #256] + + constexpr u32 ldrTls = 0xF9408000; // LDR X0, [X0, #256] (ThreadContext::tpidrroEl0) offset += sizeof(ldrTls); + u32 movXn{}; u32 ldrX0{}; if (instrMrs->destReg != regs::X0) { movXn = instr::Mov(regs::X(instrMrs->destReg), regs::X0).raw; offset += sizeof(movXn); + ldrX0 = 0xF84107E0; // LDR X0, [SP], #16 offset += sizeof(ldrX0); } + instr::B bret(-offset + sizeof(u32)); offset += sizeof(bret); @@ -303,14 +317,19 @@ namespace skyline { patch.push_back(ldrX0); patch.push_back(bret.raw); } else if (frequency != TegraX1Freq) { + // These deal with changing the timer registers, we only do this if the clock frequency doesn't match the X1's clock frequency if (instrMrs->srcReg == CntpctEl0) { + // If this moves CNTPCT_EL0 into a register then call RescaleClock to rescale the device's clock to the X1's clock frequency and write result to register instr::B bJunc(offset); offset += guest::RescaleClockSize; + instr::Ldr ldr(0xF94003E0); // LDR XOUT, [SP] ldr.destReg = instrMrs->destReg; offset += sizeof(ldr); - const u32 addSp = 0x910083FF; // ADD SP, SP, #32 + + constexpr u32 addSp = 0x910083FF; // ADD SP, SP, #32 offset += sizeof(addSp); + instr::B bret(-offset + sizeof(u32)); offset += sizeof(bret); @@ -322,9 +341,12 @@ namespace skyline { patch.push_back(addSp); patch.push_back(bret.raw); } else if (instrMrs->srcReg == CntfrqEl0) { + // If this moves CNTFRQ_EL0 into a register then move the Tegra X1's clock frequency into the register (Rather than the host clock frequency) instr::B bJunc(offset); - auto movFreq = instr::MoveU32Reg(static_cast(instrMrs->destReg), TegraX1Freq); + + auto movFreq = instr::MoveRegister(static_cast(instrMrs->destReg), TegraX1Freq); offset += sizeof(u32) * movFreq.size(); + instr::B bret(-offset + sizeof(u32)); offset += sizeof(bret); @@ -334,9 +356,10 @@ namespace skyline { patch.push_back(bret.raw); } } else { + // If the host clock frequency is the same as the Tegra X1's clock frequency if (instrMrs->srcReg == CntpctEl0) { - instr::Mrs mrs(CntvctEl0, regs::X(instrMrs->destReg)); - *address = mrs.raw; + // If this moves CNTPCT_EL0 into a register, change the instruction to move CNTVCT_EL0 instead as Linux or most other OSes don't allow access to CNTPCT_EL0 rather only CNTVCT_EL0 can be accessed from userspace + *address = instr::Mrs(CntvctEl0, regs::X(instrMrs->destReg)).raw; } } } diff --git a/app/src/main/cpp/skyline/nce/guest.cpp b/app/src/main/cpp/skyline/nce/guest.cpp index d7a60d7f..6f509db9 100644 --- a/app/src/main/cpp/skyline/nce/guest.cpp +++ b/app/src/main/cpp/skyline/nce/guest.cpp @@ -5,6 +5,8 @@ #include #include // This is used implicitly #include +#include +#include #include "guest_common.h" #define FORCE_INLINE __attribute__((always_inline)) inline // NOLINT(cppcoreguidelines-macro-usage) @@ -98,54 +100,14 @@ namespace skyline::guest { /** * @note Do not use any functions that cannot be inlined from this, as this function is placed at an arbitrary address in the guest. In addition, do not use any static variables or globals as the .bss section is not copied into the guest. */ - void SvcHandler(u64 pc, u32 svc) { + void SvcHandler(u64 pc, u16 svc) { volatile ThreadContext *ctx; asm("MRS %0, TPIDR_EL0":"=r"(ctx)); ctx->pc = pc; - ctx->commandId = svc; + ctx->svc = svc; - if (svc == 0xB) { // svcSleepThread - switch (ctx->registers.x0) { - case 0: - case 1: - case 2: { - asm("MOV X0, XZR\n\t" - "MOV X1, XZR\n\t" - "MOV X2, XZR\n\t" - "MOV X3, XZR\n\t" - "MOV X4, XZR\n\t" - "MOV X5, XZR\n\t" - "MOV X8, #124\n\t" // __NR_sched_yield - "STR LR, [SP, #-16]!\n\t" - "MOV LR, SP\n\t" - "SVC #0\n\t" - "MOV SP, LR\n\t" - "LDR LR, [SP], #16":: : "x0", "x1", "x2", "x3", "x4", "x5", "x8"); - break; - } - - default: { - struct timespec spec = { - .tv_sec = static_cast(ctx->registers.x0 / 1000000000), - .tv_nsec = static_cast(ctx->registers.x0 % 1000000000) - }; - asm("MOV X0, %0\n\t" - "MOV X1, XZR\n\t" - "MOV X2, XZR\n\t" - "MOV X3, XZR\n\t" - "MOV X4, XZR\n\t" - "MOV X5, XZR\n\t" - "MOV X8, #101\n\t" // __NR_nanosleep - "STR LR, [SP, #-16]!\n\t" - "MOV LR, SP\n\t" - "SVC #0\n\t" - "MOV SP, LR\n\t" - "LDR LR, [SP], #16"::"r"(&spec) : "x0", "x1", "x2", "x3", "x4", "x5", "x8"); - } - } - return; - } else if (svc == 0x1E) { // svcGetSystemTick + if (svc == 0x1E) { // svcGetSystemTick asm("STP X1, X2, [SP, #-16]!\n\t" "STR Q0, [SP, #-16]!\n\t" "STR Q1, [SP, #-16]!\n\t" @@ -175,7 +137,7 @@ namespace skyline::guest { if (ctx->state == ThreadState::WaitRun) { break; } else if (ctx->state == ThreadState::WaitFunc) { - if (ctx->commandId == static_cast(ThreadCall::Syscall)) { + if (ctx->threadCall == ThreadCall::Syscall) { SaveCtxStack(); LoadCtxTls(); @@ -187,7 +149,7 @@ namespace skyline::guest { SaveCtxTls(); LoadCtxStack(); - } else if (ctx->commandId == static_cast(ThreadCall::Memcopy)) { + } else if (ctx->threadCall == ThreadCall::Memcopy) { auto src = reinterpret_cast(ctx->registers.x0); auto dest = reinterpret_cast(ctx->registers.x1); auto size = ctx->registers.x2; @@ -195,7 +157,7 @@ namespace skyline::guest { while (src < end) *(src++) = *(dest++); - } else if (ctx->commandId == static_cast(ThreadCall::Clone)) { + } else if (ctx->threadCall == ThreadCall::Clone) { SaveCtxStack(); LoadCtxTls(); @@ -248,7 +210,15 @@ namespace skyline::guest { ctx->state = ThreadState::Running; } - void SignalHandler(int signal, siginfo_t *info, ucontext_t *ucontext) { + [[noreturn]] void Exit(int) { + if (gettid() == getpid()) + syscall(__NR_exit_group, 0); + else + syscall(__NR_exit, 0); + __builtin_unreachable(); + } + + [[noreturn]] void SignalHandler(int signal, siginfo_t *info, ucontext_t *ucontext) { volatile ThreadContext *ctx; asm("MRS %0, TPIDR_EL0":"=r"(ctx)); @@ -256,7 +226,7 @@ namespace skyline::guest { ctx->registers.regs[index] = ucontext->uc_mcontext.regs[index]; ctx->pc = ucontext->uc_mcontext.pc; - ctx->commandId = static_cast(signal); + ctx->signal = static_cast(signal); ctx->faultAddress = ucontext->uc_mcontext.fault_address; ctx->sp = ucontext->uc_mcontext.sp; @@ -264,7 +234,7 @@ namespace skyline::guest { ctx->state = ThreadState::GuestCrash; if (ctx->state == ThreadState::WaitRun) - exit(0); + Exit(0); } } @@ -279,7 +249,7 @@ namespace skyline::guest { if (ctx->state == ThreadState::WaitRun) { break; } else if (ctx->state == ThreadState::WaitFunc) { - if (ctx->commandId == static_cast(ThreadCall::Syscall)) { + if (ctx->threadCall == ThreadCall::Syscall) { SaveCtxStack(); LoadCtxTls(); @@ -292,7 +262,7 @@ namespace skyline::guest { SaveCtxTls(); LoadCtxStack(); } - } else if (ctx->commandId == static_cast(ThreadCall::Memcopy)) { + } else if (ctx->threadCall == ThreadCall::Memcopy) { auto src = reinterpret_cast(ctx->registers.x0); auto dest = reinterpret_cast(ctx->registers.x1); auto size = ctx->registers.x2; @@ -311,6 +281,12 @@ namespace skyline::guest { for (int signal : {SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV}) sigaction(signal, &sigact, nullptr); + sigact = { + .sa_handler = Exit, + }; + + sigaction(SIGTERM, &sigact, nullptr); + ctx->state = ThreadState::Running; asm("MOV LR, %0\n\t" diff --git a/app/src/main/cpp/skyline/nce/guest.h b/app/src/main/cpp/skyline/nce/guest.h index 88ad5022..327244ef 100644 --- a/app/src/main/cpp/skyline/nce/guest.h +++ b/app/src/main/cpp/skyline/nce/guest.h @@ -42,6 +42,6 @@ namespace skyline { * @param pc The address of PC when the call was being done * @param svc The SVC ID of the SVC being called */ - void SvcHandler(u64 pc, u32 svc); + void SvcHandler(u64 pc, u16 svc); } } diff --git a/app/src/main/cpp/skyline/nce/guest_common.h b/app/src/main/cpp/skyline/nce/guest_common.h index 11e3cab4..9cf47cc2 100644 --- a/app/src/main/cpp/skyline/nce/guest_common.h +++ b/app/src/main/cpp/skyline/nce/guest_common.h @@ -123,7 +123,7 @@ namespace skyline { /** * @brief This enumeration is used to convey the state of a thread to the kernel */ - enum class ThreadState : u32 { + enum class ThreadState : u8 { NotReady = 0, //!< The thread hasn't yet entered the entry handler Running = 1, //!< The thread is currently executing code WaitKernel = 2, //!< The thread is currently waiting on the kernel @@ -136,10 +136,10 @@ namespace skyline { /** * @brief This enumeration holds the functions that can be run on the guest process */ - enum class ThreadCall : u32 { - Syscall = 0x100, //!< A linux syscall needs to be called from the guest - Memcopy = 0x101, //!< To copy memory from one location to another - Clone = 0x102, //!< Use the clone syscall to create a new thread + enum class ThreadCall : u8 { + Syscall = 1, //!< A linux syscall needs to be called from the guest + Memcopy = 2, //!< To copy memory from one location to another + Clone = 3, //!< Use the clone syscall to create a new thread }; /** @@ -147,7 +147,9 @@ namespace skyline { */ struct ThreadContext { ThreadState state; //!< The state of the guest - u32 commandId; //!< The command ID of the current kernel call/function call + ThreadCall threadCall; //!< The function to run in the guest process + u16 svc; //!< The SVC ID of the current kernel call + u32 signal; //!< The signal caught by the guest process u64 pc; //!< The program counter register on the guest Registers registers; //!< The general purpose registers on the guest u64 tpidrroEl0; //!< The value for TPIDRRO_EL0 for the current thread diff --git a/app/src/main/cpp/skyline/nce/instructions.h b/app/src/main/cpp/skyline/nce/instructions.h index 293d1504..2547fb9b 100644 --- a/app/src/main/cpp/skyline/nce/instructions.h +++ b/app/src/main/cpp/skyline/nce/instructions.h @@ -190,12 +190,12 @@ namespace skyline { * @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 bits and 16-bit aligned) in the register to store the value at + * @param shift The offset (in units of 16-bits) in the register to store the value at */ inline constexpr Movz(regs::X destReg, u16 imm16, u8 shift = 0) { this->destReg = static_cast(destReg); this->imm16 = imm16; - hw = static_cast(shift / 16); + hw = shift; sig = 0xA5; sf = 1; } @@ -204,22 +204,22 @@ 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 bits and 16-bit aligned) in the register to store the value at + * @param shift The offset (in units of 16-bits) in the register to store the value at */ inline constexpr Movz(regs::W destReg, u16 imm16, u8 shift = 0) { this->destReg = static_cast(destReg); this->imm16 = imm16; - hw = static_cast(shift / 16); + hw = shift; sig = 0xA5; sf = 0; } /** * @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 u8 Shift() { - return static_cast(hw * 16); + return static_cast(hw * sizeof(u16)); } /** @@ -252,12 +252,12 @@ namespace skyline { * @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 bits and 16-bit aligned) in the register to store the value at + * @param shift The offset (in units of 16-bits) in the register to store the value at */ inline constexpr Movk(regs::X destReg, u16 imm16, u8 shift = 0) { this->destReg = static_cast(destReg); this->imm16 = imm16; - hw = static_cast(shift / 16); + hw = shift; sig = 0xE5; sf = 1; } @@ -266,22 +266,22 @@ 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 bits and 16-bit aligned) in the register to store the value at + * @param shift The offset (in units of 16-bits) in the register to store the value at */ inline constexpr Movk(regs::W destReg, u16 imm16, u8 shift = 0) { this->destReg = static_cast(destReg); this->imm16 = imm16; - hw = static_cast(shift / 16); + hw = shift; sig = 0xE5; sf = 0; } /** * @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 u8 Shift() { - return static_cast(hw * 16); + return static_cast(hw * sizeof(u16)); } /** @@ -306,57 +306,27 @@ namespace skyline { static_assert(sizeof(Movk) == sizeof(u32)); /** - * @param destReg The destination register of the operation - * @param value The 64-bit value to insert into the register - * @return A vector with the instructions to insert the value + * @param destination The destination register of the operation + * @param value The value to insert into the register + * @return A array with the instructions to insert the value */ - inline const std::vector MoveU64Reg(regs::X destReg, u64 value) { - union { - u64 val; - struct { - u16 v0; - u16 v16; - u16 v32; - u16 v48; - }; - } val; - val.val = value; - std::vector instr; - instr::Movz mov0(destReg, val.v0, 0); - instr.push_back(mov0.raw); - instr::Movk mov16(destReg, val.v16, 16); - if (val.v16) - instr.push_back(mov16.raw); - instr::Movk mov32(destReg, val.v32, 32); - if (val.v32) - instr.push_back(mov32.raw); - instr::Movk mov48(destReg, val.v48, 48); - if (val.v48) - instr.push_back(mov48.raw); - return instr; - } + template + inline constexpr std::array MoveRegister(regs::X destination, Type value) { + std::array instructions; - /** - * @param destReg The destination register of the operation - * @param value The 32-bit value to insert into the register - * @return A vector with the instructions to insert the value - */ - inline const std::vector MoveU32Reg(regs::X destReg, u32 value) { - union { - u32 val; - struct { - u16 v0; - u16 v16; - }; - } val; - val.val = value; - std::vector instr; - instr::Movz mov0(destReg, val.v0, 0); - instr.push_back(mov0.raw); - instr::Movk mov16(destReg, val.v16, 16); - if (val.v16) - instr.push_back(mov16.raw); - return instr; + auto valuePointer = reinterpret_cast(&value); + u8 offset{}; + + for (auto &instruction : instructions) { + if (offset) + instruction = instr::Movk(destination, *(valuePointer + offset), offset).raw; + else + instruction = instr::Movz(destination, *(valuePointer + offset), offset).raw; + + offset++; + } + + return instructions; } /** diff --git a/app/src/main/cpp/skyline/os.cpp b/app/src/main/cpp/skyline/os.cpp index 3850e895..944dc341 100644 --- a/app/src/main/cpp/skyline/os.cpp +++ b/app/src/main/cpp/skyline/os.cpp @@ -8,7 +8,7 @@ namespace skyline::kernel { OS::OS(std::shared_ptr &jvmManager, std::shared_ptr &logger, std::shared_ptr &settings) : state(this, process, jvmManager, settings, logger), memory(state), serviceManager(state) {} - void OS::Execute(const int romFd, const TitleFormat romType) { + void OS::Execute(int romFd, TitleFormat romType) { std::shared_ptr loader; if (romType == TitleFormat::NRO) { @@ -33,7 +33,7 @@ namespace skyline::kernel { auto tlsMem = std::make_shared(state, 0, (sizeof(ThreadContext) + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1), memory::Permission{true, true, false}, memory::states::Reserved); tlsMem->guest = tlsMem->kernel; - pid_t pid = clone(reinterpret_cast(&guest::GuestEntry), reinterpret_cast(stack->guest.address + stackSize), CLONE_FILES | CLONE_FS | CLONE_SETTLS | SIGCHLD, reinterpret_cast(entry), nullptr, reinterpret_cast(tlsMem->guest.address)); + auto pid = clone(reinterpret_cast(&guest::GuestEntry), reinterpret_cast(stack->guest.address + stackSize), CLONE_FILES | CLONE_FS | CLONE_SETTLS | SIGCHLD, reinterpret_cast(entry), nullptr, reinterpret_cast(tlsMem->guest.address)); if (pid == -1) throw exception("Call to clone() has failed: {}", strerror(errno)); diff --git a/app/src/main/cpp/skyline/os.h b/app/src/main/cpp/skyline/os.h index e4be4072..298e1c0e 100644 --- a/app/src/main/cpp/skyline/os.h +++ b/app/src/main/cpp/skyline/os.h @@ -37,7 +37,7 @@ namespace skyline::kernel { * @param romFd A FD to the ROM file to execute * @param romType The type of the ROM file */ - void Execute(const int romFd, const TitleFormat romType); + void Execute(int romFd, TitleFormat romType); /** * @brief Creates a new process diff --git a/app/src/main/cpp/skyline/services/am/controller/ICommonStateGetter.cpp b/app/src/main/cpp/skyline/services/am/controller/ICommonStateGetter.cpp index 1b49af56..b6109185 100644 --- a/app/src/main/cpp/skyline/services/am/controller/ICommonStateGetter.cpp +++ b/app/src/main/cpp/skyline/services/am/controller/ICommonStateGetter.cpp @@ -34,6 +34,7 @@ namespace skyline::service::am { response.errorCode = constant::status::NoMessages; return; } + response.Push(messageQueue.front()); messageQueue.pop(); } diff --git a/app/src/main/cpp/skyline/services/am/controller/ISelfController.cpp b/app/src/main/cpp/skyline/services/am/controller/ISelfController.cpp index 5703f78a..3bc80ade 100644 --- a/app/src/main/cpp/skyline/services/am/controller/ISelfController.cpp +++ b/app/src/main/cpp/skyline/services/am/controller/ISelfController.cpp @@ -25,10 +25,12 @@ namespace skyline::service::am { void ISelfController::CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { state.logger->Debug("Creating Managed Layer on Default Display"); + auto hosBinder = state.os->serviceManager.GetService(Service::hosbinder_IHOSBinderDriver); if (hosBinder->layerStatus != hosbinder::LayerStatus::Uninitialized) throw exception("The application is creating more than one layer"); hosBinder->layerStatus = hosbinder::LayerStatus::Managed; + response.Push(0); } } diff --git a/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp b/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp index 3cef207b..58965830 100644 --- a/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp +++ b/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp @@ -5,7 +5,7 @@ #include "IAudioOut.h" namespace skyline::service::audio { - IAudioOut::IAudioOut(const DeviceState &state, ServiceManager &manager, const u8 channelCount, const u32 sampleRate) : sampleRate(sampleRate), channelCount(channelCount), releaseEvent(std::make_shared(state)), BaseService(state, manager, Service::audio_IAudioOut, "audio:IAudioOut", { + IAudioOut::IAudioOut(const DeviceState &state, ServiceManager &manager, u8 channelCount, u32 sampleRate) : sampleRate(sampleRate), channelCount(channelCount), releaseEvent(std::make_shared(state)), BaseService(state, manager, Service::audio_IAudioOut, "audio:IAudioOut", { {0x0, SFUNC(IAudioOut::GetAudioOutState)}, {0x1, SFUNC(IAudioOut::StartAudioOut)}, {0x2, SFUNC(IAudioOut::StopAudioOut)}, diff --git a/app/src/main/cpp/skyline/services/audio/IAudioOut.h b/app/src/main/cpp/skyline/services/audio/IAudioOut.h index 0839d3b0..b05253fe 100644 --- a/app/src/main/cpp/skyline/services/audio/IAudioOut.h +++ b/app/src/main/cpp/skyline/services/audio/IAudioOut.h @@ -28,7 +28,7 @@ namespace skyline::service::audio { * @param channelCount The channel count of the audio data the audio out will be fed * @param sampleRate The sample rate of the audio data the audio out will be fed */ - IAudioOut(const DeviceState &state, ServiceManager &manager, const u8 channelCount, const u32 sampleRate); + IAudioOut(const DeviceState &state, ServiceManager &manager, u8 channelCount, u32 sampleRate); /** * @brief Closes the audio track diff --git a/app/src/main/cpp/skyline/services/base_service.h b/app/src/main/cpp/skyline/services/base_service.h index fbbd95d7..eed605f0 100644 --- a/app/src/main/cpp/skyline/services/base_service.h +++ b/app/src/main/cpp/skyline/services/base_service.h @@ -91,12 +91,12 @@ namespace skyline::service { class BaseService { protected: const DeviceState &state; //!< The state of the device - ServiceManager &manager; //!< A pointer to the service manager - const std::unordered_map> vTable; //!< This holds the mapping from an object's CmdId to the actual function + ServiceManager &manager; //!< A reference to the service manager + std::unordered_map> vTable; //!< This holds the mapping from a function's CmdId to the actual function public: - const Service serviceType; //!< The type of the service this is - const std::string serviceName; //!< The name of the service + Service serviceType; //!< The type of this service + std::string serviceName; //!< The name of this service /** * @param state The state of the device @@ -105,7 +105,7 @@ namespace skyline::service { * @param serviceName The name of the service * @param vTable The functions of the service */ - BaseService(const DeviceState &state, ServiceManager &manager, const Service serviceType, const std::string &serviceName, const std::unordered_map> &vTable) : state(state), manager(manager), serviceType(serviceType), serviceName(serviceName), vTable(vTable) {} + BaseService(const DeviceState &state, ServiceManager &manager, Service serviceType, const std::string &serviceName, const std::unordered_map> &vTable) : state(state), manager(manager), serviceType(serviceType), serviceName(serviceName), vTable(vTable) {} /** * @brief This handles all IPC commands with type request to a service diff --git a/app/src/main/cpp/skyline/services/fatalsrv/IService.cpp b/app/src/main/cpp/skyline/services/fatalsrv/IService.cpp index 4a025426..938a16f3 100644 --- a/app/src/main/cpp/skyline/services/fatalsrv/IService.cpp +++ b/app/src/main/cpp/skyline/services/fatalsrv/IService.cpp @@ -11,6 +11,6 @@ namespace skyline::service::fatalsrv { }) {} void IService::ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - throw exception("A fatal error with code: 0x{:X} has caused emulation to stop", *reinterpret_cast(request.cmdArg)); + throw exception("A fatal error with code: 0x{:X} has caused emulation to stop", request.Pop()); } } diff --git a/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp b/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp index b8bce3ca..63fdd30e 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp +++ b/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp @@ -4,5 +4,5 @@ #include "IFileSystem.h" namespace skyline::service::fssrv { - IFileSystem::IFileSystem(const FsType type, const DeviceState &state, ServiceManager &manager) : type(type), BaseService(state, manager, Service::fssrv_IFileSystem, "fssrv:IFileSystem", {}) {} + IFileSystem::IFileSystem(FsType type, const DeviceState &state, ServiceManager &manager) : type(type), BaseService(state, manager, Service::fssrv_IFileSystem, "fssrv:IFileSystem", {}) {} } diff --git a/app/src/main/cpp/skyline/services/fssrv/IFileSystem.h b/app/src/main/cpp/skyline/services/fssrv/IFileSystem.h index a1fdcdf0..34f64683 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFileSystem.h +++ b/app/src/main/cpp/skyline/services/fssrv/IFileSystem.h @@ -11,9 +11,9 @@ namespace skyline::service::fssrv { * @brief These are the possible types of the filesystem */ enum class FsType { - Nand, - SdCard, - GameCard + Nand, //!< The internal NAND storage + SdCard, //!< The external SDCard storage + GameCard, //!< The Game-Card of the inserted game (https://switchbrew.org/wiki/Gamecard) }; /** @@ -21,7 +21,7 @@ namespace skyline::service::fssrv { */ class IFileSystem : public BaseService { public: - const FsType type; + FsType type; //!< The type of filesystem this class represents IFileSystem(FsType type, const DeviceState &state, ServiceManager &manager); }; diff --git a/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp b/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp index 51325281..a4407901 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp +++ b/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp @@ -10,7 +10,7 @@ namespace skyline::service::fssrv { }) {} void IFileSystemProxy::SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - process = *reinterpret_cast(request.cmdArg); + process = request.Pop(); } void IFileSystemProxy::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { diff --git a/app/src/main/cpp/skyline/services/hid/IAppletResource.cpp b/app/src/main/cpp/skyline/services/hid/IAppletResource.cpp index 41f134e2..a6310edf 100644 --- a/app/src/main/cpp/skyline/services/hid/IAppletResource.cpp +++ b/app/src/main/cpp/skyline/services/hid/IAppletResource.cpp @@ -12,6 +12,7 @@ namespace skyline::service::hid { hidSharedMemory = std::make_shared(state, NULL, constant::HidSharedMemSize, memory::Permission{true, false, false}); auto handle = state.process->InsertItem(hidSharedMemory); state.logger->Debug("HID Shared Memory Handle: 0x{:X}", handle); + response.copyHandles.push_back(handle); } } diff --git a/app/src/main/cpp/skyline/services/hid/IHidServer.cpp b/app/src/main/cpp/skyline/services/hid/IHidServer.cpp index b3a8d61e..fcb4d0b9 100644 --- a/app/src/main/cpp/skyline/services/hid/IHidServer.cpp +++ b/app/src/main/cpp/skyline/services/hid/IHidServer.cpp @@ -30,6 +30,7 @@ namespace skyline::service::hid { const auto &buffer = request.inputBuf.at(0); size_t numId = buffer.size / sizeof(NpadId); u64 address = buffer.address; + for (size_t i = 0; i < numId; i++) { auto id = state.process->GetObject(address); deviceMap[id] = JoyConDevice(id); @@ -50,6 +51,7 @@ namespace skyline::service::hid { void IHidServer::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { auto controllerId = request.Pop(); auto appletUserId = request.Pop(); + deviceMap[controllerId].assignment = JoyConAssignment::Single; deviceMap[controllerId].side = request.Pop(); } diff --git a/app/src/main/cpp/skyline/services/hosbinder/IHOSBinderDriver.cpp b/app/src/main/cpp/skyline/services/hosbinder/IHOSBinderDriver.cpp index 4d492432..906e8033 100644 --- a/app/src/main/cpp/skyline/services/hosbinder/IHOSBinderDriver.cpp +++ b/app/src/main/cpp/skyline/services/hosbinder/IHOSBinderDriver.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "IHOSBinderDriver.h" #include "display.h" @@ -123,9 +124,9 @@ namespace skyline::service::hosbinder { std::shared_ptr nvBuffer{}; auto nvmap = state.os->serviceManager.GetService(Service::nvdrv_INvDrvServices)->GetDevice(nvdrv::device::NvDeviceType::nvmap); - if (gbpBuffer->nvmapHandle) + if (gbpBuffer->nvmapHandle) { nvBuffer = nvmap->handleTable.at(gbpBuffer->nvmapHandle); - else { + } else { for (const auto &object : nvmap->handleTable) { if (object.second->id == gbpBuffer->nvmapId) { nvBuffer = object.second; @@ -140,10 +141,10 @@ namespace skyline::service::hosbinder { switch (gbpBuffer->format) { case WINDOW_FORMAT_RGBA_8888: case WINDOW_FORMAT_RGBX_8888: - format = gpu::texture::format::RGBA8888Unorm; + format = gpu::format::RGBA8888Unorm; break; case WINDOW_FORMAT_RGB_565: - format = gpu::texture::format::RGB565Unorm; + format = gpu::format::RGB565Unorm; break; default: throw exception("Unknown pixel format used for FB"); diff --git a/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp b/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp index 4c1e7563..0dfcec6a 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/INvDrvServices.cpp @@ -22,28 +22,35 @@ namespace skyline::service::nvdrv { std::shared_ptr object; switch (type) { - case (device::NvDeviceType::nvhost_ctrl): + case device::NvDeviceType::nvhost_ctrl: object = std::make_shared(state); break; - case (device::NvDeviceType::nvhost_gpu): - case (device::NvDeviceType::nvhost_vic): - case (device::NvDeviceType::nvhost_nvdec): + + case device::NvDeviceType::nvhost_gpu: + case device::NvDeviceType::nvhost_vic: + case device::NvDeviceType::nvhost_nvdec: object = std::make_shared(state, type); break; - case (device::NvDeviceType::nvhost_ctrl_gpu): + + case device::NvDeviceType::nvhost_ctrl_gpu: object = std::make_shared(state); break; - case (device::NvDeviceType::nvmap): + + case device::NvDeviceType::nvmap: object = std::make_shared(state); break; - case (device::NvDeviceType::nvhost_as_gpu): + + case device::NvDeviceType::nvhost_as_gpu: object = std::make_shared(state); break; + default: throw exception("Cannot find NVDRV device"); } + deviceMap[type] = object; fdMap[fdIndex] = object; + return fdIndex++; } @@ -59,6 +66,7 @@ namespace skyline::service::nvdrv { void INvDrvServices::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { auto buffer = request.inputBuf.at(0); auto path = state.process->GetString(buffer.address, buffer.size); + response.Push(OpenDevice(path)); response.Push(constant::status::Success); } @@ -66,20 +74,24 @@ namespace skyline::service::nvdrv { void INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { auto fd = request.Pop(); auto cmd = request.Pop(); + state.logger->Debug("IOCTL on device: 0x{:X}, cmd: 0x{:X}", fd, cmd); try { if (request.inputBuf.empty() || request.outputBuf.empty()) { if (request.inputBuf.empty()) { device::IoctlData data(request.outputBuf.at(0)); + fdMap.at(fd)->HandleIoctl(cmd, data); response.Push(data.status); } else { device::IoctlData data(request.inputBuf.at(0)); + fdMap.at(fd)->HandleIoctl(cmd, data); response.Push(data.status); } } else { device::IoctlData data(request.inputBuf.at(0), request.outputBuf.at(0)); + fdMap.at(fd)->HandleIoctl(cmd, data); response.Push(data.status); } @@ -89,16 +101,19 @@ namespace skyline::service::nvdrv { } void INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - u32 fd = *reinterpret_cast(request.cmdArg); + auto fd = request.Pop(); state.logger->Debug("Closing NVDRV device ({})", fd); + try { auto device = fdMap.at(fd); if (!--device->refCount) deviceMap.erase(device->deviceType); + fdMap.erase(fd); } catch (const std::out_of_range &) { state.logger->Warn("Trying to close non-existent FD"); } + response.Push(constant::status::Success); } @@ -111,6 +126,7 @@ namespace skyline::service::nvdrv { auto eventId = request.Pop(); auto event = std::make_shared(state); auto handle = state.process->InsertItem(event); + state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", fd, eventId, handle); response.copyHandles.push_back(handle); } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp index 79607eff..daa5ee6b 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp @@ -25,6 +25,7 @@ namespace skyline::service::nvdrv::device { void NvHostChannel::SetPriority(IoctlData &buffer) { auto priority = state.process->GetObject(buffer.input[0].address); + switch (priority) { case NvChannelPriority::Low: timeslice = 1300; diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp index 617c369d..ec047763 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -31,6 +31,7 @@ namespace skyline::service::nvdrv::device { u32 subregionHeightAlignPixels{0x40}; u32 subregionCount{0x10}; } zCullInfo; + state.process->WriteMemory(zCullInfo, buffer.output[0].address); } @@ -72,11 +73,13 @@ namespace skyline::service::nvdrv::device { u64 chipName; // 0x6230326D67 ("gm20b") u64 grCompbitStoreBaseHw; // 0x0 (not supported) }; + struct Data { u64 gpuCharacteristicsBufSize; // InOut u64 gpuCharacteristicsBufAddr; // In GpuCharacteristics gpuCharacteristics; // Out } data = state.process->GetObject(buffer.input[0].address); + data.gpuCharacteristics = { .arch = 0x120, .impl = 0xB, @@ -113,7 +116,9 @@ namespace skyline::service::nvdrv::device { .chipName = 0x6230326D67, .grCompbitStoreBaseHw = 0x0 }; + data.gpuCharacteristicsBufSize = 0xA0; + state.process->WriteMemory(data, buffer.output[0].address); } @@ -123,8 +128,10 @@ namespace skyline::service::nvdrv::device { u32 reserved[3]; // In u64 maskBuf; // Out } data = state.process->GetObject(buffer.input[0].address); + if (data.maskBufSize) data.maskBuf = 0x3; + state.process->WriteMemory(data, buffer.output[0].address); } @@ -136,6 +143,7 @@ namespace skyline::service::nvdrv::device { .slot = 0x07, .mask = 0x01 }; + state.process->WriteMemory(data, buffer.output[0].address); } } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp index 78a61d7d..11b31ff6 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp @@ -21,8 +21,10 @@ namespace skyline::service::nvdrv::device { u32 size; // In u32 handle; // Out } data = state.process->GetObject(buffer.input[0].address); + handleTable[handleIndex] = std::make_shared(idIndex++, data.size); data.handle = handleIndex++; + state.process->WriteMemory(data, buffer.output[0].address); state.logger->Debug("Create: Input: Size: 0x{:X}, Output: Handle: 0x{:X}, Status: {}", data.size, data.handle, buffer.status); } @@ -32,6 +34,7 @@ namespace skyline::service::nvdrv::device { u32 id; // In u32 handle; // Out } data = state.process->GetObject(buffer.input[0].address); + bool found{}; for (const auto &object : handleTable) { if (object.second->id == data.id) { @@ -40,10 +43,12 @@ namespace skyline::service::nvdrv::device { break; } } + if (found) state.process->WriteMemory(data, buffer.output[0].address); else buffer.status = NvStatus::BadValue; + state.logger->Debug("FromId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status); } @@ -57,6 +62,7 @@ namespace skyline::service::nvdrv::device { u8 _pad0_[7]; u64 address; // InOut } data = state.process->GetObject(buffer.input[0].address); + auto &object = handleTable.at(data.handle); object->heapMask = data.heapMask; object->flags = data.flags; @@ -64,6 +70,7 @@ namespace skyline::service::nvdrv::device { object->kind = data.kind; object->address = data.address; object->status = NvMapObject::Status::Allocated; + state.logger->Debug("Alloc: Input: Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}, Output: Status: {}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.address, buffer.status); } @@ -75,6 +82,7 @@ namespace skyline::service::nvdrv::device { u32 size; // Out u64 flags; // Out } data = state.process->GetObject(buffer.input[0].address); + const auto &object = handleTable.at(data.handle); if (object.use_count() > 1) { data.address = static_cast(object->address); @@ -83,8 +91,10 @@ namespace skyline::service::nvdrv::device { data.address = 0x0; data.flags = 0x1; // Not free yet } + data.size = object->size; handleTable.erase(data.handle); + state.process->WriteMemory(data, buffer.output[0].address); } @@ -95,11 +105,13 @@ namespace skyline::service::nvdrv::device { Parameter parameter; // In u32 result; // Out } data = state.process->GetObject(buffer.input[0].address); + auto &object = handleTable.at(data.handle); switch (data.parameter) { case Parameter::Size: data.result = object->size; break; + case Parameter::Alignment: case Parameter::HeapMask: case Parameter::Kind: { @@ -120,13 +132,16 @@ namespace skyline::service::nvdrv::device { } break; } + case Parameter::Base: buffer.status = NvStatus::NotImplemented; break; + case Parameter::Compr: buffer.status = NvStatus::NotImplemented; break; } + state.process->WriteMemory(data, buffer.output[0].address); state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status); } @@ -136,7 +151,9 @@ namespace skyline::service::nvdrv::device { u32 id; // Out u32 handle; // In } data = state.process->GetObject(buffer.input[0].address); + data.id = handleTable.at(data.handle)->id; + state.process->WriteMemory(data, buffer.output[0].address); state.logger->Debug("GetId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status); } diff --git a/app/src/main/cpp/skyline/services/serviceman.cpp b/app/src/main/cpp/skyline/services/serviceman.cpp index c60a8ad3..4d924b15 100644 --- a/app/src/main/cpp/skyline/services/serviceman.cpp +++ b/app/src/main/cpp/skyline/services/serviceman.cpp @@ -20,7 +20,7 @@ namespace skyline::service { ServiceManager::ServiceManager(const DeviceState &state) : state(state) {} - std::shared_ptr ServiceManager::CreateService(const Service serviceType) { + std::shared_ptr ServiceManager::CreateService(Service serviceType) { auto serviceIter = serviceMap.find(serviceType); if (serviceIter != serviceMap.end()) return (*serviceIter).second; @@ -73,7 +73,7 @@ namespace skyline::service { return serviceObj; } - KHandle ServiceManager::NewSession(const Service serviceType) { + KHandle ServiceManager::NewSession(Service serviceType) { std::lock_guard serviceGuard(mutex); return state.process->NewHandle(CreateService(serviceType)).handle; } @@ -110,7 +110,7 @@ namespace skyline::service { state.logger->Debug("Service has been registered: \"{}\" (0x{:X})", serviceObject->serviceName, handle); } - void ServiceManager::CloseSession(const KHandle handle) { + void ServiceManager::CloseSession(KHandle handle) { std::lock_guard serviceGuard(mutex); auto session = state.process->GetHandle(handle); if (session->serviceStatus == type::KSession::ServiceStatus::Open) { @@ -124,7 +124,7 @@ namespace skyline::service { } }; - void ServiceManager::SyncRequestHandler(const KHandle handle) { + void ServiceManager::SyncRequestHandler(KHandle handle) { auto session = state.process->GetHandle(handle); state.logger->Debug("----Start----"); state.logger->Debug("Handle is 0x{:X}", handle); diff --git a/app/src/main/cpp/skyline/services/serviceman.h b/app/src/main/cpp/skyline/services/serviceman.h index 1690b8b9..a21ff366 100644 --- a/app/src/main/cpp/skyline/services/serviceman.h +++ b/app/src/main/cpp/skyline/services/serviceman.h @@ -22,7 +22,7 @@ namespace skyline::service { * @param serviceType The type of service requested * @return A shared pointer to an instance of the service */ - std::shared_ptr CreateService(const Service serviceType); + std::shared_ptr CreateService(Service serviceType); public: /** @@ -35,7 +35,7 @@ namespace skyline::service { * @param serviceType The type of the service * @return Handle to KService object of the service */ - KHandle NewSession(const Service serviceType); + KHandle NewSession(Service serviceType); /** * @brief Creates a new service using it's type enum and writes it's handle or virtual handle (If it's a domain request) to IpcResponse @@ -61,7 +61,7 @@ namespace skyline::service { * @note This only works for services created with `NewService` as sub-interfaces used with `RegisterService` can have multiple instances */ template - inline std::shared_ptr GetService(const Service serviceType) { + inline std::shared_ptr GetService(Service serviceType) { return std::static_pointer_cast(serviceMap.at(serviceType)); } @@ -69,12 +69,12 @@ namespace skyline::service { * @brief Closes an existing session to a service * @param service The handle of the KService object */ - void CloseSession(const KHandle handle); + void CloseSession(KHandle handle); /** * @brief Handles a Synchronous IPC Request * @param handle The handle of the object */ - void SyncRequestHandler(const KHandle handle); + void SyncRequestHandler(KHandle handle); }; } diff --git a/app/src/main/cpp/skyline/services/settings/ISystemSettingsServer.cpp b/app/src/main/cpp/skyline/services/settings/ISystemSettingsServer.cpp index 7d71f010..fe694c52 100644 --- a/app/src/main/cpp/skyline/services/settings/ISystemSettingsServer.cpp +++ b/app/src/main/cpp/skyline/services/settings/ISystemSettingsServer.cpp @@ -9,7 +9,7 @@ namespace skyline::service::settings { {0x3, SFUNC(ISystemSettingsServer::GetFirmwareVersion)}}) {} void ISystemSettingsServer::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - SysVerTitle title{.minor=9, .major=0, .micro=0, .revMajor=4, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"}; + SysVerTitle title{.major=9, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"}; state.process->WriteMemory(title, request.outputBuf.at(0).address); } } diff --git a/app/src/main/cpp/skyline/services/sm/IUserInterface.cpp b/app/src/main/cpp/skyline/services/sm/IUserInterface.cpp index fd865074..19244a5b 100644 --- a/app/src/main/cpp/skyline/services/sm/IUserInterface.cpp +++ b/app/src/main/cpp/skyline/services/sm/IUserInterface.cpp @@ -13,6 +13,7 @@ namespace skyline::service::sm { void IUserInterface::GetService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { std::string serviceName(reinterpret_cast(request.cmdArg)); + if (serviceName.empty()) { response.errorCode = constant::status::ServiceInvName; } else { diff --git a/app/src/main/cpp/skyline/services/timesrv/ITimeZoneService.cpp b/app/src/main/cpp/skyline/services/timesrv/ITimeZoneService.cpp index 11db0509..62a1c9cc 100644 --- a/app/src/main/cpp/skyline/services/timesrv/ITimeZoneService.cpp +++ b/app/src/main/cpp/skyline/services/timesrv/ITimeZoneService.cpp @@ -11,20 +11,22 @@ namespace skyline::service::timesrv { void ITimeZoneService::ToCalendarTimeWithMyRule(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { time_t curTime = std::time(nullptr); tm calender = *std::gmtime(&curTime); + CalendarTime calendarTime{ .year = static_cast(calender.tm_year), .month = static_cast(calender.tm_mon), .day = static_cast(calender.tm_hour), .minute = static_cast(calender.tm_min), - .second = static_cast(calender.tm_sec) + .second = static_cast(calender.tm_sec), }; response.Push(calendarTime); + CalendarAdditionalInfo calendarInfo{ .dayWeek = static_cast(calender.tm_wday), .dayMonth = static_cast(calender.tm_mday), .name = *reinterpret_cast(calender.tm_zone), .dst = static_cast(calender.tm_isdst), - .utcRel = static_cast(calender.tm_gmtoff) + .utcRel = static_cast(calender.tm_gmtoff), }; response.Push(calendarInfo); } diff --git a/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp b/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp index 4a86b6bf..b6268439 100644 --- a/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp +++ b/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp @@ -44,6 +44,7 @@ namespace skyline::service::visrv { std::string displayName(reinterpret_cast(request.cmdArg)); state.logger->Debug("Setting display as: {}", displayName); state.os->serviceManager.GetService(Service::hosbinder_IHOSBinderDriver)->SetDisplay(displayName); + response.Push(0); // There's only one display } @@ -59,7 +60,9 @@ namespace skyline::service::visrv { u64 userId; } input = request.Pop(); state.logger->Debug("Opening Layer: Display Name: {}, Layer ID: {}, User ID: {}", input.displayName, input.layerId, input.userId); + std::string name(input.displayName); + Parcel parcel(state); LayerParcel data{ .type = 0x20, @@ -69,7 +72,8 @@ namespace skyline::service::visrv { }; parcel.WriteData(data); parcel.objects.resize(4); - response.Push(parcel.WriteParcel(request.outputBuf.at(0))); + + response.Push(parcel.WriteParcel(request.outputBuf.at(0))); } void IApplicationDisplayService::CloseLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { @@ -87,12 +91,14 @@ namespace skyline::service::visrv { void IApplicationDisplayService::SetLayerScalingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { auto scalingMode = request.Pop(); auto layerId = request.Pop(); + state.logger->Debug("Setting Layer Scaling mode to '{}' for layer {}", scalingMode, layerId); } void IApplicationDisplayService::GetDisplayVsyncEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { KHandle handle = state.process->InsertItem(state.gpu->vsyncEvent); state.logger->Debug("VSync Event Handle: 0x{:X}", handle); + response.copyHandles.push_back(handle); } } diff --git a/app/src/main/cpp/skyline/services/visrv/IDisplayService.cpp b/app/src/main/cpp/skyline/services/visrv/IDisplayService.cpp index 221d5224..cc89e5e2 100644 --- a/app/src/main/cpp/skyline/services/visrv/IDisplayService.cpp +++ b/app/src/main/cpp/skyline/services/visrv/IDisplayService.cpp @@ -29,6 +29,7 @@ namespace skyline::service::visrv { .string = "dispdrv" }; parcel.WriteData(data); + response.Push(parcel.WriteParcel(request.outputBuf.at(0))); } diff --git a/app/src/main/cpp/skyline/services/visrv/IManagerDisplayService.cpp b/app/src/main/cpp/skyline/services/visrv/IManagerDisplayService.cpp index b4272e5a..340e55ed 100644 --- a/app/src/main/cpp/skyline/services/visrv/IManagerDisplayService.cpp +++ b/app/src/main/cpp/skyline/services/visrv/IManagerDisplayService.cpp @@ -18,19 +18,23 @@ namespace skyline::service::visrv { request.Skip(); auto displayId = request.Pop(); state.logger->Debug("Creating Managed Layer on Display: {}", displayId); + auto hosBinder = state.os->serviceManager.GetService(Service::hosbinder_IHOSBinderDriver); if (hosBinder->layerStatus != hosbinder::LayerStatus::Uninitialized) throw exception("The application is creating more than one layer"); hosBinder->layerStatus = hosbinder::LayerStatus::Managed; + response.Push(0); // There's only one layer } void IManagerDisplayService::DestroyManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { auto layerId = request.Pop(); state.logger->Debug("Destroying Managed Layer: {}", layerId); + auto hosBinder = state.os->serviceManager.GetService(Service::hosbinder_IHOSBinderDriver); if (hosBinder->layerStatus == hosbinder::LayerStatus::Uninitialized) state.logger->Warn("The application is destroying an uninitialized layer"); + hosBinder->layerStatus = hosbinder::LayerStatus::Uninitialized; } diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index 5cb350eb..1e2e567f 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -5,6 +5,7 @@ package emu.skyline +import android.annotation.SuppressLint import android.content.Intent import android.net.Uri import android.os.Bundle @@ -114,6 +115,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { /** * This makes the window fullscreen then sets up [preferenceFd] and [logFd], sets up the performance statistics and finally calls [executeApplication] for executing the application */ + @SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)