summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio_core/audio_renderer.cpp40
-rw-r--r--src/audio_core/audio_renderer.h51
-rw-r--r--src/audio_core/stream.cpp1
-rw-r--r--src/audio_core/stream.h9
-rw-r--r--src/audio_core/time_stretch.h1
-rw-r--r--src/core/arm/arm_interface.h53
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp35
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h10
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp27
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h10
-rw-r--r--src/core/core_cpu.cpp3
-rw-r--r--src/core/core_cpu.h5
-rw-r--r--src/core/gdbstub/gdbstub.cpp50
-rw-r--r--src/core/hle/kernel/mutex.cpp4
-rw-r--r--src/core/hle/kernel/svc.cpp8
-rw-r--r--src/core/hle/kernel/svc_wrap.h73
-rw-r--r--src/core/hle/kernel/thread.cpp4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp5
-rw-r--r--src/core/hle/service/am/am.cpp18
-rw-r--r--src/core/hle/service/am/am.h1
-rw-r--r--src/core/hle/service/hid/hid.cpp32
-rw-r--r--src/video_core/engines/shader_bytecode.h195
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp162
-rw-r--r--src/yuzu_cmd/config.cpp4
-rw-r--r--src/yuzu_cmd/default_ini.h2
25 files changed, 582 insertions, 221 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index ed3b7defc..83b75e61f 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -3,9 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "audio_core/algorithm/interpolate.h" 5#include "audio_core/algorithm/interpolate.h"
6#include "audio_core/audio_out.h"
6#include "audio_core/audio_renderer.h" 7#include "audio_core/audio_renderer.h"
8#include "audio_core/codec.h"
7#include "common/assert.h" 9#include "common/assert.h"
8#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "core/hle/kernel/event.h"
9#include "core/memory.h" 12#include "core/memory.h"
10 13
11namespace AudioCore { 14namespace AudioCore {
@@ -13,6 +16,41 @@ namespace AudioCore {
13constexpr u32 STREAM_SAMPLE_RATE{48000}; 16constexpr u32 STREAM_SAMPLE_RATE{48000};
14constexpr u32 STREAM_NUM_CHANNELS{2}; 17constexpr u32 STREAM_NUM_CHANNELS{2};
15 18
19class AudioRenderer::VoiceState {
20public:
21 bool IsPlaying() const {
22 return is_in_use && info.play_state == PlayState::Started;
23 }
24
25 const VoiceOutStatus& GetOutStatus() const {
26 return out_status;
27 }
28
29 const VoiceInfo& GetInfo() const {
30 return info;
31 }
32
33 VoiceInfo& Info() {
34 return info;
35 }
36
37 void SetWaveIndex(std::size_t index);
38 std::vector<s16> DequeueSamples(std::size_t sample_count);
39 void UpdateState();
40 void RefreshBuffer();
41
42private:
43 bool is_in_use{};
44 bool is_refresh_pending{};
45 std::size_t wave_index{};
46 std::size_t offset{};
47 Codec::ADPCMState adpcm_state{};
48 InterpolationState interp_state{};
49 std::vector<s16> samples;
50 VoiceOutStatus out_status{};
51 VoiceInfo info{};
52};
53
16AudioRenderer::AudioRenderer(AudioRendererParameter params, 54AudioRenderer::AudioRenderer(AudioRendererParameter params,
17 Kernel::SharedPtr<Kernel::Event> buffer_event) 55 Kernel::SharedPtr<Kernel::Event> buffer_event)
18 : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { 56 : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) {
@@ -27,6 +65,8 @@ AudioRenderer::AudioRenderer(AudioRendererParameter params,
27 QueueMixedBuffer(2); 65 QueueMixedBuffer(2);
28} 66}
29 67
68AudioRenderer::~AudioRenderer() = default;
69
30u32 AudioRenderer::GetSampleRate() const { 70u32 AudioRenderer::GetSampleRate() const {
31 return worker_params.sample_rate; 71 return worker_params.sample_rate;
32} 72}
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index c8d2cd188..2c4f5ab75 100644
--- a/src/audio_core/audio_renderer.h
+++ b/src/audio_core/audio_renderer.h
@@ -8,16 +8,20 @@
8#include <memory> 8#include <memory>
9#include <vector> 9#include <vector>
10 10
11#include "audio_core/algorithm/interpolate.h"
12#include "audio_core/audio_out.h"
13#include "audio_core/codec.h"
14#include "audio_core/stream.h" 11#include "audio_core/stream.h"
12#include "common/common_funcs.h"
15#include "common/common_types.h" 13#include "common/common_types.h"
16#include "common/swap.h" 14#include "common/swap.h"
17#include "core/hle/kernel/event.h" 15#include "core/hle/kernel/object.h"
16
17namespace Kernel {
18class Event;
19}
18 20
19namespace AudioCore { 21namespace AudioCore {
20 22
23class AudioOut;
24
21enum class PlayState : u8 { 25enum class PlayState : u8 {
22 Started = 0, 26 Started = 0,
23 Stopped = 1, 27 Stopped = 1,
@@ -158,6 +162,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
158class AudioRenderer { 162class AudioRenderer {
159public: 163public:
160 AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event); 164 AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event);
165 ~AudioRenderer();
166
161 std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params); 167 std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
162 void QueueMixedBuffer(Buffer::Tag tag); 168 void QueueMixedBuffer(Buffer::Tag tag);
163 void ReleaseAndQueueBuffers(); 169 void ReleaseAndQueueBuffers();
@@ -166,45 +172,12 @@ public:
166 u32 GetMixBufferCount() const; 172 u32 GetMixBufferCount() const;
167 173
168private: 174private:
169 class VoiceState { 175 class VoiceState;
170 public:
171 bool IsPlaying() const {
172 return is_in_use && info.play_state == PlayState::Started;
173 }
174
175 const VoiceOutStatus& GetOutStatus() const {
176 return out_status;
177 }
178
179 const VoiceInfo& GetInfo() const {
180 return info;
181 }
182
183 VoiceInfo& Info() {
184 return info;
185 }
186
187 void SetWaveIndex(std::size_t index);
188 std::vector<s16> DequeueSamples(std::size_t sample_count);
189 void UpdateState();
190 void RefreshBuffer();
191
192 private:
193 bool is_in_use{};
194 bool is_refresh_pending{};
195 std::size_t wave_index{};
196 std::size_t offset{};
197 Codec::ADPCMState adpcm_state{};
198 InterpolationState interp_state{};
199 std::vector<s16> samples;
200 VoiceOutStatus out_status{};
201 VoiceInfo info{};
202 };
203 176
204 AudioRendererParameter worker_params; 177 AudioRendererParameter worker_params;
205 Kernel::SharedPtr<Kernel::Event> buffer_event; 178 Kernel::SharedPtr<Kernel::Event> buffer_event;
206 std::vector<VoiceState> voices; 179 std::vector<VoiceState> voices;
207 std::unique_ptr<AudioCore::AudioOut> audio_out; 180 std::unique_ptr<AudioOut> audio_out;
208 AudioCore::StreamPtr stream; 181 AudioCore::StreamPtr stream;
209}; 182};
210 183
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index 386f2ec66..449db2416 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -7,6 +7,7 @@
7 7
8#include "audio_core/sink.h" 8#include "audio_core/sink.h"
9#include "audio_core/sink_details.h" 9#include "audio_core/sink_details.h"
10#include "audio_core/sink_stream.h"
10#include "audio_core/stream.h" 11#include "audio_core/stream.h"
11#include "common/assert.h" 12#include "common/assert.h"
12#include "common/logging/log.h" 13#include "common/logging/log.h"
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 3a435982d..27db1112f 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -11,13 +11,16 @@
11#include <queue> 11#include <queue>
12 12
13#include "audio_core/buffer.h" 13#include "audio_core/buffer.h"
14#include "audio_core/sink_stream.h"
15#include "common/assert.h"
16#include "common/common_types.h" 14#include "common/common_types.h"
17#include "core/core_timing.h" 15
16namespace CoreTiming {
17struct EventType;
18}
18 19
19namespace AudioCore { 20namespace AudioCore {
20 21
22class SinkStream;
23
21/** 24/**
22 * Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut 25 * Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut
23 */ 26 */
diff --git a/src/audio_core/time_stretch.h b/src/audio_core/time_stretch.h
index c2286fba1..decd760f1 100644
--- a/src/audio_core/time_stretch.h
+++ b/src/audio_core/time_stretch.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <cstddef> 7#include <cstddef>
9#include <SoundTouch.h> 8#include <SoundTouch.h>
10#include "common/common_types.h" 9#include "common/common_types.h"
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 0b2af2a9b..867e34932 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -10,7 +10,7 @@
10 10
11namespace Core { 11namespace Core {
12 12
13/// Generic ARM11 CPU interface 13/// Generic ARMv8 CPU interface
14class ARM_Interface : NonCopyable { 14class ARM_Interface : NonCopyable {
15public: 15public:
16 virtual ~ARM_Interface() {} 16 virtual ~ARM_Interface() {}
@@ -19,9 +19,9 @@ public:
19 std::array<u64, 31> cpu_registers; 19 std::array<u64, 31> cpu_registers;
20 u64 sp; 20 u64 sp;
21 u64 pc; 21 u64 pc;
22 u64 cpsr; 22 u64 pstate;
23 std::array<u128, 32> fpu_registers; 23 std::array<u128, 32> vector_registers;
24 u64 fpscr; 24 u64 fpcr;
25 }; 25 };
26 26
27 /// Runs the CPU until an event happens 27 /// Runs the CPU until an event happens
@@ -69,42 +69,50 @@ public:
69 */ 69 */
70 virtual void SetReg(int index, u64 value) = 0; 70 virtual void SetReg(int index, u64 value) = 0;
71 71
72 virtual u128 GetExtReg(int index) const = 0;
73
74 virtual void SetExtReg(int index, u128 value) = 0;
75
76 /** 72 /**
77 * Gets the value of a VFP register 73 * Gets the value of a specified vector register.
78 * @param index Register index (0-31) 74 *
79 * @return Returns the value in the register 75 * @param index The index of the vector register.
76 * @return the value within the vector register.
80 */ 77 */
81 virtual u32 GetVFPReg(int index) const = 0; 78 virtual u128 GetVectorReg(int index) const = 0;
82 79
83 /** 80 /**
84 * Sets a VFP register to the given value 81 * Sets a given value into a vector register.
85 * @param index Register index (0-31) 82 *
86 * @param value Value to set register to 83 * @param index The index of the vector register.
84 * @param value The new value to place in the register.
87 */ 85 */
88 virtual void SetVFPReg(int index, u32 value) = 0; 86 virtual void SetVectorReg(int index, u128 value) = 0;
89 87
90 /** 88 /**
91 * Get the current CPSR register 89 * Get the current PSTATE register
92 * @return Returns the value of the CPSR register 90 * @return Returns the value of the PSTATE register
93 */ 91 */
94 virtual u32 GetCPSR() const = 0; 92 virtual u32 GetPSTATE() const = 0;
95 93
96 /** 94 /**
97 * Set the current CPSR register 95 * Set the current PSTATE register
98 * @param cpsr Value to set CPSR to 96 * @param pstate Value to set PSTATE to
99 */ 97 */
100 virtual void SetCPSR(u32 cpsr) = 0; 98 virtual void SetPSTATE(u32 pstate) = 0;
101 99
102 virtual VAddr GetTlsAddress() const = 0; 100 virtual VAddr GetTlsAddress() const = 0;
103 101
104 virtual void SetTlsAddress(VAddr address) = 0; 102 virtual void SetTlsAddress(VAddr address) = 0;
105 103
104 /**
105 * Gets the value within the TPIDR_EL0 (read/write software thread ID) register.
106 *
107 * @return the value within the register.
108 */
106 virtual u64 GetTPIDR_EL0() const = 0; 109 virtual u64 GetTPIDR_EL0() const = 0;
107 110
111 /**
112 * Sets a new value within the TPIDR_EL0 (read/write software thread ID) register.
113 *
114 * @param value The new value to place in the register.
115 */
108 virtual void SetTPIDR_EL0(u64 value) = 0; 116 virtual void SetTPIDR_EL0(u64 value) = 0;
109 117
110 /** 118 /**
@@ -119,6 +127,7 @@ public:
119 */ 127 */
120 virtual void LoadContext(const ThreadContext& ctx) = 0; 128 virtual void LoadContext(const ThreadContext& ctx) = 0;
121 129
130 /// Clears the exclusive monitor's state.
122 virtual void ClearExclusiveState() = 0; 131 virtual void ClearExclusiveState() = 0;
123 132
124 /// Prepare core for thread reschedule (if needed to correctly handle state) 133 /// Prepare core for thread reschedule (if needed to correctly handle state)
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 0c175d872..3f072c51f 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -194,29 +194,20 @@ void ARM_Dynarmic::SetReg(int index, u64 value) {
194 jit->SetRegister(index, value); 194 jit->SetRegister(index, value);
195} 195}
196 196
197u128 ARM_Dynarmic::GetExtReg(int index) const { 197u128 ARM_Dynarmic::GetVectorReg(int index) const {
198 return jit->GetVector(index); 198 return jit->GetVector(index);
199} 199}
200 200
201void ARM_Dynarmic::SetExtReg(int index, u128 value) { 201void ARM_Dynarmic::SetVectorReg(int index, u128 value) {
202 jit->SetVector(index, value); 202 jit->SetVector(index, value);
203} 203}
204 204
205u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const { 205u32 ARM_Dynarmic::GetPSTATE() const {
206 UNIMPLEMENTED();
207 return {};
208}
209
210void ARM_Dynarmic::SetVFPReg(int /*index*/, u32 /*value*/) {
211 UNIMPLEMENTED();
212}
213
214u32 ARM_Dynarmic::GetCPSR() const {
215 return jit->GetPstate(); 206 return jit->GetPstate();
216} 207}
217 208
218void ARM_Dynarmic::SetCPSR(u32 cpsr) { 209void ARM_Dynarmic::SetPSTATE(u32 pstate) {
219 jit->SetPstate(cpsr); 210 jit->SetPstate(pstate);
220} 211}
221 212
222u64 ARM_Dynarmic::GetTlsAddress() const { 213u64 ARM_Dynarmic::GetTlsAddress() const {
@@ -239,18 +230,18 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
239 ctx.cpu_registers = jit->GetRegisters(); 230 ctx.cpu_registers = jit->GetRegisters();
240 ctx.sp = jit->GetSP(); 231 ctx.sp = jit->GetSP();
241 ctx.pc = jit->GetPC(); 232 ctx.pc = jit->GetPC();
242 ctx.cpsr = jit->GetPstate(); 233 ctx.pstate = jit->GetPstate();
243 ctx.fpu_registers = jit->GetVectors(); 234 ctx.vector_registers = jit->GetVectors();
244 ctx.fpscr = jit->GetFpcr(); 235 ctx.fpcr = jit->GetFpcr();
245} 236}
246 237
247void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { 238void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
248 jit->SetRegisters(ctx.cpu_registers); 239 jit->SetRegisters(ctx.cpu_registers);
249 jit->SetSP(ctx.sp); 240 jit->SetSP(ctx.sp);
250 jit->SetPC(ctx.pc); 241 jit->SetPC(ctx.pc);
251 jit->SetPstate(static_cast<u32>(ctx.cpsr)); 242 jit->SetPstate(static_cast<u32>(ctx.pstate));
252 jit->SetVectors(ctx.fpu_registers); 243 jit->SetVectors(ctx.vector_registers);
253 jit->SetFpcr(static_cast<u32>(ctx.fpscr)); 244 jit->SetFpcr(static_cast<u32>(ctx.fpcr));
254} 245}
255 246
256void ARM_Dynarmic::PrepareReschedule() { 247void ARM_Dynarmic::PrepareReschedule() {
@@ -304,8 +295,8 @@ bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr va
304 295
305bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) { 296bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) {
306 return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] { 297 return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
307 Memory::Write64(vaddr, value[0]); 298 Memory::Write64(vaddr + 0, value[0]);
308 Memory::Write64(vaddr, value[1]); 299 Memory::Write64(vaddr + 8, value[1]);
309 }); 300 });
310} 301}
311 302
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index 56c60c853..e61382d3d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -29,14 +29,12 @@ public:
29 u64 GetPC() const override; 29 u64 GetPC() const override;
30 u64 GetReg(int index) const override; 30 u64 GetReg(int index) const override;
31 void SetReg(int index, u64 value) override; 31 void SetReg(int index, u64 value) override;
32 u128 GetExtReg(int index) const override; 32 u128 GetVectorReg(int index) const override;
33 void SetExtReg(int index, u128 value) override; 33 void SetVectorReg(int index, u128 value) override;
34 u32 GetVFPReg(int index) const override; 34 u32 GetPSTATE() const override;
35 void SetVFPReg(int index, u32 value) override; 35 void SetPSTATE(u32 pstate) override;
36 u32 GetCPSR() const override;
37 void Run() override; 36 void Run() override;
38 void Step() override; 37 void Step() override;
39 void SetCPSR(u32 cpsr) override;
40 VAddr GetTlsAddress() const override; 38 VAddr GetTlsAddress() const override;
41 void SetTlsAddress(VAddr address) override; 39 void SetTlsAddress(VAddr address) override;
42 void SetTPIDR_EL0(u64 value) override; 40 void SetTPIDR_EL0(u64 value) override;
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index 4e02b7cd4..e218a0b15 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -131,33 +131,24 @@ void ARM_Unicorn::SetReg(int regn, u64 val) {
131 CHECKED(uc_reg_write(uc, treg, &val)); 131 CHECKED(uc_reg_write(uc, treg, &val));
132} 132}
133 133
134u128 ARM_Unicorn::GetExtReg(int /*index*/) const { 134u128 ARM_Unicorn::GetVectorReg(int /*index*/) const {
135 UNIMPLEMENTED(); 135 UNIMPLEMENTED();
136 static constexpr u128 res{}; 136 static constexpr u128 res{};
137 return res; 137 return res;
138} 138}
139 139
140void ARM_Unicorn::SetExtReg(int /*index*/, u128 /*value*/) { 140void ARM_Unicorn::SetVectorReg(int /*index*/, u128 /*value*/) {
141 UNIMPLEMENTED(); 141 UNIMPLEMENTED();
142} 142}
143 143
144u32 ARM_Unicorn::GetVFPReg(int /*index*/) const { 144u32 ARM_Unicorn::GetPSTATE() const {
145 UNIMPLEMENTED();
146 return {};
147}
148
149void ARM_Unicorn::SetVFPReg(int /*index*/, u32 /*value*/) {
150 UNIMPLEMENTED();
151}
152
153u32 ARM_Unicorn::GetCPSR() const {
154 u64 nzcv{}; 145 u64 nzcv{};
155 CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv)); 146 CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv));
156 return static_cast<u32>(nzcv); 147 return static_cast<u32>(nzcv);
157} 148}
158 149
159void ARM_Unicorn::SetCPSR(u32 cpsr) { 150void ARM_Unicorn::SetPSTATE(u32 pstate) {
160 u64 nzcv = cpsr; 151 u64 nzcv = pstate;
161 CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv)); 152 CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv));
162} 153}
163 154
@@ -219,7 +210,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
219 210
220 CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp)); 211 CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp));
221 CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc)); 212 CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc));
222 CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.cpsr)); 213 CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
223 214
224 for (auto i = 0; i < 29; ++i) { 215 for (auto i = 0; i < 29; ++i) {
225 uregs[i] = UC_ARM64_REG_X0 + i; 216 uregs[i] = UC_ARM64_REG_X0 + i;
@@ -234,7 +225,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
234 225
235 for (int i = 0; i < 32; ++i) { 226 for (int i = 0; i < 32; ++i) {
236 uregs[i] = UC_ARM64_REG_Q0 + i; 227 uregs[i] = UC_ARM64_REG_Q0 + i;
237 tregs[i] = &ctx.fpu_registers[i]; 228 tregs[i] = &ctx.vector_registers[i];
238 } 229 }
239 230
240 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32)); 231 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
@@ -246,7 +237,7 @@ void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
246 237
247 CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp)); 238 CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp));
248 CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc)); 239 CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc));
249 CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.cpsr)); 240 CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
250 241
251 for (int i = 0; i < 29; ++i) { 242 for (int i = 0; i < 29; ++i) {
252 uregs[i] = UC_ARM64_REG_X0 + i; 243 uregs[i] = UC_ARM64_REG_X0 + i;
@@ -261,7 +252,7 @@ void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
261 252
262 for (auto i = 0; i < 32; ++i) { 253 for (auto i = 0; i < 32; ++i) {
263 uregs[i] = UC_ARM64_REG_Q0 + i; 254 uregs[i] = UC_ARM64_REG_Q0 + i;
264 tregs[i] = (void*)&ctx.fpu_registers[i]; 255 tregs[i] = (void*)&ctx.vector_registers[i];
265 } 256 }
266 257
267 CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32)); 258 CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32));
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index d6f7cf4ab..75761950b 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -22,12 +22,10 @@ public:
22 u64 GetPC() const override; 22 u64 GetPC() const override;
23 u64 GetReg(int index) const override; 23 u64 GetReg(int index) const override;
24 void SetReg(int index, u64 value) override; 24 void SetReg(int index, u64 value) override;
25 u128 GetExtReg(int index) const override; 25 u128 GetVectorReg(int index) const override;
26 void SetExtReg(int index, u128 value) override; 26 void SetVectorReg(int index, u128 value) override;
27 u32 GetVFPReg(int index) const override; 27 u32 GetPSTATE() const override;
28 void SetVFPReg(int index, u32 value) override; 28 void SetPSTATE(u32 pstate) override;
29 u32 GetCPSR() const override;
30 void SetCPSR(u32 cpsr) override;
31 VAddr GetTlsAddress() const override; 29 VAddr GetTlsAddress() const override;
32 void SetTlsAddress(VAddr address) override; 30 void SetTlsAddress(VAddr address) override;
33 void SetTPIDR_EL0(u64 value) override; 31 void SetTPIDR_EL0(u64 value) override;
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index 15d60cc8a..21568ad50 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -9,6 +9,7 @@
9#ifdef ARCHITECTURE_x86_64 9#ifdef ARCHITECTURE_x86_64
10#include "core/arm/dynarmic/arm_dynarmic.h" 10#include "core/arm/dynarmic/arm_dynarmic.h"
11#endif 11#endif
12#include "core/arm/exclusive_monitor.h"
12#include "core/arm/unicorn/arm_unicorn.h" 13#include "core/arm/unicorn/arm_unicorn.h"
13#include "core/core_cpu.h" 14#include "core/core_cpu.h"
14#include "core/core_timing.h" 15#include "core/core_timing.h"
@@ -66,6 +67,8 @@ Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
66 scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get()); 67 scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
67} 68}
68 69
70Cpu::~Cpu() = default;
71
69std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) { 72std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) {
70 if (Settings::values.use_cpu_jit) { 73 if (Settings::values.use_cpu_jit) {
71#ifdef ARCHITECTURE_x86_64 74#ifdef ARCHITECTURE_x86_64
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 1d229b42f..685532965 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -6,11 +6,10 @@
6 6
7#include <atomic> 7#include <atomic>
8#include <condition_variable> 8#include <condition_variable>
9#include <cstddef>
9#include <memory> 10#include <memory>
10#include <mutex> 11#include <mutex>
11#include <string>
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "core/arm/exclusive_monitor.h"
14 13
15namespace Kernel { 14namespace Kernel {
16class Scheduler; 15class Scheduler;
@@ -19,6 +18,7 @@ class Scheduler;
19namespace Core { 18namespace Core {
20 19
21class ARM_Interface; 20class ARM_Interface;
21class ExclusiveMonitor;
22 22
23constexpr unsigned NUM_CPU_CORES{4}; 23constexpr unsigned NUM_CPU_CORES{4};
24 24
@@ -43,6 +43,7 @@ class Cpu {
43public: 43public:
44 Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, 44 Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
45 std::shared_ptr<CpuBarrier> cpu_barrier, std::size_t core_index); 45 std::shared_ptr<CpuBarrier> cpu_barrier, std::size_t core_index);
46 ~Cpu();
46 47
47 void RunLoop(bool tight_loop = true); 48 void RunLoop(bool tight_loop = true);
48 49
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index cfaf20a88..1b04f68bf 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -65,9 +65,9 @@ constexpr u32 MSG_WAITALL = 8;
65constexpr u32 LR_REGISTER = 30; 65constexpr u32 LR_REGISTER = 30;
66constexpr u32 SP_REGISTER = 31; 66constexpr u32 SP_REGISTER = 31;
67constexpr u32 PC_REGISTER = 32; 67constexpr u32 PC_REGISTER = 32;
68constexpr u32 CPSR_REGISTER = 33; 68constexpr u32 PSTATE_REGISTER = 33;
69constexpr u32 UC_ARM64_REG_Q0 = 34; 69constexpr u32 UC_ARM64_REG_Q0 = 34;
70constexpr u32 FPSCR_REGISTER = 66; 70constexpr u32 FPCR_REGISTER = 66;
71 71
72// TODO/WiP - Used while working on support for FPU 72// TODO/WiP - Used while working on support for FPU
73constexpr u32 TODO_DUMMY_REG_997 = 997; 73constexpr u32 TODO_DUMMY_REG_997 = 997;
@@ -116,7 +116,7 @@ constexpr char target_xml[] =
116 116
117 <reg name="pc" bitsize="64" type="code_ptr"/> 117 <reg name="pc" bitsize="64" type="code_ptr"/>
118 118
119 <flags id="cpsr_flags" size="4"> 119 <flags id="pstate_flags" size="4">
120 <field name="SP" start="0" end="0"/> 120 <field name="SP" start="0" end="0"/>
121 <field name="" start="1" end="1"/> 121 <field name="" start="1" end="1"/>
122 <field name="EL" start="2" end="3"/> 122 <field name="EL" start="2" end="3"/>
@@ -135,7 +135,7 @@ constexpr char target_xml[] =
135 <field name="Z" start="30" end="30"/> 135 <field name="Z" start="30" end="30"/>
136 <field name="N" start="31" end="31"/> 136 <field name="N" start="31" end="31"/>
137 </flags> 137 </flags>
138 <reg name="cpsr" bitsize="32" type="cpsr_flags"/> 138 <reg name="pstate" bitsize="32" type="pstate_flags"/>
139 </feature> 139 </feature>
140 <feature name="org.gnu.gdb.aarch64.fpu"> 140 <feature name="org.gnu.gdb.aarch64.fpu">
141 </feature> 141 </feature>
@@ -227,10 +227,10 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
227 return thread->context.sp; 227 return thread->context.sp;
228 } else if (id == PC_REGISTER) { 228 } else if (id == PC_REGISTER) {
229 return thread->context.pc; 229 return thread->context.pc;
230 } else if (id == CPSR_REGISTER) { 230 } else if (id == PSTATE_REGISTER) {
231 return thread->context.cpsr; 231 return thread->context.pstate;
232 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { 232 } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) {
233 return thread->context.fpu_registers[id - UC_ARM64_REG_Q0][0]; 233 return thread->context.vector_registers[id - UC_ARM64_REG_Q0][0];
234 } else { 234 } else {
235 return 0; 235 return 0;
236 } 236 }
@@ -247,10 +247,10 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
247 thread->context.sp = val; 247 thread->context.sp = val;
248 } else if (id == PC_REGISTER) { 248 } else if (id == PC_REGISTER) {
249 thread->context.pc = val; 249 thread->context.pc = val;
250 } else if (id == CPSR_REGISTER) { 250 } else if (id == PSTATE_REGISTER) {
251 thread->context.cpsr = val; 251 thread->context.pstate = val;
252 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { 252 } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) {
253 thread->context.fpu_registers[id - (CPSR_REGISTER + 1)][0] = val; 253 thread->context.vector_registers[id - (PSTATE_REGISTER + 1)][0] = val;
254 } 254 }
255} 255}
256 256
@@ -781,11 +781,11 @@ static void ReadRegister() {
781 LongToGdbHex(reply, RegRead(id, current_thread)); 781 LongToGdbHex(reply, RegRead(id, current_thread));
782 } else if (id == PC_REGISTER) { 782 } else if (id == PC_REGISTER) {
783 LongToGdbHex(reply, RegRead(id, current_thread)); 783 LongToGdbHex(reply, RegRead(id, current_thread));
784 } else if (id == CPSR_REGISTER) { 784 } else if (id == PSTATE_REGISTER) {
785 IntToGdbHex(reply, (u32)RegRead(id, current_thread)); 785 IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread)));
786 } else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) { 786 } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
787 LongToGdbHex(reply, RegRead(id, current_thread)); 787 LongToGdbHex(reply, RegRead(id, current_thread));
788 } else if (id == FPSCR_REGISTER) { 788 } else if (id == FPCR_REGISTER) {
789 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread)); 789 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread));
790 } else { 790 } else {
791 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread)); 791 LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread));
@@ -811,7 +811,7 @@ static void ReadRegisters() {
811 811
812 bufptr += 16; 812 bufptr += 16;
813 813
814 IntToGdbHex(bufptr, (u32)RegRead(CPSR_REGISTER, current_thread)); 814 IntToGdbHex(bufptr, static_cast<u32>(RegRead(PSTATE_REGISTER, current_thread)));
815 815
816 bufptr += 8; 816 bufptr += 8;
817 817
@@ -843,11 +843,11 @@ static void WriteRegister() {
843 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); 843 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
844 } else if (id == PC_REGISTER) { 844 } else if (id == PC_REGISTER) {
845 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); 845 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
846 } else if (id == CPSR_REGISTER) { 846 } else if (id == PSTATE_REGISTER) {
847 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread); 847 RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
848 } else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) { 848 } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
849 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); 849 RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
850 } else if (id == FPSCR_REGISTER) { 850 } else if (id == FPCR_REGISTER) {
851 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread); 851 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread);
852 } else { 852 } else {
853 RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread); 853 RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread);
@@ -866,16 +866,16 @@ static void WriteRegisters() {
866 if (command_buffer[0] != 'G') 866 if (command_buffer[0] != 'G')
867 return SendReply("E01"); 867 return SendReply("E01");
868 868
869 for (u32 i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) { 869 for (u32 i = 0, reg = 0; reg <= FPCR_REGISTER; i++, reg++) {
870 if (reg <= SP_REGISTER) { 870 if (reg <= SP_REGISTER) {
871 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); 871 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
872 } else if (reg == PC_REGISTER) { 872 } else if (reg == PC_REGISTER) {
873 RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); 873 RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
874 } else if (reg == CPSR_REGISTER) { 874 } else if (reg == PSTATE_REGISTER) {
875 RegWrite(CPSR_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread); 875 RegWrite(PSTATE_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread);
876 } else if (reg >= UC_ARM64_REG_Q0 && reg < FPSCR_REGISTER) { 876 } else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) {
877 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); 877 RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
878 } else if (reg == FPSCR_REGISTER) { 878 } else if (reg == FPCR_REGISTER) {
879 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread); 879 RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread);
880 } else { 880 } else {
881 UNIMPLEMENTED(); 881 UNIMPLEMENTED();
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 36bf0b677..51f4544be 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -62,7 +62,7 @@ ResultCode Mutex::TryAcquire(HandleTable& handle_table, VAddr address, Handle ho
62 Handle requesting_thread_handle) { 62 Handle requesting_thread_handle) {
63 // The mutex address must be 4-byte aligned 63 // The mutex address must be 4-byte aligned
64 if ((address % sizeof(u32)) != 0) { 64 if ((address % sizeof(u32)) != 0) {
65 return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); 65 return ERR_INVALID_ADDRESS;
66 } 66 }
67 67
68 SharedPtr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); 68 SharedPtr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle);
@@ -100,7 +100,7 @@ ResultCode Mutex::TryAcquire(HandleTable& handle_table, VAddr address, Handle ho
100ResultCode Mutex::Release(VAddr address) { 100ResultCode Mutex::Release(VAddr address) {
101 // The mutex address must be 4-byte aligned 101 // The mutex address must be 4-byte aligned
102 if ((address % sizeof(u32)) != 0) { 102 if ((address % sizeof(u32)) != 0) {
103 return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); 103 return ERR_INVALID_ADDRESS;
104 } 104 }
105 105
106 auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); 106 auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address);
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index c5c1697ee..371fc439e 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -280,6 +280,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
280 "requesting_current_thread_handle=0x{:08X}", 280 "requesting_current_thread_handle=0x{:08X}",
281 holding_thread_handle, mutex_addr, requesting_thread_handle); 281 holding_thread_handle, mutex_addr, requesting_thread_handle);
282 282
283 if (Memory::IsKernelVirtualAddress(mutex_addr)) {
284 return ERR_INVALID_ADDRESS_STATE;
285 }
286
283 auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); 287 auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
284 return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle, 288 return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
285 requesting_thread_handle); 289 requesting_thread_handle);
@@ -289,6 +293,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
289static ResultCode ArbitrateUnlock(VAddr mutex_addr) { 293static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
290 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr); 294 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr);
291 295
296 if (Memory::IsKernelVirtualAddress(mutex_addr)) {
297 return ERR_INVALID_ADDRESS_STATE;
298 }
299
292 return Mutex::Release(mutex_addr); 300 return Mutex::Release(mutex_addr);
293} 301}
294 302
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 1eda5f879..fea9ba5ea 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -13,7 +13,9 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16#define PARAM(n) Core::CurrentArmInterface().GetReg(n) 16static inline u64 Param(int n) {
17 return Core::CurrentArmInterface().GetReg(n);
18}
17 19
18/** 20/**
19 * HLE a function return from the current ARM userland process 21 * HLE a function return from the current ARM userland process
@@ -28,23 +30,23 @@ static inline void FuncReturn(u64 res) {
28 30
29template <ResultCode func(u64)> 31template <ResultCode func(u64)>
30void SvcWrap() { 32void SvcWrap() {
31 FuncReturn(func(PARAM(0)).raw); 33 FuncReturn(func(Param(0)).raw);
32} 34}
33 35
34template <ResultCode func(u32)> 36template <ResultCode func(u32)>
35void SvcWrap() { 37void SvcWrap() {
36 FuncReturn(func((u32)PARAM(0)).raw); 38 FuncReturn(func((u32)Param(0)).raw);
37} 39}
38 40
39template <ResultCode func(u32, u32)> 41template <ResultCode func(u32, u32)>
40void SvcWrap() { 42void SvcWrap() {
41 FuncReturn(func((u32)PARAM(0), (u32)PARAM(1)).raw); 43 FuncReturn(func((u32)Param(0), (u32)Param(1)).raw);
42} 44}
43 45
44template <ResultCode func(u32*, u32)> 46template <ResultCode func(u32*, u32)>
45void SvcWrap() { 47void SvcWrap() {
46 u32 param_1 = 0; 48 u32 param_1 = 0;
47 u32 retval = func(&param_1, (u32)PARAM(1)).raw; 49 u32 retval = func(&param_1, (u32)Param(1)).raw;
48 Core::CurrentArmInterface().SetReg(1, param_1); 50 Core::CurrentArmInterface().SetReg(1, param_1);
49 FuncReturn(retval); 51 FuncReturn(retval);
50} 52}
@@ -52,39 +54,39 @@ void SvcWrap() {
52template <ResultCode func(u32*, u64)> 54template <ResultCode func(u32*, u64)>
53void SvcWrap() { 55void SvcWrap() {
54 u32 param_1 = 0; 56 u32 param_1 = 0;
55 u32 retval = func(&param_1, PARAM(1)).raw; 57 u32 retval = func(&param_1, Param(1)).raw;
56 Core::CurrentArmInterface().SetReg(1, param_1); 58 Core::CurrentArmInterface().SetReg(1, param_1);
57 FuncReturn(retval); 59 FuncReturn(retval);
58} 60}
59 61
60template <ResultCode func(u64, s32)> 62template <ResultCode func(u64, s32)>
61void SvcWrap() { 63void SvcWrap() {
62 FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); 64 FuncReturn(func(Param(0), (s32)Param(1)).raw);
63} 65}
64 66
65template <ResultCode func(u64*, u64)> 67template <ResultCode func(u64*, u64)>
66void SvcWrap() { 68void SvcWrap() {
67 u64 param_1 = 0; 69 u64 param_1 = 0;
68 u32 retval = func(&param_1, PARAM(1)).raw; 70 u32 retval = func(&param_1, Param(1)).raw;
69 Core::CurrentArmInterface().SetReg(1, param_1); 71 Core::CurrentArmInterface().SetReg(1, param_1);
70 FuncReturn(retval); 72 FuncReturn(retval);
71} 73}
72 74
73template <ResultCode func(u32, u64)> 75template <ResultCode func(u32, u64)>
74void SvcWrap() { 76void SvcWrap() {
75 FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), PARAM(1)).raw); 77 FuncReturn(func((u32)(Param(0) & 0xFFFFFFFF), Param(1)).raw);
76} 78}
77 79
78template <ResultCode func(u32, u32, u64)> 80template <ResultCode func(u32, u32, u64)>
79void SvcWrap() { 81void SvcWrap() {
80 FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), (u32)(PARAM(1) & 0xFFFFFFFF), PARAM(2)).raw); 82 FuncReturn(func((u32)(Param(0) & 0xFFFFFFFF), (u32)(Param(1) & 0xFFFFFFFF), Param(2)).raw);
81} 83}
82 84
83template <ResultCode func(u32, u32*, u64*)> 85template <ResultCode func(u32, u32*, u64*)>
84void SvcWrap() { 86void SvcWrap() {
85 u32 param_1 = 0; 87 u32 param_1 = 0;
86 u64 param_2 = 0; 88 u64 param_2 = 0;
87 ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2); 89 ResultCode retval = func((u32)(Param(2) & 0xFFFFFFFF), &param_1, &param_2);
88 Core::CurrentArmInterface().SetReg(1, param_1); 90 Core::CurrentArmInterface().SetReg(1, param_1);
89 Core::CurrentArmInterface().SetReg(2, param_2); 91 Core::CurrentArmInterface().SetReg(2, param_2);
90 FuncReturn(retval.raw); 92 FuncReturn(retval.raw);
@@ -93,46 +95,46 @@ void SvcWrap() {
93template <ResultCode func(u64, u64, u32, u32)> 95template <ResultCode func(u64, u64, u32, u32)>
94void SvcWrap() { 96void SvcWrap() {
95 FuncReturn( 97 FuncReturn(
96 func(PARAM(0), PARAM(1), (u32)(PARAM(3) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw); 98 func(Param(0), Param(1), (u32)(Param(3) & 0xFFFFFFFF), (u32)(Param(3) & 0xFFFFFFFF)).raw);
97} 99}
98 100
99template <ResultCode func(u32, u64, u32)> 101template <ResultCode func(u32, u64, u32)>
100void SvcWrap() { 102void SvcWrap() {
101 FuncReturn(func((u32)PARAM(0), PARAM(1), (u32)PARAM(2)).raw); 103 FuncReturn(func((u32)Param(0), Param(1), (u32)Param(2)).raw);
102} 104}
103 105
104template <ResultCode func(u64, u64, u64)> 106template <ResultCode func(u64, u64, u64)>
105void SvcWrap() { 107void SvcWrap() {
106 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2)).raw); 108 FuncReturn(func(Param(0), Param(1), Param(2)).raw);
107} 109}
108 110
109template <ResultCode func(u32, u64, u64, u32)> 111template <ResultCode func(u32, u64, u64, u32)>
110void SvcWrap() { 112void SvcWrap() {
111 FuncReturn(func((u32)PARAM(0), PARAM(1), PARAM(2), (u32)PARAM(3)).raw); 113 FuncReturn(func((u32)Param(0), Param(1), Param(2), (u32)Param(3)).raw);
112} 114}
113 115
114template <ResultCode func(u32, u64, u64)> 116template <ResultCode func(u32, u64, u64)>
115void SvcWrap() { 117void SvcWrap() {
116 FuncReturn(func((u32)PARAM(0), PARAM(1), PARAM(2)).raw); 118 FuncReturn(func((u32)Param(0), Param(1), Param(2)).raw);
117} 119}
118 120
119template <ResultCode func(u32*, u64, u64, s64)> 121template <ResultCode func(u32*, u64, u64, s64)>
120void SvcWrap() { 122void SvcWrap() {
121 u32 param_1 = 0; 123 u32 param_1 = 0;
122 ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)); 124 ResultCode retval = func(&param_1, Param(1), (u32)(Param(2) & 0xFFFFFFFF), (s64)Param(3));
123 Core::CurrentArmInterface().SetReg(1, param_1); 125 Core::CurrentArmInterface().SetReg(1, param_1);
124 FuncReturn(retval.raw); 126 FuncReturn(retval.raw);
125} 127}
126 128
127template <ResultCode func(u64, u64, u32, s64)> 129template <ResultCode func(u64, u64, u32, s64)>
128void SvcWrap() { 130void SvcWrap() {
129 FuncReturn(func(PARAM(0), PARAM(1), (u32)PARAM(2), (s64)PARAM(3)).raw); 131 FuncReturn(func(Param(0), Param(1), (u32)Param(2), (s64)Param(3)).raw);
130} 132}
131 133
132template <ResultCode func(u64*, u64, u64, u64)> 134template <ResultCode func(u64*, u64, u64, u64)>
133void SvcWrap() { 135void SvcWrap() {
134 u64 param_1 = 0; 136 u64 param_1 = 0;
135 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3)).raw; 137 u32 retval = func(&param_1, Param(1), Param(2), Param(3)).raw;
136 Core::CurrentArmInterface().SetReg(1, param_1); 138 Core::CurrentArmInterface().SetReg(1, param_1);
137 FuncReturn(retval); 139 FuncReturn(retval);
138} 140}
@@ -141,7 +143,7 @@ template <ResultCode func(u32*, u64, u64, u64, u32, s32)>
141void SvcWrap() { 143void SvcWrap() {
142 u32 param_1 = 0; 144 u32 param_1 = 0;
143 u32 retval = 145 u32 retval =
144 func(&param_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF)) 146 func(&param_1, Param(1), Param(2), Param(3), (u32)Param(4), (s32)(Param(5) & 0xFFFFFFFF))
145 .raw; 147 .raw;
146 Core::CurrentArmInterface().SetReg(1, param_1); 148 Core::CurrentArmInterface().SetReg(1, param_1);
147 FuncReturn(retval); 149 FuncReturn(retval);
@@ -151,13 +153,13 @@ template <ResultCode func(MemoryInfo*, PageInfo*, u64)>
151void SvcWrap() { 153void SvcWrap() {
152 MemoryInfo memory_info = {}; 154 MemoryInfo memory_info = {};
153 PageInfo page_info = {}; 155 PageInfo page_info = {};
154 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; 156 u32 retval = func(&memory_info, &page_info, Param(2)).raw;
155 157
156 Memory::Write64(PARAM(0), memory_info.base_address); 158 Memory::Write64(Param(0), memory_info.base_address);
157 Memory::Write64(PARAM(0) + 8, memory_info.size); 159 Memory::Write64(Param(0) + 8, memory_info.size);
158 Memory::Write32(PARAM(0) + 16, memory_info.type); 160 Memory::Write32(Param(0) + 16, memory_info.type);
159 Memory::Write32(PARAM(0) + 20, memory_info.attributes); 161 Memory::Write32(Param(0) + 20, memory_info.attributes);
160 Memory::Write32(PARAM(0) + 24, memory_info.permission); 162 Memory::Write32(Param(0) + 24, memory_info.permission);
161 163
162 FuncReturn(retval); 164 FuncReturn(retval);
163} 165}
@@ -165,7 +167,7 @@ void SvcWrap() {
165template <ResultCode func(u32*, u64, u64, u32)> 167template <ResultCode func(u32*, u64, u64, u32)>
166void SvcWrap() { 168void SvcWrap() {
167 u32 param_1 = 0; 169 u32 param_1 = 0;
168 u32 retval = func(&param_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; 170 u32 retval = func(&param_1, Param(1), Param(2), (u32)(Param(3) & 0xFFFFFFFF)).raw;
169 Core::CurrentArmInterface().SetReg(1, param_1); 171 Core::CurrentArmInterface().SetReg(1, param_1);
170 FuncReturn(retval); 172 FuncReturn(retval);
171} 173}
@@ -174,7 +176,7 @@ template <ResultCode func(Handle*, u64, u32, u32)>
174void SvcWrap() { 176void SvcWrap() {
175 u32 param_1 = 0; 177 u32 param_1 = 0;
176 u32 retval = 178 u32 retval =
177 func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; 179 func(&param_1, Param(1), (u32)(Param(2) & 0xFFFFFFFF), (u32)(Param(3) & 0xFFFFFFFF)).raw;
178 Core::CurrentArmInterface().SetReg(1, param_1); 180 Core::CurrentArmInterface().SetReg(1, param_1);
179 FuncReturn(retval); 181 FuncReturn(retval);
180} 182}
@@ -182,14 +184,14 @@ void SvcWrap() {
182template <ResultCode func(u64, u32, s32, s64)> 184template <ResultCode func(u64, u32, s32, s64)>
183void SvcWrap() { 185void SvcWrap() {
184 FuncReturn( 186 FuncReturn(
185 func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)) 187 func(Param(0), (u32)(Param(1) & 0xFFFFFFFF), (s32)(Param(2) & 0xFFFFFFFF), (s64)Param(3))
186 .raw); 188 .raw);
187} 189}
188 190
189template <ResultCode func(u64, u32, s32, s32)> 191template <ResultCode func(u64, u32, s32, s32)>
190void SvcWrap() { 192void SvcWrap() {
191 FuncReturn(func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), 193 FuncReturn(func(Param(0), (u32)(Param(1) & 0xFFFFFFFF), (s32)(Param(2) & 0xFFFFFFFF),
192 (s32)(PARAM(3) & 0xFFFFFFFF)) 194 (s32)(Param(3) & 0xFFFFFFFF))
193 .raw); 195 .raw);
194} 196}
195 197
@@ -219,20 +221,17 @@ void SvcWrap() {
219 221
220template <void func(s64)> 222template <void func(s64)>
221void SvcWrap() { 223void SvcWrap() {
222 func((s64)PARAM(0)); 224 func((s64)Param(0));
223} 225}
224 226
225template <void func(u64, u64 len)> 227template <void func(u64, u64 len)>
226void SvcWrap() { 228void SvcWrap() {
227 func(PARAM(0), PARAM(1)); 229 func(Param(0), Param(1));
228} 230}
229 231
230template <void func(u64, u64, u64)> 232template <void func(u64, u64, u64)>
231void SvcWrap() { 233void SvcWrap() {
232 func(PARAM(0), PARAM(1), PARAM(2)); 234 func(Param(0), Param(1), Param(2));
233} 235}
234 236
235#undef PARAM
236#undef FuncReturn
237
238} // namespace Kernel 237} // namespace Kernel
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 89cd5f401..d4183d6e3 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -217,8 +217,8 @@ static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAdd
217 context.cpu_registers[0] = arg; 217 context.cpu_registers[0] = arg;
218 context.pc = entry_point; 218 context.pc = entry_point;
219 context.sp = stack_top; 219 context.sp = stack_top;
220 context.cpsr = 0; 220 context.pstate = 0;
221 context.fpscr = 0; 221 context.fpcr = 0;
222} 222}
223 223
224ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point, 224ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point,
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 0071ca613..bcb3475db 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -25,7 +25,7 @@ const UUID& UUID::Generate() {
25ProfileManager::ProfileManager() { 25ProfileManager::ProfileManager() {
26 // TODO(ogniK): Create the default user we have for now until loading/saving users is added 26 // TODO(ogniK): Create the default user we have for now until loading/saving users is added
27 auto user_uuid = UUID{1, 0}; 27 auto user_uuid = UUID{1, 0};
28 CreateNewUser(user_uuid, Settings::values.username); 28 ASSERT(CreateNewUser(user_uuid, Settings::values.username).IsSuccess());
29 OpenUser(user_uuid); 29 OpenUser(user_uuid);
30} 30}
31 31
@@ -91,7 +91,8 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& usern
91/// specifically by allowing an std::string for the username. This is required specifically since 91/// specifically by allowing an std::string for the username. This is required specifically since
92/// we're loading a string straight from the config 92/// we're loading a string straight from the config
93ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) { 93ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) {
94 ProfileUsername username_output; 94 ProfileUsername username_output{};
95
95 if (username.size() > username_output.size()) { 96 if (username.size() > username_output.size()) {
96 std::copy_n(username.begin(), username_output.size(), username_output.begin()); 97 std::copy_n(username.begin(), username_output.size(), username_output.begin());
97 } else { 98 } else {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d1f7007ec..9c975325a 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -20,6 +20,7 @@
20#include "core/hle/service/nvflinger/nvflinger.h" 20#include "core/hle/service/nvflinger/nvflinger.h"
21#include "core/hle/service/pm/pm.h" 21#include "core/hle/service/pm/pm.h"
22#include "core/hle/service/set/set.h" 22#include "core/hle/service/set/set.h"
23#include "core/hle/service/vi/vi.h"
23#include "core/settings.h" 24#include "core/settings.h"
24 25
25namespace Service::AM { 26namespace Service::AM {
@@ -334,7 +335,7 @@ ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter"
334 {51, nullptr, "SetVrModeEnabled"}, 335 {51, nullptr, "SetVrModeEnabled"},
335 {52, nullptr, "SwitchLcdBacklight"}, 336 {52, nullptr, "SwitchLcdBacklight"},
336 {55, nullptr, "IsInControllerFirmwareUpdateSection"}, 337 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
337 {60, nullptr, "GetDefaultDisplayResolution"}, 338 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
338 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, 339 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent,
339 "GetDefaultDisplayResolutionChangeEvent"}, 340 "GetDefaultDisplayResolutionChangeEvent"},
340 {62, nullptr, "GetHdcpAuthenticationState"}, 341 {62, nullptr, "GetHdcpAuthenticationState"},
@@ -393,6 +394,21 @@ void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLEReque
393 LOG_WARNING(Service_AM, "(STUBBED) called"); 394 LOG_WARNING(Service_AM, "(STUBBED) called");
394} 395}
395 396
397void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) {
398 IPC::ResponseBuilder rb{ctx, 4};
399 rb.Push(RESULT_SUCCESS);
400
401 if (Settings::values.use_docked_mode) {
402 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
403 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
404 } else {
405 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
406 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
407 }
408
409 LOG_DEBUG(Service_AM, "called");
410}
411
396void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { 412void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
397 const bool use_docked_mode{Settings::values.use_docked_mode}; 413 const bool use_docked_mode{Settings::values.use_docked_mode};
398 IPC::ResponseBuilder rb{ctx, 3}; 414 IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index fd9ae296b..b39b0d838 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -123,6 +123,7 @@ private:
123 void GetOperationMode(Kernel::HLERequestContext& ctx); 123 void GetOperationMode(Kernel::HLERequestContext& ctx);
124 void GetPerformanceMode(Kernel::HLERequestContext& ctx); 124 void GetPerformanceMode(Kernel::HLERequestContext& ctx);
125 void GetBootMode(Kernel::HLERequestContext& ctx); 125 void GetBootMode(Kernel::HLERequestContext& ctx);
126 void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
126 127
127 Kernel::SharedPtr<Kernel::Event> event; 128 Kernel::SharedPtr<Kernel::Event> event;
128}; 129};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ab2f17db9..256c49bfc 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -313,7 +313,7 @@ public:
313 {64, nullptr, "DeactivateJoySixAxisSensor"}, 313 {64, nullptr, "DeactivateJoySixAxisSensor"},
314 {65, nullptr, "GetJoySixAxisSensorLifoHandle"}, 314 {65, nullptr, "GetJoySixAxisSensorLifoHandle"},
315 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"}, 315 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
316 {67, nullptr, "StopSixAxisSensor"}, 316 {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
317 {68, nullptr, "IsSixAxisSensorFusionEnabled"}, 317 {68, nullptr, "IsSixAxisSensorFusionEnabled"},
318 {69, nullptr, "EnableSixAxisSensorFusion"}, 318 {69, nullptr, "EnableSixAxisSensorFusion"},
319 {70, nullptr, "SetSixAxisSensorFusionParameters"}, 319 {70, nullptr, "SetSixAxisSensorFusionParameters"},
@@ -329,7 +329,7 @@ public:
329 {80, nullptr, "GetGyroscopeZeroDriftMode"}, 329 {80, nullptr, "GetGyroscopeZeroDriftMode"},
330 {81, nullptr, "ResetGyroscopeZeroDriftMode"}, 330 {81, nullptr, "ResetGyroscopeZeroDriftMode"},
331 {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"}, 331 {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
332 {91, nullptr, "ActivateGesture"}, 332 {91, &Hid::ActivateGesture, "ActivateGesture"},
333 {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, 333 {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
334 {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"}, 334 {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
335 {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"}, 335 {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
@@ -364,8 +364,8 @@ public:
364 {208, nullptr, "GetActualVibrationGcErmCommand"}, 364 {208, nullptr, "GetActualVibrationGcErmCommand"},
365 {209, nullptr, "BeginPermitVibrationSession"}, 365 {209, nullptr, "BeginPermitVibrationSession"},
366 {210, nullptr, "EndPermitVibrationSession"}, 366 {210, nullptr, "EndPermitVibrationSession"},
367 {300, nullptr, "ActivateConsoleSixAxisSensor"}, 367 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
368 {301, nullptr, "StartConsoleSixAxisSensor"}, 368 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
369 {302, nullptr, "StopConsoleSixAxisSensor"}, 369 {302, nullptr, "StopConsoleSixAxisSensor"},
370 {303, nullptr, "ActivateSevenSixAxisSensor"}, 370 {303, nullptr, "ActivateSevenSixAxisSensor"},
371 {304, nullptr, "StartSevenSixAxisSensor"}, 371 {304, nullptr, "StartSevenSixAxisSensor"},
@@ -579,6 +579,30 @@ private:
579 rb.Push(RESULT_SUCCESS); 579 rb.Push(RESULT_SUCCESS);
580 LOG_WARNING(Service_HID, "(STUBBED) called"); 580 LOG_WARNING(Service_HID, "(STUBBED) called");
581 } 581 }
582
583 void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
584 IPC::ResponseBuilder rb{ctx, 2};
585 rb.Push(RESULT_SUCCESS);
586 LOG_WARNING(Service_HID, "(STUBBED) called");
587 }
588
589 void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
590 IPC::ResponseBuilder rb{ctx, 2};
591 rb.Push(RESULT_SUCCESS);
592 LOG_WARNING(Service_HID, "(STUBBED) called");
593 }
594
595 void StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
596 IPC::ResponseBuilder rb{ctx, 2};
597 rb.Push(RESULT_SUCCESS);
598 LOG_WARNING(Service_HID, "(STUBBED) called");
599 }
600
601 void ActivateGesture(Kernel::HLERequestContext& ctx) {
602 IPC::ResponseBuilder rb{ctx, 2};
603 rb.Push(RESULT_SUCCESS);
604 LOG_WARNING(Service_HID, "(STUBBED) called");
605 }
582}; 606};
583 607
584class HidDbg final : public ServiceFramework<HidDbg> { 608class HidDbg final : public ServiceFramework<HidDbg> {
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 6e555ea03..7e1de0fa1 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -240,6 +240,41 @@ enum class FlowCondition : u64 {
240 Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? 240 Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
241}; 241};
242 242
243enum class ControlCode : u64 {
244 F = 0,
245 LT = 1,
246 EQ = 2,
247 LE = 3,
248 GT = 4,
249 NE = 5,
250 GE = 6,
251 Num = 7,
252 Nan = 8,
253 LTU = 9,
254 EQU = 10,
255 LEU = 11,
256 GTU = 12,
257 NEU = 13,
258 GEU = 14,
259 //
260 OFF = 16,
261 LO = 17,
262 SFF = 18,
263 LS = 19,
264 HI = 20,
265 SFT = 21,
266 HS = 22,
267 OFT = 23,
268 CSM_TA = 24,
269 CSM_TR = 25,
270 CSM_MX = 26,
271 FCSM_TA = 27,
272 FCSM_TR = 28,
273 FCSM_MX = 29,
274 RLE = 30,
275 RGT = 31,
276};
277
243enum class PredicateResultMode : u64 { 278enum class PredicateResultMode : u64 {
244 None = 0x0, 279 None = 0x0,
245 NotZero = 0x3, 280 NotZero = 0x3,
@@ -271,6 +306,15 @@ enum class TextureProcessMode : u64 {
271 LLA = 7 // Load LOD. The A is unknown, does not appear to differ with LL 306 LLA = 7 // Load LOD. The A is unknown, does not appear to differ with LL
272}; 307};
273 308
309enum class TextureMiscMode : u64 {
310 DC,
311 AOFFI, // Uses Offset
312 NDV,
313 NODEP,
314 MZ,
315 PTP,
316};
317
274enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; 318enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 };
275enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; 319enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 };
276 320
@@ -546,6 +590,15 @@ union Instruction {
546 } pset; 590 } pset;
547 591
548 union { 592 union {
593 BitField<0, 3, u64> pred0;
594 BitField<3, 3, u64> pred3;
595 BitField<8, 5, ControlCode> cc; // flag in cc
596 BitField<39, 3, u64> pred39;
597 BitField<42, 1, u64> neg_pred39;
598 BitField<45, 4, PredOperation> op; // op with pred39
599 } csetp;
600
601 union {
549 BitField<39, 3, u64> pred39; 602 BitField<39, 3, u64> pred39;
550 BitField<42, 1, u64> neg_pred; 603 BitField<42, 1, u64> neg_pred;
551 BitField<43, 1, u64> neg_a; 604 BitField<43, 1, u64> neg_a;
@@ -590,42 +643,127 @@ union Instruction {
590 BitField<28, 1, u64> array; 643 BitField<28, 1, u64> array;
591 BitField<29, 2, TextureType> texture_type; 644 BitField<29, 2, TextureType> texture_type;
592 BitField<31, 4, u64> component_mask; 645 BitField<31, 4, u64> component_mask;
646 BitField<49, 1, u64> nodep_flag;
647 BitField<50, 1, u64> dc_flag;
648 BitField<54, 1, u64> aoffi_flag;
593 BitField<55, 3, TextureProcessMode> process_mode; 649 BitField<55, 3, TextureProcessMode> process_mode;
594 650
595 bool IsComponentEnabled(std::size_t component) const { 651 bool IsComponentEnabled(std::size_t component) const {
596 return ((1ull << component) & component_mask) != 0; 652 return ((1ull << component) & component_mask) != 0;
597 } 653 }
654
655 TextureProcessMode GetTextureProcessMode() const {
656 return process_mode;
657 }
658
659 bool UsesMiscMode(TextureMiscMode mode) const {
660 switch (mode) {
661 case TextureMiscMode::DC:
662 return dc_flag != 0;
663 case TextureMiscMode::NODEP:
664 return nodep_flag != 0;
665 case TextureMiscMode::AOFFI:
666 return aoffi_flag != 0;
667 default:
668 break;
669 }
670 return false;
671 }
598 } tex; 672 } tex;
599 673
600 union { 674 union {
601 BitField<22, 6, TextureQueryType> query_type; 675 BitField<22, 6, TextureQueryType> query_type;
602 BitField<31, 4, u64> component_mask; 676 BitField<31, 4, u64> component_mask;
677 BitField<49, 1, u64> nodep_flag;
678
679 bool UsesMiscMode(TextureMiscMode mode) const {
680 switch (mode) {
681 case TextureMiscMode::NODEP:
682 return nodep_flag != 0;
683 default:
684 break;
685 }
686 return false;
687 }
603 } txq; 688 } txq;
604 689
605 union { 690 union {
606 BitField<28, 1, u64> array; 691 BitField<28, 1, u64> array;
607 BitField<29, 2, TextureType> texture_type; 692 BitField<29, 2, TextureType> texture_type;
608 BitField<31, 4, u64> component_mask; 693 BitField<31, 4, u64> component_mask;
694 BitField<35, 1, u64> ndv_flag;
695 BitField<49, 1, u64> nodep_flag;
609 696
610 bool IsComponentEnabled(std::size_t component) const { 697 bool IsComponentEnabled(std::size_t component) const {
611 return ((1ull << component) & component_mask) != 0; 698 return ((1ull << component) & component_mask) != 0;
612 } 699 }
700
701 bool UsesMiscMode(TextureMiscMode mode) const {
702 switch (mode) {
703 case TextureMiscMode::NDV:
704 return (ndv_flag != 0);
705 case TextureMiscMode::NODEP:
706 return (nodep_flag != 0);
707 default:
708 break;
709 }
710 return false;
711 }
613 } tmml; 712 } tmml;
614 713
615 union { 714 union {
616 BitField<28, 1, u64> array; 715 BitField<28, 1, u64> array;
617 BitField<29, 2, TextureType> texture_type; 716 BitField<29, 2, TextureType> texture_type;
717 BitField<35, 1, u64> ndv_flag;
718 BitField<49, 1, u64> nodep_flag;
719 BitField<50, 1, u64> dc_flag;
720 BitField<54, 2, u64> info;
618 BitField<56, 2, u64> component; 721 BitField<56, 2, u64> component;
722
723 bool UsesMiscMode(TextureMiscMode mode) const {
724 switch (mode) {
725 case TextureMiscMode::NDV:
726 return ndv_flag != 0;
727 case TextureMiscMode::NODEP:
728 return nodep_flag != 0;
729 case TextureMiscMode::DC:
730 return dc_flag != 0;
731 case TextureMiscMode::AOFFI:
732 return info == 1;
733 case TextureMiscMode::PTP:
734 return info == 2;
735 default:
736 break;
737 }
738 return false;
739 }
619 } tld4; 740 } tld4;
620 741
621 union { 742 union {
743 BitField<49, 1, u64> nodep_flag;
744 BitField<50, 1, u64> dc_flag;
745 BitField<51, 1, u64> aoffi_flag;
622 BitField<52, 2, u64> component; 746 BitField<52, 2, u64> component;
747
748 bool UsesMiscMode(TextureMiscMode mode) const {
749 switch (mode) {
750 case TextureMiscMode::DC:
751 return dc_flag != 0;
752 case TextureMiscMode::NODEP:
753 return nodep_flag != 0;
754 case TextureMiscMode::AOFFI:
755 return aoffi_flag != 0;
756 default:
757 break;
758 }
759 return false;
760 }
623 } tld4s; 761 } tld4s;
624 762
625 union { 763 union {
626 BitField<0, 8, Register> gpr0; 764 BitField<0, 8, Register> gpr0;
627 BitField<28, 8, Register> gpr28; 765 BitField<28, 8, Register> gpr28;
628 BitField<49, 1, u64> nodep; 766 BitField<49, 1, u64> nodep_flag;
629 BitField<50, 3, u64> component_mask_selector; 767 BitField<50, 3, u64> component_mask_selector;
630 BitField<53, 4, u64> texture_info; 768 BitField<53, 4, u64> texture_info;
631 769
@@ -645,6 +783,37 @@ union Instruction {
645 UNREACHABLE(); 783 UNREACHABLE();
646 } 784 }
647 785
786 TextureProcessMode GetTextureProcessMode() const {
787 switch (texture_info) {
788 case 0:
789 case 2:
790 case 6:
791 case 8:
792 case 9:
793 case 11:
794 return TextureProcessMode::LZ;
795 case 3:
796 case 5:
797 case 13:
798 return TextureProcessMode::LL;
799 default:
800 break;
801 }
802 return TextureProcessMode::None;
803 }
804
805 bool UsesMiscMode(TextureMiscMode mode) const {
806 switch (mode) {
807 case TextureMiscMode::DC:
808 return (texture_info >= 4 && texture_info <= 6) || texture_info == 9;
809 case TextureMiscMode::NODEP:
810 return nodep_flag != 0;
811 default:
812 break;
813 }
814 return false;
815 }
816
648 bool IsArrayTexture() const { 817 bool IsArrayTexture() const {
649 // TEXS only supports Texture2D arrays. 818 // TEXS only supports Texture2D arrays.
650 return texture_info >= 7 && texture_info <= 9; 819 return texture_info >= 7 && texture_info <= 9;
@@ -673,6 +842,7 @@ union Instruction {
673 } texs; 842 } texs;
674 843
675 union { 844 union {
845 BitField<49, 1, u64> nodep_flag;
676 BitField<53, 4, u64> texture_info; 846 BitField<53, 4, u64> texture_info;
677 847
678 TextureType GetTextureType() const { 848 TextureType GetTextureType() const {
@@ -693,6 +863,26 @@ union Instruction {
693 UNREACHABLE(); 863 UNREACHABLE();
694 } 864 }
695 865
866 TextureProcessMode GetTextureProcessMode() const {
867 if (texture_info == 1 || texture_info == 5 || texture_info == 12)
868 return TextureProcessMode::LL;
869 return TextureProcessMode::LZ;
870 }
871
872 bool UsesMiscMode(TextureMiscMode mode) const {
873 switch (mode) {
874 case TextureMiscMode::AOFFI:
875 return texture_info == 12 || texture_info == 4;
876 case TextureMiscMode::MZ:
877 return texture_info == 5;
878 case TextureMiscMode::NODEP:
879 return nodep_flag != 0;
880 default:
881 break;
882 }
883 return false;
884 }
885
696 bool IsArrayTexture() const { 886 bool IsArrayTexture() const {
697 // TEXS only supports Texture2D arrays. 887 // TEXS only supports Texture2D arrays.
698 return texture_info == 8; 888 return texture_info == 8;
@@ -735,6 +925,7 @@ union Instruction {
735 BitField<36, 5, u64> index; 925 BitField<36, 5, u64> index;
736 } cbuf36; 926 } cbuf36;
737 927
928 BitField<47, 1, u64> generates_cc;
738 BitField<61, 1, u64> is_b_imm; 929 BitField<61, 1, u64> is_b_imm;
739 BitField<60, 1, u64> is_b_gpr; 930 BitField<60, 1, u64> is_b_gpr;
740 BitField<59, 1, u64> is_c_gpr; 931 BitField<59, 1, u64> is_c_gpr;
@@ -859,6 +1050,7 @@ public:
859 ISET_IMM, 1050 ISET_IMM,
860 PSETP, 1051 PSETP,
861 PSET, 1052 PSET,
1053 CSETP,
862 XMAD_IMM, 1054 XMAD_IMM,
863 XMAD_CR, 1055 XMAD_CR,
864 XMAD_RC, 1056 XMAD_RC,
@@ -1095,6 +1287,7 @@ private:
1095 INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"), 1287 INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
1096 INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"), 1288 INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"),
1097 INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), 1289 INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
1290 INST("010100001010----", Id::CSETP, Type::PredicateSetPredicate, "CSETP"),
1098 INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"), 1291 INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
1099 INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"), 1292 INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
1100 INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"), 1293 INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index a1638c12e..b3e95187e 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -236,6 +236,14 @@ private:
236 const std::string& suffix; 236 const std::string& suffix;
237}; 237};
238 238
239enum class InternalFlag : u64 {
240 ZeroFlag = 0,
241 CarryFlag = 1,
242 OverflowFlag = 2,
243 NaNFlag = 3,
244 Amount
245};
246
239/** 247/**
240 * Used to manage shader registers that are emulated with GLSL. This class keeps track of the state 248 * Used to manage shader registers that are emulated with GLSL. This class keeps track of the state
241 * of all registers (e.g. whether they are currently being used as Floats or Integers), and 249 * of all registers (e.g. whether they are currently being used as Floats or Integers), and
@@ -329,13 +337,19 @@ public:
329 void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, 337 void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem,
330 const std::string& value, u64 dest_num_components, 338 const std::string& value, u64 dest_num_components,
331 u64 value_num_components, bool is_saturated = false, 339 u64 value_num_components, bool is_saturated = false,
332 u64 dest_elem = 0, Register::Size size = Register::Size::Word) { 340 u64 dest_elem = 0, Register::Size size = Register::Size::Word,
341 bool sets_cc = false) {
333 ASSERT_MSG(!is_saturated, "Unimplemented"); 342 ASSERT_MSG(!is_saturated, "Unimplemented");
334 343
335 const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"}; 344 const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"};
336 345
337 SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')', 346 SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')',
338 dest_num_components, value_num_components, dest_elem); 347 dest_num_components, value_num_components, dest_elem);
348
349 if (sets_cc) {
350 const std::string zero_condition = "( " + ConvertIntegerSize(value, size) + " == 0 )";
351 SetInternalFlag(InternalFlag::ZeroFlag, zero_condition);
352 }
339 } 353 }
340 354
341 /** 355 /**
@@ -352,6 +366,26 @@ public:
352 shader.AddLine(dest + " = " + src + ';'); 366 shader.AddLine(dest + " = " + src + ';');
353 } 367 }
354 368
369 std::string GetControlCode(const Tegra::Shader::ControlCode cc) const {
370 switch (cc) {
371 case Tegra::Shader::ControlCode::NEU:
372 return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')';
373 default:
374 LOG_CRITICAL(HW_GPU, "Unimplemented Control Code {}", static_cast<u32>(cc));
375 UNREACHABLE();
376 return "false";
377 }
378 }
379
380 std::string GetInternalFlag(const InternalFlag ii) const {
381 const u32 code = static_cast<u32>(ii);
382 return "internalFlag_" + std::to_string(code) + suffix;
383 }
384
385 void SetInternalFlag(const InternalFlag ii, const std::string& value) const {
386 shader.AddLine(GetInternalFlag(ii) + " = " + value + ';');
387 }
388
355 /** 389 /**
356 * Writes code that does a output attribute assignment to register operation. Output attributes 390 * Writes code that does a output attribute assignment to register operation. Output attributes
357 * are stored as floats, so this may require conversion. 391 * are stored as floats, so this may require conversion.
@@ -415,6 +449,12 @@ public:
415 } 449 }
416 declarations.AddNewLine(); 450 declarations.AddNewLine();
417 451
452 for (u32 ii = 0; ii < static_cast<u64>(InternalFlag::Amount); ii++) {
453 const InternalFlag code = static_cast<InternalFlag>(ii);
454 declarations.AddLine("bool " + GetInternalFlag(code) + " = false;");
455 }
456 declarations.AddNewLine();
457
418 for (const auto element : declr_input_attribute) { 458 for (const auto element : declr_input_attribute) {
419 // TODO(bunnei): Use proper number of elements for these 459 // TODO(bunnei): Use proper number of elements for these
420 u32 idx = 460 u32 idx =
@@ -938,8 +978,6 @@ private:
938 // TEXS has two destination registers and a swizzle. The first two elements in the swizzle 978 // TEXS has two destination registers and a swizzle. The first two elements in the swizzle
939 // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1 979 // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1
940 980
941 ASSERT_MSG(instr.texs.nodep == 0, "TEXS nodep not implemented");
942
943 std::size_t written_components = 0; 981 std::size_t written_components = 0;
944 for (u32 component = 0; component < 4; ++component) { 982 for (u32 component = 0; component < 4; ++component) {
945 if (!instr.texs.IsComponentEnabled(component)) { 983 if (!instr.texs.IsComponentEnabled(component)) {
@@ -1622,7 +1660,8 @@ private:
1622 } 1660 }
1623 1661
1624 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, 1662 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1,
1625 1, instr.alu.saturate_d, 0, instr.conversion.dest_size); 1663 1, instr.alu.saturate_d, 0, instr.conversion.dest_size,
1664 instr.generates_cc.Value() != 0);
1626 break; 1665 break;
1627 } 1666 }
1628 case OpCode::Id::I2F_R: 1667 case OpCode::Id::I2F_R:
@@ -1761,8 +1800,8 @@ private:
1761 Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective, 1800 Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective,
1762 Tegra::Shader::IpaSampleMode::Default}; 1801 Tegra::Shader::IpaSampleMode::Default};
1763 1802
1764 u32 next_element = instr.attribute.fmt20.element; 1803 u64 next_element = instr.attribute.fmt20.element;
1765 u32 next_index = static_cast<u32>(instr.attribute.fmt20.index.Value()); 1804 u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
1766 1805
1767 const auto LoadNextElement = [&](u32 reg_offset) { 1806 const auto LoadNextElement = [&](u32 reg_offset) {
1768 regs.SetRegisterToInputAttibute(instr.gpr0.Value() + reg_offset, next_element, 1807 regs.SetRegisterToInputAttibute(instr.gpr0.Value() + reg_offset, next_element,
@@ -1826,8 +1865,8 @@ private:
1826 ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0, 1865 ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0,
1827 "Unaligned attribute loads are not supported"); 1866 "Unaligned attribute loads are not supported");
1828 1867
1829 u32 next_element = instr.attribute.fmt20.element; 1868 u64 next_element = instr.attribute.fmt20.element;
1830 u32 next_index = static_cast<u32>(instr.attribute.fmt20.index.Value()); 1869 u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
1831 1870
1832 const auto StoreNextElement = [&](u32 reg_offset) { 1871 const auto StoreNextElement = [&](u32 reg_offset) {
1833 regs.SetOutputAttributeToRegister(static_cast<Attribute::Index>(next_index), 1872 regs.SetOutputAttributeToRegister(static_cast<Attribute::Index>(next_index),
@@ -1853,6 +1892,13 @@ private:
1853 Tegra::Shader::TextureType texture_type{instr.tex.texture_type}; 1892 Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
1854 std::string coord; 1893 std::string coord;
1855 1894
1895 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
1896 "NODEP is not implemented");
1897 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
1898 "AOFFI is not implemented");
1899 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
1900 "DC is not implemented");
1901
1856 switch (texture_type) { 1902 switch (texture_type) {
1857 case Tegra::Shader::TextureType::Texture1D: { 1903 case Tegra::Shader::TextureType::Texture1D: {
1858 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1904 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
@@ -1935,6 +1981,11 @@ private:
1935 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; 1981 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
1936 bool is_array{instr.texs.IsArrayTexture()}; 1982 bool is_array{instr.texs.IsArrayTexture()};
1937 1983
1984 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
1985 "NODEP is not implemented");
1986 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
1987 "DC is not implemented");
1988
1938 switch (texture_type) { 1989 switch (texture_type) {
1939 case Tegra::Shader::TextureType::Texture2D: { 1990 case Tegra::Shader::TextureType::Texture2D: {
1940 if (is_array) { 1991 if (is_array) {
@@ -1971,6 +2022,13 @@ private:
1971 ASSERT(instr.tlds.IsArrayTexture() == false); 2022 ASSERT(instr.tlds.IsArrayTexture() == false);
1972 std::string coord; 2023 std::string coord;
1973 2024
2025 ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2026 "NODEP is not implemented");
2027 ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
2028 "AOFFI is not implemented");
2029 ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ),
2030 "MZ is not implemented");
2031
1974 switch (instr.tlds.GetTextureType()) { 2032 switch (instr.tlds.GetTextureType()) {
1975 case Tegra::Shader::TextureType::Texture2D: { 2033 case Tegra::Shader::TextureType::Texture2D: {
1976 if (instr.tlds.IsArrayTexture()) { 2034 if (instr.tlds.IsArrayTexture()) {
@@ -1999,6 +2057,17 @@ private:
1999 ASSERT(instr.tld4.array == 0); 2057 ASSERT(instr.tld4.array == 0);
2000 std::string coord; 2058 std::string coord;
2001 2059
2060 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2061 "NODEP is not implemented");
2062 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
2063 "AOFFI is not implemented");
2064 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
2065 "DC is not implemented");
2066 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
2067 "NDV is not implemented");
2068 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP),
2069 "PTP is not implemented");
2070
2002 switch (instr.tld4.texture_type) { 2071 switch (instr.tld4.texture_type) {
2003 case Tegra::Shader::TextureType::Texture2D: { 2072 case Tegra::Shader::TextureType::Texture2D: {
2004 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2073 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
@@ -2036,6 +2105,13 @@ private:
2036 break; 2105 break;
2037 } 2106 }
2038 case OpCode::Id::TLD4S: { 2107 case OpCode::Id::TLD4S: {
2108 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2109 "NODEP is not implemented");
2110 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
2111 "AOFFI is not implemented");
2112 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
2113 "DC is not implemented");
2114
2039 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 2115 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
2040 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 2116 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
2041 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. 2117 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
@@ -2048,6 +2124,9 @@ private:
2048 break; 2124 break;
2049 } 2125 }
2050 case OpCode::Id::TXQ: { 2126 case OpCode::Id::TXQ: {
2127 ASSERT_MSG(!instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2128 "NODEP is not implemented");
2129
2051 // TODO: the new commits on the texture refactor, change the way samplers work. 2130 // TODO: the new commits on the texture refactor, change the way samplers work.
2052 // Sadly, not all texture instructions specify the type of texture their sampler 2131 // Sadly, not all texture instructions specify the type of texture their sampler
2053 // uses. This must be fixed at a later instance. 2132 // uses. This must be fixed at a later instance.
@@ -2068,6 +2147,11 @@ private:
2068 break; 2147 break;
2069 } 2148 }
2070 case OpCode::Id::TMML: { 2149 case OpCode::Id::TMML: {
2150 ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2151 "NODEP is not implemented");
2152 ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
2153 "NDV is not implemented");
2154
2071 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 2155 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
2072 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2156 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2073 const bool is_array = instr.tmml.array != 0; 2157 const bool is_array = instr.tmml.array != 0;
@@ -2234,31 +2318,55 @@ private:
2234 break; 2318 break;
2235 } 2319 }
2236 case OpCode::Type::PredicateSetPredicate: { 2320 case OpCode::Type::PredicateSetPredicate: {
2237 const std::string op_a = 2321 switch (opcode->GetId()) {
2238 GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); 2322 case OpCode::Id::PSETP: {
2239 const std::string op_b = 2323 const std::string op_a =
2240 GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); 2324 GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
2325 const std::string op_b =
2326 GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0);
2241 2327
2242 // We can't use the constant predicate as destination. 2328 // We can't use the constant predicate as destination.
2243 ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 2329 ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
2244 2330
2245 const std::string second_pred = 2331 const std::string second_pred =
2246 GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); 2332 GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0);
2247 2333
2248 const std::string combiner = GetPredicateCombiner(instr.psetp.op); 2334 const std::string combiner = GetPredicateCombiner(instr.psetp.op);
2249 2335
2250 const std::string predicate = 2336 const std::string predicate =
2251 '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')'; 2337 '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')';
2252 2338
2253 // Set the primary predicate to the result of Predicate OP SecondPredicate 2339 // Set the primary predicate to the result of Predicate OP SecondPredicate
2254 SetPredicate(instr.psetp.pred3, 2340 SetPredicate(instr.psetp.pred3,
2255 '(' + predicate + ") " + combiner + " (" + second_pred + ')'); 2341 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
2256 2342
2257 if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { 2343 if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
2258 // Set the secondary predicate to the result of !Predicate OP SecondPredicate, 2344 // Set the secondary predicate to the result of !Predicate OP SecondPredicate,
2259 // if enabled 2345 // if enabled
2260 SetPredicate(instr.psetp.pred0, 2346 SetPredicate(instr.psetp.pred0,
2261 "!(" + predicate + ") " + combiner + " (" + second_pred + ')'); 2347 "!(" + predicate + ") " + combiner + " (" + second_pred + ')');
2348 }
2349 break;
2350 }
2351 case OpCode::Id::CSETP: {
2352 const std::string pred =
2353 GetPredicateCondition(instr.csetp.pred39, instr.csetp.neg_pred39 != 0);
2354 const std::string combiner = GetPredicateCombiner(instr.csetp.op);
2355 const std::string controlCode = regs.GetControlCode(instr.csetp.cc);
2356 if (instr.csetp.pred3 != static_cast<u64>(Pred::UnusedIndex)) {
2357 SetPredicate(instr.csetp.pred3,
2358 '(' + controlCode + ") " + combiner + " (" + pred + ')');
2359 }
2360 if (instr.csetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
2361 SetPredicate(instr.csetp.pred0,
2362 "!(" + controlCode + ") " + combiner + " (" + pred + ')');
2363 }
2364 break;
2365 }
2366 default: {
2367 LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}", opcode->GetName());
2368 UNREACHABLE();
2369 }
2262 } 2370 }
2263 break; 2371 break;
2264 } 2372 }
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 991abda2e..7ec1f5110 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -125,6 +125,10 @@ void Config::ReadValues() {
125 125
126 // System 126 // System
127 Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); 127 Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false);
128 Settings::values.username = sdl2_config->Get("System", "username", "yuzu");
129 if (Settings::values.username.empty()) {
130 Settings::values.username = "yuzu";
131 }
128 132
129 // Miscellaneous 133 // Miscellaneous
130 Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace"); 134 Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace");
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 002a4ec15..d35c441e9 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -176,7 +176,7 @@ use_docked_mode =
176 176
177# Sets the account username, max length is 32 characters 177# Sets the account username, max length is 32 characters
178# yuzu (default) 178# yuzu (default)
179username = 179username = yuzu
180 180
181# Sets the systems language index 181# Sets the systems language index
182# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese, 182# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,