Merge pull request #6 from shadps4-emu/main

+
This commit is contained in:
Emulator-Team-2 2024-08-31 20:09:13 +02:00 committed by GitHub
commit dccf3a82c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
130 changed files with 2984 additions and 1950 deletions

5
.gitmodules vendored
View File

@ -81,4 +81,7 @@
[submodule "externals/ffmpeg-core"] [submodule "externals/ffmpeg-core"]
path = externals/ffmpeg-core path = externals/ffmpeg-core
url = https://github.com/shadps4-emu/ext-ffmpeg-core.git url = https://github.com/shadps4-emu/ext-ffmpeg-core.git
shallow = true shallow = true
[submodule "externals/half"]
path = externals/half
url = https://github.com/ROCm/half.git

View File

@ -521,6 +521,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
src/video_core/renderer_vulkan/vk_resource_pool.h src/video_core/renderer_vulkan/vk_resource_pool.h
src/video_core/renderer_vulkan/vk_scheduler.cpp src/video_core/renderer_vulkan/vk_scheduler.cpp
src/video_core/renderer_vulkan/vk_scheduler.h src/video_core/renderer_vulkan/vk_scheduler.h
src/video_core/renderer_vulkan/vk_shader_cache.cpp
src/video_core/renderer_vulkan/vk_shader_cache.h
src/video_core/renderer_vulkan/vk_shader_util.cpp src/video_core/renderer_vulkan/vk_shader_util.cpp
src/video_core/renderer_vulkan/vk_shader_util.h src/video_core/renderer_vulkan/vk_shader_util.h
src/video_core/renderer_vulkan/vk_swapchain.cpp src/video_core/renderer_vulkan/vk_swapchain.cpp
@ -642,6 +644,9 @@ if (APPLE)
# Replacement for std::chrono::time_zone # Replacement for std::chrono::time_zone
target_link_libraries(shadps4 PRIVATE date::date-tz) target_link_libraries(shadps4 PRIVATE date::date-tz)
# Half float conversions for F16C patches
target_link_libraries(shadps4 PRIVATE half)
endif() endif()
if (NOT ENABLE_QT_GUI) if (NOT ENABLE_QT_GUI)

View File

@ -142,11 +142,17 @@ if (WIN32)
target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument") target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument")
endif() endif()
# date if (APPLE)
if (APPLE AND NOT TARGET date::date-tz) # half
option(BUILD_TZ_LIB "" ON) add_library(half INTERFACE)
option(USE_SYSTEM_TZ_DB "" ON) target_include_directories(half INTERFACE half/include)
add_subdirectory(date)
# date
if (NOT TARGET date::date-tz)
option(BUILD_TZ_LIB "" ON)
option(USE_SYSTEM_TZ_DB "" ON)
add_subdirectory(date)
endif()
endif() endif()
# Tracy # Tracy

2
externals/glslang vendored

@ -1 +1 @@
Subproject commit d59c84d388c805022e2bddea08aa41cbe7e43e55 Subproject commit 12cbda959b6df2af119a76a73ff906c2bed36884

1
externals/half vendored Submodule

@ -0,0 +1 @@
Subproject commit 1ddada225144cac0de8f6b5c0dd9acffd99a2e68

2
externals/robin-map vendored

@ -1 +1 @@
Subproject commit 1115dad3ffa0994e3f43b693d9b9cc99944c64c1 Subproject commit 2c48a1a50203bbaf1e3d0d64c5d726d56f8d3bb3

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit 8db09231c448b913ae905d5237ce2eca46e3fe87 Subproject commit 37090c74cc6e680f2bc334cac8fd182f7634a1f6

2
externals/toml11 vendored

@ -1 +1 @@
Subproject commit cc0bee4fd46ea1f5db147d63ea545208cc9e8405 Subproject commit 4b740127230472779c4a4d71e1a75aaa3a367a2d

2
externals/xbyak vendored

@ -1 +1 @@
Subproject commit aabb091ae37068498751fd58202a9854408ecb0e Subproject commit ccdf68421bc8eb85693f573080fc0a5faad862db

View File

@ -106,6 +106,7 @@ static auto UserPaths = [] {
create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR); create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR);
create_path(PathType::CheatsDir, user_dir / CHEATS_DIR); create_path(PathType::CheatsDir, user_dir / CHEATS_DIR);
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR); create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
create_path(PathType::AddonsDir, user_dir / ADDONS_DIR);
return paths; return paths;
}(); }();

View File

@ -22,6 +22,7 @@ enum class PathType {
CapturesDir, // Where rdoc captures are stored. CapturesDir, // Where rdoc captures are stored.
CheatsDir, // Where cheats are stored. CheatsDir, // Where cheats are stored.
PatchesDir, // Where patches are stored. PatchesDir, // Where patches are stored.
AddonsDir, // Where additional content is stored.
}; };
constexpr auto PORTABLE_DIR = "user"; constexpr auto PORTABLE_DIR = "user";
@ -39,6 +40,7 @@ constexpr auto DOWNLOAD_DIR = "download";
constexpr auto CAPTURES_DIR = "captures"; constexpr auto CAPTURES_DIR = "captures";
constexpr auto CHEATS_DIR = "cheats"; constexpr auto CHEATS_DIR = "cheats";
constexpr auto PATCHES_DIR = "patches"; constexpr auto PATCHES_DIR = "patches";
constexpr auto ADDONS_DIR = "addcont";
// Filenames // Filenames
constexpr auto LOG_FILE = "shad_log.txt"; constexpr auto LOG_FILE = "shad_log.txt";

View File

@ -15,6 +15,7 @@
#else #else
#include <pthread.h> #include <pthread.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include <half.hpp>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
#endif #endif
@ -30,6 +31,12 @@ static Xbyak::Reg ZydisToXbyakRegister(const ZydisRegister reg) {
if (reg >= ZYDIS_REGISTER_RAX && reg <= ZYDIS_REGISTER_R15) { if (reg >= ZYDIS_REGISTER_RAX && reg <= ZYDIS_REGISTER_R15) {
return Xbyak::Reg64(reg - ZYDIS_REGISTER_RAX + Xbyak::Operand::RAX); return Xbyak::Reg64(reg - ZYDIS_REGISTER_RAX + Xbyak::Operand::RAX);
} }
if (reg >= ZYDIS_REGISTER_XMM0 && reg <= ZYDIS_REGISTER_XMM31) {
return Xbyak::Xmm(reg - ZYDIS_REGISTER_XMM0 + xmm0.getIdx());
}
if (reg >= ZYDIS_REGISTER_YMM0 && reg <= ZYDIS_REGISTER_YMM31) {
return Xbyak::Ymm(reg - ZYDIS_REGISTER_YMM0 + ymm0.getIdx());
}
UNREACHABLE_MSG("Unsupported register: {}", static_cast<u32>(reg)); UNREACHABLE_MSG("Unsupported register: {}", static_cast<u32>(reg));
} }
@ -66,6 +73,12 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera
return ptr[expression]; return ptr[expression];
} }
static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) {
ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE,
"Expected immediate operand, got type: {}", static_cast<u32>(operand.type));
return operand.imm.value.u;
}
static std::unique_ptr<Xbyak::Operand> ZydisToXbyakOperand(const ZydisDecodedOperand& operand) { static std::unique_ptr<Xbyak::Operand> ZydisToXbyakOperand(const ZydisDecodedOperand& operand) {
switch (operand.type) { switch (operand.type) {
case ZYDIS_OPERAND_TYPE_REGISTER: { case ZYDIS_OPERAND_TYPE_REGISTER: {
@ -110,51 +123,135 @@ static Xbyak::Reg AllocateScratchRegister(
#ifdef __APPLE__ #ifdef __APPLE__
static constexpr u32 MaxSavedRegisters = 3; static pthread_key_t stack_pointer_slot;
static pthread_key_t register_save_slots[MaxSavedRegisters]; static pthread_key_t patch_stack_slot;
static std::once_flag register_save_init_flag; static std::once_flag patch_context_slots_init_flag;
static_assert(sizeof(void*) == sizeof(u64), static_assert(sizeof(void*) == sizeof(u64),
"Cannot fit a register inside a thread local storage slot."); "Cannot fit a register inside a thread local storage slot.");
static void InitializeRegisterSaveSlots() { static void InitializePatchContextSlots() {
for (u32 i = 0; i < MaxSavedRegisters; i++) { ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0,
ASSERT_MSG(pthread_key_create(&register_save_slots[i], nullptr) == 0, "Unable to allocate thread-local register for stack pointer.");
"Unable to allocate thread-local register save slot {}", i); ASSERT_MSG(pthread_key_create(&patch_stack_slot, nullptr) == 0,
"Unable to allocate thread-local register for patch stack.");
}
void InitializeThreadPatchStack() {
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
const auto* patch_stack = std::malloc(0x1000);
pthread_setspecific(patch_stack_slot, patch_stack);
}
void CleanupThreadPatchStack() {
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
auto* patch_stack = pthread_getspecific(patch_stack_slot);
if (patch_stack != nullptr) {
std::free(patch_stack);
pthread_setspecific(patch_stack_slot, nullptr);
} }
} }
/// Saves the stack pointer to thread local storage and loads the patch stack.
static void SaveStack(Xbyak::CodeGenerator& c) {
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
// Save stack pointer and load patch stack.
c.putSeg(gs);
c.mov(qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))], rsp);
c.putSeg(gs);
c.mov(rsp, qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))]);
}
/// Restores the stack pointer from thread local storage.
static void RestoreStack(Xbyak::CodeGenerator& c) {
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
// Save patch stack pointer and load original stack.
c.putSeg(gs);
c.mov(qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))], rsp);
c.putSeg(gs);
c.mov(rsp, qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))]);
}
#else
// These utilities are not implemented as we can't save anything to thread local storage without
// temporary registers.
void InitializeThreadPatchStack() {
// No-op
}
void CleanupThreadPatchStack() {
// No-op
}
/// Saves the stack pointer to thread local storage and loads the patch stack.
static void SaveStack(Xbyak::CodeGenerator& c) {
UNIMPLEMENTED();
}
/// Restores the stack pointer from thread local storage.
static void RestoreStack(Xbyak::CodeGenerator& c) {
UNIMPLEMENTED();
}
#endif
/// Switches to the patch stack, saves registers, and restores the original stack.
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) { static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) {
ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to save {} registers.", SaveStack(c);
regs.size());
std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots);
u32 index = 0;
for (const auto& reg : regs) { for (const auto& reg : regs) {
const auto offset = reinterpret_cast<void*>(register_save_slots[index++] * sizeof(void*)); c.push(reg.cvt64());
c.putSeg(gs);
c.mov(qword[offset], reg.cvt64());
} }
RestoreStack(c);
} }
/// Switches to the patch stack, restores registers, and restores the original stack.
static void RestoreRegisters(Xbyak::CodeGenerator& c, static void RestoreRegisters(Xbyak::CodeGenerator& c,
const std::initializer_list<Xbyak::Reg> regs) { const std::initializer_list<Xbyak::Reg> regs) {
ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to restore {} registers.", SaveStack(c);
regs.size());
std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots);
u32 index = 0;
for (const auto& reg : regs) { for (const auto& reg : regs) {
const auto offset = reinterpret_cast<void*>(register_save_slots[index++] * sizeof(void*)); c.pop(reg.cvt64());
}
RestoreStack(c);
}
c.putSeg(gs); /// Switches to the patch stack and stores all registers.
c.mov(reg.cvt64(), qword[offset]); static void SaveContext(Xbyak::CodeGenerator& c) {
SaveStack(c);
for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) {
c.push(Xbyak::Reg64(reg));
}
for (int reg = 0; reg <= 7; reg++) {
c.sub(rsp, 32);
c.vmovdqu(ptr[rsp], Xbyak::Ymm(reg));
} }
} }
/// Restores all registers and restores the original stack.
/// If the destination is a register, it is not restored to preserve the output.
static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst) {
for (int reg = 7; reg >= 0; reg--) {
if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) {
c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp]);
}
c.add(rsp, 32);
}
for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) {
if (!dst.isREG() || dst.getIdx() != reg) {
c.pop(Xbyak::Reg64(reg));
} else {
c.add(rsp, 4);
}
}
RestoreStack(c);
}
#ifdef __APPLE__
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
const auto dst = ZydisToXbyakRegisterOperand(operands[0]); const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]); const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
@ -204,9 +301,9 @@ static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
c.and_(dst, scratch2); c.and_(dst, scratch2);
if (dst.getIdx() == shift.getIdx()) { if (dst.getIdx() == shift.getIdx()) {
RestoreRegisters(c, {scratch1, scratch2}); RestoreRegisters(c, {scratch2, scratch1});
} else { } else {
RestoreRegisters(c, {scratch1, scratch2, shift}); RestoreRegisters(c, {shift, scratch2, scratch1});
} }
} }
@ -258,10 +355,138 @@ static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat
RestoreRegisters(c, {scratch}); RestoreRegisters(c, {scratch});
} }
bool FilterRosetta2Only(const ZydisDecodedOperand*) { static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
const u32 count) {
for (u32 i = 0; i < count; i++) {
out[i] = half_float::half_cast<float>(in[i]);
}
}
static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
const auto src = ZydisToXbyakOperand(operands[1]);
const auto float_count = dst.getBit() / 32;
const auto byte_count = float_count * 4;
SaveContext(c);
// Allocate stack space for outputs and load into first parameter.
c.sub(rsp, byte_count);
c.mov(rdi, rsp);
if (src->isXMM()) {
// Allocate stack space for inputs and load into second parameter.
c.sub(rsp, byte_count);
c.mov(rsi, rsp);
// Move input to the allocated space.
c.movdqu(ptr[rsp], *reinterpret_cast<Xbyak::Xmm*>(src.get()));
} else {
c.lea(rsi, src->getAddress());
}
// Load float count into third parameter.
c.mov(rdx, float_count);
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPH2PS));
c.call(rax);
if (src->isXMM()) {
// Clean up after inputs space.
c.add(rsp, byte_count);
}
// Load outputs into destination register and clean up space.
if (dst.isYMM()) {
c.vmovdqu(*reinterpret_cast<const Xbyak::Ymm*>(&dst), ptr[rsp]);
} else {
c.movdqu(*reinterpret_cast<const Xbyak::Xmm*>(&dst), ptr[rsp]);
}
c.add(rsp, byte_count);
RestoreContext(c, dst);
}
using SingleToHalfFloatConverter = half_float::half (*)(float);
static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = {
half_float::half_cast<half_float::half, std::round_to_nearest, float>,
half_float::half_cast<half_float::half, std::round_toward_neg_infinity, float>,
half_float::half_cast<half_float::half, std::round_toward_infinity, float>,
half_float::half_cast<half_float::half, std::round_toward_zero, float>,
};
static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in,
const u32 count, const u8 rounding_mode) {
const auto conversion_func = SingleToHalfFloatConverters[rounding_mode];
for (u32 i = 0; i < count; i++) {
out[i] = conversion_func(in[i]);
}
}
static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
const auto dst = ZydisToXbyakOperand(operands[0]);
const auto src = ZydisToXbyakRegisterOperand(operands[1]);
const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]);
const auto float_count = src.getBit() / 32;
const auto byte_count = float_count * 4;
SaveContext(c);
if (dst->isXMM()) {
// Allocate stack space for outputs and load into first parameter.
c.sub(rsp, byte_count);
c.mov(rdi, rsp);
} else {
c.lea(rdi, dst->getAddress());
}
// Allocate stack space for inputs and load into second parameter.
c.sub(rsp, byte_count);
c.mov(rsi, rsp);
// Move input to the allocated space.
if (src.isYMM()) {
c.vmovdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Ymm*>(&src));
} else {
c.movdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Xmm*>(&src));
}
// Load float count into third parameter.
c.mov(rdx, float_count);
// Load rounding mode into fourth parameter.
if (ctrl & 4) {
// Load from MXCSR.RC.
c.stmxcsr(ptr[rsp - 4]);
c.mov(rcx, ptr[rsp - 4]);
c.shr(rcx, 13);
c.and_(rcx, 3);
} else {
c.mov(rcx, ctrl & 3);
}
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPS2PH));
c.call(rax);
// Clean up after inputs space.
c.add(rsp, byte_count);
if (dst->isXMM()) {
// Load outputs into destination register and clean up space.
c.movdqu(*reinterpret_cast<Xbyak::Xmm*>(dst.get()), ptr[rsp]);
c.add(rsp, byte_count);
}
RestoreContext(c, *dst);
}
static bool FilterRosetta2Only(const ZydisDecodedOperand*) {
int ret = 0; int ret = 0;
size_t size = sizeof(ret); size_t size = sizeof(ret);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) != 0) { if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) {
return false; return false;
} }
return ret; return ret;
@ -339,12 +564,16 @@ static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
#endif #endif
#ifdef __APPLE__ #ifdef __APPLE__
// BMI1 instructions that are not supported by Rosetta 2 on Apple Silicon. // Patches for instruction sets not supported by Rosetta 2.
// BMI1
{ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}}, {ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}},
{ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}}, {ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}},
{ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}}, {ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}},
{ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}}, {ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}},
{ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}}, {ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}},
// F16C
{ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
{ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
#endif #endif
}; };

View File

@ -9,6 +9,12 @@ class CodeGenerator;
namespace Core { namespace Core {
/// Initializes a stack for the current thread for use by patch implementations.
void InitializeThreadPatchStack();
/// Cleans up the patch stack for the current thread.
void CleanupThreadPatchStack();
/// Patches CPU instructions that cannot run as-is on the host. /// Patches CPU instructions that cannot run as-is on the host.
void PatchInstructions(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c); void PatchInstructions(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c);

View File

@ -67,15 +67,19 @@ bool PKG::Open(const std::filesystem::path& filepath) {
file.Seek(0x47); // skip first 7 characters of content_id file.Seek(0x47); // skip first 7 characters of content_id
file.Read(pkgTitleID); file.Read(pkgTitleID);
file.Seek(0);
pkg.resize(pkgheader.pkg_promote_size);
file.Read(pkg);
u32 offset = pkgheader.pkg_table_entry_offset; u32 offset = pkgheader.pkg_table_entry_offset;
u32 n_files = pkgheader.pkg_table_entry_count; u32 n_files = pkgheader.pkg_table_entry_count;
file.Seek(offset);
for (int i = 0; i < n_files; i++) { for (int i = 0; i < n_files; i++) {
PKGEntry entry; PKGEntry entry{};
std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry)); file.Read(entry.id);
file.Read(entry.filename_offset);
file.Read(entry.flags1);
file.Read(entry.flags2);
file.Read(entry.offset);
file.Read(entry.size);
file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
// Try to figure out the name // Try to figure out the name
const auto name = GetEntryNameByType(entry.id); const auto name = GetEntryNameByType(entry.id);
@ -113,9 +117,6 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
failreason = "Content size is bigger than pkg size"; failreason = "Content size is bigger than pkg size";
return false; return false;
} }
file.Seek(0);
pkg.resize(pkgheader.pkg_promote_size);
file.Read(pkg);
u32 offset = pkgheader.pkg_table_entry_offset; u32 offset = pkgheader.pkg_table_entry_offset;
u32 n_files = pkgheader.pkg_table_entry_count; u32 n_files = pkgheader.pkg_table_entry_count;
@ -126,9 +127,18 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
std::array<std::array<u8, 256>, 7> key1; std::array<std::array<u8, 256>, 7> key1;
std::array<u8, 256> imgkeydata; std::array<u8, 256> imgkeydata;
file.Seek(offset);
for (int i = 0; i < n_files; i++) { for (int i = 0; i < n_files; i++) {
PKGEntry entry; PKGEntry entry{};
std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry)); file.Read(entry.id);
file.Read(entry.filename_offset);
file.Read(entry.flags1);
file.Read(entry.flags2);
file.Read(entry.offset);
file.Read(entry.size);
file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
auto currentPos = file.Tell();
// Try to figure out the name // Try to figure out the name
const auto name = GetEntryNameByType(entry.id); const auto name = GetEntryNameByType(entry.id);
@ -139,8 +149,15 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
// Just print with id // Just print with id
Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id), Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id),
Common::FS::FileAccessMode::Write); Common::FS::FileAccessMode::Write);
out.WriteRaw<u8>(pkg.data() + entry.offset, entry.size); file.Seek(entry.offset);
std::vector<u8> data;
data.resize(entry.size);
file.ReadRaw<u8>(data.data(), entry.size);
out.WriteRaw<u8>(data.data(), entry.size);
out.Close(); out.Close();
file.Seek(currentPos);
continue; continue;
} }
@ -178,14 +195,25 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
} }
Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write); Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write);
out.WriteRaw<u8>(pkg.data() + entry.offset, entry.size); file.Seek(entry.offset);
std::vector<u8> data;
data.resize(entry.size);
file.ReadRaw<u8>(data.data(), entry.size);
out.WriteRaw<u8>(data.data(), entry.size);
out.Close(); out.Close();
// Decrypt Np stuff and overwrite. // Decrypt Np stuff and overwrite.
if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 || if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 ||
entry.id == 0x403) { // somehow 0x401 is not decrypting entry.id == 0x403) { // somehow 0x401 is not decrypting
decNp.resize(entry.size); decNp.resize(entry.size);
std::span<u8> cipherNp(pkg.data() + entry.offset, entry.size); file.Seek(entry.offset);
std::vector<u8> data;
data.resize(entry.size);
file.ReadRaw<u8>(data.data(), entry.size);
std::span<u8> cipherNp(data.data(), entry.size);
std::array<u8, 64> concatenated_ivkey_dk3_; std::array<u8, 64> concatenated_ivkey_dk3_;
std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry)); std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry));
std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_)); std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
@ -197,6 +225,8 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
out.Write(decNp); out.Write(decNp);
out.Close(); out.Close();
} }
file.Seek(currentPos);
} }
// Extract trophy files // Extract trophy files
@ -214,28 +244,31 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey); PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey);
const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok. const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok.
// Read encrypted pfs_image int num_blocks = 0;
std::vector<u8> pfs_encrypted(length);
file.Seek(pkgheader.pfs_image_offset);
file.Read(pfs_encrypted);
file.Close();
// Decrypt the pfs_image.
std::vector<u8> pfs_decrypted(length);
PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
// Retrieve PFSC from decrypted pfs_image.
pfsc_offset = GetPFSCOffset(pfs_decrypted);
std::vector<u8> pfsc(length); std::vector<u8> pfsc(length);
std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset); if (length != 0) {
// Read encrypted pfs_image
std::vector<u8> pfs_encrypted(length);
file.Seek(pkgheader.pfs_image_offset);
file.Read(pfs_encrypted);
file.Close();
// Decrypt the pfs_image.
std::vector<u8> pfs_decrypted(length);
PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
PFSCHdr pfsChdr; // Retrieve PFSC from decrypted pfs_image.
std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr)); pfsc_offset = GetPFSCOffset(pfs_decrypted);
std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset);
const int num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2); PFSCHdr pfsChdr;
sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset. std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr));
for (int i = 0; i < num_blocks + 1; i++) { num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2);
std::memcpy(&sectorMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8); sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset.
for (int i = 0; i < num_blocks + 1; i++) {
std::memcpy(&sectorMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8);
}
} }
u32 ent_size = 0; u32 ent_size = 0;
@ -296,7 +329,15 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
} else { } else {
// Set the the folder according to the current inode. // Set the the folder according to the current inode.
// Can be 2 or more (rarely) // Can be 2 or more (rarely)
extractPaths[ndinode_counter] = extract_path.parent_path() / GetTitleID(); auto parent_path = extract_path.parent_path();
auto title_id = GetTitleID();
if (parent_path.filename() != title_id) {
extractPaths[ndinode_counter] = parent_path / title_id;
} else {
// DLCs path has different structure
extractPaths[ndinode_counter] = extract_path;
}
uroot_reached = false; uroot_reached = false;
break; break;
} }

View File

@ -149,7 +149,6 @@ public:
private: private:
Crypto crypto; Crypto crypto;
TRP trp; TRP trp;
std::vector<u8> pkg;
u64 pkgSize = 0; u64 pkgSize = 0;
char pkgTitleID[9]; char pkgTitleID[9];
PKGHeader pkgheader; PKGHeader pkgheader;

View File

@ -1,20 +1,38 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include <cmath> #include <cmath>
#include <common/path_util.h>
#include <common/singleton.h>
#include <core/file_format/psf.h>
#include <core/file_sys/fs.h>
#include "app_content.h" #include "app_content.h"
#include "common/io_file.h" #include "common/io_file.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/path_util.h"
#include "common/singleton.h"
#include "common/string_util.h"
#include "core/file_format/psf.h"
#include "core/file_sys/fs.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
namespace Libraries::AppContent { namespace Libraries::AppContent {
int32_t addcont_count = 0;
struct AddContInfo {
char entitlementLabel[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE];
OrbisAppContentAddcontDownloadStatus status;
OrbisAppContentGetEntitlementKey key;
};
std::array<AddContInfo, ORBIS_APP_CONTENT_INFO_LIST_MAX_SIZE> addcont_info = {{
{"0000000000000000",
ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED,
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00}},
}};
std::string title_id;
int PS4_SYSV_ABI _Z5dummyv() { int PS4_SYSV_ABI _Z5dummyv() {
LOG_ERROR(Lib_AppContent, "(STUBBED) called"); LOG_ERROR(Lib_AppContent, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
@ -35,9 +53,31 @@ int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAppContentAddcontMount() { int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label,
LOG_ERROR(Lib_AppContent, "(STUBBED) called"); const OrbisNpUnifiedEntitlementLabel* entitlement_label,
return ORBIS_OK; OrbisAppContentMountPoint* mount_point) {
LOG_INFO(Lib_AppContent, "called");
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / title_id /
entitlement_label->data;
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
for (int i = 0; i < addcont_count; i++) {
if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel,
ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) {
continue;
}
if (addcont_info[i].status != ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED) {
return ORBIS_APP_CONTENT_ERROR_NOT_FOUND;
}
snprintf(mount_point->data, ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE, "/addcont%d", i);
mnt->Mount(mount_dir, mount_point->data);
return ORBIS_OK;
}
return ORBIS_APP_CONTENT_ERROR_NOT_FOUND;
} }
int PS4_SYSV_ABI sceAppContentAddcontShrink() { int PS4_SYSV_ABI sceAppContentAddcontShrink() {
@ -124,22 +164,80 @@ int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAppContentGetAddcontInfo() { int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label,
LOG_ERROR(Lib_AppContent, "(STUBBED) called"); const OrbisNpUnifiedEntitlementLabel* entitlementLabel,
return ORBIS_OK; OrbisAppContentAddcontInfo* info) {
LOG_INFO(Lib_AppContent, "called");
if (entitlementLabel == nullptr || info == nullptr) {
return ORBIS_APP_CONTENT_ERROR_PARAMETER;
}
for (auto i = 0; i < addcont_count; i++) {
if (strncmp(entitlementLabel->data, addcont_info[i].entitlementLabel,
ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) {
continue;
}
LOG_INFO(Lib_AppContent, "found DLC {}", entitlementLabel->data);
strncpy(info->entitlement_label.data, addcont_info[i].entitlementLabel,
ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE);
info->status = addcont_info[i].status;
return ORBIS_OK;
}
return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
} }
int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label,
OrbisAppContentAddcontInfo* list, u32 list_num, OrbisAppContentAddcontInfo* list, u32 list_num,
u32* hit_num) { u32* hit_num) {
*hit_num = 0; LOG_INFO(Lib_AppContent, "called");
LOG_ERROR(Lib_AppContent, "(DUMMY) called");
if (list_num == 0 || list == nullptr) {
if (hit_num == nullptr) {
return ORBIS_APP_CONTENT_ERROR_PARAMETER;
}
*hit_num = addcont_count;
return ORBIS_OK;
}
int dlcs_to_list = addcont_count < list_num ? addcont_count : list_num;
for (int i = 0; i < dlcs_to_list; i++) {
strncpy(list[i].entitlement_label.data, addcont_info[i].entitlementLabel,
ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE);
list[i].status = addcont_info[i].status;
}
if (hit_num != nullptr) {
*hit_num = dlcs_to_list;
}
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAppContentGetEntitlementKey() { int PS4_SYSV_ABI sceAppContentGetEntitlementKey(
LOG_ERROR(Lib_AppContent, "(STUBBED) called"); u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label,
return ORBIS_OK; OrbisAppContentGetEntitlementKey* key) {
LOG_ERROR(Lib_AppContent, "called");
if (entitlement_label == nullptr || key == nullptr) {
return ORBIS_APP_CONTENT_ERROR_PARAMETER;
}
for (int i = 0; i < addcont_count; i++) {
if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel,
ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) {
continue;
}
memcpy(key->data, addcont_info[i].key.data, ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE);
return ORBIS_OK;
}
return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
} }
int PS4_SYSV_ABI sceAppContentGetRegion() { int PS4_SYSV_ABI sceAppContentGetRegion() {
@ -150,7 +248,25 @@ int PS4_SYSV_ABI sceAppContentGetRegion() {
int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam,
OrbisAppContentBootParam* bootParam) { OrbisAppContentBootParam* bootParam) {
LOG_ERROR(Lib_AppContent, "(DUMMY) called"); LOG_ERROR(Lib_AppContent, "(DUMMY) called");
bootParam->attr = 0; // always 0 auto* param_sfo = Common::Singleton<PSF>::Instance();
const auto addons_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir);
title_id = param_sfo->GetString("TITLE_ID");
auto addon_path = addons_dir / title_id;
if (std::filesystem::exists(addon_path)) {
for (const auto& entry : std::filesystem::directory_iterator(addon_path)) {
if (entry.is_directory()) {
auto entitlement_label = entry.path().filename().string();
AddContInfo info{};
info.status = ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED;
strcpy(info.entitlementLabel, entitlement_label.c_str());
addcont_info[addcont_count++] = info;
}
}
}
return ORBIS_OK; return ORBIS_OK;
} }
@ -324,4 +440,4 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) {
sceAppContentGetDownloadedStoreCountry); sceAppContentGetDownloadedStoreCountry);
}; };
} // namespace Libraries::AppContent } // namespace Libraries::AppContent

View File

@ -41,6 +41,16 @@ struct OrbisAppContentMountPoint {
constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_NONE = 0; constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_NONE = 0;
constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_FORMAT = (1 << 0); constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_FORMAT = (1 << 0);
constexpr int ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE = 17; constexpr int ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE = 17;
constexpr int ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE = 16;
constexpr int ORBIS_APP_CONTENT_INFO_LIST_MAX_SIZE = 2500;
enum OrbisAppContentAddcontDownloadStatus : u32 {
ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_EXTRA_DATA = 0,
ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_IN_QUEUE = 1,
ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOADING = 2,
ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOAD_SUSPENDED = 3,
ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED = 4
};
struct OrbisNpUnifiedEntitlementLabel { struct OrbisNpUnifiedEntitlementLabel {
char data[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE]; char data[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE];
@ -54,11 +64,17 @@ struct OrbisAppContentAddcontInfo {
u32 status; u32 status;
}; };
struct OrbisAppContentGetEntitlementKey {
char data[ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE];
};
int PS4_SYSV_ABI _Z5dummyv(); int PS4_SYSV_ABI _Z5dummyv();
int PS4_SYSV_ABI sceAppContentAddcontDelete(); int PS4_SYSV_ABI sceAppContentAddcontDelete();
int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownload(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownload();
int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp();
int PS4_SYSV_ABI sceAppContentAddcontMount(); int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label,
const OrbisNpUnifiedEntitlementLabel* entitlement_label,
OrbisAppContentMountPoint* mount_point);
int PS4_SYSV_ABI sceAppContentAddcontShrink(); int PS4_SYSV_ABI sceAppContentAddcontShrink();
int PS4_SYSV_ABI sceAppContentAddcontUnmount(); int PS4_SYSV_ABI sceAppContentAddcontUnmount();
int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value); int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value);
@ -70,11 +86,15 @@ int PS4_SYSV_ABI sceAppContentDownload1Shrink();
int PS4_SYSV_ABI sceAppContentDownloadDataFormat(); int PS4_SYSV_ABI sceAppContentDownloadDataFormat();
int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(); int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb();
int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress(); int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress();
int PS4_SYSV_ABI sceAppContentGetAddcontInfo(); int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label,
const OrbisNpUnifiedEntitlementLabel* entitlementLabel,
OrbisAppContentAddcontInfo* info);
int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label,
OrbisAppContentAddcontInfo* list, u32 list_num, OrbisAppContentAddcontInfo* list, u32 list_num,
u32* hit_num); u32* hit_num);
int PS4_SYSV_ABI sceAppContentGetEntitlementKey(); int PS4_SYSV_ABI sceAppContentGetEntitlementKey(
u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label,
OrbisAppContentGetEntitlementKey* key);
int PS4_SYSV_ABI sceAppContentGetRegion(); int PS4_SYSV_ABI sceAppContentGetRegion();
int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam,
OrbisAppContentBootParam* bootParam); OrbisAppContentBootParam* bootParam);

View File

@ -2,9 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <memory> #include <memory>
#include <common/assert.h>
#include <magic_enum.hpp> #include <magic_enum.hpp>
#include "audio_core/sdl_audio.h" #include "audio_core/sdl_audio.h"
#include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/audio/audioout.h" #include "core/libraries/audio/audioout.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"

View File

@ -325,4 +325,4 @@ void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("yN7Jhuv8g24", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerVprintf); LIB_FUNCTION("yN7Jhuv8g24", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerVprintf);
}; };
} // namespace Libraries::AvPlayer } // namespace Libraries::AvPlayer

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -460,4 +460,6 @@ constexpr int ORBIS_AVPLAYER_ERROR_INFO_AES_ENCRY = 0x806A00B5;
constexpr int ORBIS_AVPLAYER_ERROR_INFO_OTHER_ENCRY = 0x806A00BF; constexpr int ORBIS_AVPLAYER_ERROR_INFO_OTHER_ENCRY = 0x806A00BF;
// AppContent library // AppContent library
constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002;
constexpr int ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = 0x80D90007;
constexpr int ORBIS_APP_CONTENT_ERROR_NOT_FOUND = 0x80D90005;

View File

@ -650,12 +650,12 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32
} }
s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
u32 flags) { u32 flags) {
LOG_TRACE(Lib_GnmDriver, "called"); LOG_TRACE(Lib_GnmDriver, "called");
if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) && if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) &&
(vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) { (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) {
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndexIndirect>( cmdbuf = WriteHeader<PM4ItOpcode::DrawIndexIndirect>(
@ -665,7 +665,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset,
cmdbuf[0] = data_offset; cmdbuf[0] = data_offset;
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[3] = 0; cmdbuf[3] = 0;
cmdbuf += 4; cmdbuf += 4;
@ -707,11 +707,11 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset,
} }
s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags) { u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags) {
LOG_TRACE(Lib_GnmDriver, "called"); LOG_TRACE(Lib_GnmDriver, "called");
if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) && if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) &&
(vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) { (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) {
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndirect>(cmdbuf, 4, PM4ShaderType::ShaderGraphics, cmdbuf = WriteHeader<PM4ItOpcode::DrawIndirect>(cmdbuf, 4, PM4ShaderType::ShaderGraphics,
@ -721,7 +721,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32
cmdbuf[0] = data_offset; cmdbuf[0] = data_offset;
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[3] = 2; // auto index cmdbuf[3] = 2; // auto index
cmdbuf += 4; cmdbuf += 4;

View File

@ -45,7 +45,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr
u32 flags, u32 type); u32 flags, u32 type);
s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags); s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags);
s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
u32 flags); u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti();
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti(); int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti();
@ -53,7 +53,7 @@ int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced();
s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count, s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count,
u32 flags); u32 flags);
s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags); u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti();
int PS4_SYSV_ABI sceGnmDrawIndirectMulti(); int PS4_SYSV_ABI sceGnmDrawIndirectMulti();
u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size); u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size);

View File

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <common/assert.h> #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <thread> #include <thread>
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "event_flag_obj.h" #include "event_flag_obj.h"

View File

@ -2,8 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include "common/types.h" #include "common/types.h"
namespace Libraries::Kernel { namespace Libraries::Kernel {

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <thread> #include <thread>
#include "common/assert.h" #include "common/assert.h"
#include "core/libraries/kernel/event_queue.h" #include "core/libraries/kernel/event_queue.h"

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <sys/types.h> #include <sys/types.h>
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <bit> #include <bit>
#include "common/alignment.h" #include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"

View File

@ -4,12 +4,14 @@
#include <mutex> #include <mutex>
#include <semaphore> #include <semaphore>
#include <thread> #include <thread>
#include "common/alignment.h" #include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/error.h" #include "common/error.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "common/thread.h" #include "common/thread.h"
#include "core/cpu_patches.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/kernel/libkernel.h" #include "core/libraries/kernel/libkernel.h"
#include "core/libraries/kernel/thread_management.h" #include "core/libraries/kernel/thread_management.h"
@ -985,6 +987,7 @@ static void cleanup_thread(void* arg) {
destructor(value); destructor(value);
} }
} }
Core::CleanupThreadPatchStack();
thread->is_almost_done = true; thread->is_almost_done = true;
} }
@ -992,6 +995,7 @@ static void* run_thread(void* arg) {
auto* thread = static_cast<ScePthread>(arg); auto* thread = static_cast<ScePthread>(arg);
Common::SetCurrentThreadName(thread->name.c_str()); Common::SetCurrentThreadName(thread->name.c_str());
auto* linker = Common::Singleton<Core::Linker>::Instance(); auto* linker = Common::Singleton<Core::Linker>::Instance();
Core::InitializeThreadPatchStack();
linker->InitTlsForThread(false); linker->InitTlsForThread(false);
void* ret = nullptr; void* ret = nullptr;
g_pthread_self = thread; g_pthread_self = thread;

View File

@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {

View File

@ -2,10 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <condition_variable> #include <condition_variable>
#include <list>
#include <mutex> #include <mutex>
#include <utility>
#include <boost/intrusive/list.hpp>
#include <pthread.h> #include <pthread.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
@ -13,9 +13,6 @@
namespace Libraries::Kernel { namespace Libraries::Kernel {
using ListBaseHook =
boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>;
class Semaphore { class Semaphore {
public: public:
Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo) Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo)
@ -37,7 +34,7 @@ public:
// Create waiting thread object and add it into the list of waiters. // Create waiting thread object and add it into the list of waiters.
WaitingThread waiter{need_count, is_fifo}; WaitingThread waiter{need_count, is_fifo};
AddWaiter(waiter); AddWaiter(&waiter);
// Perform the wait. // Perform the wait.
return waiter.Wait(lk, timeout); return waiter.Wait(lk, timeout);
@ -52,14 +49,14 @@ public:
// Wake up threads in order of priority. // Wake up threads in order of priority.
for (auto it = wait_list.begin(); it != wait_list.end();) { for (auto it = wait_list.begin(); it != wait_list.end();) {
auto& waiter = *it; auto* waiter = *it;
if (waiter.need_count > token_count) { if (waiter->need_count > token_count) {
it++; it++;
continue; continue;
} }
it = wait_list.erase(it); it = wait_list.erase(it);
token_count -= waiter.need_count; token_count -= waiter->need_count;
waiter.cv.notify_one(); waiter->cv.notify_one();
} }
return true; return true;
@ -70,9 +67,9 @@ public:
if (num_waiters) { if (num_waiters) {
*num_waiters = wait_list.size(); *num_waiters = wait_list.size();
} }
for (auto& waiter : wait_list) { for (auto* waiter : wait_list) {
waiter.was_cancled = true; waiter->was_cancled = true;
waiter.cv.notify_one(); waiter->cv.notify_one();
} }
wait_list.clear(); wait_list.clear();
token_count = set_count < 0 ? init_count : set_count; token_count = set_count < 0 ? init_count : set_count;
@ -80,7 +77,7 @@ public:
} }
public: public:
struct WaitingThread : public ListBaseHook { struct WaitingThread {
std::condition_variable cv; std::condition_variable cv;
u32 priority; u32 priority;
s32 need_count; s32 need_count;
@ -132,7 +129,7 @@ public:
} }
}; };
void AddWaiter(WaitingThread& waiter) { void AddWaiter(WaitingThread* waiter) {
// Insert at the end of the list for FIFO order. // Insert at the end of the list for FIFO order.
if (is_fifo) { if (is_fifo) {
wait_list.push_back(waiter); wait_list.push_back(waiter);
@ -140,16 +137,13 @@ public:
} }
// Find the first with priority less then us and insert right before it. // Find the first with priority less then us and insert right before it.
auto it = wait_list.begin(); auto it = wait_list.begin();
while (it != wait_list.end() && it->priority > waiter.priority) { while (it != wait_list.end() && (*it)->priority > waiter->priority) {
it++; it++;
} }
wait_list.insert(it, waiter); wait_list.insert(it, waiter);
} }
using WaitingThreads = std::list<WaitingThread*> wait_list;
boost::intrusive::list<WaitingThread, boost::intrusive::base_hook<ListBaseHook>,
boost::intrusive::constant_time_size<false>>;
WaitingThreads wait_list;
std::string name; std::string name;
std::atomic<s32> token_count; std::atomic<s32> token_count;
std::mutex mutex; std::mutex mutex;

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <thread> #include <thread>
#include "common/assert.h" #include "common/assert.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/native_clock.h" #include "common/native_clock.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <cmath> #include <cmath>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -2,13 +2,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/config.h" #include "common/config.h"
#include "core/libraries/ajm/ajm.h"
#include "core/libraries/app_content/app_content.h" #include "core/libraries/app_content/app_content.h"
#include "core/libraries/audio/audioin.h" #include "core/libraries/audio/audioin.h"
#include "core/libraries/audio/audioout.h" #include "core/libraries/audio/audioout.h"
#include "core/libraries/avplayer/avplayer.h"
#include "core/libraries/dialogs/error_dialog.h"
#include "core/libraries/dialogs/ime_dialog.h"
#include "core/libraries/disc_map/disc_map.h" #include "core/libraries/disc_map/disc_map.h"
#include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/gnmdriver/gnmdriver.h"
#include "core/libraries/kernel/libkernel.h" #include "core/libraries/kernel/libkernel.h"
#include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libc_internal/libc_internal.h"
#include "core/libraries/libpng/pngdec.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/network/http.h" #include "core/libraries/network/http.h"
#include "core/libraries/network/net.h" #include "core/libraries/network/net.h"
@ -32,11 +37,6 @@
#include "core/libraries/system/userservice.h" #include "core/libraries/system/userservice.h"
#include "core/libraries/usbd/usbd.h" #include "core/libraries/usbd/usbd.h"
#include "core/libraries/videoout/video_out.h" #include "core/libraries/videoout/video_out.h"
#include "src/core/libraries/ajm/ajm.h"
#include "src/core/libraries/avplayer/avplayer.h"
#include "src/core/libraries/dialogs/error_dialog.h"
#include "src/core/libraries/dialogs/ime_dialog.h"
#include "src/core/libraries/libpng/pngdec.h"
namespace Libraries { namespace Libraries {

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/loader/elf.h" #include "core/loader/elf.h"
#include "core/loader/symbols_resolver.h" #include "core/loader/symbols_resolver.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/config.h" #include "common/config.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include <unordered_map> #include <unordered_map>
#include "common/logging/log.h" #include "common/logging/log.h"

View File

@ -1,11 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator #include "common/assert.h"
#include <common/assert.h>
#include <common/singleton.h>
#include "common/config.h" #include "common/config.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "input/controller.h" #include "input/controller.h"

View File

@ -1,9 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <core/file_format/playgo_chunk.h>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/file_format/playgo_chunk.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/system/systemservice.h" #include "core/libraries/system/systemservice.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "common/types.h" #include "common/types.h"
#include "playgo_types.h" #include "playgo_types.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {

View File

@ -1,8 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include <chrono> #include <chrono>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -3,12 +3,13 @@
#include <span> #include <span>
#include <vector> #include <vector>
#include <common/path_util.h>
#include <common/singleton.h>
#include <core/file_format/psf.h>
#include <core/file_sys/fs.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/path_util.h"
#include "common/singleton.h"
#include "core/file_format/psf.h"
#include "core/file_sys/fs.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/save_data/savedata.h" #include "core/libraries/save_data/savedata.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Generated By moduleGenerator
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <string_view> #include <string_view>
#include "common/assert.h" #include "common/assert.h"
#include "common/types.h" #include "common/types.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <pthread.h> #include <pthread.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/config.h" #include "common/config.h"
#include "common/debug.h" #include "common/debug.h"

View File

@ -10,6 +10,7 @@
#include "common/thread.h" #include "common/thread.h"
#include "core/aerolib/aerolib.h" #include "core/aerolib/aerolib.h"
#include "core/aerolib/stubs.h" #include "core/aerolib/stubs.h"
#include "core/cpu_patches.h"
#include "core/libraries/kernel/memory_management.h" #include "core/libraries/kernel/memory_management.h"
#include "core/libraries/kernel/thread_management.h" #include "core/libraries/kernel/thread_management.h"
#include "core/linker.h" #include "core/linker.h"
@ -85,6 +86,7 @@ void Linker::Execute() {
// Init primary thread. // Init primary thread.
Common::SetCurrentThreadName("GAME_MainThread"); Common::SetCurrentThreadName("GAME_MainThread");
Libraries::Kernel::pthreadInitSelfMainThread(); Libraries::Kernel::pthreadInitSelfMainThread();
InitializeThreadPatchStack();
InitTlsForThread(true); InitTlsForThread(true);
// Start shared library modules // Start shared library modules
@ -104,6 +106,8 @@ void Linker::Execute() {
RunMainEntry(m->GetEntryAddress(), &p, ProgramExitFunc); RunMainEntry(m->GetEntryAddress(), &p, ProgramExitFunc);
} }
} }
CleanupThreadPatchStack();
} }
s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) {

View File

@ -84,6 +84,8 @@ void Emulator::Run(const std::filesystem::path& file) {
// Applications expect to be run from /app0 so mount the file's parent path as app0. // Applications expect to be run from /app0 so mount the file's parent path as app0.
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
mnt->Mount(file.parent_path(), "/app0"); mnt->Mount(file.parent_path(), "/app0");
// Certain games may use /hostapp as well such as CUSA001100
mnt->Mount(file.parent_path(), "/hostapp");
// Loading param.sfo file if exists // Loading param.sfo file if exists
std::string id; std::string id;

View File

@ -130,7 +130,7 @@ void CheatsPatches::setupUI() {
// Call the method to fill the list of cheat files // Call the method to fill the list of cheat files
populateFileListCheats(); populateFileListCheats();
QLabel* repositoryLabel = new QLabel("Repository:"); QLabel* repositoryLabel = new QLabel(tr("Repository:"));
repositoryLabel->setAlignment(Qt::AlignLeft); repositoryLabel->setAlignment(Qt::AlignLeft);
repositoryLabel->setAlignment(Qt::AlignVCenter); repositoryLabel->setAlignment(Qt::AlignVCenter);
@ -175,7 +175,8 @@ void CheatsPatches::setupUI() {
int ret = QMessageBox::warning( int ret = QMessageBox::warning(
this, tr("Delete File"), this, tr("Delete File"),
QString(tr("Do you want to delete the selected file?\n%1")).arg(selectedFileName), QString(tr("Do you want to delete the selected file?\\n%1").replace("\\n", "\n"))
.arg(selectedFileName),
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) { if (ret == QMessageBox::Yes) {
@ -1123,7 +1124,7 @@ void CheatsPatches::addPatchesToLayout(const QString& filePath) {
void CheatsPatches::updateNoteTextEdit(const QString& patchName) { void CheatsPatches::updateNoteTextEdit(const QString& patchName) {
if (m_patchInfos.contains(patchName)) { if (m_patchInfos.contains(patchName)) {
const PatchInfo& patchInfo = m_patchInfos[patchName]; const PatchInfo& patchInfo = m_patchInfos[patchName];
QString text = QString(tr("Name:") + " %1\n" + tr("Author:") + " %2\n\n%3") QString text = QString(tr("Name:") + " %1\n" + tr("Author: ") + "%2\n\n%3")
.arg(patchInfo.name) .arg(patchInfo.name)
.arg(patchInfo.author) .arg(patchInfo.author)
.arg(patchInfo.note); .arg(patchInfo.note);
@ -1261,4 +1262,4 @@ void CheatsPatches::onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered) {
} else { } else {
instructionsTextEdit->setText(defaultTextEdit); instructionsTextEdit->setText(defaultTextEdit);
} }
} }

View File

@ -36,6 +36,7 @@ public:
void downloadCheats(const QString& source, const QString& m_gameSerial, void downloadCheats(const QString& source, const QString& m_gameSerial,
const QString& m_gameVersion, bool showMessageBox); const QString& m_gameVersion, bool showMessageBox);
void downloadPatches(const QString repository, const bool showMessageBox); void downloadPatches(const QString repository, const bool showMessageBox);
void createFilesJson(const QString& repository);
signals: signals:
void downloadFinished(); void downloadFinished();
@ -58,7 +59,6 @@ private:
void applyCheat(const QString& modName, bool enabled); void applyCheat(const QString& modName, bool enabled);
void applyPatch(const QString& patchName, bool enabled); void applyPatch(const QString& patchName, bool enabled);
void createFilesJson(const QString& repository);
void uncheckAllCheatCheckBoxes(); void uncheckAllCheatCheckBoxes();
void updateNoteTextEdit(const QString& patchName); void updateNoteTextEdit(const QString& patchName);

View File

@ -140,7 +140,7 @@ public:
new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage); new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage);
cheatsPatches->show(); cheatsPatches->show();
connect(widget->parent(), &QWidget::destroyed, cheatsPatches, connect(widget->parent(), &QWidget::destroyed, cheatsPatches,
[widget, cheatsPatches]() { cheatsPatches->deleteLater(); }); [cheatsPatches]() { cheatsPatches->deleteLater(); });
} }
if (selected == &openTrophyViewer) { if (selected == &openTrophyViewer) {

View File

@ -7,6 +7,7 @@
#include "about_dialog.h" #include "about_dialog.h"
#include "cheats_patches.h" #include "cheats_patches.h"
#include "common/io_file.h" #include "common/io_file.h"
#include "common/string_util.h"
#include "common/version.h" #include "common/version.h"
#include "core/file_format/pkg.h" #include "core/file_format/pkg.h"
#include "core/loader.h" #include "core/loader.h"
@ -365,7 +366,7 @@ void MainWindow::CreateConnects() {
panelDialog->accept(); panelDialog->accept();
}); });
connect(downloadAllPatchesButton, &QPushButton::clicked, this, [this, panelDialog]() { connect(downloadAllPatchesButton, &QPushButton::clicked, [panelDialog]() {
QEventLoop eventLoop; QEventLoop eventLoop;
int pendingDownloads = 0; int pendingDownloads = 0;
@ -390,6 +391,8 @@ void MainWindow::CreateConnects() {
nullptr, tr("Download Complete"), nullptr, tr("Download Complete"),
QString(tr("Patches Downloaded Successfully!") + "\n" + QString(tr("Patches Downloaded Successfully!") + "\n" +
tr("All Patches available for all games have been downloaded."))); tr("All Patches available for all games have been downloaded.")));
cheatsPatches->createFilesJson("GoldHEN");
cheatsPatches->createFilesJson("shadPS4");
panelDialog->accept(); panelDialog->accept();
}); });
panelDialog->exec(); panelDialog->exec();
@ -615,39 +618,48 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
pkg = PKG(); pkg = PKG();
pkg.Open(file); pkg.Open(file);
std::string failreason; std::string failreason;
const auto extract_path = auto extract_path = std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID();
std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID();
QString pkgType = QString::fromStdString(pkg.GetPkgFlags()); QString pkgType = QString::fromStdString(pkg.GetPkgFlags());
QDir game_dir(QString::fromStdString(extract_path.string())); QDir game_dir(QString::fromStdString(extract_path.string()));
if (game_dir.exists()) { if (game_dir.exists()) {
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(tr("PKG Extraction")); msgBox.setWindowTitle(tr("PKG Extraction"));
psf.open("", pkg.sfo);
std::string content_id = psf.GetString("CONTENT_ID");
std::string entitlement_label = Common::SplitString(content_id, '-')[2];
auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) /
pkg.GetTitleID() / entitlement_label;
QDir addon_dir(QString::fromStdString(addon_extract_path.string()));
auto category = psf.GetString("CATEGORY");
if (pkgType.contains("PATCH")) { if (pkgType.contains("PATCH")) {
psf.open("", pkg.sfo);
QString pkg_app_version = QString::fromStdString(psf.GetString("APP_VER")); QString pkg_app_version = QString::fromStdString(psf.GetString("APP_VER"));
psf.open(extract_path.string() + "/sce_sys/param.sfo", {}); psf.open(extract_path.string() + "/sce_sys/param.sfo", {});
QString game_app_version = QString::fromStdString(psf.GetString("APP_VER")); QString game_app_version = QString::fromStdString(psf.GetString("APP_VER"));
double appD = game_app_version.toDouble(); double appD = game_app_version.toDouble();
double pkgD = pkg_app_version.toDouble(); double pkgD = pkg_app_version.toDouble();
if (pkgD == appD) { if (pkgD == appD) {
msgBox.setText(QString(tr("Patch detected!\nPKG and Game versions match!: " msgBox.setText(QString(tr("Patch detected!") + "\n" +
"%1\nWould you like ") + tr("PKG and Game versions match: ") + pkg_app_version +
tr("to overwrite?")) "\n" + tr("Would you like to overwrite?")));
.arg(pkg_app_version));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No);
} else if (pkgD < appD) { } else if (pkgD < appD) {
msgBox.setText(QString(tr("Patch detected!\nPKG Version %1 is older ") + msgBox.setText(QString(tr("Patch detected!") + "\n" +
tr("than installed version!: %2\nWould you like ") + tr("PKG Version %1 is older than installed version: ")
tr("to overwrite?")) .arg(pkg_app_version) +
.arg(pkg_app_version, game_app_version)); game_app_version + "\n" +
tr("Would you like to overwrite?")));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No);
} else { } else {
msgBox.setText( msgBox.setText(QString(tr("Patch detected!") + "\n" +
QString(tr("Patch detected!\nGame is installed: %1\nWould you like ") + tr("Game is installed: ") + game_app_version + "\n" +
tr("to install Patch: %2?")) tr("Would you like to install Patch: ") +
.arg(game_app_version, pkg_app_version)); pkg_app_version + " ?"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No);
} }
@ -657,10 +669,38 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
} else { } else {
return; return;
} }
} else if (category == "ac") {
if (!addon_dir.exists()) {
QMessageBox addonMsgBox;
addonMsgBox.setWindowTitle(tr("DLC Installation"));
addonMsgBox.setText(QString(tr("Would you like to install DLC: %1?"))
.arg(QString::fromStdString(entitlement_label)));
addonMsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
addonMsgBox.setDefaultButton(QMessageBox::No);
int result = addonMsgBox.exec();
if (result == QMessageBox::Yes) {
extract_path = addon_extract_path;
} else {
return;
}
} else {
msgBox.setText(QString(tr("DLC already installed:") + "\n" +
QString::fromStdString(addon_extract_path.string()) +
"\n\n" + tr("Would you like to overwrite?")));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
int result = msgBox.exec();
if (result == QMessageBox::Yes) {
extract_path = addon_extract_path;
} else {
return;
}
}
} else { } else {
msgBox.setText( msgBox.setText(QString(tr("Game already installed") + "\n" +
QString(tr("Game already installed\n%1\nWould you like to overwrite?")) QString::fromStdString(extract_path.string()) + "\n" +
.arg(QString::fromStdString(extract_path.string()))); tr("Would you like to overwrite?")));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No);
int result = msgBox.exec(); int result = msgBox.exec();
@ -685,45 +725,47 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int
} else { } else {
int nfiles = pkg.GetNumberOfFiles(); int nfiles = pkg.GetNumberOfFiles();
QVector<int> indices; if (nfiles > 0) {
for (int i = 0; i < nfiles; i++) { QVector<int> indices;
indices.append(i); for (int i = 0; i < nfiles; i++) {
} indices.append(i);
QProgressDialog dialog;
dialog.setWindowTitle(tr("PKG Extraction"));
dialog.setWindowModality(Qt::WindowModal);
QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg);
dialog.setLabelText(extractmsg);
dialog.setAutoClose(true);
dialog.setRange(0, nfiles);
QFutureWatcher<void> futureWatcher;
connect(&futureWatcher, &QFutureWatcher<void>::finished, this, [=, this]() {
if (pkgNum == nPkg) {
QString path = QString::fromStdString(Config::getGameInstallDir());
QMessageBox extractMsgBox(this);
extractMsgBox.setWindowTitle(tr("Extraction Finished"));
extractMsgBox.setText(
QString(tr("Game successfully installed at %1")).arg(path));
extractMsgBox.addButton(QMessageBox::Ok);
extractMsgBox.setDefaultButton(QMessageBox::Ok);
connect(&extractMsgBox, &QMessageBox::buttonClicked, this,
[&](QAbstractButton* button) {
if (extractMsgBox.button(QMessageBox::Ok) == button) {
extractMsgBox.close();
emit ExtractionFinished();
}
});
extractMsgBox.exec();
} }
});
connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); }); QProgressDialog dialog;
connect(&futureWatcher, &QFutureWatcher<void>::progressValueChanged, &dialog, dialog.setWindowTitle(tr("PKG Extraction"));
&QProgressDialog::setValue); dialog.setWindowModality(Qt::WindowModal);
futureWatcher.setFuture( QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg);
QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); })); dialog.setLabelText(extractmsg);
dialog.exec(); dialog.setAutoClose(true);
dialog.setRange(0, nfiles);
QFutureWatcher<void> futureWatcher;
connect(&futureWatcher, &QFutureWatcher<void>::finished, this, [=, this]() {
if (pkgNum == nPkg) {
QString path = QString::fromStdString(Config::getGameInstallDir());
QMessageBox extractMsgBox(this);
extractMsgBox.setWindowTitle(tr("Extraction Finished"));
extractMsgBox.setText(
QString(tr("Game successfully installed at %1")).arg(path));
extractMsgBox.addButton(QMessageBox::Ok);
extractMsgBox.setDefaultButton(QMessageBox::Ok);
connect(&extractMsgBox, &QMessageBox::buttonClicked, this,
[&](QAbstractButton* button) {
if (extractMsgBox.button(QMessageBox::Ok) == button) {
extractMsgBox.close();
emit ExtractionFinished();
}
});
extractMsgBox.exec();
}
});
connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); });
connect(&futureWatcher, &QFutureWatcher<void>::progressValueChanged, &dialog,
&QProgressDialog::setValue);
futureWatcher.setFuture(
QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); }));
dialog.exec();
}
} }
} else { } else {
QMessageBox::critical(this, tr("PKG ERROR"), QMessageBox::critical(this, tr("PKG ERROR"),

View File

@ -566,44 +566,54 @@
<translation>PKG-udtrækning</translation> <translation>PKG-udtrækning</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch opdaget!\nPKG- og spilversioner stemmer overens!: %1\nVil du </translation> <translation>Opdatering detekteret!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>overskrive?</translation> <translation>PKG og spilversioner matcher: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Patch opdaget!\nPKG-version %1 er ældre </translation> <translation>Vil du overskrive?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>end installeret version!: %2\nVil du </translation> <translation>PKG Version %1 er ældre end den installerede version: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>overskrive?</translation> <translation>Spillet er installeret: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Patch opdaget!\nSpillet er installeret: %1\nVil du </translation> <translation>Vil du installere opdateringen: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>installere patch: %2?</translation> <translation>DLC Installation</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Spil allerede installeret\n%1\nVil du overskrive?</translation> <translation>Vil du installere DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC allerede installeret:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Spillet er allerede installeret</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG-Extraktion</translation> <translation>PKG-Extraktion</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch erkannt!\nPKG- und Spielversion stimmen überein!: %1\nMöchten Sie </translation> <translation>Patch erkannt!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>überschreiben?</translation> <translation>PKG- und Spielversionen stimmen überein: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Patch erkannt!\nPKG-Version %1 ist älter </translation> <translation>Würden Sie gerne überschreiben?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>als die installierte Version!: %2\nMöchten Sie </translation> <translation>PKG-Version %1 ist älter als die installierte Version: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>überschreiben?</translation> <translation>Spiel ist installiert: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Patch erkannt!\nSpiel ist installiert: %1\nMöchten Sie </translation> <translation>Möchten Sie den Patch installieren: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>Patch installieren: %2?</translation> <translation>DLC-Installation</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Spiel bereits installiert\n%1\nMöchten Sie überschreiben?</translation> <translation>Würden Sie gerne DLC installieren: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC bereits installiert:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Spiel bereits installiert</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>Εξαγωγή PKG</translation> <translation>Εξαγωγή PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Ανίχνευση Patch!\nΟι εκδόσεις PKG και παιχνιδιού ταιριάζουν!: %1\nΘέλετε </translation> <translation>Αναγνώριση ενημέρωσης!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>να αντικαταστήσετε;</translation> <translation>Οι εκδόσεις PKG και παιχνιδιού ταιριάζουν: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Ανίχνευση Patch!\nΗ έκδοση PKG %1 είναι παλαιότερη </translation> <translation>Θέλετε να αντικαταστήσετε;</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>από την εγκατεστημένη έκδοση!: %2\nΘέλετε </translation> <translation>Η έκδοση PKG %1 είναι παλαιότερη από την εγκατεστημένη έκδοση: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>να αντικαταστήσετε;</translation> <translation>Το παιχνίδι είναι εγκατεστημένο: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Ανίχνευση Patch!\nΤο παιχνίδι είναι εγκατεστημένο: %1\nΘέλετε </translation> <translation>Θέλετε να εγκαταστήσετε την ενημέρωση: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>να εγκαταστήσετε το Patch: %2;</translation> <translation>Εγκατάσταση DLC</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Το παιχνίδι είναι ήδη εγκατεστημένο\n%1\nΘέλετε να αντικαταστήσετε;</translation> <translation>Θέλετε να εγκαταστήσετε το DLC: %1;</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC ήδη εγκατεστημένο:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Παιχνίδι ήδη εγκατεστημένο</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG Extraction</translation> <translation>PKG Extraction</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch detected!\nPKG and Game versions match!: %1\nWould you like </translation> <translation>Patch detected!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>to overwrite?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Patch detected!\nPKG Version %1 is older </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>than installed version!: %2\nWould you like </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>to overwrite?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Patch detected!\nGame is installed: %1\nWould you like </translation> <translation>PKG and Game versions match: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>to install Patch: %2?</translation> <translation>Would you like to overwrite?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Game already installed\n%1\nWould you like to overwrite?</translation> <translation>PKG Version %1 is older than installed version: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Game is installed: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Would you like to install Patch: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>DLC Installation</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Would you like to install DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC already installed:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Game already installed</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>Extracción de PKG</translation> <translation>Extracción de PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>¡Parche detectado!\n¡La versión de PKG y del juego coinciden!: %1\n¿Te gustaría </translation> <translation>¡Actualización detectada!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>¿sobrescribir?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>¡Parche detectado!\nLa versión de PKG %1 es más antigua </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>que la versión instalada!: %2\n¿Te gustaría </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>¿sobrescribir?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>¡Parche detectado!\nJuego está instalado: %1\n¿Te gustaría </translation> <translation>Las versiones de PKG y del juego coinciden: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>¿instalar el parche: %2?</translation> <translation>¿Desea sobrescribir?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Juego ya instalado\n%1\n¿Te gustaría sobrescribirlo?</translation> <translation>La versión de PKG %1 es más antigua que la versión instalada: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>El juego está instalado: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>¿Desea instalar la actualización: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>Instalación de DLC</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>¿Desea instalar el DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC ya instalado:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Juego ya instalado</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG:n purku</translation> <translation>PKG:n purku</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Korjaus havaittu!\nPKG:n ja pelin versiot vastaavat!: %1\nHaluatko </translation> <translation>Päivitys havaittu!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>korvata?</translation> <translation>PKG- ja peliversiot vastaavat: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Korjaus havaittu!\nPKG Version %1 on vanhempi </translation> <translation>Haluatko korvata?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>kuin asennettu versio!: %2\nHaluatko </translation> <translation>PKG-versio %1 on vanhempi kuin asennettu versio: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>korvata?</translation> <translation>Peli on asennettu: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Korjaus havaittu!\nPeli on asennettu: %1\nHaluatko </translation> <translation>Haluatko asentaa päivityksen: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>asentaa korjaus: %2?</translation> <translation>DLC-asennus</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Peli on jo asennettu\n%1\nHaluatko korvata sen?</translation> <translation>Haluatko asentaa DLC:n: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC on jo asennettu:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Peli on jo asennettu</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -93,7 +93,7 @@
<message> <message>
<location filename="../gui_context_menus.h" line="48"/> <location filename="../gui_context_menus.h" line="48"/>
<source>Cheats / Patches</source> <source>Cheats / Patches</source>
<translation>Trucs / Patchs</translation> <translation>Cheats/Patchs</translation>
</message> </message>
<message> <message>
<location filename="../gui_context_menus.h" line="49"/> <location filename="../gui_context_menus.h" line="49"/>
@ -108,7 +108,7 @@
<message> <message>
<location filename="../gui_context_menus.h" line="59"/> <location filename="../gui_context_menus.h" line="59"/>
<source>Copy info</source> <source>Copy info</source>
<translation>Copier les informations</translation> <translation>Copier infos</translation>
</message> </message>
<message> <message>
<location filename="../gui_context_menus.h" line="60"/> <location filename="../gui_context_menus.h" line="60"/>
@ -133,7 +133,7 @@
<message> <message>
<location filename="../gui_context_menus.h" line="196"/> <location filename="../gui_context_menus.h" line="196"/>
<source>Shortcut created successfully!\n %1</source> <source>Shortcut created successfully!\n %1</source>
<translation>Raccourci créé avec succès!\n %1</translation> <translation>Raccourci créé avec succès !\n %1</translation>
</message> </message>
<message> <message>
<location filename="../gui_context_menus.h" line="199"/> <location filename="../gui_context_menus.h" line="199"/>
@ -143,7 +143,7 @@
<message> <message>
<location filename="../gui_context_menus.h" line="200"/> <location filename="../gui_context_menus.h" line="200"/>
<source>Error creating shortcut!\n %1</source> <source>Error creating shortcut!\n %1</source>
<translation>Erreur lors de la création du raccourci!\n %1</translation> <translation>Erreur lors de la création du raccourci !\n %1</translation>
</message> </message>
<message> <message>
<location filename="../gui_context_menus.h" line="275"/> <location filename="../gui_context_menus.h" line="275"/>
@ -256,7 +256,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="343"/> <location filename="../main_window_ui.h" line="343"/>
<source>Download Cheats/Patches</source> <source>Download Cheats/Patches</source>
<translation>Télécharger Trucs / Patchs</translation> <translation>Télécharger Cheats/Patchs</translation>
</message> </message>
<message> <message>
<location filename="../main_window_ui.h" line="345"/> <location filename="../main_window_ui.h" line="345"/>
@ -485,12 +485,12 @@
<message> <message>
<location filename="../settings_dialog.ui" line="560"/> <location filename="../settings_dialog.ui" line="560"/>
<source>Enable Vulkan Validation Layers</source> <source>Enable Vulkan Validation Layers</source>
<translation>Couche de validation Vulkan</translation> <translation>Activer la couche de validation Vulkan</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.ui" line="567"/> <location filename="../settings_dialog.ui" line="567"/>
<source>Enable Vulkan Synchronization Validation</source> <source>Enable Vulkan Synchronization Validation</source>
<translation>Synchroniser la validation Vulkan</translation> <translation>Activer la synchronisation de la validation Vulkan</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.ui" line="574"/> <location filename="../settings_dialog.ui" line="574"/>
@ -503,17 +503,17 @@
<message> <message>
<location filename="../main_window.cpp" line="168"/> <location filename="../main_window.cpp" line="168"/>
<source> * Unsupported Vulkan Version</source> <source> * Unsupported Vulkan Version</source>
<translation> * Version Vulkan non prise en charge</translation> <translation> * Version de Vulkan non prise en charge</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="326"/> <location filename="../main_window.cpp" line="326"/>
<source>Download Cheats For All Installed Games</source> <source>Download Cheats For All Installed Games</source>
<translation>Télécharger les cheats pour tous les jeux installés</translation> <translation>Télécharger les Cheats pour tous les jeux installés</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="328"/> <location filename="../main_window.cpp" line="328"/>
<source>Download Patches For All Games</source> <source>Download Patches For All Games</source>
<translation>Télécharger les patches pour tous les jeux</translation> <translation>Télécharger les patchs pour tous les jeux</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="363"/> <location filename="../main_window.cpp" line="363"/>
@ -523,17 +523,17 @@
<message> <message>
<location filename="../main_window.cpp" line="364"/> <location filename="../main_window.cpp" line="364"/>
<source>You have downloaded cheats for all the games you have installed.</source> <source>You have downloaded cheats for all the games you have installed.</source>
<translation>Vous avez téléchargé des cheats pour tous les jeux que vous avez installés.</translation> <translation>Vous avez téléchargé des Cheats pour tous les jeux installés.</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="391"/> <location filename="../main_window.cpp" line="391"/>
<source>Patches Downloaded Successfully!</source> <source>Patches Downloaded Successfully!</source>
<translation>Patches téléchargés avec succès !</translation> <translation>Patchs téléchargés avec succès !</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="392"/> <location filename="../main_window.cpp" line="392"/>
<source>All Patches available for all games have been downloaded.</source> <source>All Patches available for all games have been downloaded.</source>
<translation>Tous les patches disponibles pour tous les jeux ont é téléchargés.</translation> <translation>Tous les patchs disponibles pour les jeux ont é téléchargés.</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="549"/> <location filename="../main_window.cpp" line="549"/>
@ -543,7 +543,7 @@
<message> <message>
<location filename="../main_window.cpp" line="575"/> <location filename="../main_window.cpp" line="575"/>
<source>PKG File (*.PKG)</source> <source>PKG File (*.PKG)</source>
<translation>Fichier PKG (*.PKG)</translation> <translation>Fichiers PKG (*.PKG)</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="594"/> <location filename="../main_window.cpp" line="594"/>
@ -553,7 +553,7 @@
<message> <message>
<location filename="../main_window.cpp" line="600"/> <location filename="../main_window.cpp" line="600"/>
<source>Game Boot</source> <source>Game Boot</source>
<translation>Boot du jeu</translation> <translation>Démarrer un jeu</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="600"/> <location filename="../main_window.cpp" line="600"/>
@ -563,57 +563,67 @@
<message> <message>
<location filename="../main_window.cpp" line="623"/> <location filename="../main_window.cpp" line="623"/>
<source>PKG Extraction</source> <source>PKG Extraction</source>
<translation>Extraction PKG</translation> <translation>Extraction du PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch détecté !\nLes versions PKG et Jeu correspondent : %1\nSouhaitez-vous </translation> <translation>Patch détecté !</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>écraser ?</translation> <translation>Les versions PKG et jeu correspondent : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Patch détecté !\nVersion PKG %1 est plus ancienne </translation> <translation>Souhaitez-vous remplacer ?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>que la version installée ! : %2\nSouhaitez-vous </translation> <translation>La version PKG %1 est plus ancienne que la version installée : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>écraser ?</translation> <translation>Jeu installé : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Patch détecté !\nJeu est installé : %1\nSouhaitez-vous </translation> <translation>Souhaitez-vous installer le patch : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>installer le patch : %2 ?</translation> <translation>Installation du DLC</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Jeu déjà installé\n%1\nSouhaitez-vous écraser ?</translation> <translation>Souhaitez-vous installer le DLC : %1 ?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC déjà installé :</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Jeu déjà installé</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>
<source>PKG is a patch, please install the game first!</source> <source>PKG is a patch, please install the game first!</source>
<translation>PKG est un patch, veuillez d'abord installer le jeu !</translation> <translation>Le PKG est un patch, veuillez d'abord installer le jeu !</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="681"/> <location filename="../main_window.cpp" line="681"/>
<source>PKG ERROR</source> <source>PKG ERROR</source>
<translation>ERREUR PKG</translation> <translation>Erreur PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="693"/> <location filename="../main_window.cpp" line="693"/>
@ -633,7 +643,7 @@
<message> <message>
<location filename="../main_window.cpp" line="725"/> <location filename="../main_window.cpp" line="725"/>
<source>File doesn't appear to be a valid PKG file</source> <source>File doesn't appear to be a valid PKG file</source>
<translation>Le fichier ne semble pas être un fichier PKG valide</translation> <translation>Le fichier ne semble pas être un PKG valide</translation>
</message> </message>
</context> </context>
<context> <context>
@ -641,12 +651,12 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="44"/> <location filename="../cheats_patches.cpp" line="44"/>
<source>Cheats / Patches</source> <source>Cheats / Patches</source>
<translation>Cheats / Patches</translation> <translation>Cheats/Patches</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="50"/> <location filename="../cheats_patches.cpp" line="50"/>
<source>defaultTextEdit_MSG</source> <source>defaultTextEdit_MSG</source>
<translation>Les cheats/patches sont expérimentaux.\nUtilisez-les avec précaution.\n\nTéléchargez les cheats individuellement en sélectionnant le dépôt et en cliquant sur le bouton de téléchargement.\nDans l'onglet Patches, vous pouvez télécharger tous les patches en une seule fois, choisir lesquels vous souhaitez utiliser et enregistrer votre sélection.\n\nComme nous ne développons pas les Cheats/Patches,\nmerci de signaler les problèmes à l'auteur du cheat.\n\nVous avez créé un nouveau cheat ? Visitez :\nhttps://github.com/shadps4-emu/ps4_cheats</translation> <translation>Les Cheats/Patchs sont expérimentaux.\nUtilisez-les avec précaution.\n\nTéléchargez les Cheats individuellement en sélectionnant le dépôt et en cliquant sur le bouton de téléchargement.\nDans l'onglet Patchs, vous pouvez télécharger tous les patchs en une seule fois, choisir lesquels vous souhaitez utiliser et enregistrer votre sélection.\n\nComme nous ne développons pas les Cheats/Patches,\nmerci de signaler les problèmes à l'auteur du Cheat.\n\nVous avez créé un nouveau cheat ? Visitez :\nhttps://github.com/shadps4-emu/ps4_cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="69"/> <location filename="../cheats_patches.cpp" line="69"/>
@ -671,7 +681,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="126"/> <location filename="../cheats_patches.cpp" line="126"/>
<source>Select Cheat File:</source> <source>Select Cheat File:</source>
<translation>Sélectionner le fichier de cheat :</translation> <translation>Sélectionner le fichier de Cheat :</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="133"/> <location filename="../cheats_patches.cpp" line="133"/>
@ -681,7 +691,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="149"/> <location filename="../cheats_patches.cpp" line="149"/>
<source>Download Cheats</source> <source>Download Cheats</source>
<translation>Télécharger les cheats</translation> <translation>Télécharger les Cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="155"/> <location filename="../cheats_patches.cpp" line="155"/>
@ -696,7 +706,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="170"/> <location filename="../cheats_patches.cpp" line="170"/>
<source>You can delete the cheats you don't want after downloading them.</source> <source>You can delete the cheats you don't want after downloading them.</source>
<translation>Vous pouvez supprimer les cheats que vous ne souhaitez pas après les avoir téléchargés.</translation> <translation>Vous pouvez supprimer les Cheats que vous ne souhaitez pas après les avoir téléchargés.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="178"/> <location filename="../cheats_patches.cpp" line="178"/>
@ -711,7 +721,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="241"/> <location filename="../cheats_patches.cpp" line="241"/>
<source>Download Patches</source> <source>Download Patches</source>
<translation>Télécharger les patches</translation> <translation>Télécharger les patchs</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="248"/> <location filename="../cheats_patches.cpp" line="248"/>
@ -811,7 +821,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="556"/> <location filename="../cheats_patches.cpp" line="556"/>
<source>CheatsNotFound_MSG</source> <source>CheatsNotFound_MSG</source>
<translation>Aucun cheat trouvé pour ce jeu dans cette version du dépôt sélectionné,essayez un autre dépôt ou une version différente du jeu.</translation> <translation>Aucun Cheat trouvé pour ce jeu dans cette version du dépôt sélectionné, essayez un autre dépôt ou une version différente du jeu.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="593"/> <location filename="../cheats_patches.cpp" line="593"/>
@ -841,7 +851,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="763"/> <location filename="../cheats_patches.cpp" line="763"/>
<source>DownloadComplete_MSG</source> <source>DownloadComplete_MSG</source>
<translation>Patchs téléchargés avec succès ! Tous les patches disponibles pour tous les jeux ont é téléchargés, il n'est pas nécessaire de les télécharger individuellement pour chaque jeu comme c'est le cas pour les cheats.</translation> <translation>Patchs téléchargés avec succès ! Tous les patches disponibles pour tous les jeux ont é téléchargés, il n'est pas nécessaire de les télécharger individuellement pour chaque jeu comme c'est le cas pour les Cheats.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="773"/> <location filename="../cheats_patches.cpp" line="773"/>
@ -861,7 +871,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="819"/> <location filename="../cheats_patches.cpp" line="819"/>
<source>XML ERROR:</source> <source>XML ERROR:</source>
<translation>ERREUR XML :</translation> <translation>Erreur XML :</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="826"/> <location filename="../cheats_patches.cpp" line="826"/>
@ -889,4 +899,4 @@
<translation>Nom :</translation> <translation>Nom :</translation>
</message> </message>
</context> </context>
</TS> </TS>

View File

@ -566,44 +566,54 @@
<translation>PKG kicsomagolás</translation> <translation>PKG kicsomagolás</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Javítás észlelve!\nA PKG és a játék verziók egyeznek: %1\nSzeretnéd </translation> <translation>Frissítés észlelve!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>felülírni?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Javítás észlelve!\nA PKG verzió %1 régebbi </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>mint a telepített verzió: %2\nSzeretnéd </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>felülírni?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Javítás észlelve!\nA játék telepítve van: %1\nSzeretnéd </translation> <translation>A PKG és a játék verziói egyeznek: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>a javítást telepíteni: %2?</translation> <translation>Szeretné felülírni?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>A játék már telepítve van\n%1\nSzeretnéd felülírni?</translation> <translation>A %1-es PKG verzió régebbi, mint a telepített verzió: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>A játék telepítve van: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Szeretné telepíteni a frissítést: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>DLC Telepítés</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Szeretné telepíteni a DLC-t: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC már telepítve:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>A játék már telepítve van</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>Ekstraksi PKG</translation> <translation>Ekstraksi PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch terdeteksi!\nVersi PKG dan Game cocok!: %1\nApakah Anda ingin </translation> <translation>Patch terdeteksi!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>menimpa?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Patch terdeteksi!\nVersi PKG %1 lebih lama </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>daripada versi yang terpasang!: %2\nApakah Anda ingin </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>menimpa?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Patch terdeteksi!\nGame terpasang: %1\nApakah Anda ingin </translation> <translation>Versi PKG dan Game cocok: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>memasang Patch: %2?</translation> <translation>Apakah Anda ingin menimpa?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Game sudah terpasang\n%1\nApakah Anda ingin menimpa?</translation> <translation>Versi PKG %1 lebih lama dari versi yang terpasang: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Game telah terpasang: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Apakah Anda ingin menginstal patch: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>Instalasi DLC</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Apakah Anda ingin menginstal DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC sudah terpasang:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Game sudah terpasang</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -181,7 +181,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="318"/> <location filename="../main_window_ui.h" line="318"/>
<source>Install application from a .pkg file</source> <source>Install application from a .pkg file</source>
<translation>Installa applicazione da un file .pkg file</translation> <translation>Installa applicazione da un file .pkg</translation>
</message> </message>
<message> <message>
<location filename="../main_window_ui.h" line="320"/> <location filename="../main_window_ui.h" line="320"/>
@ -236,7 +236,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="338"/> <location filename="../main_window_ui.h" line="338"/>
<source>List View</source> <source>List View</source>
<translation>Visualizzazione lista</translation> <translation>Visualizzazione Lista</translation>
</message> </message>
<message> <message>
<location filename="../main_window_ui.h" line="340"/> <location filename="../main_window_ui.h" line="340"/>
@ -341,7 +341,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="364"/> <location filename="../main_window_ui.h" line="364"/>
<source>toolBar</source> <source>toolBar</source>
<translation>barra strumenti</translation> <translation>Barra strumenti</translation>
</message> </message>
</context> </context>
<context> <context>
@ -356,8 +356,8 @@
<name>TrophyViewer</name> <name>TrophyViewer</name>
<message> <message>
<location filename="../trophy_viewer.cpp" line="8"/> <location filename="../trophy_viewer.cpp" line="8"/>
<source>Visualizzatore Trofei</source> <source>Trophy Viewer</source>
<translation>Trophy Viewer</translation> <translation>Visualizzatore Trofei</translation>
</message> </message>
</context> </context>
<context> <context>
@ -503,42 +503,42 @@
<message> <message>
<location filename="../main_window.cpp" line="168"/> <location filename="../main_window.cpp" line="168"/>
<source> * Unsupported Vulkan Version</source> <source> * Unsupported Vulkan Version</source>
<translation> * Versi Vulkan Tidak Didukung</translation> <translation> * Versione Vulkan non supportata</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="326"/> <location filename="../main_window.cpp" line="326"/>
<source>Download Cheats For All Installed Games</source> <source>Download Cheats For All Installed Games</source>
<translation>Unduh Cheat Untuk Semua Game yang Terinstal</translation> <translation>Scarica Trucchi per tutti i giochi installati</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="328"/> <location filename="../main_window.cpp" line="328"/>
<source>Download Patches For All Games</source> <source>Download Patches For All Games</source>
<translation>Unduh Patch Untuk Semua Game</translation> <translation>Scarica Patch per tutti i giochi</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="363"/> <location filename="../main_window.cpp" line="363"/>
<source>Download Complete</source> <source>Download Complete</source>
<translation>Unduhan Selesai</translation> <translation>Scaricamento completato</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="364"/> <location filename="../main_window.cpp" line="364"/>
<source>You have downloaded cheats for all the games you have installed.</source> <source>You have downloaded cheats for all the games you have installed.</source>
<translation>Anda telah mengunduh cheat untuk semua game yang telah Anda instal.</translation> <translation>Hai scaricato trucchi per tutti i giochi installati.</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="391"/> <location filename="../main_window.cpp" line="391"/>
<source>Patches Downloaded Successfully!</source> <source>Patches Downloaded Successfully!</source>
<translation>Patch Berhasil Diunduh!</translation> <translation>Patch scaricate con successo!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="392"/> <location filename="../main_window.cpp" line="392"/>
<source>All Patches available for all games have been downloaded.</source> <source>All Patches available for all games have been downloaded.</source>
<translation>Semua patch yang tersedia untuk semua game telah diunduh.</translation> <translation>Tutte le patch disponibili per tutti i giochi sono state scaricate.</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="549"/> <location filename="../main_window.cpp" line="549"/>
<source>Games: </source> <source>Games: </source>
<translation>Game: </translation> <translation>Giochi: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="575"/> <location filename="../main_window.cpp" line="575"/>
@ -553,87 +553,97 @@
<message> <message>
<location filename="../main_window.cpp" line="600"/> <location filename="../main_window.cpp" line="600"/>
<source>Game Boot</source> <source>Game Boot</source>
<translation>Boot Game</translation> <translation>Avvia Gioco</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="600"/> <location filename="../main_window.cpp" line="600"/>
<source>Only one file can be selected!</source> <source>Only one file can be selected!</source>
<translation>Hanya satu file yang dapat dipilih!</translation> <translation>Si può selezionare solo un file!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="623"/> <location filename="../main_window.cpp" line="623"/>
<source>PKG Extraction</source> <source>PKG Extraction</source>
<translation>Ekstraksi PKG</translation> <translation>Estrazione file PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch terdeteksi!\nVersi PKG dan Game cocok!: %1\nApakah Anda ingin </translation> <translation>Patch rilevata!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>menimpa?</translation> <translation>Le versioni di PKG e del gioco corrispondono: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Patch terdeteksi!\nVersi PKG %1 lebih lama </translation> <translation>Vuoi sovrascrivere?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>daripada versi yang terinstal!: %2\nApakah Anda ingin </translation> <translation>La versione PKG %1 è più vecchia rispetto alla versione installata: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>menimpa?</translation> <translation>Gioco installato: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Patch terdeteksi!\nGame terinstal: %1\nApakah Anda ingin </translation> <translation>Vuoi installare la patch: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>menginstal Patch: %2?</translation> <translation>Installazione DLC</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Game sudah terinstal\n%1\nApakah Anda ingin menimpa?</translation> <translation>Vuoi installare il DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC già installato:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Gioco già installato</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>
<source>PKG is a patch, please install the game first!</source> <source>PKG is a patch, please install the game first!</source>
<translation>PKG adalah patch, silakan instal game terlebih dahulu!</translation> <translation>Questo file PKG contiene una patch. Per favore, installa prima il gioco!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="681"/> <location filename="../main_window.cpp" line="681"/>
<source>PKG ERROR</source> <source>PKG ERROR</source>
<translation>ERROR PKG</translation> <translation>ERRORE PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="693"/> <location filename="../main_window.cpp" line="693"/>
<source>Extracting PKG %1/%2</source> <source>Extracting PKG %1/%2</source>
<translation>Estrazione PKG %1/%2</translation> <translation>Estrazione file PKG %1/%2</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="703"/> <location filename="../main_window.cpp" line="703"/>
<source>Extraction Finished</source> <source>Extraction Finished</source>
<translation>Ekstraksi Selesai</translation> <translation>Estrazione Completata</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="704"/> <location filename="../main_window.cpp" line="704"/>
<source>Game successfully installed at %1</source> <source>Game successfully installed at %1</source>
<translation>Game berhasil diinstal di %1</translation> <translation>Gioco installato correttamente in %1</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="725"/> <location filename="../main_window.cpp" line="725"/>
<source>File doesn't appear to be a valid PKG file</source> <source>File doesn't appear to be a valid PKG file</source>
<translation>File tidak tampak sebagai file PKG yang valid</translation> <translation>Il file sembra non essere un file PKG valido</translation>
</message> </message>
</context> </context>
<context> <context>
@ -641,87 +651,87 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="44"/> <location filename="../cheats_patches.cpp" line="44"/>
<source>Cheats / Patches</source> <source>Cheats / Patches</source>
<translation>Cheat / Patch</translation> <translation>Trucchi / Patch</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="50"/> <location filename="../cheats_patches.cpp" line="50"/>
<source>defaultTextEdit_MSG</source> <source>defaultTextEdit_MSG</source>
<translation>I cheats/patches sono sperimentali.\nUtilizzali con cautela.\n\nScarica i cheats singolarmente selezionando il repository e cliccando sul pulsante di download.\nNella scheda Patches, puoi scaricare tutti i patch in una volta sola, scegliere quali vuoi utilizzare e salvare la tua selezione.\n\nPoiché non sviluppiamo i Cheats/Patches,\nper favore segnala i problemi all'autore del cheat.\n\nHai creato un nuovo cheat? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats</translation> <translation>I trucchi e le patch sono sperimentali.\nUtilizzali con cautela.\n\nScarica i trucchi singolarmente selezionando l'archivio e cliccando sul pulsante di download.\nNella scheda Patch, puoi scaricare tutte le patch in una volta sola, scegliere quali vuoi utilizzare e salvare la tua selezione.\n\nPoiché non sviluppiamo i trucchi e le patch,\nper favore segnala i problemi all'autore dei trucchi.\n\nHai creato un nuovo trucco? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="69"/> <location filename="../cheats_patches.cpp" line="69"/>
<source>No Image Available</source> <source>No Image Available</source>
<translation>Tidak Ada Gambar</translation> <translation>Nessuna immagine disponibile</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="79"/> <location filename="../cheats_patches.cpp" line="79"/>
<source>Serial: </source> <source>Serial: </source>
<translation>Serial: </translation> <translation>Seriale: </translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="83"/> <location filename="../cheats_patches.cpp" line="83"/>
<source>Version: </source> <source>Version: </source>
<translation>Versi: </translation> <translation>Versione: </translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="87"/> <location filename="../cheats_patches.cpp" line="87"/>
<source>Size: </source> <source>Size: </source>
<translation>Ukuran: </translation> <translation>Dimensione: </translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="126"/> <location filename="../cheats_patches.cpp" line="126"/>
<source>Select Cheat File:</source> <source>Select Cheat File:</source>
<translation>Pilih File Cheat:</translation> <translation>Seleziona File Trucchi:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="133"/> <location filename="../cheats_patches.cpp" line="133"/>
<source>Repository:</source> <source>Repository:</source>
<translation>Repositori:</translation> <translation>Archivio:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="149"/> <location filename="../cheats_patches.cpp" line="149"/>
<source>Download Cheats</source> <source>Download Cheats</source>
<translation>Unduh Cheat</translation> <translation>Scarica trucchi</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="155"/> <location filename="../cheats_patches.cpp" line="155"/>
<source>Delete File</source> <source>Delete File</source>
<translation>Hapus File</translation> <translation>Cancella File</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="169"/> <location filename="../cheats_patches.cpp" line="169"/>
<source>No files selected.</source> <source>No files selected.</source>
<translation>Tidak ada file yang dipilih.</translation> <translation>Nessun file selezionato.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="170"/> <location filename="../cheats_patches.cpp" line="170"/>
<source>You can delete the cheats you don't want after downloading them.</source> <source>You can delete the cheats you don't want after downloading them.</source>
<translation>Anda dapat menghapus cheat yang tidak diinginkan setelah mengunduhnya.</translation> <translation>Puoi cancellare i trucchi che non vuoi utilizzare dopo averli scaricati.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="178"/> <location filename="../cheats_patches.cpp" line="178"/>
<source>Do you want to delete the selected file?\n%1</source> <source>Do you want to delete the selected file?\n%1</source>
<translation>Apakah Anda ingin menghapus file yang dipilih?\n%1</translation> <translation>Vuoi cancellare il file selezionato?\n%1</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="213"/> <location filename="../cheats_patches.cpp" line="213"/>
<source>Select Patch File:</source> <source>Select Patch File:</source>
<translation>Pilih File Patch:</translation> <translation>Seleziona File Patch:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="241"/> <location filename="../cheats_patches.cpp" line="241"/>
<source>Download Patches</source> <source>Download Patches</source>
<translation>Unduh Patch</translation> <translation>Scarica Patch</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="248"/> <location filename="../cheats_patches.cpp" line="248"/>
<source>Save</source> <source>Save</source>
<translation>Simpan</translation> <translation>Salva</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="256"/> <location filename="../cheats_patches.cpp" line="256"/>
<source>Cheats</source> <source>Cheats</source>
<translation>Cheat</translation> <translation>Trucchi</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="257"/> <location filename="../cheats_patches.cpp" line="257"/>
@ -731,162 +741,162 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="278"/> <location filename="../cheats_patches.cpp" line="278"/>
<source>Error</source> <source>Error</source>
<translation>Kesalahan</translation> <translation>Errore</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="278"/> <location filename="../cheats_patches.cpp" line="278"/>
<source>No patch selected.</source> <source>No patch selected.</source>
<translation>Tidak ada patch yang dipilih.</translation> <translation>Nessuna patch selezionata.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="292"/> <location filename="../cheats_patches.cpp" line="292"/>
<source>Unable to open files.json for reading.</source> <source>Unable to open files.json for reading.</source>
<translation>Gagal membuka files.json untuk dibaca.</translation> <translation>Impossibile aprire il file .json per la lettura.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="316"/> <location filename="../cheats_patches.cpp" line="316"/>
<source>No patch file found for the current serial.</source> <source>No patch file found for the current serial.</source>
<translation>Tidak ada file patch ditemukan untuk serial saat ini.</translation> <translation>Nessun file patch trovato per il seriale selezionato.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="323"/> <location filename="../cheats_patches.cpp" line="323"/>
<source>Unable to open the file for reading.</source> <source>Unable to open the file for reading.</source>
<translation>Gagal membuka file untuk dibaca.</translation> <translation>Impossibile aprire il file per la lettura.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="422"/> <location filename="../cheats_patches.cpp" line="422"/>
<source>Unable to open the file for writing.</source> <source>Unable to open the file for writing.</source>
<translation>Gagal membuka file untuk ditulis.</translation> <translation>Impossibile aprire il file per la scrittura.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="432"/> <location filename="../cheats_patches.cpp" line="432"/>
<source>Failed to parse XML: </source> <source>Failed to parse XML: </source>
<translation>Gagal mengurai XML: </translation> <translation>Analisi XML fallita: </translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="434"/> <location filename="../cheats_patches.cpp" line="434"/>
<source>Success</source> <source>Success</source>
<translation>Berhasil</translation> <translation>Successo</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="434"/> <location filename="../cheats_patches.cpp" line="434"/>
<source>Options saved successfully.</source> <source>Options saved successfully.</source>
<translation>Opsi berhasil disimpan.</translation> <translation>Opzioni salvate con successo.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="470"/> <location filename="../cheats_patches.cpp" line="470"/>
<source>Invalid Source</source> <source>Invalid Source</source>
<translation>Sumber Tidak Valid</translation> <translation>Fonte non valida</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="471"/> <location filename="../cheats_patches.cpp" line="471"/>
<source>The selected source is invalid.</source> <source>The selected source is invalid.</source>
<translation>Sumber yang dipilih tidak valid.</translation> <translation>La fonte selezionata non è valida.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="519"/> <location filename="../cheats_patches.cpp" line="519"/>
<source>File Exists</source> <source>File Exists</source>
<translation>File Ada</translation> <translation>Il file è presente</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="520"/> <location filename="../cheats_patches.cpp" line="520"/>
<source>File already exists. Do you want to replace it?</source> <source>File already exists. Do you want to replace it?</source>
<translation>File sudah ada. Apakah Anda ingin menggantinya?</translation> <translation>Il file è già presente. Vuoi sostituirlo?</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="539"/> <location filename="../cheats_patches.cpp" line="539"/>
<source>Failed to save file:</source> <source>Failed to save file:</source>
<translation>Gagal menyimpan file:</translation> <translation>Salvataggio file fallito:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="545"/> <location filename="../cheats_patches.cpp" line="545"/>
<source>Failed to download file:</source> <source>Failed to download file:</source>
<translation>Gagal mengunduh file:</translation> <translation>Scaricamento file fallito:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="556"/> <location filename="../cheats_patches.cpp" line="556"/>
<source>Cheats Not Found</source> <source>Cheats Not Found</source>
<translation>Cheat Tidak Ditemukan</translation> <translation>Trucchi non trovati</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="556"/> <location filename="../cheats_patches.cpp" line="556"/>
<source>CheatsNotFound_MSG</source> <source>CheatsNotFound_MSG</source>
<translation>Cheat tidak ditemukan untuk game ini dalam versi repositori yang dipilih, coba repositori lain atau versi game yang berbeda.</translation> <translation>Non sono stati trovati trucchi per questa versione del gioco nell'archivio selezionato, prova un altro archivio o una versione diversa del gioco.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="593"/> <location filename="../cheats_patches.cpp" line="593"/>
<source>Cheats Downloaded Successfully</source> <source>Cheats Downloaded Successfully</source>
<translation>Cheat Berhasil Diunduh</translation> <translation>Trucchi scaricati con successo!</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="594"/> <location filename="../cheats_patches.cpp" line="594"/>
<source>CheatsDownloadedSuccessfully_MSG</source> <source>CheatsDownloadedSuccessfully_MSG</source>
<translation>Anda telah berhasil mengunduh cheat untuk versi game ini dari repositori yang dipilih. Anda dapat mencoba mengunduh dari repositori lain, jika tersedia, Anda juga dapat menggunakannya dengan memilih file dari daftar.</translation> <translation>Hai scaricato con successo i trucchi per questa versione del gioco dall'archivio selezionato. Puoi provare a scaricare da un altro archivio, se disponibile, puoi anche utilizzarlo selezionando il file dall'elenco.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="747"/> <location filename="../cheats_patches.cpp" line="747"/>
<source>Failed to save:</source> <source>Failed to save:</source>
<translation>Gagal menyimpan:</translation> <translation>Salvataggio fallito:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="754"/> <location filename="../cheats_patches.cpp" line="754"/>
<source>Failed to download:</source> <source>Failed to download:</source>
<translation>Gagal mengunduh:</translation> <translation>Impossibile scaricare:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="762"/> <location filename="../cheats_patches.cpp" line="762"/>
<source>Download Complete</source> <source>Download Complete</source>
<translation>Unduhan Selesai</translation> <translation>Scaricamento completo</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="763"/> <location filename="../cheats_patches.cpp" line="763"/>
<source>DownloadComplete_MSG</source> <source>DownloadComplete_MSG</source>
<translation>Patch Berhasil Diunduh! Semua patch yang tersedia untuk semua game telah diunduh, tidak perlu mengunduhnya secara individu untuk setiap game seperti yang terjadi pada Cheat.</translation> <translation>Patch scaricata con successo! Vengono scaricate tutte le patch disponibili per tutti i giochi, non è necessario scaricarle singolarmente per ogni gioco come nel caso dei trucchi.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="773"/> <location filename="../cheats_patches.cpp" line="773"/>
<source>Failed to parse JSON data from HTML.</source> <source>Failed to parse JSON data from HTML.</source>
<translation>Gagal mengurai data JSON dari HTML.</translation> <translation>Impossibile analizzare i dati JSON dall'HTML.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="778"/> <location filename="../cheats_patches.cpp" line="778"/>
<source>Failed to retrieve HTML page.</source> <source>Failed to retrieve HTML page.</source>
<translation>Gagal mengambil halaman HTML.</translation> <translation>Impossibile recuperare la pagina HTML.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="801"/> <location filename="../cheats_patches.cpp" line="801"/>
<source>Failed to open file:</source> <source>Failed to open file:</source>
<translation>Gagal membuka file:</translation> <translation>Impossibile aprire file:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="819"/> <location filename="../cheats_patches.cpp" line="819"/>
<source>XML ERROR:</source> <source>XML ERROR:</source>
<translation>KESALAHAN XML:</translation> <translation>ERRORE XML:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="826"/> <location filename="../cheats_patches.cpp" line="826"/>
<source>Failed to open files.json for writing</source> <source>Failed to open files.json for writing</source>
<translation>Gagal membuka files.json untuk menulis</translation> <translation>Impossibile aprire i file .json per la scrittura</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="925"/> <location filename="../cheats_patches.cpp" line="925"/>
<source>Author: </source> <source>Author: </source>
<translation>Penulis: </translation> <translation>Autore: </translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="997"/> <location filename="../cheats_patches.cpp" line="997"/>
<source>Directory does not exist:</source> <source>Directory does not exist:</source>
<translation>Direktori tidak ada:</translation> <translation>La cartella non esiste:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="1006"/> <location filename="../cheats_patches.cpp" line="1006"/>
<source>Failed to open files.json for reading.</source> <source>Failed to open files.json for reading.</source>
<translation>Gagal membuka files.json untuk dibaca.</translation> <translation>Impossibile aprire i file .json per la lettura.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="1006"/> <location filename="../cheats_patches.cpp" line="1006"/>
<source>Name:</source> <source>Name:</source>
<translation>Nama:</translation> <translation>Nome:</translation>
</message> </message>
</context> </context>
</TS> </TS>

View File

@ -566,44 +566,54 @@
<translation>PKG抽出</translation> <translation>PKG抽出</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>\nPKGとゲームバージョンが一致しています: %1\n上書きしますか</translation> <translation></translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation></translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>\nPKGバージョン %1 </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>: %2\n上書きしますか</translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>\nゲームがインストールされています: %1\nインストールしますか</translation> <translation>PKGとゲームのバージョンが一致しています: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>: %2?</translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>\n%1\n上書きしますか</translation> <translation>PKGバージョン %1 : </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>DLCのインストール</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>DLCをインストールしてもよろしいですか: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLCはすでにインストールされています:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG Extraction</translation> <translation>PKG Extraction</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch detected!\nPKG and Game versions match!: %1\nWould you like </translation> <translation>Patch detected!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>to overwrite?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Patch detected!\nPKG Version %1 is older </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>than installed version!: %2\nWould you like </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>to overwrite?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Patch detected!\nGame is installed: %1\nWould you like </translation> <translation>PKG and Game versions match: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>to install Patch: %2?</translation> <translation>Would you like to overwrite?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Game already installed\n%1\nWould you like to overwrite?</translation> <translation>PKG Version %1 is older than installed version: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Game is installed: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Would you like to install Patch: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>DLC Installation</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Would you like to install DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC already installed:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Game already installed</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG ištraukimas</translation> <translation>PKG ištraukimas</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Pataisa aptikta!\nPKG ir žaidimo versijos atitinka!: %1\nAr norėtumėte </translation> <translation>Rasta atnaujinimą!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>perrašyti?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Pataisa aptikta!\nPKG versija %1 yra senesnė </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>nei įdiegta versija!: %2\nAr norėtumėte </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>perrašyti?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Pataisa aptikta!\nŽaidimas įdiegtas: %1\nAr norėtumėte </translation> <translation>PKG ir žaidimo versijos sutampa: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>įdiegti pataisą: %2?</translation> <translation>Ar norite perrašyti?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Žaidimas jau įdiegtas\n%1\nAr norėtumėte perrašyti?</translation> <translation>PKG versija %1 yra senesnė nei įdiegta versija: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Žaidimas įdiegtas: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Ar norite įdiegti atnaujinimą: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>DLC diegimas</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Ar norite įdiegti DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC jau įdiegtas:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Žaidimas jau įdiegtas</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG-ekstraksjon</translation> <translation>PKG-ekstraksjon</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Oppdatering oppdaget!\nPKG og spillversjoner stemmer!: %1\nØnsker du å </translation> <translation>Oppdatering oppdaget!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>overskrive?</translation> <translation>PKG- og spillversjoner stemmer overens: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Oppdatering oppdaget!\nPKG-versjon %1 er eldre </translation> <translation>Ønsker du å overskrive?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>enn installert versjon!: %2\nØnsker du å </translation> <translation>PKG-versjon %1 er eldre enn installert versjon: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>overskrive?</translation> <translation>Spillet er installert: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Oppdatering oppdaget!\nSpillet er installert: %1\nØnsker du å </translation> <translation>Ønsker du å installere oppdateringen: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>installere oppdateringen: %2?</translation> <translation>DLC-installasjon</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Spill allerede installert\n%1\nØnsker du å overskrive?</translation> <translation>Ønsker du å installere DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC allerede installert:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Spillet er allerede installert</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG-extractie</translation> <translation>PKG-extractie</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch gedetecteerd!\nPKG en spelversies komen overeen!: %1\nWil je </translation> <translation>Patch gedetecteerd!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>overschrijven?</translation> <translation>PKG- en gameversies komen overeen: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Patch gedetecteerd!\nPKG-versie %1 is ouder </translation> <translation>Wilt u overschrijven?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>dan de geïnstalleerde versie!: %2\nWil je </translation> <translation>PKG-versie %1 is ouder dan de geïnstalleerde versie: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>overschrijven?</translation> <translation>Game is geïnstalleerd: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Patch gedetecteerd!\nSpel is geïnstalleerd: %1\nWil je </translation> <translation>Wilt u de patch installeren: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>de patch installeren: %2?</translation> <translation>DLC-installatie</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Spel al geïnstalleerd\n%1\nWil je het overschrijven?</translation> <translation>Wilt u DLC installeren: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC al geïnstalleerd:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Game al geïnstalleerd</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>Ekstrakcja PKG</translation> <translation>Ekstrakcja PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Wykryto poprawkę!\nWersje PKG i gry pasują do siebie!: %1\nCzy chcesz </translation> <translation>Wykryto łatkę!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>nadpisać?</translation> <translation>Wersje PKG i gry zgodne: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Wykryto poprawkę!\nWersja PKG %1 jest starsza </translation> <translation>Czy chcesz nadpisać?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>niż zainstalowana wersja!: %2\nCzy chcesz </translation> <translation>Wersja PKG %1 jest starsza niż zainstalowana wersja: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>nadpisać?</translation> <translation>Gra jest zainstalowana: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Wykryto poprawkę!\nGra jest zainstalowana: %1\nCzy chcesz </translation> <translation>Czy chcesz zainstalować łatkę: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>zainstalować poprawkę: %2?</translation> <translation>Instalacja DLC</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Gra już zainstalowana\n%1\nCzy chcesz nadpisać?</translation> <translation>Czy chcesz zainstalować DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC już zainstalowane:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Gra już zainstalowana</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -37,7 +37,7 @@
<message> <message>
<location filename="../game_info.cpp" line="26"/> <location filename="../game_info.cpp" line="26"/>
<source>Loading game list, please wait :3</source> <source>Loading game list, please wait :3</source>
<translation>Carregando lista de jogos, por favor aguarde :3</translation> <translation>Carregando a lista de jogos, por favor aguarde :3</translation>
</message> </message>
<message> <message>
<location filename="../game_info.cpp" line="26"/> <location filename="../game_info.cpp" line="26"/>
@ -256,7 +256,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="343"/> <location filename="../main_window_ui.h" line="343"/>
<source>Download Cheats/Patches</source> <source>Download Cheats/Patches</source>
<translation>Baixar Trapaças / Patches</translation> <translation>Baixar Cheats/Patches</translation>
</message> </message>
<message> <message>
<location filename="../main_window_ui.h" line="345"/> <location filename="../main_window_ui.h" line="345"/>
@ -291,7 +291,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="354"/> <location filename="../main_window_ui.h" line="354"/>
<source>Game List Mode</source> <source>Game List Mode</source>
<translation>Modo de Lista de Jogos</translation> <translation>Modo da Lista de Jogos</translation>
</message> </message>
<message> <message>
<location filename="../main_window_ui.h" line="355"/> <location filename="../main_window_ui.h" line="355"/>
@ -425,7 +425,7 @@
<message> <message>
<location filename="../settings_dialog.ui" line="235"/> <location filename="../settings_dialog.ui" line="235"/>
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtro</translation> <translation>Filtro do Registro</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.ui" line="272"/> <location filename="../settings_dialog.ui" line="272"/>
@ -508,12 +508,12 @@
<message> <message>
<location filename="../main_window.cpp" line="326"/> <location filename="../main_window.cpp" line="326"/>
<source>Download Cheats For All Installed Games</source> <source>Download Cheats For All Installed Games</source>
<translation>Baixar Trapaças para todos os jogos instalados</translation> <translation>Baixar Cheats para Todos os Jogos Instalados</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="328"/> <location filename="../main_window.cpp" line="328"/>
<source>Download Patches For All Games</source> <source>Download Patches For All Games</source>
<translation>Baixar Patches para todos os jogos</translation> <translation>Baixar Patches para Todos os Jogos</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="363"/> <location filename="../main_window.cpp" line="363"/>
@ -523,7 +523,7 @@
<message> <message>
<location filename="../main_window.cpp" line="364"/> <location filename="../main_window.cpp" line="364"/>
<source>You have downloaded cheats for all the games you have installed.</source> <source>You have downloaded cheats for all the games you have installed.</source>
<translation>Você baixou trapaças para todos os jogos que instalou.</translation> <translation>Você baixou cheats para todos os jogos que instalou.</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="391"/> <location filename="../main_window.cpp" line="391"/>
@ -566,54 +566,64 @@
<translation>Extração de PKG</translation> <translation>Extração de PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch detectado!\nVersões PKG e do Jogo correspondem!: %1\nGostaria de </translation> <translation>Atualização detectada!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>substituir?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Patch detectado!\nVersão PKG %1 é mais antiga </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>do que a versão instalada!: %2\nGostaria de </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>substituir?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Patch detectado!\nJogo está instalado: %1\nGostaria de </translation> <translation>As versões do PKG e do Jogo são igual: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>instalar o Patch: %2?</translation> <translation>Gostaria de substituir?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Jogo instalado\n%1\nGostaria de substituir?</translation> <translation>Versão do PKG %1 é mais antiga do que a versão instalada: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Jogo instalado: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Você gostaria de instalar a atualização: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>Instalação de DLC</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Você gostaria de instalar o DLC: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC instalada:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>O jogo está instalado:</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>
<source>PKG is a patch, please install the game first!</source> <source>PKG is a patch, please install the game first!</source>
<translation>PKG é um patch, por favor, instale o jogo primeiro!</translation> <translation>O PKG é um patch, por favor, instale o jogo primeiro!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="681"/> <location filename="../main_window.cpp" line="681"/>
<source>PKG ERROR</source> <source>PKG ERROR</source>
<translation>ERRO PKG</translation> <translation>ERRO de PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="693"/> <location filename="../main_window.cpp" line="693"/>
@ -641,12 +651,12 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="44"/> <location filename="../cheats_patches.cpp" line="44"/>
<source>Cheats / Patches</source> <source>Cheats / Patches</source>
<translation>Trapaças / Patches</translation> <translation>Cheats / Patches</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="50"/> <location filename="../cheats_patches.cpp" line="50"/>
<source>defaultTextEdit_MSG</source> <source>defaultTextEdit_MSG</source>
<translation>Trapaças/Patches são experimentais.\nUse com cautela.\n\nBaixe as trapaças individualmente selecionando o repositório e clicando no botão de download.\nNa aba Patches, você pode baixar todos os Patches de uma vez, escolher qual deseja usar e salvar a opção.\n\nComo não desenvolvemos as Trapaças/Patches,\npor favor, reporte problemas relacionados ao autor da trapaça.\n\nCriou uma nova trapaça? Visite:\nhttps://github.com/shadps4-emu/ps4_cheats</translation> <translation>Cheats/Patches são experimentais.\nUse com cautela.\n\nBaixe os cheats individualmente selecionando o repositório e clicando no botão de download.\nNa aba Patches, você pode baixar todos os Patches de uma vez, escolha qual deseja usar e salve a opção.\n\nComo não desenvolvemos os Cheats/Patches,\npor favor, reporte problemas relacionados ao autor do cheat.\n\nCriou um novo cheat? Visite:\nhttps://github.com/shadps4-emu/ps4_cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="69"/> <location filename="../cheats_patches.cpp" line="69"/>
@ -656,7 +666,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="79"/> <location filename="../cheats_patches.cpp" line="79"/>
<source>Serial: </source> <source>Serial: </source>
<translation>Série: </translation> <translation>Serial: </translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="83"/> <location filename="../cheats_patches.cpp" line="83"/>
@ -671,7 +681,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="126"/> <location filename="../cheats_patches.cpp" line="126"/>
<source>Select Cheat File:</source> <source>Select Cheat File:</source>
<translation>Selecione o Arquivo de Trapaça:</translation> <translation>Selecione o Arquivo de Cheat:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="133"/> <location filename="../cheats_patches.cpp" line="133"/>
@ -681,7 +691,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="149"/> <location filename="../cheats_patches.cpp" line="149"/>
<source>Download Cheats</source> <source>Download Cheats</source>
<translation>Baixar Trapaças</translation> <translation>Baixar Cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="155"/> <location filename="../cheats_patches.cpp" line="155"/>
@ -696,7 +706,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="170"/> <location filename="../cheats_patches.cpp" line="170"/>
<source>You can delete the cheats you don't want after downloading them.</source> <source>You can delete the cheats you don't want after downloading them.</source>
<translation>Você pode excluir as trapaças que não deseja após baixá-las.</translation> <translation>Você pode excluir os cheats que não deseja após baixá-las.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="178"/> <location filename="../cheats_patches.cpp" line="178"/>
@ -721,7 +731,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="256"/> <location filename="../cheats_patches.cpp" line="256"/>
<source>Cheats</source> <source>Cheats</source>
<translation>Trapaças</translation> <translation>Cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="257"/> <location filename="../cheats_patches.cpp" line="257"/>
@ -746,7 +756,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="316"/> <location filename="../cheats_patches.cpp" line="316"/>
<source>No patch file found for the current serial.</source> <source>No patch file found for the current serial.</source>
<translation>Nenhum arquivo de patch encontrado para a série atual.</translation> <translation>Nenhum arquivo de patch encontrado para o serial atual.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="323"/> <location filename="../cheats_patches.cpp" line="323"/>
@ -806,22 +816,22 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="556"/> <location filename="../cheats_patches.cpp" line="556"/>
<source>Cheats Not Found</source> <source>Cheats Not Found</source>
<translation>Trapaças Não Encontradas</translation> <translation>Cheats Não Encontrados</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="556"/> <location filename="../cheats_patches.cpp" line="556"/>
<source>CheatsNotFound_MSG</source> <source>CheatsNotFound_MSG</source>
<translation>Nenhuma trapaça encontrada para este jogo nesta versão do repositório selecionado, tente outro repositório ou uma versão diferente do jogo.</translation> <translation>Nenhum cheat encontrado para este jogo nesta versão do repositório selecionado, tente outro repositório ou uma versão diferente do jogo.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="593"/> <location filename="../cheats_patches.cpp" line="593"/>
<source>Cheats Downloaded Successfully</source> <source>Cheats Downloaded Successfully</source>
<translation>Trapaças Baixadas com Sucesso</translation> <translation>Cheats Baixados com Sucesso</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="594"/> <location filename="../cheats_patches.cpp" line="594"/>
<source>CheatsDownloadedSuccessfully_MSG</source> <source>CheatsDownloadedSuccessfully_MSG</source>
<translation>Você baixou as trapaças com sucesso. Para esta versão do jogo a partir do repositório selecionado.Você pode tentar baixar de outro repositório, se estiver disponível, também será possível usá-lo selecionando o arquivo da lista.</translation> <translation>Você baixou os cheats com sucesso. Para esta versão do jogo a partir do repositório selecionado. Você pode tentar baixar de outro repositório, se estiver disponível, também será possível usá-lo selecionando o arquivo da lista.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="747"/> <location filename="../cheats_patches.cpp" line="747"/>
@ -841,7 +851,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="763"/> <location filename="../cheats_patches.cpp" line="763"/>
<source>DownloadComplete_MSG</source> <source>DownloadComplete_MSG</source>
<translation>Patches Baixados com Sucesso! Todos os patches disponíveis para todos os jogos foram baixados, não é necessário baixá-los individualmente para cada jogo como acontece com as Trapaças.</translation> <translation>Patches Baixados com Sucesso! Todos os patches disponíveis para todos os jogos foram baixados, não é necessário baixá-los individualmente para cada jogo como acontece com os Cheats.</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="773"/> <location filename="../cheats_patches.cpp" line="773"/>
@ -861,7 +871,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="819"/> <location filename="../cheats_patches.cpp" line="819"/>
<source>XML ERROR:</source> <source>XML ERROR:</source>
<translation>ERRO XML:</translation> <translation>ERRO de XML:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="826"/> <location filename="../cheats_patches.cpp" line="826"/>
@ -876,7 +886,7 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="997"/> <location filename="../cheats_patches.cpp" line="997"/>
<source>Directory does not exist:</source> <source>Directory does not exist:</source>
<translation>Diretório não existe:</translation> <translation>O Diretório não existe:</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="1006"/> <location filename="../cheats_patches.cpp" line="1006"/>

View File

@ -566,44 +566,54 @@
<translation>Extracție PKG</translation> <translation>Extracție PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Patch detectat!\nVersiunile PKG și Joc se potrivesc!: %1\nAi dori </translation> <translation>Patch detectat!</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation> suprascrii?</translation> <translation>Versiunile PKG și ale jocului sunt compatibile: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Patch detectat!\nVersiunea PKG %1 este mai veche </translation> <translation>Doriți suprascrieți?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>decât versiunea instalată!: %2\nAi dori </translation> <translation>Versiunea PKG %1 este mai veche decât versiunea instalată: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation> suprascrii?</translation> <translation>Jocul este instalat: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Patch detectat!\nJocul este instalat: %1\nAi dori </translation> <translation>Doriți instalați patch-ul: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>instalezi Patch-ul: %2?</translation> <translation>Instalare DLC</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Jocul este deja instalat\n%1\nAi dori suprascrii?</translation> <translation>Doriți instalați DLC-ul: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC deja instalat:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Jocul deja instalat</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -93,7 +93,7 @@
<message> <message>
<location filename="../gui_context_menus.h" line="48"/> <location filename="../gui_context_menus.h" line="48"/>
<source>Cheats / Patches</source> <source>Cheats / Patches</source>
<translation>Читы / Патчи</translation> <translation>Читы и патчи</translation>
</message> </message>
<message> <message>
<location filename="../gui_context_menus.h" line="49"/> <location filename="../gui_context_menus.h" line="49"/>
@ -256,7 +256,7 @@
<message> <message>
<location filename="../main_window_ui.h" line="343"/> <location filename="../main_window_ui.h" line="343"/>
<source>Download Cheats/Patches</source> <source>Download Cheats/Patches</source>
<translation>Скачать Читы / Патчи</translation> <translation>Скачать читы или патчи</translation>
</message> </message>
<message> <message>
<location filename="../main_window_ui.h" line="345"/> <location filename="../main_window_ui.h" line="345"/>
@ -566,45 +566,55 @@
<translation>Извлечение PKG</translation> <translation>Извлечение PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Обнаружен патч!\nВерсии PKG и игры совпадают!: %1\nХотите </translation> <translation>Обнаружен патч!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>перезаписать?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Обнаружен патч!\nВерсия PKG %1 устарела </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>по сравнению с установленной версией!: %2\nХотите </translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>перезаписать?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Обнаружен патч!\гра установлена: %1\nХотите </translation> <translation>Версии PKG и игры совпадают: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>установить патч: %2?</translation> <translation>Хотите перезаписать?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Игра уже установлена\n%1\nХотите перезаписать?</translation> <translation>Версия PKG %1 старее установленной версии: </translation>
</message> </message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Игра установлена: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Хотите установить патч: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>Установка DLC</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>Вы хотите установить DLC: %1??</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC уже установлен:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Игра уже установлена</translation>
</message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>
<source>PKG is a patch, please install the game first!</source> <source>PKG is a patch, please install the game first!</source>
@ -628,7 +638,7 @@
<message> <message>
<location filename="../main_window.cpp" line="704"/> <location filename="../main_window.cpp" line="704"/>
<source>Game successfully installed at %1</source> <source>Game successfully installed at %1</source>
<translation>Игра успешно установлена по адресу %1</translation> <translation>Игра успешно установлена в %1</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="725"/> <location filename="../main_window.cpp" line="725"/>
@ -641,13 +651,13 @@
<message> <message>
<location filename="../cheats_patches.cpp" line="44"/> <location filename="../cheats_patches.cpp" line="44"/>
<source>Cheats / Patches</source> <source>Cheats / Patches</source>
<translation>Читы / Патчи</translation> <translation>Читы и патчи</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="50"/> <location filename="../cheats_patches.cpp" line="50"/>
<source>defaultTextEdit_MSG</source> <source>defaultTextEdit_MSG</source>
<translation>Cheats/Patches sunt experimentale.\nUtilizați cu prudență.\n\nDescărcați cheats individual prin selectarea depozitului și făcând clic pe butonul de descărcare.\nÎn fila Patches, puteți descărca toate patch-urile deodată, alege pe cele pe care doriți le utilizați și salvați selecția.\n\nDeoarece nu dezvoltăm Cheats/Patches,\nte rugăm raportezi problemele autorului cheat-ului.\n\nAi creat un nou cheat? Vizitează:\nhttps://github.com/shadps4-emu/ps4_cheats</translation> <translation>Читы и патчи экспериментальны.\спользуйте с осторожностью.\n\nСкачивайте читы, выбрав репозиторий и нажав на кнопку загрузки.\nВо вкладке "Патчи" вы можете скачать все патчи сразу, выбирать какие вы хотите использовать, и сохранять выбор.\n\оскольку мы не разрабатываем читы/патчи,\nпожалуйста сообщайте о проблемах автору чита/патча.\n\nСоздали новый чит? Посетите:\nhttps://github.com/shadps4-emu/ps4_cheats</translation>
</message> </message>
<message> <message>
<location filename="../cheats_patches.cpp" line="69"/> <location filename="../cheats_patches.cpp" line="69"/>
<source>No Image Available</source> <source>No Image Available</source>

View File

@ -566,44 +566,54 @@
<translation>PKG Çıkartma</translation> <translation>PKG Çıkartma</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Yama tespit edildi!\nPKG ve Oyun sürümleri uyuyor!: %1\nÜzerine yazmak ister misiniz?</translation> <translation>Yamanın tespit edildi!</translation>
</message>
<message>
<location filename="../main_window.cpp" line="634"/>
<source>to overwrite?</source>
<translation>üzerine yazmak?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="639"/>
<source>Patch detected!\nPKG Version %1 is older </source>
<translation>Yama tespit edildi!\nPKG Sürümü %1 daha eski </translation>
</message>
<message>
<location filename="../main_window.cpp" line="640"/>
<source>than installed version!: %2\nWould you like </source>
<translation>yüklü sürümden!: %2\nÜzerine yazmak ister misiniz?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="641"/>
<source>to overwrite?</source>
<translation>üzerine yazmak?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>PKG and Game versions match: </source>
<translation>Yama tespit edildi!\nOyun yüklü: %1\nÜzerine yazmak ister misiniz?</translation> <translation>PKG ve oyun sürümleri uyumlu: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="647"/>
<source>to install Patch: %2?</source> <source>Would you like to overwrite?</source>
<translation>Yamayı kurmak ister misiniz: %2?</translation> <translation>Üzerine yazmak ister misiniz?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="639"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>PKG Version %1 is older than installed version: </source>
<translation>Oyun zaten yüklü\n%1\nÜzerine yazmak ister misiniz?</translation> <translation>PKG Sürümü %1, kurulu sürümden daha eski: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Game is installed: </source>
<translation>Oyun yüklendi: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="660"/>
<source>Would you like to install Patch: </source>
<translation>Yamanın yüklenmesini ister misiniz: </translation>
</message>
<message>
<location filename="../main_window.cpp" line="673"/>
<source>DLC Installation</source>
<translation>DLC Yükleme</translation>
</message>
<message>
<location filename="../main_window.cpp" line="674"/>
<source>Would you like to install DLC: %1?</source>
<translation>DLC'yi yüklemek ister misiniz: %1?</translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC zaten yüklü:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Oyun zaten yüklü</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,45 +566,55 @@
<translation>Giải nén PKG</translation> <translation>Giải nén PKG</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>Đã phát hiện bản !\nPhiên bản PKG trò chơi khớp!: %1\nBạn muốn </translation> <translation>Đã phát hiện bản !</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation>ghi đè không?</translation> <translation>Các phiên bản PKG trò chơi khớp nhau: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>Đã phát hiện bản !\nPhiên bản PKG %1 hơn </translation> <translation>Bạn muốn ghi đè không?</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>so với phiên bản đã cài đt!: %2\nBạn muốn </translation> <translation>Phiên bản PKG %1 hơn phiên bản đã cài đt: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation>ghi đè không?</translation> <translation>Trò chơi đã đưc cài đt: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>Đã phát hiện bản !\nTrò chơi đã đưc cài đt: %1\nBạn muốn </translation> <translation>Bạn muốn cài đt bản : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>cài đt bản : %2?</translation> <translation>Cài đt DLC</translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>Trò chơi đã đưc cài đt\n%1\nBạn muốn ghi đè không?</translation> <translation>Bạn muốn cài đt DLC: %1?</translation>
</message> </message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC đã đưc cài đt:</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation>Trò chơi đã đưc cài đt</translation>
</message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>
<source>PKG is a patch, please install the game first!</source> <source>PKG is a patch, please install the game first!</source>

View File

@ -566,44 +566,54 @@
<translation>PKG </translation> <translation>PKG </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>\nPKG %1\n您想要 </translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation></translation> <translation>PKG : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>\nPKG %1 </translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>%2\n您想要 </translation> <translation>PKG %1 : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation></translation> <translation>: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>\n游戏已安装%1\n您想要 </translation> <translation>: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>%2</translation> <translation>DLC </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>\n%1\n您想要覆盖吗</translation> <translation> DLC: %1 </translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC :</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -566,44 +566,54 @@
<translation>PKG </translation> <translation>PKG </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="633"/> <location filename="../main_window.cpp" line="646"/>
<source>Patch detected!\nPKG and Game versions match!: %1\nWould you like </source> <source>Patch detected!</source>
<translation>\nPKG : %1\n您是否希望 </translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="634"/> <location filename="../main_window.cpp" line="646"/>
<source>to overwrite?</source> <source>PKG and Game versions match: </source>
<translation></translation> <translation>PKG : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="639"/> <location filename="../main_window.cpp" line="647"/>
<source>Patch detected!\nPKG Version %1 is older </source> <source>Would you like to overwrite?</source>
<translation>\nPKG %1 </translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="640"/> <location filename="../main_window.cpp" line="639"/>
<source>than installed version!: %2\nWould you like </source> <source>PKG Version %1 is older than installed version: </source>
<translation>: %2\n您是否希望 </translation> <translation>PKG %1 : </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="641"/> <location filename="../main_window.cpp" line="660"/>
<source>to overwrite?</source> <source>Game is installed: </source>
<translation></translation> <translation>: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="646"/> <location filename="../main_window.cpp" line="660"/>
<source>Patch detected!\nGame is installed: %1\nWould you like </source> <source>Would you like to install Patch: </source>
<translation>\n遊戲已安裝: %1\n您是否希望 </translation> <translation>: </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="647"/> <location filename="../main_window.cpp" line="673"/>
<source>to install Patch: %2?</source> <source>DLC Installation</source>
<translation>: %2</translation> <translation>DLC </translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="659"/> <location filename="../main_window.cpp" line="674"/>
<source>Game already installed\n%1\nWould you like to overwrite?</source> <source>Would you like to install DLC: %1?</source>
<translation>\n%1\n您是否希望覆蓋</translation> <translation> DLC: %1 </translation>
</message>
<message>
<location filename="../main_window.cpp" line="688"/>
<source>DLC already installed:</source>
<translation>DLC :</translation>
</message>
<message>
<location filename="../main_window.cpp" line="701"/>
<source>Game already installed</source>
<translation></translation>
</message> </message>
<message> <message>
<location filename="../main_window.cpp" line="674"/> <location filename="../main_window.cpp" line="674"/>

View File

@ -99,7 +99,7 @@ Id TypeId(const EmitContext& ctx, IR::Type type) {
} }
} }
void Traverse(EmitContext& ctx, IR::Program& program) { void Traverse(EmitContext& ctx, const IR::Program& program) {
IR::Block* current_block{}; IR::Block* current_block{};
for (const IR::AbstractSyntaxNode& node : program.syntax_list) { for (const IR::AbstractSyntaxNode& node : program.syntax_list) {
switch (node.type) { switch (node.type) {
@ -162,7 +162,7 @@ void Traverse(EmitContext& ctx, IR::Program& program) {
} }
} }
Id DefineMain(EmitContext& ctx, IR::Program& program) { Id DefineMain(EmitContext& ctx, const IR::Program& program) {
const Id void_function{ctx.TypeFunction(ctx.void_id)}; const Id void_function{ctx.TypeFunction(ctx.void_id)};
const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)};
for (IR::Block* const block : program.blocks) { for (IR::Block* const block : program.blocks) {
@ -185,8 +185,28 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
ctx.AddCapability(spv::Capability::Int16); ctx.AddCapability(spv::Capability::Int16);
} }
ctx.AddCapability(spv::Capability::Int64); ctx.AddCapability(spv::Capability::Int64);
if (info.has_storage_images) { if (info.has_storage_images || info.has_image_buffers) {
ctx.AddCapability(spv::Capability::StorageImageExtendedFormats); ctx.AddCapability(spv::Capability::StorageImageExtendedFormats);
ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat);
ctx.AddCapability(spv::Capability::StorageImageWriteWithoutFormat);
}
if (info.has_texel_buffers) {
ctx.AddCapability(spv::Capability::SampledBuffer);
}
if (info.has_image_buffers) {
ctx.AddCapability(spv::Capability::ImageBuffer);
}
if (info.has_image_gather) {
ctx.AddCapability(spv::Capability::ImageGatherExtended);
}
if (info.has_image_query) {
ctx.AddCapability(spv::Capability::ImageQuery);
}
if (info.uses_lane_id) {
ctx.AddCapability(spv::Capability::GroupNonUniform);
}
if (info.uses_group_quad) {
ctx.AddCapability(spv::Capability::GroupNonUniformQuad);
} }
switch (program.info.stage) { switch (program.info.stage) {
case Stage::Compute: { case Stage::Compute: {
@ -206,19 +226,9 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
} else { } else {
ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft); ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft);
} }
ctx.AddCapability(spv::Capability::GroupNonUniform);
if (info.uses_group_quad) {
ctx.AddCapability(spv::Capability::GroupNonUniformQuad);
}
if (info.has_discard) { if (info.has_discard) {
ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT);
} }
if (info.has_image_gather) {
ctx.AddCapability(spv::Capability::ImageGatherExtended);
}
if (info.has_image_query) {
ctx.AddCapability(spv::Capability::ImageQuery);
}
if (info.stores.Get(IR::Attribute::Depth)) { if (info.stores.Get(IR::Attribute::Depth)) {
ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing);
} }
@ -229,7 +239,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
ctx.AddEntryPoint(execution_model, main, "main", interfaces); ctx.AddEntryPoint(execution_model, main, "main", interfaces);
} }
void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { void PatchPhiNodes(const IR::Program& program, EmitContext& ctx) {
auto inst{program.blocks.front()->begin()}; auto inst{program.blocks.front()->begin()};
size_t block_index{0}; size_t block_index{0};
ctx.PatchDeferredPhi([&](size_t phi_arg) { ctx.PatchDeferredPhi([&](size_t phi_arg) {
@ -248,8 +258,8 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) {
} }
} // Anonymous namespace } // Anonymous namespace
std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program, u32& binding) { std::vector<u32> EmitSPIRV(const Profile& profile, const IR::Program& program, u32& binding) {
EmitContext ctx{profile, program, binding}; EmitContext ctx{profile, program.info, binding};
const Id main{DefineMain(ctx, program)}; const Id main{DefineMain(ctx, program)};
DefineEntryPoint(program, ctx, main); DefineEntryPoint(program, ctx, main);
if (program.info.stage == Stage::Vertex) { if (program.info.stage == Stage::Vertex) {

View File

@ -9,7 +9,7 @@
namespace Shader::Backend::SPIRV { namespace Shader::Backend::SPIRV {
[[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program, [[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, const IR::Program& program,
u32& binding); u32& binding);
} // namespace Shader::Backend::SPIRV } // namespace Shader::Backend::SPIRV

View File

@ -262,171 +262,16 @@ Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) {
return EmitLoadBufferF32xN<4>(ctx, handle, address); return EmitLoadBufferF32xN<4>(ctx, handle, address);
} }
static bool IsSignedInteger(AmdGpu::NumberFormat format) {
switch (format) {
case AmdGpu::NumberFormat::Unorm:
case AmdGpu::NumberFormat::Uscaled:
case AmdGpu::NumberFormat::Uint:
return false;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::Sscaled:
case AmdGpu::NumberFormat::Sint:
case AmdGpu::NumberFormat::SnormNz:
return true;
case AmdGpu::NumberFormat::Float:
default:
UNREACHABLE();
}
}
static u32 UXBitsMax(u32 bit_width) {
return (1u << bit_width) - 1u;
}
static u32 SXBitsMax(u32 bit_width) {
return (1u << (bit_width - 1u)) - 1u;
}
static Id ConvertValue(EmitContext& ctx, Id value, AmdGpu::NumberFormat format, u32 bit_width) {
switch (format) {
case AmdGpu::NumberFormat::Unorm:
return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(UXBitsMax(bit_width))));
case AmdGpu::NumberFormat::Snorm:
return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(SXBitsMax(bit_width))));
case AmdGpu::NumberFormat::SnormNz:
// (x * 2 + 1) / (Format::SMAX * 2)
value = ctx.OpFMul(ctx.F32[1], value, ctx.ConstF32(2.f));
value = ctx.OpFAdd(ctx.F32[1], value, ctx.ConstF32(1.f));
return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(SXBitsMax(bit_width) * 2)));
case AmdGpu::NumberFormat::Uscaled:
case AmdGpu::NumberFormat::Sscaled:
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
case AmdGpu::NumberFormat::Float:
return value;
default:
UNREACHABLE_MSG("Unsupported number format for conversion: {}",
magic_enum::enum_name(format));
}
}
static Id ComponentOffset(EmitContext& ctx, Id address, u32 stride, u32 bit_offset) {
Id comp_offset = ctx.ConstU32(bit_offset);
if (stride < 4) {
// comp_offset += (address % 4) * 8;
const Id byte_offset = ctx.OpUMod(ctx.U32[1], address, ctx.ConstU32(4u));
const Id bit_offset = ctx.OpShiftLeftLogical(ctx.U32[1], byte_offset, ctx.ConstU32(3u));
comp_offset = ctx.OpIAdd(ctx.U32[1], comp_offset, bit_offset);
}
return comp_offset;
}
static Id GetBufferFormatValue(EmitContext& ctx, u32 handle, Id address, u32 comp) {
auto& buffer = ctx.buffers[handle];
const auto format = buffer.dfmt;
switch (format) {
case AmdGpu::DataFormat::FormatInvalid:
return ctx.f32_zero_value;
case AmdGpu::DataFormat::Format8:
case AmdGpu::DataFormat::Format16:
case AmdGpu::DataFormat::Format32:
case AmdGpu::DataFormat::Format8_8:
case AmdGpu::DataFormat::Format16_16:
case AmdGpu::DataFormat::Format10_11_11:
case AmdGpu::DataFormat::Format11_11_10:
case AmdGpu::DataFormat::Format10_10_10_2:
case AmdGpu::DataFormat::Format2_10_10_10:
case AmdGpu::DataFormat::Format8_8_8_8:
case AmdGpu::DataFormat::Format32_32:
case AmdGpu::DataFormat::Format16_16_16_16:
case AmdGpu::DataFormat::Format32_32_32:
case AmdGpu::DataFormat::Format32_32_32_32: {
const u32 num_components = AmdGpu::NumComponents(format);
if (comp >= num_components) {
return ctx.f32_zero_value;
}
// uint index = address / 4;
Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
const u32 stride = buffer.stride;
if (stride > 4) {
const u32 index_offset = u32(AmdGpu::ComponentOffset(format, comp) / 32);
if (index_offset > 0) {
// index += index_offset;
index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(index_offset));
}
}
const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index);
const u32 bit_offset = AmdGpu::ComponentOffset(format, comp) % 32;
const u32 bit_width = AmdGpu::ComponentBits(format, comp);
const auto num_format = buffer.nfmt;
if (num_format == AmdGpu::NumberFormat::Float) {
if (bit_width == 32) {
return ctx.OpLoad(ctx.F32[1], ptr);
} else if (bit_width == 16) {
const Id comp_offset = ComponentOffset(ctx, address, stride, bit_offset);
Id value = ctx.OpLoad(ctx.U32[1], ptr);
value =
ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset, ctx.ConstU32(bit_width));
value = ctx.OpSConvert(ctx.U16, value);
value = ctx.OpBitcast(ctx.F16[1], value);
return ctx.OpFConvert(ctx.F32[1], value);
} else {
UNREACHABLE_MSG("Invalid float bit width {}", bit_width);
}
} else {
Id value = ctx.OpLoad(ctx.U32[1], ptr);
const bool is_signed = IsSignedInteger(num_format);
if (bit_width < 32) {
const Id comp_offset = ComponentOffset(ctx, address, stride, bit_offset);
if (is_signed) {
value = ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset,
ctx.ConstU32(bit_width));
} else {
value = ctx.OpBitFieldUExtract(ctx.U32[1], value, comp_offset,
ctx.ConstU32(bit_width));
}
}
value = ctx.OpBitcast(ctx.F32[1], value);
return ConvertValue(ctx, value, num_format, bit_width);
}
break;
}
default:
UNREACHABLE_MSG("Invalid format for conversion: {}", magic_enum::enum_name(format));
}
}
template <u32 N>
static Id EmitLoadBufferFormatF32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
auto& buffer = ctx.buffers[handle];
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
if constexpr (N == 1) {
return GetBufferFormatValue(ctx, handle, address, 0);
} else {
boost::container::static_vector<Id, N> ids;
for (u32 i = 0; i < N; i++) {
ids.push_back(GetBufferFormatValue(ctx, handle, address, i));
}
return ctx.OpCompositeConstruct(ctx.F32[N], ids);
}
}
Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
return EmitLoadBufferFormatF32xN<1>(ctx, inst, handle, address); const auto& buffer = ctx.texture_buffers[handle];
} const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id);
const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset);
Id EmitLoadBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { Id texel = buffer.is_storage ? ctx.OpImageRead(buffer.result_type, tex_buffer, coord)
return EmitLoadBufferFormatF32xN<2>(ctx, inst, handle, address); : ctx.OpImageFetch(buffer.result_type, tex_buffer, coord);
} if (buffer.is_integer) {
texel = ctx.OpBitcast(ctx.F32[4], texel);
Id EmitLoadBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { }
return EmitLoadBufferFormatF32xN<3>(ctx, inst, handle, address); return texel;
}
Id EmitLoadBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
return EmitLoadBufferFormatF32xN<4>(ctx, inst, handle, address);
} }
template <u32 N> template <u32 N>
@ -467,97 +312,14 @@ void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address
EmitStoreBufferF32xN<1>(ctx, handle, address, value); EmitStoreBufferF32xN<1>(ctx, handle, address, value);
} }
static Id ConvertF32ToFormat(EmitContext& ctx, Id value, AmdGpu::NumberFormat format,
u32 bit_width) {
switch (format) {
case AmdGpu::NumberFormat::Unorm:
return ctx.OpConvertFToU(
ctx.U32[1], ctx.OpFMul(ctx.F32[1], value, ctx.ConstF32(float(UXBitsMax(bit_width)))));
case AmdGpu::NumberFormat::Uint:
return ctx.OpBitcast(ctx.U32[1], value);
case AmdGpu::NumberFormat::Float:
return value;
default:
UNREACHABLE_MSG("Unsupported number format for conversion: {}",
magic_enum::enum_name(format));
}
}
template <u32 N>
static void EmitStoreBufferFormatF32xN(EmitContext& ctx, u32 handle, Id address, Id value) {
auto& buffer = ctx.buffers[handle];
const auto format = buffer.dfmt;
const auto num_format = buffer.nfmt;
switch (format) {
case AmdGpu::DataFormat::FormatInvalid:
return;
case AmdGpu::DataFormat::Format8_8_8_8:
case AmdGpu::DataFormat::Format16:
case AmdGpu::DataFormat::Format32:
case AmdGpu::DataFormat::Format32_32:
case AmdGpu::DataFormat::Format32_32_32_32: {
ASSERT(N == AmdGpu::NumComponents(format));
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index);
Id packed_value{};
for (u32 i = 0; i < N; i++) {
const u32 bit_width = AmdGpu::ComponentBits(format, i);
const u32 bit_offset = AmdGpu::ComponentOffset(format, i) % 32;
const Id comp{ConvertF32ToFormat(
ctx, N == 1 ? value : ctx.OpCompositeExtract(ctx.F32[1], value, i), num_format,
bit_width)};
if (bit_width == 32) {
if constexpr (N == 1) {
ctx.OpStore(ptr, comp);
} else {
const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i));
const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id,
ctx.u32_zero_value, index_i);
ctx.OpStore(ptr, comp);
}
} else {
if (i == 0) {
packed_value = comp;
} else {
packed_value =
ctx.OpBitFieldInsert(ctx.U32[1], packed_value, comp,
ctx.ConstU32(bit_offset), ctx.ConstU32(bit_width));
}
if (i == N - 1) {
ctx.OpStore(ptr, packed_value);
}
}
}
} break;
default:
UNREACHABLE_MSG("Invalid format for conversion: {}", magic_enum::enum_name(format));
}
}
void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
EmitStoreBufferFormatF32xN<1>(ctx, handle, address, value); const auto& buffer = ctx.texture_buffers[handle];
} const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id);
const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset);
void EmitStoreBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, if (buffer.is_integer) {
Id value) { value = ctx.OpBitcast(ctx.U32[4], value);
EmitStoreBufferFormatF32xN<2>(ctx, handle, address, value); }
} ctx.OpImageWrite(tex_buffer, coord, value);
void EmitStoreBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address,
Id value) {
EmitStoreBufferFormatF32xN<3>(ctx, handle, address, value);
}
void EmitStoreBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address,
Id value) {
EmitStoreBufferFormatF32xN<4>(ctx, handle, address, value);
} }
} // namespace Shader::Backend::SPIRV } // namespace Shader::Backend::SPIRV

