mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-02 07:22:24 +00:00
Merge branch 'shadps4-emu:main' into set_pc
This commit is contained in:
commit
b005ddd426
@ -200,7 +200,14 @@ execute_process(
|
|||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
set(APP_VERSION "0.7.1 WIP")
|
# Set Version
|
||||||
|
set(EMULATOR_VERSION_MAJOR "0")
|
||||||
|
set(EMULATOR_VERSION_MINOR "7")
|
||||||
|
set(EMULATOR_VERSION_PATCH "1")
|
||||||
|
|
||||||
|
set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}")
|
||||||
|
|
||||||
|
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP")
|
||||||
set(APP_IS_RELEASE false)
|
set(APP_IS_RELEASE false)
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
||||||
|
|
||||||
@ -563,6 +570,8 @@ set(NP_LIBS src/core/libraries/np_common/np_common.cpp
|
|||||||
src/core/libraries/np_web_api/np_web_api.h
|
src/core/libraries/np_web_api/np_web_api.h
|
||||||
src/core/libraries/np_party/np_party.cpp
|
src/core/libraries/np_party/np_party.cpp
|
||||||
src/core/libraries/np_party/np_party.h
|
src/core/libraries/np_party/np_party.h
|
||||||
|
src/core/libraries/np_auth/np_auth.cpp
|
||||||
|
src/core/libraries/np_auth/np_auth.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||||
|
13
README.md
13
README.md
@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
|
|
||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
<a href="https://discord.gg/bFJxfftGW6">
|
<a href="https://discord.gg/bFJxfftGW6">
|
||||||
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4 Discord&logo=Discord&logoColor=white" width="240">
|
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4%20Discord&logo=Discord&logoColor=white" width="275">
|
||||||
<a href="https://github.com/shadps4-emu/shadPS4/releases/latest">
|
<a href="https://github.com/shadps4-emu/shadPS4/releases/latest">
|
||||||
<img src="https://img.shields.io/github/downloads/shadps4-emu/shadPS4/total.svg" width="140">
|
<img src="https://img.shields.io/github/downloads/shadps4-emu/shadPS4/total.svg" width="140">
|
||||||
<a href="https://shadps4.net/">
|
<a href="https://shadps4.net/">
|
||||||
@ -146,16 +146,13 @@ The following firmware modules are supported and must be placed in shadPS4's `us
|
|||||||
# Main team
|
# Main team
|
||||||
|
|
||||||
- [**georgemoralis**](https://github.com/georgemoralis)
|
- [**georgemoralis**](https://github.com/georgemoralis)
|
||||||
- [**raphaelthegreat**](https://github.com/raphaelthegreat)
|
|
||||||
- [**psucien**](https://github.com/psucien)
|
- [**psucien**](https://github.com/psucien)
|
||||||
- [**skmp**](https://github.com/skmp)
|
|
||||||
- [**wheremyfoodat**](https://github.com/wheremyfoodat)
|
|
||||||
- [**raziel1000**](https://github.com/raziel1000)
|
|
||||||
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
||||||
- [**roamic**](https://github.com/vladmikhalin)
|
- [**roamic**](https://github.com/vladmikhalin)
|
||||||
- [**poly**](https://github.com/polybiusproxy)
|
|
||||||
- [**squidbus**](https://github.com/squidbus)
|
- [**squidbus**](https://github.com/squidbus)
|
||||||
- [**frodo**](https://github.com/baggins183)
|
- [**frodo**](https://github.com/baggins183)
|
||||||
|
- [**Stephen Miller**](https://github.com/StevenMiller123)
|
||||||
|
- [**kalaposfos13**](https://github.com/kalaposfos13)
|
||||||
|
|
||||||
Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
||||||
|
|
||||||
@ -166,11 +163,11 @@ Open a PR and we'll check it :)
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
|
|
||||||
If you want to translate shadPS4 to your language we use [**crowdin**](https://crowdin.com/project/shadps4-emulator).
|
If you want to translate shadPS4 to your language we use [**Crowdin**](https://crowdin.com/project/shadps4-emulator).
|
||||||
# Contributors
|
# Contributors
|
||||||
|
|
||||||
<a href="https://github.com/shadps4-emu/shadPS4/graphs/contributors">
|
<a href="https://github.com/shadps4-emu/shadPS4/graphs/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=15">
|
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=24">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, Ssl2) \
|
SUB(Lib, Ssl2) \
|
||||||
SUB(Lib, SysModule) \
|
SUB(Lib, SysModule) \
|
||||||
SUB(Lib, Move) \
|
SUB(Lib, Move) \
|
||||||
|
SUB(Lib, NpAuth) \
|
||||||
SUB(Lib, NpCommon) \
|
SUB(Lib, NpCommon) \
|
||||||
SUB(Lib, NpManager) \
|
SUB(Lib, NpManager) \
|
||||||
SUB(Lib, NpScore) \
|
SUB(Lib, NpScore) \
|
||||||
|
@ -69,6 +69,7 @@ enum class Class : u8 {
|
|||||||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||||
|
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||||
|
@ -2804,7 +2804,7 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
|
|||||||
liverpool = std::make_unique<AmdGpu::Liverpool>();
|
liverpool = std::make_unique<AmdGpu::Liverpool>();
|
||||||
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());
|
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());
|
||||||
|
|
||||||
const int result = sceKernelGetCompiledSdkVersion(&sdk_version);
|
const s32 result = sceKernelGetCompiledSdkVersion(&sdk_version);
|
||||||
if (result != ORBIS_OK) {
|
if (result != ORBIS_OK) {
|
||||||
sdk_version = 0;
|
sdk_version = 0;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
|
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
|
||||||
LOG_WARNING(Kernel_Vmm, "called");
|
LOG_TRACE(Kernel_Vmm, "called");
|
||||||
const auto* memory = Core::Memory::Instance();
|
const auto* memory = Core::Memory::Instance();
|
||||||
return memory->GetTotalDirectSize();
|
return memory->GetTotalDirectSize();
|
||||||
}
|
}
|
||||||
@ -106,12 +106,6 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
|
|||||||
if (physAddrOut == nullptr || sizeOut == nullptr) {
|
if (physAddrOut == nullptr || sizeOut == nullptr) {
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
if (searchEnd > sceKernelGetDirectMemorySize()) {
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
if (searchEnd <= searchStart) {
|
|
||||||
return ORBIS_KERNEL_ERROR_ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* memory = Core::Memory::Instance();
|
auto* memory = Core::Memory::Instance();
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "core/libraries/network/netctl.h"
|
#include "core/libraries/network/netctl.h"
|
||||||
#include "core/libraries/network/ssl.h"
|
#include "core/libraries/network/ssl.h"
|
||||||
#include "core/libraries/network/ssl2.h"
|
#include "core/libraries/network/ssl2.h"
|
||||||
|
#include "core/libraries/np_auth/np_auth.h"
|
||||||
#include "core/libraries/np_common/np_common.h"
|
#include "core/libraries/np_common/np_common.h"
|
||||||
#include "core/libraries/np_manager/np_manager.h"
|
#include "core/libraries/np_manager/np_manager.h"
|
||||||
#include "core/libraries/np_party/np_party.h"
|
#include "core/libraries/np_party/np_party.h"
|
||||||
@ -88,6 +89,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||||||
Libraries::NpScore::RegisterlibSceNpScore(sym);
|
Libraries::NpScore::RegisterlibSceNpScore(sym);
|
||||||
Libraries::NpTrophy::RegisterlibSceNpTrophy(sym);
|
Libraries::NpTrophy::RegisterlibSceNpTrophy(sym);
|
||||||
Libraries::NpWebApi::RegisterlibSceNpWebApi(sym);
|
Libraries::NpWebApi::RegisterlibSceNpWebApi(sym);
|
||||||
|
Libraries::NpAuth::RegisterlibSceNpAuth(sym);
|
||||||
Libraries::ScreenShot::RegisterlibSceScreenShot(sym);
|
Libraries::ScreenShot::RegisterlibSceScreenShot(sym);
|
||||||
Libraries::AppContent::RegisterlibSceAppContent(sym);
|
Libraries::AppContent::RegisterlibSceAppContent(sym);
|
||||||
Libraries::PngDec::RegisterlibScePngDec(sym);
|
Libraries::PngDec::RegisterlibScePngDec(sym);
|
||||||
|
99
src/core/libraries/np_auth/np_auth.cpp
Normal file
99
src/core/libraries/np_auth/np_auth.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
#include "core/libraries/libs.h"
|
||||||
|
#include "core/libraries/np_auth/np_auth.h"
|
||||||
|
|
||||||
|
namespace Libraries::NpAuth {
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCode() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetIdToken() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthAbortRequest() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthCreateAsyncRequest() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthCreateRequest() {
|
||||||
|
LOG_WARNING(Lib_NpAuth, "(DUMMY) called");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 id) {
|
||||||
|
LOG_WARNING(Lib_NpAuth, "(DUMMY) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeA() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeV3() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenA() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenV3() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthPollAsync() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthSetTimeout() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthWaitAsync() {
|
||||||
|
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1,
|
||||||
|
sceNpAuthGetAuthorizationCode);
|
||||||
|
LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken);
|
||||||
|
LIB_FUNCTION("cE7wIsqXdZ8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthAbortRequest);
|
||||||
|
LIB_FUNCTION("N+mr7GjTvr8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
|
||||||
|
sceNpAuthCreateAsyncRequest);
|
||||||
|
LIB_FUNCTION("6bwFkosYRQg", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthCreateRequest);
|
||||||
|
LIB_FUNCTION("H8wG9Bk-nPc", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthDeleteRequest);
|
||||||
|
LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
|
||||||
|
sceNpAuthGetAuthorizationCode);
|
||||||
|
LIB_FUNCTION("qAUXQ9GdWp8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
|
||||||
|
sceNpAuthGetAuthorizationCodeA);
|
||||||
|
LIB_FUNCTION("KI4dHLlTNl0", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
|
||||||
|
sceNpAuthGetAuthorizationCodeV3);
|
||||||
|
LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken);
|
||||||
|
LIB_FUNCTION("CocbHVIKPE8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdTokenA);
|
||||||
|
LIB_FUNCTION("RdsFVsgSpZY", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdTokenV3);
|
||||||
|
LIB_FUNCTION("gjSyfzSsDcE", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthPollAsync);
|
||||||
|
LIB_FUNCTION("PM3IZCw-7m0", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthSetTimeout);
|
||||||
|
LIB_FUNCTION("SK-S7daqJSE", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthWaitAsync);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::NpAuth
|
29
src/core/libraries/np_auth/np_auth.h
Normal file
29
src/core/libraries/np_auth/np_auth.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
namespace Core::Loader {
|
||||||
|
class SymbolsResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Libraries::NpAuth {
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCode();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetIdToken();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthAbortRequest();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthCreateAsyncRequest();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthCreateRequest();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 id);
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeA();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeV3();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenA();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenV3();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthPollAsync();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthSetTimeout();
|
||||||
|
s32 PS4_SYSV_ABI sceNpAuthWaitAsync();
|
||||||
|
|
||||||
|
void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym);
|
||||||
|
} // namespace Libraries::NpAuth
|
@ -108,8 +108,8 @@ void Linker::Execute(const std::vector<std::string> args) {
|
|||||||
static constexpr s64 InternalMemorySize = 0x1000000;
|
static constexpr s64 InternalMemorySize = 0x1000000;
|
||||||
void* addr_out{reinterpret_cast<void*>(KernelAllocBase)};
|
void* addr_out{reinterpret_cast<void*>(KernelAllocBase)};
|
||||||
|
|
||||||
const s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(
|
s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(&addr_out, InternalMemorySize, 3,
|
||||||
&addr_out, InternalMemorySize, 3, 0, "SceKernelInternalMemory");
|
0, "SceKernelInternalMemory");
|
||||||
ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping");
|
ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping");
|
||||||
|
|
||||||
main_thread.Run([this, module, args](std::stop_token) {
|
main_thread.Run([this, module, args](std::stop_token) {
|
||||||
|
@ -139,35 +139,35 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
|
|||||||
alignment = alignment > 0 ? alignment : 16_KB;
|
alignment = alignment > 0 ? alignment : 16_KB;
|
||||||
|
|
||||||
auto dmem_area = FindDmemArea(search_start);
|
auto dmem_area = FindDmemArea(search_start);
|
||||||
|
auto mapping_start = search_start > dmem_area->second.base
|
||||||
|
? Common::AlignUp(search_start, alignment)
|
||||||
|
: Common::AlignUp(dmem_area->second.base, alignment);
|
||||||
|
auto mapping_end = Common::AlignUp(mapping_start + size, alignment);
|
||||||
|
|
||||||
const auto is_suitable = [&] {
|
// Find the first free, large enough dmem area in the range.
|
||||||
if (dmem_area == dmem_map.end()) {
|
while ((!dmem_area->second.is_free || dmem_area->second.GetEnd() < mapping_end) &&
|
||||||
return false;
|
dmem_area != dmem_map.end()) {
|
||||||
}
|
// The current dmem_area isn't suitable, move to the next one.
|
||||||
const auto aligned_base = Common::AlignUp(dmem_area->second.base, alignment);
|
dmem_area++;
|
||||||
const auto alignment_size = aligned_base - dmem_area->second.base;
|
|
||||||
const auto remaining_size =
|
// Update local variables based on the new dmem_area
|
||||||
dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0;
|
mapping_start = search_start > dmem_area->second.base
|
||||||
return dmem_area->second.is_free && remaining_size >= size;
|
? Common::AlignUp(search_start, alignment)
|
||||||
};
|
: Common::AlignUp(dmem_area->second.base, alignment);
|
||||||
while (dmem_area != dmem_map.end() && !is_suitable() &&
|
mapping_end = Common::AlignUp(mapping_start + size, alignment);
|
||||||
dmem_area->second.GetEnd() <= search_end) {
|
|
||||||
++dmem_area;
|
|
||||||
}
|
}
|
||||||
if (!is_suitable()) {
|
|
||||||
|
if (dmem_area == dmem_map.end()) {
|
||||||
|
// There are no suitable mappings in this range
|
||||||
LOG_ERROR(Kernel_Vmm, "Unable to find free direct memory area: size = {:#x}", size);
|
LOG_ERROR(Kernel_Vmm, "Unable to find free direct memory area: size = {:#x}", size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align free position
|
|
||||||
PAddr free_addr = dmem_area->second.base;
|
|
||||||
free_addr = Common::AlignUp(free_addr, alignment);
|
|
||||||
|
|
||||||
// Add the allocated region to the list and commit its pages.
|
// Add the allocated region to the list and commit its pages.
|
||||||
auto& area = CarveDmemArea(free_addr, size)->second;
|
auto& area = CarveDmemArea(mapping_start, size)->second;
|
||||||
area.memory_type = memory_type;
|
area.memory_type = memory_type;
|
||||||
area.is_free = false;
|
area.is_free = false;
|
||||||
return free_addr;
|
return mapping_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::Free(PAddr phys_addr, size_t size) {
|
void MemoryManager::Free(PAddr phys_addr, size_t size) {
|
||||||
@ -632,17 +632,34 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si
|
|||||||
auto dmem_area = FindDmemArea(search_start);
|
auto dmem_area = FindDmemArea(search_start);
|
||||||
PAddr paddr{};
|
PAddr paddr{};
|
||||||
size_t max_size{};
|
size_t max_size{};
|
||||||
while (dmem_area != dmem_map.end() && dmem_area->second.GetEnd() <= search_end) {
|
|
||||||
|
while (dmem_area != dmem_map.end()) {
|
||||||
if (!dmem_area->second.is_free) {
|
if (!dmem_area->second.is_free) {
|
||||||
dmem_area++;
|
dmem_area++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment)
|
auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment)
|
||||||
: dmem_area->second.base;
|
: dmem_area->second.base;
|
||||||
const auto alignment_size = aligned_base - dmem_area->second.base;
|
const auto alignment_size = aligned_base - dmem_area->second.base;
|
||||||
const auto remaining_size =
|
auto remaining_size =
|
||||||
dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0;
|
dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0;
|
||||||
|
|
||||||
|
if (dmem_area->second.base < search_start) {
|
||||||
|
// We need to trim remaining_size to ignore addresses before search_start
|
||||||
|
remaining_size = remaining_size > (search_start - dmem_area->second.base)
|
||||||
|
? remaining_size - (search_start - dmem_area->second.base)
|
||||||
|
: 0;
|
||||||
|
aligned_base = alignment > 0 ? Common::AlignUp(search_start, alignment) : search_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dmem_area->second.GetEnd() > search_end) {
|
||||||
|
// We need to trim remaining_size to ignore addresses beyond search_end
|
||||||
|
remaining_size = remaining_size > (dmem_area->second.GetEnd() - search_end)
|
||||||
|
? remaining_size - (dmem_area->second.GetEnd() - search_end)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (remaining_size > max_size) {
|
if (remaining_size > max_size) {
|
||||||
paddr = aligned_base;
|
paddr = aligned_base;
|
||||||
max_size = remaining_size;
|
max_size = remaining_size;
|
||||||
|
@ -127,58 +127,9 @@ tr("Do you want to overwrite existing mappings with the mappings from the Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
void KBMSettings::ButtonConnects() {
|
void KBMSettings::ButtonConnects() {
|
||||||
connect(ui->CrossButton, &QPushButton::clicked, this,
|
for (auto& button : ButtonsList) {
|
||||||
[this]() { StartTimer(ui->CrossButton); });
|
connect(button, &QPushButton::clicked, this, [this, &button]() { StartTimer(button); });
|
||||||
connect(ui->CircleButton, &QPushButton::clicked, this,
|
}
|
||||||
[this]() { StartTimer(ui->CircleButton); });
|
|
||||||
connect(ui->TriangleButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->TriangleButton); });
|
|
||||||
connect(ui->SquareButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->SquareButton); });
|
|
||||||
|
|
||||||
connect(ui->L1Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L1Button); });
|
|
||||||
connect(ui->L2Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L2Button); });
|
|
||||||
connect(ui->L3Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L3Button); });
|
|
||||||
connect(ui->R1Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R1Button); });
|
|
||||||
connect(ui->R2Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R2Button); });
|
|
||||||
connect(ui->R3Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R3Button); });
|
|
||||||
|
|
||||||
connect(ui->TouchpadButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->TouchpadButton); });
|
|
||||||
connect(ui->OptionsButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->OptionsButton); });
|
|
||||||
|
|
||||||
connect(ui->DpadUpButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->DpadUpButton); });
|
|
||||||
connect(ui->DpadDownButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->DpadDownButton); });
|
|
||||||
connect(ui->DpadLeftButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->DpadLeftButton); });
|
|
||||||
connect(ui->DpadRightButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->DpadRightButton); });
|
|
||||||
|
|
||||||
connect(ui->LStickUpButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->LStickUpButton); });
|
|
||||||
connect(ui->LStickDownButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->LStickDownButton); });
|
|
||||||
connect(ui->LStickLeftButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->LStickLeftButton); });
|
|
||||||
connect(ui->LStickRightButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->LStickRightButton); });
|
|
||||||
|
|
||||||
connect(ui->RStickUpButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->RStickUpButton); });
|
|
||||||
connect(ui->RStickDownButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->RStickDownButton); });
|
|
||||||
connect(ui->RStickLeftButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->RStickLeftButton); });
|
|
||||||
connect(ui->RStickRightButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->RStickRightButton); });
|
|
||||||
|
|
||||||
connect(ui->LHalfButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->LHalfButton); });
|
|
||||||
connect(ui->RHalfButton, &QPushButton::clicked, this,
|
|
||||||
[this]() { StartTimer(ui->RHalfButton); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KBMSettings::DisableMappingButtons() {
|
void KBMSettings::DisableMappingButtons() {
|
||||||
|
@ -106,8 +106,6 @@ public:
|
|||||||
|
|
||||||
toggleLabelsAct = new QAction(MainWindow);
|
toggleLabelsAct = new QAction(MainWindow);
|
||||||
toggleLabelsAct->setObjectName("toggleLabelsAct");
|
toggleLabelsAct->setObjectName("toggleLabelsAct");
|
||||||
toggleLabelsAct->setText(
|
|
||||||
QCoreApplication::translate("MainWindow", "Show Labels Under Icons"));
|
|
||||||
toggleLabelsAct->setCheckable(true);
|
toggleLabelsAct->setCheckable(true);
|
||||||
toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons());
|
toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons());
|
||||||
|
|
||||||
@ -413,6 +411,8 @@ public:
|
|||||||
setThemeTokyoNight->setText("Tokyo Night");
|
setThemeTokyoNight->setText("Tokyo Night");
|
||||||
setThemeOled->setText("OLED");
|
setThemeOled->setText("OLED");
|
||||||
toolBar->setWindowTitle(QCoreApplication::translate("MainWindow", "toolBar", nullptr));
|
toolBar->setWindowTitle(QCoreApplication::translate("MainWindow", "toolBar", nullptr));
|
||||||
|
toggleLabelsAct->setText(
|
||||||
|
QCoreApplication::translate("MainWindow", "Show Labels Under Icons"));
|
||||||
} // retranslateUi
|
} // retranslateUi
|
||||||
};
|
};
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -138,7 +138,7 @@
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>File Exists</source>
|
<source>File Exists</source>
|
||||||
<translation>Il file è presente</translation>
|
<translation>Il file esiste già </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>File already exists. Do you want to replace it?</source>
|
<source>File already exists. Do you want to replace it?</source>
|
||||||
|
@ -21,6 +21,15 @@ Id SharedAtomicU32(EmitContext& ctx, Id offset, Id value,
|
|||||||
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
|
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id SharedAtomicU32_IncDec(EmitContext& ctx, Id offset,
|
||||||
|
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id)) {
|
||||||
|
const Id shift_id{ctx.ConstU32(2U)};
|
||||||
|
const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)};
|
||||||
|
const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)};
|
||||||
|
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||||
|
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics);
|
||||||
|
}
|
||||||
|
|
||||||
Id BufferAtomicU32BoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto emit_func) {
|
Id BufferAtomicU32BoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto emit_func) {
|
||||||
if (Sirit::ValidId(buffer_size)) {
|
if (Sirit::ValidId(buffer_size)) {
|
||||||
// Bounds checking enabled, wrap in a conditional branch to make sure that
|
// Bounds checking enabled, wrap in a conditional branch to make sure that
|
||||||
@ -99,6 +108,18 @@ Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value) {
|
|||||||
return SharedAtomicU32(ctx, offset, value, &Sirit::Module::OpAtomicXor);
|
return SharedAtomicU32(ctx, offset, value, &Sirit::Module::OpAtomicXor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id EmitSharedAtomicISub32(EmitContext& ctx, Id offset, Id value) {
|
||||||
|
return SharedAtomicU32(ctx, offset, value, &Sirit::Module::OpAtomicISub);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSharedAtomicIIncrement32(EmitContext& ctx, Id offset) {
|
||||||
|
return SharedAtomicU32_IncDec(ctx, offset, &Sirit::Module::OpAtomicIIncrement);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSharedAtomicIDecrement32(EmitContext& ctx, Id offset) {
|
||||||
|
return SharedAtomicU32_IncDec(ctx, offset, &Sirit::Module::OpAtomicIDecrement);
|
||||||
|
}
|
||||||
|
|
||||||
Id EmitBufferAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
Id EmitBufferAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) {
|
||||||
return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicIAdd);
|
return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicIAdd);
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,10 @@ Id EmitSharedAtomicSMin32(EmitContext& ctx, Id offset, Id value);
|
|||||||
Id EmitSharedAtomicAnd32(EmitContext& ctx, Id offset, Id value);
|
Id EmitSharedAtomicAnd32(EmitContext& ctx, Id offset, Id value);
|
||||||
Id EmitSharedAtomicOr32(EmitContext& ctx, Id offset, Id value);
|
Id EmitSharedAtomicOr32(EmitContext& ctx, Id offset, Id value);
|
||||||
Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value);
|
Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value);
|
||||||
|
Id EmitSharedAtomicIIncrement32(EmitContext& ctx, Id offset);
|
||||||
|
Id EmitSharedAtomicIDecrement32(EmitContext& ctx, Id offset);
|
||||||
|
Id EmitSharedAtomicISub32(EmitContext& ctx, Id offset, Id value);
|
||||||
|
|
||||||
Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2);
|
Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2);
|
||||||
Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3);
|
Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3);
|
||||||
Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4);
|
Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4);
|
||||||
|
@ -3569,19 +3569,19 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
|
|||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
// 65 = IMAGE_GATHER4_CL
|
// 65 = IMAGE_GATHER4_CL
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
// 68 = IMAGE_GATHER4_L
|
// 68 = IMAGE_GATHER4_L
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 69 = IMAGE_GATHER4_B
|
// 69 = IMAGE_GATHER4_B
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 70 = IMAGE_GATHER4_B_CL
|
// 70 = IMAGE_GATHER4_B_CL
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 71 = IMAGE_GATHER4_LZ
|
// 71 = IMAGE_GATHER4_LZ
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
@ -3589,19 +3589,19 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
|
|||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
// 73 = IMAGE_GATHER4_C_CL
|
// 73 = IMAGE_GATHER4_C_CL
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
// 76 = IMAGE_GATHER4_C_L
|
// 76 = IMAGE_GATHER4_C_L
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 77 = IMAGE_GATHER4_C_B
|
// 77 = IMAGE_GATHER4_C_B
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 78 = IMAGE_GATHER4_C_B_CL
|
// 78 = IMAGE_GATHER4_C_B_CL
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 79 = IMAGE_GATHER4_C_LZ
|
// 79 = IMAGE_GATHER4_C_LZ
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
@ -3609,19 +3609,19 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
|
|||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
// 81 = IMAGE_GATHER4_CL_O
|
// 81 = IMAGE_GATHER4_CL_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
// 84 = IMAGE_GATHER4_L_O
|
// 84 = IMAGE_GATHER4_L_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 85 = IMAGE_GATHER4_B_O
|
// 85 = IMAGE_GATHER4_B_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 86 = IMAGE_GATHER4_B_CL_O
|
// 86 = IMAGE_GATHER4_B_CL_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 87 = IMAGE_GATHER4_LZ_O
|
// 87 = IMAGE_GATHER4_LZ_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
@ -3629,19 +3629,19 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
|
|||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
// 89 = IMAGE_GATHER4_C_CL_O
|
// 89 = IMAGE_GATHER4_C_CL_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
// 92 = IMAGE_GATHER4_C_L_O
|
// 92 = IMAGE_GATHER4_C_L_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 93 = IMAGE_GATHER4_C_B_O
|
// 93 = IMAGE_GATHER4_C_B_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 94 = IMAGE_GATHER4_C_B_CL_O
|
// 94 = IMAGE_GATHER4_C_B_CL_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Float32},
|
||||||
// 95 = IMAGE_GATHER4_C_LZ_O
|
// 95 = IMAGE_GATHER4_C_LZ_O
|
||||||
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Float32},
|
ScalarType::Float32},
|
||||||
|
@ -13,6 +13,12 @@ void Translator::EmitDataShare(const GcnInst& inst) {
|
|||||||
// DS
|
// DS
|
||||||
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_SUB_U32:
|
||||||
|
return DS_SUB_U32(inst, false);
|
||||||
|
case Opcode::DS_INC_U32:
|
||||||
|
return DS_INC_U32(inst, false);
|
||||||
|
case Opcode::DS_DEC_U32:
|
||||||
|
return DS_DEC_U32(inst, false);
|
||||||
case Opcode::DS_MIN_I32:
|
case Opcode::DS_MIN_I32:
|
||||||
return DS_MIN_U32(inst, true, false);
|
return DS_MIN_U32(inst, true, false);
|
||||||
case Opcode::DS_MAX_I32:
|
case Opcode::DS_MAX_I32:
|
||||||
@ -35,6 +41,8 @@ void Translator::EmitDataShare(const GcnInst& inst) {
|
|||||||
return DS_WRITE(32, false, true, true, inst);
|
return DS_WRITE(32, false, true, true, inst);
|
||||||
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_SUB_RTN_U32:
|
||||||
|
return DS_SUB_U32(inst, true);
|
||||||
case Opcode::DS_MIN_RTN_U32:
|
case Opcode::DS_MIN_RTN_U32:
|
||||||
return DS_MIN_U32(inst, false, true);
|
return DS_MIN_U32(inst, false, true);
|
||||||
case Opcode::DS_MAX_RTN_U32:
|
case Opcode::DS_MAX_RTN_U32:
|
||||||
@ -228,6 +236,40 @@ void Translator::DS_SWIZZLE_B32(const GcnInst& inst) {
|
|||||||
SetDst(inst.dst[0], ir.QuadShuffle(src, index));
|
SetDst(inst.dst[0], ir.QuadShuffle(src, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Translator::DS_INC_U32(const GcnInst& inst, bool rtn) {
|
||||||
|
const IR::U32 addr{GetSrc(inst.src[0])};
|
||||||
|
const IR::U32 offset =
|
||||||
|
ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0));
|
||||||
|
const IR::U32 addr_offset = ir.IAdd(addr, offset);
|
||||||
|
const IR::Value original_val = ir.SharedAtomicIIncrement(addr_offset);
|
||||||
|
if (rtn) {
|
||||||
|
SetDst(inst.dst[0], IR::U32{original_val});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Translator::DS_DEC_U32(const GcnInst& inst, bool rtn) {
|
||||||
|
const IR::U32 addr{GetSrc(inst.src[0])};
|
||||||
|
const IR::U32 offset =
|
||||||
|
ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0));
|
||||||
|
const IR::U32 addr_offset = ir.IAdd(addr, offset);
|
||||||
|
const IR::Value original_val = ir.SharedAtomicIDecrement(addr_offset);
|
||||||
|
if (rtn) {
|
||||||
|
SetDst(inst.dst[0], IR::U32{original_val});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Translator::DS_SUB_U32(const GcnInst& inst, bool rtn) {
|
||||||
|
const IR::U32 addr{GetSrc(inst.src[0])};
|
||||||
|
const IR::U32 data{GetSrc(inst.src[1])};
|
||||||
|
const IR::U32 offset =
|
||||||
|
ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0));
|
||||||
|
const IR::U32 addr_offset = ir.IAdd(addr, offset);
|
||||||
|
const IR::Value original_val = ir.SharedAtomicISub(addr_offset, data);
|
||||||
|
if (rtn) {
|
||||||
|
SetDst(inst.dst[0], IR::U32{original_val});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64,
|
void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64,
|
||||||
const GcnInst& inst) {
|
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))};
|
||||||
|
@ -30,6 +30,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) {
|
|||||||
return S_SUB_I32(inst);
|
return S_SUB_I32(inst);
|
||||||
case Opcode::S_ADDC_U32:
|
case Opcode::S_ADDC_U32:
|
||||||
return S_ADDC_U32(inst);
|
return S_ADDC_U32(inst);
|
||||||
|
case Opcode::S_SUBB_U32:
|
||||||
|
return S_SUBB_U32(inst);
|
||||||
case Opcode::S_MIN_I32:
|
case Opcode::S_MIN_I32:
|
||||||
return S_MIN_U32(true, inst);
|
return S_MIN_U32(true, inst);
|
||||||
case Opcode::S_MIN_U32:
|
case Opcode::S_MIN_U32:
|
||||||
@ -238,6 +240,17 @@ void Translator::S_SUB_U32(const GcnInst& inst) {
|
|||||||
ir.SetScc(ir.IGreaterThan(src1, src0, false));
|
ir.SetScc(ir.IGreaterThan(src1, src0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Translator::S_SUBB_U32(const GcnInst& inst) {
|
||||||
|
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||||
|
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||||
|
const IR::U32 borrow{ir.Select(ir.GetScc(), ir.Imm32(1U), ir.Imm32(0U))};
|
||||||
|
const IR::U32 result{ir.ISub(ir.ISub(src0, src1), borrow)};
|
||||||
|
SetDst(inst.dst[0], result);
|
||||||
|
|
||||||
|
const IR::U32 sum_with_borrow{ir.IAdd(src1, borrow)};
|
||||||
|
ir.SetScc(ir.ILessThan(src0, sum_with_borrow, false));
|
||||||
|
}
|
||||||
|
|
||||||
void Translator::S_ADD_I32(const GcnInst& inst) {
|
void Translator::S_ADD_I32(const GcnInst& inst) {
|
||||||
const IR::U32 src0{GetSrc(inst.src[0])};
|
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||||
const IR::U32 src1{GetSrc(inst.src[1])};
|
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||||
|
@ -80,6 +80,7 @@ public:
|
|||||||
// SOP2
|
// SOP2
|
||||||
void S_ADD_U32(const GcnInst& inst);
|
void S_ADD_U32(const GcnInst& inst);
|
||||||
void S_SUB_U32(const GcnInst& inst);
|
void S_SUB_U32(const GcnInst& inst);
|
||||||
|
void S_SUBB_U32(const GcnInst& inst);
|
||||||
void S_ADD_I32(const GcnInst& inst);
|
void S_ADD_I32(const GcnInst& inst);
|
||||||
void S_SUB_I32(const GcnInst& inst);
|
void S_SUB_I32(const GcnInst& inst);
|
||||||
void S_ADDC_U32(const GcnInst& inst);
|
void S_ADDC_U32(const GcnInst& inst);
|
||||||
@ -274,6 +275,9 @@ public:
|
|||||||
void DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst);
|
void DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst);
|
||||||
void DS_APPEND(const GcnInst& inst);
|
void DS_APPEND(const GcnInst& inst);
|
||||||
void DS_CONSUME(const GcnInst& inst);
|
void DS_CONSUME(const GcnInst& inst);
|
||||||
|
void DS_SUB_U32(const GcnInst& inst, bool rtn);
|
||||||
|
void DS_INC_U32(const GcnInst& inst, bool rtn);
|
||||||
|
void DS_DEC_U32(const GcnInst& inst, bool rtn);
|
||||||
|
|
||||||
// Buffer Memory
|
// Buffer Memory
|
||||||
// MUBUF / MTBUF
|
// MUBUF / MTBUF
|
||||||
|
@ -357,6 +357,18 @@ U32 IREmitter::SharedAtomicXor(const U32& address, const U32& data) {
|
|||||||
return Inst<U32>(Opcode::SharedAtomicXor32, address, data);
|
return Inst<U32>(Opcode::SharedAtomicXor32, address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 IREmitter::SharedAtomicIIncrement(const U32& address) {
|
||||||
|
return Inst<U32>(Opcode::SharedAtomicIIncrement32, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 IREmitter::SharedAtomicIDecrement(const U32& address) {
|
||||||
|
return Inst<U32>(Opcode::SharedAtomicIDecrement32, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 IREmitter::SharedAtomicISub(const U32& address, const U32& data) {
|
||||||
|
return Inst<U32>(Opcode::SharedAtomicISub32, address, data);
|
||||||
|
}
|
||||||
|
|
||||||
U32 IREmitter::ReadConst(const Value& base, const U32& offset) {
|
U32 IREmitter::ReadConst(const Value& base, const U32& offset) {
|
||||||
return Inst<U32>(Opcode::ReadConst, base, offset);
|
return Inst<U32>(Opcode::ReadConst, base, offset);
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,10 @@ public:
|
|||||||
[[nodiscard]] U32 SharedAtomicOr(const U32& address, const U32& data);
|
[[nodiscard]] U32 SharedAtomicOr(const U32& address, const U32& data);
|
||||||
[[nodiscard]] U32 SharedAtomicXor(const U32& address, const U32& data);
|
[[nodiscard]] U32 SharedAtomicXor(const U32& address, const U32& data);
|
||||||
|
|
||||||
|
[[nodiscard]] U32 SharedAtomicIIncrement(const U32& address);
|
||||||
|
[[nodiscard]] U32 SharedAtomicIDecrement(const U32& address);
|
||||||
|
[[nodiscard]] U32 SharedAtomicISub(const U32& address, const U32& data);
|
||||||
|
|
||||||
[[nodiscard]] U32 ReadConst(const Value& base, const U32& offset);
|
[[nodiscard]] U32 ReadConst(const Value& base, const U32& offset);
|
||||||
[[nodiscard]] U32 ReadConstBuffer(const Value& handle, const U32& index);
|
[[nodiscard]] U32 ReadConstBuffer(const Value& handle, const U32& index);
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@ OPCODE(SharedAtomicUMax32, U32, U32,
|
|||||||
OPCODE(SharedAtomicAnd32, U32, U32, U32, )
|
OPCODE(SharedAtomicAnd32, U32, U32, U32, )
|
||||||
OPCODE(SharedAtomicOr32, U32, U32, U32, )
|
OPCODE(SharedAtomicOr32, U32, U32, U32, )
|
||||||
OPCODE(SharedAtomicXor32, U32, U32, U32, )
|
OPCODE(SharedAtomicXor32, U32, U32, U32, )
|
||||||
|
OPCODE(SharedAtomicISub32, U32, U32, U32, )
|
||||||
|
OPCODE(SharedAtomicIIncrement32, U32, U32, )
|
||||||
|
OPCODE(SharedAtomicIDecrement32, U32, U32, )
|
||||||
|
|
||||||
// Context getters/setters
|
// Context getters/setters
|
||||||
OPCODE(GetUserData, U32, ScalarReg, )
|
OPCODE(GetUserData, U32, ScalarReg, )
|
||||||
|
@ -1 +1,43 @@
|
|||||||
IDI_ICON1 ICON "images/shadps4.ico"
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "winresrc.h"
|
||||||
|
|
||||||
|
#define xstr(s) str(s)
|
||||||
|
#define str(s) #s
|
||||||
|
|
||||||
|
// NEUTRAL LANG
|
||||||
|
LANGUAGE LANG_NEUTRAL, 0x8
|
||||||
|
|
||||||
|
// ICON
|
||||||
|
IDI_ICON1 ICON "images/shadps4.ico"
|
||||||
|
|
||||||
|
// VERSION
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0
|
||||||
|
PRODUCTVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "\0"
|
||||||
|
VALUE "FileDescription", "shadPS4 - PlayStation 4 Emulator\0"
|
||||||
|
VALUE "FileVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) ".0\0"
|
||||||
|
VALUE "InternalName", "shadPS4\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright 2025 shadPS4 Team\0"
|
||||||
|
VALUE "OriginalFilename", "shadPS4.exe\0"
|
||||||
|
VALUE "ProductName", "shadPS4\0"
|
||||||
|
VALUE "ProductVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) ".0\0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
@ -999,16 +999,13 @@ void Rasterizer::UpdateViewportScissorState() const {
|
|||||||
boost::container::static_vector<vk::Viewport, Liverpool::NumViewports> viewports;
|
boost::container::static_vector<vk::Viewport, Liverpool::NumViewports> viewports;
|
||||||
boost::container::static_vector<vk::Rect2D, Liverpool::NumViewports> scissors;
|
boost::container::static_vector<vk::Rect2D, Liverpool::NumViewports> scissors;
|
||||||
|
|
||||||
const auto& vp_ctl = regs.viewport_control;
|
|
||||||
const float reduce_z =
|
|
||||||
regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW ? 1.0f : 0.0f;
|
|
||||||
|
|
||||||
if (regs.polygon_control.enable_window_offset &&
|
if (regs.polygon_control.enable_window_offset &&
|
||||||
(regs.window_offset.window_x_offset != 0 || regs.window_offset.window_y_offset != 0)) {
|
(regs.window_offset.window_x_offset != 0 || regs.window_offset.window_y_offset != 0)) {
|
||||||
LOG_ERROR(Render_Vulkan,
|
LOG_ERROR(Render_Vulkan,
|
||||||
"PA_SU_SC_MODE_CNTL.VTX_WINDOW_OFFSET_ENABLE support is not yet implemented.");
|
"PA_SU_SC_MODE_CNTL.VTX_WINDOW_OFFSET_ENABLE support is not yet implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& vp_ctl = regs.viewport_control;
|
||||||
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
|
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
|
||||||
const auto& vp = regs.viewports[i];
|
const auto& vp = regs.viewports[i];
|
||||||
const auto& vp_d = regs.viewport_depths[i];
|
const auto& vp_d = regs.viewport_depths[i];
|
||||||
@ -1019,16 +1016,32 @@ void Rasterizer::UpdateViewportScissorState() const {
|
|||||||
const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f;
|
const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f;
|
||||||
const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f;
|
const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f;
|
||||||
|
|
||||||
vk::Viewport viewport = {
|
vk::Viewport viewport{};
|
||||||
.minDepth = zoffset - zscale * reduce_z,
|
|
||||||
.maxDepth = zscale + zoffset,
|
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/209a0ed/src/amd/vulkan/radv_pipeline_graphics.c#L688-689
|
||||||
};
|
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/209a0ed/src/amd/vulkan/radv_cmd_buffer.c#L3103-3109
|
||||||
|
// When the clip space is ranged [-1...1], the zoffset is centered.
|
||||||
|
// By reversing the above viewport calculations, we get the following:
|
||||||
|
if (regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW) {
|
||||||
|
viewport.minDepth = zoffset - zscale;
|
||||||
|
viewport.maxDepth = zoffset + zscale;
|
||||||
|
} else {
|
||||||
|
viewport.minDepth = zoffset;
|
||||||
|
viewport.maxDepth = zoffset + zscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!regs.depth_render_override.disable_viewport_clamp) {
|
||||||
|
// Apply depth clamp.
|
||||||
|
viewport.minDepth = std::max(viewport.minDepth, vp_d.zmin);
|
||||||
|
viewport.maxDepth = std::min(viewport.maxDepth, vp_d.zmax);
|
||||||
|
}
|
||||||
|
|
||||||
if (!instance.IsDepthRangeUnrestrictedSupported()) {
|
if (!instance.IsDepthRangeUnrestrictedSupported()) {
|
||||||
// Unrestricted depth range not supported by device. Make best attempt
|
// Unrestricted depth range not supported by device. Restrict to valid range.
|
||||||
// by restricting to valid range.
|
|
||||||
viewport.minDepth = std::max(viewport.minDepth, 0.f);
|
viewport.minDepth = std::max(viewport.minDepth, 0.f);
|
||||||
viewport.maxDepth = std::min(viewport.maxDepth, 1.f);
|
viewport.maxDepth = std::min(viewport.maxDepth, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regs.IsClipDisabled()) {
|
if (regs.IsClipDisabled()) {
|
||||||
// In case if clipping is disabled we patch the shader to convert vertex position
|
// In case if clipping is disabled we patch the shader to convert vertex position
|
||||||
// from screen space coordinates to NDC by defining a render space as full hardware
|
// from screen space coordinates to NDC by defining a render space as full hardware
|
||||||
@ -1048,6 +1061,7 @@ void Rasterizer::UpdateViewportScissorState() const {
|
|||||||
viewport.width = xscale * 2.0f;
|
viewport.width = xscale * 2.0f;
|
||||||
viewport.height = yscale * 2.0f;
|
viewport.height = yscale * 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
viewports.push_back(viewport);
|
viewports.push_back(viewport);
|
||||||
|
|
||||||
auto vp_scsr = scsr;
|
auto vp_scsr = scsr;
|
||||||
|
Loading…
Reference in New Issue
Block a user