Compare commits

...

35 Commits

Author SHA1 Message Date
David Marcec
08819ec70a Removed MakeBuilder as it's not needed anymore 2018-09-19 15:13:56 +10:00
David Marcec
6a0612f2bf Removed the use of rp.MakeBuilder
Due to keeping the code style consistent in the yuzu codebase. `rb = rp.MakeBuilder(...)` was replaced with `rb{ctx, ...}`
2018-09-19 15:09:59 +10:00
bunnei
b33ce787b7 Merge pull request #1348 from ogniK5377/GetImageSize
Implemented IProfile::GetImageSize
2018-09-18 22:15:18 -04:00
bunnei
d85130d7be Merge pull request #1319 from lioncash/audio
audio_core: Replace includes with forward declarations where applicable.
2018-09-18 22:14:26 -04:00
bunnei
c9942fe46e Merge pull request #1351 from ogniK5377/GetDefaultDisplayResolution
Implemented GetDefaultDisplayResolution
2018-09-18 22:13:28 -04:00
bunnei
bf957d5345 Merge pull request #1341 from lioncash/dependency
core/core_cpu: Replace exclusive monitor include with forward declaration
2018-09-18 22:13:05 -04:00
bunnei
c768535463 Merge pull request #1346 from lioncash/svc
svc_wrap: Convert the PARAM macro into a function
2018-09-18 22:12:47 -04:00
bunnei
e9abbcae85 Merge pull request #1350 from ogniK5377/Six-Axis-Stub
Stubbed ActivateConsoleSixAxisSensor & StartConsoleSixAxisSensor
2018-09-18 22:12:12 -04:00
bunnei
bd88d4108f Merge pull request #1342 from lioncash/trunc
gl_shader_decompiler: Avoid truncation warnings within LD_A and ST_A code
2018-09-18 22:11:48 -04:00
bunnei
0284cbe7ec Merge pull request #1279 from FernandoS27/csetp
shader_decompiler: Implemented (Partialy) Control Codes and CSETP
2018-09-18 22:10:48 -04:00
bunnei
6415f81bb8 Merge pull request #1299 from FernandoS27/texture-sanatize
shader_decompiler: Asserts for Texture Instructions
2018-09-18 22:10:09 -04:00
Philippe Babin
9155c8daeb Invalid default value of username in yuzu_cmd (#1334)
* Fix bug where default username value for yuzu_cmd create an userprofile with uninitialize data as username

* Fix format

* Apply code review changes

* Remove nullptr check
2018-09-18 19:58:28 -04:00
bunnei
733c47623b Merge pull request #1343 from lioncash/mutex
kernel/svc: Handle invalid address cases within svcArbitrateLock() and svcArbitrateUnlock()
2018-09-18 14:25:00 -04:00
bunnei
c2cf784376 Merge pull request #1344 from lioncash/arm
arm_interface: Remove ARM11-isms from the CPU interface
2018-09-18 14:24:20 -04:00
bunnei
c7a4bf5074 Merge pull request #1345 from lioncash/write
arm_dynarmic: Correct ExclusiveWrite128()'s operation
2018-09-18 14:23:57 -04:00
David Marcec
de9604d63e Added ActivateGesture 2018-09-19 01:13:58 +10:00
David Marcec
a8b1c7763b Added StopSixAxisSensor 2018-09-19 00:56:02 +10:00
David Marcec
717889e93c Stubbed ActivateConsoleSixAxisSensor & StartConsoleSixAxisSensor 2018-09-19 00:52:20 +10:00
David Marcec
528e5cee67 Implemented GetImageSize 2018-09-19 00:16:52 +10:00
Lioncash
f85ab0a123 svc_wrap: Convert the PARAM macro into a function
This can just be a regular function, getting rid of the need to also
explicitly undef the define at the end of the file. Given FuncReturn()
was already converted into a function, it's #undef can also be removed.
2018-09-18 04:27:38 -04:00
Lioncash
ead2a4eeb4 arm_dynarmic: Correct ExclusiveWrite128()'s operation
Previously the second half of the value being written would overwrite
the first half. Thankfully this wasn't a bug that was being encountered,
as the function is currently unused.
2018-09-18 03:56:32 -04:00
Lioncash
b51e7e0288 arm_interface: Remove ARM11-isms from the CPU interface
This modifies the CPU interface to more accurately match an
AArch64-supporting CPU as opposed to an ARM11 one. Two of the methods
don't even make sense to keep around for this interface, as Adv Simd is
used, rather than the VFP in the primary execution state. This is
essentially a modernization change that should have occurred from the
get-go.
2018-09-18 03:20:04 -04:00
Lioncash
71b48cb00f kernel/mutex: Replace ResultCode construction for invalid addresses with the named variant
We already have a ResultCode constant for the case of an invalid
address, so we can just use it instead of re-rolling that ResultCode
type.
2018-09-17 23:27:53 -04:00
Lioncash
b6867602ca kernel/svc: Handle error cases for svcArbitrateLock() and svcArbitrateUnlock()
The kernel does the equivalent of the following check before proceeding:

if (address + 0x8000000000 < 0x7FFFE00000) {
    return ERR_INVALID_MEMORY_STATE;
}

which is essentially what our IsKernelVirtualAddress() function does. So
we should also be checking for this.

The kernel also checks if the given input addresses are 4-byte aligned,
however our Mutex::TryAcquire() and Mutex::Release() functions already
handle this, so we don't need to add code for this case.
2018-09-17 23:27:53 -04:00
FernandoS27
567a5524b9 Implemented Internal Flags 2018-09-17 20:50:54 -04:00
Lioncash
9a8dbba1e5 gl_shader_decompiler: Avoid truncation warnings within LD_A and ST_A code
These are internally stored as u64 values, so using u32 here causes
truncation warnings. Instead, we can just use u64 and preserve the bit
width.
2018-09-17 19:25:55 -04:00
Lioncash
4a84986bc3 core/core_cpu: Replace exclusive monitor include with forward declaration
We don't need to include this as a dependency within the header. A
regular forward declaration will suffice here.
2018-09-17 18:16:55 -04:00
FernandoS27
e4bb759c4b Implemented I2I.CC on the NEU control code, used by SMO 2018-09-17 17:42:46 -04:00
FernandoS27
e2ac8fb36d Implemented CSETP 2018-09-17 17:42:44 -04:00
FernandoS27
aac77bbd18 Implemented Control Codes 2018-09-17 17:42:43 -04:00
Lioncash
f7308a6c25 time_stretch: Remove unused <array> include
This isn't used within this header and isn't necessary.
2018-09-17 15:08:34 -04:00
Lioncash
2fd124bc93 stream: Replace includes with forward declarations where applicable
Avoids propagating includes in headers where it's not necessary to do
so.
2018-09-17 15:08:34 -04:00
Lioncash
1adbcd54fe audio_renderer: Replace includes with forward declarations where applicable
Avoids including unnecessary headers within the audio_renderer.h header,
lessening the likelihood of needing to rebuild source files including
this header if they ever change.

Given std::vector allows forward declaring contained types, we can move
VoiceState to the cpp file and hide the implementation entirely.
2018-09-17 15:08:30 -04:00
FernandoS27
31e52113b3 Added asserts for texture misc modes to texture instructions 2018-09-17 12:56:36 -04:00
FernandoS27
55a4756766 Added texture misc modes to texture instructions 2018-09-17 12:51:05 -04:00
31 changed files with 601 additions and 257 deletions

View File

@@ -3,9 +3,12 @@
// Refer to the license.txt file included.
#include "audio_core/algorithm/interpolate.h"
#include "audio_core/audio_out.h"
#include "audio_core/audio_renderer.h"
#include "audio_core/codec.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/kernel/event.h"
#include "core/memory.h"
namespace AudioCore {
@@ -13,6 +16,41 @@ namespace AudioCore {
constexpr u32 STREAM_SAMPLE_RATE{48000};
constexpr u32 STREAM_NUM_CHANNELS{2};
class AudioRenderer::VoiceState {
public:
bool IsPlaying() const {
return is_in_use && info.play_state == PlayState::Started;
}
const VoiceOutStatus& GetOutStatus() const {
return out_status;
}
const VoiceInfo& GetInfo() const {
return info;
}
VoiceInfo& Info() {
return info;
}
void SetWaveIndex(std::size_t index);
std::vector<s16> DequeueSamples(std::size_t sample_count);
void UpdateState();
void RefreshBuffer();
private:
bool is_in_use{};
bool is_refresh_pending{};
std::size_t wave_index{};
std::size_t offset{};
Codec::ADPCMState adpcm_state{};
InterpolationState interp_state{};
std::vector<s16> samples;
VoiceOutStatus out_status{};
VoiceInfo info{};
};
AudioRenderer::AudioRenderer(AudioRendererParameter params,
Kernel::SharedPtr<Kernel::Event> buffer_event)
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) {
@@ -27,6 +65,8 @@ AudioRenderer::AudioRenderer(AudioRendererParameter params,
QueueMixedBuffer(2);
}
AudioRenderer::~AudioRenderer() = default;
u32 AudioRenderer::GetSampleRate() const {
return worker_params.sample_rate;
}

View File

@@ -8,16 +8,20 @@
#include <memory>
#include <vector>
#include "audio_core/algorithm/interpolate.h"
#include "audio_core/audio_out.h"
#include "audio_core/codec.h"
#include "audio_core/stream.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/object.h"
namespace Kernel {
class Event;
}
namespace AudioCore {
class AudioOut;
enum class PlayState : u8 {
Started = 0,
Stopped = 1,
@@ -158,6 +162,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
class AudioRenderer {
public:
AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event);
~AudioRenderer();
std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
void QueueMixedBuffer(Buffer::Tag tag);
void ReleaseAndQueueBuffers();
@@ -166,45 +172,12 @@ public:
u32 GetMixBufferCount() const;
private:
class VoiceState {
public:
bool IsPlaying() const {
return is_in_use && info.play_state == PlayState::Started;
}
const VoiceOutStatus& GetOutStatus() const {
return out_status;
}
const VoiceInfo& GetInfo() const {
return info;
}
VoiceInfo& Info() {
return info;
}
void SetWaveIndex(std::size_t index);
std::vector<s16> DequeueSamples(std::size_t sample_count);
void UpdateState();
void RefreshBuffer();
private:
bool is_in_use{};
bool is_refresh_pending{};
std::size_t wave_index{};
std::size_t offset{};
Codec::ADPCMState adpcm_state{};
InterpolationState interp_state{};
std::vector<s16> samples;
VoiceOutStatus out_status{};
VoiceInfo info{};
};
class VoiceState;
AudioRendererParameter worker_params;
Kernel::SharedPtr<Kernel::Event> buffer_event;
std::vector<VoiceState> voices;
std::unique_ptr<AudioCore::AudioOut> audio_out;
std::unique_ptr<AudioOut> audio_out;
AudioCore::StreamPtr stream;
};

View File

@@ -7,6 +7,7 @@
#include "audio_core/sink.h"
#include "audio_core/sink_details.h"
#include "audio_core/sink_stream.h"
#include "audio_core/stream.h"
#include "common/assert.h"
#include "common/logging/log.h"

View File

@@ -11,13 +11,16 @@
#include <queue>
#include "audio_core/buffer.h"
#include "audio_core/sink_stream.h"
#include "common/assert.h"
#include "common/common_types.h"
#include "core/core_timing.h"
namespace CoreTiming {
struct EventType;
}
namespace AudioCore {
class SinkStream;
/**
* Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut
*/

View File

@@ -4,7 +4,6 @@
#pragma once
#include <array>
#include <cstddef>
#include <SoundTouch.h>
#include "common/common_types.h"

View File

@@ -10,7 +10,7 @@
namespace Core {
/// Generic ARM11 CPU interface
/// Generic ARMv8 CPU interface
class ARM_Interface : NonCopyable {
public:
virtual ~ARM_Interface() {}
@@ -19,9 +19,9 @@ public:
std::array<u64, 31> cpu_registers;
u64 sp;
u64 pc;
u64 cpsr;
std::array<u128, 32> fpu_registers;
u64 fpscr;
u64 pstate;
std::array<u128, 32> vector_registers;
u64 fpcr;
};
/// Runs the CPU until an event happens
@@ -69,42 +69,50 @@ public:
*/
virtual void SetReg(int index, u64 value) = 0;
virtual u128 GetExtReg(int index) const = 0;
virtual void SetExtReg(int index, u128 value) = 0;
/**
* Gets the value of a specified vector register.
*
* @param index The index of the vector register.
* @return the value within the vector register.
*/
virtual u128 GetVectorReg(int index) const = 0;
/**
* Gets the value of a VFP register
* @param index Register index (0-31)
* @return Returns the value in the register
* Sets a given value into a vector register.
*
* @param index The index of the vector register.
* @param value The new value to place in the register.
*/
virtual u32 GetVFPReg(int index) const = 0;
virtual void SetVectorReg(int index, u128 value) = 0;
/**
* Sets a VFP register to the given value
* @param index Register index (0-31)
* @param value Value to set register to
* Get the current PSTATE register
* @return Returns the value of the PSTATE register
*/
virtual void SetVFPReg(int index, u32 value) = 0;
virtual u32 GetPSTATE() const = 0;
/**
* Get the current CPSR register
* @return Returns the value of the CPSR register
* Set the current PSTATE register
* @param pstate Value to set PSTATE to
*/
virtual u32 GetCPSR() const = 0;
/**
* Set the current CPSR register
* @param cpsr Value to set CPSR to
*/
virtual void SetCPSR(u32 cpsr) = 0;
virtual void SetPSTATE(u32 pstate) = 0;
virtual VAddr GetTlsAddress() const = 0;
virtual void SetTlsAddress(VAddr address) = 0;
/**
* Gets the value within the TPIDR_EL0 (read/write software thread ID) register.
*
* @return the value within the register.
*/
virtual u64 GetTPIDR_EL0() const = 0;
/**
* Sets a new value within the TPIDR_EL0 (read/write software thread ID) register.
*
* @param value The new value to place in the register.
*/
virtual void SetTPIDR_EL0(u64 value) = 0;
/**
@@ -119,6 +127,7 @@ public:
*/
virtual void LoadContext(const ThreadContext& ctx) = 0;
/// Clears the exclusive monitor's state.
virtual void ClearExclusiveState() = 0;
/// Prepare core for thread reschedule (if needed to correctly handle state)

View File

@@ -194,29 +194,20 @@ void ARM_Dynarmic::SetReg(int index, u64 value) {
jit->SetRegister(index, value);
}
u128 ARM_Dynarmic::GetExtReg(int index) const {
u128 ARM_Dynarmic::GetVectorReg(int index) const {
return jit->GetVector(index);
}
void ARM_Dynarmic::SetExtReg(int index, u128 value) {
void ARM_Dynarmic::SetVectorReg(int index, u128 value) {
jit->SetVector(index, value);
}
u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const {
UNIMPLEMENTED();
return {};
}
void ARM_Dynarmic::SetVFPReg(int /*index*/, u32 /*value*/) {
UNIMPLEMENTED();
}
u32 ARM_Dynarmic::GetCPSR() const {
u32 ARM_Dynarmic::GetPSTATE() const {
return jit->GetPstate();
}
void ARM_Dynarmic::SetCPSR(u32 cpsr) {
jit->SetPstate(cpsr);
void ARM_Dynarmic::SetPSTATE(u32 pstate) {
jit->SetPstate(pstate);
}
u64 ARM_Dynarmic::GetTlsAddress() const {
@@ -239,18 +230,18 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
ctx.cpu_registers = jit->GetRegisters();
ctx.sp = jit->GetSP();
ctx.pc = jit->GetPC();
ctx.cpsr = jit->GetPstate();
ctx.fpu_registers = jit->GetVectors();
ctx.fpscr = jit->GetFpcr();
ctx.pstate = jit->GetPstate();
ctx.vector_registers = jit->GetVectors();
ctx.fpcr = jit->GetFpcr();
}
void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
jit->SetRegisters(ctx.cpu_registers);
jit->SetSP(ctx.sp);
jit->SetPC(ctx.pc);
jit->SetPstate(static_cast<u32>(ctx.cpsr));
jit->SetVectors(ctx.fpu_registers);
jit->SetFpcr(static_cast<u32>(ctx.fpscr));
jit->SetPstate(static_cast<u32>(ctx.pstate));
jit->SetVectors(ctx.vector_registers);
jit->SetFpcr(static_cast<u32>(ctx.fpcr));
}
void ARM_Dynarmic::PrepareReschedule() {
@@ -304,8 +295,8 @@ bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr va
bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) {
return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
Memory::Write64(vaddr, value[0]);
Memory::Write64(vaddr, value[1]);
Memory::Write64(vaddr + 0, value[0]);
Memory::Write64(vaddr + 8, value[1]);
});
}

View File

@@ -29,14 +29,12 @@ public:
u64 GetPC() const override;
u64 GetReg(int index) const override;
void SetReg(int index, u64 value) override;
u128 GetExtReg(int index) const override;
void SetExtReg(int index, u128 value) override;
u32 GetVFPReg(int index) const override;
void SetVFPReg(int index, u32 value) override;
u32 GetCPSR() const override;
u128 GetVectorReg(int index) const override;
void SetVectorReg(int index, u128 value) override;
u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override;
void Run() override;
void Step() override;
void SetCPSR(u32 cpsr) override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override;

View File

@@ -131,33 +131,24 @@ void ARM_Unicorn::SetReg(int regn, u64 val) {
CHECKED(uc_reg_write(uc, treg, &val));
}
u128 ARM_Unicorn::GetExtReg(int /*index*/) const {
u128 ARM_Unicorn::GetVectorReg(int /*index*/) const {
UNIMPLEMENTED();
static constexpr u128 res{};
return res;
}
void ARM_Unicorn::SetExtReg(int /*index*/, u128 /*value*/) {
void ARM_Unicorn::SetVectorReg(int /*index*/, u128 /*value*/) {
UNIMPLEMENTED();
}
u32 ARM_Unicorn::GetVFPReg(int /*index*/) const {
UNIMPLEMENTED();
return {};
}
void ARM_Unicorn::SetVFPReg(int /*index*/, u32 /*value*/) {
UNIMPLEMENTED();
}
u32 ARM_Unicorn::GetCPSR() const {
u32 ARM_Unicorn::GetPSTATE() const {
u64 nzcv{};
CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv));
return static_cast<u32>(nzcv);
}
void ARM_Unicorn::SetCPSR(u32 cpsr) {
u64 nzcv = cpsr;
void ARM_Unicorn::SetPSTATE(u32 pstate) {
u64 nzcv = pstate;
CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv));
}
@@ -219,7 +210,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp));
CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc));
CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.cpsr));
CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
for (auto i = 0; i < 29; ++i) {
uregs[i] = UC_ARM64_REG_X0 + i;
@@ -234,7 +225,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
for (int i = 0; i < 32; ++i) {
uregs[i] = UC_ARM64_REG_Q0 + i;
tregs[i] = &ctx.fpu_registers[i];
tregs[i] = &ctx.vector_registers[i];
}
CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
@@ -246,7 +237,7 @@ void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp));
CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc));
CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.cpsr));
CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
for (int i = 0; i < 29; ++i) {
uregs[i] = UC_ARM64_REG_X0 + i;
@@ -261,7 +252,7 @@ void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
for (auto i = 0; i < 32; ++i) {
uregs[i] = UC_ARM64_REG_Q0 + i;
tregs[i] = (void*)&ctx.fpu_registers[i];
tregs[i] = (void*)&ctx.vector_registers[i];
}
CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32));