View File

@ -41,13 +41,14 @@ void Name(EmitContext& ctx, Id object, std::string_view format_str, Args&&... ar
} // Anonymous namespace } // Anonymous namespace
EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& binding_) EmitContext::EmitContext(const Profile& profile_, const Shader::Info& info_, u32& binding_)
: Sirit::Module(profile_.supported_spirv), info{program.info}, profile{profile_}, : Sirit::Module(profile_.supported_spirv), info{info_}, profile{profile_}, stage{info.stage},
stage{program.info.stage}, binding{binding_} { binding{binding_} {
AddCapability(spv::Capability::Shader); AddCapability(spv::Capability::Shader);
DefineArithmeticTypes(); DefineArithmeticTypes();
DefineInterfaces(); DefineInterfaces();
DefineBuffers(); DefineBuffers();
DefineTextureBuffers();
DefineImagesAndSamplers(); DefineImagesAndSamplers();
DefineSharedMemory(); DefineSharedMemory();
} }
@ -123,25 +124,24 @@ void EmitContext::DefineInterfaces() {
DefineOutputs(); DefineOutputs();
} }
Id GetAttributeType(EmitContext& ctx, AmdGpu::NumberFormat fmt) { const VectorIds& GetAttributeType(EmitContext& ctx, AmdGpu::NumberFormat fmt) {
switch (fmt) { switch (fmt) {
case AmdGpu::NumberFormat::Float: case AmdGpu::NumberFormat::Float:
case AmdGpu::NumberFormat::Unorm: case AmdGpu::NumberFormat::Unorm:
case AmdGpu::NumberFormat::Snorm: case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz: case AmdGpu::NumberFormat::SnormNz:
return ctx.F32[4];
case AmdGpu::NumberFormat::Sint:
return ctx.S32[4];
case AmdGpu::NumberFormat::Uint:
return ctx.U32[4];
case AmdGpu::NumberFormat::Sscaled: case AmdGpu::NumberFormat::Sscaled:
return ctx.F32[4];
case AmdGpu::NumberFormat::Uscaled: case AmdGpu::NumberFormat::Uscaled:
return ctx.F32[4]; case AmdGpu::NumberFormat::Srgb:
return ctx.F32;
case AmdGpu::NumberFormat::Sint:
return ctx.S32;
case AmdGpu::NumberFormat::Uint:
return ctx.U32;
default: default:
break; break;
} }
throw InvalidArgument("Invalid attribute type {}", fmt); UNREACHABLE_MSG("Invalid attribute type {}", fmt);
} }
EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id) { EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id) {
@ -162,7 +162,7 @@ EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat f
default: default:
break; break;
} }
throw InvalidArgument("Invalid attribute type {}", fmt); UNREACHABLE_MSG("Invalid attribute type {}", fmt);
} }
void EmitContext::DefineBufferOffsets() { void EmitContext::DefineBufferOffsets() {
@ -177,6 +177,16 @@ void EmitContext::DefineBufferOffsets() {
buffer.offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U)); buffer.offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U));
buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U)); buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U));
} }
for (auto& tex_buffer : texture_buffers) {
const u32 binding = tex_buffer.binding;
const u32 half = Shader::PushData::BufOffsetIndex + (binding >> 4);
const u32 comp = (binding & 0xf) >> 2;
const u32 offset = (binding & 0x3) << 3;
const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]),
push_data_block, ConstU32(half), ConstU32(comp))};
const Id value{OpLoad(U32[1], ptr)};
tex_buffer.coord_offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U));
}
} }
Id MakeDefaultValue(EmitContext& ctx, u32 default_value) { Id MakeDefaultValue(EmitContext& ctx, u32 default_value) {
@ -195,6 +205,11 @@ Id MakeDefaultValue(EmitContext& ctx, u32 default_value) {
} }
void EmitContext::DefineInputs() { void EmitContext::DefineInputs() {
if (info.uses_lane_id) {
subgroup_local_invocation_id = DefineVariable(
U32[1], spv::BuiltIn::SubgroupLocalInvocationId, spv::StorageClass::Input);
Decorate(subgroup_local_invocation_id, spv::Decoration::Flat);
}
switch (stage) { switch (stage) {
case Stage::Vertex: { case Stage::Vertex: {
vertex_index = DefineVariable(U32[1], spv::BuiltIn::VertexIndex, spv::StorageClass::Input); vertex_index = DefineVariable(U32[1], spv::BuiltIn::VertexIndex, spv::StorageClass::Input);
@ -202,7 +217,7 @@ void EmitContext::DefineInputs() {
instance_id = DefineVariable(U32[1], spv::BuiltIn::InstanceIndex, spv::StorageClass::Input); instance_id = DefineVariable(U32[1], spv::BuiltIn::InstanceIndex, spv::StorageClass::Input);
for (const auto& input : info.vs_inputs) { for (const auto& input : info.vs_inputs) {
const Id type{GetAttributeType(*this, input.fmt)}; const Id type{GetAttributeType(*this, input.fmt)[4]};
if (input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate0 || if (input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate0 ||
input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate1) { input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate1) {
@ -229,15 +244,12 @@ void EmitContext::DefineInputs() {
break; break;
} }
case Stage::Fragment: case Stage::Fragment:
subgroup_local_invocation_id = DefineVariable(
U32[1], spv::BuiltIn::SubgroupLocalInvocationId, spv::StorageClass::Input);
Decorate(subgroup_local_invocation_id, spv::Decoration::Flat);
frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input); frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input);
frag_depth = DefineVariable(F32[1], spv::BuiltIn::FragDepth, spv::StorageClass::Output); frag_depth = DefineVariable(F32[1], spv::BuiltIn::FragDepth, spv::StorageClass::Output);
front_facing = DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input); front_facing = DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input);
for (const auto& input : info.ps_inputs) { for (const auto& input : info.ps_inputs) {
const u32 semantic = input.param_index; const u32 semantic = input.param_index;
if (input.is_default) { if (input.is_default && !input.is_flat) {
input_params[semantic] = {MakeDefaultValue(*this, input.default_value), F32[1], input_params[semantic] = {MakeDefaultValue(*this, input.default_value), F32[1],
F32[1], 4, true}; F32[1], 4, true};
continue; continue;
@ -328,47 +340,75 @@ void EmitContext::DefinePushDataBlock() {
void EmitContext::DefineBuffers() { void EmitContext::DefineBuffers() {
boost::container::small_vector<Id, 8> type_ids; boost::container::small_vector<Id, 8> type_ids;
for (u32 i = 0; const auto& buffer : info.buffers) { const auto define_struct = [&](Id record_array_type, bool is_instance_data) {
const auto* data_types = True(buffer.used_types & IR::Type::F32) ? &F32 : &U32;
const Id data_type = (*data_types)[1];
const Id record_array_type{buffer.is_storage
? TypeRuntimeArray(data_type)
: TypeArray(data_type, ConstU32(buffer.length))};
const Id struct_type{TypeStruct(record_array_type)}; const Id struct_type{TypeStruct(record_array_type)};
if (std::ranges::find(type_ids, record_array_type.value, &Id::value) == type_ids.end()) { if (std::ranges::find(type_ids, record_array_type.value, &Id::value) != type_ids.end()) {
Decorate(record_array_type, spv::Decoration::ArrayStride, 4); return struct_type;
const auto name =
buffer.is_instance_data
? fmt::format("{}_instance_data{}_{}{}", stage, i, 'f',
sizeof(float) * CHAR_BIT)
: fmt::format("{}_cbuf_block_{}{}", stage, 'f', sizeof(float) * CHAR_BIT);
Name(struct_type, name);
Decorate(struct_type, spv::Decoration::Block);
MemberName(struct_type, 0, "data");
MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U);
type_ids.push_back(record_array_type);
} }
Decorate(record_array_type, spv::Decoration::ArrayStride, 4);
const auto name = is_instance_data ? fmt::format("{}_instance_data_f32", stage)
: fmt::format("{}_cbuf_block_f32", stage);
Name(struct_type, name);
Decorate(struct_type, spv::Decoration::Block);
MemberName(struct_type, 0, "data");
MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U);
type_ids.push_back(record_array_type);
return struct_type;
};
for (const auto& desc : info.buffers) {
const auto sharp = desc.GetSharp(info);
const bool is_storage = desc.IsStorage(sharp);
const auto* data_types = True(desc.used_types & IR::Type::F32) ? &F32 : &U32;
const Id data_type = (*data_types)[1];
const Id record_array_type{is_storage ? TypeRuntimeArray(data_type)
: TypeArray(data_type, ConstU32(sharp.NumDwords()))};
const Id struct_type{define_struct(record_array_type, desc.is_instance_data)};
const auto storage_class = const auto storage_class =
buffer.is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform; is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform;
const Id struct_pointer_type{TypePointer(storage_class, struct_type)}; const Id struct_pointer_type{TypePointer(storage_class, struct_type)};
const Id pointer_type = TypePointer(storage_class, data_type); const Id pointer_type = TypePointer(storage_class, data_type);
const Id id{AddGlobalVariable(struct_pointer_type, storage_class)}; const Id id{AddGlobalVariable(struct_pointer_type, storage_class)};
Decorate(id, spv::Decoration::Binding, binding); Decorate(id, spv::Decoration::Binding, binding);
Decorate(id, spv::Decoration::DescriptorSet, 0U); Decorate(id, spv::Decoration::DescriptorSet, 0U);
Name(id, fmt::format("{}_{}", buffer.is_storage ? "ssbo" : "cbuf", buffer.sgpr_base)); if (is_storage && !desc.is_written) {
Decorate(id, spv::Decoration::NonWritable);
}
Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "cbuf", desc.sgpr_base));
buffers.push_back({ buffers.push_back({
.id = id, .id = id,
.binding = binding++, .binding = binding++,
.data_types = data_types, .data_types = data_types,
.pointer_type = pointer_type, .pointer_type = pointer_type,
.dfmt = buffer.dfmt,
.nfmt = buffer.nfmt,
.stride = buffer.GetVsharp(info).GetStride(),
}); });
interfaces.push_back(id); interfaces.push_back(id);
i++; }
}
void EmitContext::DefineTextureBuffers() {
for (const auto& desc : info.texture_buffers) {
const bool is_integer =
desc.nfmt == AmdGpu::NumberFormat::Uint || desc.nfmt == AmdGpu::NumberFormat::Sint;
const VectorIds& sampled_type{GetAttributeType(*this, desc.nfmt)};
const u32 sampled = desc.is_written ? 2 : 1;
const Id image_type{TypeImage(sampled_type[1], spv::Dim::Buffer, false, false, false,
sampled, spv::ImageFormat::Unknown)};
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
Decorate(id, spv::Decoration::Binding, binding);
Decorate(id, spv::Decoration::DescriptorSet, 0U);
Name(id, fmt::format("{}_{}", desc.is_written ? "imgbuf" : "texbuf", desc.sgpr_base));
texture_buffers.push_back({
.id = id,
.binding = binding++,
.image_type = image_type,
.result_type = sampled_type[4],
.is_integer = is_integer,
.is_storage = desc.is_written,
});
interfaces.push_back(id);
} }
} }
@ -447,7 +487,7 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) {
Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
const auto image = ctx.info.ReadUd<AmdGpu::Image>(desc.sgpr_base, desc.dword_offset); const auto image = ctx.info.ReadUd<AmdGpu::Image>(desc.sgpr_base, desc.dword_offset);
const auto format = desc.is_storage ? GetFormat(image) : spv::ImageFormat::Unknown; const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown;
const u32 sampled = desc.is_storage ? 2 : 1; const u32 sampled = desc.is_storage ? 2 : 1;
switch (desc.type) { switch (desc.type) {
case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1D:
@ -470,17 +510,8 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
void EmitContext::DefineImagesAndSamplers() { void EmitContext::DefineImagesAndSamplers() {
for (const auto& image_desc : info.images) { for (const auto& image_desc : info.images) {
const VectorIds* data_types = [&] { const VectorIds& data_types = GetAttributeType(*this, image_desc.nfmt);
switch (image_desc.nfmt) { const Id sampled_type = data_types[1];
case AmdGpu::NumberFormat::Uint:
return &U32;
case AmdGpu::NumberFormat::Sint:
return &S32;
default:
return &F32;
}
}();
const Id sampled_type = data_types->Get(1);
const Id image_type{ImageType(*this, image_desc, sampled_type)}; const Id image_type{ImageType(*this, image_desc, sampled_type)};
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
@ -489,7 +520,7 @@ void EmitContext::DefineImagesAndSamplers() {
Name(id, fmt::format("{}_{}{}_{:02x}", stage, "img", image_desc.sgpr_base, Name(id, fmt::format("{}_{}{}_{:02x}", stage, "img", image_desc.sgpr_base,
image_desc.dword_offset)); image_desc.dword_offset));
images.push_back({ images.push_back({
.data_types = data_types, .data_types = &data_types,
.id = id, .id = id,
.sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type), .sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type),
.pointer_type = pointer_type, .pointer_type = pointer_type,
@ -498,13 +529,12 @@ void EmitContext::DefineImagesAndSamplers() {
interfaces.push_back(id); interfaces.push_back(id);
++binding; ++binding;
} }
if (std::ranges::any_of(info.images, &ImageResource::is_atomic)) {
image_u32 = TypePointer(spv::StorageClass::Image, U32[1]); image_u32 = TypePointer(spv::StorageClass::Image, U32[1]);
}
if (info.samplers.empty()) { if (info.samplers.empty()) {
return; return;
} }
sampler_type = TypeSampler(); sampler_type = TypeSampler();
sampler_pointer_type = TypePointer(spv::StorageClass::UniformConstant, sampler_type); sampler_pointer_type = TypePointer(spv::StorageClass::UniformConstant, sampler_type);
for (const auto& samp_desc : info.samplers) { for (const auto& samp_desc : info.samplers) {
@ -520,14 +550,15 @@ void EmitContext::DefineImagesAndSamplers() {
} }
void EmitContext::DefineSharedMemory() { void EmitContext::DefineSharedMemory() {
static constexpr size_t DefaultSharedMemSize = 16_KB; static constexpr size_t DefaultSharedMemSize = 2_KB;
if (!info.uses_shared) { if (!info.uses_shared) {
return; return;
} }
if (info.shared_memory_size == 0) { u32 shared_memory_size = info.shared_memory_size;
info.shared_memory_size = DefaultSharedMemSize; if (shared_memory_size == 0) {
shared_memory_size = DefaultSharedMemSize;
} }
const u32 num_elements{Common::DivCeil(info.shared_memory_size, 4U)}; const u32 num_elements{Common::DivCeil(shared_memory_size, 4U)};
const Id type{TypeArray(U32[1], ConstU32(num_elements))}; const Id type{TypeArray(U32[1], ConstU32(num_elements))};
shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type);
shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]);

View File

@ -36,7 +36,7 @@ struct VectorIds {
class EmitContext final : public Sirit::Module { class EmitContext final : public Sirit::Module {
public: public:
explicit EmitContext(const Profile& profile, IR::Program& program, u32& binding); explicit EmitContext(const Profile& profile, const Shader::Info& info, u32& binding);
~EmitContext(); ~EmitContext();
Id Def(const IR::Value& value); Id Def(const IR::Value& value);
@ -124,7 +124,7 @@ public:
return ConstantComposite(type, constituents); return ConstantComposite(type, constituents);
} }
Info& info; const Info& info;
const Profile& profile; const Profile& profile;
Stage stage{}; Stage stage{};
@ -207,13 +207,20 @@ public:
u32 binding; u32 binding;
const VectorIds* data_types; const VectorIds* data_types;
Id pointer_type; Id pointer_type;
AmdGpu::DataFormat dfmt; };
AmdGpu::NumberFormat nfmt; struct TextureBufferDefinition {
u32 stride; Id id;
Id coord_offset;
u32 binding;
Id image_type;
Id result_type;
bool is_integer;
bool is_storage;
}; };
u32& binding; u32& binding;
boost::container::small_vector<BufferDefinition, 16> buffers; boost::container::small_vector<BufferDefinition, 16> buffers;
boost::container::small_vector<TextureBufferDefinition, 8> texture_buffers;
boost::container::small_vector<TextureDefinition, 8> images; boost::container::small_vector<TextureDefinition, 8> images;
boost::container::small_vector<Id, 4> samplers; boost::container::small_vector<Id, 4> samplers;
@ -238,6 +245,7 @@ private:
void DefineOutputs(); void DefineOutputs();
void DefinePushDataBlock(); void DefinePushDataBlock();
void DefineBuffers(); void DefineBuffers();
void DefineTextureBuffers();
void DefineImagesAndSamplers(); void DefineImagesAndSamplers();
void DefineSharedMemory(); void DefineSharedMemory();

View File

@ -18,25 +18,31 @@ void Translator::EmitDataShare(const GcnInst& inst) {
case Opcode::DS_READ2_B64: case Opcode::DS_READ2_B64:
return DS_READ(64, false, true, inst); return DS_READ(64, false, true, inst);
case Opcode::DS_WRITE_B32: case Opcode::DS_WRITE_B32:
return DS_WRITE(32, false, false, inst); return DS_WRITE(32, false, false, false, inst);
case Opcode::DS_WRITE2ST64_B32:
return DS_WRITE(32, false, true, true, inst);
case Opcode::DS_WRITE_B64: case Opcode::DS_WRITE_B64:
return DS_WRITE(64, false, false, inst); return DS_WRITE(64, false, false, false, inst);
case Opcode::DS_WRITE2_B32: case Opcode::DS_WRITE2_B32:
return DS_WRITE(32, false, true, inst); return DS_WRITE(32, false, true, false, inst);
case Opcode::DS_WRITE2_B64: case Opcode::DS_WRITE2_B64:
return DS_WRITE(64, false, true, inst); return DS_WRITE(64, false, true, false, inst);
case Opcode::DS_ADD_U32: case Opcode::DS_ADD_U32:
return DS_ADD_U32(inst, false); return DS_ADD_U32(inst, false);
case Opcode::DS_MIN_U32: case Opcode::DS_MIN_U32:
return DS_MIN_U32(inst, false); return DS_MIN_U32(inst, false, false);
case Opcode::DS_MIN_I32:
return DS_MIN_U32(inst, true, false);
case Opcode::DS_MAX_U32: case Opcode::DS_MAX_U32:
return DS_MAX_U32(inst, false); return DS_MAX_U32(inst, false, false);
case Opcode::DS_MAX_I32:
return DS_MAX_U32(inst, true, false);
case Opcode::DS_ADD_RTN_U32: case Opcode::DS_ADD_RTN_U32:
return DS_ADD_U32(inst, true); return DS_ADD_U32(inst, true);
case Opcode::DS_MIN_RTN_U32: case Opcode::DS_MIN_RTN_U32:
return DS_MIN_U32(inst, true); return DS_MIN_U32(inst, false, true);
case Opcode::DS_MAX_RTN_U32: case Opcode::DS_MAX_RTN_U32:
return DS_MAX_U32(inst, true); return DS_MAX_U32(inst, false, true);
default: default:
LogMissingOpcode(inst); LogMissingOpcode(inst);
} }
@ -89,12 +95,13 @@ void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnIn
} }
} }
void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst) { void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64,
const GcnInst& inst) {
const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))};
const IR::VectorReg data0{inst.src[1].code}; const IR::VectorReg data0{inst.src[1].code};
const IR::VectorReg data1{inst.src[2].code}; const IR::VectorReg data1{inst.src[2].code};
if (is_pair) { if (is_pair) {
const u32 adj = bit_size == 32 ? 4 : 8; const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1);
const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj)));
if (bit_size == 32) { if (bit_size == 32) {
ir.WriteShared(32, ir.GetVectorReg(data0), addr0); ir.WriteShared(32, ir.GetVectorReg(data0), addr0);
@ -133,23 +140,23 @@ void Translator::DS_ADD_U32(const GcnInst& inst, bool rtn) {
} }
} }
void Translator::DS_MIN_U32(const GcnInst& inst, bool rtn) { void Translator::DS_MIN_U32(const GcnInst& inst, bool is_signed, bool rtn) {
const IR::U32 addr{GetSrc(inst.src[0])}; const IR::U32 addr{GetSrc(inst.src[0])};
const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 data{GetSrc(inst.src[1])};
const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0));
const IR::U32 addr_offset = ir.IAdd(addr, offset); const IR::U32 addr_offset = ir.IAdd(addr, offset);
const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, false); const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, is_signed);
if (rtn) { if (rtn) {
SetDst(inst.dst[0], IR::U32{original_val}); SetDst(inst.dst[0], IR::U32{original_val});
} }
} }
void Translator::DS_MAX_U32(const GcnInst& inst, bool rtn) { void Translator::DS_MAX_U32(const GcnInst& inst, bool is_signed, bool rtn) {
const IR::U32 addr{GetSrc(inst.src[0])}; const IR::U32 addr{GetSrc(inst.src[0])};
const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 data{GetSrc(inst.src[1])};
const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0));
const IR::U32 addr_offset = ir.IAdd(addr, offset); const IR::U32 addr_offset = ir.IAdd(addr, offset);
const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, false); const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, is_signed);
if (rtn) { if (rtn) {
SetDst(inst.dst[0], IR::U32{original_val}); SetDst(inst.dst[0], IR::U32{original_val});
} }

