Compare commits

...

81 Commits

Author SHA1 Message Date
bunnei
dfc3eed0cb maxwell_to_gl: Implement VertexAttribute::Size::Size_16_16_16_16.
- Used by Super Mario Odyssey (in game).
2018-08-08 23:28:17 -04:00
bunnei
06d0b96ca9 maxwell_to_gl: Implement PrimitiveTopology::Points.
- Used by Super Mario Odyssey (in game).
2018-08-08 23:28:00 -04:00
bunnei
25ba4d1b68 Merge pull request #982 from bunnei/stub-unk-63
gl_shader_decompiler: Stub input attribute Unknown_63.
2018-08-08 22:28:18 -04:00
bunnei
2f4f4f147f Merge pull request #986 from mailwl/acc-loadimage
Service/Account: stub LoadImage function
2018-08-08 21:21:06 -04:00
bunnei
cf917a5e93 Merge pull request #976 from bunnei/shader-imm
gl_shader_decompiler: Let OpenGL interpret floats.
2018-08-08 19:17:01 -04:00
bunnei
9ceceb212f Merge pull request #981 from bunnei/cbuf-corrupt
maxwell_3d: Use correct const buffer size and check bounds.
2018-08-08 19:16:34 -04:00
bunnei
9f48454ea9 Merge pull request #978 from bunnei/fixioctl
nvhost_gpu: Don't over copy IoctlSubmitGpfifo.
2018-08-08 19:16:14 -04:00
bunnei
cc2526dd51 Merge pull request #985 from bunnei/rt-r11g11b10
gpu: Add R11G11B10_FLOAT to RenderTargetBytesPerPixel.
2018-08-08 18:21:34 -04:00
bunnei
096b04f1a4 Merge pull request #979 from bunnei/vtx88
maxwell_to_gl: Implement VertexAttribute::Size::Size_8_8.
2018-08-08 18:18:50 -04:00
bunnei
756e1e6f9b Merge pull request #975 from bunnei/am-stub
am: Stub SetScreenShotImageOrientation.
2018-08-08 16:46:45 -04:00
bunnei
599c011f40 Merge pull request #980 from bunnei/fix-logs
renderer_opengl: Use trace log in a few places.
2018-08-08 16:45:42 -04:00
bunnei
d224eb7c39 Merge pull request #966 from lioncash/modernize
common: Convert type traits templates over to variable template versions where applicable
2018-08-08 15:28:34 -04:00
bunnei
fd9da4232b Merge pull request #850 from DarkLordZach/icon-meta
Add Icons and Metadata Support
2018-08-08 12:27:19 -04:00
bunnei
507e6ae100 Merge pull request #968 from lioncash/vec
vector_math: Minor cleanups
2018-08-08 12:00:13 -04:00
bunnei
6a2f415298 Merge pull request #969 from lioncash/lz4
externals/CMakeLists: Add EXCLUDE_FROM_ALL to lz4's add_subdirectory() command
2018-08-08 11:59:14 -04:00
bunnei
448264e719 Merge pull request #958 from lioncash/nv-global
nvdrv: Get rid of global std::weak_ptr
2018-08-08 11:58:45 -04:00
mailwl
c0d44d3b2a Service/Account: stub LoadImage function 2018-08-08 14:42:54 +03:00
bunnei
f156a45c01 Merge pull request #972 from lioncash/catch
externals: Update catch to 2.3.0
2018-08-08 03:00:57 -04:00
bunnei
6a5d032809 Merge pull request #965 from lioncash/unused-files
hle: Remove unused romfs.cpp/.h
2018-08-08 03:00:38 -04:00
bunnei
4941e3d412 Merge pull request #974 from lioncash/acc
acc: Add missing function table entries for GetUserCount
2018-08-08 02:56:00 -04:00
bunnei
7bf422d58c gpu: Add R11G11B10_FLOAT to RenderTargetBytesPerPixel.
- Used by Super Mario Odyssey.
2018-08-08 02:42:14 -04:00
Mat M
9fde7d739a Merge pull request #983 from mailwl/hid-fix
hid: fix IsSixAxisSensorAtRest() response
2018-08-08 02:37:32 -04:00
mailwl
3c498189b6 hid: fix IsSixAxisSensorAtRest() response 2018-08-08 09:36:23 +03:00
bunnei
7f0d0a93f7 gl_shader_decompiler: Stub input attribute Unknown_63. 2018-08-08 02:35:59 -04:00
bunnei
57982df105 maxwell_3d: Use correct const buffer size and check bounds.
- Fixes mem corruption with Super Mario Odyssey and Pokkén Tournament DX.
2018-08-08 02:10:25 -04:00
bunnei
8c6338b6f9 renderer_opengl: Use trace log in a few places. 2018-08-08 01:53:23 -04:00
bunnei
c120ed7d18 maxwell_to_gl: Implement VertexAttribute::Size::Size_8_8. 2018-08-08 01:50:53 -04:00
bunnei
0f834e2284 nvhost_gpu: Don't over copy IoctlSubmitGpfifo. 2018-08-08 01:49:47 -04:00
bunnei
e542356d0c gl_shader_decompiler: Let OpenGL interpret floats.
- Accuracy is lost in translation to string, e.g. with NaN.
- Needed for Super Mario Odyssey.
2018-08-08 01:45:23 -04:00
bunnei
b7fb9f2071 am: Stub SetScreenShotImageOrientation.
- Used by Super Mario Odyssey.
2018-08-08 00:41:35 -04:00
Lioncash
934a2b9604 acc: Add missing function table entries for GetUserCount
Given this is stubbed within the common module in
5ac7b84, it should be added to the other relevant tables as well.
2018-08-07 22:50:45 -04:00
bunnei
2bc296801a acc: Stub GetUserCount. (#973)
- Used by Pokken Tournament DX.
2018-08-07 22:39:12 -04:00
bunnei
80cfd88e4e Merge pull request #967 from lioncash/sign
file_util: Avoid sign-conversions in WriteArray() and ReadArray()
2018-08-07 22:37:00 -04:00
Lioncash
d378d98e26 nvdrv: Get rid of global std::weak_ptr
Rather than use global state, we can simply pass the instance into the
NVFlinger instance directly.
2018-08-07 21:53:05 -04:00
Lioncash
766c1a2d50 vector_math: Remove unimplemented function prototypes 2018-08-07 21:33:48 -04:00
Lioncash
5c323d96e0 vector_math: Make functions constexpr where applicable 2018-08-07 21:32:05 -04:00
Lioncash
4e3bc37791 vector_math: Convert typedefs to type aliases 2018-08-07 21:15:10 -04:00
Lioncash
a7d6efc520 common: Convert type traits templates over to variable template versions where applicable
Uses the C++17 inline variable variants
2018-08-07 19:34:47 -04:00
Lioncash
cd1a96f389 hle: Remove unused romfs.cpp/.h
These files are no longer used, so we can get rid of them.
2018-08-07 19:34:12 -04:00
Lioncash
62b0b83fd8 externals: Update catch to 2.3.0
Updates the library from 2.2.3 to 2.3.0
2018-08-07 19:26:13 -04:00
bunnei
825e8cb925 Merge pull request #971 from DarkLordZach/mbedtls-2.12.0
externals/mbedtls: Update to mbedtls v2.12.0
2018-08-07 19:25:50 -04:00
Zach Hilman
1fbb7aff1e externals/mbedtls: Update to mbedtls v2.12.0 2018-08-07 19:22:49 -04:00
bunnei
4fa3511a63 Merge pull request #964 from Hexagon12/lower-logs
Lowered down the logging for command processor methods
2018-08-07 19:00:19 -04:00
Hexagon12
7139f05fc5 Fixed the sRGB pixel format (#963)
* Changed the sRGB pixel format return

* Add a message about SRGBA -> RGBA conversion
2018-08-07 18:59:50 -04:00
Lioncash
e530f82dd3 externals/CMakeLists: Add EXCLUDE_FROM_ALL to lz4's add_subdirectory() command
We don't need to build the lz4 CLI tool, or anything else. We just want
to build in the library statically, so we specify this to ensure that.
Now, we don't potentially build unnecessary targets.
2018-08-07 18:40:52 -04:00
Zach Hilman
1abfd4166e configure_gamelist: Use explicit QVariant constructor 2018-08-07 17:10:10 -04:00
bunnei
b9829a05be Merge pull request #920 from DarkLordZach/titlekey
content_archive: Add support for titlekey cryptography
2018-08-07 17:01:25 -04:00
bunnei
7ed8565978 Merge pull request #957 from lioncash/event
nvflinger: Correct typo in name of composition event
2018-08-07 15:56:51 -04:00
bunnei
6576bc8927 Merge pull request #954 from lioncash/hid
services/hid: Add ActivateNpadWithRevision() to the hid function info array
2018-08-07 15:56:34 -04:00
bunnei
2d57cbaec1 Merge pull request #960 from lioncash/apm
service/apm: Add the apm:sys service
2018-08-07 14:57:12 -04:00
bunnei
3242e7c164 Merge pull request #950 from lioncash/hotkey
qt/hotkey: Get rid of global hotkey map instance
2018-08-07 14:45:45 -04:00
bunnei
c707240685 Merge pull request #948 from hcorion/fix-mbedtls-installing-files
CMakeLists: Make mbedtls and cubeb not install headers and libraries
2018-08-07 14:27:43 -04:00
bunnei
573a66c23d Merge pull request #955 from lioncash/view
nvflinger: Use std::string_view in OpenDisplay()
2018-08-07 14:26:51 -04:00
bunnei
97c6f984dc Merge pull request #953 from lioncash/time
service/time: Amend command IDs of ToPosixTime() and ToPosixTimeWithMyRule()
2018-08-07 14:25:52 -04:00
bunnei
07595987ac Merge pull request #959 from KAMiKAZOW/cubeb-compilation
Make building cubeb optional
2018-08-07 14:25:17 -04:00
bunnei
b09c4f45c7 Merge pull request #956 from lioncash/nv
nvdrv: Get rid of indirect inclusions
2018-08-07 14:23:32 -04:00
Lioncash
0735a0c8a1 file_util: Avoid sign-conversions in WriteArray() and ReadArray()
Prevents compiler warnings.
2018-08-07 13:51:37 -04:00
Hexagon12
bc6d91a103 Lowered down the logging for methods 2018-08-07 19:51:40 +03:00
bunnei
c392650e21 Merge pull request #952 from lioncash/usb
service: Add usb services
2018-08-07 11:27:49 -04:00
bunnei
8f73f41824 Merge pull request #949 from lioncash/priv
client_port: Make all data members private
2018-08-07 11:20:26 -04:00
bunnei
c4397ec77e Merge pull request #951 from lioncash/glad
externals: Update glad to 0.1.26
2018-08-07 11:20:02 -04:00
bunnei
438d9aa407 Merge pull request #961 from DarkLordZach/nca-as-drd-scope
loader: Fix scope error in DeconstructedRomDirectory
2018-08-07 11:18:52 -04:00
Zach Hilman
3e81c09094 loader: Fix scope error in DeconstructedRomDirectory 2018-08-07 10:37:38 -04:00
Lioncash
12ab5a0547 service/apm: Add the apm:sys service
Adds the basic skeleton of the apm:sys service based off the information
on Switch Brew.
2018-08-07 10:05:26 -04:00
Lioncash
d3f64785d1 nvflinger: Correct typo in name of composition event 2018-08-07 09:03:52 -04:00
Lioncash
300ab211e8 nvdrv: Make Ioctl()'s definition match its prototype
The only reason this wasn't a compilation error is because we use
little-endian systems.
2018-08-07 08:57:11 -04:00
Lioncash
fa8017295b nvdrv: Get rid of indirect inclusions 2018-08-07 08:54:50 -04:00
Lioncash
e40b0cf437 nvflinger: Get rid of indirect inclusions 2018-08-07 08:32:05 -04:00
Lioncash
7e49881b7f nvflinger: Use std::string_view in OpenDisplay()
We don't need to use a std::string here, given all that's done is
comparing the character sequence against another. This allows passing
regular const char* without needing to heap allocate.
2018-08-07 08:32:06 -04:00
KAMiKAZOW
0f5c4615ae Make building cubeb optional 2018-08-07 13:21:56 +02:00
Lioncash
890e543304 services/hid: Add ActivateNpadWithRevision() to the hid function info array
Updated based off the information on Switch Brew.
2018-08-07 03:23:20 -04:00
Lioncash
20c976ff2a service/time: Amend command IDs of ToPosixTime() and ToPosixTimeWithMyRule()
Updates the ID of these based off the information on Switch Brew.
2018-08-07 03:18:07 -04:00
Lioncash
45bc449ff9 service: Add usb services
Adds basic skeleton for the usb services based off the information provided by Switch Brew.
2018-08-07 03:14:03 -04:00
Lioncash
0db0e4c8f3 externals: Update glad to 0.1.26
Updates the library from 0.1.25. Mainly fixes issues related to macOS,
but we may as well update the library.
2018-08-07 02:24:34 -04:00
Zach Hilman
91cfe70301 loader: Add icon and title support to XCI 2018-08-06 23:13:42 -04:00
Zach Hilman
e4422b09b6 Fix missing qjpeg DLL 2018-08-06 23:06:33 -04:00
Zach Hilman
5927cf0e17 Use const where applicable 2018-08-06 23:06:33 -04:00
Zach Hilman
9e88f03e75 Avoid parsing RomFS to directory in NCA 2018-08-06 23:06:33 -04:00
Lioncash
da2f00ab7d client_port: Make all data members private
These members don't need to be entirely exposed, we can instead expose
an API to operate on them without directly needing to mutate them

We can also guard against overflow/API misuse this way as well, given
active_sessions is an unsigned value.
2018-08-06 23:05:17 -04:00
Zion Nimchuk
e3321c2e00 Make mbedtls and cubeb not install headers and libraries 2018-08-06 18:32:07 -07:00
Zach Hilman
2cc962e171 content_archive: Add support for titlekey cryptography 2018-08-04 14:57:21 -04:00
91 changed files with 4448 additions and 3654 deletions

View File

@@ -4,8 +4,10 @@ function(copy_yuzu_Qt5_deps target_dir)
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(PLATFORMS ${DLL_DEST}platforms/)
set(STYLES ${DLL_DEST}styles/)
set(IMAGEFORMATS ${DLL_DEST}imageformats/)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
icudt*.dll
icuin*.dll
@@ -17,4 +19,5 @@ function(copy_yuzu_Qt5_deps target_dir)
)
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} qjpeg$<$<CONFIG:Debug>:d>.*)
endfunction(copy_yuzu_Qt5_deps)

