early-access version 3032
This commit is contained in:
parent
971803d545
commit
6fb2358eb1
12 changed files with 101 additions and 50 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3031.
|
This is the source code for early-access 3032.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,9 @@ std::vector<std::string> ListSDLSinkDevices(bool capture) {
|
||||||
|
|
||||||
const int device_count = SDL_GetNumAudioDevices(capture);
|
const int device_count = SDL_GetNumAudioDevices(capture);
|
||||||
for (int i = 0; i < device_count; ++i) {
|
for (int i = 0; i < device_count; ++i) {
|
||||||
device_list.emplace_back(SDL_GetAudioDeviceName(i, 0));
|
if (const char* name = SDL_GetAudioDeviceName(i, capture)) {
|
||||||
|
device_list.emplace_back(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device_list;
|
return device_list;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/uuid.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/savedata_factory.h"
|
#include "core/file_sys/savedata_factory.h"
|
||||||
#include "core/file_sys/vfs.h"
|
#include "core/file_sys/vfs.h"
|
||||||
|
@ -59,6 +60,36 @@ bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataA
|
||||||
attr.title_id == 0 && attr.save_id == 0);
|
attr.title_id == 0 && attr.save_id == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id,
|
||||||
|
u128 user_id) {
|
||||||
|
// Only detect nand user saves.
|
||||||
|
const auto space_id_path = [space_id]() -> std::string_view {
|
||||||
|
switch (space_id) {
|
||||||
|
case SaveDataSpaceId::NandUser:
|
||||||
|
return "/user/save";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (space_id_path.empty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::UUID uuid;
|
||||||
|
std::memcpy(uuid.uuid.data(), user_id.data(), sizeof(Common::UUID));
|
||||||
|
|
||||||
|
// Only detect account/device saves from the future location.
|
||||||
|
switch (type) {
|
||||||
|
case SaveDataType::SaveData:
|
||||||
|
return fmt::format("{}/account/{}/{:016X}/1", space_id_path, uuid.RawString(), title_id);
|
||||||
|
case SaveDataType::DeviceSaveData:
|
||||||
|
return fmt::format("{}/device/{:016X}/1", space_id_path, title_id);
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::string SaveDataAttribute::DebugInfo() const {
|
std::string SaveDataAttribute::DebugInfo() const {
|
||||||
|
@ -82,7 +113,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
|
||||||
PrintSaveDataAttributeWarnings(meta);
|
PrintSaveDataAttributeWarnings(meta);
|
||||||
|
|
||||||
const auto save_directory =
|
const auto save_directory =
|
||||||
GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
||||||
|
|
||||||
auto out = dir->CreateDirectoryRelative(save_directory);
|
auto out = dir->CreateDirectoryRelative(save_directory);
|
||||||
|
|
||||||
|
@ -99,7 +130,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
|
||||||
const SaveDataAttribute& meta) const {
|
const SaveDataAttribute& meta) const {
|
||||||
|
|
||||||
const auto save_directory =
|
const auto save_directory =
|
||||||
GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
||||||
|
|
||||||
auto out = dir->GetDirectoryRelative(save_directory);
|
auto out = dir->GetDirectoryRelative(save_directory);
|
||||||
|
|
||||||
|
@ -134,9 +165,9 @@ std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId space,
|
std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir,
|
||||||
SaveDataType type, u64 title_id, u128 user_id,
|
SaveDataSpaceId space, SaveDataType type, u64 title_id,
|
||||||
u64 save_id) {
|
u128 user_id, u64 save_id) {
|
||||||
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
|
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
|
||||||
// be interpreted as the title id of the current process.
|
// be interpreted as the title id of the current process.
|
||||||
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
|
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
|
||||||
|
@ -145,6 +176,17 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For compat with a future impl.
|
||||||
|
if (std::string future_path =
|
||||||
|
GetFutureSaveDataPath(space, type, title_id & ~(0xFFULL), user_id);
|
||||||
|
!future_path.empty()) {
|
||||||
|
// Check if this location exists, and prefer it over the old.
|
||||||
|
if (const auto future_dir = dir->GetDirectoryRelative(future_path); future_dir != nullptr) {
|
||||||
|
LOG_INFO(Service_FS, "Using save at new location: {}", future_path);
|
||||||
|
return future_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string out = GetSaveDataSpaceIdPath(space);
|
std::string out = GetSaveDataSpaceIdPath(space);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -167,7 +209,8 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s
|
||||||
|
|
||||||
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
|
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
|
||||||
u128 user_id) const {
|
u128 user_id) const {
|
||||||
const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
|
const auto path =
|
||||||
|
GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
|
||||||
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
||||||
|
|
||||||
const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME);
|
const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME);
|
||||||
|
@ -185,7 +228,8 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
|
||||||
|
|
||||||
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
|
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
|
||||||
SaveDataSize new_value) const {
|
SaveDataSize new_value) const {
|
||||||
const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
|
const auto path =
|
||||||
|
GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
|
||||||
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
||||||
|
|
||||||
const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
|
const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
|
||||||
|
|
|
@ -95,8 +95,8 @@ public:
|
||||||
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
|
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
|
||||||
|
|
||||||
static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space);
|
static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space);
|
||||||
static std::string GetFullPath(Core::System& system, SaveDataSpaceId space, SaveDataType type,
|
static std::string GetFullPath(Core::System& system, VirtualDir dir, SaveDataSpaceId space,
|
||||||
u64 title_id, u128 user_id, u64 save_id);
|
SaveDataType type, u64 title_id, u128 user_id, u64 save_id);
|
||||||
|
|
||||||
SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const;
|
SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const;
|
||||||
void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
|
void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
|
||||||
|
|
|
@ -14,7 +14,7 @@ enum class CameraAmbientNoiseLevel : u32 {
|
||||||
Low,
|
Low,
|
||||||
Medium,
|
Medium,
|
||||||
High,
|
High,
|
||||||
Unkown3, // This level can't be reached
|
Unknown3, // This level can't be reached
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is nn::irsensor::CameraLightTarget
|
// This is nn::irsensor::CameraLightTarget
|
||||||
|
@ -75,9 +75,9 @@ enum class IrCameraStatus : u32 {
|
||||||
enum class IrCameraInternalStatus : u32 {
|
enum class IrCameraInternalStatus : u32 {
|
||||||
Stopped,
|
Stopped,
|
||||||
FirmwareUpdateNeeded,
|
FirmwareUpdateNeeded,
|
||||||
Unkown2,
|
Unknown2,
|
||||||
Unkown3,
|
Unknown3,
|
||||||
Unkown4,
|
Unknown4,
|
||||||
FirmwareVersionRequested,
|
FirmwareVersionRequested,
|
||||||
FirmwareVersionIsInvalid,
|
FirmwareVersionIsInvalid,
|
||||||
Ready,
|
Ready,
|
||||||
|
@ -121,20 +121,20 @@ enum class IrSensorFunctionLevel : u8 {
|
||||||
|
|
||||||
// This is nn::irsensor::MomentProcessorPreprocess
|
// This is nn::irsensor::MomentProcessorPreprocess
|
||||||
enum class MomentProcessorPreprocess : u32 {
|
enum class MomentProcessorPreprocess : u32 {
|
||||||
Unkown0,
|
Unknown0,
|
||||||
Unkown1,
|
Unknown1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is nn::irsensor::PackedMomentProcessorPreprocess
|
// This is nn::irsensor::PackedMomentProcessorPreprocess
|
||||||
enum class PackedMomentProcessorPreprocess : u8 {
|
enum class PackedMomentProcessorPreprocess : u8 {
|
||||||
Unkown0,
|
Unknown0,
|
||||||
Unkown1,
|
Unknown1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is nn::irsensor::PointingStatus
|
// This is nn::irsensor::PointingStatus
|
||||||
enum class PointingStatus : u32 {
|
enum class PointingStatus : u32 {
|
||||||
Unkown0,
|
Unknown0,
|
||||||
Unkown1,
|
Unknown1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrsRect {
|
struct IrsRect {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/spin_lock.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -36,28 +37,30 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Allocate() {
|
void* Allocate() {
|
||||||
Node* ret = m_head.load();
|
m_lock.lock();
|
||||||
|
|
||||||
do {
|
Node* ret = m_head;
|
||||||
if (ret == nullptr) {
|
if (ret != nullptr) [[likely]] {
|
||||||
break;
|
m_head = ret->next;
|
||||||
}
|
}
|
||||||
} while (!m_head.compare_exchange_weak(ret, ret->next));
|
|
||||||
|
|
||||||
|
m_lock.unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Free(void* obj) {
|
void Free(void* obj) {
|
||||||
Node* node = static_cast<Node*>(obj);
|
m_lock.lock();
|
||||||
|
|
||||||
Node* cur_head = m_head.load();
|
Node* node = static_cast<Node*>(obj);
|
||||||
do {
|
node->next = m_head;
|
||||||
node->next = cur_head;
|
m_head = node;
|
||||||
} while (!m_head.compare_exchange_weak(cur_head, node));
|
|
||||||
|
m_lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<Node*> m_head{};
|
std::atomic<Node*> m_head{};
|
||||||
|
Common::SpinLock m_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
|
@ -2118,7 +2118,7 @@ void Hid::WritePalmaWaveEntry(Kernel::HLERequestContext& ctx) {
|
||||||
ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
|
ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
|
||||||
|
|
||||||
LOG_WARNING(Service_HID,
|
LOG_WARNING(Service_HID,
|
||||||
"(STUBBED) called, connection_handle={}, wave_set={}, unkown={}, "
|
"(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, "
|
||||||
"t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
|
"t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
|
||||||
connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
|
connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,10 @@ private:
|
||||||
u8 pointing_status;
|
u8 pointing_status;
|
||||||
INSERT_PADDING_BYTES(3);
|
INSERT_PADDING_BYTES(3);
|
||||||
u32 unknown;
|
u32 unknown;
|
||||||
float unkown_float1;
|
float unknown_float1;
|
||||||
float position_x;
|
float position_x;
|
||||||
float position_y;
|
float position_y;
|
||||||
float unkown_float2;
|
float unknown_float2;
|
||||||
Core::IrSensor::IrsRect window_of_interest;
|
Core::IrSensor::IrsRect window_of_interest;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PointingProcessorMarkerData) == 0x20,
|
static_assert(sizeof(PointingProcessorMarkerData) == 0x20,
|
||||||
|
|
|
@ -272,14 +272,14 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b
|
||||||
void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) {
|
void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) {
|
||||||
auto& stores = program.info.stores;
|
auto& stores = program.info.stores;
|
||||||
if (stores.Legacy()) {
|
if (stores.Legacy()) {
|
||||||
std::queue<IR::Attribute> ununsed_output_generics{};
|
std::queue<IR::Attribute> unused_output_generics{};
|
||||||
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
|
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
|
||||||
if (!stores.Generic(index)) {
|
if (!stores.Generic(index)) {
|
||||||
ununsed_output_generics.push(IR::Attribute::Generic0X + index * 4);
|
unused_output_generics.push(IR::Attribute::Generic0X + index * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.info.legacy_stores_mapping =
|
program.info.legacy_stores_mapping =
|
||||||
GenerateLegacyToGenericMappings(stores, ununsed_output_generics, {});
|
GenerateLegacyToGenericMappings(stores, unused_output_generics, {});
|
||||||
for (IR::Block* const block : program.post_order_blocks) {
|
for (IR::Block* const block : program.post_order_blocks) {
|
||||||
for (IR::Inst& inst : block->Instructions()) {
|
for (IR::Inst& inst : block->Instructions()) {
|
||||||
switch (inst.GetOpcode()) {
|
switch (inst.GetOpcode()) {
|
||||||
|
@ -300,16 +300,16 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run
|
||||||
|
|
||||||
auto& loads = program.info.loads;
|
auto& loads = program.info.loads;
|
||||||
if (loads.Legacy()) {
|
if (loads.Legacy()) {
|
||||||
std::queue<IR::Attribute> ununsed_input_generics{};
|
std::queue<IR::Attribute> unused_input_generics{};
|
||||||
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
|
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
|
||||||
const AttributeType input_type{runtime_info.generic_input_types[index]};
|
const AttributeType input_type{runtime_info.generic_input_types[index]};
|
||||||
if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) ||
|
if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) ||
|
||||||
input_type == AttributeType::Disabled) {
|
input_type == AttributeType::Disabled) {
|
||||||
ununsed_input_generics.push(IR::Attribute::Generic0X + index * 4);
|
unused_input_generics.push(IR::Attribute::Generic0X + index * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto mappings = GenerateLegacyToGenericMappings(
|
auto mappings = GenerateLegacyToGenericMappings(
|
||||||
loads, ununsed_input_generics, runtime_info.previous_stage_legacy_stores_mapping);
|
loads, unused_input_generics, runtime_info.previous_stage_legacy_stores_mapping);
|
||||||
for (IR::Block* const block : program.post_order_blocks) {
|
for (IR::Block* const block : program.post_order_blocks) {
|
||||||
for (IR::Inst& inst : block->Instructions()) {
|
for (IR::Inst& inst : block->Instructions()) {
|
||||||
switch (inst.GetOpcode()) {
|
switch (inst.GetOpcode()) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ class DescriptorTable {
|
||||||
public:
|
public:
|
||||||
explicit DescriptorTable(Tegra::MemoryManager& gpu_memory_) : gpu_memory{gpu_memory_} {}
|
explicit DescriptorTable(Tegra::MemoryManager& gpu_memory_) : gpu_memory{gpu_memory_} {}
|
||||||
|
|
||||||
[[nodiscard]] bool Synchornize(GPUVAddr gpu_addr, u32 limit) {
|
[[nodiscard]] bool Synchronize(GPUVAddr gpu_addr, u32 limit) {
|
||||||
[[likely]] if (current_gpu_addr == gpu_addr && current_limit == limit) {
|
[[likely]] if (current_gpu_addr == gpu_addr && current_limit == limit) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,11 +193,11 @@ void TextureCache<P>::SynchronizeGraphicsDescriptors() {
|
||||||
const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
|
const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
|
||||||
const u32 tic_limit = maxwell3d->regs.tex_header.limit;
|
const u32 tic_limit = maxwell3d->regs.tex_header.limit;
|
||||||
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
|
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
|
||||||
if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tex_sampler.Address(),
|
if (channel_state->graphics_sampler_table.Synchronize(maxwell3d->regs.tex_sampler.Address(),
|
||||||
tsc_limit)) {
|
tsc_limit)) {
|
||||||
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tex_header.Address(),
|
if (channel_state->graphics_image_table.Synchronize(maxwell3d->regs.tex_header.Address(),
|
||||||
tic_limit)) {
|
tic_limit)) {
|
||||||
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
|
@ -209,10 +209,10 @@ void TextureCache<P>::SynchronizeComputeDescriptors() {
|
||||||
const u32 tic_limit = kepler_compute->regs.tic.limit;
|
const u32 tic_limit = kepler_compute->regs.tic.limit;
|
||||||
const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit;
|
const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit;
|
||||||
const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address();
|
const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address();
|
||||||
if (channel_state->compute_sampler_table.Synchornize(tsc_gpu_addr, tsc_limit)) {
|
if (channel_state->compute_sampler_table.Synchronize(tsc_gpu_addr, tsc_limit)) {
|
||||||
channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
if (channel_state->compute_image_table.Synchornize(kepler_compute->regs.tic.Address(),
|
if (channel_state->compute_image_table.Synchronize(kepler_compute->regs.tic.Address(),
|
||||||
tic_limit)) {
|
tic_limit)) {
|
||||||
channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1895,6 +1895,8 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
|
||||||
case GameListOpenTarget::SaveData: {
|
case GameListOpenTarget::SaveData: {
|
||||||
open_target = tr("Save Data");
|
open_target = tr("Save Data");
|
||||||
const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
|
const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
|
||||||
|
auto vfs_nand_dir =
|
||||||
|
vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read);
|
||||||
|
|
||||||
if (has_user_save) {
|
if (has_user_save) {
|
||||||
// User save data
|
// User save data
|
||||||
|
@ -1921,15 +1923,15 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
|
||||||
ASSERT(user_id);
|
ASSERT(user_id);
|
||||||
|
|
||||||
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
||||||
*system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
|
*system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser,
|
||||||
program_id, user_id->AsU128(), 0);
|
FileSys::SaveDataType::SaveData, program_id, user_id->AsU128(), 0);
|
||||||
|
|
||||||
path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
|
path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
|
||||||
} else {
|
} else {
|
||||||
// Device save data
|
// Device save data
|
||||||
const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
||||||
*system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
|
*system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser,
|
||||||
program_id, {}, 0);
|
FileSys::SaveDataType::SaveData, program_id, {}, 0);
|
||||||
|
|
||||||
path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path);
|
path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue