summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt5
-rw-r--r--src/common/assert.h5
-rw-r--r--src/common/math_util.h16
-rw-r--r--src/common/x64/xbyak_abi.h222
-rw-r--r--src/common/x64/xbyak_util.h47
-rw-r--r--src/core/file_sys/card_image.h13
-rw-r--r--src/core/hle/kernel/process.cpp1
-rw-r--r--src/core/hle/kernel/process.h1
-rw-r--r--src/core/hle/kernel/shared_memory.cpp22
-rw-r--r--src/core/hle/kernel/shared_memory.h48
-rw-r--r--src/core/hle/kernel/svc.cpp4
-rw-r--r--src/core/hle/service/am/am.cpp4
-rw-r--r--src/core/hle/service/ldr/ldr.cpp41
-rw-r--r--src/video_core/engines/maxwell_3d.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp3
15 files changed, 91 insertions, 350 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index eccd8f64a..895ee53f1 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -95,14 +95,9 @@ if(ARCHITECTURE_x86_64)
PRIVATE
x64/cpu_detect.cpp
x64/cpu_detect.h
- x64/xbyak_abi.h
- x64/xbyak_util.h
)
endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::boost fmt microprofile)
-if (ARCHITECTURE_x86_64)
- target_link_libraries(common PRIVATE xbyak)
-endif()
diff --git a/src/common/assert.h b/src/common/assert.h
index 0d4eddc19..6002f7ab1 100644
--- a/src/common/assert.h
+++ b/src/common/assert.h
@@ -52,5 +52,8 @@ __declspec(noinline, noreturn)
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...)
#endif
-#define UNIMPLEMENTED() LOG_CRITICAL(Debug, "Unimplemented code!")
+#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!")
#define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
+
+#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
+#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 343cdd902..94b4394c5 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -4,18 +4,12 @@
#pragma once
-#include <algorithm>
#include <cstdlib>
#include <type_traits>
namespace MathUtil {
-static constexpr float PI = 3.14159265f;
-
-inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1,
- unsigned length1) {
- return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
-}
+constexpr float PI = 3.14159265f;
template <class T>
struct Rectangle {
@@ -24,16 +18,16 @@ struct Rectangle {
T right{};
T bottom{};
- Rectangle() = default;
+ constexpr Rectangle() = default;
- Rectangle(T left, T top, T right, T bottom)
+ constexpr Rectangle(T left, T top, T right, T bottom)
: left(left), top(top), right(right), bottom(bottom) {}
T GetWidth() const {
- return std::abs(static_cast<typename std::make_signed<T>::type>(right - left));
+ return std::abs(static_cast<std::make_signed_t<T>>(right - left));
}
T GetHeight() const {
- return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top));
+ return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
}
Rectangle<T> TranslateX(const T x) const {
return Rectangle{left + x, top, right + x, bottom};
diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h
deleted file mode 100644
index 636a5c0f9..000000000
--- a/src/common/x64/xbyak_abi.h
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <initializer_list>
-#include <xbyak.h>
-#include "common/assert.h"
-#include "common/bit_set.h"
-
-namespace Common::X64 {
-
-inline int RegToIndex(const Xbyak::Reg& reg) {
- using Kind = Xbyak::Reg::Kind;
- ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0,
- "RegSet only support GPRs and XMM registers.");
- ASSERT_MSG(reg.getIdx() < 16, "RegSet only supports XXM0-15.");
- return reg.getIdx() + (reg.getKind() == Kind::REG ? 0 : 16);
-}
-
-inline Xbyak::Reg64 IndexToReg64(int reg_index) {
- ASSERT(reg_index < 16);
- return Xbyak::Reg64(reg_index);
-}
-
-inline Xbyak::Xmm IndexToXmm(int reg_index) {
- ASSERT(reg_index >= 16 && reg_index < 32);
- return Xbyak::Xmm(reg_index - 16);
-}
-
-inline Xbyak::Reg IndexToReg(int reg_index) {
- if (reg_index < 16) {
- return IndexToReg64(reg_index);
- } else {
- return IndexToXmm(reg_index);
- }
-}
-
-inline BitSet32 BuildRegSet(std::initializer_list<Xbyak::Reg> regs) {
- BitSet32 bits;
- for (const Xbyak::Reg& reg : regs) {
- bits[RegToIndex(reg)] = true;
- }
- return bits;
-}
-
-const BitSet32 ABI_ALL_GPRS(0x0000FFFF);
-const BitSet32 ABI_ALL_XMMS(0xFFFF0000);
-
-#ifdef _WIN32
-
-// Microsoft x64 ABI
-const Xbyak::Reg ABI_RETURN = Xbyak::util::rax;
-const Xbyak::Reg ABI_PARAM1 = Xbyak::util::rcx;
-const Xbyak::Reg ABI_PARAM2 = Xbyak::util::rdx;
-const Xbyak::Reg ABI_PARAM3 = Xbyak::util::r8;
-const Xbyak::Reg ABI_PARAM4 = Xbyak::util::r9;
-
-const BitSet32 ABI_ALL_CALLER_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rcx,
- Xbyak::util::rdx,
- Xbyak::util::r8,
- Xbyak::util::r9,
- Xbyak::util::r10,
- Xbyak::util::r11,
- // XMMs
- Xbyak::util::xmm0,
- Xbyak::util::xmm1,
- Xbyak::util::xmm2,
- Xbyak::util::xmm3,
- Xbyak::util::xmm4,
- Xbyak::util::xmm5,
-});
-
-const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rbx,
- Xbyak::util::rsi,
- Xbyak::util::rdi,
- Xbyak::util::rbp,
- Xbyak::util::r12,
- Xbyak::util::r13,
- Xbyak::util::r14,
- Xbyak::util::r15,
- // XMMs
- Xbyak::util::xmm6,
- Xbyak::util::xmm7,
- Xbyak::util::xmm8,
- Xbyak::util::xmm9,
- Xbyak::util::xmm10,
- Xbyak::util::xmm11,
- Xbyak::util::xmm12,
- Xbyak::util::xmm13,
- Xbyak::util::xmm14,
- Xbyak::util::xmm15,
-});
-
-constexpr std::size_t ABI_SHADOW_SPACE = 0x20;
-
-#else
-
-// System V x86-64 ABI
-const Xbyak::Reg ABI_RETURN = Xbyak::util::rax;
-const Xbyak::Reg ABI_PARAM1 = Xbyak::util::rdi;
-const Xbyak::Reg ABI_PARAM2 = Xbyak::util::rsi;
-const Xbyak::Reg ABI_PARAM3 = Xbyak::util::rdx;
-const Xbyak::Reg ABI_PARAM4 = Xbyak::util::rcx;
-
-const BitSet32 ABI_ALL_CALLER_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rcx,
- Xbyak::util::rdx,
- Xbyak::util::rdi,
- Xbyak::util::rsi,
- Xbyak::util::r8,
- Xbyak::util::r9,
- Xbyak::util::r10,
- Xbyak::util::r11,
- // XMMs
- Xbyak::util::xmm0,
- Xbyak::util::xmm1,
- Xbyak::util::xmm2,
- Xbyak::util::xmm3,
- Xbyak::util::xmm4,
- Xbyak::util::xmm5,
- Xbyak::util::xmm6,
- Xbyak::util::xmm7,
- Xbyak::util::xmm8,
- Xbyak::util::xmm9,
- Xbyak::util::xmm10,
- Xbyak::util::xmm11,
- Xbyak::util::xmm12,
- Xbyak::util::xmm13,
- Xbyak::util::xmm14,
- Xbyak::util::xmm15,
-});
-
-const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rbx,
- Xbyak::util::rbp,
- Xbyak::util::r12,
- Xbyak::util::r13,
- Xbyak::util::r14,
- Xbyak::util::r15,
-});
-
-constexpr std::size_t ABI_SHADOW_SPACE = 0;
-
-#endif
-
-inline void ABI_CalculateFrameSize(BitSet32 regs, std::size_t rsp_alignment,
- std::size_t needed_frame_size, s32* out_subtraction,
- s32* out_xmm_offset) {
- int count = (regs & ABI_ALL_GPRS).Count();
- rsp_alignment -= count * 8;
- std::size_t subtraction = 0;
- int xmm_count = (regs & ABI_ALL_XMMS).Count();
- if (xmm_count) {
- // If we have any XMMs to save, we must align the stack here.
- subtraction = rsp_alignment & 0xF;
- }
- subtraction += 0x10 * xmm_count;
- std::size_t xmm_base_subtraction = subtraction;
- subtraction += needed_frame_size;
- subtraction += ABI_SHADOW_SPACE;
- // Final alignment.
- rsp_alignment -= subtraction;
- subtraction += rsp_alignment & 0xF;
-
- *out_subtraction = (s32)subtraction;
- *out_xmm_offset = (s32)(subtraction - xmm_base_subtraction);
-}
-
-inline std::size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs,
- std::size_t rsp_alignment,
- std::size_t needed_frame_size = 0) {
- s32 subtraction, xmm_offset;
- ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset);
-
- for (int reg_index : (regs & ABI_ALL_GPRS)) {
- code.push(IndexToReg64(reg_index));
- }
-
- if (subtraction != 0) {
- code.sub(code.rsp, subtraction);
- }
-
- for (int reg_index : (regs & ABI_ALL_XMMS)) {
- code.movaps(code.xword[code.rsp + xmm_offset], IndexToXmm(reg_index));
- xmm_offset += 0x10;
- }
-
- return ABI_SHADOW_SPACE;
-}
-
-inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs,
- std::size_t rsp_alignment,
- std::size_t needed_frame_size = 0) {
- s32 subtraction, xmm_offset;
- ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset);
-
- for (int reg_index : (regs & ABI_ALL_XMMS)) {
- code.movaps(IndexToXmm(reg_index), code.xword[code.rsp + xmm_offset]);
- xmm_offset += 0x10;
- }
-
- if (subtraction != 0) {
- code.add(code.rsp, subtraction);
- }
-
- // GPRs need to be popped in reverse order
- for (int reg_index = 15; reg_index >= 0; reg_index--) {
- if (regs[reg_index]) {
- code.pop(IndexToReg64(reg_index));
- }
- }
-}
-
-} // namespace Common::X64
diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h
deleted file mode 100644
index 5cc8a8c76..000000000
--- a/src/common/x64/xbyak_util.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <type_traits>
-#include <xbyak.h>
-#include "common/x64/xbyak_abi.h"
-
-namespace Common::X64 {
-
-// Constants for use with cmpps/cmpss
-enum {
- CMP_EQ = 0,
- CMP_LT = 1,
- CMP_LE = 2,
- CMP_UNORD = 3,
- CMP_NEQ = 4,
- CMP_NLT = 5,
- CMP_NLE = 6,
- CMP_ORD = 7,
-};
-
-inline bool IsWithin2G(uintptr_t ref, uintptr_t target) {
- u64 distance = target - (ref + 5);
- return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
-}
-
-inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
- return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
-}
-
-template <typename T>
-inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
- static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
- std::size_t addr = reinterpret_cast<std::size_t>(f);
- if (IsWithin2G(code, addr)) {
- code.call(f);
- } else {
- // ABI_RETURN is a safe temp register to use before a call
- code.mov(ABI_RETURN, addr);
- code.call(ABI_RETURN);
- }
-}
-
-} // namespace Common::X64
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h
index 25f5914b6..a350496f7 100644
--- a/src/core/file_sys/card_image.h
+++ b/src/core/file_sys/card_image.h
@@ -32,7 +32,18 @@ enum class GamecardSize : u8 {
};
struct GamecardInfo {
- std::array<u8, 0x70> data;
+ u64_le firmware_version;
+ u32_le access_control_flags;
+ u32_le read_wait_time1;
+ u32_le read_wait_time2;
+ u32_le write_wait_time1;
+ u32_le write_wait_time2;
+ u32_le firmware_mode;
+ u32_le cup_version;
+ std::array<u8, 4> reserved1;
+ u64_le update_partition_hash;
+ u64_le cup_id;
+ std::array<u8, 0x38> reserved2;
};
static_assert(sizeof(GamecardInfo) == 0x70, "GamecardInfo has incorrect size.");
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 1412257a0..7ca538401 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <memory>
+#include <random>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 230e395ff..ada845c7f 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -8,7 +8,6 @@
#include <bitset>
#include <cstddef>
#include <memory>
-#include <random>
#include <string>
#include <vector>
#include <boost/container/static_vector.hpp>
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index a016a86b6..0494581f5 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -61,7 +61,7 @@ SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, SharedPtr<Proce
}
SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
- KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size,
+ KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, std::size_t offset, u64 size,
MemoryPermission permissions, MemoryPermission other_permissions, std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));
@@ -78,10 +78,10 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
return shared_memory;
}
-ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
+ResultCode SharedMemory::Map(Process& target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions) {
const MemoryPermission own_other_permissions =
- target_process == owner_process ? this->permissions : this->other_permissions;
+ &target_process == owner_process ? this->permissions : this->other_permissions;
// Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
@@ -106,7 +106,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
VAddr target_address = address;
// Map the memory block into the target process
- auto result = target_process->VMManager().MapMemoryBlock(
+ auto result = target_process.VMManager().MapMemoryBlock(
target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
if (result.Failed()) {
LOG_ERROR(
@@ -116,14 +116,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
return result.Code();
}
- return target_process->VMManager().ReprotectRange(target_address, size,
- ConvertPermissions(permissions));
+ return target_process.VMManager().ReprotectRange(target_address, size,
+ ConvertPermissions(permissions));
}
-ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
+ResultCode SharedMemory::Unmap(Process& target_process, VAddr address) {
// TODO(Subv): Verify what happens if the application tries to unmap an address that is not
// mapped to a SharedMemory.
- return target_process->VMManager().UnmapRange(address, size);
+ return target_process.VMManager().UnmapRange(address, size);
}
VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
@@ -132,7 +132,11 @@ VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
return static_cast<VMAPermission>(masked_permissions);
}
-u8* SharedMemory::GetPointer(u32 offset) {
+u8* SharedMemory::GetPointer(std::size_t offset) {
+ return backing_block->data() + backing_block_offset + offset;
+}
+
+const u8* SharedMemory::GetPointer(std::size_t offset) const {
return backing_block->data() + backing_block_offset + offset;
}
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 2c06bb7ce..0b48db699 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -64,7 +64,7 @@ public:
*/
static SharedPtr<SharedMemory> CreateForApplet(KernelCore& kernel,
std::shared_ptr<std::vector<u8>> heap_block,
- u32 offset, u32 size,
+ std::size_t offset, u64 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
@@ -81,6 +81,11 @@ public:
return HANDLE_TYPE;
}
+ /// Gets the size of the underlying memory block in bytes.
+ u64 GetSize() const {
+ return size;
+ }
+
/**
* Converts the specified MemoryPermission into the equivalent VMAPermission.
* @param permission The MemoryPermission to convert.
@@ -94,44 +99,51 @@ public:
* @param permissions Memory block map permissions (specified by SVC field)
* @param other_permissions Memory block map other permissions (specified by SVC field)
*/
- ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
+ ResultCode Map(Process& target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions);
/**
* Unmaps a shared memory block from the specified address in system memory
- * @param target_process Process from which to umap the memory block.
+ * @param target_process Process from which to unmap the memory block.
* @param address Address in system memory where the shared memory block is mapped
* @return Result code of the unmap operation
*/
- ResultCode Unmap(Process* target_process, VAddr address);
+ ResultCode Unmap(Process& target_process, VAddr address);
/**
* Gets a pointer to the shared memory block
* @param offset Offset from the start of the shared memory block to get pointer
- * @return Pointer to the shared memory block from the specified offset
+ * @return A pointer to the shared memory block from the specified offset
*/
- u8* GetPointer(u32 offset = 0);
+ u8* GetPointer(std::size_t offset = 0);
+
+ /**
+ * Gets a constant pointer to the shared memory block
+ * @param offset Offset from the start of the shared memory block to get pointer
+ * @return A constant pointer to the shared memory block from the specified offset
+ */
+ const u8* GetPointer(std::size_t offset = 0) const;
+
+private:
+ explicit SharedMemory(KernelCore& kernel);
+ ~SharedMemory() override;
- /// Process that created this shared memory block.
- SharedPtr<Process> owner_process;
- /// Address of shared memory block in the owner process if specified.
- VAddr base_address;
/// Backing memory for this shared memory block.
std::shared_ptr<std::vector<u8>> backing_block;
/// Offset into the backing block for this shared memory.
- std::size_t backing_block_offset;
+ std::size_t backing_block_offset = 0;
/// Size of the memory block. Page-aligned.
- u64 size;
+ u64 size = 0;
/// Permission restrictions applied to the process which created the block.
- MemoryPermission permissions;
+ MemoryPermission permissions{};
/// Permission restrictions applied to other processes mapping the block.
- MemoryPermission other_permissions;
+ MemoryPermission other_permissions{};
+ /// Process that created this shared memory block.
+ SharedPtr<Process> owner_process;
+ /// Address of shared memory block in the owner process if specified.
+ VAddr base_address = 0;
/// Name of shared memory object.
std::string name;
-
-private:
- explicit SharedMemory(KernelCore& kernel);
- ~SharedMemory() override;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 51c367de7..b8b6b4d49 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -789,7 +789,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_MEMORY_RANGE;
}
- return shared_memory->Map(current_process, addr, permissions_type, MemoryPermission::DontCare);
+ return shared_memory->Map(*current_process, addr, permissions_type, MemoryPermission::DontCare);
}
static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
@@ -819,7 +819,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
return ERR_INVALID_MEMORY_RANGE;
}
- return shared_memory->Unmap(current_process, addr);
+ return shared_memory->Unmap(*current_process, addr);
}
/// Query process memory
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9696db42b..11181a0af 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -818,8 +818,8 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
return;
}
- const auto mem_begin = shared_mem->backing_block->begin() + shared_mem->backing_block_offset;
- const auto mem_end = mem_begin + shared_mem->size;
+ const u8* mem_begin = shared_mem->GetPointer();
+ const u8* mem_end = mem_begin + shared_mem->GetSize();
std::vector<u8> memory{mem_begin, mem_end};
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index b43f1f054..7a9d0d0dd 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -16,35 +16,18 @@
namespace Service::LDR {
-namespace ErrCodes {
-enum {
- InvalidMemoryState = 51,
- InvalidNRO = 52,
- InvalidNRR = 53,
- MissingNRRHash = 54,
- MaximumNRO = 55,
- MaximumNRR = 56,
- AlreadyLoaded = 57,
- InvalidAlignment = 81,
- InvalidSize = 82,
- InvalidNROAddress = 84,
- InvalidNRRAddress = 85,
- NotInitialized = 87,
-};
-}
-
-constexpr ResultCode ERROR_INVALID_MEMORY_STATE(ErrorModule::Loader, ErrCodes::InvalidMemoryState);
-constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO);
-constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR);
-constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash);
-constexpr ResultCode ERROR_MAXIMUM_NRO(ErrorModule::Loader, ErrCodes::MaximumNRO);
-constexpr ResultCode ERROR_MAXIMUM_NRR(ErrorModule::Loader, ErrCodes::MaximumNRR);
-constexpr ResultCode ERROR_ALREADY_LOADED(ErrorModule::Loader, ErrCodes::AlreadyLoaded);
-constexpr ResultCode ERROR_INVALID_ALIGNMENT(ErrorModule::Loader, ErrCodes::InvalidAlignment);
-constexpr ResultCode ERROR_INVALID_SIZE(ErrorModule::Loader, ErrCodes::InvalidSize);
-constexpr ResultCode ERROR_INVALID_NRO_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNROAddress);
-constexpr ResultCode ERROR_INVALID_NRR_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNRRAddress);
-constexpr ResultCode ERROR_NOT_INITIALIZED(ErrorModule::Loader, ErrCodes::NotInitialized);
+constexpr ResultCode ERROR_INVALID_MEMORY_STATE{ErrorModule::Loader, 51};
+constexpr ResultCode ERROR_INVALID_NRO{ErrorModule::Loader, 52};
+constexpr ResultCode ERROR_INVALID_NRR{ErrorModule::Loader, 53};
+constexpr ResultCode ERROR_MISSING_NRR_HASH{ErrorModule::Loader, 54};
+constexpr ResultCode ERROR_MAXIMUM_NRO{ErrorModule::Loader, 55};
+constexpr ResultCode ERROR_MAXIMUM_NRR{ErrorModule::Loader, 56};
+constexpr ResultCode ERROR_ALREADY_LOADED{ErrorModule::Loader, 57};
+constexpr ResultCode ERROR_INVALID_ALIGNMENT{ErrorModule::Loader, 81};
+constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::Loader, 82};
+constexpr ResultCode ERROR_INVALID_NRO_ADDRESS{ErrorModule::Loader, 84};
+constexpr ResultCode ERROR_INVALID_NRR_ADDRESS{ErrorModule::Loader, 85};
+constexpr ResultCode ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87};
constexpr u64 MAXIMUM_LOADED_RO = 0x40;
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index a04e00ecb..2bc534be3 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -69,6 +69,15 @@ void Maxwell3D::InitializeRegisterDefaults() {
// TODO(Rodrigo): Most games do not set a point size. I think this is a case of a
// register carrying a default value. Assume it's OpenGL's default (1).
regs.point_size = 1.0f;
+
+ // TODO(bunnei): Some games do not initialize the color masks (e.g. Sonic Mania). Assuming a
+ // default of enabled fixes rendering here.
+ for (std::size_t color_mask = 0; color_mask < Regs::NumRenderTargets; color_mask++) {
+ regs.color_mask[color_mask].R.Assign(1);
+ regs.color_mask[color_mask].G.Assign(1);
+ regs.color_mask[color_mask].B.Assign(1);
+ regs.color_mask[color_mask].A.Assign(1);
+ }
}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 5fde22ad4..e8f319438 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -761,8 +761,7 @@ private:
u64 dest_num_components, u64 value_num_components, u64 dest_elem,
bool precise) {
if (reg == Register::ZeroIndex) {
- LOG_CRITICAL(HW_GPU, "Cannot set Register::ZeroIndex");
- UNREACHABLE();
+ // Setting RZ is a nop in hardware.
return;
}