View File

@ -1,14 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "shader_recompiler/frontend/translate/translate.h" #include "shader_recompiler/frontend/translate/translate.h"
namespace Shader::Gcn { namespace Shader::Gcn {
void Translator::EmitExport(const GcnInst& inst) { void Translator::EmitExport(const GcnInst& inst) {
if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) { if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) {
LOG_WARNING(Render_Recompiler, "An ambiguous export appeared in translation");
ir.Discard(ir.LogicalNot(ir.GetExec())); ir.Discard(ir.LogicalNot(ir.GetExec()));
} }

View File

@ -31,6 +31,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) {
return S_OR_B64(NegateMode::Result, false, inst); return S_OR_B64(NegateMode::Result, false, inst);
case Opcode::S_XOR_B64: case Opcode::S_XOR_B64:
return S_OR_B64(NegateMode::None, true, inst); return S_OR_B64(NegateMode::None, true, inst);
case Opcode::S_XNOR_B64:
return S_OR_B64(NegateMode::Result, true, inst);
case Opcode::S_ORN2_B64: case Opcode::S_ORN2_B64:
return S_OR_B64(NegateMode::Src1, false, inst); return S_OR_B64(NegateMode::Src1, false, inst);
case Opcode::S_AND_B64: case Opcode::S_AND_B64:

View File

@ -354,7 +354,7 @@ void Translator::EmitFetch(const GcnInst& inst) {
if (!std::filesystem::exists(dump_dir)) { if (!std::filesystem::exists(dump_dir)) {
std::filesystem::create_directories(dump_dir); std::filesystem::create_directories(dump_dir);
} }
const auto filename = fmt::format("vs_fetch_{:#018x}.bin", info.pgm_hash); const auto filename = fmt::format("vs_{:#018x}_fetch.bin", info.pgm_hash);
const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; const auto file = IOFile{dump_dir / filename, FileAccessMode::Write};
file.WriteRaw<u8>(code, fetch_size); file.WriteRaw<u8>(code, fetch_size);
} }
@ -399,9 +399,7 @@ void Translator::EmitFetch(const GcnInst& inst) {
info.buffers.push_back({ info.buffers.push_back({
.sgpr_base = attrib.sgpr_base, .sgpr_base = attrib.sgpr_base,
.dword_offset = attrib.dword_offset, .dword_offset = attrib.dword_offset,
.length = buffer.num_records,
.used_types = IR::Type::F32, .used_types = IR::Type::F32,
.is_storage = true, // we may not fit into UBO with large meshes
.is_instance_data = true, .is_instance_data = true,
}); });
instance_buf_handle = s32(info.buffers.size() - 1); instance_buf_handle = s32(info.buffers.size() - 1);
@ -438,6 +436,7 @@ void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) {
case Opcode::S_CBRANCH_SCC1: case Opcode::S_CBRANCH_SCC1:
case Opcode::S_CBRANCH_VCCNZ: case Opcode::S_CBRANCH_VCCNZ:
case Opcode::S_CBRANCH_VCCZ: case Opcode::S_CBRANCH_VCCZ:
case Opcode::S_CBRANCH_EXECNZ:
case Opcode::S_BRANCH: case Opcode::S_BRANCH:
return; return;
default: default:

View File

@ -191,8 +191,10 @@ public:
void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst); void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst);
// Vector Memory // Vector Memory
void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_format, const GcnInst& inst); void BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst);
void BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_format, const GcnInst& inst); void BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst);
void BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst);
void BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst);
void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst); void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst);
// Vector interpolation // Vector interpolation
@ -202,10 +204,10 @@ public:
// Data share // Data share
void DS_SWIZZLE_B32(const GcnInst& inst); void DS_SWIZZLE_B32(const GcnInst& inst);
void DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst); void DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst);
void DS_WRITE(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst); void DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst);
void DS_ADD_U32(const GcnInst& inst, bool rtn); void DS_ADD_U32(const GcnInst& inst, bool rtn);
void DS_MIN_U32(const GcnInst& inst, bool rtn); void DS_MIN_U32(const GcnInst& inst, bool is_signed, bool rtn);
void DS_MAX_U32(const GcnInst& inst, bool rtn); void DS_MAX_U32(const GcnInst& inst, bool is_signed, bool rtn);
void V_READFIRSTLANE_B32(const GcnInst& inst); void V_READFIRSTLANE_B32(const GcnInst& inst);
void V_READLANE_B32(const GcnInst& inst); void V_READLANE_B32(const GcnInst& inst);
void V_WRITELANE_B32(const GcnInst& inst); void V_WRITELANE_B32(const GcnInst& inst);