View File

@@ -117,6 +117,7 @@ after_build:
mkdir $RELEASE_DIST
mkdir $RELEASE_DIST/platforms
mkdir $RELEASE_DIST/styles
mkdir $RELEASE_DIST/imageformats
# copy the compiled binaries and other release files to the release folder
Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
@@ -140,6 +141,9 @@ after_build:
# copy the qt windows vista style dll to platforms
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/styles/qwindowsvistastyle.dll" -force -destination "$RELEASE_DIST/styles"
# copy the qt jpeg imageformat dll to platforms
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/imageformats/qjpeg.dll" -force -destination "$RELEASE_DIST/imageformats"
7z a -tzip $MINGW_BUILD_ZIP $RELEASE_DIST\*
7z a $MINGW_SEVENZIP $RELEASE_DIST
}

View File

@@ -32,11 +32,11 @@ add_subdirectory(inih)
# lz4
set(LZ4_BUNDLED_MODE ON)
add_subdirectory(lz4/contrib/cmake_unofficial)
add_subdirectory(lz4/contrib/cmake_unofficial EXCLUDE_FROM_ALL)
target_include_directories(lz4_static INTERFACE ./lz4/lib)
# mbedtls
add_subdirectory(mbedtls)
add_subdirectory(mbedtls EXCLUDE_FROM_ALL)
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
# MicroProfile
@@ -62,5 +62,5 @@ target_include_directories(opus INTERFACE ./opus/include)
# Cubeb
if(ENABLE_CUBEB)
set(BUILD_TESTS OFF CACHE BOOL "")
add_subdirectory(cubeb)
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
endif()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,6 @@ add_library(audio_core STATIC
audio_renderer.cpp
audio_renderer.h
buffer.h
cubeb_sink.cpp
cubeb_sink.h
codec.cpp
codec.h
null_sink.h
@@ -15,6 +13,8 @@ add_library(audio_core STATIC
sink_details.cpp
sink_details.h
sink_stream.h
$<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h>
)
create_target_directory_groups(audio_core)

View File

@@ -9,13 +9,13 @@ namespace Common {
template <typename T>
constexpr T AlignUp(T value, size_t size) {
static_assert(std::is_unsigned<T>::value, "T must be an unsigned value.");
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>(value + (size - value % size) % size);
}
template <typename T>
constexpr T AlignDown(T value, size_t size) {
static_assert(std::is_unsigned<T>::value, "T must be an unsigned value.");
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>(value - value % size);
}

View File

@@ -96,7 +96,7 @@ static inline int LeastSignificantSetBit(u64 val) {
template <typename IntTy>
class BitSet {
static_assert(!std::is_signed<IntTy>::value, "BitSet should not be used with signed types");
static_assert(!std::is_signed_v<IntTy>, "BitSet should not be used with signed types");
public:
// A reference to a particular bit, returned from operator[].

View File

@@ -8,6 +8,7 @@
#include <cstdio>
#include <fstream>
#include <functional>
#include <limits>
#include <string>
#include <string_view>
#include <type_traits>
@@ -207,39 +208,42 @@ public:
template <typename T>
size_t ReadArray(T* data, size_t length) const {
static_assert(std::is_trivially_copyable<T>(),
static_assert(std::is_trivially_copyable_v<T>,
"Given array does not consist of trivially copyable objects");
if (!IsOpen())
return -1;
if (!IsOpen()) {
return std::numeric_limits<size_t>::max();
}
return std::fread(data, sizeof(T), length, m_file);
}
template <typename T>
size_t WriteArray(const T* data, size_t length) {
static_assert(std::is_trivially_copyable<T>(),
static_assert(std::is_trivially_copyable_v<T>,
"Given array does not consist of trivially copyable objects");
if (!IsOpen())
return -1;
if (!IsOpen()) {
return std::numeric_limits<size_t>::max();
}
return std::fwrite(data, sizeof(T), length, m_file);
}
template <typename T>
size_t ReadBytes(T* data, size_t length) const {
static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
return ReadArray(reinterpret_cast<char*>(data), length);
}
template <typename T>
size_t WriteBytes(const T* data, size_t length) {
static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
return WriteArray(reinterpret_cast<const char*>(data), length);
}
template <typename T>
size_t WriteObject(const T& object) {
static_assert(!std::is_pointer<T>::value, "Given object is a pointer");
static_assert(!std::is_pointer_v<T>, "WriteObject arguments must not be a pointer");
return WriteArray(&object, 1);
}

View File

@@ -28,7 +28,7 @@ static inline u64 ComputeHash64(const void* data, size_t len) {
*/
template <typename T>
static inline u64 ComputeStructHash64(const T& data) {
static_assert(std::is_trivially_copyable<T>(),
static_assert(std::is_trivially_copyable_v<T>,
"Type passed to ComputeStructHash64 must be trivially copyable");
return ComputeHash64(&data, sizeof(data));
}
@@ -38,7 +38,7 @@ template <typename T>
struct HashableStruct {
// In addition to being trivially copyable, T must also have a trivial default constructor,
// because any member initialization would be overridden by memset
static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial");
static_assert(std::is_trivial_v<T>, "Type passed to HashableStruct must be trivial");
/*
* We use a union because "implicitly-defined copy/move constructor for a union X copies the
* object representation of X." and "implicitly-defined copy assignment operator for a union X

View File

@@ -200,6 +200,7 @@ void FileBackend::Write(const Entry& entry) {
SUB(Service, SPL) \
SUB(Service, SSL) \
SUB(Service, Time) \
SUB(Service, USB) \
SUB(Service, VI) \
SUB(Service, WLAN) \
CLS(HW) \

View File

@@ -87,6 +87,7 @@ enum class Class : ClassType {
Service_SPL, ///< The SPL service
Service_SSL, ///< The SSL service
Service_Time, ///< The time service
Service_USB, ///< The USB (Universal Serial Bus) service
Service_VI, ///< The VI (Video interface) service
Service_WLAN, ///< The WLAN (Wireless local area network) service
HW, ///< Low-level hardware emulation

View File

@@ -42,140 +42,136 @@ class Vec3;
template <typename T>
class Vec4;
template <typename T>
static inline Vec2<T> MakeVec(const T& x, const T& y);
template <typename T>
static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z);
template <typename T>
static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w);
template <typename T>
class Vec2 {
public:
T x{};
T y{};
Vec2() = default;
Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
constexpr Vec2() = default;
constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
template <typename T2>
Vec2<T2> Cast() const {
return Vec2<T2>((T2)x, (T2)y);
constexpr Vec2<T2> Cast() const {
return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
}
static Vec2 AssignToAll(const T& f) {
return Vec2<T>(f, f);
static constexpr Vec2 AssignToAll(const T& f) {
return Vec2{f, f};
}
Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
return MakeVec(x + other.x, y + other.y);
constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
return {x + other.x, y + other.y};
}
void operator+=(const Vec2& other) {
constexpr Vec2& operator+=(const Vec2& other) {
x += other.x;
y += other.y;
return *this;
}
Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
return MakeVec(x - other.x, y - other.y);
constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
return {x - other.x, y - other.y};
}
void operator-=(const Vec2& other) {
constexpr Vec2& operator-=(const Vec2& other) {
x -= other.x;
y -= other.y;
return *this;
}
template <typename U = T>
Vec2<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
return MakeVec(-x, -y);
constexpr Vec2<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
return {-x, -y};
}
Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
return MakeVec(x * other.x, y * other.y);
}
template <typename V>
Vec2<decltype(T{} * V{})> operator*(const V& f) const {
return MakeVec(x * f, y * f);
}
template <typename V>
void operator*=(const V& f) {
*this = *this * f;
}
template <typename V>
Vec2<decltype(T{} / V{})> operator/(const V& f) const {
return MakeVec(x / f, y / f);
}
template <typename V>
void operator/=(const V& f) {
*this = *this / f;
constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
return {x * other.x, y * other.y};
}
T Length2() const {
template <typename V>
constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
return {x * f, y * f};
}
template <typename V>
constexpr Vec2& operator*=(const V& f) {
*this = *this * f;
return *this;
}
template <typename V>
constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
return {x / f, y / f};
}
template <typename V>
constexpr Vec2& operator/=(const V& f) {
*this = *this / f;
return *this;
}
constexpr T Length2() const {
return x * x + y * y;
}
// Only implemented for T=float
float Length() const;
void SetLength(const float l);
Vec2 WithLength(const float l) const;
float Distance2To(Vec2& other);
Vec2 Normalized() const;
float Normalize(); // returns the previous length, which is often useful
T& operator[](int i) // allow vector[1] = 3 (vector.y=3)
{
constexpr T& operator[](std::size_t i) {
return *((&x) + i);
}
T operator[](const int i) const {
constexpr const T& operator[](std::size_t i) const {
return *((&x) + i);
}
void SetZero() {
constexpr void SetZero() {
x = 0;
y = 0;
}
// Common aliases: UV (texel coordinates), ST (texture coordinates)
T& u() {
constexpr T& u() {
return x;
}
T& v() {
constexpr T& v() {
return y;
}
T& s() {
constexpr T& s() {
return x;
}
T& t() {
constexpr T& t() {
return y;
}
const T& u() const {
constexpr const T& u() const {
return x;
}
const T& v() const {
constexpr const T& v() const {
return y;
}
const T& s() const {
constexpr const T& s() const {
return x;
}
const T& t() const {
constexpr const T& t() const {
return y;
}
// swizzlers - create a subvector of specific components
const Vec2 yx() const {
constexpr Vec2 yx() const {
return Vec2(y, x);
}
const Vec2 vu() const {
constexpr Vec2 vu() const {
return Vec2(y, x);
}
const Vec2 ts() const {
constexpr Vec2 ts() const {
return Vec2(y, x);
}
};
template <typename T, typename V>
Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
return Vec2<T>(f * vec.x, f * vec.y);
}
typedef Vec2<float> Vec2f;
using Vec2f = Vec2<float>;
template <>
inline float Vec2<float>::Length() const {
@@ -196,147 +192,151 @@ public:
T y{};
T z{};
Vec3() = default;
Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
constexpr Vec3() = default;
constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
template <typename T2>
Vec3<T2> Cast() const {
return MakeVec<T2>((T2)x, (T2)y, (T2)z);
constexpr Vec3<T2> Cast() const {
return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
}
// Only implemented for T=int and T=float
static Vec3 FromRGB(unsigned int rgb);
unsigned int ToRGB() const; // alpha bits set to zero
static Vec3 AssignToAll(const T& f) {
return MakeVec(f, f, f);
static constexpr Vec3 AssignToAll(const T& f) {
return Vec3(f, f, f);
}
Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
return MakeVec(x + other.x, y + other.y, z + other.z);
constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
return {x + other.x, y + other.y, z + other.z};
}
void operator+=(const Vec3& other) {
constexpr Vec3& operator+=(const Vec3& other) {
x += other.x;
y += other.y;
z += other.z;
return *this;
}
Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
return MakeVec(x - other.x, y - other.y, z - other.z);
constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
return {x - other.x, y - other.y, z - other.z};
}
void operator-=(const Vec3& other) {
constexpr Vec3& operator-=(const Vec3& other) {
x -= other.x;
y -= other.y;
z -= other.z;
return *this;
}
template <typename U = T>
Vec3<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
return MakeVec(-x, -y, -z);
}
Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
return MakeVec(x * other.x, y * other.y, z * other.z);
}
template <typename V>
Vec3<decltype(T{} * V{})> operator*(const V& f) const {
return MakeVec(x * f, y * f, z * f);
}
template <typename V>
void operator*=(const V& f) {
*this = *this * f;
}
template <typename V>
Vec3<decltype(T{} / V{})> operator/(const V& f) const {
return MakeVec(x / f, y / f, z / f);
}
template <typename V>
void operator/=(const V& f) {
*this = *this / f;
constexpr Vec3<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
return {-x, -y, -z};
}
T Length2() const {
constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
return {x * other.x, y * other.y, z * other.z};
}
template <typename V>
constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
return {x * f, y * f, z * f};
}
template <typename V>
constexpr Vec3& operator*=(const V& f) {
*this = *this * f;
return *this;
}
template <typename V>
constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
return {x / f, y / f, z / f};
}
template <typename V>
constexpr Vec3& operator/=(const V& f) {
*this = *this / f;
return *this;
}
constexpr T Length2() const {
return x * x + y * y + z * z;
}
// Only implemented for T=float
float Length() const;
void SetLength(const float l);
Vec3 WithLength(const float l) const;
float Distance2To(Vec3& other);
Vec3 Normalized() const;
float Normalize(); // returns the previous length, which is often useful
T& operator[](int i) // allow vector[2] = 3 (vector.z=3)
{
return *((&x) + i);
}
T operator[](const int i) const {
constexpr T& operator[](std::size_t i) {
return *((&x) + i);
}
void SetZero() {
constexpr const T& operator[](std::size_t i) const {
return *((&x) + i);
}
constexpr void SetZero() {
x = 0;
y = 0;
z = 0;
}
// Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
T& u() {
constexpr T& u() {
return x;
}
T& v() {
constexpr T& v() {
return y;
}
T& w() {
constexpr T& w() {
return z;
}
T& r() {
constexpr T& r() {
return x;
}
T& g() {
constexpr T& g() {
return y;
}
T& b() {
constexpr T& b() {
return z;
}
T& s() {
constexpr T& s() {
return x;
}
T& t() {
constexpr T& t() {
return y;
}
T& q() {
constexpr T& q() {
return z;
}
const T& u() const {
constexpr const T& u() const {
return x;
}
const T& v() const {
constexpr const T& v() const {
return y;
}
const T& w() const {
constexpr const T& w() const {
return z;
}
const T& r() const {
constexpr const T& r() const {
return x;
}
const T& g() const {
constexpr const T& g() const {
return y;
}
const T& b() const {
constexpr const T& b() const {
return z;
}
const T& s() const {
constexpr const T& s() const {
return x;
}
const T& t() const {
constexpr const T& t() const {
return y;
}
const T& q() const {
constexpr const T& q() const {
return z;
}
@@ -345,7 +345,7 @@ public:
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
// component names (x<->r) and permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) \
const Vec2<T> name() const { \
constexpr Vec2<T> name() const { \
return Vec2<T>(a, b); \
}
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
@@ -366,7 +366,7 @@ public:
};
template <typename T, typename V>
Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
}
@@ -387,7 +387,7 @@ inline float Vec3<float>::Normalize() {
return length;
}
typedef Vec3<float> Vec3f;
using Vec3f = Vec3<float>;
template <typename T>
class Vec4 {
@@ -397,86 +397,88 @@ public:
T z{};
T w{};
Vec4() = default;
Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}
constexpr Vec4() = default;
constexpr Vec4(const T& x_, const T& y_, const T& z_, const T& w_)
: x(x_), y(y_), z(z_), w(w_) {}
template <typename T2>
Vec4<T2> Cast() const {
return Vec4<T2>((T2)x, (T2)y, (T2)z, (T2)w);
constexpr Vec4<T2> Cast() const {
return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
static_cast<T2>(w));
}
// Only implemented for T=int and T=float
static Vec4 FromRGBA(unsigned int rgba);
unsigned int ToRGBA() const;
static Vec4 AssignToAll(const T& f) {
return Vec4<T>(f, f, f, f);
static constexpr Vec4 AssignToAll(const T& f) {
return Vec4(f, f, f, f);
}
Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w);
constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
return {x + other.x, y + other.y, z + other.z, w + other.w};
}
void operator+=(const Vec4& other) {
constexpr Vec4& operator+=(const Vec4& other) {
x += other.x;
y += other.y;
z += other.z;
w += other.w;
return *this;
}
Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
return MakeVec(x - other.x, y - other.y, z - other.z, w - other.w);
constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
return {x - other.x, y - other.y, z - other.z, w - other.w};
}
void operator-=(const Vec4& other) {
constexpr Vec4& operator-=(const Vec4& other) {
x -= other.x;
y -= other.y;
z -= other.z;
w -= other.w;
return *this;
}
template <typename U = T>
Vec4<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
return MakeVec(-x, -y, -z, -w);
}
Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
return MakeVec(x * other.x, y * other.y, z * other.z, w * other.w);
}
template <typename V>
Vec4<decltype(T{} * V{})> operator*(const V& f) const {
return MakeVec(x * f, y * f, z * f, w * f);
}
template <typename V>
void operator*=(const V& f) {
*this = *this * f;
}
template <typename V>
Vec4<decltype(T{} / V{})> operator/(const V& f) const {
return MakeVec(x / f, y / f, z / f, w / f);
}
template <typename V>
void operator/=(const V& f) {
*this = *this / f;
constexpr Vec4<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
return {-x, -y, -z, -w};
}
T Length2() const {
constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
return {x * other.x, y * other.y, z * other.z, w * other.w};
}
template <typename V>
constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
return {x * f, y * f, z * f, w * f};
}
template <typename V>
constexpr Vec4& operator*=(const V& f) {
*this = *this * f;
return *this;
}
template <typename V>
constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
return {x / f, y / f, z / f, w / f};
}
template <typename V>
constexpr Vec4& operator/=(const V& f) {
*this = *this / f;
return *this;
}
constexpr T Length2() const {
return x * x + y * y + z * z + w * w;
}
// Only implemented for T=float
float Length() const;
void SetLength(const float l);
Vec4 WithLength(const float l) const;
float Distance2To(Vec4& other);
Vec4 Normalized() const;
float Normalize(); // returns the previous length, which is often useful
T& operator[](int i) // allow vector[2] = 3 (vector.z=3)
{
return *((&x) + i);
}
T operator[](const int i) const {
constexpr T& operator[](std::size_t i) {
return *((&x) + i);
}
void SetZero() {
constexpr const T& operator[](std::size_t i) const {
return *((&x) + i);
}
constexpr void SetZero() {
x = 0;
y = 0;
z = 0;
@@ -484,29 +486,29 @@ public:
}
// Common alias: RGBA (colors)
T& r() {
constexpr T& r() {
return x;
}
T& g() {
constexpr T& g() {
return y;
}
T& b() {
constexpr T& b() {
return z;
}
T& a() {
constexpr T& a() {
return w;
}
const T& r() const {
constexpr const T& r() const {
return x;
}
const T& g() const {
constexpr const T& g() const {
return y;
}
const T& b() const {
constexpr const T& b() const {
return z;
}
const T& a() const {
constexpr const T& a() const {
return w;
}
@@ -518,7 +520,7 @@ public:
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
// permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) \
const Vec2<T> name() const { \
constexpr Vec2<T> name() const { \
return Vec2<T>(a, b); \
}
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
@@ -545,7 +547,7 @@ public:
#undef _DEFINE_SWIZZLER2
#define _DEFINE_SWIZZLER3(a, b, c, name) \
const Vec3<T> name() const { \
constexpr Vec3<T> name() const { \
return Vec3<T>(a, b, c); \
}
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
@@ -579,51 +581,51 @@ public:
};
template <typename T, typename V>
Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
return MakeVec(f * vec.x, f * vec.y, f * vec.z, f * vec.w);
constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
}
typedef Vec4<float> Vec4f;
using Vec4f = Vec4<float>;
template <typename T>
static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) {
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) {
return a.x * b.x + a.y * b.y;
}
template <typename T>
static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
template <typename T>
static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
template <typename T>
static inline Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) {
return MakeVec(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) {
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
}
// linear interpolation via float: 0.0=begin, 1.0=end
template <typename X>
static inline decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
const float t) {
constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
const float t) {
return begin * (1.f - t) + end * t;
}
// linear interpolation via int: 0=begin, base=end
template <typename X, int base>
static inline decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end,
const int t) {
constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end,
const int t) {
return (begin * (base - t) + end * t) / base;
}
// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
// interpolation.
template <typename X>
inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s,
const float t) {
constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s,
const float t) {
auto y0 = Lerp(x00, x01, s);
auto y1 = Lerp(x10, x11, s);
return Lerp(y0, y1, t);
@@ -631,42 +633,42 @@ inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x1
// Utility vector factories
template <typename T>
static inline Vec2<T> MakeVec(const T& x, const T& y) {
constexpr Vec2<T> MakeVec(const T& x, const T& y) {
return Vec2<T>{x, y};
}
template <typename T>
static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
return Vec3<T>{x, y, z};
}
template <typename T>
static inline Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
return MakeVec(x, y, zw[0], zw[1]);
}
template <typename T>
static inline Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
return MakeVec(xy[0], xy[1], z);
}
template <typename T>
static inline Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
return MakeVec(x, yz[0], yz[1]);
}
template <typename T>
static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
return Vec4<T>{x, y, z, w};
}
template <typename T>
static inline Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
return MakeVec(xy[0], xy[1], z, w);
}
template <typename T>
static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
return MakeVec(x, yz[0], yz[1], w);
}
@@ -674,17 +676,17 @@ static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
// out soon enough due to misuse of the returned structure.
template <typename T>
static inline Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
return MakeVec(xy[0], xy[1], zw[0], zw[1]);
}
template <typename T>
static inline Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
return MakeVec(xyz[0], xyz[1], xyz[2], w);
}
template <typename T>
static inline Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
return MakeVec(x, yzw[0], yzw[1], yzw[2]);
}

View File

@@ -34,7 +34,7 @@ inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
template <typename T>
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
static_assert(std::is_pointer<T>(), "Argument must be a (function) pointer.");
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
size_t addr = reinterpret_cast<size_t>(f);
if (IsWithin2G(code, addr)) {
code.call(f);

View File

@@ -104,8 +104,6 @@ add_library(core STATIC
hle/lock.cpp
hle/lock.h
hle/result.h
hle/romfs.cpp
hle/romfs.h
hle/service/acc/acc.cpp
hle/service/acc/acc.h
hle/service/acc/acc_aa.cpp
@@ -315,6 +313,8 @@ add_library(core STATIC
hle/service/time/interface.h
hle/service/time/time.cpp
hle/service/time/time.h
hle/service/usb/usb.cpp
hle/service/usb/usb.h
hle/service/vi/vi.cpp
hle/service/vi/vi.h
hle/service/vi/vi_m.cpp

View File

@@ -5,6 +5,7 @@
#include <array>
#include <string>
#include <core/loader/loader.h>
#include "common/logging/log.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/file_sys/vfs_offset.h"

View File

@@ -76,12 +76,17 @@ bool IsValidNCA(const NCAHeader& header) {
return header.magic == Common::MakeMagic('N', 'C', 'A', '3');
}
boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
u8 NCA::GetCryptoRevision() const {
u8 master_key_id = header.crypto_type;
if (header.crypto_type_2 > master_key_id)
master_key_id = header.crypto_type_2;
if (master_key_id > 0)
--master_key_id;
return master_key_id;
}
boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
const auto master_key_id = GetCryptoRevision();
if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index))
return boost::none;
@@ -108,38 +113,67 @@ boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType ty
return out;
}
VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const {
boost::optional<Core::Crypto::Key128> NCA::GetTitlekey() const {
const auto master_key_id = GetCryptoRevision();
u128 rights_id{};
memcpy(rights_id.data(), header.rights_id.data(), 16);
if (rights_id == u128{})
return boost::none;
auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
if (titlekey == Core::Crypto::Key128{})
return boost::none;
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id), Core::Crypto::Mode::ECB);
cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), Core::Crypto::Op::Decrypt);
return titlekey;
}
VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting_offset) const {
if (!encrypted)
return in;
switch (header.raw.header.crypto_type) {
switch (s_header.raw.header.crypto_type) {
case NCASectionCryptoType::NONE:
LOG_DEBUG(Crypto, "called with mode=NONE");
return in;
case NCASectionCryptoType::CTR:
LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
{
const auto key = GetKeyAreaKey(NCASectionCryptoType::CTR);
boost::optional<Core::Crypto::Key128> key = boost::none;
if (std::find_if_not(header.rights_id.begin(), header.rights_id.end(),
[](char c) { return c == 0; }) == header.rights_id.end()) {
key = GetKeyAreaKey(NCASectionCryptoType::CTR);
} else {
key = GetTitlekey();
}
if (key == boost::none)
return nullptr;
auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(
std::move(in), key.value(), starting_offset);
std::vector<u8> iv(16);
for (u8 i = 0; i < 8; ++i)
iv[i] = header.raw.section_ctr[0x8 - i - 1];
iv[i] = s_header.raw.section_ctr[0x8 - i - 1];
out->SetIV(iv);
return std::static_pointer_cast<VfsFile>(out);
}
case NCASectionCryptoType::XTS:
// TODO(DarkLordZach): Implement XTSEncryptionLayer and title key encryption.
// TODO(DarkLordZach): Implement XTSEncryptionLayer.
default:
LOG_ERROR(Crypto, "called with unhandled crypto type={:02X}",
static_cast<u8>(header.raw.header.crypto_type));
static_cast<u8>(s_header.raw.header.crypto_type));
return nullptr;
}
}
NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
if (file == nullptr) {
status = Loader::ResultStatus::ErrorInvalidFormat;
return;
}
if (sizeof(NCAHeader) != file->ReadObject(&header))
LOG_ERROR(Loader, "File reader errored out during header read.");

View File

@@ -12,6 +12,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "control_metadata.h"
#include "core/crypto/key_manager.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/loader/loader.h"
@@ -95,7 +96,9 @@ protected:
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
private:
u8 GetCryptoRevision() const;
boost::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const;
boost::optional<Core::Crypto::Key128> GetTitlekey() const;
VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const;
std::vector<VirtualDir> dirs;

View File

@@ -62,6 +62,13 @@ enum class Language : u8 {
Chinese = 14,
};
static constexpr std::array<const char*, 15> LANGUAGE_NAMES = {
"AmericanEnglish", "BritishEnglish", "Japanese",
"French", "German", "LatinAmericanSpanish",
"Spanish", "Italian", "Dutch",
"CanadianFrench", "Portugese", "Russian",
"Korean", "Taiwanese", "Chinese"};
// A class representing the format used by NX metadata files, typically named Control.nacp.
// These store application name, dev name, title id, and other miscellaneous data.
class NACP {

View File

@@ -14,8 +14,8 @@
namespace Kernel {
ClientPort::ClientPort() {}
ClientPort::~ClientPort() {}
ClientPort::ClientPort() = default;
ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
// Note: Threads do not wait for the server endpoint to call
@@ -40,4 +40,12 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
}
void ClientPort::ConnectionClosed() {
if (active_sessions == 0) {
return;
}
--active_sessions;
}
} // namespace Kernel

View File

@@ -37,14 +37,20 @@ public:
*/
ResultVal<SharedPtr<ClientSession>> Connect();
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
u32 active_sessions; ///< Number of currently open sessions to this port
std::string name; ///< Name of client port (optional)
/**
* Signifies that a previously active connection has been closed,
* decreasing the total number of active connections to this port.
*/
void ConnectionClosed();
private:
ClientPort();
~ClientPort() override;
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
u32 active_sessions = 0; ///< Number of currently open sessions to this port
std::string name; ///< Name of client port (optional)
};
} // namespace Kernel

View File

@@ -27,7 +27,7 @@ ServerSession::~ServerSession() {
// Decrease the port's connection count.
if (parent->port)
parent->port->active_sessions--;
parent->port->ConnectionClosed();
// TODO(Subv): Wake up all the ClientSession's waiting threads and set
// the SendSyncRequest result to 0xC920181A.

View File

@@ -1,102 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstring>
#include "common/swap.h"
#include "core/hle/romfs.h"
namespace RomFS {
struct Header {
u32_le header_length;
u32_le dir_hash_table_offset;
u32_le dir_hash_table_length;
u32_le dir_table_offset;
u32_le dir_table_length;
u32_le file_hash_table_offset;
u32_le file_hash_table_length;
u32_le file_table_offset;
u32_le file_table_length;
u32_le data_offset;
};
static_assert(sizeof(Header) == 0x28, "Header has incorrect size");
struct DirectoryMetadata {
u32_le parent_dir_offset;
u32_le next_dir_offset;
u32_le first_child_dir_offset;
u32_le first_file_offset;
u32_le same_hash_next_dir_offset;
u32_le name_length; // in bytes
// followed by directory name
};
static_assert(sizeof(DirectoryMetadata) == 0x18, "DirectoryMetadata has incorrect size");
struct FileMetadata {
u32_le parent_dir_offset;
u32_le next_file_offset;
u64_le data_offset;
u64_le data_length;
u32_le same_hash_next_file_offset;
u32_le name_length; // in bytes
// followed by file name
};
static_assert(sizeof(FileMetadata) == 0x20, "FileMetadata has incorrect size");
static bool MatchName(const u8* buffer, u32 name_length, const std::u16string& name) {
std::vector<char16_t> name_buffer(name_length / sizeof(char16_t));
std::memcpy(name_buffer.data(), buffer, name_length);
return name == std::u16string(name_buffer.begin(), name_buffer.end());
}
const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path) {
constexpr u32 INVALID_FIELD = 0xFFFFFFFF;
// Split path into directory names and file name
std::vector<std::u16string> dir_names = path;
dir_names.pop_back();
const std::u16string& file_name = path.back();
Header header;
std::memcpy(&header, romfs, sizeof(header));
// Find directories of each level
DirectoryMetadata dir;
const u8* current_dir = romfs + header.dir_table_offset;
std::memcpy(&dir, current_dir, sizeof(dir));
for (const std::u16string& dir_name : dir_names) {
u32 child_dir_offset;
child_dir_offset = dir.first_child_dir_offset;
while (true) {
if (child_dir_offset == INVALID_FIELD) {
return nullptr;
}
const u8* current_child_dir = romfs + header.dir_table_offset + child_dir_offset;
std::memcpy(&dir, current_child_dir, sizeof(dir));
if (MatchName(current_child_dir + sizeof(dir), dir.name_length, dir_name)) {
current_dir = current_child_dir;
break;
}
child_dir_offset = dir.next_dir_offset;
}
}
// Find the file
FileMetadata file;
u32 file_offset = dir.first_file_offset;
while (file_offset != INVALID_FIELD) {
const u8* current_file = romfs + header.file_table_offset + file_offset;
std::memcpy(&file, current_file, sizeof(file));
if (MatchName(current_file + sizeof(file), file.name_length, file_name)) {
return romfs + header.data_offset + file.data_offset;
}
file_offset = file.next_file_offset;
}
return nullptr;
}
} // namespace RomFS

View File

@@ -1,22 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <vector>
#include "common/common_types.h"
namespace RomFS {
/**
* Gets the pointer to a file in a RomFS image.
* @param romfs The pointer to the RomFS image
* @param path A vector containing the directory names and file name of the path to the file
* @return the pointer to the file
* @todo reimplement this with a full RomFS manager
*/
const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path);
} // namespace RomFS

View File

@@ -42,7 +42,7 @@ public:
{0, &IProfile::Get, "Get"},
{1, &IProfile::GetBase, "GetBase"},
{10, nullptr, "GetImageSize"},
{11, nullptr, "LoadImage"},
{11, &IProfile::LoadImage, "LoadImage"},
};
RegisterHandlers(functions);
}
@@ -83,6 +83,27 @@ private:
rb.PushRaw(profile_base);
}
void LoadImage(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
// smallest jpeg https://github.com/mathiasbynens/small/blob/master/jpeg.jpg
// TODO(mailwl): load actual profile image from disk, width 256px, max size 0x20000
const u32 jpeg_size = 107;
static const std::array<u8, jpeg_size> jpeg{
0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03,
0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04,
0x08, 0x06, 0x06, 0x05, 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a,
0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f,
0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10,
0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x11, 0x00,
0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01,
0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
};
ctx.WriteBuffer(jpeg.data(), jpeg_size);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(jpeg_size);
}
u128 user_id; ///< The user id this profile refers to.
};
@@ -119,6 +140,13 @@ private:
}
};
void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
}
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};

