Compare commits
2 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5dbda3f76 | ||
|
|
2bcebcff2a |
@@ -1,5 +1,6 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
brew update
|
||||
brew install dylibbundler p7zip qt5 sdl2 ccache
|
||||
brew install p7zip qt5 sdl2 ccache
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
pip3 install macpack
|
||||
|
||||
@@ -11,92 +11,19 @@ mkdir "$REV_NAME"
|
||||
cp build/bin/yuzu-cmd "$REV_NAME"
|
||||
cp -r build/bin/yuzu.app "$REV_NAME"
|
||||
|
||||
# move qt libs into app bundle for deployment
|
||||
$(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/yuzu.app"
|
||||
# move libs into folder for deployment
|
||||
macpack "${REV_NAME}/yuzu.app/Contents/MacOS/yuzu" -d "../Frameworks"
|
||||
# move qt frameworks into app bundle for deployment
|
||||
$(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/yuzu.app" -executable="${REV_NAME}/yuzu.app/Contents/MacOS/yuzu"
|
||||
|
||||
# move SDL2 libs into folder for deployment
|
||||
dylibbundler -b -x "${REV_NAME}/yuzu-cmd" -cd -d "${REV_NAME}/libs" -p "@executable_path/libs/"
|
||||
|
||||
# Make the changes to make the yuzu app standalone (i.e. not dependent on the current brew installation).
|
||||
# To do this, the absolute references to each and every QT framework must be re-written to point to the local frameworks
|
||||
# (in the Contents/Frameworks folder).
|
||||
# The "install_name_tool" is used to do so.
|
||||
|
||||
# Coreutils is a hack to coerce Homebrew to point to the absolute Cellar path (symlink dereferenced). i.e:
|
||||
# ls -l /usr/local/opt/qt5:: /usr/local/opt/qt5 -> ../Cellar/qt5/5.6.1-1
|
||||
# grealpath ../Cellar/qt5/5.6.1-1:: /usr/local/Cellar/qt5/5.6.1-1
|
||||
brew install coreutils || brew upgrade coreutils || true
|
||||
|
||||
REV_NAME_ALT=$REV_NAME/
|
||||
# grealpath is located in coreutils, there is no "realpath" for OS X :(
|
||||
QT_BREWS_PATH=$(grealpath "$(brew --prefix qt5)")
|
||||
BREW_PATH=$(brew --prefix)
|
||||
QT_VERSION_NUM=5
|
||||
|
||||
$BREW_PATH/opt/qt5/bin/macdeployqt "${REV_NAME_ALT}yuzu.app" \
|
||||
-executable="${REV_NAME_ALT}yuzu.app/Contents/MacOS/yuzu"
|
||||
|
||||
# These are the files that macdeployqt packed into Contents/Frameworks/ - we don't want those, so we replace them.
|
||||
declare -a macos_libs=("QtCore" "QtWidgets" "QtGui" "QtOpenGL" "QtPrintSupport")
|
||||
|
||||
for macos_lib in "${macos_libs[@]}"
|
||||
do
|
||||
SC_FRAMEWORK_PART=$macos_lib.framework/Versions/$QT_VERSION_NUM/$macos_lib
|
||||
# Replace macdeployqt versions of the Frameworks with our own (from /usr/local/opt/qt5/lib/)
|
||||
cp "$BREW_PATH/opt/qt5/lib/$SC_FRAMEWORK_PART" "${REV_NAME_ALT}yuzu.app/Contents/Frameworks/$SC_FRAMEWORK_PART"
|
||||
|
||||
# Replace references within the embedded Framework files with "internal" versions.
|
||||
for macos_lib2 in "${macos_libs[@]}"
|
||||
do
|
||||
# Since brew references both the non-symlinked and symlink paths of QT5, it needs to be duplicated.
|
||||
# /usr/local/Cellar/qt5/5.6.1-1/lib and /usr/local/opt/qt5/lib both resolve to the same files.
|
||||
# So the two lines below are effectively duplicates when resolved as a path, but as strings, they aren't.
|
||||
RM_FRAMEWORK_PART=$macos_lib2.framework/Versions/$QT_VERSION_NUM/$macos_lib2
|
||||
install_name_tool -change \
|
||||
$QT_BREWS_PATH/lib/$RM_FRAMEWORK_PART \
|
||||
@executable_path/../Frameworks/$RM_FRAMEWORK_PART \
|
||||
"${REV_NAME_ALT}yuzu.app/Contents/Frameworks/$SC_FRAMEWORK_PART"
|
||||
install_name_tool -change \
|
||||
"$BREW_PATH/opt/qt5/lib/$RM_FRAMEWORK_PART" \
|
||||
@executable_path/../Frameworks/$RM_FRAMEWORK_PART \
|
||||
"${REV_NAME_ALT}yuzu.app/Contents/Frameworks/$SC_FRAMEWORK_PART"
|
||||
done
|
||||
done
|
||||
|
||||
# Handles `This application failed to start because it could not find or load the Qt platform plugin "cocoa"`
|
||||
# Which manifests itself as:
|
||||
# "Exception Type: EXC_CRASH (SIGABRT) | Exception Codes: 0x0000000000000000, 0x0000000000000000 | Exception Note: EXC_CORPSE_NOTIFY"
|
||||
# There may be more dylibs needed to be fixed...
|
||||
declare -a macos_plugins=("Plugins/platforms/libqcocoa.dylib")
|
||||
|
||||
for macos_lib in "${macos_plugins[@]}"
|
||||
do
|
||||
install_name_tool -id @executable_path/../$macos_lib "${REV_NAME_ALT}yuzu.app/Contents/$macos_lib"
|
||||
for macos_lib2 in "${macos_libs[@]}"
|
||||
do
|
||||
RM_FRAMEWORK_PART=$macos_lib2.framework/Versions/$QT_VERSION_NUM/$macos_lib2
|
||||
install_name_tool -change \
|
||||
$QT_BREWS_PATH/lib/$RM_FRAMEWORK_PART \
|
||||
@executable_path/../Frameworks/$RM_FRAMEWORK_PART \
|
||||
"${REV_NAME_ALT}yuzu.app/Contents/$macos_lib"
|
||||
install_name_tool -change \
|
||||
"$BREW_PATH/opt/qt5/lib/$RM_FRAMEWORK_PART" \
|
||||
@executable_path/../Frameworks/$RM_FRAMEWORK_PART \
|
||||
"${REV_NAME_ALT}yuzu.app/Contents/$macos_lib"
|
||||
done
|
||||
done
|
||||
|
||||
for macos_lib in "${macos_libs[@]}"
|
||||
do
|
||||
# Debugging info for Travis-CI
|
||||
otool -L "${REV_NAME_ALT}yuzu.app/Contents/Frameworks/$macos_lib.framework/Versions/$QT_VERSION_NUM/$macos_lib"
|
||||
done
|
||||
# move libs into folder for deployment
|
||||
macpack "${REV_NAME}/yuzu-cmd" -d "libs"
|
||||
|
||||
# Make the yuzu.app application launch a debugging terminal.
|
||||
# Store away the actual binary
|
||||
mv ${REV_NAME_ALT}yuzu.app/Contents/MacOS/yuzu ${REV_NAME_ALT}yuzu.app/Contents/MacOS/yuzu-bin
|
||||
mv ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu-bin
|
||||
|
||||
cat > ${REV_NAME_ALT}yuzu.app/Contents/MacOS/yuzu <<EOL
|
||||
cat > ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu <<EOL
|
||||
#!/usr/bin/env bash
|
||||
cd "\`dirname "\$0"\`"
|
||||
chmod +x yuzu-bin
|
||||
@@ -105,6 +32,9 @@ EOL
|
||||
# Content that will serve as the launching script for yuzu (within the .app folder)
|
||||
|
||||
# Make the launching script executable
|
||||
chmod +x ${REV_NAME_ALT}yuzu.app/Contents/MacOS/yuzu
|
||||
chmod +x ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu
|
||||
|
||||
# Verify loader instructions
|
||||
find "$REV_NAME" -exec otool -L {} \;
|
||||
|
||||
. .travis/common/post-upload.sh
|
||||
|
||||
@@ -104,12 +104,78 @@ endif()
|
||||
message(STATUS "Target architecture: ${ARCHITECTURE}")
|
||||
|
||||
|
||||
# Configure C++ standard
|
||||
# Configure compilation flags
|
||||
# ===========================
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
|
||||
if (MINGW)
|
||||
add_definitions(-DMINGW_HAS_SECURE_API)
|
||||
|
||||
if (MINGW_STATIC_BUILD)
|
||||
add_definitions(-DQT_STATICPLUGIN)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# Silence "deprecation" warnings
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_WARNINGS)
|
||||
# Avoid windows.h junk
|
||||
add_definitions(/DNOMINMAX)
|
||||
# Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors.
|
||||
add_definitions(/DWIN32_LEAN_AND_MEAN)
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE)
|
||||
|
||||
# Tweak optimization settings
|
||||
# As far as I can tell, there's no way to override the CMake defaults while leaving user
|
||||
# changes intact, so we'll just clobber everything and say sorry.
|
||||
message(STATUS "Cache compiler flags ignored, please edit CMakeLists.txt to change the flags.")
|
||||
|
||||
# /W3 - Level 3 warnings
|
||||
# /MP - Multi-threaded compilation
|
||||
# /Zi - Output debugging information
|
||||
# /Zo - enhanced debug info for optimized builds
|
||||
# /permissive- - enables stricter C++ standards conformance checks
|
||||
set(CMAKE_C_FLAGS "/W3 /MP /Zi /Zo /permissive-" CACHE STRING "" FORCE)
|
||||
# /EHsc - C++-only exception handling semantics
|
||||
# /Zc:throwingNew - let codegen assume `operator new` will never return null
|
||||
# /Zc:inline - let codegen omit inline functions in object files
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} /EHsc /std:c++latest /Zc:throwingNew,inline" CACHE STRING "" FORCE)
|
||||
|
||||
# /MDd - Multi-threaded Debug Runtime DLL
|
||||
set(CMAKE_C_FLAGS_DEBUG "/Od /MDd" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "" FORCE)
|
||||
|
||||
# /O2 - Optimization level 2
|
||||
# /GS- - No stack buffer overflow checks
|
||||
# /MD - Multi-threaded runtime DLL
|
||||
set(CMAKE_C_FLAGS_RELEASE "/O2 /GS- /MD" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "" FORCE)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
# Set file offset size to 64 bits.
|
||||
#
|
||||
# On modern Unixes, this is typically already the case. The lone exception is
|
||||
# glibc, which may default to 32 bits. glibc allows this to be configured
|
||||
# by setting _FILE_OFFSET_BITS.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
||||
# CMake seems to only define _DEBUG on Windows
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_DEBUG> $<$<NOT:$<CONFIG:Debug>>:NDEBUG>)
|
||||
|
||||
# System imported libraries
|
||||
# ======================
|
||||
|
||||
@@ -260,21 +326,25 @@ endif()
|
||||
# Platform-specific library requirements
|
||||
# ======================================
|
||||
|
||||
if (APPLE)
|
||||
# Umbrella framework for everything GUI-related
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
IF (APPLE)
|
||||
find_library(COCOA_LIBRARY Cocoa) # Umbrella framework for everything GUI-related
|
||||
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
|
||||
elseif (WIN32)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
ELSEIF (WIN32)
|
||||
# WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600)
|
||||
set(PLATFORM_LIBRARIES winmm ws2_32)
|
||||
if (MINGW)
|
||||
IF (MINGW)
|
||||
# PSAPI is the Process Status API
|
||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
|
||||
endif()
|
||||
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
|
||||
ENDIF (MINGW)
|
||||
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
|
||||
set(PLATFORM_LIBRARIES rt)
|
||||
endif()
|
||||
ENDIF (APPLE)
|
||||
|
||||
# Setup a custom clang-format target (if clang-format can be found) that will run
|
||||
# against all the src files. This should be used before making a pull request.
|
||||
|
||||
@@ -1,79 +1,18 @@
|
||||
# Enable modules to include each other's files
|
||||
include_directories(.)
|
||||
|
||||
# CMake seems to only define _DEBUG on Windows
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_DEBUG> $<$<NOT:$<CONFIG:Debug>>:NDEBUG>)
|
||||
|
||||
# Set compilation flags
|
||||
if (MSVC)
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE)
|
||||
|
||||
# Silence "deprecation" warnings
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
|
||||
|
||||
# Avoid windows.h junk
|
||||
add_definitions(-DNOMINMAX)
|
||||
|
||||
# Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors.
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
|
||||
# /W3 - Level 3 warnings
|
||||
# /MP - Multi-threaded compilation
|
||||
# /Zi - Output debugging information
|
||||
# /Zo - enhanced debug info for optimized builds
|
||||
# /permissive- - enables stricter C++ standards conformance checks
|
||||
# /EHsc - C++-only exception handling semantics
|
||||
# /Zc:throwingNew - let codegen assume `operator new` will never return null
|
||||
# /Zc:inline - let codegen omit inline functions in object files
|
||||
add_compile_options(/W3 /MP /Zi /Zo /permissive- /EHsc /std:c++latest /Zc:throwingNew,inline)
|
||||
|
||||
# /GS- - No stack buffer overflow checks
|
||||
add_compile_options("$<$<CONFIG:Release>:/GS->")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE)
|
||||
else()
|
||||
add_compile_options("-Wno-attributes")
|
||||
|
||||
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
add_compile_options("-stdlib=libc++")
|
||||
endif()
|
||||
|
||||
# Set file offset size to 64 bits.
|
||||
#
|
||||
# On modern Unixes, this is typically already the case. The lone exception is
|
||||
# glibc, which may default to 32 bits. glibc allows this to be configured
|
||||
# by setting _FILE_OFFSET_BITS.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
add_definitions(-DMINGW_HAS_SECURE_API)
|
||||
|
||||
if (MINGW_STATIC_BUILD)
|
||||
add_definitions(-DQT_STATICPLUGIN)
|
||||
add_compile_options("-static")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(audio_core)
|
||||
add_subdirectory(video_core)
|
||||
add_subdirectory(input_common)
|
||||
add_subdirectory(tests)
|
||||
|
||||
if (ENABLE_SDL2)
|
||||
add_subdirectory(yuzu_cmd)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT)
|
||||
add_subdirectory(yuzu)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
add_subdirectory(web_service)
|
||||
endif()
|
||||
|
||||
@@ -38,7 +38,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
|
||||
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
|
||||
|
||||
release_event = core_timing.RegisterEvent(
|
||||
name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(); });
|
||||
name, [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); });
|
||||
}
|
||||
|
||||
void Stream::Play() {
|
||||
|
||||
@@ -70,8 +70,6 @@ add_library(core STATIC
|
||||
file_sys/system_archive/ng_word.h
|
||||
file_sys/system_archive/system_archive.cpp
|
||||
file_sys/system_archive/system_archive.h
|
||||
file_sys/system_archive/system_version.cpp
|
||||
file_sys/system_archive/system_version.h
|
||||
file_sys/vfs.cpp
|
||||
file_sys/vfs.h
|
||||
file_sys/vfs_concat.cpp
|
||||
@@ -146,8 +144,6 @@ add_library(core STATIC
|
||||
hle/kernel/svc_wrap.h
|
||||
hle/kernel/thread.cpp
|
||||
hle/kernel/thread.h
|
||||
hle/kernel/transfer_memory.cpp
|
||||
hle/kernel/transfer_memory.h
|
||||
hle/kernel/vm_manager.cpp
|
||||
hle/kernel/vm_manager.h
|
||||
hle/kernel/wait_object.cpp
|
||||
|
||||
@@ -186,7 +186,7 @@ void CoreTiming::Advance() {
|
||||
Event evt = std::move(event_queue.front());
|
||||
std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
|
||||
event_queue.pop_back();
|
||||
evt.type->callback(evt.userdata, global_timer - evt.time);
|
||||
evt.type->callback(evt.userdata, static_cast<int>(global_timer - evt.time));
|
||||
}
|
||||
|
||||
is_global_timer_sane = false;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace Core::Timing {
|
||||
|
||||
/// A callback that may be scheduled for a particular core timing event.
|
||||
using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>;
|
||||
using TimedCallback = std::function<void(u64 userdata, int cycles_late)>;
|
||||
|
||||
/// Contains the characteristics of a particular event.
|
||||
struct EventType {
|
||||
|
||||
@@ -423,7 +423,6 @@ std::array<u8, 16> TextCheatParser::ParseSingleLineCheat(const std::string& line
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
u64 MemoryReadImpl(u32 width, VAddr addr) {
|
||||
switch (width) {
|
||||
case 1:
|
||||
@@ -458,7 +457,6 @@ void MemoryWriteImpl(u32 width, VAddr addr, u64 value) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
CheatEngine::CheatEngine(Core::System& system, std::vector<CheatList> cheats_,
|
||||
const std::string& build_id, VAddr code_region_start,
|
||||
|
||||
@@ -11,9 +11,6 @@ namespace FileSys {
|
||||
constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1};
|
||||
constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002};
|
||||
constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001};
|
||||
constexpr ResultCode ERROR_OUT_OF_BOUNDS{ErrorModule::FS, 3005};
|
||||
constexpr ResultCode ERROR_FAILED_MOUNT_ARCHIVE{ErrorModule::FS, 3223};
|
||||
constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::FS, 6001};
|
||||
constexpr ResultCode ERROR_INVALID_OFFSET{ErrorModule::FS, 6061};
|
||||
constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::FS, 6062};
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "core/loader/nso.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace FileSys {
|
||||
@@ -33,6 +32,14 @@ constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{
|
||||
"subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "subsdk8", "subsdk9",
|
||||
};
|
||||
|
||||
struct NSOBuildHeader {
|
||||
u32_le magic;
|
||||
INSERT_PADDING_BYTES(0x3C);
|
||||
std::array<u8, 0x20> build_id;
|
||||
INSERT_PADDING_BYTES(0xA0);
|
||||
};
|
||||
static_assert(sizeof(NSOBuildHeader) == 0x100, "NSOBuildHeader has incorrect size.");
|
||||
|
||||
std::string FormatTitleVersion(u32 version, TitleVersionFormat format) {
|
||||
std::array<u8, sizeof(u32)> bytes{};
|
||||
bytes[0] = version % SINGLE_BYTE_MODULUS;
|
||||
@@ -156,16 +163,14 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD
|
||||
}
|
||||
|
||||
std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
|
||||
if (nso.size() < sizeof(Loader::NSOHeader)) {
|
||||
if (nso.size() < 0x100)
|
||||
return nso;
|
||||
}
|
||||
|
||||
Loader::NSOHeader header;
|
||||
std::memcpy(&header, nso.data(), sizeof(header));
|
||||
NSOBuildHeader header;
|
||||
std::memcpy(&header, nso.data(), sizeof(NSOBuildHeader));
|
||||
|
||||
if (header.magic != Common::MakeMagic('N', 'S', 'O', '0')) {
|
||||
if (header.magic != Common::MakeMagic('N', 'S', 'O', '0'))
|
||||
return nso;
|
||||
}
|
||||
|
||||
const auto build_id_raw = Common::HexArrayToString(header.build_id);
|
||||
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
|
||||
@@ -208,11 +213,9 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (out.size() < sizeof(Loader::NSOHeader)) {
|
||||
if (out.size() < 0x100)
|
||||
return nso;
|
||||
}
|
||||
|
||||
std::memcpy(out.data(), &header, sizeof(header));
|
||||
std::memcpy(out.data(), &header, sizeof(NSOBuildHeader));
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "core/file_sys/romfs.h"
|
||||
#include "core/file_sys/system_archive/ng_word.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
@@ -31,7 +30,7 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
|
||||
{0x0100000000000806, "NgWord", &NgWord1},
|
||||
{0x0100000000000807, "SsidList", nullptr},
|
||||
{0x0100000000000808, "Dictionary", nullptr},
|
||||
{0x0100000000000809, "SystemVersion", &SystemVersion},
|
||||
{0x0100000000000809, "SystemVersion", nullptr},
|
||||
{0x010000000000080A, "AvatarImage", nullptr},
|
||||
{0x010000000000080B, "LocalNews", nullptr},
|
||||
{0x010000000000080C, "Eula", nullptr},
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
namespace SystemVersionData {
|
||||
|
||||
// This section should reflect the best system version to describe yuzu's HLE api.
|
||||
// TODO(DarkLordZach): Update when HLE gets better.
|
||||
|
||||
constexpr u8 VERSION_MAJOR = 5;
|
||||
constexpr u8 VERSION_MINOR = 1;
|
||||
constexpr u8 VERSION_MICRO = 0;
|
||||
|
||||
constexpr u8 REVISION_MAJOR = 3;
|
||||
constexpr u8 REVISION_MINOR = 0;
|
||||
|
||||
constexpr char PLATFORM_STRING[] = "NX";
|
||||
constexpr char VERSION_HASH[] = "23f9df53e25709d756e0c76effcb2473bd3447dd";
|
||||
constexpr char DISPLAY_VERSION[] = "5.1.0";
|
||||
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 5.1.0-3.0";
|
||||
|
||||
} // namespace SystemVersionData
|
||||
|
||||
std::string GetLongDisplayVersion() {
|
||||
return SystemVersionData::DISPLAY_TITLE;
|
||||
}
|
||||
|
||||
VirtualDir SystemVersion() {
|
||||
VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file");
|
||||
file->WriteObject(SystemVersionData::VERSION_MAJOR, 0);
|
||||
file->WriteObject(SystemVersionData::VERSION_MINOR, 1);
|
||||
file->WriteObject(SystemVersionData::VERSION_MICRO, 2);
|
||||
file->WriteObject(SystemVersionData::REVISION_MAJOR, 4);
|
||||
file->WriteObject(SystemVersionData::REVISION_MINOR, 5);
|
||||
file->WriteArray(SystemVersionData::PLATFORM_STRING,
|
||||
std::min<u64>(sizeof(SystemVersionData::PLATFORM_STRING), 0x20ULL), 0x8);
|
||||
file->WriteArray(SystemVersionData::VERSION_HASH,
|
||||
std::min<u64>(sizeof(SystemVersionData::VERSION_HASH), 0x40ULL), 0x28);
|
||||
file->WriteArray(SystemVersionData::DISPLAY_VERSION,
|
||||
std::min<u64>(sizeof(SystemVersionData::DISPLAY_VERSION), 0x18ULL), 0x68);
|
||||
file->WriteArray(SystemVersionData::DISPLAY_TITLE,
|
||||
std::min<u64>(sizeof(SystemVersionData::DISPLAY_TITLE), 0x80ULL), 0x80);
|
||||
return std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{file},
|
||||
std::vector<VirtualDir>{}, "data");
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
std::string GetLongDisplayVersion();
|
||||
|
||||
VirtualDir SystemVersion();
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
@@ -29,7 +29,7 @@ namespace Kernel {
|
||||
* @param thread_handle The handle of the thread that's been awoken
|
||||
* @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
|
||||
*/
|
||||
static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) {
|
||||
static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_late) {
|
||||
const auto proper_handle = static_cast<Handle>(thread_handle);
|
||||
const auto& system = Core::System::GetInstance();
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include <unordered_map>
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
template <typename T>
|
||||
class ResultVal;
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ bool Object::IsWaitable() const {
|
||||
case HandleType::Unknown:
|
||||
case HandleType::WritableEvent:
|
||||
case HandleType::SharedMemory:
|
||||
case HandleType::TransferMemory:
|
||||
case HandleType::AddressArbiter:
|
||||
case HandleType::ResourceLimit:
|
||||
case HandleType::ClientPort:
|
||||
|
||||
@@ -22,7 +22,6 @@ enum class HandleType : u32 {
|
||||
WritableEvent,
|
||||
ReadableEvent,
|
||||
SharedMemory,
|
||||
TransferMemory,
|
||||
Thread,
|
||||
Process,
|
||||
AddressArbiter,
|
||||
|
||||
@@ -35,6 +35,14 @@ class Thread;
|
||||
|
||||
struct CodeSet;
|
||||
|
||||
struct AddressMapping {
|
||||
// Address and size must be page-aligned
|
||||
VAddr address;
|
||||
u64 size;
|
||||
bool read_only;
|
||||
bool unk_flag;
|
||||
};
|
||||
|
||||
enum class MemoryRegion : u16 {
|
||||
APPLICATION = 1,
|
||||
SYSTEM = 2,
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/kernel/svc_wrap.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/kernel/transfer_memory.h"
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/hle/result.h"
|
||||
@@ -1587,121 +1586,14 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
|
||||
}
|
||||
|
||||
auto& kernel = Core::System::GetInstance().Kernel();
|
||||
auto transfer_mem_handle = TransferMemory::Create(kernel, addr, size, perms);
|
||||
auto process = kernel.CurrentProcess();
|
||||
auto& handle_table = process->GetHandleTable();
|
||||
const auto shared_mem_handle = SharedMemory::Create(kernel, process, size, perms, perms, addr);
|
||||
|
||||
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
|
||||
const auto result = handle_table.Create(std::move(transfer_mem_handle));
|
||||
if (result.Failed()) {
|
||||
return result.Code();
|
||||
}
|
||||
|
||||
*handle = *result;
|
||||
CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode MapTransferMemory(Handle handle, VAddr address, u64 size, u32 permission_raw) {
|
||||
LOG_DEBUG(Kernel_SVC,
|
||||
"called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}, permissions=0x{:08X}",
|
||||
handle, address, size, permission_raw);
|
||||
|
||||
if (!Common::Is4KBAligned(address)) {
|
||||
LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
|
||||
address);
|
||||
return ERR_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
|
||||
size);
|
||||
return ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (!IsValidAddressRange(address, size)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Given address and size overflows the 64-bit range (address=0x{:016X}, "
|
||||
"size=0x{:016X}).",
|
||||
address, size);
|
||||
return ERR_INVALID_ADDRESS_STATE;
|
||||
}
|
||||
|
||||
const auto permissions = static_cast<MemoryPermission>(permission_raw);
|
||||
if (permissions != MemoryPermission::None && permissions != MemoryPermission::Read &&
|
||||
permissions != MemoryPermission::ReadWrite) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid transfer memory permissions given (permissions=0x{:08X}).",
|
||||
permission_raw);
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
const auto& kernel = Core::System::GetInstance().Kernel();
|
||||
const auto* const current_process = kernel.CurrentProcess();
|
||||
const auto& handle_table = current_process->GetHandleTable();
|
||||
|
||||
auto transfer_memory = handle_table.Get<TransferMemory>(handle);
|
||||
if (!transfer_memory) {
|
||||
LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
|
||||
handle);
|
||||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Given address and size don't fully fit within the ASLR region "
|
||||
"(address=0x{:016X}, size=0x{:016X}).",
|
||||
address, size);
|
||||
return ERR_INVALID_MEMORY_RANGE;
|
||||
}
|
||||
|
||||
return transfer_memory->MapMemory(address, size, permissions);
|
||||
}
|
||||
|
||||
static ResultCode UnmapTransferMemory(Handle handle, VAddr address, u64 size) {
|
||||
LOG_DEBUG(Kernel_SVC, "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}", handle,
|
||||
address, size);
|
||||
|
||||
if (!Common::Is4KBAligned(address)) {
|
||||
LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
|
||||
address);
|
||||
return ERR_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
|
||||
size);
|
||||
return ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (!IsValidAddressRange(address, size)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Given address and size overflows the 64-bit range (address=0x{:016X}, "
|
||||
"size=0x{:016X}).",
|
||||
address, size);
|
||||
return ERR_INVALID_ADDRESS_STATE;
|
||||
}
|
||||
|
||||
const auto& kernel = Core::System::GetInstance().Kernel();
|
||||
const auto* const current_process = kernel.CurrentProcess();
|
||||
const auto& handle_table = current_process->GetHandleTable();
|
||||
|
||||
auto transfer_memory = handle_table.Get<TransferMemory>(handle);
|
||||
if (!transfer_memory) {
|
||||
LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
|
||||
handle);
|
||||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Given address and size don't fully fit within the ASLR region "
|
||||
"(address=0x{:016X}, size=0x{:016X}).",
|
||||
address, size);
|
||||
return ERR_INVALID_MEMORY_RANGE;
|
||||
}
|
||||
|
||||
return transfer_memory->UnmapMemory(address, size);
|
||||
}
|
||||
|
||||
static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
|
||||
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
|
||||
|
||||
@@ -2077,8 +1969,8 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x4E, nullptr, "ReadWriteRegister"},
|
||||
{0x4F, nullptr, "SetProcessActivity"},
|
||||
{0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"},
|
||||
{0x51, SvcWrap<MapTransferMemory>, "MapTransferMemory"},
|
||||
{0x52, SvcWrap<UnmapTransferMemory>, "UnmapTransferMemory"},
|
||||
{0x51, nullptr, "MapTransferMemory"},
|
||||
{0x52, nullptr, "UnmapTransferMemory"},
|
||||
{0x53, nullptr, "CreateInterruptEvent"},
|
||||
{0x54, nullptr, "QueryPhysicalAddress"},
|
||||
{0x55, nullptr, "QueryIoMapping"},
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/kernel/transfer_memory.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {}
|
||||
TransferMemory::~TransferMemory() = default;
|
||||
|
||||
SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address,
|
||||
size_t size, MemoryPermission permissions) {
|
||||
SharedPtr<TransferMemory> transfer_memory{new TransferMemory(kernel)};
|
||||
|
||||
transfer_memory->base_address = base_address;
|
||||
transfer_memory->memory_size = size;
|
||||
transfer_memory->owner_permissions = permissions;
|
||||
transfer_memory->owner_process = kernel.CurrentProcess();
|
||||
|
||||
return transfer_memory;
|
||||
}
|
||||
|
||||
ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermission permissions) {
|
||||
if (memory_size != size) {
|
||||
return ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (owner_permissions != permissions) {
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (is_mapped) {
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
const auto map_state = owner_permissions == MemoryPermission::None
|
||||
? MemoryState::TransferMemoryIsolated
|
||||
: MemoryState::TransferMemory;
|
||||
auto& vm_manager = owner_process->VMManager();
|
||||
const auto map_result = vm_manager.MapMemoryBlock(
|
||||
address, std::make_shared<std::vector<u8>>(size), 0, size, map_state);
|
||||
|
||||
if (map_result.Failed()) {
|
||||
return map_result.Code();
|
||||
}
|
||||
|
||||
is_mapped = true;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode TransferMemory::UnmapMemory(VAddr address, size_t size) {
|
||||
if (memory_size != size) {
|
||||
return ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
auto& vm_manager = owner_process->VMManager();
|
||||
const auto result = vm_manager.UnmapRange(address, size);
|
||||
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
is_mapped = false;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -1,91 +0,0 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
union ResultCode;
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class Process;
|
||||
|
||||
enum class MemoryPermission : u32;
|
||||
|
||||
/// Defines the interface for transfer memory objects.
|
||||
///
|
||||
/// Transfer memory is typically used for the purpose of
|
||||
/// transferring memory between separate process instances,
|
||||
/// thus the name.
|
||||
///
|
||||
class TransferMemory final : public Object {
|
||||
public:
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
|
||||
|
||||
static SharedPtr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, size_t size,
|
||||
MemoryPermission permissions);
|
||||
|
||||
TransferMemory(const TransferMemory&) = delete;
|
||||
TransferMemory& operator=(const TransferMemory&) = delete;
|
||||
|
||||
TransferMemory(TransferMemory&&) = delete;
|
||||
TransferMemory& operator=(TransferMemory&&) = delete;
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "TransferMemory";
|
||||
}
|
||||
|
||||
std::string GetName() const override {
|
||||
return GetTypeName();
|
||||
}
|
||||
|
||||
HandleType GetHandleType() const override {
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
/// Attempts to map transfer memory with the given range and memory permissions.
|
||||
///
|
||||
/// @param address The base address to being mapping memory at.
|
||||
/// @param size The size of the memory to map, in bytes.
|
||||
/// @param permissions The memory permissions to check against when mapping memory.
|
||||
///
|
||||
/// @pre The given address, size, and memory permissions must all match
|
||||
/// the same values that were given when creating the transfer memory
|
||||
/// instance.
|
||||
///
|
||||
ResultCode MapMemory(VAddr address, size_t size, MemoryPermission permissions);
|
||||
|
||||
/// Unmaps the transfer memory with the given range
|
||||
///
|
||||
/// @param address The base address to begin unmapping memory at.
|
||||
/// @param size The size of the memory to unmap, in bytes.
|
||||
///
|
||||
/// @pre The given address and size must be the same as the ones used
|
||||
/// to create the transfer memory instance.
|
||||
///
|
||||
ResultCode UnmapMemory(VAddr address, size_t size);
|
||||
|
||||
private:
|
||||
explicit TransferMemory(KernelCore& kernel);
|
||||
~TransferMemory() override;
|
||||
|
||||
/// The base address for the memory managed by this instance.
|
||||
VAddr base_address = 0;
|
||||
|
||||
/// Size of the memory, in bytes, that this instance manages.
|
||||
size_t memory_size = 0;
|
||||
|
||||
/// The memory permissions that are applied to this instance.
|
||||
MemoryPermission owner_permissions{};
|
||||
|
||||
/// The process that this transfer memory instance was created under.
|
||||
Process* owner_process = nullptr;
|
||||
|
||||
/// Whether or not this transfer memory instance has mapped memory.
|
||||
bool is_mapped = false;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -36,9 +36,9 @@ namespace Service::HID {
|
||||
|
||||
// Updating period for each HID device.
|
||||
// TODO(ogniK): Find actual polling rate of hid
|
||||
constexpr s64 pad_update_ticks = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 66);
|
||||
constexpr s64 accelerometer_update_ticks = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 100);
|
||||
constexpr s64 gyroscope_update_ticks = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 100);
|
||||
constexpr u64 pad_update_ticks = Core::Timing::BASE_CLOCK_RATE / 66;
|
||||
constexpr u64 accelerometer_update_ticks = Core::Timing::BASE_CLOCK_RATE / 100;
|
||||
constexpr u64 gyroscope_update_ticks = Core::Timing::BASE_CLOCK_RATE / 100;
|
||||
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
|
||||
|
||||
IAppletResource::IAppletResource() : ServiceFramework("IAppletResource") {
|
||||
@@ -75,7 +75,7 @@ IAppletResource::IAppletResource() : ServiceFramework("IAppletResource") {
|
||||
// Register update callbacks
|
||||
auto& core_timing = Core::System::GetInstance().CoreTiming();
|
||||
pad_update_event =
|
||||
core_timing.RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 cycles_late) {
|
||||
core_timing.RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, int cycles_late) {
|
||||
UpdateControllers(userdata, cycles_late);
|
||||
});
|
||||
|
||||
@@ -106,7 +106,7 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
|
||||
rb.PushCopyObjects(shared_mem);
|
||||
}
|
||||
|
||||
void IAppletResource::UpdateControllers(u64 userdata, s64 cycles_late) {
|
||||
void IAppletResource::UpdateControllers(u64 userdata, int cycles_late) {
|
||||
auto& core_timing = Core::System::GetInstance().CoreTiming();
|
||||
|
||||
const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
|
||||
|
||||
@@ -65,7 +65,7 @@ private:
|
||||
}
|
||||
|
||||
void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
|
||||
void UpdateControllers(u64 userdata, s64 cycles_late);
|
||||
void UpdateControllers(u64 userdata, int cycles_late);
|
||||
|
||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
namespace Service::NVFlinger {
|
||||
|
||||
constexpr std::size_t SCREEN_REFRESH_RATE = 60;
|
||||
constexpr s64 frame_ticks = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
|
||||
constexpr u64 frame_ticks = static_cast<u64>(Core::Timing::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
|
||||
|
||||
NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_timing} {
|
||||
displays.emplace_back(0, "Default");
|
||||
@@ -37,7 +37,7 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t
|
||||
|
||||
// Schedule the screen composition events
|
||||
composition_event =
|
||||
core_timing.RegisterEvent("ScreenComposition", [this](u64 userdata, s64 cycles_late) {
|
||||
core_timing.RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
|
||||
Compose();
|
||||
this->core_timing.ScheduleEvent(frame_ticks - cycles_late, composition_event);
|
||||
});
|
||||
|
||||
@@ -2,88 +2,13 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/set/set_sys.h"
|
||||
|
||||
namespace Service::Set {
|
||||
|
||||
namespace {
|
||||
constexpr u64 SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET = 0x05;
|
||||
|
||||
enum class GetFirmwareVersionType {
|
||||
Version1,
|
||||
Version2,
|
||||
};
|
||||
|
||||
void GetFirmwareVersionImpl(Kernel::HLERequestContext& ctx, GetFirmwareVersionType type) {
|
||||
LOG_WARNING(Service_SET, "called - Using hardcoded firmware version '{}'",
|
||||
FileSys::SystemArchive::GetLongDisplayVersion());
|
||||
|
||||
ASSERT_MSG(ctx.GetWriteBufferSize() == 0x100,
|
||||
"FirmwareVersion output buffer must be 0x100 bytes in size!");
|
||||
|
||||
// Instead of using the normal procedure of checking for the real system archive and if it
|
||||
// doesn't exist, synthesizing one, I feel that that would lead to strange bugs because a
|
||||
// used is using a really old or really new SystemVersion title. The synthesized one ensures
|
||||
// consistence (currently reports as 5.1.0-0.0)
|
||||
const auto archive = FileSys::SystemArchive::SystemVersion();
|
||||
|
||||
const auto early_exit_failure = [&ctx](const std::string& desc, ResultCode code) {
|
||||
LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
|
||||
desc.c_str());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(code);
|
||||
};
|
||||
|
||||
if (archive == nullptr) {
|
||||
early_exit_failure("The system version archive couldn't be synthesized.",
|
||||
FileSys::ERROR_FAILED_MOUNT_ARCHIVE);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto ver_file = archive->GetFile("file");
|
||||
if (ver_file == nullptr) {
|
||||
early_exit_failure("The system version archive didn't contain the file 'file'.",
|
||||
FileSys::ERROR_INVALID_ARGUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = ver_file->ReadAllBytes();
|
||||
if (data.size() != 0x100) {
|
||||
early_exit_failure("The system version file 'file' was not the correct size.",
|
||||
FileSys::ERROR_OUT_OF_BOUNDS);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will
|
||||
// zero out the REVISION_MINOR field.
|
||||
if (type == GetFirmwareVersionType::Version1) {
|
||||
data[SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET] = 0;
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(data);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void SET_SYS::GetFirmwareVersion(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1);
|
||||
}
|
||||
|
||||
void SET_SYS::GetFirmwareVersion2(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2);
|
||||
}
|
||||
|
||||
void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
@@ -108,8 +33,8 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
{0, nullptr, "SetLanguageCode"},
|
||||
{1, nullptr, "SetNetworkSettings"},
|
||||
{2, nullptr, "GetNetworkSettings"},
|
||||
{3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"},
|
||||
{4, &SET_SYS::GetFirmwareVersion2, "GetFirmwareVersion2"},
|
||||
{3, nullptr, "GetFirmwareVersion"},
|
||||
{4, nullptr, "GetFirmwareVersion2"},
|
||||
{5, nullptr, "GetFirmwareVersionDigest"},
|
||||
{7, nullptr, "GetLockScreenFlag"},
|
||||
{8, nullptr, "SetLockScreenFlag"},
|
||||
|
||||
@@ -20,8 +20,6 @@ private:
|
||||
BasicBlack = 1,
|
||||
};
|
||||
|
||||
void GetFirmwareVersion(Kernel::HLERequestContext& ctx);
|
||||
void GetFirmwareVersion2(Kernel::HLERequestContext& ctx);
|
||||
void GetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
void SetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
|
||||
|
||||
@@ -21,8 +21,36 @@
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Loader {
|
||||
namespace {
|
||||
struct MODHeader {
|
||||
|
||||
struct NsoSegmentHeader {
|
||||
u32_le offset;
|
||||
u32_le location;
|
||||
u32_le size;
|
||||
union {
|
||||
u32_le alignment;
|
||||
u32_le bss_size;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size.");
|
||||
|
||||
struct NsoHeader {
|
||||
u32_le magic;
|
||||
u32_le version;
|
||||
INSERT_PADDING_WORDS(1);
|
||||
u8 flags;
|
||||
std::array<NsoSegmentHeader, 3> segments; // Text, RoData, Data (in that order)
|
||||
std::array<u8, 0x20> build_id;
|
||||
std::array<u32_le, 3> segments_compressed_size;
|
||||
|
||||
bool IsSegmentCompressed(size_t segment_num) const {
|
||||
ASSERT_MSG(segment_num < 3, "Invalid segment {}", segment_num);
|
||||
return ((flags >> segment_num) & 1);
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(NsoHeader) == 0x6c, "NsoHeader has incorrect size.");
|
||||
static_assert(std::is_trivially_copyable_v<NsoHeader>, "NsoHeader isn't trivially copyable.");
|
||||
|
||||
struct ModHeader {
|
||||
u32_le magic;
|
||||
u32_le dynamic_offset;
|
||||
u32_le bss_start_offset;
|
||||
@@ -31,32 +59,7 @@ struct MODHeader {
|
||||
u32_le eh_frame_hdr_end_offset;
|
||||
u32_le module_offset; // Offset to runtime-generated module object. typically equal to .bss base
|
||||
};
|
||||
static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size.");
|
||||
|
||||
std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
|
||||
const NSOSegmentHeader& header) {
|
||||
std::vector<u8> uncompressed_data(header.size);
|
||||
const int bytes_uncompressed =
|
||||
LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()),
|
||||
reinterpret_cast<char*>(uncompressed_data.data()),
|
||||
static_cast<int>(compressed_data.size()), header.size);
|
||||
|
||||
ASSERT_MSG(bytes_uncompressed == static_cast<int>(header.size) &&
|
||||
bytes_uncompressed == static_cast<int>(uncompressed_data.size()),
|
||||
"{} != {} != {}", bytes_uncompressed, header.size, uncompressed_data.size());
|
||||
|
||||
return uncompressed_data;
|
||||
}
|
||||
|
||||
constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
bool NSOHeader::IsSegmentCompressed(size_t segment_num) const {
|
||||
ASSERT_MSG(segment_num < 3, "Invalid segment {}", segment_num);
|
||||
return ((flags >> segment_num) & 1) != 0;
|
||||
}
|
||||
static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size.");
|
||||
|
||||
AppLoader_NSO::AppLoader_NSO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
|
||||
|
||||
@@ -73,22 +76,38 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
return FileType::NSO;
|
||||
}
|
||||
|
||||
static std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
|
||||
const NsoSegmentHeader& header) {
|
||||
std::vector<u8> uncompressed_data(header.size);
|
||||
const int bytes_uncompressed =
|
||||
LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()),
|
||||
reinterpret_cast<char*>(uncompressed_data.data()),
|
||||
static_cast<int>(compressed_data.size()), header.size);
|
||||
|
||||
ASSERT_MSG(bytes_uncompressed == static_cast<int>(header.size) &&
|
||||
bytes_uncompressed == static_cast<int>(uncompressed_data.size()),
|
||||
"{} != {} != {}", bytes_uncompressed, header.size, uncompressed_data.size());
|
||||
|
||||
return uncompressed_data;
|
||||
}
|
||||
|
||||
static constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
|
||||
}
|
||||
|
||||
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||
const FileSys::VfsFile& file, VAddr load_base,
|
||||
bool should_pass_arguments,
|
||||
std::optional<FileSys::PatchManager> pm) {
|
||||
if (file.GetSize() < sizeof(NSOHeader)) {
|
||||
if (file.GetSize() < sizeof(NsoHeader))
|
||||
return {};
|
||||
}
|
||||
|
||||
NSOHeader nso_header{};
|
||||
if (sizeof(NSOHeader) != file.ReadObject(&nso_header)) {
|
||||
NsoHeader nso_header{};
|
||||
if (sizeof(NsoHeader) != file.ReadObject(&nso_header))
|
||||
return {};
|
||||
}
|
||||
|
||||
if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) {
|
||||
if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0'))
|
||||
return {};
|
||||
}
|
||||
|
||||
// Build program image
|
||||
Kernel::CodeSet codeset;
|
||||
@@ -124,10 +143,10 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||
std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32));
|
||||
|
||||
// Read MOD header
|
||||
MODHeader mod_header{};
|
||||
ModHeader mod_header{};
|
||||
// Default .bss to size in segment header if MOD0 section doesn't exist
|
||||
u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)};
|
||||
std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(MODHeader));
|
||||
std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader));
|
||||
const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')};
|
||||
if (has_mod_header) {
|
||||
// Resize program image to include .bss section and page align each section
|
||||
@@ -139,15 +158,13 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||
|
||||
// Apply patches if necessary
|
||||
if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
|
||||
std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size());
|
||||
pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header),
|
||||
reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader));
|
||||
pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.begin(),
|
||||
program_image.end());
|
||||
std::vector<u8> pi_header(program_image.size() + 0x100);
|
||||
std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader));
|
||||
std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size());
|
||||
|
||||
pi_header = pm->PatchNSO(pi_header);
|
||||
|
||||
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.begin());
|
||||
std::memcpy(program_image.data(), pi_header.data() + 0x100, program_image.size());
|
||||
}
|
||||
|
||||
// Apply cheats if they exist and the program has a valid title ID
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
@@ -18,43 +16,6 @@ class Process;
|
||||
|
||||
namespace Loader {
|
||||
|
||||
struct NSOSegmentHeader {
|
||||
u32_le offset;
|
||||
u32_le location;
|
||||
u32_le size;
|
||||
union {
|
||||
u32_le alignment;
|
||||
u32_le bss_size;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(NSOSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size.");
|
||||
|
||||
struct NSOHeader {
|
||||
using SHA256Hash = std::array<u8, 0x20>;
|
||||
|
||||
struct RODataRelativeExtent {
|
||||
u32_le data_offset;
|
||||
u32_le size;
|
||||
};
|
||||
|
||||
u32_le magic;
|
||||
u32_le version;
|
||||
u32 reserved;
|
||||
u32_le flags;
|
||||
std::array<NSOSegmentHeader, 3> segments; // Text, RoData, Data (in that order)
|
||||
std::array<u8, 0x20> build_id;
|
||||
std::array<u32_le, 3> segments_compressed_size;
|
||||
std::array<u8, 0x1C> padding;
|
||||
RODataRelativeExtent api_info_extent;
|
||||
RODataRelativeExtent dynstr_extent;
|
||||
RODataRelativeExtent dynsyn_extent;
|
||||
std::array<SHA256Hash, 3> segment_hashes;
|
||||
|
||||
bool IsSegmentCompressed(size_t segment_num) const;
|
||||
};
|
||||
static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
|
||||
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
||||
|
||||
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||
|
||||
struct NSOArgumentHeader {
|
||||
|
||||
@@ -71,8 +71,8 @@ private:
|
||||
bool is_registered{}; ///< Whether the object is currently registered with the cache
|
||||
bool is_dirty{}; ///< Whether the object is dirty (out of sync with guest memory)
|
||||
u64 last_modified_ticks{}; ///< When the object was last modified, used for in-order flushing
|
||||
const u8* host_ptr{}; ///< Pointer to the memory backing this cached region
|
||||
CacheAddr cache_addr{}; ///< Cache address memory, unique from emulated virtual address space
|
||||
const u8* host_ptr{}; ///< Pointer to the memory backing this cached region
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace OpenGL {
|
||||
|
||||
CachedBufferEntry::CachedBufferEntry(VAddr cpu_addr, std::size_t size, GLintptr offset,
|
||||
std::size_t alignment, u8* host_ptr)
|
||||
: RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, size{size}, offset{offset},
|
||||
alignment{alignment} {}
|
||||
: cpu_addr{cpu_addr}, size{size}, offset{offset}, alignment{alignment}, RasterizerCacheObject{
|
||||
host_ptr} {}
|
||||
|
||||
OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size)
|
||||
: RasterizerCache{rasterizer}, stream_buffer(size, true) {}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace OpenGL {
|
||||
|
||||
CachedGlobalRegion::CachedGlobalRegion(VAddr cpu_addr, u32 size, u8* host_ptr)
|
||||
: RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, size{size} {
|
||||
: cpu_addr{cpu_addr}, size{size}, RasterizerCacheObject{host_ptr} {
|
||||
buffer.Create();
|
||||
// Bind and unbind the buffer so it gets allocated by the driver
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer.handle);
|
||||
|
||||
@@ -562,8 +562,8 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
|
||||
}
|
||||
|
||||
CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||
: RasterizerCacheObject{params.host_ptr}, params{params},
|
||||
gl_target{SurfaceTargetToGL(params.target)}, cached_size_in_bytes{params.size_in_bytes} {
|
||||
: params{params}, gl_target{SurfaceTargetToGL(params.target)},
|
||||
cached_size_in_bytes{params.size_in_bytes}, RasterizerCacheObject{params.host_ptr} {
|
||||
|
||||
const auto optional_cpu_addr{
|
||||
Core::System::GetInstance().GPU().MemoryManager().GpuToCpuAddress(params.gpu_addr)};
|
||||
|
||||
@@ -215,9 +215,9 @@ CachedShader::CachedShader(VAddr cpu_addr, u64 unique_identifier,
|
||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||
const PrecompiledPrograms& precompiled_programs,
|
||||
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr)
|
||||
: RasterizerCacheObject{host_ptr}, host_ptr{host_ptr}, cpu_addr{cpu_addr},
|
||||
unique_identifier{unique_identifier}, program_type{program_type}, disk_cache{disk_cache},
|
||||
precompiled_programs{precompiled_programs} {
|
||||
: host_ptr{host_ptr}, cpu_addr{cpu_addr}, unique_identifier{unique_identifier},
|
||||
program_type{program_type}, disk_cache{disk_cache},
|
||||
precompiled_programs{precompiled_programs}, RasterizerCacheObject{host_ptr} {
|
||||
|
||||
const std::size_t code_size = CalculateProgramSize(program_code);
|
||||
const std::size_t code_size_b =
|
||||
@@ -245,9 +245,9 @@ CachedShader::CachedShader(VAddr cpu_addr, u64 unique_identifier,
|
||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||
const PrecompiledPrograms& precompiled_programs,
|
||||
GLShader::ProgramResult result, u8* host_ptr)
|
||||
: RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, unique_identifier{unique_identifier},
|
||||
program_type{program_type}, disk_cache{disk_cache}, precompiled_programs{
|
||||
precompiled_programs} {
|
||||
: cpu_addr{cpu_addr}, unique_identifier{unique_identifier}, program_type{program_type},
|
||||
disk_cache{disk_cache}, precompiled_programs{precompiled_programs}, RasterizerCacheObject{
|
||||
host_ptr} {
|
||||
|
||||
code = std::move(result.first);
|
||||
entries = result.second;
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace Vulkan {
|
||||
|
||||
CachedBufferEntry::CachedBufferEntry(VAddr cpu_addr, std::size_t size, u64 offset,
|
||||
std::size_t alignment, u8* host_ptr)
|
||||
: RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, size{size}, offset{offset},
|
||||
alignment{alignment} {}
|
||||
: cpu_addr{cpu_addr}, size{size}, offset{offset}, alignment{alignment}, RasterizerCacheObject{
|
||||
host_ptr} {}
|
||||
|
||||
VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager,
|
||||
VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
|
||||
|
||||
Reference in New Issue
Block a user