View File

@ -415,14 +415,20 @@ void Translator::V_ADDC_U32(const GcnInst& inst) {
const auto src0 = GetSrc<IR::U32>(inst.src[0]); const auto src0 = GetSrc<IR::U32>(inst.src[0]);
const auto src1 = GetSrc<IR::U32>(inst.src[1]); const auto src1 = GetSrc<IR::U32>(inst.src[1]);
IR::U32 scarry; IR::U1 carry;
if (inst.src_count == 3) { // VOP3 if (inst.src_count == 3) { // VOP3
IR::U1 thread_bit{ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[2].code))}; if (inst.src[2].field == OperandField::VccLo) {
scarry = IR::U32{ir.Select(thread_bit, ir.Imm32(1), ir.Imm32(0))}; carry = ir.GetVcc();
} else if (inst.src[2].field == OperandField::ScalarGPR) {
carry = ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[2].code));
} else {
UNREACHABLE();
}
} else { // VOP2 } else { // VOP2
scarry = ir.GetVccLo(); carry = ir.GetVcc();
} }
const IR::U32 scarry = IR::U32{ir.Select(carry, ir.Imm32(1), ir.Imm32(0))};
const IR::U32 result = ir.IAdd(ir.IAdd(src0, src1), scarry); const IR::U32 result = ir.IAdd(ir.IAdd(src0, src1), scarry);
const IR::VectorReg dst_reg{inst.dst[0].code}; const IR::VectorReg dst_reg{inst.dst[0].code};