View File

@@ -22,12 +22,10 @@ public:
u64 GetPC() const override;
u64 GetReg(int index) const override;
void SetReg(int index, u64 value) override;
u128 GetExtReg(int index) const override;
void SetExtReg(int index, u128 value) override;
u32 GetVFPReg(int index) const override;
void SetVFPReg(int index, u32 value) override;
u32 GetCPSR() const override;
void SetCPSR(u32 cpsr) override;
u128 GetVectorReg(int index) const override;
void SetVectorReg(int index, u128 value) override;
u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override;

View File

@@ -9,6 +9,7 @@
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic.h"
#endif
#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
#include "core/core_cpu.h"
#include "core/core_timing.h"
@@ -66,6 +67,8 @@ Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
}
Cpu::~Cpu() = default;
std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) {
if (Settings::values.use_cpu_jit) {
#ifdef ARCHITECTURE_x86_64

View File

@@ -6,11 +6,10 @@
#include <atomic>
#include <condition_variable>
#include <cstddef>
#include <memory>
#include <mutex>
#include <string>
#include "common/common_types.h"
#include "core/arm/exclusive_monitor.h"
namespace Kernel {
class Scheduler;
@@ -19,6 +18,7 @@ class Scheduler;
namespace Core {
class ARM_Interface;
class ExclusiveMonitor;
constexpr unsigned NUM_CPU_CORES{4};
@@ -43,6 +43,7 @@ class Cpu {
public:
Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
std::shared_ptr<CpuBarrier> cpu_barrier, std::size_t core_index);
~Cpu();
void RunLoop(bool tight_loop = true);

View File

@@ -65,9 +65,9 @@ constexpr u32 MSG_WAITALL = 8;
constexpr u32 LR_REGISTER = 30;
constexpr u32 SP_REGISTER = 31;
constexpr u32 PC_REGISTER = 32;
constexpr u32 CPSR_REGISTER = 33;
constexpr u32 PSTATE_REGISTER = 33;
constexpr u32 UC_ARM64_REG_Q0 = 34;
constexpr u32 FPSCR_REGISTER = 66;
constexpr u32 FPCR_REGISTER = 66;
// TODO/WiP - Used while working on support for FPU
constexpr u32 TODO_DUMMY_REG_997 = 997;
@@ -116,7 +116,7 @@ constexpr char target_xml[] =
<reg name="pc" bitsize="64" type="code_ptr"/>
<flags id="cpsr_flags" size="4">
<flags id="pstate_flags" size="4">
<field name="SP" start="0" end="0"/>
<field name="" start="1" end="1"/>
<field name="EL" start="2" end="3"/>
@@ -135,7 +135,7 @@ constexpr char target_xml[] =
<field name="Z" start="30" end="30"/>
<field name="N" start="31" end="31"/>
</flags>
<reg name="cpsr" bitsize="32" type="cpsr_flags"/>
<reg name="pstate" bitsize="32" type="pstate_flags"/>
</feature>
<feature name="org.gnu.gdb.aarch64.fpu">
</feature>
@@ -227,10 +227,10 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
return thread->context.sp;
} else if (id == PC_REGISTER) {
return thread->context.pc;
} else if (id == CPSR_REGISTER) {
return thread->context.cpsr;
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
return thread->context.fpu_registers[id - UC_ARM64_REG_Q0][0];
} else if (id == PSTATE_REGISTER) {
return thread->context.pstate;
} else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) {
return thread->context.vector_registers[id - UC_ARM64_REG_Q0][0];
} else {
return 0;
}
@@ -247,10 +247,10 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
thread->context.sp = val;
} else if (id == PC_REGISTER) {
thread->context.pc = val;
} else if (id == CPSR_REGISTER) {
thread->context.cpsr = val;
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
thread->context.fpu_registers[id - (CPSR_REGISTER + 1)][0] = val;
} else if (id == PSTATE_REGISTER) {
thread->context.pstate = val;
} else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) {
thread->context.vector_registers[id - (PSTATE_REGISTER + 1)][0] = val;
}
}
@@ -781,11 +781,11 @@ static void ReadRegister() {
LongToGdbHex(reply, RegRead(id, current_thread));
} else if (id == PC_REGISTER) {
LongToGdbHex(reply, RegRead(id, current_thread));
} else if (id == CPSR_REGISTER) {
IntToGdbHex(reply, (u32)RegRead(id, current_thread));
} else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) {
} else if (id == PSTATE_REGISTER) {
IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread)));
} else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
LongToGdbHex(reply, RegRead(id, current_thread));
} else if (id == FPSCR_REGISTER) {
} else if (id == FPCR_REGISTER) {
LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread));
} else {
LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread));
@@ -811,7 +811,7 @@ static void ReadRegisters() {
bufptr += 16;
IntToGdbHex(bufptr, (u32)RegRead(CPSR_REGISTER, current_thread));
IntToGdbHex(bufptr, static_cast<u32>(RegRead(PSTATE_REGISTER, current_thread)));
bufptr += 8;
@@ -843,11 +843,11 @@ static void WriteRegister() {
RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
} else if (id == PC_REGISTER) {
RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
} else if (id == CPSR_REGISTER) {
} else if (id == PSTATE_REGISTER) {
RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
} else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) {
} else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
} else if (id == FPSCR_REGISTER) {
} else if (id == FPCR_REGISTER) {
RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread);
} else {
RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread);
@@ -866,16 +866,16 @@ static void WriteRegisters() {
if (command_buffer[0] != 'G')
return SendReply("E01");
for (u32 i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) {
for (u32 i = 0, reg = 0; reg <= FPCR_REGISTER; i++, reg++) {
if (reg <= SP_REGISTER) {
RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == PC_REGISTER) {
RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == CPSR_REGISTER) {
RegWrite(CPSR_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread);
} else if (reg >= UC_ARM64_REG_Q0 && reg < FPSCR_REGISTER) {
} else if (reg == PSTATE_REGISTER) {
RegWrite(PSTATE_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread);
} else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) {
RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == FPSCR_REGISTER) {
} else if (reg == FPCR_REGISTER) {
RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else {
UNIMPLEMENTED();

View File

@@ -290,13 +290,6 @@ public:
Skip(CommandIdSize, false);
}
ResponseBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy,
u32 num_handles_to_move,
ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) const {
return ResponseBuilder{*context, normal_params_size, num_handles_to_copy,
num_handles_to_move, flags};
}
template <typename T>
T Pop();

View File

@@ -62,7 +62,7 @@ ResultCode Mutex::TryAcquire(HandleTable& handle_table, VAddr address, Handle ho
Handle requesting_thread_handle) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress);
return ERR_INVALID_ADDRESS;
}
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
ResultCode Mutex::Release(VAddr address) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress);
return ERR_INVALID_ADDRESS;
}
auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address);

View File

@@ -280,6 +280,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
"requesting_current_thread_handle=0x{:08X}",
holding_thread_handle, mutex_addr, requesting_thread_handle);
if (Memory::IsKernelVirtualAddress(mutex_addr)) {
return ERR_INVALID_ADDRESS_STATE;
}
auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
requesting_thread_handle);
@@ -289,6 +293,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr);
if (Memory::IsKernelVirtualAddress(mutex_addr)) {
return ERR_INVALID_ADDRESS_STATE;
}
return Mutex::Release(mutex_addr);
}

View File

@@ -13,7 +13,9 @@
namespace Kernel {
#define PARAM(n) Core::CurrentArmInterface().GetReg(n)
static inline u64 Param(int n) {
return Core::CurrentArmInterface().GetReg(n);
}
/**
* HLE a function return from the current ARM userland process
@@ -28,23 +30,23 @@ static inline void FuncReturn(u64 res) {
template <ResultCode func(u64)>
void SvcWrap() {
FuncReturn(func(PARAM(0)).raw);
FuncReturn(func(Param(0)).raw);
}
template <ResultCode func(u32)>
void SvcWrap() {
FuncReturn(func((u32)PARAM(0)).raw);
FuncReturn(func((u32)Param(0)).raw);
}
template <ResultCode func(u32, u32)>
void SvcWrap() {
FuncReturn(func((u32)PARAM(0), (u32)PARAM(1)).raw);
FuncReturn(func((u32)Param(0), (u32)Param(1)).raw);
}
template <ResultCode func(u32*, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, (u32)PARAM(1)).raw;
u32 retval = func(&param_1, (u32)Param(1)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -52,39 +54,39 @@ void SvcWrap() {
template <ResultCode func(u32*, u64)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(1)).raw;
u32 retval = func(&param_1, Param(1)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
template <ResultCode func(u64, s32)>
void SvcWrap() {
FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw);
FuncReturn(func(Param(0), (s32)Param(1)).raw);
}
template <ResultCode func(u64*, u64)>
void SvcWrap() {
u64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1)).raw;
u32 retval = func(&param_1, Param(1)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
template <ResultCode func(u32, u64)>
void SvcWrap() {
FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), PARAM(1)).raw);
FuncReturn(func((u32)(Param(0) & 0xFFFFFFFF), Param(1)).raw);
}
template <ResultCode func(u32, u32, u64)>
void SvcWrap() {
FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), (u32)(PARAM(1) & 0xFFFFFFFF), PARAM(2)).raw);
FuncReturn(func((u32)(Param(0) & 0xFFFFFFFF), (u32)(Param(1) & 0xFFFFFFFF), Param(2)).raw);
}
template <ResultCode func(u32, u32*, u64*)>
void SvcWrap() {
u32 param_1 = 0;
u64 param_2 = 0;
ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2);
ResultCode retval = func((u32)(Param(2) & 0xFFFFFFFF), &param_1, &param_2);
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CurrentArmInterface().SetReg(2, param_2);
FuncReturn(retval.raw);
@@ -93,46 +95,46 @@ void SvcWrap() {
template <ResultCode func(u64, u64, u32, u32)>
void SvcWrap() {
FuncReturn(
func(PARAM(0), PARAM(1), (u32)(PARAM(3) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw);
func(Param(0), Param(1), (u32)(Param(3) & 0xFFFFFFFF), (u32)(Param(3) & 0xFFFFFFFF)).raw);
}
template <ResultCode func(u32, u64, u32)>
void SvcWrap() {
FuncReturn(func((u32)PARAM(0), PARAM(1), (u32)PARAM(2)).raw);
FuncReturn(func((u32)Param(0), Param(1), (u32)Param(2)).raw);
}
template <ResultCode func(u64, u64, u64)>
void SvcWrap() {
FuncReturn(func(PARAM(0), PARAM(1), PARAM(2)).raw);
FuncReturn(func(Param(0), Param(1), Param(2)).raw);
}
template <ResultCode func(u32, u64, u64, u32)>
void SvcWrap() {
FuncReturn(func((u32)PARAM(0), PARAM(1), PARAM(2), (u32)PARAM(3)).raw);
FuncReturn(func((u32)Param(0), Param(1), Param(2), (u32)Param(3)).raw);
}
template <ResultCode func(u32, u64, u64)>
void SvcWrap() {
FuncReturn(func((u32)PARAM(0), PARAM(1), PARAM(2)).raw);
FuncReturn(func((u32)Param(0), Param(1), Param(2)).raw);
}
template <ResultCode func(u32*, u64, u64, s64)>
void SvcWrap() {
u32 param_1 = 0;
ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3));
ResultCode retval = func(&param_1, Param(1), (u32)(Param(2) & 0xFFFFFFFF), (s64)Param(3));
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval.raw);
}
template <ResultCode func(u64, u64, u32, s64)>
void SvcWrap() {
FuncReturn(func(PARAM(0), PARAM(1), (u32)PARAM(2), (s64)PARAM(3)).raw);
FuncReturn(func(Param(0), Param(1), (u32)Param(2), (s64)Param(3)).raw);
}
template <ResultCode func(u64*, u64, u64, u64)>
void SvcWrap() {
u64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3)).raw;
u32 retval = func(&param_1, Param(1), Param(2), Param(3)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -141,7 +143,7 @@ template <ResultCode func(u32*, u64, u64, u64, u32, s32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval =
func(&param_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))
func(&param_1, Param(1), Param(2), Param(3), (u32)Param(4), (s32)(Param(5) & 0xFFFFFFFF))
.raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
@@ -151,13 +153,13 @@ template <ResultCode func(MemoryInfo*, PageInfo*, u64)>
void SvcWrap() {
MemoryInfo memory_info = {};
PageInfo page_info = {};
u32 retval = func(&memory_info, &page_info, PARAM(2)).raw;
u32 retval = func(&memory_info, &page_info, Param(2)).raw;
Memory::Write64(PARAM(0), memory_info.base_address);
Memory::Write64(PARAM(0) + 8, memory_info.size);
Memory::Write32(PARAM(0) + 16, memory_info.type);
Memory::Write32(PARAM(0) + 20, memory_info.attributes);
Memory::Write32(PARAM(0) + 24, memory_info.permission);
Memory::Write64(Param(0), memory_info.base_address);
Memory::Write64(Param(0) + 8, memory_info.size);
Memory::Write32(Param(0) + 16, memory_info.type);
Memory::Write32(Param(0) + 20, memory_info.attributes);
Memory::Write32(Param(0) + 24, memory_info.permission);
FuncReturn(retval);
}
@@ -165,7 +167,7 @@ void SvcWrap() {
template <ResultCode func(u32*, u64, u64, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
u32 retval = func(&param_1, Param(1), Param(2), (u32)(Param(3) & 0xFFFFFFFF)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -174,7 +176,7 @@ template <ResultCode func(Handle*, u64, u32, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval =
func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
func(&param_1, Param(1), (u32)(Param(2) & 0xFFFFFFFF), (u32)(Param(3) & 0xFFFFFFFF)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -182,14 +184,14 @@ void SvcWrap() {
template <ResultCode func(u64, u32, s32, s64)>
void SvcWrap() {
FuncReturn(
func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3))
func(Param(0), (u32)(Param(1) & 0xFFFFFFFF), (s32)(Param(2) & 0xFFFFFFFF), (s64)Param(3))
.raw);
}
template <ResultCode func(u64, u32, s32, s32)>
void SvcWrap() {
FuncReturn(func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF),
(s32)(PARAM(3) & 0xFFFFFFFF))
FuncReturn(func(Param(0), (u32)(Param(1) & 0xFFFFFFFF), (s32)(Param(2) & 0xFFFFFFFF),
(s32)(Param(3) & 0xFFFFFFFF))
.raw);
}
@@ -219,20 +221,17 @@ void SvcWrap() {
template <void func(s64)>
void SvcWrap() {
func((s64)PARAM(0));
func((s64)Param(0));
}
template <void func(u64, u64 len)>
void SvcWrap() {
func(PARAM(0), PARAM(1));
func(Param(0), Param(1));
}
template <void func(u64, u64, u64)>
void SvcWrap() {
func(PARAM(0), PARAM(1), PARAM(2));
func(Param(0), Param(1), Param(2));
}
#undef PARAM
#undef FuncReturn
} // namespace Kernel

View File

@@ -217,8 +217,8 @@ static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAdd
context.cpu_registers[0] = arg;
context.pc = entry_point;
context.sp = stack_top;
context.cpsr = 0;
context.fpscr = 0;
context.pstate = 0;
context.fpcr = 0;
}
ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point,

View File

@@ -34,7 +34,7 @@ public:
static const FunctionInfo functions[] = {
{0, &IProfile::Get, "Get"},
{1, &IProfile::GetBase, "GetBase"},
{10, nullptr, "GetImageSize"},
{10, &IProfile::GetImageSize, "GetImageSize"},
{11, &IProfile::LoadImage, "LoadImage"},
};
RegisterHandlers(functions);
@@ -93,6 +93,14 @@ private:
rb.Push<u32>(jpeg_size);
}
void GetImageSize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr u32 jpeg_size = 107;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(jpeg_size);
}
const ProfileManager& profile_manager;
UUID user_id; ///< The user id this profile refers to.
};

View File

@@ -25,7 +25,7 @@ const UUID& UUID::Generate() {
ProfileManager::ProfileManager() {
// TODO(ogniK): Create the default user we have for now until loading/saving users is added
auto user_uuid = UUID{1, 0};
CreateNewUser(user_uuid, Settings::values.username);
ASSERT(CreateNewUser(user_uuid, Settings::values.username).IsSuccess());
OpenUser(user_uuid);
}
@@ -91,7 +91,8 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& usern
/// specifically by allowing an std::string for the username. This is required specifically since
/// we're loading a string straight from the config
ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) {
ProfileUsername username_output;
ProfileUsername username_output{};
if (username.size() > username_output.size()) {
std::copy_n(username.begin(), username_output.size(), username_output.begin());
} else {

View File

@@ -462,7 +462,7 @@ private:
std::memcpy(&buffer[offset], data.data(), data.size());
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)};
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called, offset={}", offset);
@@ -478,7 +478,7 @@ private:
ctx.WriteBuffer(buffer.data() + offset, size);
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)};
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called, offset={}", offset);
@@ -568,7 +568,7 @@ private:
IPC::RequestParser rp{ctx};
storage_stack.push(rp.PopIpcInterface<AM::IStorage>());
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)};
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called");
@@ -616,7 +616,7 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
const u64 size{rp.Pop<u64>()};
std::vector<u8> buffer(size);
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 1)};
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorage>(std::move(buffer));

View File

@@ -190,7 +190,7 @@ void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
ctx.WriteBuffer(DefaultDevice);
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1); // Amount of audio devices

View File

@@ -137,7 +137,7 @@ private:
constexpr std::array<char, 15> audio_interface{{"AudioInterface"}};
ctx.WriteBuffer(audio_interface);
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
}
@@ -151,7 +151,7 @@ private:
auto file_buffer = ctx.ReadBuffer();
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -162,7 +162,7 @@ private:
constexpr std::array<char, 12> audio_interface{{"AudioDevice"}};
ctx.WriteBuffer(audio_interface);
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
}

View File

@@ -313,7 +313,7 @@ public:
{64, nullptr, "DeactivateJoySixAxisSensor"},
{65, nullptr, "GetJoySixAxisSensorLifoHandle"},
{66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
{67, nullptr, "StopSixAxisSensor"},
{67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
{68, nullptr, "IsSixAxisSensorFusionEnabled"},
{69, nullptr, "EnableSixAxisSensorFusion"},
{70, nullptr, "SetSixAxisSensorFusionParameters"},
@@ -329,7 +329,7 @@ public:
{80, nullptr, "GetGyroscopeZeroDriftMode"},
{81, nullptr, "ResetGyroscopeZeroDriftMode"},
{82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
{91, nullptr, "ActivateGesture"},
{91, &Hid::ActivateGesture, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
{102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
@@ -364,8 +364,8 @@ public:
{208, nullptr, "GetActualVibrationGcErmCommand"},
{209, nullptr, "BeginPermitVibrationSession"},
{210, nullptr, "EndPermitVibrationSession"},
{300, nullptr, "ActivateConsoleSixAxisSensor"},
{301, nullptr, "StartConsoleSixAxisSensor"},
{300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
{301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
{302, nullptr, "StopConsoleSixAxisSensor"},
{303, nullptr, "ActivateSevenSixAxisSensor"},
{304, nullptr, "StartSevenSixAxisSensor"},
@@ -579,6 +579,30 @@ private:
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateGesture(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
};
class HidDbg final : public ServiceFramework<HidDbg> {

View File

@@ -108,7 +108,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
auto client_port = service_manager->GetServicePort(name);
if (client_port.Failed()) {
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(client_port.Code());
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, client_port.Code().raw);
if (name.length() == 0)
@@ -121,8 +121,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
ASSERT(session.Succeeded());
if (session.Succeeded()) {
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, (*session)->GetObjectId());
IPC::ResponseBuilder rb =
rp.MakeBuilder(2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles);
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(session.Code());
rb.PushMoveObjects(std::move(session).Unwrap());
}

View File

@@ -71,7 +71,7 @@ private:
LOG_WARNING(Service_SSL, "(STUBBED) called");
IPC::RequestParser rp{ctx};
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}

View File

@@ -650,7 +650,7 @@ private:
u64 layer_id = rp.Pop<u64>();
u64 z_value = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -658,7 +658,7 @@ private:
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
bool visibility = rp.Pop<bool>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:08X}, visibility={}", layer_id,
visibility);
@@ -747,7 +747,7 @@ private:
IPC::RequestParser rp{ctx};
u64 display = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -761,7 +761,7 @@ private:
u64 layer_id = nv_flinger->CreateLayer(display);
IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(layer_id);
}
@@ -772,7 +772,7 @@ private:
u32 stack = rp.Pop<u32>();
u64 layer_id = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -780,7 +780,7 @@ private:
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
bool visibility = rp.Pop<bool>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
visibility);
@@ -837,7 +837,7 @@ private:
ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(nv_flinger->OpenDisplay(name));
}
@@ -847,7 +847,7 @@ private:
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -856,7 +856,7 @@ private:
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode) {
@@ -874,7 +874,7 @@ private:
u32 scaling_mode = rp.Pop<u32>();
u64 unknown = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -882,7 +882,7 @@ private:
IPC::RequestParser rp{ctx};
DisplayInfo display_info;
ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(1);
LOG_WARNING(Service_VI, "(STUBBED) called");
@@ -903,7 +903,7 @@ private:
u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
}
@@ -922,7 +922,7 @@ private:
u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push(layer_id);
rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
@@ -934,7 +934,7 @@ private:
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -945,7 +945,7 @@ private:
auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 1, 0);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(vsync_event);
}

View File

@@ -240,6 +240,41 @@ enum class FlowCondition : u64 {
Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
};
enum class ControlCode : u64 {
F = 0,
LT = 1,
EQ = 2,
LE = 3,
GT = 4,
NE = 5,
GE = 6,
Num = 7,
Nan = 8,
LTU = 9,
EQU = 10,
LEU = 11,
GTU = 12,
NEU = 13,
GEU = 14,
//
OFF = 16,
LO = 17,
SFF = 18,
LS = 19,
HI = 20,
SFT = 21,
HS = 22,
OFT = 23,
CSM_TA = 24,
CSM_TR = 25,
CSM_MX = 26,
FCSM_TA = 27,
FCSM_TR = 28,
FCSM_MX = 29,
RLE = 30,
RGT = 31,
};
enum class PredicateResultMode : u64 {
None = 0x0,
NotZero = 0x3,
@@ -271,6 +306,15 @@ enum class TextureProcessMode : u64 {
LLA = 7 // Load LOD. The A is unknown, does not appear to differ with LL
};
enum class TextureMiscMode : u64 {
DC,
AOFFI, // Uses Offset
NDV,
NODEP,
MZ,
PTP,
};
enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 };
enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 };
@@ -545,6 +589,15 @@ union Instruction {
BitField<45, 2, PredOperation> op;
} pset;
union {
BitField<0, 3, u64> pred0;
BitField<3, 3, u64> pred3;
BitField<8, 5, ControlCode> cc; // flag in cc
BitField<39, 3, u64> pred39;
BitField<42, 1, u64> neg_pred39;
BitField<45, 4, PredOperation> op; // op with pred39
} csetp;
union {
BitField<39, 3, u64> pred39;
BitField<42, 1, u64> neg_pred;
@@ -590,42 +643,127 @@ union Instruction {
BitField<28, 1, u64> array;
BitField<29, 2, TextureType> texture_type;
BitField<31, 4, u64> component_mask;
BitField<49, 1, u64> nodep_flag;
BitField<50, 1, u64> dc_flag;
BitField<54, 1, u64> aoffi_flag;
BitField<55, 3, TextureProcessMode> process_mode;
bool IsComponentEnabled(std::size_t component) const {
return ((1ull << component) & component_mask) != 0;
}
TextureProcessMode GetTextureProcessMode() const {
return process_mode;
}
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return dc_flag != 0;
case TextureMiscMode::NODEP:
return nodep_flag != 0;
case TextureMiscMode::AOFFI:
return aoffi_flag != 0;
default:
break;
}
return false;
}
} tex;
union {
BitField<22, 6, TextureQueryType> query_type;
BitField<31, 4, u64> component_mask;
BitField<49, 1, u64> nodep_flag;
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NODEP:
return nodep_flag != 0;
default:
break;
}
return false;
}
} txq;
union {
BitField<28, 1, u64> array;
BitField<29, 2, TextureType> texture_type;
BitField<31, 4, u64> component_mask;
BitField<35, 1, u64> ndv_flag;
BitField<49, 1, u64> nodep_flag;
bool IsComponentEnabled(std::size_t component) const {
return ((1ull << component) & component_mask) != 0;
}
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NDV:
return (ndv_flag != 0);
case TextureMiscMode::NODEP:
return (nodep_flag != 0);
default:
break;
}
return false;
}
} tmml;
union {
BitField<28, 1, u64> array;
BitField<29, 2, TextureType> texture_type;
BitField<35, 1, u64> ndv_flag;
BitField<49, 1, u64> nodep_flag;
BitField<50, 1, u64> dc_flag;
BitField<54, 2, u64> info;
BitField<56, 2, u64> component;
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NDV:
return ndv_flag != 0;
case TextureMiscMode::NODEP:
return nodep_flag != 0;
case TextureMiscMode::DC:
return dc_flag != 0;
case TextureMiscMode::AOFFI:
return info == 1;
case TextureMiscMode::PTP:
return info == 2;
default:
break;
}
return false;
}
} tld4;
union {
BitField<49, 1, u64> nodep_flag;
BitField<50, 1, u64> dc_flag;
BitField<51, 1, u64> aoffi_flag;
BitField<52, 2, u64> component;
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return dc_flag != 0;
case TextureMiscMode::NODEP:
return nodep_flag != 0;
case TextureMiscMode::AOFFI:
return aoffi_flag != 0;
default:
break;
}
return false;
}
} tld4s;
union {
BitField<0, 8, Register> gpr0;
BitField<28, 8, Register> gpr28;
BitField<49, 1, u64> nodep;
BitField<49, 1, u64> nodep_flag;
BitField<50, 3, u64> component_mask_selector;
BitField<53, 4, u64> texture_info;
@@ -645,6 +783,37 @@ union Instruction {
UNREACHABLE();
}
TextureProcessMode GetTextureProcessMode() const {
switch (texture_info) {
case 0:
case 2:
case 6:
case 8:
case 9:
case 11:
return TextureProcessMode::LZ;
case 3:
case 5:
case 13:
return TextureProcessMode::LL;
default:
break;
}
return TextureProcessMode::None;
}
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return (texture_info >= 4 && texture_info <= 6) || texture_info == 9;
case TextureMiscMode::NODEP:
return nodep_flag != 0;
default:
break;
}
return false;
}
bool IsArrayTexture() const {
// TEXS only supports Texture2D arrays.
return texture_info >= 7 && texture_info <= 9;
@@ -673,6 +842,7 @@ union Instruction {
} texs;
union {
BitField<49, 1, u64> nodep_flag;
BitField<53, 4, u64> texture_info;
TextureType GetTextureType() const {
@@ -693,6 +863,26 @@ union Instruction {
UNREACHABLE();
}
TextureProcessMode GetTextureProcessMode() const {
if (texture_info == 1 || texture_info == 5 || texture_info == 12)
return TextureProcessMode::LL;
return TextureProcessMode::LZ;
}
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::AOFFI:
return texture_info == 12 || texture_info == 4;
case TextureMiscMode::MZ:
return texture_info == 5;
case TextureMiscMode::NODEP:
return nodep_flag != 0;
default:
break;
}
return false;
}
bool IsArrayTexture() const {
// TEXS only supports Texture2D arrays.
return texture_info == 8;
@@ -735,6 +925,7 @@ union Instruction {
BitField<36, 5, u64> index;
} cbuf36;
BitField<47, 1, u64> generates_cc;
BitField<61, 1, u64> is_b_imm;
BitField<60, 1, u64> is_b_gpr;
BitField<59, 1, u64> is_c_gpr;
@@ -859,6 +1050,7 @@ public:
ISET_IMM,
PSETP,
PSET,
CSETP,
XMAD_IMM,
XMAD_CR,
XMAD_RC,
@@ -1095,6 +1287,7 @@ private:
INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"),
INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
INST("010100001010----", Id::CSETP, Type::PredicateSetPredicate, "CSETP"),
INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"),

View File

@@ -236,6 +236,14 @@ private:
const std::string& suffix;
};
enum class InternalFlag : u64 {
ZeroFlag = 0,
CarryFlag = 1,
OverflowFlag = 2,
NaNFlag = 3,
Amount
};
/**
* Used to manage shader registers that are emulated with GLSL. This class keeps track of the state
* of all registers (e.g. whether they are currently being used as Floats or Integers), and
@@ -329,13 +337,19 @@ public:
void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem,
const std::string& value, u64 dest_num_components,
u64 value_num_components, bool is_saturated = false,
u64 dest_elem = 0, Register::Size size = Register::Size::Word) {
u64 dest_elem = 0, Register::Size size = Register::Size::Word,
bool sets_cc = false) {
ASSERT_MSG(!is_saturated, "Unimplemented");
const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"};
SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')',
dest_num_components, value_num_components, dest_elem);
if (sets_cc) {
const std::string zero_condition = "( " + ConvertIntegerSize(value, size) + " == 0 )";
SetInternalFlag(InternalFlag::ZeroFlag, zero_condition);
}
}
/**
@@ -352,6 +366,26 @@ public:
shader.AddLine(dest + " = " + src + ';');
}
std::string GetControlCode(const Tegra::Shader::ControlCode cc) const {
switch (cc) {
case Tegra::Shader::ControlCode::NEU:
return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')';
default:
LOG_CRITICAL(HW_GPU, "Unimplemented Control Code {}", static_cast<u32>(cc));
UNREACHABLE();
return "false";
}
}
std::string GetInternalFlag(const InternalFlag ii) const {
const u32 code = static_cast<u32>(ii);
return "internalFlag_" + std::to_string(code) + suffix;
}
void SetInternalFlag(const InternalFlag ii, const std::string& value) const {
shader.AddLine(GetInternalFlag(ii) + " = " + value + ';');
}
/**
* Writes code that does a output attribute assignment to register operation. Output attributes
* are stored as floats, so this may require conversion.
@@ -415,6 +449,12 @@ public:
}
declarations.AddNewLine();
for (u32 ii = 0; ii < static_cast<u64>(InternalFlag::Amount); ii++) {
const InternalFlag code = static_cast<InternalFlag>(ii);
declarations.AddLine("bool " + GetInternalFlag(code) + " = false;");
}
declarations.AddNewLine();
for (const auto element : declr_input_attribute) {
// TODO(bunnei): Use proper number of elements for these
u32 idx =
@@ -938,8 +978,6 @@ private:
// TEXS has two destination registers and a swizzle. The first two elements in the swizzle
// go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1
ASSERT_MSG(instr.texs.nodep == 0, "TEXS nodep not implemented");
std::size_t written_components = 0;
for (u32 component = 0; component < 4; ++component) {
if (!instr.texs.IsComponentEnabled(component)) {
@@ -1622,7 +1660,8 @@ private:
}
regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1,
1, instr.alu.saturate_d, 0, instr.conversion.dest_size);
1, instr.alu.saturate_d, 0, instr.conversion.dest_size,
instr.generates_cc.Value() != 0);
break;
}
case OpCode::Id::I2F_R:
@@ -1761,8 +1800,8 @@ private:
Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective,
Tegra::Shader::IpaSampleMode::Default};
u32 next_element = instr.attribute.fmt20.element;
u32 next_index = static_cast<u32>(instr.attribute.fmt20.index.Value());
u64 next_element = instr.attribute.fmt20.element;
u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
const auto LoadNextElement = [&](u32 reg_offset) {
regs.SetRegisterToInputAttibute(instr.gpr0.Value() + reg_offset, next_element,
@@ -1826,8 +1865,8 @@ private:
ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0,
"Unaligned attribute loads are not supported");
u32 next_element = instr.attribute.fmt20.element;
u32 next_index = static_cast<u32>(instr.attribute.fmt20.index.Value());
u64 next_element = instr.attribute.fmt20.element;
u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
const auto StoreNextElement = [&](u32 reg_offset) {
regs.SetOutputAttributeToRegister(static_cast<Attribute::Index>(next_index),
@@ -1853,6 +1892,13 @@ private:
Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
std::string coord;
ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
"AOFFI is not implemented");
ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
"DC is not implemented");
switch (texture_type) {
case Tegra::Shader::TextureType::Texture1D: {
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
@@ -1935,6 +1981,11 @@ private:
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
bool is_array{instr.texs.IsArrayTexture()};
ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
"DC is not implemented");
switch (texture_type) {
case Tegra::Shader::TextureType::Texture2D: {
if (is_array) {
@@ -1971,6 +2022,13 @@ private:
ASSERT(instr.tlds.IsArrayTexture() == false);
std::string coord;
ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
"AOFFI is not implemented");
ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ),
"MZ is not implemented");
switch (instr.tlds.GetTextureType()) {
case Tegra::Shader::TextureType::Texture2D: {
if (instr.tlds.IsArrayTexture()) {
@@ -1999,6 +2057,17 @@ private:
ASSERT(instr.tld4.array == 0);
std::string coord;
ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
"AOFFI is not implemented");
ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
"DC is not implemented");
ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
"NDV is not implemented");
ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP),
"PTP is not implemented");
switch (instr.tld4.texture_type) {
case Tegra::Shader::TextureType::Texture2D: {
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
@@ -2036,6 +2105,13 @@ private:
break;
}
case OpCode::Id::TLD4S: {
ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
"AOFFI is not implemented");
ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
"DC is not implemented");
const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
// TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
@@ -2048,6 +2124,9 @@ private:
break;
}
case OpCode::Id::TXQ: {
ASSERT_MSG(!instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
// TODO: the new commits on the texture refactor, change the way samplers work.
// Sadly, not all texture instructions specify the type of texture their sampler
// uses. This must be fixed at a later instance.
@@ -2068,6 +2147,11 @@ private:
break;
}
case OpCode::Id::TMML: {
ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
"NODEP is not implemented");
ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
"NDV is not implemented");
const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
const bool is_array = instr.tmml.array != 0;
@@ -2234,31 +2318,55 @@ private:
break;
}
case OpCode::Type::PredicateSetPredicate: {
const std::string op_a =
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
const std::string op_b =
GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0);
switch (opcode->GetId()) {
case OpCode::Id::PSETP: {
const std::string op_a =
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
const std::string op_b =
GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0);
// We can't use the constant predicate as destination.
ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
// We can't use the constant predicate as destination.
ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
const std::string second_pred =
GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0);
const std::string second_pred =
GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0);
const std::string combiner = GetPredicateCombiner(instr.psetp.op);
const std::string combiner = GetPredicateCombiner(instr.psetp.op);
const std::string predicate =
'(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')';
const std::string predicate =
'(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')';
// Set the primary predicate to the result of Predicate OP SecondPredicate
SetPredicate(instr.psetp.pred3,
'(' + predicate + ") " + combiner + " (" + second_pred + ')');
// Set the primary predicate to the result of Predicate OP SecondPredicate
SetPredicate(instr.psetp.pred3,
'(' + predicate + ") " + combiner + " (" + second_pred + ')');
if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
// Set the secondary predicate to the result of !Predicate OP SecondPredicate,
// if enabled
SetPredicate(instr.psetp.pred0,
"!(" + predicate + ") " + combiner + " (" + second_pred + ')');
if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
// Set the secondary predicate to the result of !Predicate OP SecondPredicate,
// if enabled
SetPredicate(instr.psetp.pred0,
"!(" + predicate + ") " + combiner + " (" + second_pred + ')');
}
break;
}
case OpCode::Id::CSETP: {
const std::string pred =
GetPredicateCondition(instr.csetp.pred39, instr.csetp.neg_pred39 != 0);
const std::string combiner = GetPredicateCombiner(instr.csetp.op);
const std::string controlCode = regs.GetControlCode(instr.csetp.cc);
if (instr.csetp.pred3 != static_cast<u64>(Pred::UnusedIndex)) {
SetPredicate(instr.csetp.pred3,
'(' + controlCode + ") " + combiner + " (" + pred + ')');
}
if (instr.csetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
SetPredicate(instr.csetp.pred0,
"!(" + controlCode + ") " + combiner + " (" + pred + ')');
}
break;
}
default: {
LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}", opcode->GetName());
UNREACHABLE();
}
}
break;
}

View File

@@ -125,6 +125,10 @@ void Config::ReadValues() {
// System
Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false);
Settings::values.username = sdl2_config->Get("System", "username", "yuzu");
if (Settings::values.username.empty()) {
Settings::values.username = "yuzu";
}
// Miscellaneous
Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace");

View File

@@ -176,7 +176,7 @@ use_docked_mode =
# Sets the account username, max length is 32 characters
# yuzu (default)
username =
username = yuzu
# Sets the systems language index
# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,