diff options
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 | ||
| 11 | namespace AudioCore { | 14 | namespace AudioCore { |
| @@ -13,6 +16,41 @@ namespace AudioCore { | |||
| 13 | constexpr u32 STREAM_SAMPLE_RATE{48000}; | 16 | constexpr u32 STREAM_SAMPLE_RATE{48000}; |
| 14 | constexpr u32 STREAM_NUM_CHANNELS{2}; | 17 | constexpr u32 STREAM_NUM_CHANNELS{2}; |
| 15 | 18 | ||
| 19 | class AudioRenderer::VoiceState { | ||
| 20 | public: | ||
| 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 | |||
| 42 | private: | ||
| 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 | |||
| 16 | AudioRenderer::AudioRenderer(AudioRendererParameter params, | 54 | AudioRenderer::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 | ||
| 68 | AudioRenderer::~AudioRenderer() = default; | ||
| 69 | |||
| 30 | u32 AudioRenderer::GetSampleRate() const { | 70 | u32 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 | |||
| 17 | namespace Kernel { | ||
| 18 | class Event; | ||
| 19 | } | ||
| 18 | 20 | ||
| 19 | namespace AudioCore { | 21 | namespace AudioCore { |
| 20 | 22 | ||
| 23 | class AudioOut; | ||
| 24 | |||
| 21 | enum class PlayState : u8 { | 25 | enum 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 | |||
| 158 | class AudioRenderer { | 162 | class AudioRenderer { |
| 159 | public: | 163 | public: |
| 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 | ||
| 168 | private: | 174 | private: |
| 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 | |
| 16 | namespace CoreTiming { | ||
| 17 | struct EventType; | ||
| 18 | } | ||
| 18 | 19 | ||
| 19 | namespace AudioCore { | 20 | namespace AudioCore { |
| 20 | 21 | ||
| 22 | class 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 | ||
| 11 | namespace Core { | 11 | namespace Core { |
| 12 | 12 | ||
| 13 | /// Generic ARM11 CPU interface | 13 | /// Generic ARMv8 CPU interface |
| 14 | class ARM_Interface : NonCopyable { | 14 | class ARM_Interface : NonCopyable { |
| 15 | public: | 15 | public: |
| 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 | ||
| 197 | u128 ARM_Dynarmic::GetExtReg(int index) const { | 197 | u128 ARM_Dynarmic::GetVectorReg(int index) const { |
| 198 | return jit->GetVector(index); | 198 | return jit->GetVector(index); |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | void ARM_Dynarmic::SetExtReg(int index, u128 value) { | 201 | void ARM_Dynarmic::SetVectorReg(int index, u128 value) { |
| 202 | jit->SetVector(index, value); | 202 | jit->SetVector(index, value); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const { | 205 | u32 ARM_Dynarmic::GetPSTATE() const { |
| 206 | UNIMPLEMENTED(); | ||
| 207 | return {}; | ||
| 208 | } | ||
| 209 | |||
| 210 | void ARM_Dynarmic::SetVFPReg(int /*index*/, u32 /*value*/) { | ||
| 211 | UNIMPLEMENTED(); | ||
| 212 | } | ||
| 213 | |||
| 214 | u32 ARM_Dynarmic::GetCPSR() const { | ||
| 215 | return jit->GetPstate(); | 206 | return jit->GetPstate(); |
| 216 | } | 207 | } |
| 217 | 208 | ||
| 218 | void ARM_Dynarmic::SetCPSR(u32 cpsr) { | 209 | void ARM_Dynarmic::SetPSTATE(u32 pstate) { |
| 219 | jit->SetPstate(cpsr); | 210 | jit->SetPstate(pstate); |
| 220 | } | 211 | } |
| 221 | 212 | ||
| 222 | u64 ARM_Dynarmic::GetTlsAddress() const { | 213 | u64 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 | ||
| 247 | void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { | 238 | void 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 | ||
| 256 | void ARM_Dynarmic::PrepareReschedule() { | 247 | void ARM_Dynarmic::PrepareReschedule() { |
| @@ -304,8 +295,8 @@ bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr va | |||
| 304 | 295 | ||
| 305 | bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) { | 296 | bool 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 | ||
| 134 | u128 ARM_Unicorn::GetExtReg(int /*index*/) const { | 134 | u128 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 | ||
| 140 | void ARM_Unicorn::SetExtReg(int /*index*/, u128 /*value*/) { | 140 | void ARM_Unicorn::SetVectorReg(int /*index*/, u128 /*value*/) { |
| 141 | UNIMPLEMENTED(); | 141 | UNIMPLEMENTED(); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | u32 ARM_Unicorn::GetVFPReg(int /*index*/) const { | 144 | u32 ARM_Unicorn::GetPSTATE() const { |
| 145 | UNIMPLEMENTED(); | ||
| 146 | return {}; | ||
| 147 | } | ||
| 148 | |||
| 149 | void ARM_Unicorn::SetVFPReg(int /*index*/, u32 /*value*/) { | ||
| 150 | UNIMPLEMENTED(); | ||
| 151 | } | ||
| 152 | |||
| 153 | u32 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 | ||
| 159 | void ARM_Unicorn::SetCPSR(u32 cpsr) { | 150 | void 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 | ||
| 70 | Cpu::~Cpu() = default; | ||
| 71 | |||
| 69 | std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) { | 72 | std::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 | ||
| 15 | namespace Kernel { | 14 | namespace Kernel { |
| 16 | class Scheduler; | 15 | class Scheduler; |
| @@ -19,6 +18,7 @@ class Scheduler; | |||
| 19 | namespace Core { | 18 | namespace Core { |
| 20 | 19 | ||
| 21 | class ARM_Interface; | 20 | class ARM_Interface; |
| 21 | class ExclusiveMonitor; | ||
| 22 | 22 | ||
| 23 | constexpr unsigned NUM_CPU_CORES{4}; | 23 | constexpr unsigned NUM_CPU_CORES{4}; |
| 24 | 24 | ||
| @@ -43,6 +43,7 @@ class Cpu { | |||
| 43 | public: | 43 | public: |
| 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; | |||
| 65 | constexpr u32 LR_REGISTER = 30; | 65 | constexpr u32 LR_REGISTER = 30; |
| 66 | constexpr u32 SP_REGISTER = 31; | 66 | constexpr u32 SP_REGISTER = 31; |
| 67 | constexpr u32 PC_REGISTER = 32; | 67 | constexpr u32 PC_REGISTER = 32; |
| 68 | constexpr u32 CPSR_REGISTER = 33; | 68 | constexpr u32 PSTATE_REGISTER = 33; |
| 69 | constexpr u32 UC_ARM64_REG_Q0 = 34; | 69 | constexpr u32 UC_ARM64_REG_Q0 = 34; |
| 70 | constexpr u32 FPSCR_REGISTER = 66; | 70 | constexpr 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 |
| 73 | constexpr u32 TODO_DUMMY_REG_997 = 997; | 73 | constexpr 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 | |||
| 100 | ResultCode Mutex::Release(VAddr address) { | 100 | ResultCode 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, | |||
| 289 | static ResultCode ArbitrateUnlock(VAddr mutex_addr) { | 293 | static 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 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | #define PARAM(n) Core::CurrentArmInterface().GetReg(n) | 16 | static 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 | ||
| 29 | template <ResultCode func(u64)> | 31 | template <ResultCode func(u64)> |
| 30 | void SvcWrap() { | 32 | void SvcWrap() { |
| 31 | FuncReturn(func(PARAM(0)).raw); | 33 | FuncReturn(func(Param(0)).raw); |
| 32 | } | 34 | } |
| 33 | 35 | ||
| 34 | template <ResultCode func(u32)> | 36 | template <ResultCode func(u32)> |
| 35 | void SvcWrap() { | 37 | void SvcWrap() { |
| 36 | FuncReturn(func((u32)PARAM(0)).raw); | 38 | FuncReturn(func((u32)Param(0)).raw); |
| 37 | } | 39 | } |
| 38 | 40 | ||
| 39 | template <ResultCode func(u32, u32)> | 41 | template <ResultCode func(u32, u32)> |
| 40 | void SvcWrap() { | 42 | void 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 | ||
| 44 | template <ResultCode func(u32*, u32)> | 46 | template <ResultCode func(u32*, u32)> |
| 45 | void SvcWrap() { | 47 | void SvcWrap() { |
| 46 | u32 param_1 = 0; | 48 | u32 param_1 = 0; |
| 47 | u32 retval = func(¶m_1, (u32)PARAM(1)).raw; | 49 | u32 retval = func(¶m_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() { | |||
| 52 | template <ResultCode func(u32*, u64)> | 54 | template <ResultCode func(u32*, u64)> |
| 53 | void SvcWrap() { | 55 | void SvcWrap() { |
| 54 | u32 param_1 = 0; | 56 | u32 param_1 = 0; |
| 55 | u32 retval = func(¶m_1, PARAM(1)).raw; | 57 | u32 retval = func(¶m_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 | ||
| 60 | template <ResultCode func(u64, s32)> | 62 | template <ResultCode func(u64, s32)> |
| 61 | void SvcWrap() { | 63 | void SvcWrap() { |
| 62 | FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); | 64 | FuncReturn(func(Param(0), (s32)Param(1)).raw); |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | template <ResultCode func(u64*, u64)> | 67 | template <ResultCode func(u64*, u64)> |
| 66 | void SvcWrap() { | 68 | void SvcWrap() { |
| 67 | u64 param_1 = 0; | 69 | u64 param_1 = 0; |
| 68 | u32 retval = func(¶m_1, PARAM(1)).raw; | 70 | u32 retval = func(¶m_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 | ||
| 73 | template <ResultCode func(u32, u64)> | 75 | template <ResultCode func(u32, u64)> |
| 74 | void SvcWrap() { | 76 | void 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 | ||
| 78 | template <ResultCode func(u32, u32, u64)> | 80 | template <ResultCode func(u32, u32, u64)> |
| 79 | void SvcWrap() { | 81 | void 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 | ||
| 83 | template <ResultCode func(u32, u32*, u64*)> | 85 | template <ResultCode func(u32, u32*, u64*)> |
| 84 | void SvcWrap() { | 86 | void 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), ¶m_1, ¶m_2); | 89 | ResultCode retval = func((u32)(Param(2) & 0xFFFFFFFF), ¶m_1, ¶m_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() { | |||
| 93 | template <ResultCode func(u64, u64, u32, u32)> | 95 | template <ResultCode func(u64, u64, u32, u32)> |
| 94 | void SvcWrap() { | 96 | void 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 | ||
| 99 | template <ResultCode func(u32, u64, u32)> | 101 | template <ResultCode func(u32, u64, u32)> |
| 100 | void SvcWrap() { | 102 | void 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 | ||
| 104 | template <ResultCode func(u64, u64, u64)> | 106 | template <ResultCode func(u64, u64, u64)> |
| 105 | void SvcWrap() { | 107 | void 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 | ||
| 109 | template <ResultCode func(u32, u64, u64, u32)> | 111 | template <ResultCode func(u32, u64, u64, u32)> |
| 110 | void SvcWrap() { | 112 | void 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 | ||
| 114 | template <ResultCode func(u32, u64, u64)> | 116 | template <ResultCode func(u32, u64, u64)> |
| 115 | void SvcWrap() { | 117 | void 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 | ||
| 119 | template <ResultCode func(u32*, u64, u64, s64)> | 121 | template <ResultCode func(u32*, u64, u64, s64)> |
| 120 | void SvcWrap() { | 122 | void SvcWrap() { |
| 121 | u32 param_1 = 0; | 123 | u32 param_1 = 0; |
| 122 | ResultCode retval = func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)); | 124 | ResultCode retval = func(¶m_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 | ||
| 127 | template <ResultCode func(u64, u64, u32, s64)> | 129 | template <ResultCode func(u64, u64, u32, s64)> |
| 128 | void SvcWrap() { | 130 | void 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 | ||
| 132 | template <ResultCode func(u64*, u64, u64, u64)> | 134 | template <ResultCode func(u64*, u64, u64, u64)> |
| 133 | void SvcWrap() { | 135 | void SvcWrap() { |
| 134 | u64 param_1 = 0; | 136 | u64 param_1 = 0; |
| 135 | u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3)).raw; | 137 | u32 retval = func(¶m_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)> | |||
| 141 | void SvcWrap() { | 143 | void SvcWrap() { |
| 142 | u32 param_1 = 0; | 144 | u32 param_1 = 0; |
| 143 | u32 retval = | 145 | u32 retval = |
| 144 | func(¶m_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF)) | 146 | func(¶m_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)> | |||
| 151 | void SvcWrap() { | 153 | void 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() { | |||
| 165 | template <ResultCode func(u32*, u64, u64, u32)> | 167 | template <ResultCode func(u32*, u64, u64, u32)> |
| 166 | void SvcWrap() { | 168 | void SvcWrap() { |
| 167 | u32 param_1 = 0; | 169 | u32 param_1 = 0; |
| 168 | u32 retval = func(¶m_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; | 170 | u32 retval = func(¶m_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)> | |||
| 174 | void SvcWrap() { | 176 | void SvcWrap() { |
| 175 | u32 param_1 = 0; | 177 | u32 param_1 = 0; |
| 176 | u32 retval = | 178 | u32 retval = |
| 177 | func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; | 179 | func(¶m_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() { | |||
| 182 | template <ResultCode func(u64, u32, s32, s64)> | 184 | template <ResultCode func(u64, u32, s32, s64)> |
| 183 | void SvcWrap() { | 185 | void 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 | ||
| 189 | template <ResultCode func(u64, u32, s32, s32)> | 191 | template <ResultCode func(u64, u32, s32, s32)> |
| 190 | void SvcWrap() { | 192 | void 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 | ||
| 220 | template <void func(s64)> | 222 | template <void func(s64)> |
| 221 | void SvcWrap() { | 223 | void SvcWrap() { |
| 222 | func((s64)PARAM(0)); | 224 | func((s64)Param(0)); |
| 223 | } | 225 | } |
| 224 | 226 | ||
| 225 | template <void func(u64, u64 len)> | 227 | template <void func(u64, u64 len)> |
| 226 | void SvcWrap() { | 228 | void SvcWrap() { |
| 227 | func(PARAM(0), PARAM(1)); | 229 | func(Param(0), Param(1)); |
| 228 | } | 230 | } |
| 229 | 231 | ||
| 230 | template <void func(u64, u64, u64)> | 232 | template <void func(u64, u64, u64)> |
| 231 | void SvcWrap() { | 233 | void 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 | ||
| 224 | ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point, | 224 | ResultVal<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() { | |||
| 25 | ProfileManager::ProfileManager() { | 25 | ProfileManager::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 |
| 93 | ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) { | 93 | ResultCode 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 | ||
| 25 | namespace Service::AM { | 26 | namespace 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 | ||
| 397 | void 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 | |||
| 396 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { | 412 | void 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 | ||
| 584 | class HidDbg final : public ServiceFramework<HidDbg> { | 608 | class 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 | ||
| 243 | enum 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 | |||
| 243 | enum class PredicateResultMode : u64 { | 278 | enum 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 | ||
| 309 | enum class TextureMiscMode : u64 { | ||
| 310 | DC, | ||
| 311 | AOFFI, // Uses Offset | ||
| 312 | NDV, | ||
| 313 | NODEP, | ||
| 314 | MZ, | ||
| 315 | PTP, | ||
| 316 | }; | ||
| 317 | |||
| 274 | enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; | 318 | enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; |
| 275 | enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; | 319 | enum 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 | ||
| 239 | enum 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) |
| 179 | username = | 179 | username = 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, |