View File

@ -56,57 +56,57 @@ void Translator::EmitVectorMemory(const GcnInst& inst) {
// Buffer load operations // Buffer load operations
case Opcode::TBUFFER_LOAD_FORMAT_X: case Opcode::TBUFFER_LOAD_FORMAT_X:
return BUFFER_LOAD_FORMAT(1, true, true, inst); return BUFFER_LOAD(1, true, inst);
case Opcode::TBUFFER_LOAD_FORMAT_XY: case Opcode::TBUFFER_LOAD_FORMAT_XY:
return BUFFER_LOAD_FORMAT(2, true, true, inst); return BUFFER_LOAD(2, true, inst);
case Opcode::TBUFFER_LOAD_FORMAT_XYZ: case Opcode::TBUFFER_LOAD_FORMAT_XYZ:
return BUFFER_LOAD_FORMAT(3, true, true, inst); return BUFFER_LOAD(3, true, inst);
case Opcode::TBUFFER_LOAD_FORMAT_XYZW: case Opcode::TBUFFER_LOAD_FORMAT_XYZW:
return BUFFER_LOAD_FORMAT(4, true, true, inst); return BUFFER_LOAD(4, true, inst);
case Opcode::BUFFER_LOAD_FORMAT_X: case Opcode::BUFFER_LOAD_FORMAT_X:
return BUFFER_LOAD_FORMAT(1, false, true, inst); return BUFFER_LOAD_FORMAT(1, inst);
case Opcode::BUFFER_LOAD_FORMAT_XY: case Opcode::BUFFER_LOAD_FORMAT_XY:
return BUFFER_LOAD_FORMAT(2, false, true, inst); return BUFFER_LOAD_FORMAT(2, inst);
case Opcode::BUFFER_LOAD_FORMAT_XYZ: case Opcode::BUFFER_LOAD_FORMAT_XYZ:
return BUFFER_LOAD_FORMAT(3, false, true, inst); return BUFFER_LOAD_FORMAT(3, inst);
case Opcode::BUFFER_LOAD_FORMAT_XYZW: case Opcode::BUFFER_LOAD_FORMAT_XYZW:
return BUFFER_LOAD_FORMAT(4, false, true, inst); return BUFFER_LOAD_FORMAT(4, inst);
case Opcode::BUFFER_LOAD_DWORD: case Opcode::BUFFER_LOAD_DWORD:
return BUFFER_LOAD_FORMAT(1, false, false, inst); return BUFFER_LOAD(1, false, inst);
case Opcode::BUFFER_LOAD_DWORDX2: case Opcode::BUFFER_LOAD_DWORDX2:
return BUFFER_LOAD_FORMAT(2, false, false, inst); return BUFFER_LOAD(2, false, inst);
case Opcode::BUFFER_LOAD_DWORDX3: case Opcode::BUFFER_LOAD_DWORDX3:
return BUFFER_LOAD_FORMAT(3, false, false, inst); return BUFFER_LOAD(3, false, inst);
case Opcode::BUFFER_LOAD_DWORDX4: case Opcode::BUFFER_LOAD_DWORDX4:
return BUFFER_LOAD_FORMAT(4, false, false, inst); return BUFFER_LOAD(4, false, inst);
// Buffer store operations // Buffer store operations
case Opcode::BUFFER_STORE_FORMAT_X: case Opcode::BUFFER_STORE_FORMAT_X:
return BUFFER_STORE_FORMAT(1, false, true, inst); return BUFFER_STORE_FORMAT(1, inst);
case Opcode::BUFFER_STORE_FORMAT_XY: case Opcode::BUFFER_STORE_FORMAT_XY:
return BUFFER_STORE_FORMAT(2, false, true, inst); return BUFFER_STORE_FORMAT(2, inst);
case Opcode::BUFFER_STORE_FORMAT_XYZ: case Opcode::BUFFER_STORE_FORMAT_XYZ:
return BUFFER_STORE_FORMAT(3, false, true, inst); return BUFFER_STORE_FORMAT(3, inst);
case Opcode::BUFFER_STORE_FORMAT_XYZW: case Opcode::BUFFER_STORE_FORMAT_XYZW:
return BUFFER_STORE_FORMAT(4, false, true, inst); return BUFFER_STORE_FORMAT(4, inst);
case Opcode::TBUFFER_STORE_FORMAT_X: case Opcode::TBUFFER_STORE_FORMAT_X:
return BUFFER_STORE_FORMAT(1, true, true, inst); return BUFFER_STORE(1, true, inst);
case Opcode::TBUFFER_STORE_FORMAT_XY: case Opcode::TBUFFER_STORE_FORMAT_XY:
return BUFFER_STORE_FORMAT(2, true, true, inst); return BUFFER_STORE(2, true, inst);
case Opcode::TBUFFER_STORE_FORMAT_XYZ: case Opcode::TBUFFER_STORE_FORMAT_XYZ:
return BUFFER_STORE_FORMAT(3, true, true, inst); return BUFFER_STORE(3, true, inst);
case Opcode::BUFFER_STORE_DWORD: case Opcode::BUFFER_STORE_DWORD:
return BUFFER_STORE_FORMAT(1, false, false, inst); return BUFFER_STORE(1, false, inst);
case Opcode::BUFFER_STORE_DWORDX2: case Opcode::BUFFER_STORE_DWORDX2:
return BUFFER_STORE_FORMAT(2, false, false, inst); return BUFFER_STORE(2, false, inst);
case Opcode::BUFFER_STORE_DWORDX3: case Opcode::BUFFER_STORE_DWORDX3:
return BUFFER_STORE_FORMAT(3, false, false, inst); return BUFFER_STORE(3, false, inst);
case Opcode::BUFFER_STORE_DWORDX4: case Opcode::BUFFER_STORE_DWORDX4:
return BUFFER_STORE_FORMAT(4, false, false, inst); return BUFFER_STORE(4, false, inst);
// Buffer atomic operations // Buffer atomic operations
case Opcode::BUFFER_ATOMIC_ADD: case Opcode::BUFFER_ATOMIC_ADD:
@ -349,8 +349,7 @@ void Translator::IMAGE_STORE(const GcnInst& inst) {
ir.ImageWrite(handle, body, value, {}); ir.ImageWrite(handle, body, value, {});
} }
void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_format, void Translator::BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst) {
const GcnInst& inst) {
const auto& mtbuf = inst.control.mtbuf; const auto& mtbuf = inst.control.mtbuf;
const IR::VectorReg vaddr{inst.src[0].code}; const IR::VectorReg vaddr{inst.src[0].code};
const IR::ScalarReg sharp{inst.src[2].code * 4}; const IR::ScalarReg sharp{inst.src[2].code * 4};
@ -370,22 +369,19 @@ void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_forma
info.index_enable.Assign(mtbuf.idxen); info.index_enable.Assign(mtbuf.idxen);
info.offset_enable.Assign(mtbuf.offen); info.offset_enable.Assign(mtbuf.offen);
info.inst_offset.Assign(mtbuf.offset); info.inst_offset.Assign(mtbuf.offset);
info.is_typed.Assign(is_typed);
if (is_typed) { if (is_typed) {
info.dmft.Assign(static_cast<AmdGpu::DataFormat>(mtbuf.dfmt)); const auto dmft = static_cast<AmdGpu::DataFormat>(mtbuf.dfmt);
info.nfmt.Assign(static_cast<AmdGpu::NumberFormat>(mtbuf.nfmt)); const auto nfmt = static_cast<AmdGpu::NumberFormat>(mtbuf.nfmt);
ASSERT(info.nfmt == AmdGpu::NumberFormat::Float && ASSERT(nfmt == AmdGpu::NumberFormat::Float &&
(info.dmft == AmdGpu::DataFormat::Format32_32_32_32 || (dmft == AmdGpu::DataFormat::Format32_32_32_32 ||
info.dmft == AmdGpu::DataFormat::Format32_32_32 || dmft == AmdGpu::DataFormat::Format32_32_32 ||
info.dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32));
info.dmft == AmdGpu::DataFormat::Format32));
} }
const IR::Value handle = const IR::Value handle =
ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1),
ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3));
const IR::Value value = is_format ? ir.LoadBufferFormat(num_dwords, handle, address, info) const IR::Value value = ir.LoadBuffer(num_dwords, handle, address, info);
: ir.LoadBuffer(num_dwords, handle, address, info);
const IR::VectorReg dst_reg{inst.src[1].code}; const IR::VectorReg dst_reg{inst.src[1].code};
if (num_dwords == 1) { if (num_dwords == 1) {
ir.SetVectorReg(dst_reg, IR::F32{value}); ir.SetVectorReg(dst_reg, IR::F32{value});
@ -396,8 +392,34 @@ void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_forma
} }
} }
void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_format, void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst) {
const GcnInst& inst) { const auto& mubuf = inst.control.mubuf;
const IR::VectorReg vaddr{inst.src[0].code};
const IR::ScalarReg sharp{inst.src[2].code * 4};
ASSERT_MSG(!mubuf.offen && mubuf.offset == 0, "Offsets for image buffers are not supported");
const IR::Value address = [&] -> IR::Value {
if (mubuf.idxen) {
return ir.GetVectorReg(vaddr);
}
return {};
}();
const IR::Value soffset{GetSrc(inst.src[3])};
ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported");
IR::BufferInstInfo info{};
info.index_enable.Assign(mubuf.idxen);
const IR::Value handle =
ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1),
ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3));
const IR::Value value = ir.LoadBufferFormat(handle, address, info);
const IR::VectorReg dst_reg{inst.src[1].code};
for (u32 i = 0; i < num_dwords; i++) {
ir.SetVectorReg(dst_reg + i, IR::F32{ir.CompositeExtract(value, i)});
}
}
void Translator::BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst) {
const auto& mtbuf = inst.control.mtbuf; const auto& mtbuf = inst.control.mtbuf;
const IR::VectorReg vaddr{inst.src[0].code}; const IR::VectorReg vaddr{inst.src[0].code};
const IR::ScalarReg sharp{inst.src[2].code * 4}; const IR::ScalarReg sharp{inst.src[2].code * 4};
@ -417,45 +439,76 @@ void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_form
info.index_enable.Assign(mtbuf.idxen); info.index_enable.Assign(mtbuf.idxen);
info.offset_enable.Assign(mtbuf.offen); info.offset_enable.Assign(mtbuf.offen);
info.inst_offset.Assign(mtbuf.offset); info.inst_offset.Assign(mtbuf.offset);
info.is_typed.Assign(is_typed);
if (is_typed) { if (is_typed) {
info.dmft.Assign(static_cast<AmdGpu::DataFormat>(mtbuf.dfmt)); const auto dmft = static_cast<AmdGpu::DataFormat>(mtbuf.dfmt);
info.nfmt.Assign(static_cast<AmdGpu::NumberFormat>(mtbuf.nfmt)); const auto nfmt = static_cast<AmdGpu::NumberFormat>(mtbuf.nfmt);
ASSERT(nfmt == AmdGpu::NumberFormat::Float &&
(dmft == AmdGpu::DataFormat::Format32_32_32_32 ||
dmft == AmdGpu::DataFormat::Format32_32_32 ||
dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32));
} }
IR::Value value{}; IR::Value value{};
const IR::VectorReg src_reg{inst.src[1].code}; const IR::VectorReg src_reg{inst.src[1].code};
switch (num_dwords) { switch (num_dwords) {
case 1: case 1:
value = ir.GetVectorReg<Shader::IR::F32>(src_reg); value = ir.GetVectorReg<IR::F32>(src_reg);
break; break;
case 2: case 2:
value = ir.CompositeConstruct(ir.GetVectorReg<Shader::IR::F32>(src_reg), value = ir.CompositeConstruct(ir.GetVectorReg<IR::F32>(src_reg),
ir.GetVectorReg<Shader::IR::F32>(src_reg + 1)); ir.GetVectorReg<IR::F32>(src_reg + 1));
break; break;
case 3: case 3:
value = ir.CompositeConstruct(ir.GetVectorReg<Shader::IR::F32>(src_reg), value = ir.CompositeConstruct(ir.GetVectorReg<IR::F32>(src_reg),
ir.GetVectorReg<Shader::IR::F32>(src_reg + 1), ir.GetVectorReg<IR::F32>(src_reg + 1),
ir.GetVectorReg<Shader::IR::F32>(src_reg + 2)); ir.GetVectorReg<IR::F32>(src_reg + 2));
break; break;
case 4: case 4:
value = ir.CompositeConstruct(ir.GetVectorReg<Shader::IR::F32>(src_reg), value = ir.CompositeConstruct(
ir.GetVectorReg<Shader::IR::F32>(src_reg + 1), ir.GetVectorReg<IR::F32>(src_reg), ir.GetVectorReg<IR::F32>(src_reg + 1),
ir.GetVectorReg<Shader::IR::F32>(src_reg + 2), ir.GetVectorReg<IR::F32>(src_reg + 2), ir.GetVectorReg<IR::F32>(src_reg + 3));
ir.GetVectorReg<Shader::IR::F32>(src_reg + 3));
break; break;
} }
const IR::Value handle = const IR::Value handle =
ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1),
ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3));
if (is_format) { ir.StoreBuffer(num_dwords, handle, address, value, info);
ir.StoreBufferFormat(num_dwords, handle, address, value, info); }
} else {
ir.StoreBuffer(num_dwords, handle, address, value, info); void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst) {
} const auto& mubuf = inst.control.mubuf;
const IR::VectorReg vaddr{inst.src[0].code};
const IR::ScalarReg sharp{inst.src[2].code * 4};
ASSERT_MSG(!mubuf.offen && mubuf.offset == 0, "Offsets for image buffers are not supported");
const IR::Value address = [&] -> IR::Value {
if (mubuf.idxen) {
return ir.GetVectorReg(vaddr);
}
return {};
}();
const IR::Value soffset{GetSrc(inst.src[3])};
ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported");
IR::BufferInstInfo info{};
info.index_enable.Assign(mubuf.idxen);
const IR::VectorReg src_reg{inst.src[1].code};
std::array<IR::Value, 4> comps{};
for (u32 i = 0; i < num_dwords; i++) {
comps[i] = ir.GetVectorReg<IR::F32>(src_reg + i);
}
for (u32 i = num_dwords; i < 4; i++) {
comps[i] = ir.Imm32(0.f);
}
const IR::Value value = ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]);
const IR::Value handle =
ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1),
ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3));
ir.StoreBufferFormat(handle, address, value, info);
} }
// TODO: U64
void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) { void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) {
const auto& mubuf = inst.control.mubuf; const auto& mubuf = inst.control.mubuf;
const IR::VectorReg vaddr{inst.src[0].code}; const IR::VectorReg vaddr{inst.src[0].code};

View File

@ -325,20 +325,8 @@ Value IREmitter::LoadBuffer(int num_dwords, const Value& handle, const Value& ad
} }
} }
Value IREmitter::LoadBufferFormat(int num_dwords, const Value& handle, const Value& address, Value IREmitter::LoadBufferFormat(const Value& handle, const Value& address, BufferInstInfo info) {
BufferInstInfo info) { return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address);
switch (num_dwords) {
case 1:
return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address);
case 2:
return Inst(Opcode::LoadBufferFormatF32x2, Flags{info}, handle, address);
case 3:
return Inst(Opcode::LoadBufferFormatF32x3, Flags{info}, handle, address);
case 4:
return Inst(Opcode::LoadBufferFormatF32x4, Flags{info}, handle, address);
default:
UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords);
}
} }
void IREmitter::StoreBuffer(int num_dwords, const Value& handle, const Value& address, void IREmitter::StoreBuffer(int num_dwords, const Value& handle, const Value& address,
@ -409,24 +397,9 @@ Value IREmitter::BufferAtomicSwap(const Value& handle, const Value& address, con
return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value); return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value);
} }
void IREmitter::StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, void IREmitter::StoreBufferFormat(const Value& handle, const Value& address, const Value& data,
const Value& data, BufferInstInfo info) { BufferInstInfo info) {
switch (num_dwords) { Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data);
case 1:
Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data);
break;
case 2:
Inst(Opcode::StoreBufferFormatF32x2, Flags{info}, handle, address, data);
break;
case 3:
Inst(Opcode::StoreBufferFormatF32x3, Flags{info}, handle, address, data);
break;
case 4:
Inst(Opcode::StoreBufferFormatF32x4, Flags{info}, handle, address, data);
break;
default:
UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords);
}
} }
U32 IREmitter::LaneId() { U32 IREmitter::LaneId() {

View File

@ -92,12 +92,12 @@ public:
[[nodiscard]] Value LoadBuffer(int num_dwords, const Value& handle, const Value& address, [[nodiscard]] Value LoadBuffer(int num_dwords, const Value& handle, const Value& address,
BufferInstInfo info); BufferInstInfo info);
[[nodiscard]] Value LoadBufferFormat(int num_dwords, const Value& handle, const Value& address, [[nodiscard]] Value LoadBufferFormat(const Value& handle, const Value& address,
BufferInstInfo info); BufferInstInfo info);
void StoreBuffer(int num_dwords, const Value& handle, const Value& address, const Value& data, void StoreBuffer(int num_dwords, const Value& handle, const Value& address, const Value& data,
BufferInstInfo info); BufferInstInfo info);
void StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, void StoreBufferFormat(const Value& handle, const Value& address, const Value& data,
const Value& data, BufferInstInfo info); BufferInstInfo info);
[[nodiscard]] Value BufferAtomicIAdd(const Value& handle, const Value& address, [[nodiscard]] Value BufferAtomicIAdd(const Value& handle, const Value& address,
const Value& value, BufferInstInfo info); const Value& value, BufferInstInfo info);

View File

@ -56,9 +56,6 @@ bool Inst::MayHaveSideEffects() const noexcept {
case Opcode::StoreBufferF32x3: case Opcode::StoreBufferF32x3:
case Opcode::StoreBufferF32x4: case Opcode::StoreBufferF32x4:
case Opcode::StoreBufferFormatF32: case Opcode::StoreBufferFormatF32:
case Opcode::StoreBufferFormatF32x2:
case Opcode::StoreBufferFormatF32x3:
case Opcode::StoreBufferFormatF32x4:
case Opcode::StoreBufferU32: case Opcode::StoreBufferU32:
case Opcode::BufferAtomicIAdd32: case Opcode::BufferAtomicIAdd32:
case Opcode::BufferAtomicSMin32: case Opcode::BufferAtomicSMin32:

View File

@ -79,19 +79,13 @@ OPCODE(LoadBufferF32, F32, Opaq
OPCODE(LoadBufferF32x2, F32x2, Opaque, Opaque, ) OPCODE(LoadBufferF32x2, F32x2, Opaque, Opaque, )
OPCODE(LoadBufferF32x3, F32x3, Opaque, Opaque, ) OPCODE(LoadBufferF32x3, F32x3, Opaque, Opaque, )
OPCODE(LoadBufferF32x4, F32x4, Opaque, Opaque, ) OPCODE(LoadBufferF32x4, F32x4, Opaque, Opaque, )
OPCODE(LoadBufferFormatF32, F32, Opaque, Opaque, ) OPCODE(LoadBufferFormatF32, F32x4, Opaque, Opaque, )
OPCODE(LoadBufferFormatF32x2, F32x2, Opaque, Opaque, )
OPCODE(LoadBufferFormatF32x3, F32x3, Opaque, Opaque, )
OPCODE(LoadBufferFormatF32x4, F32x4, Opaque, Opaque, )
OPCODE(LoadBufferU32, U32, Opaque, Opaque, ) OPCODE(LoadBufferU32, U32, Opaque, Opaque, )
OPCODE(StoreBufferF32, Void, Opaque, Opaque, F32, ) OPCODE(StoreBufferF32, Void, Opaque, Opaque, F32, )
OPCODE(StoreBufferF32x2, Void, Opaque, Opaque, F32x2, ) OPCODE(StoreBufferF32x2, Void, Opaque, Opaque, F32x2, )
OPCODE(StoreBufferF32x3, Void, Opaque, Opaque, F32x3, ) OPCODE(StoreBufferF32x3, Void, Opaque, Opaque, F32x3, )
OPCODE(StoreBufferF32x4, Void, Opaque, Opaque, F32x4, ) OPCODE(StoreBufferF32x4, Void, Opaque, Opaque, F32x4, )
OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32, ) OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32x4, )
OPCODE(StoreBufferFormatF32x2, Void, Opaque, Opaque, F32x2, )
OPCODE(StoreBufferFormatF32x3, Void, Opaque, Opaque, F32x3, )
OPCODE(StoreBufferFormatF32x4, Void, Opaque, Opaque, F32x4, )
OPCODE(StoreBufferU32, Void, Opaque, Opaque, U32, ) OPCODE(StoreBufferU32, Void, Opaque, Opaque, U32, )
// Buffer atomic operations // Buffer atomic operations

View File

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include "common/alignment.h"
#include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/basic_block.h"
#include "shader_recompiler/ir/breadth_first_search.h" #include "shader_recompiler/ir/breadth_first_search.h"
#include "shader_recompiler/ir/ir_emitter.h" #include "shader_recompiler/ir/ir_emitter.h"
@ -45,10 +46,6 @@ bool IsBufferStore(const IR::Inst& inst) {
case IR::Opcode::StoreBufferF32x2: case IR::Opcode::StoreBufferF32x2:
case IR::Opcode::StoreBufferF32x3: case IR::Opcode::StoreBufferF32x3:
case IR::Opcode::StoreBufferF32x4: case IR::Opcode::StoreBufferF32x4:
case IR::Opcode::StoreBufferFormatF32:
case IR::Opcode::StoreBufferFormatF32x2:
case IR::Opcode::StoreBufferFormatF32x3:
case IR::Opcode::StoreBufferFormatF32x4:
case IR::Opcode::StoreBufferU32: case IR::Opcode::StoreBufferU32:
return true; return true;
default: default:
@ -62,10 +59,6 @@ bool IsBufferInstruction(const IR::Inst& inst) {
case IR::Opcode::LoadBufferF32x2: case IR::Opcode::LoadBufferF32x2:
case IR::Opcode::LoadBufferF32x3: case IR::Opcode::LoadBufferF32x3:
case IR::Opcode::LoadBufferF32x4: case IR::Opcode::LoadBufferF32x4:
case IR::Opcode::LoadBufferFormatF32:
case IR::Opcode::LoadBufferFormatF32x2:
case IR::Opcode::LoadBufferFormatF32x3:
case IR::Opcode::LoadBufferFormatF32x4:
case IR::Opcode::LoadBufferU32: case IR::Opcode::LoadBufferU32:
case IR::Opcode::ReadConstBuffer: case IR::Opcode::ReadConstBuffer:
case IR::Opcode::ReadConstBufferU32: case IR::Opcode::ReadConstBufferU32:
@ -75,6 +68,11 @@ bool IsBufferInstruction(const IR::Inst& inst) {
} }
} }
bool IsTextureBufferInstruction(const IR::Inst& inst) {
return inst.GetOpcode() == IR::Opcode::LoadBufferFormatF32 ||
inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32;
}
static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) {
switch (num_format) { switch (num_format) {
case AmdGpu::NumberFormat::Float: case AmdGpu::NumberFormat::Float:
@ -100,28 +98,6 @@ static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_for
IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) { IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) {
switch (inst.GetOpcode()) { switch (inst.GetOpcode()) {
case IR::Opcode::LoadBufferFormatF32:
case IR::Opcode::LoadBufferFormatF32x2:
case IR::Opcode::LoadBufferFormatF32x3:
case IR::Opcode::LoadBufferFormatF32x4:
case IR::Opcode::StoreBufferFormatF32:
case IR::Opcode::StoreBufferFormatF32x2:
case IR::Opcode::StoreBufferFormatF32x3:
case IR::Opcode::StoreBufferFormatF32x4:
switch (num_format) {
case AmdGpu::NumberFormat::Unorm:
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::Uscaled:
case AmdGpu::NumberFormat::Sscaled:
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
case AmdGpu::NumberFormat::SnormNz:
return IR::Type::U32;
case AmdGpu::NumberFormat::Float:
return IR::Type::F32;
default:
UNREACHABLE();
}
case IR::Opcode::LoadBufferF32: case IR::Opcode::LoadBufferF32:
case IR::Opcode::LoadBufferF32x2: case IR::Opcode::LoadBufferF32x2:
case IR::Opcode::LoadBufferF32x3: case IR::Opcode::LoadBufferF32x3:
@ -143,20 +119,8 @@ IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) {
} }
} }
bool IsImageInstruction(const IR::Inst& inst) { bool IsImageAtomicInstruction(const IR::Inst& inst) {
switch (inst.GetOpcode()) { switch (inst.GetOpcode()) {
case IR::Opcode::ImageSampleExplicitLod:
case IR::Opcode::ImageSampleImplicitLod:
case IR::Opcode::ImageSampleDrefExplicitLod:
case IR::Opcode::ImageSampleDrefImplicitLod:
case IR::Opcode::ImageFetch:
case IR::Opcode::ImageGather:
case IR::Opcode::ImageGatherDref:
case IR::Opcode::ImageQueryDimensions:
case IR::Opcode::ImageQueryLod:
case IR::Opcode::ImageGradient:
case IR::Opcode::ImageRead:
case IR::Opcode::ImageWrite:
case IR::Opcode::ImageAtomicIAdd32: case IR::Opcode::ImageAtomicIAdd32:
case IR::Opcode::ImageAtomicSMin32: case IR::Opcode::ImageAtomicSMin32:
case IR::Opcode::ImageAtomicUMin32: case IR::Opcode::ImageAtomicUMin32:
@ -178,20 +142,27 @@ bool IsImageStorageInstruction(const IR::Inst& inst) {
switch (inst.GetOpcode()) { switch (inst.GetOpcode()) {
case IR::Opcode::ImageWrite: case IR::Opcode::ImageWrite:
case IR::Opcode::ImageRead: case IR::Opcode::ImageRead:
case IR::Opcode::ImageAtomicIAdd32:
case IR::Opcode::ImageAtomicSMin32:
case IR::Opcode::ImageAtomicUMin32:
case IR::Opcode::ImageAtomicSMax32:
case IR::Opcode::ImageAtomicUMax32:
case IR::Opcode::ImageAtomicInc32:
case IR::Opcode::ImageAtomicDec32:
case IR::Opcode::ImageAtomicAnd32:
case IR::Opcode::ImageAtomicOr32:
case IR::Opcode::ImageAtomicXor32:
case IR::Opcode::ImageAtomicExchange32:
return true; return true;
default: default:
return false; return IsImageAtomicInstruction(inst);
}
}
bool IsImageInstruction(const IR::Inst& inst) {
switch (inst.GetOpcode()) {
case IR::Opcode::ImageSampleExplicitLod:
case IR::Opcode::ImageSampleImplicitLod:
case IR::Opcode::ImageSampleDrefExplicitLod:
case IR::Opcode::ImageSampleDrefImplicitLod:
case IR::Opcode::ImageFetch:
case IR::Opcode::ImageGather:
case IR::Opcode::ImageGatherDref:
case IR::Opcode::ImageQueryDimensions:
case IR::Opcode::ImageQueryLod:
case IR::Opcode::ImageGradient:
return true;
default:
return IsImageStorageInstruction(inst);
} }
} }
@ -214,7 +185,8 @@ u32 ImageOffsetArgumentPosition(const IR::Inst& inst) {
class Descriptors { class Descriptors {
public: public:
explicit Descriptors(Info& info_) explicit Descriptors(Info& info_)
: info{info_}, buffer_resources{info_.buffers}, image_resources{info_.images}, : info{info_}, buffer_resources{info_.buffers},
texture_buffer_resources{info_.texture_buffers}, image_resources{info_.images},
sampler_resources{info_.samplers} {} sampler_resources{info_.samplers} {}
u32 Add(const BufferResource& desc) { u32 Add(const BufferResource& desc) {
@ -224,13 +196,21 @@ public:
desc.inline_cbuf == existing.inline_cbuf; desc.inline_cbuf == existing.inline_cbuf;
})}; })};
auto& buffer = buffer_resources[index]; auto& buffer = buffer_resources[index];
ASSERT(buffer.length == desc.length);
buffer.is_storage |= desc.is_storage;
buffer.used_types |= desc.used_types; buffer.used_types |= desc.used_types;
buffer.is_written |= desc.is_written; buffer.is_written |= desc.is_written;
return index; return index;
} }
u32 Add(const TextureBufferResource& desc) {
const u32 index{Add(texture_buffer_resources, desc, [&desc](const auto& existing) {
return desc.sgpr_base == existing.sgpr_base &&
desc.dword_offset == existing.dword_offset;
})};
auto& buffer = texture_buffer_resources[index];
buffer.is_written |= desc.is_written;
return index;
}
u32 Add(const ImageResource& desc) { u32 Add(const ImageResource& desc) {
const u32 index{Add(image_resources, desc, [&desc](const auto& existing) { const u32 index{Add(image_resources, desc, [&desc](const auto& existing) {
return desc.sgpr_base == existing.sgpr_base && return desc.sgpr_base == existing.sgpr_base &&
@ -247,7 +227,7 @@ public:
return true; return true;
} }
// Samplers with different bindings might still be the same. // Samplers with different bindings might still be the same.
return existing.GetSsharp(info) == desc.GetSsharp(info); return existing.GetSharp(info) == desc.GetSharp(info);
})}; })};
return index; return index;
} }
@ -265,6 +245,7 @@ private:
const Info& info; const Info& info;
BufferResourceList& buffer_resources; BufferResourceList& buffer_resources;
TextureBufferResourceList& texture_buffer_resources;
ImageResourceList& image_resources; ImageResourceList& image_resources;
SamplerResourceList& sampler_resources; SamplerResourceList& sampler_resources;
}; };
@ -361,33 +342,6 @@ SharpLocation TrackSharp(const IR::Inst* inst) {
}; };
} }
static constexpr size_t MaxUboSize = 65536;
static bool IsLoadBufferFormat(const IR::Inst& inst) {
switch (inst.GetOpcode()) {
case IR::Opcode::LoadBufferFormatF32:
case IR::Opcode::LoadBufferFormatF32x2:
case IR::Opcode::LoadBufferFormatF32x3:
case IR::Opcode::LoadBufferFormatF32x4:
return true;
default:
return false;
}
}
static u32 BufferLength(const AmdGpu::Buffer& buffer) {
const auto stride = buffer.GetStride();
if (stride < sizeof(f32)) {
ASSERT(sizeof(f32) % stride == 0);
return (((buffer.num_records - 1) / sizeof(f32)) + 1) * stride;
} else if (stride == sizeof(f32)) {
return buffer.num_records;
} else {
ASSERT(stride % sizeof(f32) == 0);
return buffer.num_records * (stride / sizeof(f32));
}
}
s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors,
AmdGpu::Buffer& cbuf) { AmdGpu::Buffer& cbuf) {
@ -414,10 +368,8 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors,
return descriptors.Add(BufferResource{ return descriptors.Add(BufferResource{
.sgpr_base = std::numeric_limits<u32>::max(), .sgpr_base = std::numeric_limits<u32>::max(),
.dword_offset = 0, .dword_offset = 0,
.length = BufferLength(cbuf),
.used_types = BufferDataType(inst, cbuf.GetNumberFmt()), .used_types = BufferDataType(inst, cbuf.GetNumberFmt()),
.inline_cbuf = cbuf, .inline_cbuf = cbuf,
.is_storage = IsBufferStore(inst) || cbuf.GetSize() > MaxUboSize,
}); });
} }
@ -429,28 +381,17 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
IR::Inst* handle = inst.Arg(0).InstRecursive(); IR::Inst* handle = inst.Arg(0).InstRecursive();
IR::Inst* producer = handle->Arg(0).InstRecursive(); IR::Inst* producer = handle->Arg(0).InstRecursive();
const auto sharp = TrackSharp(producer); const auto sharp = TrackSharp(producer);
const bool is_store = IsBufferStore(inst);
buffer = info.ReadUd<AmdGpu::Buffer>(sharp.sgpr_base, sharp.dword_offset); buffer = info.ReadUd<AmdGpu::Buffer>(sharp.sgpr_base, sharp.dword_offset);
binding = descriptors.Add(BufferResource{ binding = descriptors.Add(BufferResource{
.sgpr_base = sharp.sgpr_base, .sgpr_base = sharp.sgpr_base,
.dword_offset = sharp.dword_offset, .dword_offset = sharp.dword_offset,
.length = BufferLength(buffer),
.used_types = BufferDataType(inst, buffer.GetNumberFmt()), .used_types = BufferDataType(inst, buffer.GetNumberFmt()),
.is_storage = is_store || buffer.GetSize() > MaxUboSize, .is_written = IsBufferStore(inst),
.is_written = is_store,
}); });
} }
// Update buffer descriptor format. // Update buffer descriptor format.
const auto inst_info = inst.Flags<IR::BufferInstInfo>(); const auto inst_info = inst.Flags<IR::BufferInstInfo>();
auto& buffer_desc = info.buffers[binding];
if (inst_info.is_typed) {
buffer_desc.dfmt = inst_info.dmft;
buffer_desc.nfmt = inst_info.nfmt;
} else {
buffer_desc.dfmt = buffer.GetDataFmt();
buffer_desc.nfmt = buffer.GetNumberFmt();
}
// Replace handle with binding index in buffer resource list. // Replace handle with binding index in buffer resource list.
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
@ -463,20 +404,7 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
return; return;
} }
if (IsLoadBufferFormat(inst)) {
if (UseFP16(buffer.GetDataFmt(), buffer.GetNumberFmt())) {
info.uses_fp16 = true;
}
} else {
const u32 stride = buffer.GetStride();
if (stride < 4) {
LOG_WARNING(Render_Vulkan,
"non-formatting load_buffer_* is not implemented for stride {}", stride);
}
}
// Compute address of the buffer using the stride. // Compute address of the buffer using the stride.
// Todo: What if buffer is rebound with different stride?
IR::U32 address = ir.Imm32(inst_info.inst_offset.Value()); IR::U32 address = ir.Imm32(inst_info.inst_offset.Value());
if (inst_info.index_enable) { if (inst_info.index_enable) {
const IR::U32 index = inst_info.offset_enable ? IR::U32{ir.CompositeExtract(inst.Arg(1), 0)} const IR::U32 index = inst_info.offset_enable ? IR::U32{ir.CompositeExtract(inst.Arg(1), 0)}
@ -491,8 +419,31 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
inst.SetArg(1, address); inst.SetArg(1, address);
} }
void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
Descriptors& descriptors) {
const IR::Inst* handle = inst.Arg(0).InstRecursive();
const IR::Inst* producer = handle->Arg(0).InstRecursive();
const auto sharp = TrackSharp(producer);
const auto buffer = info.ReadUd<AmdGpu::Buffer>(sharp.sgpr_base, sharp.dword_offset);
const s32 binding = descriptors.Add(TextureBufferResource{
.sgpr_base = sharp.sgpr_base,
.dword_offset = sharp.dword_offset,
.nfmt = buffer.GetNumberFmt(),
.is_written = inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32,
});
// Replace handle with binding index in texture buffer resource list.
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
inst.SetArg(0, ir.Imm32(binding));
ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable);
}
IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t, IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t,
const IR::Value& z) { const IR::Value& z, bool is_storage) {
// When cubemap is written with imageStore it is treated like 2DArray.
if (is_storage) {
return ir.CompositeConstruct(s, t, z);
}
// We need to fix x and y coordinate, // We need to fix x and y coordinate,
// because the s and t coordinate will be scaled and plus 1.5 by v_madak_f32. // because the s and t coordinate will be scaled and plus 1.5 by v_madak_f32.
// We already force the scale value to be 1.0 when handling v_cubema_f32, // We already force the scale value to be 1.0 when handling v_cubema_f32,
@ -530,13 +481,15 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
return; return;
} }
ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); ASSERT(image.GetType() != AmdGpu::ImageType::Invalid);
const bool is_storage = IsImageStorageInstruction(inst);
u32 image_binding = descriptors.Add(ImageResource{ u32 image_binding = descriptors.Add(ImageResource{
.sgpr_base = tsharp.sgpr_base, .sgpr_base = tsharp.sgpr_base,
.dword_offset = tsharp.dword_offset, .dword_offset = tsharp.dword_offset,
.type = image.GetType(), .type = image.GetType(),
.nfmt = static_cast<AmdGpu::NumberFormat>(image.GetNumberFmt()), .nfmt = static_cast<AmdGpu::NumberFormat>(image.GetNumberFmt()),
.is_storage = IsImageStorageInstruction(inst), .is_storage = is_storage,
.is_depth = bool(inst_info.is_depth), .is_depth = bool(inst_info.is_depth),
.is_atomic = IsImageAtomicInstruction(inst),
}); });
// Read sampler sharp. This doesn't exist for IMAGE_LOAD/IMAGE_STORE instructions // Read sampler sharp. This doesn't exist for IMAGE_LOAD/IMAGE_STORE instructions
@ -593,7 +546,8 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
case AmdGpu::ImageType::Color3D: // x, y, z case AmdGpu::ImageType::Color3D: // x, y, z
return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)};
case AmdGpu::ImageType::Cube: // x, y, face case AmdGpu::ImageType::Cube: // x, y, face
return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_storage),
body->Arg(3)};
default: default:
UNREACHABLE_MSG("Unknown image type {}", image.GetType()); UNREACHABLE_MSG("Unknown image type {}", image.GetType());
} }
@ -668,6 +622,10 @@ void ResourceTrackingPass(IR::Program& program) {
PatchBufferInstruction(*block, inst, info, descriptors); PatchBufferInstruction(*block, inst, info, descriptors);
continue; continue;
} }
if (IsTextureBufferInstruction(inst)) {
PatchTextureBufferInstruction(*block, inst, info, descriptors);
continue;
}
if (IsImageInstruction(inst)) { if (IsImageInstruction(inst)) {
PatchImageInstruction(*block, inst, info, descriptors); PatchImageInstruction(*block, inst, info, descriptors);
} }