View File

@@ -14,6 +14,7 @@ public:
public:
explicit Interface(std::shared_ptr<Module> module, const char* name);
void GetUserCount(Kernel::HLERequestContext& ctx);
void GetUserExistence(Kernel::HLERequestContext& ctx);
void ListAllUsers(Kernel::HLERequestContext& ctx);
void ListOpenUsers(Kernel::HLERequestContext& ctx);

View File

@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetUserCount"},
{0, &ACC_SU::GetUserCount, "GetUserCount"},
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
{2, &ACC_SU::ListAllUsers, "ListAllUsers"},
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},

View File

@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetUserCount"},
{0, &ACC_U0::GetUserCount, "GetUserCount"},
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
{2, &ACC_U0::ListAllUsers, "ListAllUsers"},
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},

View File

@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetUserCount"},
{0, &ACC_U1::GetUserCount, "GetUserCount"},
{1, &ACC_U1::GetUserExistence, "GetUserExistence"},
{2, &ACC_U1::ListAllUsers, "ListAllUsers"},
{3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},

View File

@@ -136,7 +136,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
{17, nullptr, "SetControllerFirmwareUpdateSection"},
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
{19, nullptr, "SetScreenShotImageOrientation"},
{19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"},
{20, nullptr, "SetDesirableKeyboardLayout"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
@@ -254,6 +254,13 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
// TODO(Subv): Find out how AM determines the display to use, for now just create the layer
// in the Default display.

View File

@@ -83,6 +83,7 @@ private:
void LockExit(Kernel::HLERequestContext& ctx);
void UnlockExit(Kernel::HLERequestContext& ctx);
void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx);
void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);

