From 81d7adea95f0c183306e12f8dd0c6844bdb6b9fe Mon Sep 17 00:00:00 2001 From: boykopovar Date: Tue, 8 Sep 2026 12:10:49 +0300 Subject: [PATCH] feat(log): log system detalization --- README.md | 1 + core/libs/prx/libSceAgc/CMakeLists.txt | 1 + core/libs/prx/libSceAgc/Shader/Export.cpp | 251 ++++-------------- .../libs/prx/libSceAgc/Shader/ShaderUtils.cpp | 152 +++++++++++ .../libs/prx/libSceAgc/Shader/ShaderUtils.hpp | 32 +++ core/libs/prx/libc/Export.cpp | 8 + core/libs/prx/libc/include/General.hpp | 40 +++ core/libs/prx/libc/src/FileAndHeap.cpp | 2 +- core/libs/prx/libc/src/Strings.cpp | 2 +- 9 files changed, 282 insertions(+), 207 deletions(-) create mode 100644 core/libs/prx/libSceAgc/Shader/ShaderUtils.cpp create mode 100644 core/libs/prx/libSceAgc/Shader/ShaderUtils.hpp diff --git a/README.md b/README.md index 1d28ea0b8..2a89ab534 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Implementations of system prx libraries suitable for dynamic linking: [core/libs Execution reaches `_start`, stack unwinding and exception handling tables are built. All unimplemented functions throw std::runtime_error. `what()` is printed to stderr and the process terminates. Shader initialization via `sceAgcCreate*` passes. + Now: `sceVideoOutOpen not implemented`. ## Disclaimer diff --git a/core/libs/prx/libSceAgc/CMakeLists.txt b/core/libs/prx/libSceAgc/CMakeLists.txt index 29383fca1..eaeb0e180 100644 --- a/core/libs/prx/libSceAgc/CMakeLists.txt +++ b/core/libs/prx/libSceAgc/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(libSceAgc SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Shader/Export.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Shader/ShaderUtils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Acb/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Cb/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/DcbDraw/Export.cpp diff --git a/core/libs/prx/libSceAgc/Shader/Export.cpp b/core/libs/prx/libSceAgc/Shader/Export.cpp index 7018976b3..d6fbc4e7a 100644 --- a/core/libs/prx/libSceAgc/Shader/Export.cpp +++ b/core/libs/prx/libSceAgc/Shader/Export.cpp @@ -1,228 +1,64 @@ -#include -#include +#include #include +#include + #include "SceShaders.hpp" -#include "prx/libc/include/General.hpp" +#include "ShaderUtils.hpp" #include "ShaderConstants.hpp" -namespace { - -using namespace ShaderRegs; - -template -static void _resolveRelativePtr(T*& field) { - if (field == nullptr) { - return; - } - field = reinterpret_cast( - reinterpret_cast(field) + reinterpret_cast(&field) - ); -} - -static bool _getProgramAddressRegisterOffset(std::uint8_t type, std::uint32_t& loOffset) { - switch (static_cast(type)) { - case ShaderBinaryType::Cs: loOffset = COMPUTE_PGM_LO; return true; - case ShaderBinaryType::Ps: loOffset = SPI_SHADER_PGM_LO_PS; return true; - case ShaderBinaryType::Gs: loOffset = SPI_SHADER_PGM_LO_ES; return true; - case ShaderBinaryType::Hs: loOffset = SPI_SHADER_PGM_LO_LS; return true; - case ShaderBinaryType::GsBack: loOffset = SPI_SHADER_PGM_LO_GS; return true; - case ShaderBinaryType::HsBack: loOffset = SPI_SHADER_PGM_LO_HS; return true; - default: return false; - } -} - -static int _patchProgramAddressRegister(ShaderRegister* regs, std::uint32_t numRegs, std::uint8_t type, std::uint64_t base) { - std::uint32_t loOffset = 0; - if (!_getProgramAddressRegisterOffset(type, loOffset)) { - return 0; - } - - if (regs == nullptr || numRegs == 0) { - throw std::runtime_error("sceAgcCreateShader: sh_registers missing for shader type requiring program address patch"); - } - - for (std::uint32_t i = 0; i < numRegs; ++i) { - if (regs[i].offset != loOffset) { - continue; - } - const std::uint32_t hiIndex = i + 1u; - if (hiIndex >= numRegs || regs[hiIndex].offset != loOffset + 1u) { - throw std::runtime_error("sceAgcCreateShader: shader program address hi register missing"); - } - const std::uint64_t shaderOffset = - (static_cast(regs[i].value) << 8u) | - ((static_cast(regs[hiIndex].value) & 0xFFu) << 40u); - const std::uint64_t addr = base + shaderOffset; - regs[i].value = static_cast((addr >> 8u) & 0xFFFFFFFFu); - regs[hiIndex].value &= 0xFFFFFF00u; - regs[hiIndex].value |= static_cast((addr >> 40u) & 0xFFu); - return 0; - } - - throw std::runtime_error("sceAgcCreateShader: shader program address lo register not found"); -} - -static std::uint32_t _graphicsPrimTypeToGsOut(std::uint32_t primType) { - switch (static_cast(primType)) { - case PrimitiveType::PointList: - return static_cast(GsOutputPrimitiveType::Points); - case PrimitiveType::LineList: - case PrimitiveType::LineStrip: - case PrimitiveType::LineListAdjacency: - case PrimitiveType::LineStripAdjacency: - case PrimitiveType::LineLoop: - return static_cast(GsOutputPrimitiveType::Lines); - case PrimitiveType::RectList: - return static_cast(GsOutputPrimitiveType::Rectangle2D); - case PrimitiveType::RectListLegacy: - return static_cast(GsOutputPrimitiveType::RectList); - default: - return static_cast(GsOutputPrimitiveType::Triangles); - } -} - -static std::uint32_t _shaderSemanticWord(const ShaderSemantic& s) { - return ((s.semantic & 0xFFu) << 0u) - | ((s.hardware_mapping & 0xFFu) << 8u) - | ((s.size_in_elements & 0xFu) << 16u) - | ((s.is_f16 & 0x3u) << 20u) - | ((s.is_flat_shaded & 0x1u) << 22u) - | ((s.is_linear & 0x1u) << 23u) - | ((s.is_custom & 0x1u) << 24u) - | ((s.static_vb_index & 0x1u) << 25u) - | ((s.static_attribute & 0x1u) << 26u) - | ((s.reserved & 0x1u) << 27u) - | ((s.default_value & 0x3u) << 28u) - | ((s.default_value_hi & 0x3u) << 30u); -} - -static std::uint32_t _applyInterpolantDefaultValue(std::uint32_t value, std::uint32_t psWord) { - value &= ~0x00000300u; - value |= ((psWord >> 28u) & 0x3u) << 8u; - return value; -} - -static std::uint32_t _applyInterpolantDefaultValueHi(std::uint32_t value, std::uint32_t psWord) { - value &= ~0x00600000u; - value |= ((psWord >> 30u) & 0x3u) << 21u; - return value; -} - -static std::uint32_t _createInterpolantF16Value(std::uint32_t psWord, const ShaderSemantic* gsSemantic) { - std::uint32_t value = (psWord << 4u) & 0x03000000u; - if (gsSemantic == nullptr) { - value |= 0x00180020u; - } else { - const std::uint32_t commonWord = psWord & _shaderSemanticWord(*gsSemantic); - value &= 0xFFF7FFDFu; - value |= (commonWord >> 15u) & 0x20u; - value ^= 0x00080020u; - value &= ~0x00100000u; - value |= (~commonWord >> 1u) & 0x00100000u; - } - return _applyInterpolantDefaultValueHi(value, psWord); -} - -static std::uint32_t _createInterpolantNonF16Value(std::uint32_t psWord, const ShaderSemantic* gsSemantic) { - std::uint32_t value = 0; - if ((psWord & 0x01000000u) != 0 || gsSemantic == nullptr) { - value |= 0x20u; - } - return value; -} - -static std::uint32_t _createInterpolantMappingValue(std::uint32_t value, std::uint32_t psWord, std::uint32_t gsWord) { - const std::uint32_t flatShade = - ((psWord & 0x00400000u) != 0 || (psWord & 0x01000000u) != 0) ? 0x00000400u : 0u; - value &= ~0x0000001Fu; - value |= (gsWord >> 8u) & 0x1Fu; - value &= ~0x00000400u; - value |= flatShade; - return _applyInterpolantDefaultValue(value, psWord); -} - -static std::uint32_t _createInterpolantDefaultValue(std::uint32_t value, std::uint32_t psWord) { - value &= ~0x0000001Fu; - value &= ~0x00000400u; - return _applyInterpolantDefaultValue(value, psWord); -} - -static const ShaderSemantic* _findOutputSemantic(const Shader* gs, std::uint32_t semantic) { - if (gs == nullptr || gs->output_semantics == nullptr) { - return nullptr; - } - for (std::uint16_t i = 0; i < gs->num_output_semantics; ++i) { - if (gs->output_semantics[i].semantic == semantic) { - return &gs->output_semantics[i]; - } - } - return nullptr; -} - -static void _setInterpolantRegister(ShaderRegister* regs, std::uint32_t index, std::uint32_t value) { - regs[index].offset = SPI_PS_INPUT_CNTL_0 + index; - regs[index].value = value; -} - -static void _fillIdentityInterpolants(ShaderRegister* regs, std::uint32_t firstIndex) { - for (std::uint32_t i = firstIndex; i < 32u; ++i) { - _setInterpolantRegister(regs, i, i); - } -} - -} - extern "C" { int sceAgcCreateShader(Shader** dst, void* header, const volatile void* code) { + constexpr auto fn = __func__; if (dst == nullptr) { - throw std::runtime_error("sceAgcCreateShader: dst is null"); + throw std::runtime_error(std::string(fn) + ": dst is null"); } if (header == nullptr) { - throw std::runtime_error("sceAgcCreateShader: header is null"); + throw std::runtime_error(std::string(fn) + ": header is null"); } if (code == nullptr) { - throw std::runtime_error("sceAgcCreateShader: code is null"); + throw std::runtime_error(std::string(fn) + ": code is null"); } auto* h = static_cast(header); - _resolveRelativePtr(h->cx_registers); - _resolveRelativePtr(h->sh_registers); - _resolveRelativePtr(h->user_data); - _resolveRelativePtr(h->specials); - _resolveRelativePtr(h->input_semantics); - _resolveRelativePtr(h->output_semantics); + ResolveRelativePtr(h->cx_registers); + ResolveRelativePtr(h->sh_registers); + ResolveRelativePtr(h->user_data); + ResolveRelativePtr(h->specials); + ResolveRelativePtr(h->input_semantics); + ResolveRelativePtr(h->output_semantics); if (h->user_data != nullptr) { - _resolveRelativePtr(h->user_data->direct_resource_offset); - _resolveRelativePtr(h->user_data->sharp_resource_offset[0]); - _resolveRelativePtr(h->user_data->sharp_resource_offset[1]); - _resolveRelativePtr(h->user_data->sharp_resource_offset[2]); - _resolveRelativePtr(h->user_data->sharp_resource_offset[3]); + ResolveRelativePtr(h->user_data->direct_resource_offset); + ResolveRelativePtr(h->user_data->sharp_resource_offset[0]); + ResolveRelativePtr(h->user_data->sharp_resource_offset[1]); + ResolveRelativePtr(h->user_data->sharp_resource_offset[2]); + ResolveRelativePtr(h->user_data->sharp_resource_offset[3]); } h->code = code; if (h->file_header != ShaderRegs::SHADER_FILE_HEADER_MAGIC) { - throw std::runtime_error("sceAgcCreateShader: invalid file_header magic"); + throw std::runtime_error(std::string(fn) + ": invalid file_header magic"); } if (h->version != ShaderRegs::SHADER_VERSION) { - throw std::runtime_error("sceAgcCreateShader: unsupported shader version"); + throw std::runtime_error(std::string(fn) + ": unsupported shader version"); } const auto base = reinterpret_cast(code); if ((base & ShaderRegs::SHADER_BASE_ALIGN_MASK) != 0) { - throw std::runtime_error("sceAgcCreateShader: code address violates alignment mask"); + throw std::runtime_error(std::string(fn) + ": code address violates alignment mask"); } - int result = _patchProgramAddressRegister(h->sh_registers, h->num_sh_registers, h->type, base); + int result = PatchProgramAddressRegister(h->sh_registers, h->num_sh_registers, h->type, base); if (result != 0) { return result; } *dst = h; + APS5_LOG_OUT("OK type=%u sh_regs=%u shader_size=%u", h->type, h->num_sh_registers, h->shader_size); return 0; } @@ -231,7 +67,7 @@ int sceAgcCreatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs, cons return 0; } if (gs == nullptr) { - throw std::runtime_error("sceAgcCreatePrimState: gs is null"); + throw std::runtime_error(std::string(__func__) + ": gs is null"); } if (cx_regs != nullptr) { @@ -240,7 +76,7 @@ int sceAgcCreatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs, cons cx_regs[1] = gs->specials->vgt_gs_out_prim_type; } else { cx_regs[1].offset = ShaderRegs::VGT_GS_OUT_PRIM_TYPE; - cx_regs[1].value = _graphicsPrimTypeToGsOut(prim_type); + cx_regs[1].value = GraphicsPrimTypeToGsOut(prim_type); } if (hs != nullptr) { @@ -262,13 +98,14 @@ int sceAgcCreatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs, cons } } + APS5_LOG_OUT("OK prim_type=%u", prim_type); return 0; } int sceAgcUpdatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs, std::uint32_t prim_type) { if (cx_regs != nullptr && (cx_regs[0].value & (ShaderRegs::VGT_SHADER_STAGES_GS_BIT | ShaderRegs::VGT_SHADER_STAGES_NGG_BIT)) == 0) { cx_regs[1].value &= ~0x7u; - cx_regs[1].value |= _graphicsPrimTypeToGsOut(prim_type); + cx_regs[1].value |= GraphicsPrimTypeToGsOut(prim_type); } if (uc_regs != nullptr) { @@ -276,49 +113,53 @@ int sceAgcUpdatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs, std: uc_regs[2].value |= prim_type; } + APS5_LOG_OUT("OK prim_type=%u", prim_type); return 0; } int sceAgcCreateInterpolantMapping(ShaderRegister* regs, const Shader* gs, const Shader* ps) { + constexpr auto fn = __func__; if (regs == nullptr) { - throw std::runtime_error("sceAgcCreateInterpolantMapping: regs is null"); + throw std::runtime_error(std::string(fn) + ": regs is null"); } if (ps == nullptr || ps->num_input_semantics == 0) { - _fillIdentityInterpolants(regs, 0); + FillIdentityInterpolants(regs, 0); + APS5_LOG_CHARS_OUT("OK identity ps_inputs=0"); return 0; } if (ps->num_input_semantics != 0 && ps->input_semantics == nullptr) { - throw std::runtime_error("sceAgcCreateInterpolantMapping: ps->input_semantics is null but num_input_semantics != 0"); + throw std::runtime_error(std::string(fn) + ": ps->input_semantics is null but num_input_semantics != 0"); } if (gs == nullptr) { - throw std::runtime_error("sceAgcCreateInterpolantMapping: gs is null"); + throw std::runtime_error(std::string(fn) + ": gs is null"); } if (gs->num_output_semantics != 0 && gs->output_semantics == nullptr) { - throw std::runtime_error("sceAgcCreateInterpolantMapping: gs->output_semantics is null but num_output_semantics != 0"); + throw std::runtime_error(std::string(fn) + ": gs->output_semantics is null but num_output_semantics != 0"); } for (std::uint32_t i = 0; i < ps->num_input_semantics; ++i) { const ShaderSemantic& psSemantic = ps->input_semantics[i]; - const ShaderSemantic* gsSemantic = _findOutputSemantic(gs, psSemantic.semantic); - const std::uint32_t psWord = _shaderSemanticWord(psSemantic); + const ShaderSemantic* gsSemantic = FindOutputSemantic(gs, psSemantic.semantic); + const std::uint32_t psWord = ShaderSemanticWord(psSemantic); std::uint32_t value = ((psWord & 0x00300000u) != 0) - ? _createInterpolantF16Value(psWord, gsSemantic) - : _createInterpolantNonF16Value(psWord, gsSemantic); + ? CreateInterpolantF16Value(psWord, gsSemantic) + : CreateInterpolantNonF16Value(psWord, gsSemantic); value = (gsSemantic == nullptr) - ? _createInterpolantDefaultValue(value, psWord) - : _createInterpolantMappingValue(value, psWord, _shaderSemanticWord(*gsSemantic)); + ? CreateInterpolantDefaultValue(value, psWord) + : CreateInterpolantMappingValue(value, psWord, ShaderSemanticWord(*gsSemantic)); - _setInterpolantRegister(regs, i, value); + SetInterpolantRegister(regs, i, value); } - _fillIdentityInterpolants(regs, ps->num_input_semantics); + FillIdentityInterpolants(regs, ps->num_input_semantics); + APS5_LOG_OUT("OK ps_inputs=%u gs_outputs=%u", ps->num_input_semantics, gs->num_output_semantics); return 0; } -} // extern "C" +} diff --git a/core/libs/prx/libSceAgc/Shader/ShaderUtils.cpp b/core/libs/prx/libSceAgc/Shader/ShaderUtils.cpp new file mode 100644 index 000000000..a38969dc5 --- /dev/null +++ b/core/libs/prx/libSceAgc/Shader/ShaderUtils.cpp @@ -0,0 +1,152 @@ +#include +#include "ShaderUtils.hpp" + +using namespace ShaderRegs; + +bool GetProgramAddressRegisterOffset(std::uint8_t type, std::uint32_t& loOffset) { + switch (static_cast(type)) { + case ShaderBinaryType::Cs: loOffset = COMPUTE_PGM_LO; return true; + case ShaderBinaryType::Ps: loOffset = SPI_SHADER_PGM_LO_PS; return true; + case ShaderBinaryType::Gs: loOffset = SPI_SHADER_PGM_LO_ES; return true; + case ShaderBinaryType::Hs: loOffset = SPI_SHADER_PGM_LO_LS; return true; + case ShaderBinaryType::GsBack: loOffset = SPI_SHADER_PGM_LO_GS; return true; + case ShaderBinaryType::HsBack: loOffset = SPI_SHADER_PGM_LO_HS; return true; + default: return false; + } +} + +int PatchProgramAddressRegister(ShaderRegister* regs, std::uint32_t numRegs, std::uint8_t type, std::uint64_t base) { + std::uint32_t loOffset = 0; + if (!GetProgramAddressRegisterOffset(type, loOffset)) { + return 0; + } + if (regs == nullptr || numRegs == 0) { + throw std::runtime_error("sceAgcCreateShader: sh_registers missing for shader type requiring program address patch"); + } + for (std::uint32_t i = 0; i < numRegs; ++i) { + if (regs[i].offset != loOffset) { + continue; + } + const std::uint32_t hiIndex = i + 1u; + if (hiIndex >= numRegs || regs[hiIndex].offset != loOffset + 1u) { + throw std::runtime_error("sceAgcCreateShader: shader program address hi register missing"); + } + const std::uint64_t shaderOffset = + (static_cast(regs[i].value) << 8u) | + ((static_cast(regs[hiIndex].value) & 0xFFu) << 40u); + const std::uint64_t addr = base + shaderOffset; + regs[i].value = static_cast((addr >> 8u) & 0xFFFFFFFFu); + regs[hiIndex].value &= 0xFFFFFF00u; + regs[hiIndex].value |= static_cast((addr >> 40u) & 0xFFu); + return 0; + } + throw std::runtime_error("sceAgcCreateShader: shader program address lo register not found"); +} + +std::uint32_t GraphicsPrimTypeToGsOut(std::uint32_t primType) { + switch (static_cast(primType)) { + case PrimitiveType::PointList: + return static_cast(GsOutputPrimitiveType::Points); + case PrimitiveType::LineList: + case PrimitiveType::LineStrip: + case PrimitiveType::LineListAdjacency: + case PrimitiveType::LineStripAdjacency: + case PrimitiveType::LineLoop: + return static_cast(GsOutputPrimitiveType::Lines); + case PrimitiveType::RectList: + return static_cast(GsOutputPrimitiveType::Rectangle2D); + case PrimitiveType::RectListLegacy: + return static_cast(GsOutputPrimitiveType::RectList); + default: + return static_cast(GsOutputPrimitiveType::Triangles); + } +} + +std::uint32_t ShaderSemanticWord(const ShaderSemantic& s) { + return ((s.semantic & 0xFFu) << 0u) + | ((s.hardware_mapping & 0xFFu) << 8u) + | ((s.size_in_elements & 0xFu) << 16u) + | ((s.is_f16 & 0x3u) << 20u) + | ((s.is_flat_shaded & 0x1u) << 22u) + | ((s.is_linear & 0x1u) << 23u) + | ((s.is_custom & 0x1u) << 24u) + | ((s.static_vb_index & 0x1u) << 25u) + | ((s.static_attribute & 0x1u) << 26u) + | ((s.reserved & 0x1u) << 27u) + | ((s.default_value & 0x3u) << 28u) + | ((s.default_value_hi & 0x3u) << 30u); +} + +std::uint32_t ApplyInterpolantDefaultValue(std::uint32_t value, std::uint32_t psWord) { + value &= ~0x00000300u; + value |= ((psWord >> 28u) & 0x3u) << 8u; + return value; +} + +std::uint32_t ApplyInterpolantDefaultValueHi(std::uint32_t value, std::uint32_t psWord) { + value &= ~0x00600000u; + value |= ((psWord >> 30u) & 0x3u) << 21u; + return value; +} + +std::uint32_t CreateInterpolantF16Value(std::uint32_t psWord, const ShaderSemantic* gsSemantic) { + std::uint32_t value = (psWord << 4u) & 0x03000000u; + if (gsSemantic == nullptr) { + value |= 0x00180020u; + } else { + const std::uint32_t commonWord = psWord & ShaderSemanticWord(*gsSemantic); + value &= 0xFFF7FFDFu; + value |= (commonWord >> 15u) & 0x20u; + value ^= 0x00080020u; + value &= ~0x00100000u; + value |= (~commonWord >> 1u) & 0x00100000u; + } + return ApplyInterpolantDefaultValueHi(value, psWord); +} + +std::uint32_t CreateInterpolantNonF16Value(std::uint32_t psWord, const ShaderSemantic* gsSemantic) { + std::uint32_t value = 0; + if ((psWord & 0x01000000u) != 0 || gsSemantic == nullptr) { + value |= 0x20u; + } + return value; +} + +std::uint32_t CreateInterpolantMappingValue(std::uint32_t value, std::uint32_t psWord, std::uint32_t gsWord) { + const std::uint32_t flatShade = + ((psWord & 0x00400000u) != 0 || (psWord & 0x01000000u) != 0) ? 0x00000400u : 0u; + value &= ~0x0000001Fu; + value |= (gsWord >> 8u) & 0x1Fu; + value &= ~0x00000400u; + value |= flatShade; + return ApplyInterpolantDefaultValue(value, psWord); +} + +std::uint32_t CreateInterpolantDefaultValue(std::uint32_t value, std::uint32_t psWord) { + value &= ~0x0000001Fu; + value &= ~0x00000400u; + return ApplyInterpolantDefaultValue(value, psWord); +} + +const ShaderSemantic* FindOutputSemantic(const Shader* gs, std::uint32_t semantic) { + if (gs == nullptr || gs->output_semantics == nullptr) { + return nullptr; + } + for (std::uint16_t i = 0; i < gs->num_output_semantics; ++i) { + if (gs->output_semantics[i].semantic == semantic) { + return &gs->output_semantics[i]; + } + } + return nullptr; +} + +void SetInterpolantRegister(ShaderRegister* regs, std::uint32_t index, std::uint32_t value) { + regs[index].offset = SPI_PS_INPUT_CNTL_0 + index; + regs[index].value = value; +} + +void FillIdentityInterpolants(ShaderRegister* regs, std::uint32_t firstIndex) { + for (std::uint32_t i = firstIndex; i < 32u; ++i) { + SetInterpolantRegister(regs, i, i); + } +} diff --git a/core/libs/prx/libSceAgc/Shader/ShaderUtils.hpp b/core/libs/prx/libSceAgc/Shader/ShaderUtils.hpp new file mode 100644 index 000000000..39f1b3b5d --- /dev/null +++ b/core/libs/prx/libSceAgc/Shader/ShaderUtils.hpp @@ -0,0 +1,32 @@ +#ifndef CORE_LIBS_LIBSCEAGC_SHADER_UTILS_HPP +#define CORE_LIBS_LIBSCEAGC_SHADER_UTILS_HPP + +#include +#include "SceShaders.hpp" +#include "ShaderConstants.hpp" + +template +void ResolveRelativePtr(T*& field) { + if (field == nullptr) { + return; + } + field = reinterpret_cast( + reinterpret_cast(field) + reinterpret_cast(&field) + ); +} + +bool GetProgramAddressRegisterOffset(std::uint8_t type, std::uint32_t& loOffset); +int PatchProgramAddressRegister(ShaderRegister* regs, std::uint32_t numRegs, std::uint8_t type, std::uint64_t base); +std::uint32_t GraphicsPrimTypeToGsOut(std::uint32_t primType); +std::uint32_t ShaderSemanticWord(const ShaderSemantic& s); +std::uint32_t ApplyInterpolantDefaultValue(std::uint32_t value, std::uint32_t psWord); +std::uint32_t ApplyInterpolantDefaultValueHi(std::uint32_t value, std::uint32_t psWord); +std::uint32_t CreateInterpolantF16Value(std::uint32_t psWord, const ShaderSemantic* gsSemantic); +std::uint32_t CreateInterpolantNonF16Value(std::uint32_t psWord, const ShaderSemantic* gsSemantic); +std::uint32_t CreateInterpolantMappingValue(std::uint32_t value, std::uint32_t psWord, std::uint32_t gsWord); +std::uint32_t CreateInterpolantDefaultValue(std::uint32_t value, std::uint32_t psWord); +const ShaderSemantic* FindOutputSemantic(const Shader* gs, std::uint32_t semantic); +void SetInterpolantRegister(ShaderRegister* regs, std::uint32_t index, std::uint32_t value); +void FillIdentityInterpolants(ShaderRegister* regs, std::uint32_t firstIndex); + +#endif diff --git a/core/libs/prx/libc/Export.cpp b/core/libs/prx/libc/Export.cpp index 5972ab5aa..fe709d61d 100644 --- a/core/libs/prx/libc/Export.cpp +++ b/core/libs/prx/libc/Export.cpp @@ -23,20 +23,24 @@ extern "C" { void init_env_nid_postfix(const InitEnvParams* params) { (void)params; + NotImplemented_nid_no_patch(__func__); } void catchReturnFromMain_nid_postfix(int status) { (void)status; + NotImplemented_nid_no_patch(__func__); } int cxa_atexit_nid_postfix(void (*func)(void*), void* arg, void* d) { (void)func; (void)arg; (void)d; + NotImplemented_nid_no_patch(__func__); return 0; } void cxa_finalize_nid_postfix(void* d) { + NotImplemented_nid_no_patch(__func__); (void)d; } @@ -44,17 +48,20 @@ extern "C" { (void)flag; (void)func; (void)arg; + NotImplemented_nid_no_patch(__func__); return 0; } void LibcHeapGetTraceInfo_nid_postfix(LibcHeapInfo* info) { (void)info; + NotImplemented_nid_no_patch(__func__); } int LibcInternalExtCxaThreadAtexit_nid_postfix(void (*destructor)(void*), void* object, void* module_id) { (void)destructor; (void)object; (void)module_id; + NotImplemented_nid_no_patch(__func__); return 0; } @@ -64,6 +71,7 @@ extern "C" { ) { (void)msp; (void)ptr; (void)error; (void)arg3; (void)arg4; (void)arg5; + NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/prx/libc/include/General.hpp b/core/libs/prx/libc/include/General.hpp index 7eac4b651..df95d82b7 100644 --- a/core/libs/prx/libc/include/General.hpp +++ b/core/libs/prx/libc/include/General.hpp @@ -1,6 +1,46 @@ #ifndef CORE_LIBS_PRX_LIBC_INCLUDE_GENERAL_HPP #define CORE_LIBS_PRX_LIBC_INCLUDE_GENERAL_HPP +#include extern "C" void NotImplemented_nid_no_patch(const char* funcName); +inline const char* TrimNidPostfix(const char* func) { + return func; + const char* pos = std::strstr(func, "_nid_postfix"); + if (pos != nullptr) { + static thread_local char buf[256]; + const std::size_t len = static_cast(pos - func); + std::memcpy(buf, func, len); + buf[len] = '\0'; + return buf; + } + return func; +} + +constexpr const char* BaseName(const char* path) { + const char* last = path; + const char* prev = nullptr; + for (const char* p = path; *p; ++p) + if (*p == '/' || *p == '\\') { + prev = last; + last = p + 1; + } + return (prev && *prev) ? prev : last; +} + +#define _APS5_FILE_ BaseName(__FILE__) + +#define _APS5_LOG_IMPL(stream, fmt, ...) \ +(std::fprintf(stream, "[%s:%d %s] " fmt "\n", _APS5_FILE_, __LINE__, TrimNidPostfix(__func__), __VA_ARGS__), \ +std::fflush(stream)) + +#define _APS5_LOG_IMPL_NF(stream, fmt) \ +(std::fprintf(stream, "[%s:%d %s] " fmt "\n", _APS5_FILE_, __LINE__, TrimNidPostfix(__func__)), \ +std::fflush(stream)) + +#define APS5_LOG_OUT(fmt, ...) _APS5_LOG_IMPL(stdout, fmt, __VA_ARGS__) +#define APS5_LOG_ERR(fmt, ...) _APS5_LOG_IMPL(stderr, fmt, __VA_ARGS__) +#define APS5_LOG_CHARS_OUT(fmt) _APS5_LOG_IMPL_NF(stdout, fmt) +#define APS5_LOG_CHARS_ERR(fmt) _APS5_LOG_IMPL_NF(stderr, fmt) + #endif diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index be89114e7..8f2673d29 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -23,7 +23,7 @@ FileStream* fopen_nid_postfix(const char* filename, const char* mode) { auto stream = std::make_unique(handle.get(), true); handle.release(); - std::fprintf(stderr, "fopen success: \"%s\"\n", filename); + APS5_LOG_OUT("success: \"%s\"", filename); return stream.release(); } diff --git a/core/libs/prx/libc/src/Strings.cpp b/core/libs/prx/libc/src/Strings.cpp index c103088a3..24e68679f 100644 --- a/core/libs/prx/libc/src/Strings.cpp +++ b/core/libs/prx/libc/src/Strings.cpp @@ -8,7 +8,7 @@ extern "C" { void* memset_nid_postfix(void* s, int c, size_t n) { - fprintf(stderr, "memset_nid_postfix: s=%p c=%d n=%zu\n", s, c, n); + APS5_LOG_OUT("s=%p c=%d n=%zu", s, c, n); return std::memset(s, c, n); }