View File

@ -29,6 +29,12 @@ void Visit(Info& info, IR::Inst& inst) {
case IR::Opcode::ImageWrite: case IR::Opcode::ImageWrite:
info.has_storage_images = true; info.has_storage_images = true;
break; break;
case IR::Opcode::LoadBufferFormatF32:
info.has_texel_buffers = true;
break;
case IR::Opcode::StoreBufferFormatF32:
info.has_image_buffers = true;
break;
case IR::Opcode::QuadShuffle: case IR::Opcode::QuadShuffle:
info.uses_group_quad = true; info.uses_group_quad = true;
break; break;
@ -44,6 +50,9 @@ void Visit(Info& info, IR::Inst& inst) {
case IR::Opcode::ImageQueryLod: case IR::Opcode::ImageQueryLod:
info.has_image_query = true; info.has_image_query = true;
break; break;
case IR::Opcode::LaneId:
info.uses_lane_id = true;
break;
default: default:
break; break;
} }

View File

@ -12,11 +12,13 @@
namespace Shader::IR { namespace Shader::IR {
struct Program { struct Program {
explicit Program(Info& info_) : info{info_} {}
AbstractSyntaxList syntax_list; AbstractSyntaxList syntax_list;
BlockList blocks; BlockList blocks;
BlockList post_order_blocks; BlockList post_order_blocks;
std::vector<Gcn::GcnInst> ins_list; std::vector<Gcn::GcnInst> ins_list;
Info info; Info& info;
}; };
[[nodiscard]] std::string DumpProgram(const Program& program); [[nodiscard]] std::string DumpProgram(const Program& program);

Some files were not shown because too many files have changed in this diff Show More