View File

@@ -13,6 +13,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module_ = std::make_shared<Module>();
std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager);
std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
std::make_shared<APM_Sys>()->InstallAsService(service_manager);
}
} // namespace Service::APM

View File

@@ -74,6 +74,31 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
LOG_DEBUG(Service_APM, "called");
}
APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestPerformanceMode"},
{1, &APM_Sys::GetPerformanceEvent, "GetPerformanceEvent"},
{2, nullptr, "GetThrottlingState"},
{3, nullptr, "GetLastThrottlingState"},
{4, nullptr, "ClearLastThrottlingState"},
{5, nullptr, "LoadAndApplySettings"},
};
// clang-format on
RegisterHandlers(functions);
}
void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
LOG_DEBUG(Service_APM, "called");
}
} // namespace Service::APM

View File

@@ -19,4 +19,12 @@ private:
std::shared_ptr<Module> apm;
};
class APM_Sys final : public ServiceFramework<APM_Sys> {
public:
explicit APM_Sys();
private:
void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
};
} // namespace Service::APM

View File

@@ -337,6 +337,7 @@ public:
"AcquireNpadStyleSetUpdateEventHandle"},
{107, nullptr, "DisconnectNpad"},
{108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
{109, nullptr, "ActivateNpadWithRevision"},
{120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
{121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
{122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
@@ -456,7 +457,7 @@ private:
}
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
// TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
rb.Push(true);

View File

@@ -7,8 +7,8 @@
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "video_core/gpu.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
namespace Service::Nvidia::Devices {

View File

@@ -2,14 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "video_core/memory_manager.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
namespace Service::Nvidia::Devices {

View File

@@ -2,6 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstdlib>
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"

View File

@@ -5,8 +5,6 @@
#pragma once
#include <array>
#include <cstdlib>
#include <cstring>
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"

View File

@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"

View File

@@ -2,12 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <map>
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
#include "core/memory.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Service::Nvidia::Devices {
@@ -145,7 +147,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
}
params.fence_out.id = 0;
params.fence_out.value = 0;
std::memcpy(output.data(), &params, output.size());
std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
return 0;
}

View File

@@ -6,6 +6,7 @@
#include <memory>
#include <vector>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"

View File

@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"

View File

@@ -4,11 +4,9 @@
#pragma once
#include <array>
#include <cstdlib>
#include <cstring>
#include <vector>
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service::Nvidia::Devices {

View File

@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <cinttypes>
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"

View File

@@ -5,7 +5,6 @@
#pragma once
#include <memory>
#include <string>
#include "core/hle/kernel/event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"

View File

@@ -16,19 +16,18 @@
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvmemp.h"
#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service::Nvidia {
std::weak_ptr<Module> nvdrv;
void InstallInterfaces(SM::ServiceManager& service_manager) {
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger) {
auto module_ = std::make_shared<Module>();
std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:s")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:t")->InstallAsService(service_manager);
std::make_shared<NVMEMP>()->InstallAsService(service_manager);
nvdrv = module_;
nvflinger.SetNVDrvInstance(module_);
}
Module::Module() {
@@ -54,7 +53,7 @@ u32 Module::Open(const std::string& device_name) {
return fd;
}
u32 Module::Ioctl(u32 fd, u32_le command, const std::vector<u8>& input, std::vector<u8>& output) {
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = open_files.find(fd);
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");

View File

@@ -10,6 +10,10 @@
#include "common/common_types.h"
#include "core/hle/service/service.h"
namespace Service::NVFlinger {
class NVFlinger;
}
namespace Service::Nvidia {
namespace Devices {
@@ -56,8 +60,6 @@ private:
};
/// Registers all NVDRV services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
extern std::weak_ptr<Module> nvdrv;
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger);
} // namespace Service::Nvidia

View File

@@ -4,8 +4,6 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvmemp.h"
namespace Service::Nvidia {

View File

@@ -3,8 +3,11 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <boost/optional.hpp>
#include "common/alignment.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "core/core.h"
@@ -31,7 +34,7 @@ NVFlinger::NVFlinger() {
// Schedule the screen composition events
composition_event =
CoreTiming::RegisterEvent("ScreenCompositioin", [this](u64 userdata, int cycles_late) {
CoreTiming::RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
Compose();
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, composition_event);
});
@@ -43,7 +46,11 @@ NVFlinger::~NVFlinger() {
CoreTiming::UnscheduleEvent(composition_event, 0);
}
u64 NVFlinger::OpenDisplay(const std::string& name) {
void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
nvdrv = std::move(instance);
}
u64 NVFlinger::OpenDisplay(std::string_view name) {
LOG_WARNING(Service, "Opening display {}", name);
// TODO(Subv): Currently we only support the Default display.
@@ -138,9 +145,6 @@ void NVFlinger::Compose() {
auto& igbp_buffer = buffer->igbp_buffer;
// Now send the buffer to the GPU for drawing.
auto nvdrv = Nvidia::nvdrv.lock();
ASSERT(nvdrv);
// TODO(Subv): Support more than just disp0. The display device selection is probably based
// on which display we're drawing (Default, Internal, External, etc)
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");

View File

@@ -5,13 +5,21 @@
#pragma once
#include <memory>
#include <boost/optional.hpp>
#include <string>
#include <string_view>
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/event.h"
namespace CoreTiming {
struct EventType;
}
namespace Service::Nvidia {
class Module;
}
namespace Service::NVFlinger {
class BufferQueue;
@@ -40,8 +48,11 @@ public:
NVFlinger();
~NVFlinger();
/// Sets the NVDrv module instance to use to send buffers to the GPU.
void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
/// Opens the specified display and returns the id.
u64 OpenDisplay(const std::string& name);
u64 OpenDisplay(std::string_view name);
/// Creates a layer on the specified display and returns the layer id.
u64 CreateLayer(u64 display_id);
@@ -66,6 +77,8 @@ private:
/// Returns the layer identified by the specified id in the desired display.
Layer& GetLayer(u64 display_id, u64 layer_id);
std::shared_ptr<Nvidia::Module> nvdrv;
std::vector<Display> displays;
std::vector<std::shared_ptr<BufferQueue>> buffer_queues;

View File

@@ -63,6 +63,7 @@
#include "core/hle/service/spl/module.h"
#include "core/hle/service/ssl/ssl.h"
#include "core/hle/service/time/time.h"
#include "core/hle/service/usb/usb.h"
#include "core/hle/service/vi/vi.h"
#include "core/hle/service/wlan/wlan.h"
@@ -237,7 +238,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
NIFM::InstallInterfaces(*sm);
NIM::InstallInterfaces(*sm);
NS::InstallInterfaces(*sm);
Nvidia::InstallInterfaces(*sm);
Nvidia::InstallInterfaces(*sm, *nv_flinger);
PCIe::InstallInterfaces(*sm);
PCTL::InstallInterfaces(*sm);
PCV::InstallInterfaces(*sm);
@@ -249,6 +250,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
SPL::InstallInterfaces(*sm);
SSL::InstallInterfaces(*sm);
Time::InstallInterfaces(*sm);
USB::InstallInterfaces(*sm);
VI::InstallInterfaces(*sm, nv_flinger);
WLAN::InstallInterfaces(*sm);

View File

@@ -80,8 +80,8 @@ public:
{5, nullptr, "GetTimeZoneRuleVersion"},
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
{200, nullptr, "ToPosixTime"},
{201, nullptr, "ToPosixTimeWithMyRule"},
{201, nullptr, "ToPosixTime"},
{202, nullptr, "ToPosixTimeWithMyRule"},
};
RegisterHandlers(functions);
}

View File

@@ -0,0 +1,238 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <memory>
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/usb/usb.h"
namespace Service::USB {
class IDsInterface final : public ServiceFramework<IDsInterface> {
public:
explicit IDsInterface() : ServiceFramework{"IDsInterface"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetDsEndpoint"},
{1, nullptr, "GetSetupEvent"},
{2, nullptr, "Unknown"},
{3, nullptr, "EnableInterface"},
{4, nullptr, "DisableInterface"},
{5, nullptr, "CtrlInPostBufferAsync"},
{6, nullptr, "CtrlOutPostBufferAsync"},
{7, nullptr, "GetCtrlInCompletionEvent"},
{8, nullptr, "GetCtrlInReportData"},
{9, nullptr, "GetCtrlOutCompletionEvent"},
{10, nullptr, "GetCtrlOutReportData"},
{11, nullptr, "StallCtrl"},
{12, nullptr, "AppendConfigurationData"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class USB_DS final : public ServiceFramework<USB_DS> {
public:
explicit USB_DS() : ServiceFramework{"usb:ds"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "BindDevice"},
{1, nullptr, "BindClientProcess"},
{2, nullptr, "GetDsInterface"},
{3, nullptr, "GetStateChangeEvent"},
{4, nullptr, "GetState"},
{5, nullptr, "ClearDeviceData"},
{6, nullptr, "AddUsbStringDescriptor"},
{7, nullptr, "DeleteUsbStringDescriptor"},
{8, nullptr, "SetUsbDeviceDescriptor"},
{9, nullptr, "SetBinaryObjectStore"},
{10, nullptr, "Enable"},
{11, nullptr, "Disable"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class IClientEpSession final : public ServiceFramework<IClientEpSession> {
public:
explicit IClientEpSession() : ServiceFramework{"IClientEpSession"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "PostBufferAsync"},
{5, nullptr, "Unknown5"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
{8, nullptr, "Unknown8"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class IClientIfSession final : public ServiceFramework<IClientIfSession> {
public:
explicit IClientIfSession() : ServiceFramework{"IClientIfSession"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "Unknown5"},
{5, nullptr, "CtrlXferAsync"},
{6, nullptr, "Unknown6"},
{7, nullptr, "GetCtrlXferReport"},
{8, nullptr, "Unknown7"},
{9, nullptr, "GetClientEpSession"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class USB_HS final : public ServiceFramework<USB_HS> {
public:
explicit USB_HS() : ServiceFramework{"usb:hs"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "BindClientProcess"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, nullptr, "Unknown5"},
{6, nullptr, "GetInterfaceStateChangeEvent"},
{7, nullptr, "GetClientIfSession"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class IPdSession final : public ServiceFramework<IPdSession> {
public:
explicit IPdSession() : ServiceFramework{"IPdSession"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "BindNoticeEvent"},
{1, nullptr, "Unknown1"},
{2, nullptr, "GetStatus"},
{3, nullptr, "GetNotice"},
{4, nullptr, "Unknown2"},
{5, nullptr, "Unknown3"},
{6, nullptr, "ReplyPowerRequest"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class USB_PD final : public ServiceFramework<USB_PD> {
public:
explicit USB_PD() : ServiceFramework{"usb:pd"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &USB_PD::GetPdSession, "GetPdSession"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void GetPdSession(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IPdSession>();
LOG_DEBUG(Service_USB, "called");
}
};
class IPdCradleSession final : public ServiceFramework<IPdCradleSession> {
public:
explicit IPdCradleSession() : ServiceFramework{"IPdCradleSession"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "VdmUserWrite"},
{1, nullptr, "VdmUserRead"},
{2, nullptr, "Vdm20Init"},
{3, nullptr, "GetFwType"},
{4, nullptr, "GetFwRevision"},
{5, nullptr, "GetManufacturerId"},
{6, nullptr, "GetDeviceId"},
{7, nullptr, "Unknown1"},
{8, nullptr, "Unknown2"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class USB_PD_C final : public ServiceFramework<USB_PD_C> {
public:
explicit USB_PD_C() : ServiceFramework{"usb:pd:c"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void GetPdCradleSession(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IPdCradleSession>();
LOG_DEBUG(Service_USB, "called");
}
};
class USB_PM final : public ServiceFramework<USB_PM> {
public:
explicit USB_PM() : ServiceFramework{"usb:pm"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "Unknown5"},
{5, nullptr, "Unknown6"},
};
// clang-format on
RegisterHandlers(functions);
}
};
void InstallInterfaces(SM::ServiceManager& sm) {
std::make_shared<USB_DS>()->InstallAsService(sm);
std::make_shared<USB_HS>()->InstallAsService(sm);
std::make_shared<USB_PD>()->InstallAsService(sm);
std::make_shared<USB_PD_C>()->InstallAsService(sm);
std::make_shared<USB_PM>()->InstallAsService(sm);
}
} // namespace Service::USB

View File

@@ -0,0 +1,15 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
namespace Service::SM {
class ServiceManager;
}
namespace Service::USB {
void InstallInterfaces(SM::ServiceManager& sm);
} // namespace Service::USB

View File

@@ -7,6 +7,7 @@
#include "common/file_util.h"
#include "common/logging/log.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
@@ -17,8 +18,50 @@
namespace Loader {
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
: AppLoader(std::move(file)) {}
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_)
: AppLoader(std::move(file_)) {
const auto dir = file->GetContainingDirectory();
// Icon
FileSys::VirtualFile icon_file = nullptr;
for (const auto& language : FileSys::LANGUAGE_NAMES) {
icon_file = dir->GetFile("icon_" + std::string(language) + ".dat");
if (icon_file != nullptr) {
icon_data = icon_file->ReadAllBytes();
break;
}
}
if (icon_data.empty()) {
// Any png, jpeg, or bmp file
const auto& files = dir->GetFiles();
const auto icon_iter =
std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
return file->GetExtension() == "png" || file->GetExtension() == "jpg" ||
file->GetExtension() == "bmp" || file->GetExtension() == "jpeg";
});
if (icon_iter != files.end())
icon_data = (*icon_iter)->ReadAllBytes();
}
// Metadata
FileSys::VirtualFile nacp_file = dir->GetFile("control.nacp");
if (nacp_file == nullptr) {
const auto& files = dir->GetFiles();
const auto nacp_iter =
std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
return file->GetExtension() == "nacp";
});
if (nacp_iter != files.end())
nacp_file = *nacp_iter;
}
if (nacp_file != nullptr) {
FileSys::NACP nacp(nacp_file);
title_id = nacp.GetTitleId();
name = nacp.GetApplicationName();
}
}
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
FileSys::VirtualDir directory)
@@ -41,7 +84,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
if (dir == nullptr) {
if (file == nullptr)
return ResultStatus::ErrorInvalidFormat;
const FileSys::VirtualDir dir = file->GetContainingDirectory();
dir = file->GetContainingDirectory();
}
const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
@@ -105,4 +148,25 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile
return ResultStatus::Success;
}
ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector<u8>& buffer) {
if (icon_data.empty())
return ResultStatus::ErrorNotUsed;
buffer = icon_data;
return ResultStatus::Success;
}
ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program_id) {
if (name.empty())
return ResultStatus::ErrorNotUsed;
out_program_id = title_id;
return ResultStatus::Success;
}
ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& title) {
if (name.empty())
return ResultStatus::ErrorNotUsed;
title = name;
return ResultStatus::Success;
}
} // namespace Loader

View File

@@ -39,11 +39,18 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
ResultStatus ReadTitle(std::string& title) override;
private:
FileSys::ProgramMetadata metadata;
FileSys::VirtualFile romfs;
FileSys::VirtualDir dir;
std::vector<u8> icon_data;
std::string name;
u64 title_id{};
};
} // namespace Loader

View File

@@ -68,7 +68,7 @@ FileType GuessFromFilename(const std::string& name) {
return FileType::Unknown;
}
const char* GetFileTypeString(FileType type) {
std::string GetFileTypeString(FileType type) {
switch (type) {
case FileType::ELF:
return "ELF";

View File

@@ -61,7 +61,7 @@ FileType GuessFromFilename(const std::string& name);
/**
* Convert a FileType into a string which can be displayed to the user.
*/
const char* GetFileTypeString(FileType type);
std::string GetFileTypeString(FileType type);
/// Return type for functions in Loader namespace
enum class ResultStatus {

View File

@@ -77,8 +77,8 @@ ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
}
ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
if (nca == nullptr)
return ResultStatus::ErrorNotLoaded;
if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
return ResultStatus::ErrorInvalidFormat;
out_program_id = nca->GetTitleId();
return ResultStatus::Success;
}

View File

@@ -33,7 +33,6 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
~AppLoader_NCA();
@@ -41,6 +40,7 @@ public:
private:
FileSys::ProgramMetadata metadata;
FileSys::NCAHeader header;
std::unique_ptr<FileSys::NCA> nca;
std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader;
};

View File

@@ -26,7 +26,25 @@ namespace Loader {
AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
: AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
nca_loader(std::make_unique<AppLoader_NCA>(
xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {}
xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {
if (xci->GetStatus() != ResultStatus::Success)
return;
const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
return;
const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
if (romfs == nullptr)
return;
for (const auto& language : FileSys::LANGUAGE_NAMES) {
icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
if (icon_file != nullptr)
break;
}
const auto nacp_raw = romfs->GetFile("control.nacp");
if (nacp_raw == nullptr)
return;
nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
}
AppLoader_XCI::~AppLoader_XCI() = default;
@@ -71,4 +89,17 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
return nca_loader->ReadProgramId(out_program_id);
}
ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) {
if (icon_file == nullptr)
return ResultStatus::ErrorInvalidFormat;
buffer = icon_file->ReadAllBytes();
return ResultStatus::Success;
}
ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
if (nacp_file == nullptr)
return ResultStatus::ErrorInvalidFormat;
title = nacp_file->GetApplicationName();
return ResultStatus::Success;
}
} // namespace Loader

View File

@@ -33,12 +33,17 @@ public:
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
ResultStatus ReadTitle(std::string& title) override;
private:
FileSys::ProgramMetadata metadata;
std::unique_ptr<FileSys::XCI> xci;
std::unique_ptr<AppLoader_NCA> nca_loader;
FileSys::VirtualFile icon_file;
std::shared_ptr<FileSys::NACP> nacp_file;
};
} // namespace Loader

View File

@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <catch.hpp>
#include <catch2/catch.hpp>
#include <math.h>
#include "common/param_package.h"

View File

@@ -2,7 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <catch.hpp>
#include <catch2/catch.hpp>
#include <array>
#include <bitset>

View File

@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <catch.hpp>
#include <catch2/catch.hpp>
#include <glad/glad.h>
// This is not an actual test, but a work-around for issue #2183.

View File

@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <catch2/catch.hpp>
// Catch provides the main function since we've given it the
// CATCH_CONFIG_MAIN preprocessor directive.

View File

@@ -29,10 +29,10 @@ enum class BufferMethods {
};
void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) {
LOG_WARNING(HW_GPU,
"Processing method {:08X} on subchannel {} value "
"{:08X} remaining params {}",
method, subchannel, value, remaining_params);
LOG_TRACE(HW_GPU,
"Processing method {:08X} on subchannel {} value "
"{:08X} remaining params {}",
method, subchannel, value, remaining_params);
if (method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id.

View File

@@ -238,6 +238,8 @@ void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
auto& buffer = shader.const_buffers[bind_data.index];
ASSERT(bind_data.index < Regs::MaxConstBuffers);
buffer.enabled = bind_data.valid.Value() != 0;
buffer.index = bind_data.index;
buffer.address = regs.const_buffer.BufferAddress();

View File

@@ -44,7 +44,7 @@ public:
static constexpr size_t MaxShaderProgram = 6;
static constexpr size_t MaxShaderStage = 5;
// Maximum number of const buffers per shader stage.
static constexpr size_t MaxConstBuffers = 16;
static constexpr size_t MaxConstBuffers = 18;
enum class QueryMode : u32 {
Write = 0,

View File

@@ -78,6 +78,8 @@ union Attribute {
// shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
// shader.
TessCoordInstanceIDVertexID = 47,
// TODO(bunnei): Figure out what this is used for. Super Mario Odyssey uses this.
Unknown_63 = 63,
};
union {
@@ -254,20 +256,15 @@ union Instruction {
BitField<56, 1, u64> invert_b;
} lop32i;
float GetImm20_19() const {
float result{};
u32 GetImm20_19() const {
u32 imm{static_cast<u32>(imm20_19)};
imm <<= 12;
imm |= negate_imm ? 0x80000000 : 0;
std::memcpy(&result, &imm, sizeof(imm));
return result;
return imm;
}
float GetImm20_32() const {
float result{};
s32 imm{static_cast<s32>(imm20_32)};
std::memcpy(&result, &imm, sizeof(imm));
return result;
u32 GetImm20_32() const {
return static_cast<u32>(imm20_32);
}
s32 GetSignedImm20_20() const {

View File

@@ -42,6 +42,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
case RenderTargetFormat::RGB10_A2_UNORM:
case RenderTargetFormat::BGRA8_UNORM:
case RenderTargetFormat::R32_FLOAT:
case RenderTargetFormat::R11G11B10_FLOAT:
return 4;
default:
UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format));

View File

@@ -161,7 +161,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
// assume every shader uses them all.
for (unsigned index = 0; index < 16; ++index) {
auto& attrib = regs.vertex_attrib_format[index];
LOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
LOG_TRACE(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
attrib.offset.Value(), attrib.IsNormalized());
@@ -659,7 +659,10 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr
auto& buffer_draw_state =
state.draw.const_buffers[static_cast<size_t>(stage)][used_buffer.GetIndex()];
ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer");
if (!buffer.enabled) {
continue;
}
buffer_draw_state.enabled = true;
buffer_draw_state.bindpoint = current_bindpoint + bindpoint;

View File

@@ -204,8 +204,9 @@ struct SurfaceParams {
static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
switch (format) {
// TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the
// gamma.
case Tegra::RenderTargetFormat::RGBA8_SRGB:
return PixelFormat::SRGBA8;
case Tegra::RenderTargetFormat::RGBA8_UNORM:
return PixelFormat::ABGR8;
case Tegra::RenderTargetFormat::BGRA8_UNORM:

View File

@@ -523,6 +523,11 @@ private:
// shader.
ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex);
return "vec4(0, 0, uintBitsToFloat(gl_InstanceID), uintBitsToFloat(gl_VertexID))";
case Attribute::Index::Unknown_63:
// TODO(bunnei): Figure out what this is used for. Super Mario Odyssey uses this.
LOG_CRITICAL(HW_GPU, "Unhandled input attribute Unknown_63");
UNREACHABLE();
break;
default:
const u32 index{static_cast<u32>(attribute) -
static_cast<u32>(Attribute::Index::Attribute_0)};
@@ -534,6 +539,8 @@ private:
LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", index);
UNREACHABLE();
}
return "vec4(0, 0, 0, 0)";
}
/// Generates code representing an output attribute register.
@@ -602,12 +609,12 @@ private:
/// Generates code representing a 19-bit immediate value
static std::string GetImmediate19(const Instruction& instr) {
return std::to_string(instr.alu.GetImm20_19());
return fmt::format("uintBitsToFloat({})", instr.alu.GetImm20_19());
}
/// Generates code representing a 32-bit immediate value
static std::string GetImmediate32(const Instruction& instr) {
return std::to_string(instr.alu.GetImm20_32());
return fmt::format("uintBitsToFloat({})", instr.alu.GetImm20_32());
}
/// Generates code representing a texture sampler.

View File

@@ -7,6 +7,10 @@
#include <array>
#include <glad/glad.h>
#include "video_core/engines/maxwell_3d.h"
using Regs = Tegra::Engines::Maxwell3D::Regs;
namespace TextureUnits {
struct TextureUnit {
@@ -120,7 +124,7 @@ public:
GLuint bindpoint;
GLuint ssbo;
};
std::array<std::array<ConstBufferConfig, 16>, 5> const_buffers{};
std::array<std::array<ConstBufferConfig, Regs::MaxConstBuffers>, 5> const_buffers;
} draw;
struct {

View File

@@ -27,9 +27,11 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
case Maxwell::VertexAttribute::Type::UnsignedNorm: {
switch (attrib.size) {
case Maxwell::VertexAttribute::Size::Size_8_8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return GL_UNSIGNED_BYTE;
case Maxwell::VertexAttribute::Size::Size_16_16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return GL_UNSIGNED_SHORT;
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return GL_UNSIGNED_INT_2_10_10_10_REV;
@@ -84,6 +86,8 @@ inline GLenum IndexFormat(Maxwell::IndexFormat index_format) {
inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
switch (topology) {
case Maxwell::PrimitiveTopology::Points:
return GL_POINTS;
case Maxwell::PrimitiveTopology::Triangles:
return GL_TRIANGLES;
case Maxwell::PrimitiveTopology::TriangleStrip:

View File

@@ -430,7 +430,7 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
case GL_DEBUG_SEVERITY_LOW:
LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
LOG_TRACE(Render_OpenGL, format, str_source, str_type, id, message);
break;
}
}

View File

@@ -17,6 +17,8 @@ add_executable(yuzu
configuration/configure_debug.h
configuration/configure_dialog.cpp
configuration/configure_dialog.h
configuration/configure_gamelist.cpp
configuration/configure_gamelist.h
configuration/configure_general.cpp
configuration/configure_general.h
configuration/configure_graphics.cpp
@@ -59,6 +61,7 @@ set(UIS
configuration/configure.ui
configuration/configure_audio.ui
configuration/configure_debug.ui
configuration/configure_gamelist.ui
configuration/configure_general.ui
configuration/configure_graphics.ui
configuration/configure_input.ui

View File

@@ -122,6 +122,13 @@ void Config::ReadValues() {
qt_config->beginGroup("UI");
UISettings::values.theme = qt_config->value("theme", UISettings::themes[0].second).toString();
qt_config->beginGroup("UIGameList");
UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
UISettings::values.icon_size = qt_config->value("icon_size", 48).toUInt();
UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 0).toUInt();
UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 3).toUInt();
qt_config->endGroup();
qt_config->beginGroup("UILayout");
UISettings::values.geometry = qt_config->value("geometry").toByteArray();
UISettings::values.state = qt_config->value("state").toByteArray();
@@ -234,6 +241,13 @@ void Config::SaveValues() {
qt_config->beginGroup("UI");
qt_config->setValue("theme", UISettings::values.theme);
qt_config->beginGroup("UIGameList");
qt_config->setValue("show_unknown", UISettings::values.show_unknown);
qt_config->setValue("icon_size", UISettings::values.icon_size);
qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id);
qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id);
qt_config->endGroup();
qt_config->beginGroup("UILayout");
qt_config->setValue("geometry", UISettings::values.geometry);
qt_config->setValue("state", UISettings::values.state);

View File

@@ -24,6 +24,11 @@
<string>General</string>
</attribute>
</widget>
<widget class="ConfigureGameList" name="gameListTab">
<attribute name="title">
<string>Game List</string>
</attribute>
</widget>
<widget class="ConfigureSystem" name="systemTab">
<attribute name="title">
<string>System</string>
@@ -67,6 +72,12 @@
<header>configuration/configure_general.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureGameList</class>
<extends>QWidget</extends>
<header>configuration/configure_gamelist.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureSystem</class>
<extends>QWidget</extends>

View File

@@ -21,6 +21,7 @@ void ConfigureDialog::setConfiguration() {}
void ConfigureDialog::applyConfiguration() {
ui->generalTab->applyConfiguration();
ui->gameListTab->applyConfiguration();
ui->systemTab->applyConfiguration();
ui->inputTab->applyConfiguration();
ui->graphicsTab->applyConfiguration();

View File

@@ -0,0 +1,63 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_gamelist.h"
#include "ui_settings.h"
#include "yuzu/configuration/configure_gamelist.h"
ConfigureGameList::ConfigureGameList(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureGameList) {
ui->setupUi(this);
static const std::vector<std::pair<u32, std::string>> default_icon_sizes{
std::make_pair(0, "None"), std::make_pair(32, "Small"),
std::make_pair(64, "Standard"), std::make_pair(128, "Large"),
std::make_pair(256, "Full Size"),
};
for (const auto& size : default_icon_sizes) {
ui->icon_size_combobox->addItem(QString::fromStdString(size.second + " (" +
std::to_string(size.first) + "x" +
std::to_string(size.first) + ")"),
size.first);
}
static const std::vector<std::string> row_text_names{
"Filename",
"Filetype",
"Title ID",
"Title Name",
};
for (size_t i = 0; i < row_text_names.size(); ++i) {
ui->row_1_text_combobox->addItem(QString::fromStdString(row_text_names[i]),
QVariant::fromValue(i));
ui->row_2_text_combobox->addItem(QString::fromStdString(row_text_names[i]),
QVariant::fromValue(i));
}
this->setConfiguration();
}
ConfigureGameList::~ConfigureGameList() {}
void ConfigureGameList::setConfiguration() {
ui->show_unknown->setChecked(UISettings::values.show_unknown);
ui->icon_size_combobox->setCurrentIndex(
ui->icon_size_combobox->findData(UISettings::values.icon_size));
ui->row_1_text_combobox->setCurrentIndex(
ui->row_1_text_combobox->findData(UISettings::values.row_1_text_id));
ui->row_2_text_combobox->setCurrentIndex(
ui->row_2_text_combobox->findData(UISettings::values.row_2_text_id));
}
void ConfigureGameList::applyConfiguration() {
UISettings::values.show_unknown = ui->show_unknown->isChecked();
UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
Settings::Apply();
}

View File

@@ -0,0 +1,28 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QWidget>
namespace Ui {
class ConfigureGameList;
}
class ConfigureGameList : public QWidget {
Q_OBJECT
public:
explicit ConfigureGameList(QWidget* parent = nullptr);
~ConfigureGameList();
void applyConfiguration();
private:
void setConfiguration();
private:
std::unique_ptr<Ui::ConfigureGameList> ui;
};

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureGameList</class>
<widget class="QWidget" name="ConfigureGeneral">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>377</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="HorizontalLayout">
<item>
<layout class="QVBoxLayout" name="VerticalLayout">
<item>
<widget class="QGroupBox" name="GeneralGroupBox">
<property name="title">
<string>General</string>
</property>
<layout class="QHBoxLayout" name="GeneralHorizontalLayout">
<item>
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
<item>
<widget class="QCheckBox" name="show_unknown">
<property name="text">
<string>Show files with type 'Unknown'</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="IconSizeGroupBox">
<property name="title">
<string>Icon Size</string>
</property>
<layout class="QHBoxLayout" name="icon_size_qhbox_layout">
<item>
<layout class="QVBoxLayout" name="icon_size_qvbox_layout">
<item>
<layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
<item>
<widget class="QLabel" name="icon_size_label">
<property name="text">
<string>Icon Size:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="icon_size_combobox"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="RowGroupBox">
<property name="title">
<string>Row Text</string>
</property>
<layout class="QHBoxLayout" name="RowHorizontalLayout">
<item>
<layout class="QVBoxLayout" name="RowVerticalLayout">
<item>
<layout class="QHBoxLayout" name="row_1_qhbox_layout">
<item>
<widget class="QLabel" name="row_1_label">
<property name="text">
<string>Row 1 Text:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="row_1_text_combobox"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="row_2_qhbox_layout">
<item>
<widget class="QLabel" name="row_2_label">
<property name="text">
<string>Row 2 Text:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="row_2_text_combobox"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -9,9 +9,12 @@
#include <QKeyEvent>
#include <QMenu>
#include <QThreadPool>
#include <boost/container/flat_map.hpp>
#include "common/common_paths.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/vfs_real.h"
#include "core/loader/loader.h"
#include "game_list.h"
@@ -398,8 +401,32 @@ void GameList::RefreshGameDirectory() {
}
void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) {
const auto callback = [this, recursion](u64* num_entries_out, const std::string& directory,
const std::string& virtual_name) -> bool {
boost::container::flat_map<u64, std::shared_ptr<FileSys::NCA>> nca_control_map;
const auto nca_control_callback =
[this, &nca_control_map](u64* num_entries_out, const std::string& directory,
const std::string& virtual_name) -> bool {
std::string physical_name = directory + DIR_SEP + virtual_name;
if (stop_processing)
return false; // Breaks the callback loop.
bool is_dir = FileUtil::IsDirectory(physical_name);
QFileInfo file_info(physical_name.c_str());
if (!is_dir && file_info.suffix().toStdString() == "nca") {
auto nca = std::make_shared<FileSys::NCA>(
std::make_shared<FileSys::RealVfsFile>(physical_name));
if (nca->GetType() == FileSys::NCAContentType::Control)
nca_control_map.insert_or_assign(nca->GetTitleId(), nca);
}
return true;
};
FileUtil::ForeachDirectoryEntry(nullptr, dir_path, nca_control_callback);
const auto callback = [this, recursion,
&nca_control_map](u64* num_entries_out, const std::string& directory,
const std::string& virtual_name) -> bool {
std::string physical_name = directory + DIR_SEP + virtual_name;
if (stop_processing)
@@ -410,17 +437,50 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
(HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
std::unique_ptr<Loader::AppLoader> loader =
Loader::GetLoader(std::make_shared<FileSys::RealVfsFile>(physical_name));
if (!loader)
if (!loader || ((loader->GetFileType() == Loader::FileType::Unknown ||
loader->GetFileType() == Loader::FileType::Error) &&
!UISettings::values.show_unknown))
return true;
std::vector<u8> smdh;
loader->ReadIcon(smdh);
std::vector<u8> icon;
const auto res1 = loader->ReadIcon(icon);
u64 program_id = 0;
loader->ReadProgramId(program_id);
u64 program_id;
const auto res2 = loader->ReadProgramId(program_id);
std::string name = " ";
const auto res3 = loader->ReadTitle(name);
if ((res1 == Loader::ResultStatus::ErrorNotUsed ||
res1 == Loader::ResultStatus::ErrorNotImplemented) &&
(res3 == Loader::ResultStatus::ErrorNotUsed ||
res3 == Loader::ResultStatus::ErrorNotImplemented) &&
res2 == Loader::ResultStatus::Success) {
// Use from metadata pool.
if (nca_control_map.find(program_id) != nca_control_map.end()) {
const auto nca = nca_control_map[program_id];
const auto control_dir = nca->GetSubdirectories()[0];
const auto nacp_file = control_dir->GetFile("control.nacp");
FileSys::NACP nacp(nacp_file);
name = nacp.GetApplicationName();
FileSys::VirtualFile icon_file = nullptr;
for (const auto& language : FileSys::LANGUAGE_NAMES) {
icon_file = control_dir->GetFile("icon_" + std::string(language) + ".dat");
if (icon_file != nullptr) {
icon = icon_file->ReadAllBytes();
break;
}
}
}
}
emit EntryReady({
new GameListItemPath(FormatGameName(physical_name), smdh, program_id),
new GameListItemPath(
FormatGameName(physical_name), icon, QString::fromStdString(name),
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
program_id),
new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(FileUtil::GetSize(physical_name)),

View File

@@ -11,6 +11,7 @@
#include <QStandardItem>
#include <QString>
#include "common/string_util.h"
#include "ui_settings.h"
#include "yuzu/util/util.h"
/**
@@ -18,8 +19,7 @@
* @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
* @return QPixmap default icon
*/
static QPixmap GetDefaultIcon(bool large) {
int size = large ? 48 : 24;
static QPixmap GetDefaultIcon(u32 size) {
QPixmap icon(size, size);
icon.fill(Qt::transparent);
return icon;
@@ -44,11 +44,25 @@ public:
static const int FullPathRole = Qt::UserRole + 1;
static const int TitleRole = Qt::UserRole + 2;
static const int ProgramIdRole = Qt::UserRole + 3;
static const int FileTypeRole = Qt::UserRole + 4;
GameListItemPath() = default;
GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id) {
GameListItemPath(const QString& game_path, const std::vector<u8>& picture_data,
const QString& game_name, const QString& game_type, u64 program_id)
: GameListItem() {
setData(game_path, FullPathRole);
setData(game_name, TitleRole);
setData(qulonglong(program_id), ProgramIdRole);
setData(game_type, FileTypeRole);
QPixmap picture;
u32 size = UISettings::values.icon_size;
if (!picture.loadFromData(picture_data.data(), picture_data.size()))
picture = GetDefaultIcon(size);
picture = picture.scaled(size, size);
setData(picture, Qt::DecorationRole);
}
QVariant data(int role) const override {
@@ -57,7 +71,23 @@ public:
Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename,
nullptr);
QString title = data(TitleRole).toString();
return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title);
std::vector<QString> row_data{
QString::fromStdString(filename),
data(FileTypeRole).toString(),
QString::fromStdString(fmt::format("0x{:016X}", data(ProgramIdRole).toULongLong())),
data(TitleRole).toString(),
};
auto row1 = row_data.at(UISettings::values.row_1_text_id);
auto row2 = row_data.at(UISettings::values.row_2_text_id);
if (row1.isEmpty() || row1 == row2)
return row2;
if (row2.isEmpty())
return row1;
return row1 + "\n " + row2;
} else {
return GameListItem::data(role);
}

View File

@@ -768,6 +768,7 @@ void GMainWindow::OnConfigure() {
configureDialog.applyConfiguration();
if (UISettings::values.theme != old_theme)
UpdateUITheme();
game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
config->Save();
}
}

View File

@@ -54,6 +54,12 @@ struct Values {
// logging
bool show_console;
// Game List
bool show_unknown;
uint32_t icon_size;
uint8_t row_1_text_id;
uint8_t row_2_text_id;
};
extern Values values;