code: Add clang-format target and CI workflow (#82)

* code: Add clang format target, rules and CI workflow

* code: Run clang format on sources
This commit is contained in:
GPUCode 2024-02-23 22:57:57 +02:00 committed by GitHub
parent 32a5ff15bb
commit 6f4c6ae0bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
90 changed files with 2942 additions and 1941 deletions

37
.ci/clang-format.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash -ex
if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dist/*.desktop \
dist/*.svg dist/*.xml; then
echo Trailing whitespace found, aborting
exit 1
fi
# Default clang-format points to default 3.5 version one
CLANG_FORMAT=clang-format-15
$CLANG_FORMAT --version
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
# Get list of every file modified in this pull request
files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' || true)"
else
# Check everything for branch pushes
files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')"
fi
# Turn off tracing for this because it's too verbose
set +x
for f in $files_to_lint; do
d=$(diff -u "$f" <($CLANG_FORMAT "$f") || true)
if ! [ -z "$d" ]; then
echo "!!! $f not compliant to coding style, here is the fix:"
echo "$d"
fail=1
fi
done
set -x
if [ "$fail" = 1 ]; then
exit 1
fi

21
.github/workflows/format.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Clang Format
on:
push:
branches: [ "*" ]
pull_request:
branches: [ main ]
jobs:
clang-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install
run: sudo apt-get install clang-format-15
- name: Build
env:
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
run: ./.ci/clang-format.sh

View File

@ -27,6 +27,57 @@ function(create_target_directory_groups target_name)
endforeach() endforeach()
endfunction() endfunction()
# 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.
# =======================================================================
set(CLANG_FORMAT_POSTFIX "-15")
find_program(CLANG_FORMAT
NAMES clang-format${CLANG_FORMAT_POSTFIX}
clang-format
PATHS ${PROJECT_BINARY_DIR}/externals)
# if find_program doesn't find it, try to download from externals
if (NOT CLANG_FORMAT)
if (WIN32)
message(STATUS "Clang format not found! Downloading...")
set(CLANG_FORMAT "${PROJECT_BINARY_DIR}/externals/clang-format${CLANG_FORMAT_POSTFIX}.exe")
file(DOWNLOAD
https://github.com/citra-emu/ext-windows-bin/raw/master/clang-format${CLANG_FORMAT_POSTFIX}.exe
"${CLANG_FORMAT}" SHOW_PROGRESS
STATUS DOWNLOAD_SUCCESS)
if (NOT DOWNLOAD_SUCCESS EQUAL 0)
message(WARNING "Could not download clang format! Disabling the clang format target")
file(REMOVE ${CLANG_FORMAT})
unset(CLANG_FORMAT)
endif()
else()
message(WARNING "Clang format not found! Disabling the clang format target")
endif()
endif()
if (CLANG_FORMAT)
set(SRCS ${PROJECT_SOURCE_DIR}/src)
set(CCOMMENT "Running clang format against all the .h and .cpp files in src/")
if (WIN32)
if(MINGW)
add_custom_target(clang-format
COMMAND find `cygpath -u ${SRCS}` -iname *.h -o -iname *.cpp -o -iname *.mm | xargs `cygpath -u ${CLANG_FORMAT}` -i
COMMENT ${CCOMMENT})
else()
add_custom_target(clang-format
COMMAND powershell.exe -Command "Get-ChildItem '${SRCS}/*' -Include *.cpp,*.h,*.mm -Recurse | Foreach {&'${CLANG_FORMAT}' -i $_.fullname}"
COMMENT ${CCOMMENT})
endif()
else()
add_custom_target(clang-format
COMMAND find ${SRCS} -iname *.h -o -iname *.cpp -o -iname *.mm | xargs ${CLANG_FORMAT} -i
COMMENT ${CCOMMENT})
endif()
unset(SRCS)
unset(CCOMMENT)
endif()
add_subdirectory(third-party) add_subdirectory(third-party)
include_directories(src) include_directories(src)

256
src/.clang-format Normal file
View File

@ -0,0 +1,256 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^\<[^Q][^/.>]*\>'
Priority: -2
- Regex: '^\<'
Priority: -1
- Regex: '^\"'
Priority: 0
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 150
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
---
Language: Java
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
IncludeCategories:
- Regex: '^\<[^Q][^/.>]*\>'
Priority: -2
- Regex: '^\<'
Priority: -1
- Regex: '^\"'
Priority: 0
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 150
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
---
Language: ObjC
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
IncludeCategories:
- Regex: '^\<[^Q][^/.>]*\>'
Priority: -2
- Regex: '^\<'
Priority: -1
- Regex: '^\"'
Priority: 0
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 150
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
...

View File

@ -1,8 +1,9 @@
#include "controller.h"
#include <core/hle/libraries/libkernel/time_management.h> #include <core/hle/libraries/libkernel/time_management.h>
#include "controller.h"
namespace Emulator::Host::Controller { namespace Emulator::Host::Controller {
GameController::GameController() { m_states_num = 0; GameController::GameController() {
m_states_num = 0;
m_last_state = State(); m_last_state = State();
} }
void GameController::readState(State* state, bool* isConnected, int* connectedCount) { void GameController::readState(State* state, bool* isConnected, int* connectedCount) {

View File

@ -1,17 +1,17 @@
#pragma once #pragma once
#include "common/types.h"
#include <mutex> #include <mutex>
#include "common/types.h"
namespace Emulator::Host::Controller { namespace Emulator::Host::Controller {
struct State { struct State {
u32 buttonsState =0; u32 buttonsState = 0;
u64 time = 0; u64 time = 0;
}; };
constexpr u32 MAX_STATES = 64; constexpr u32 MAX_STATES = 64;
class GameController { class GameController {
public: public:
GameController(); GameController();
virtual ~GameController() = default; virtual ~GameController() = default;
@ -20,8 +20,7 @@ class GameController {
void checKButton(int id, u32 button, bool isPressed); void checKButton(int id, u32 button, bool isPressed);
void addState(const State& state); void addState(const State& state);
private:
private:
std::mutex m_mutex; std::mutex m_mutex;
bool m_connected = false; bool m_connected = false;
State m_last_state; State m_last_state;
@ -31,4 +30,4 @@ class GameController {
State m_states[MAX_STATES]; State m_states[MAX_STATES];
}; };
} // namespace Emulator::HLE::Libraries::Controller } // namespace Emulator::Host::Controller

View File

@ -1,5 +1,5 @@
#include "core/loader/elf.h"
#include "GUI/ElfViewer.h" #include "GUI/ElfViewer.h"
#include "core/loader/elf.h"
#include "imgui.h" #include "imgui.h"
ElfViewer::ElfViewer(Core::Loader::Elf* elf) { ElfViewer::ElfViewer(Core::Loader::Elf* elf) {
@ -15,82 +15,81 @@ void ElfViewer::Display(bool enabled) {
static int selected = -1; static int selected = -1;
ImGui::Begin("Self/Elf Viewer", &enabled); ImGui::Begin("Self/Elf Viewer", &enabled);
ImGui::BeginChild("Left Tree pane", ImVec2(300, 0), false);//left tree ImGui::BeginChild("Left Tree pane", ImVec2(300, 0), false); // left tree
if (elf->isSelfFile()) if (elf->isSelfFile()) {
{ if (ImGui::TreeNode("Self")) {
if (ImGui::TreeNode("Self")) if (ImGui::TreeNodeEx("Self Header",
{ ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen,
if (ImGui::TreeNodeEx("Self Header", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Self Header")) "Self Header")) {
{
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
selected = SELF_HEADER; selected = SELF_HEADER;
} }
if (ImGui::TreeNode("Self Segment Header")) if (ImGui::TreeNode("Self Segment Header")) {
{
const auto self = elf->GetSElfHeader(); const auto self = elf->GetSElfHeader();
for (u16 i = 0; i < self.segment_count; i++) for (u16 i = 0; i < self.segment_count; i++) {
{ if (ImGui::TreeNodeEx((void*)(intptr_t)i,
if (ImGui::TreeNodeEx((void*)(intptr_t)i, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "%d", i)) ImGuiTreeNodeFlags_Leaf |
{ ImGuiTreeNodeFlags_NoTreePushOnOpen,
"%d", i)) {
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
selected = SEG_HEADER_START+i; selected = SEG_HEADER_START + i;
} }
} }
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::TreeNodeEx("Self Id Header", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Self Id Header"); ImGui::TreeNodeEx("Self Id Header",
ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen,
"Self Id Header");
ImGui::TreePop(); ImGui::TreePop();
} }
} }
if (ImGui::TreeNode("Elf")) if (ImGui::TreeNode("Elf")) {
{
const auto elf_header = elf->GetElfHeader(); const auto elf_header = elf->GetElfHeader();
if (ImGui::TreeNodeEx("Elf Header", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Elf Header")) if (ImGui::TreeNodeEx("Elf Header",
{ ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen,
"Elf Header")) {
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
selected = ELF_HEADER; selected = ELF_HEADER;
} }
if (ImGui::TreeNode("Elf Program Headers")) if (ImGui::TreeNode("Elf Program Headers")) {
{
const auto pheader = elf->GetProgramHeader(); const auto pheader = elf->GetProgramHeader();
for (u16 i = 0; i < elf_header.e_phnum; i++) for (u16 i = 0; i < elf_header.e_phnum; i++) {
{ std::string ProgramInfo = elf->ElfPheaderFlagsStr(pheader[i].p_flags) + " " +
std::string ProgramInfo = elf->ElfPheaderFlagsStr(pheader[i].p_flags) + " " + elf->ElfPheaderTypeStr(pheader[i].p_type); elf->ElfPheaderTypeStr(pheader[i].p_type);
if (ImGui::TreeNodeEx((void*)(intptr_t)i,ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "%d - %s", i,ProgramInfo.c_str())) if (ImGui::TreeNodeEx((void*)(intptr_t)i,
{ ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen,
"%d - %s", i, ProgramInfo.c_str())) {
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
selected = ELF_PROGRAM_HEADER_START + i; selected = ELF_PROGRAM_HEADER_START + i;
} }
} }
ImGui::TreePop(); ImGui::TreePop();
} }
if (elf_header.e_shnum != 0) if (elf_header.e_shnum != 0) {
{ if (ImGui::TreeNode("Elf Section Headers")) {
if (ImGui::TreeNode("Elf Section Headers"))
{
ImGui::TreePop(); ImGui::TreePop();
} }
} }
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild();//end of left tree ImGui::EndChild(); // end of left tree
ImGui::SameLine(); ImGui::SameLine();
ImGui::BeginChild("Table View", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us ImGui::BeginChild(
"Table View",
ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
if (selected == SELF_HEADER) { if (selected == SELF_HEADER) {
ImGui::TextWrapped("%s", elf->SElfHeaderStr().c_str()); ImGui::TextWrapped("%s", elf->SElfHeaderStr().c_str());
} }
if (selected >= 100 && selected < 200) if (selected >= 100 && selected < 200) {
{ ImGui::TextWrapped("%s", elf->SELFSegHeader(selected - 100).c_str());
ImGui::TextWrapped("%s", elf->SELFSegHeader(selected-100).c_str());
} }
if (selected == ELF_HEADER) { if (selected == ELF_HEADER) {
ImGui::TextWrapped("%s", elf->ElfHeaderStr().c_str()); ImGui::TextWrapped("%s", elf->ElfHeaderStr().c_str());
} }
if (selected >= 200 && selected < 300) if (selected >= 200 && selected < 300) {
{
ImGui::TextWrapped("%s", elf->ElfPHeaderStr(selected - 200).c_str()); ImGui::TextWrapped("%s", elf->ElfPHeaderStr(selected - 200).c_str());
} }
ImGui::EndChild(); ImGui::EndChild();

View File

@ -12,10 +12,18 @@ u32 screenWidth = 1280;
u32 screenHeight = 720; u32 screenHeight = 720;
u32 logLevel = 0; // TRACE = 0 , DEBUG = 1 , INFO = 2 , WARN = 3 , ERROR = 4 , CRITICAL = 5, OFF = 6 u32 logLevel = 0; // TRACE = 0 , DEBUG = 1 , INFO = 2 , WARN = 3 , ERROR = 4 , CRITICAL = 5, OFF = 6
bool isNeoMode() { return isNeo; } bool isNeoMode() {
u32 getScreenWidth() { return screenWidth; } return isNeo;
u32 getScreenHeight() { return screenHeight; } }
u32 getLogLevel() { return logLevel; } u32 getScreenWidth() {
return screenWidth;
}
u32 getScreenHeight() {
return screenHeight;
}
u32 getLogLevel() {
return logLevel;
}
void load(const std::filesystem::path& path) { void load(const std::filesystem::path& path) {
// If the configuration file does not exist, create it and return // If the configuration file does not exist, create it and return
@ -67,7 +75,8 @@ void save(const std::filesystem::path& path) {
} }
} else { } else {
if (error) { if (error) {
fmt::print("Filesystem error accessing {} (error: {})\n", path.string(), error.message().c_str()); fmt::print("Filesystem error accessing {} (error: {})\n", path.string(),
error.message().c_str());
} }
fmt::print("Saving new configuration file {}\n", path.string()); fmt::print("Saving new configuration file {}\n", path.string());
} }

View File

@ -1,5 +1,5 @@
#include "common/disassembler.h"
#include <fmt/format.h> #include <fmt/format.h>
#include "common/disassembler.h"
namespace Common { namespace Common {
@ -13,19 +13,20 @@ Disassembler::~Disassembler() = default;
void Disassembler::printInstruction(void* code, u64 address) { void Disassembler::printInstruction(void* code, u64 address) {
ZydisDecodedInstruction instruction; ZydisDecodedInstruction instruction;
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE]; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
ZyanStatus status = ZydisDecoderDecodeFull(&m_decoder, code, sizeof(code), ZyanStatus status =
&instruction, operands); ZydisDecoderDecodeFull(&m_decoder, code, sizeof(code), &instruction, operands);
if (!ZYAN_SUCCESS(status)) { if (!ZYAN_SUCCESS(status)) {
fmt::print("decode instruction failed at {}\n", fmt::ptr(code)); fmt::print("decode instruction failed at {}\n", fmt::ptr(code));
} else { } else {
printInst(instruction, operands,address); printInst(instruction, operands, address);
} }
} }
void Disassembler::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, u64 address) { void Disassembler::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands,
u64 address) {
const int bufLen = 256; const int bufLen = 256;
char szBuffer[bufLen]; char szBuffer[bufLen];
ZydisFormatterFormatInstruction(&m_formatter, &inst, operands,inst.operand_count_visible, ZydisFormatterFormatInstruction(&m_formatter, &inst, operands, inst.operand_count_visible,
szBuffer, sizeof(szBuffer), address, ZYAN_NULL); szBuffer, sizeof(szBuffer), address, ZYAN_NULL);
fmt::print("instruction: {}\n", szBuffer); fmt::print("instruction: {}\n", szBuffer);
} }

View File

@ -1,19 +1,19 @@
#pragma once #pragma once
#include <discord_rpc.h>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <discord_rpc.h>
namespace Discord { namespace Discord {
enum class RPCStatus { Idling, Playing }; enum class RPCStatus { Idling, Playing };
class RPC { class RPC {
std::uint64_t startTimestamp; std::uint64_t startTimestamp;
bool enabled = false; bool enabled = false;
public: public:
void init(); void init();
void update(RPCStatus status, const std::string& title); void update(RPCStatus status, const std::string& title);
void stop(); void stop();
}; };
} // namespace Discord } // namespace Discord

View File

@ -2,19 +2,15 @@
#include <bit> #include <bit>
#include <cstdio> #include <cstdio>
#include <string>
#include <span> #include <span>
#include <string>
#include <vector> #include <vector>
#include "common/types.h" #include "common/types.h"
namespace Common::FS { namespace Common::FS {
enum class OpenMode : u32 { enum class OpenMode : u32 { Read = 0x1, Write = 0x2, ReadWrite = Read | Write };
Read = 0x1,
Write = 0x2,
ReadWrite = Read | Write
};
enum class SeekMode : u32 { enum class SeekMode : u32 {
Set, Set,
@ -23,7 +19,7 @@ enum class SeekMode : u32 {
}; };
class File { class File {
public: public:
File(); File();
explicit File(const std::string& path, OpenMode mode = OpenMode::Read); explicit File(const std::string& path, OpenMode mode = OpenMode::Read);
~File(); ~File();
@ -80,7 +76,7 @@ class File {
return m_file; return m_file;
} }
private: private:
std::FILE* m_file{}; std::FILE* m_file{};
}; };

View File

@ -1,6 +1,6 @@
#include "io_file.h" #include "io_file.h"
//#include "helpers.hpp" // #include "helpers.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
// 64 bit offsets for MSVC // 64 bit offsets for MSVC
@ -118,7 +118,7 @@ FILE* IOFile::getHandle() {
} }
void IOFile::setAppDataDir(const std::filesystem::path& dir) { void IOFile::setAppDataDir(const std::filesystem::path& dir) {
//if (dir == "") // if (dir == "")
// Helpers::panic("Failed to set app data directory"); // Helpers::panic("Failed to set app data directory");
appData = dir; appData = dir;
} }

View File

@ -5,7 +5,8 @@
class IOFile { class IOFile {
FILE* handle = nullptr; FILE* handle = nullptr;
static inline std::filesystem::path appData =""; // Directory for holding app data. AppData on Windows static inline std::filesystem::path appData =
""; // Directory for holding app data. AppData on Windows
public: public:
IOFile() : handle(nullptr) {} IOFile() : handle(nullptr) {}

View File

@ -1,10 +1,10 @@
#include <vector>
#include <Util/config.h>
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/pattern_formatter.h> #include <spdlog/pattern_formatter.h>
#include <spdlog/sinks/basic_file_sink.h> #include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <vector>
#include <Util/config.h>
#include "common/log.h" #include "common/log.h"
#ifdef _WIN64 #ifdef _WIN64
#include <windows.h> #include <windows.h>
@ -30,19 +30,20 @@ uint64_t tls_access(int64_t tls_offset) {
#ifdef _WIN64 #ifdef _WIN64
static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept {
auto orig_rip = pExp->ContextRecord->Rip; auto orig_rip = pExp->ContextRecord->Rip;
while (*(uint8_t *)pExp->ContextRecord->Rip == 0x66) pExp->ContextRecord->Rip++; while (*(uint8_t*)pExp->ContextRecord->Rip == 0x66)
pExp->ContextRecord->Rip++;
if (*(uint8_t *)pExp->ContextRecord->Rip == 0xcd) { if (*(uint8_t*)pExp->ContextRecord->Rip == 0xcd) {
int reg = *(uint8_t *)(pExp->ContextRecord->Rip + 1) - 0x80; int reg = *(uint8_t*)(pExp->ContextRecord->Rip + 1) - 0x80;
int sizes = *(uint8_t *)(pExp->ContextRecord->Rip + 2); int sizes = *(uint8_t*)(pExp->ContextRecord->Rip + 2);
int pattern_size = sizes & 0xF; int pattern_size = sizes & 0xF;
int imm_size = sizes >> 4; int imm_size = sizes >> 4;
int64_t tls_offset; int64_t tls_offset;
if (imm_size == 4) if (imm_size == 4)
tls_offset = *(int32_t *)(pExp->ContextRecord->Rip + pattern_size); tls_offset = *(int32_t*)(pExp->ContextRecord->Rip + pattern_size);
else else
tls_offset = *(int64_t *)(pExp->ContextRecord->Rip + pattern_size); tls_offset = *(int64_t*)(pExp->ContextRecord->Rip + pattern_size);
(&pExp->ContextRecord->Rax)[reg] = tls_access(tls_offset); /* TLS_ACCESS */ (&pExp->ContextRecord->Rax)[reg] = tls_access(tls_offset); /* TLS_ACCESS */
pExp->ContextRecord->Rip += pattern_size + imm_size; pExp->ContextRecord->Rip += pattern_size + imm_size;
@ -72,22 +73,27 @@ static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept {
break; break;
} }
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ARRAY_BOUNDS_EXCEEDED ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ARRAY_BOUNDS_EXCEEDED ({:#x}). ",
ec);
break; break;
case EXCEPTION_DATATYPE_MISALIGNMENT: case EXCEPTION_DATATYPE_MISALIGNMENT:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_DATATYPE_MISALIGNMENT ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_DATATYPE_MISALIGNMENT ({:#x}). ",
ec);
break; break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_DIVIDE_BY_ZERO:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_FLT_DIVIDE_BY_ZERO ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_FLT_DIVIDE_BY_ZERO ({:#x}). ",
ec);
break; break;
case EXCEPTION_ILLEGAL_INSTRUCTION: case EXCEPTION_ILLEGAL_INSTRUCTION:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ILLEGAL_INSTRUCTION ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ILLEGAL_INSTRUCTION ({:#x}). ",
ec);
break; break;
case EXCEPTION_IN_PAGE_ERROR: case EXCEPTION_IN_PAGE_ERROR:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_IN_PAGE_ERROR ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_IN_PAGE_ERROR ({:#x}). ", ec);
break; break;
case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_DIVIDE_BY_ZERO:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_INT_DIVIDE_BY_ZERO ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_INT_DIVIDE_BY_ZERO ({:#x}). ",
ec);
break; break;
case EXCEPTION_PRIV_INSTRUCTION: case EXCEPTION_PRIV_INSTRUCTION:
LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_PRIV_INSTRUCTION ({:#x}). ", ec); LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_PRIV_INSTRUCTION ({:#x}). ", ec);
@ -103,7 +109,6 @@ static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept {
} }
#endif #endif
int Init(bool use_stdout) { int Init(bool use_stdout) {
sinks.clear(); sinks.clear();
if (use_stdout) { if (use_stdout) {
@ -114,8 +119,10 @@ int Init(bool use_stdout) {
#else #else
sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>("shadps4.txt", true)); sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>("shadps4.txt", true));
#endif #endif
spdlog::set_default_logger(std::make_shared<spdlog::logger>("shadps4 logger", begin(sinks), end(sinks))); spdlog::set_default_logger(
auto f = std::make_unique<spdlog::pattern_formatter>("%^|%L|: %v%$", spdlog::pattern_time_type::local, std::string("")); // disable eol std::make_shared<spdlog::logger>("shadps4 logger", begin(sinks), end(sinks)));
auto f = std::make_unique<spdlog::pattern_formatter>(
"%^|%L|: %v%$", spdlog::pattern_time_type::local, std::string("")); // disable eol
spdlog::set_formatter(std::move(f)); spdlog::set_formatter(std::move(f));
spdlog::set_level(static_cast<spdlog::level::level_enum>(Config::getLogLevel())); spdlog::set_level(static_cast<spdlog::level::level_enum>(Config::getLogLevel()));
@ -129,13 +136,14 @@ int Init(bool use_stdout) {
old_terminate = std::set_terminate([]() { old_terminate = std::set_terminate([]() {
try { try {
std::rethrow_exception(std::current_exception()); std::rethrow_exception(std::current_exception());
} catch (const std::exception &e) { } catch (const std::exception& e) {
LOG_CRITICAL_IF(log_file_exceptions, "Unhandled C++ exception. {}", e.what()); LOG_CRITICAL_IF(log_file_exceptions, "Unhandled C++ exception. {}", e.what());
} catch (...) { } catch (...) {
LOG_CRITICAL_IF(log_file_exceptions, "Unhandled C++ exception. UNKNOWN"); LOG_CRITICAL_IF(log_file_exceptions, "Unhandled C++ exception. UNKNOWN");
} }
Flush(); Flush();
if (old_terminate) old_terminate(); if (old_terminate)
old_terminate();
}); });
return 0; return 0;

View File

@ -14,17 +14,23 @@ namespace Common::Log {
#define LOG_CRITICAL SPDLOG_CRITICAL #define LOG_CRITICAL SPDLOG_CRITICAL
#define LOG_TRACE_IF(flag, ...) \ #define LOG_TRACE_IF(flag, ...) \
if (flag) LOG_TRACE(__VA_ARGS__) if (flag) \
LOG_TRACE(__VA_ARGS__)
#define LOG_DEBUG_IF(flag, ...) \ #define LOG_DEBUG_IF(flag, ...) \
if (flag) LOG_DEBUG(__VA_ARGS__) if (flag) \
LOG_DEBUG(__VA_ARGS__)
#define LOG_INFO_IF(flag, ...) \ #define LOG_INFO_IF(flag, ...) \
if (flag) LOG_INFO(__VA_ARGS__) if (flag) \
LOG_INFO(__VA_ARGS__)
#define LOG_WARN_IF(flag, ...) \ #define LOG_WARN_IF(flag, ...) \
if (flag) LOG_WARN(__VA_ARGS__) if (flag) \
LOG_WARN(__VA_ARGS__)
#define LOG_ERROR_IF(flag, ...) \ #define LOG_ERROR_IF(flag, ...) \
if (flag) LOG_ERROR(__VA_ARGS__) if (flag) \
LOG_ERROR(__VA_ARGS__)
#define LOG_CRITICAL_IF(flag, ...) \ #define LOG_CRITICAL_IF(flag, ...) \
if (flag) LOG_CRITICAL(__VA_ARGS__) if (flag) \
LOG_CRITICAL(__VA_ARGS__)
int Init(bool use_stdout); int Init(bool use_stdout);

View File

@ -1,9 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/uint128.h"
#include "common/native_clock.h" #include "common/native_clock.h"
#include "common/rdtsc.h" #include "common/rdtsc.h"
#include "common/uint128.h"
#ifdef _WIN64 #ifdef _WIN64
#include <pthread_time.h> #include <pthread_time.h>
#else #else
@ -13,8 +13,8 @@
namespace Common { namespace Common {
NativeClock::NativeClock() NativeClock::NativeClock()
: rdtsc_frequency{EstimateRDTSCFrequency()}, ns_rdtsc_factor{GetFixedPoint64Factor(std::nano::den, : rdtsc_frequency{EstimateRDTSCFrequency()}, ns_rdtsc_factor{GetFixedPoint64Factor(
rdtsc_frequency)}, std::nano::den, rdtsc_frequency)},
us_rdtsc_factor{GetFixedPoint64Factor(std::micro::den, rdtsc_frequency)}, us_rdtsc_factor{GetFixedPoint64Factor(std::micro::den, rdtsc_frequency)},
ms_rdtsc_factor{GetFixedPoint64Factor(std::milli::den, rdtsc_frequency)} {} ms_rdtsc_factor{GetFixedPoint64Factor(std::milli::den, rdtsc_frequency)} {}
@ -40,4 +40,4 @@ u64 NativeClock::GetProcessTimeUS() const {
return ret.tv_nsec / 1000 + ret.tv_sec * 1000000; return ret.tv_nsec / 1000 + ret.tv_sec * 1000000;
} }
} // namespace Common::X64 } // namespace Common

View File

@ -5,7 +5,7 @@
namespace Common { namespace Common {
std::vector<std::string> SplitString(const std::string &str, char delimiter) { std::vector<std::string> SplitString(const std::string& str, char delimiter) {
std::istringstream iss(str); std::istringstream iss(str);
std::vector<std::string> output(1); std::vector<std::string> output(1);

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <vector>
#include <string> #include <string>
#include <vector>
namespace Common { namespace Common {

View File

@ -22,6 +22,12 @@ static_assert(sizeof(u128) == 16, "u128 must be 128 bits wide");
#define PS4_SYSV_ABI __attribute__((sysv_abi)) #define PS4_SYSV_ABI __attribute__((sysv_abi))
// UDLs for memory size values // UDLs for memory size values
constexpr unsigned long long operator""_KB(unsigned long long x) { return 1024ULL * x; } constexpr unsigned long long operator""_KB(unsigned long long x) {
constexpr unsigned long long operator""_MB(unsigned long long x) { return 1024_KB * x; } return 1024ULL * x;
constexpr unsigned long long operator""_GB(unsigned long long x) { return 1024_MB * x; } }
constexpr unsigned long long operator""_MB(unsigned long long x) {
return 1024_KB * x;
}
constexpr unsigned long long operator""_GB(unsigned long long x) {
return 1024_MB * x;
}

View File

@ -1,10 +1,11 @@
#include "gpu_memory.h"
#include <atomic> #include <atomic>
#include <xxh3.h> #include <xxh3.h>
#include "gpu_memory.h"
#include "common/singleton.h" #include "common/singleton.h"
void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size, void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size,
const GPUObject& info) { const GPUObject& info) {
auto* gpumemory = Common::Singleton<GPUMemory>::Instance(); auto* gpumemory = Common::Singleton<GPUMemory>::Instance();
@ -23,9 +24,12 @@ void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) {
gpumemory->m_heaps.push_back(h); gpumemory->m_heaps.push_back(h);
} }
u64 GPU::calculate_hash(const u08* buf, u64 size) { return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0); } u64 GPU::calculate_hash(const u08* buf, u64 size) {
return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0);
}
bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem) { bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx,
HLE::Libs::Graphics::VulkanMemory* mem) {
static std::atomic_uint64_t unique_id = 0; static std::atomic_uint64_t unique_id = 0;
VkPhysicalDeviceMemoryProperties memory_properties{}; VkPhysicalDeviceMemoryProperties memory_properties{};
@ -66,7 +70,8 @@ void GPU::flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx) {
int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) {
int index = 0; int index = 0;
for (const auto& heap : m_heaps) { for (const auto& heap : m_heaps) {
if ((virtual_addr >= heap.allocated_virtual_addr && virtual_addr < heap.allocated_virtual_addr + heap.allocated_size) || if ((virtual_addr >= heap.allocated_virtual_addr &&
virtual_addr < heap.allocated_virtual_addr + heap.allocated_size) ||
((virtual_addr + size - 1) >= heap.allocated_virtual_addr && ((virtual_addr + size - 1) >= heap.allocated_virtual_addr &&
(virtual_addr + size - 1) < heap.allocated_virtual_addr + heap.allocated_size)) { (virtual_addr + size - 1) < heap.allocated_virtual_addr + heap.allocated_size)) {
return index; return index;
@ -76,7 +81,8 @@ int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) {
return -1; return -1;
} }
void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, const u64* virtual_addr, const u64* size, void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
void* todo, const u64* virtual_addr, const u64* size,
int virtual_addr_num, const GPUObject& info) { int virtual_addr_num, const GPUObject& info) {
auto* gpumemory = Common::Singleton<GPUMemory>::Instance(); auto* gpumemory = Common::Singleton<GPUMemory>::Instance();
@ -101,7 +107,8 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
for (int h = 0; h < virtual_addr_num; h++) { for (int h = 0; h < virtual_addr_num; h++) {
if (info.check_hash) { if (info.check_hash) {
objInfo.hash[h] = GPU::calculate_hash(reinterpret_cast<const u08*>(virtual_addr[h]), size[h]); objInfo.hash[h] =
GPU::calculate_hash(reinterpret_cast<const u08*>(virtual_addr[h]), size[h]);
} else { } else {
objInfo.hash[h] = 0; objInfo.hash[h] = 0;
} }
@ -109,7 +116,8 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
objInfo.submit_id = submit_id; objInfo.submit_id = submit_id;
objInfo.check_hash = info.check_hash; objInfo.check_hash = info.check_hash;
objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size, virtual_addr_num, &objInfo.mem); objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size,
virtual_addr_num, &objInfo.mem);
objInfo.update_func = info.getUpdateFunc(); objInfo.update_func = info.getUpdateFunc();
int index = static_cast<int>(heap.objects.size()); int index = static_cast<int>(heap.objects.size());
@ -123,7 +131,8 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
return objInfo.gpu_object.obj; return objInfo.gpu_object.obj;
} }
GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id) { GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u64* size,
int virtual_addr_num, int heap_id, int obj_id) {
auto& heap = m_heaps[heap_id]; auto& heap = m_heaps[heap_id];
GPU::HeapBlock heapBlock{}; GPU::HeapBlock heapBlock{};
@ -135,7 +144,8 @@ GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u6
return heapBlock; return heapBlock;
} }
void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id) { void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id,
int obj_id) {
auto& heap = m_heaps[heap_id]; auto& heap = m_heaps[heap_id];
auto& heapObj = heap.objects[obj_id]; auto& heapObj = heap.objects[obj_id];
@ -147,7 +157,9 @@ void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
for (int i = 0; i < heapObj.block.virtual_addr_num; i++) { for (int i = 0; i < heapObj.block.virtual_addr_num; i++) {
if (objInfo.check_hash) { if (objInfo.check_hash) {
hash[i] = GPU::calculate_hash(reinterpret_cast<const uint8_t*>(heapObj.block.virtual_addr[i]), heapObj.block.size[i]); hash[i] = GPU::calculate_hash(
reinterpret_cast<const uint8_t*>(heapObj.block.virtual_addr[i]),
heapObj.block.size[i]);
} else { } else {
hash[i] = 0; hash[i] = 0;
} }
@ -166,7 +178,8 @@ void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
} }
if (need_update) { if (need_update) {
objInfo.update_func(ctx, objInfo.obj_params, objInfo.gpu_object.obj, heapObj.block.virtual_addr, heapObj.block.size, objInfo.update_func(ctx, objInfo.obj_params, objInfo.gpu_object.obj,
heapObj.block.virtual_addr, heapObj.block.size,
heapObj.block.virtual_addr_num); heapObj.block.virtual_addr_num);
} }
} }

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <core/PS4/HLE/Graphics/graphics_ctx.h>
#include "common/types.h"
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include <core/PS4/HLE/Graphics/graphics_ctx.h>
#include "common/types.h"
namespace GPU { namespace GPU {
@ -24,7 +24,7 @@ struct HeapBlock {
}; };
class GPUObject { class GPUObject {
public: public:
GPUObject() = default; GPUObject() = default;
virtual ~GPUObject() = default; virtual ~GPUObject() = default;
u64 obj_params[8] = {}; u64 obj_params[8] = {};
@ -32,9 +32,11 @@ class GPUObject {
bool isReadOnly = false; bool isReadOnly = false;
MemoryObjectType objectType = MemoryObjectType::InvalidObj; MemoryObjectType objectType = MemoryObjectType::InvalidObj;
using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params,
const u64* virtual_addr, const u64* size, int virtual_addr_num,
HLE::Libs::Graphics::VulkanMemory* mem); HLE::Libs::Graphics::VulkanMemory* mem);
using update_func_t = void (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, using update_func_t = void (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params,
void* obj, const u64* virtual_addr, const u64* size,
int virtual_addr_num); int virtual_addr_num);
virtual create_func_t getCreateFunc() const = 0; virtual create_func_t getCreateFunc() const = 0;
@ -63,23 +65,27 @@ struct MemoryHeap {
}; };
class GPUMemory { class GPUMemory {
public: public:
GPUMemory() {} GPUMemory() {}
virtual ~GPUMemory() {} virtual ~GPUMemory() {}
int getHeapId(u64 vaddr, u64 size); int getHeapId(u64 vaddr, u64 size);
std::mutex m_mutex; std::mutex m_mutex;
std::vector<MemoryHeap> m_heaps; std::vector<MemoryHeap> m_heaps;
void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
/*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr,
const u64* size, int virtual_addr_num, const GPUObject& info); const u64* size, int virtual_addr_num, const GPUObject& info);
HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num,
int heap_id, int obj_id);
void update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id); void update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id);
void flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx); void flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx);
}; };
void memorySetAllocArea(u64 virtual_addr, u64 size); void memorySetAllocArea(u64 virtual_addr, u64 size);
void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
/*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size,
const GPUObject& info); const GPUObject& info);
u64 calculate_hash(const u08* buf, u64 size); u64 calculate_hash(const u08* buf, u64 size);
bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem); bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx,
HLE::Libs::Graphics::VulkanMemory* mem);
void flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx); void flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx);
} // namespace GPU } // namespace GPU

View File

@ -1,20 +1,22 @@
#include "tile_manager.h"
#include "common/singleton.h"
#include <mutex> #include <mutex>
#include "common/singleton.h"
#include "tile_manager.h"
namespace GPU { namespace GPU {
static u32 IntLog2(u32 i) { return 31 - __builtin_clz(i | 1u); } static u32 IntLog2(u32 i) {
return 31 - __builtin_clz(i | 1u);
}
class TileManager { class TileManager {
public: public:
TileManager(){} TileManager() {}
virtual ~TileManager() { } virtual ~TileManager() {}
std::mutex m_mutex; std::mutex m_mutex;
}; };
class TileManager32 { class TileManager32 {
public: public:
u32 m_macro_tile_height = 0; u32 m_macro_tile_height = 0;
u32 m_bank_height = 0; u32 m_bank_height = 0;
u32 m_num_banks = 0; u32 m_num_banks = 0;
@ -69,7 +71,8 @@ class TileManager32 {
return pipe; return pipe;
} }
static u32 getBankIdx(u32 x, u32 y, u32 bank_width, u32 bank_height, u32 num_banks, u32 num_pipes) { static u32 getBankIdx(u32 x, u32 y, u32 bank_width, u32 bank_height, u32 num_banks,
u32 num_pipes) {
const u32 x_shift_offset = IntLog2(bank_width * num_pipes); const u32 x_shift_offset = IntLog2(bank_width * num_pipes);
const u32 y_shift_offset = IntLog2(bank_height); const u32 y_shift_offset = IntLog2(bank_height);
const u32 xs = x >> x_shift_offset; const u32 xs = x >> x_shift_offset;
@ -110,11 +113,13 @@ class TileManager32 {
tile_bytes = 512; tile_bytes = 512;
} }
u64 macro_tile_bytes = (128 / 8) * (m_macro_tile_height / 8) * tile_bytes / (m_num_pipes * m_num_banks); u64 macro_tile_bytes =
(128 / 8) * (m_macro_tile_height / 8) * tile_bytes / (m_num_pipes * m_num_banks);
u64 macro_tiles_per_row = m_padded_width / 128; u64 macro_tiles_per_row = m_padded_width / 128;
u64 macro_tile_row_index = y / m_macro_tile_height; u64 macro_tile_row_index = y / m_macro_tile_height;
u64 macro_tile_column_index = x / 128; u64 macro_tile_column_index = x / 128;
u64 macro_tile_index = (macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index; u64 macro_tile_index =
(macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index;
u64 macro_tile_offset = macro_tile_index * macro_tile_bytes; u64 macro_tile_offset = macro_tile_index * macro_tile_bytes;
u64 macro_tiles_per_slice = macro_tiles_per_row * (m_padded_height / m_macro_tile_height); u64 macro_tiles_per_slice = macro_tiles_per_row * (m_padded_height / m_macro_tile_height);
u64 slice_bytes = macro_tiles_per_slice * macro_tile_bytes; u64 slice_bytes = macro_tiles_per_slice * macro_tile_bytes;
@ -133,13 +138,14 @@ class TileManager32 {
u64 pipe_interleave_offset = total_offset & 0xffu; u64 pipe_interleave_offset = total_offset & 0xffu;
u64 offset = total_offset >> 8u; u64 offset = total_offset >> 8u;
u64 byte_offset = pipe_interleave_offset | (pipe << (8u)) | (bank << (8u + m_pipe_bits)) | (offset << (8u + m_pipe_bits + m_bank_bits)); u64 byte_offset = pipe_interleave_offset | (pipe << (8u)) | (bank << (8u + m_pipe_bits)) |
(offset << (8u + m_pipe_bits + m_bank_bits));
return ((byte_offset << 3u) | bit_offset) / 8; return ((byte_offset << 3u) | bit_offset) / 8;
} }
}; };
void convertTileToLinear(void* dst, const void* src,u32 width, u32 height, bool is_neo) { void convertTileToLinear(void* dst, const void* src, u32 width, u32 height, bool is_neo) {
TileManager32 t; TileManager32 t;
t.Init(width, height, is_neo); t.Init(width, height, is_neo);

View File

@ -2,14 +2,14 @@
#include "common/log.h" #include "common/log.h"
#include "common/debug.h"
#include <vulkan_util.h> #include <vulkan_util.h>
#include "common/debug.h"
#include "tile_manager.h" #include "tile_manager.h"
constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging
static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj,
int virtual_addr_num) { const u64* virtual_addr, const u64* size, int virtual_addr_num) {
auto pitch = params[GPU::VideoOutBufferObj::PITCH_PARAM]; auto pitch = params[GPU::VideoOutBufferObj::PITCH_PARAM];
bool tiled = (params[GPU::VideoOutBufferObj::IS_TILE_PARAM] != 0); bool tiled = (params[GPU::VideoOutBufferObj::IS_TILE_PARAM] != 0);
@ -21,19 +21,22 @@ static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params,
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
if (tiled) if (tiled) {
{
std::vector<u08> tempbuff(*size); std::vector<u08> tempbuff(*size);
GPU::convertTileToLinear(tempbuff.data(), reinterpret_cast<void*>(*virtual_addr), width, height, neo); GPU::convertTileToLinear(tempbuff.data(), reinterpret_cast<void*>(*virtual_addr), width,
Graphics::Vulkan::vulkanFillImage(ctx, vk_obj, tempbuff.data(), *size, pitch, static_cast<u64>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); height, neo);
Graphics::Vulkan::vulkanFillImage(
ctx, vk_obj, tempbuff.data(), *size, pitch,
static_cast<u64>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
} else { } else {
Graphics::Vulkan::vulkanFillImage(ctx, vk_obj, reinterpret_cast<void*>(*virtual_addr), *size, pitch, Graphics::Vulkan::vulkanFillImage(
ctx, vk_obj, reinterpret_cast<void*>(*virtual_addr), *size, pitch,
static_cast<u64>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); static_cast<u64>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
} }
} }
static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params,
const u64* virtual_addr, const u64* size, int virtual_addr_num,
HLE::Libs::Graphics::VulkanMemory* mem) { HLE::Libs::Graphics::VulkanMemory* mem) {
auto pixel_format = params[GPU::VideoOutBufferObj::PIXEL_FORMAT_PARAM]; auto pixel_format = params[GPU::VideoOutBufferObj::PIXEL_FORMAT_PARAM];
auto width = params[GPU::VideoOutBufferObj::WIDTH_PARAM]; auto width = params[GPU::VideoOutBufferObj::WIDTH_PARAM];
@ -44,9 +47,15 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params
VkFormat vk_format = VK_FORMAT_UNDEFINED; VkFormat vk_format = VK_FORMAT_UNDEFINED;
switch (pixel_format) { switch (pixel_format) {
case static_cast<uint64_t>(GPU::VideoOutBufferFormat::R8G8B8A8Srgb): vk_format = VK_FORMAT_R8G8B8A8_SRGB; break; case static_cast<uint64_t>(GPU::VideoOutBufferFormat::R8G8B8A8Srgb):
case static_cast<uint64_t>(GPU::VideoOutBufferFormat::B8G8R8A8Srgb): vk_format = VK_FORMAT_B8G8R8A8_SRGB; break; vk_format = VK_FORMAT_R8G8B8A8_SRGB;
default: LOG_CRITICAL_IF(log_file_videoOutBuffer, "unknown pixelFormat = {}\n", pixel_format); std::exit(0); break;
case static_cast<uint64_t>(GPU::VideoOutBufferFormat::B8G8R8A8Srgb):
vk_format = VK_FORMAT_B8G8R8A8_SRGB;
break;
default:
LOG_CRITICAL_IF(log_file_videoOutBuffer, "unknown pixelFormat = {}\n", pixel_format);
std::exit(0);
} }
vk_obj->extent.width = width; vk_obj->extent.width = width;
@ -72,8 +81,9 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params
image_info.format = vk_obj->format; image_info.format = vk_obj->format;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.initialLayout = vk_obj->layout; image_info.initialLayout = vk_obj->layout;
image_info.usage = image_info.usage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) | VK_IMAGE_USAGE_TRANSFER_DST_BIT; VK_IMAGE_USAGE_TRANSFER_SRC_BIT) |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.samples = VK_SAMPLE_COUNT_1_BIT;
@ -124,7 +134,8 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params
create_info.subresourceRange.layerCount = 1; create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1; create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->m_device, &create_info, nullptr, &vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT]); vkCreateImageView(ctx->m_device, &create_info, nullptr,
&vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT]);
if (vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT] == nullptr) { if (vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT] == nullptr) {
LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image_view is null\n"); LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image_view is null\n");
@ -134,6 +145,10 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params
return vk_obj; return vk_obj;
} }
GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const { return create_func; } GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const {
return create_func;
}
GPU::GPUObject::update_func_t GPU::VideoOutBufferObj::getUpdateFunc() const { return update_func; } GPU::GPUObject::update_func_t GPU::VideoOutBufferObj::getUpdateFunc() const {
return update_func;
}

View File

@ -13,7 +13,7 @@ enum class VideoOutBufferFormat : u64 {
}; };
class VideoOutBufferObj : public GPUObject { class VideoOutBufferObj : public GPUObject {
public: public:
static constexpr int PIXEL_FORMAT_PARAM = 0; static constexpr int PIXEL_FORMAT_PARAM = 0;
static constexpr int WIDTH_PARAM = 1; static constexpr int WIDTH_PARAM = 1;
static constexpr int HEIGHT_PARAM = 2; static constexpr int HEIGHT_PARAM = 2;
@ -21,7 +21,8 @@ class VideoOutBufferObj : public GPUObject {
static constexpr int IS_NEO_PARAM = 4; static constexpr int IS_NEO_PARAM = 4;
static constexpr int PITCH_PARAM = 5; static constexpr int PITCH_PARAM = 5;
explicit VideoOutBufferObj(VideoOutBufferFormat pixel_format, u32 width, u32 height, bool is_tiled, bool is_neo, u32 pitch) { explicit VideoOutBufferObj(VideoOutBufferFormat pixel_format, u32 width, u32 height,
bool is_tiled, bool is_neo, u32 pitch) {
obj_params[PIXEL_FORMAT_PARAM] = static_cast<uint64_t>(pixel_format); obj_params[PIXEL_FORMAT_PARAM] = static_cast<uint64_t>(pixel_format);
obj_params[WIDTH_PARAM] = width; obj_params[WIDTH_PARAM] = width;
obj_params[HEIGHT_PARAM] = height; obj_params[HEIGHT_PARAM] = height;

View File

@ -91,7 +91,8 @@ bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
bool FlipQueue::flip(u32 micros) { bool FlipQueue::flip(u32 micros) {
const auto request = [&]() -> Request* { const auto request = [&]() -> Request* {
std::unique_lock lock{m_mutex}; std::unique_lock lock{m_mutex};
m_submit_cond.wait_for(lock, std::chrono::microseconds(micros), [&] { return !m_requests.empty(); }); m_submit_cond.wait_for(lock, std::chrono::microseconds(micros),
[&] { return !m_requests.empty(); });
if (m_requests.empty()) { if (m_requests.empty()) {
return nullptr; return nullptr;
} }
@ -111,7 +112,8 @@ bool FlipQueue::flip(u32 micros) {
std::scoped_lock cfg_lock{request->cfg->m_mutex}; std::scoped_lock cfg_lock{request->cfg->m_mutex};
for (auto& flip_eq : request->cfg->m_flip_evtEq) { for (auto& flip_eq : request->cfg->m_flip_evtEq) {
if (flip_eq != nullptr) { if (flip_eq != nullptr) {
flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, Core::Kernel::EVFILT_VIDEO_OUT, reinterpret_cast<void*>(request->flip_arg)); flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, Core::Kernel::EVFILT_VIDEO_OUT,
reinterpret_cast<void*>(request->flip_arg));
} }
} }
} }

View File

@ -2,8 +2,8 @@
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <core/PS4/HLE/Graphics/video_out.h>
#include <core/PS4/HLE/Graphics/graphics_ctx.h> #include <core/PS4/HLE/Graphics/graphics_ctx.h>
#include <core/PS4/HLE/Graphics/video_out.h>
#include <emulator.h> #include <emulator.h>
using namespace HLE::Libs::Graphics::VideoOut; using namespace HLE::Libs::Graphics::VideoOut;
@ -32,14 +32,15 @@ struct VideoConfigInternal {
}; };
class FlipQueue { class FlipQueue {
public: public:
FlipQueue() {} FlipQueue() {}
virtual ~FlipQueue() {} virtual ~FlipQueue() {}
void getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out); void getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out);
bool submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg); bool submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg);
bool flip(u32 micros); bool flip(u32 micros);
private:
private:
struct Request { struct Request {
VideoConfigInternal* cfg; VideoConfigInternal* cfg;
int index; int index;
@ -55,14 +56,16 @@ class FlipQueue {
class VideoOutCtx { class VideoOutCtx {
public: public:
VideoOutCtx() {} VideoOutCtx() {}
virtual ~VideoOutCtx() {} virtual ~VideoOutCtx() {}
void Init(u32 width, u32 height); void Init(u32 width, u32 height);
int Open(); int Open();
void Close(s32 handle); void Close(s32 handle);
VideoConfigInternal* getCtx(int handle); VideoConfigInternal* getCtx(int handle);
FlipQueue& getFlipQueue() { return m_flip_queue; } FlipQueue& getFlipQueue() {
return m_flip_queue;
}
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
@ -72,7 +75,8 @@ class VideoOutCtx {
return m_graphic_ctx; return m_graphic_ctx;
} }
private:
private:
std::mutex m_mutex; std::mutex m_mutex;
VideoConfigInternal m_video_out_ctx; VideoConfigInternal m_video_out_ctx;
FlipQueue m_flip_queue; FlipQueue m_flip_queue;

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#include "common/types.h" #include <memory>
#include <mutex>
#include <vector> #include <vector>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <mutex> #include "common/types.h"
#include <memory>
namespace HLE::Libs::Graphics { namespace HLE::Libs::Graphics {

View File

@ -1,7 +1,7 @@
#include "graphics_render.h"
#include <fmt/core.h> #include <fmt/core.h>
#include "common/singleton.h" #include "common/singleton.h"
#include "emulator.h" #include "emulator.h"
#include "graphics_render.h"
static thread_local GPU::CommandPool g_command_pool; static thread_local GPU::CommandPool g_command_pool;
@ -155,7 +155,8 @@ void GPU::CommandPool::createPool(int id) {
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.commandBufferCount = m_pool[id].buffers_count; alloc_info.commandBufferCount = m_pool[id].buffers_count;
if (vkAllocateCommandBuffers(ctx->m_device, &alloc_info, m_pool[id].buffers.data()) != VK_SUCCESS) { if (vkAllocateCommandBuffers(ctx->m_device, &alloc_info, m_pool[id].buffers.data()) !=
VK_SUCCESS) {
fmt::print("Can't allocate command buffers\n"); fmt::print("Can't allocate command buffers\n");
std::exit(0); std::exit(0);
} }
@ -168,7 +169,8 @@ void GPU::CommandPool::createPool(int id) {
fence_info.pNext = nullptr; fence_info.pNext = nullptr;
fence_info.flags = 0; fence_info.flags = 0;
if (vkCreateFence(ctx->m_device, &fence_info, nullptr, &m_pool[id].fences[i]) != VK_SUCCESS) { if (vkCreateFence(ctx->m_device, &fence_info, nullptr, &m_pool[id].fences[i]) !=
VK_SUCCESS) {
fmt::print("Can't create fence\n"); fmt::print("Can't create fence\n");
std::exit(0); std::exit(0);
} }
@ -178,7 +180,8 @@ void GPU::CommandPool::createPool(int id) {
semaphore_info.pNext = nullptr; semaphore_info.pNext = nullptr;
semaphore_info.flags = 0; semaphore_info.flags = 0;
if (vkCreateSemaphore(ctx->m_device, &semaphore_info, nullptr, &m_pool[id].semaphores[i]) != VK_SUCCESS) { if (vkCreateSemaphore(ctx->m_device, &semaphore_info, nullptr, &m_pool[id].semaphores[i]) !=
VK_SUCCESS) {
fmt::print("Can't create semas\n"); fmt::print("Can't create semas\n");
std::exit(0); std::exit(0);
} }

View File

@ -6,7 +6,7 @@
namespace GPU { namespace GPU {
class CommandPool { class CommandPool {
public: public:
CommandPool() = default; CommandPool() = default;
~CommandPool() {} ~CommandPool() {}
@ -17,16 +17,20 @@ class CommandPool {
return &m_pool[id]; return &m_pool[id];
} }
private: private:
void createPool(int id); void createPool(int id);
void deleteAllPool(); void deleteAllPool();
std::array<HLE::Libs::Graphics::VulkanCommandPool, 11> m_pool{}; std::array<HLE::Libs::Graphics::VulkanCommandPool, 11> m_pool{};
}; };
class CommandBuffer { class CommandBuffer {
public: public:
explicit CommandBuffer(int queue) : m_queue(queue) { allocateBuffer(); } explicit CommandBuffer(int queue) : m_queue(queue) {
virtual ~CommandBuffer() { freeBuffer(); } allocateBuffer();
}
virtual ~CommandBuffer() {
freeBuffer();
}
void allocateBuffer(); void allocateBuffer();
void freeBuffer(); void freeBuffer();
void waitForFence(); void waitForFence();
@ -34,9 +38,14 @@ class CommandBuffer {
void end() const; void end() const;
void executeWithSemaphore(); void executeWithSemaphore();
void execute(); void execute();
u32 getIndex() const { return m_index; } u32 getIndex() const {
HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; } return m_index;
private: }
HLE::Libs::Graphics::VulkanCommandPool* getPool() {
return m_pool;
}
private:
int m_queue = -1; int m_queue = -1;
u32 m_index = static_cast<u32>(-1); u32 m_index = static_cast<u32>(-1);
HLE::Libs::Graphics::VulkanCommandPool* m_pool = nullptr; HLE::Libs::Graphics::VulkanCommandPool* m_pool = nullptr;
@ -44,19 +53,23 @@ class CommandBuffer {
}; };
class Framebuffer { class Framebuffer {
public: public:
Framebuffer() {} Framebuffer() {}
virtual ~Framebuffer() {} virtual ~Framebuffer() {}
}; };
class RenderCtx { class RenderCtx {
public: public:
RenderCtx() = default; RenderCtx() = default;
virtual ~RenderCtx() {} virtual ~RenderCtx() {}
void setGraphicCtx(HLE::Libs::Graphics::GraphicCtx* ctx) { m_graphic_ctx = ctx; } void setGraphicCtx(HLE::Libs::Graphics::GraphicCtx* ctx) {
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { return m_graphic_ctx; } m_graphic_ctx = ctx;
}
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
return m_graphic_ctx;
}
private: private:
Framebuffer m_framebuffer{}; Framebuffer m_framebuffer{};
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr; HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
}; };

View File

@ -1,19 +1,19 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <magic_enum.hpp> #include <magic_enum.hpp>
#include "common/log.h" #include "Objects/video_out_ctx.h"
#include "Util/config.h"
#include "common/debug.h" #include "common/debug.h"
#include "core/loader/symbols_resolver.h" #include "common/log.h"
#include "core/PS4/HLE/Graphics/video_out.h" #include "common/singleton.h"
#include "core/PS4/GPU/gpu_memory.h" #include "core/PS4/GPU/gpu_memory.h"
#include "core/PS4/GPU/video_out_buffer.h" #include "core/PS4/GPU/video_out_buffer.h"
#include "core/PS4/HLE/Graphics/video_out.h"
#include "core/hle/error_codes.h" #include "core/hle/error_codes.h"
#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h"
#include "core/hle/libraries/libuserservice/usr_mng_codes.h" #include "core/hle/libraries/libuserservice/usr_mng_codes.h"
#include "Util/config.h" #include "core/loader/symbols_resolver.h"
#include "Objects/video_out_ctx.h"
#include "common/singleton.h"
#include "emulator.h" #include "emulator.h"
#include "graphics_render.h" #include "graphics_render.h"
@ -33,19 +33,28 @@ bool videoOutFlip(u32 micros) {
std::string getPixelFormatString(s32 format) { std::string getPixelFormatString(s32 format) {
switch (format) { switch (format) {
case SCE_VIDEO_OUT_PIXEL_FORMAT_A8R8G8B8_SRGB: return "PIXEL_FORMAT_A8R8G8B8_SRGB"; case SCE_VIDEO_OUT_PIXEL_FORMAT_A8R8G8B8_SRGB:
case SCE_VIDEO_OUT_PIXEL_FORMAT_A8B8G8R8_SRGB: return "PIXEL_FORMAT_A8B8G8R8_SRGB"; return "PIXEL_FORMAT_A8R8G8B8_SRGB";
case SCE_VIDEO_OUT_PIXEL_FORMAT_A2R10G10B10: return "PIXEL_FORMAT_A2R10G10B10"; case SCE_VIDEO_OUT_PIXEL_FORMAT_A8B8G8R8_SRGB:
case SCE_VIDEO_OUT_PIXEL_FORMAT_A2R10G10B10_SRGB: return "PIXEL_FORMAT_A2R10G10B10_SRGB"; return "PIXEL_FORMAT_A8B8G8R8_SRGB";
case SCE_VIDEO_OUT_PIXEL_FORMAT_A2R10G10B10_BT2020_PQ: return "PIXEL_FORMAT_A2R10G10B10_BT2020_PQ"; case SCE_VIDEO_OUT_PIXEL_FORMAT_A2R10G10B10:
case SCE_VIDEO_OUT_PIXEL_FORMAT_A16R16G16B16_FLOAT: return "PIXEL_FORMAT_A16R16G16B16_FLOAT"; return "PIXEL_FORMAT_A2R10G10B10";
case SCE_VIDEO_OUT_PIXEL_FORMAT_YCBCR420_BT709: return "PIXEL_FORMAT_YCBCR420_BT709"; case SCE_VIDEO_OUT_PIXEL_FORMAT_A2R10G10B10_SRGB:
default: return "Unknown pixel format"; return "PIXEL_FORMAT_A2R10G10B10_SRGB";
case SCE_VIDEO_OUT_PIXEL_FORMAT_A2R10G10B10_BT2020_PQ:
return "PIXEL_FORMAT_A2R10G10B10_BT2020_PQ";
case SCE_VIDEO_OUT_PIXEL_FORMAT_A16R16G16B16_FLOAT:
return "PIXEL_FORMAT_A16R16G16B16_FLOAT";
case SCE_VIDEO_OUT_PIXEL_FORMAT_YCBCR420_BT709:
return "PIXEL_FORMAT_YCBCR420_BT709";
default:
return "Unknown pixel format";
} }
} }
void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute, u32 pixelFormat, u32 tilingMode, u32 aspectRatio, u32 width, void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute,
u32 height, u32 pitchInPixel) { u32 pixelFormat, u32 tilingMode, u32 aspectRatio,
u32 width, u32 height, u32 pitchInPixel) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
auto tileMode = magic_enum::enum_cast<SceVideoOutTilingMode>(tilingMode); auto tileMode = magic_enum::enum_cast<SceVideoOutTilingMode>(tilingMode);
@ -81,11 +90,13 @@ static void flip_trigger_event_func(Core::Kernel::EqueueEvent* event, void* trig
event->event.data = reinterpret_cast<intptr_t>(trigger_data); event->event.data = reinterpret_cast<intptr_t>(trigger_data);
} }
static void flip_delete_event_func(Core::Kernel::SceKernelEqueue eq, Core::Kernel::EqueueEvent* event) { static void flip_delete_event_func(Core::Kernel::SceKernelEqueue eq,
Core::Kernel::EqueueEvent* event) {
BREAKPOINT(); // TODO BREAKPOINT(); // TODO
} }
s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 handle, void* udata) { s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 handle,
void* udata) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance(); auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
@ -119,7 +130,8 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 h
return result; return result;
} }
s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses, s32 bufferNum, s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses,
s32 bufferNum,
const SceVideoOutBufferAttribute* attribute) { const SceVideoOutBufferAttribute* attribute) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance(); auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
@ -193,7 +205,9 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co
format = GPU::VideoOutBufferFormat::R8G8B8A8Srgb; format = GPU::VideoOutBufferFormat::R8G8B8A8Srgb;
} }
GPU::VideoOutBufferObj buffer_info(format, attribute->width, attribute->height, attribute->tilingMode == 0, Config::isNeoMode(), buffer_pitch); GPU::VideoOutBufferObj buffer_info(format, attribute->width, attribute->height,
attribute->tilingMode == 0, Config::isNeoMode(),
buffer_pitch);
for (int i = 0; i < bufferNum; i++) { for (int i = 0; i < bufferNum; i++) {
if (ctx->buffers[i + startIndex].buffer != nullptr) { if (ctx->buffers[i + startIndex].buffer != nullptr) {
@ -205,10 +219,13 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co
ctx->buffers[i + startIndex].buffer = addresses[i]; ctx->buffers[i + startIndex].buffer = addresses[i];
ctx->buffers[i + startIndex].buffer_size = buffer_size; ctx->buffers[i + startIndex].buffer_size = buffer_size;
ctx->buffers[i + startIndex].buffer_pitch = buffer_pitch; ctx->buffers[i + startIndex].buffer_pitch = buffer_pitch;
ctx->buffers[i + startIndex].buffer_render = static_cast<Graphics::VideoOutVulkanImage*>( ctx->buffers[i + startIndex].buffer_render =
GPU::memoryCreateObj(0, videoOut->getGraphicCtx(), nullptr, reinterpret_cast<uint64_t>(addresses[i]), buffer_size, buffer_info)); static_cast<Graphics::VideoOutVulkanImage*>(GPU::memoryCreateObj(
0, videoOut->getGraphicCtx(), nullptr, reinterpret_cast<uint64_t>(addresses[i]),
buffer_size, buffer_info));
LOG_INFO_IF(log_file_videoout, "buffers[{}] = {:#x}\n", i + startIndex, reinterpret_cast<u64>(addresses[i])); LOG_INFO_IF(log_file_videoout, "buffers[{}] = {:#x}\n", i + startIndex,
reinterpret_cast<u64>(addresses[i]));
} }
return registration_index; return registration_index;
@ -235,13 +252,15 @@ s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode
if (flipMode != 1) { if (flipMode != 1) {
// BREAKPOINT(); // only flipmode==1 is supported // BREAKPOINT(); // only flipmode==1 is supported
LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flipmode {}\n", bufferIndex);//openBOR needs 2 but seems to work LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flipmode {}\n",
bufferIndex); // openBOR needs 2 but seems to work
} }
if (bufferIndex == -1) { if (bufferIndex == -1) {
BREAKPOINT(); // blank output not supported BREAKPOINT(); // blank output not supported
} }
if (bufferIndex < -1 || bufferIndex > 15) { if (bufferIndex < -1 || bufferIndex > 15) {
LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip invalid bufferIndex {}\n", bufferIndex); LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip invalid bufferIndex {}\n",
bufferIndex);
return SCE_VIDEO_OUT_ERROR_INVALID_INDEX; return SCE_VIDEO_OUT_ERROR_INVALID_INDEX;
} }
LOG_INFO_IF(log_file_videoout, "bufferIndex = {}\n", bufferIndex); LOG_INFO_IF(log_file_videoout, "bufferIndex = {}\n", bufferIndex);
@ -252,7 +271,8 @@ s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode
LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flip queue is full\n"); LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flip queue is full\n");
return SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL; return SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL;
} }
Core::Libraries::LibSceGnmDriver::sceGnmFlushGarlic(); // hackish should be done that neccesary for niko's homebrew Core::Libraries::LibSceGnmDriver::sceGnmFlushGarlic(); // hackish should be done that neccesary
// for niko's homebrew
return SCE_OK; return SCE_OK;
} }
@ -280,7 +300,8 @@ s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutio
return SCE_OK; return SCE_OK;
} }
s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index, const void* param) { s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index,
const void* param) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (userId != SCE_USER_SERVICE_USER_ID_SYSTEM && userId != 0) { if (userId != SCE_USER_SERVICE_USER_ID_SYSTEM && userId != 0) {
BREAKPOINT(); BREAKPOINT();
@ -319,25 +340,38 @@ s32 PS4_SYSV_ABI sceVideoOutUnregisterBuffers(s32 handle, s32 attributeIndex) {
void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym) { void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym) {
using namespace Core; using namespace Core;
LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutGetFlipStatus); LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
sceVideoOutGetFlipStatus);
LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutSubmitFlip); LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutSubmitFlip);
LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutRegisterBuffers); LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
LIB_FUNCTION("HXzjK9yI30k", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutAddFlipEvent); sceVideoOutRegisterBuffers);
LIB_FUNCTION("CBiu4mCE1DA", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutSetFlipRate); LIB_FUNCTION("HXzjK9yI30k", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
LIB_FUNCTION("i6-sR91Wt-4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutSetBufferAttribute); sceVideoOutAddFlipEvent);
LIB_FUNCTION("6kPnj51T62Y", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutGetResolutionStatus); LIB_FUNCTION("CBiu4mCE1DA", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
sceVideoOutSetFlipRate);
LIB_FUNCTION("i6-sR91Wt-4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
sceVideoOutSetBufferAttribute);
LIB_FUNCTION("6kPnj51T62Y", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
sceVideoOutGetResolutionStatus);
LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutOpen); LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutOpen);
LIB_FUNCTION("zgXifHT9ErY", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutIsFlipPending); LIB_FUNCTION("zgXifHT9ErY", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
LIB_FUNCTION("N5KDtkIjjJ4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutUnregisterBuffers); sceVideoOutIsFlipPending);
LIB_FUNCTION("N5KDtkIjjJ4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
sceVideoOutUnregisterBuffers);
LIB_FUNCTION("uquVH4-Du78", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutClose); LIB_FUNCTION("uquVH4-Du78", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutClose);
// openOrbis appears to have libSceVideoOut_v1 module libSceVideoOut_v1.1 // openOrbis appears to have libSceVideoOut_v1 module libSceVideoOut_v1.1
LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutOpen); LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutOpen);
LIB_FUNCTION("CBiu4mCE1DA", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSetFlipRate); LIB_FUNCTION("CBiu4mCE1DA", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
LIB_FUNCTION("HXzjK9yI30k", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutAddFlipEvent); sceVideoOutSetFlipRate);
LIB_FUNCTION("i6-sR91Wt-4", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSetBufferAttribute); LIB_FUNCTION("HXzjK9yI30k", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutRegisterBuffers); sceVideoOutAddFlipEvent);
LIB_FUNCTION("i6-sR91Wt-4", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
sceVideoOutSetBufferAttribute);
LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
sceVideoOutRegisterBuffers);
LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSubmitFlip); LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSubmitFlip);
LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutGetFlipStatus); LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
sceVideoOutGetFlipStatus);
} }
} // namespace HLE::Libs::Graphics::VideoOut } // namespace HLE::Libs::Graphics::VideoOut

View File

@ -37,9 +37,16 @@ constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_NONE = 0;
constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_VR = 7; constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_VR = 7;
constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_STRICT_COLORIMETRY = 8; constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_STRICT_COLORIMETRY = 8;
enum SceVideoOutEventId : s16 { SCE_VIDEO_OUT_EVENT_FLIP = 0, SCE_VIDEO_OUT_EVENT_VBLANK = 1, SCE_VIDEO_OUT_EVENT_PRE_VBLANK_START = 2 }; enum SceVideoOutEventId : s16 {
SCE_VIDEO_OUT_EVENT_FLIP = 0,
SCE_VIDEO_OUT_EVENT_VBLANK = 1,
SCE_VIDEO_OUT_EVENT_PRE_VBLANK_START = 2
};
enum SceVideoOutTilingMode : s32 { SCE_VIDEO_OUT_TILING_MODE_TILE = 0, SCE_VIDEO_OUT_TILING_MODE_LINEAR = 1 }; enum SceVideoOutTilingMode : s32 {
SCE_VIDEO_OUT_TILING_MODE_TILE = 0,
SCE_VIDEO_OUT_TILING_MODE_LINEAR = 1
};
enum AspectRatioMode : s32 { SCE_VIDEO_OUT_ASPECT_RATIO_16_9 = 0 }; enum AspectRatioMode : s32 { SCE_VIDEO_OUT_ASPECT_RATIO_16_9 = 0 };
@ -101,17 +108,20 @@ std::string getPixelFormatString(s32 format);
void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym); void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym);
bool videoOutFlip(u32 micros); bool videoOutFlip(u32 micros);
void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute, u32 pixelFormat, u32 tilingMode, u32 aspectRatio, u32 width, void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute,
u32 height, u32 pitchInPixel); u32 pixelFormat, u32 tilingMode, u32 aspectRatio,
u32 width, u32 height, u32 pitchInPixel);
s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 handle, void* udata); s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 handle, void* udata);
s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses, s32 bufferNum, s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses,
s32 bufferNum,
const SceVideoOutBufferAttribute* attribute); const SceVideoOutBufferAttribute* attribute);
s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate); s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate);
s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle); s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle);
s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode, s64 flipArg); s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode, s64 flipArg);
s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, SceVideoOutFlipStatus* status); s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, SceVideoOutFlipStatus* status);
s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutionStatus* status); s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutionStatus* status);
s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index, const void* param); s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index,
const void* param);
s32 PS4_SYSV_ABI sceVideoOutClose(s32 handle); s32 PS4_SYSV_ABI sceVideoOutClose(s32 handle);
} // namespace HLE::Libs::Graphics::VideoOut } // namespace HLE::Libs::Graphics::VideoOut

View File

@ -6,8 +6,7 @@ namespace Core::AeroLib {
// Use a direct table here + binary search as contents are static // Use a direct table here + binary search as contents are static
static constexpr NidEntry NIDS[] = { static constexpr NidEntry NIDS[] = {
#define STUB(nid, name) \ #define STUB(nid, name) {nid, #name},
{ nid, #name },
#include "aerolib.inl" #include "aerolib.inl"
#undef STUB #undef STUB
}; };

View File

@ -24,11 +24,11 @@ u64 UnresolvedStub() {
} }
static u64 UnknownStub() { static u64 UnknownStub() {
LOG_ERROR("Stub: Unknown (nid: Unknown) called, returning zero to {}\n", __builtin_return_address(0)); LOG_ERROR("Stub: Unknown (nid: Unknown) called, returning zero to {}\n",
__builtin_return_address(0));
return 0; return 0;
} }
static const NidEntry* stub_nids[MAX_STUBS]; static const NidEntry* stub_nids[MAX_STUBS];
static std::string stub_nids_unknown[MAX_STUBS]; static std::string stub_nids_unknown[MAX_STUBS];
@ -36,17 +36,18 @@ template <int stub_index>
static u64 CommonStub() { static u64 CommonStub() {
auto entry = stub_nids[stub_index]; auto entry = stub_nids[stub_index];
if (entry) { if (entry) {
LOG_ERROR("Stub: {} (nid: {}) called, returning zero to {}\n", entry->name, entry->nid, __builtin_return_address(0)); LOG_ERROR("Stub: {} (nid: {}) called, returning zero to {}\n", entry->name, entry->nid,
__builtin_return_address(0));
} else { } else {
LOG_ERROR("Stub: Unknown (nid: {}) called, returning zero to {}\n", stub_nids_unknown[stub_index], __builtin_return_address(0)); LOG_ERROR("Stub: Unknown (nid: {}) called, returning zero to {}\n",
stub_nids_unknown[stub_index], __builtin_return_address(0));
} }
return 0; return 0;
} }
static u32 UsedStubEntries; static u32 UsedStubEntries;
#define XREP_1(x) \ #define XREP_1(x) &CommonStub<x>,
&CommonStub<x>,
#define XREP_2(x) XREP_1(x) XREP_1(x + 1) #define XREP_2(x) XREP_1(x) XREP_1(x + 1)
#define XREP_4(x) XREP_2(x) XREP_2(x + 2) #define XREP_4(x) XREP_2(x) XREP_2(x + 2)
@ -60,9 +61,7 @@ static u32 UsedStubEntries;
#define STUBS_LIST XREP_128(0) #define STUBS_LIST XREP_128(0)
static u64 (*stub_handlers[MAX_STUBS])() = { static u64 (*stub_handlers[MAX_STUBS])() = {STUBS_LIST};
STUBS_LIST
};
u64 GetStub(const char* nid) { u64 GetStub(const char* nid) {
if (UsedStubEntries >= MAX_STUBS) { if (UsedStubEntries >= MAX_STUBS) {

View File

@ -40,10 +40,10 @@ std::string MntPoints::getHostFile(const std::string& guest_file) {
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
for (auto& pair : m_mnt_pairs) { for (auto& pair : m_mnt_pairs) {
//horrible code but it works :D // horrible code but it works :D
int find = guest_file.find(pair.guest_path); int find = guest_file.find(pair.guest_path);
if (find == 0) { if (find == 0) {
std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size()-1); std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size() - 1);
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/'); std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
return pair.host_path + npath; return pair.host_path + npath;
} }

View File

@ -5,13 +5,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/fs_file.h"
#include <common/io_file.h> #include <common/io_file.h>
#include "common/fs_file.h"
namespace Core::FileSys { namespace Core::FileSys {
class MntPoints { class MntPoints {
public: public:
struct MntPair { struct MntPair {
std::string host_path; std::string host_path;
std::string guest_path; // e.g /app0/ std::string guest_path; // e.g /app0/
@ -25,7 +25,7 @@ class MntPoints {
std::string getHostDirectory(const std::string& guest_directory); std::string getHostDirectory(const std::string& guest_directory);
std::string getHostFile(const std::string& guest_file); std::string getHostFile(const std::string& guest_file);
private: private:
std::vector<MntPair> m_mnt_pairs; std::vector<MntPair> m_mnt_pairs;
std::mutex m_mutex; std::mutex m_mutex;
}; };
@ -36,12 +36,12 @@ struct File {
std::string m_host_name; std::string m_host_name;
std::string m_guest_name; std::string m_guest_name;
IOFile f; IOFile f;
//std::vector<Common::FS::DirEntry> dirents; // std::vector<Common::FS::DirEntry> dirents;
u32 dirents_index; u32 dirents_index;
std::mutex m_mutex; std::mutex m_mutex;
}; };
class HandleTable { class HandleTable {
public: public:
HandleTable() {} HandleTable() {}
virtual ~HandleTable() {} virtual ~HandleTable() {}
int createHandle(); int createHandle();
@ -49,7 +49,7 @@ class HandleTable {
File* getFile(int d); File* getFile(int d);
File* getFile(const std::string& host_name); File* getFile(const std::string& host_name);
private: private:
std::vector<File*> m_files; std::vector<File*> m_files;
std::mutex m_mutex; std::mutex m_mutex;
}; };

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <condition_variable>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
#include <condition_variable>
#include "common/types.h" #include "common/types.h"
namespace Core::Kernel { namespace Core::Kernel {
@ -61,15 +61,18 @@ struct EqueueEvent {
}; };
class EqueueInternal { class EqueueInternal {
public: public:
EqueueInternal() = default; EqueueInternal() = default;
virtual ~EqueueInternal(); virtual ~EqueueInternal();
void setName(const std::string& m_name) { this->m_name = m_name; } void setName(const std::string& m_name) {
this->m_name = m_name;
}
int addEvent(const EqueueEvent& event); int addEvent(const EqueueEvent& event);
int waitForEvents(SceKernelEvent* ev, int num, u32 micros); int waitForEvents(SceKernelEvent* ev, int num, u32 micros);
bool triggerEvent(u64 ident, s16 filter, void* trigger_data); bool triggerEvent(u64 ident, s16 filter, void* trigger_data);
int getTriggeredEvents(SceKernelEvent* ev, int num); int getTriggeredEvents(SceKernelEvent* ev, int num);
private:
private:
std::string m_name; std::string m_name;
std::mutex m_mutex; std::mutex m_mutex;
std::vector<EqueueEvent> m_events; std::vector<EqueueEvent> m_events;

View File

@ -6,8 +6,8 @@ static u64 AlignUp(u64 pos, u64 align) {
return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos);
} }
bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut,
u64* physAddrOut, int memoryType) { int memoryType) {
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
u64 find_free_pos = 0; u64 find_free_pos = 0;

View File

@ -4,13 +4,13 @@
#include <vector> #include <vector>
#include "common/types.h" #include "common/types.h"
#include "core/virtual_memory.h"
#include "core/PS4/GPU/gpu_memory.h" #include "core/PS4/GPU/gpu_memory.h"
#include "core/virtual_memory.h"
namespace Core::Kernel { namespace Core::Kernel {
class PhysicalMemory { class PhysicalMemory {
public: public:
struct AllocatedBlock { struct AllocatedBlock {
u64 start_addr; u64 start_addr;
u64 size; u64 size;
@ -24,11 +24,13 @@ class PhysicalMemory {
PhysicalMemory() {} PhysicalMemory() {}
virtual ~PhysicalMemory() {} virtual ~PhysicalMemory() {}
public: public:
bool Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType); bool Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut,
bool Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::MemoryMode gpu_mode); int memoryType);
bool Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode,
GPU::MemoryMode gpu_mode);
private: private:
std::vector<AllocatedBlock> m_allocatedBlocks; std::vector<AllocatedBlock> m_allocatedBlocks;
std::mutex m_mutex; std::mutex m_mutex;
}; };

View File

@ -1,7 +1,7 @@
#include "Util/config.h"
#include "common/log.h" #include "common/log.h"
#include "core/hle/kernel/cpu_management.h" #include "core/hle/kernel/cpu_management.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "Util/config.h"
namespace Core::Kernel { namespace Core::Kernel {

View File

@ -1,7 +1,7 @@
#include "common/debug.h" #include "common/debug.h"
#include "common/log.h" #include "common/log.h"
#include "core/hle/kernel/event_queues.h"
#include "core/hle/error_codes.h" #include "core/hle/error_codes.h"
#include "core/hle/kernel/event_queues.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
namespace Core::Kernel { namespace Core::Kernel {
@ -12,20 +12,25 @@ int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (eq == nullptr) { if (eq == nullptr) {
LOG_TRACE_IF(log_file_equeues, "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EINVAL eq invalid\n"); LOG_TRACE_IF(log_file_equeues,
"sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EINVAL eq invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
if (name == nullptr) { if (name == nullptr) {
LOG_TRACE_IF(log_file_equeues, "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EFAULT name invalid\n"); LOG_TRACE_IF(log_file_equeues,
"sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EFAULT name invalid\n");
return SCE_KERNEL_ERROR_EFAULT; return SCE_KERNEL_ERROR_EFAULT;
} }
if (name == NULL) { if (name == NULL) {
LOG_TRACE_IF(log_file_equeues, "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EINVAL name is null\n"); LOG_TRACE_IF(log_file_equeues,
"sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EINVAL name is null\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
if (strlen(name) > 31) { // max is 32 including null terminator if (strlen(name) > 31) { // max is 32 including null terminator
LOG_TRACE_IF(log_file_equeues, "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_ENAMETOOLONG name size exceeds 32 bytes\n"); LOG_TRACE_IF(log_file_equeues,
"sceKernelCreateEqueue returned SCE_KERNEL_ERROR_ENAMETOOLONG name size "
"exceeds 32 bytes\n");
return SCE_KERNEL_ERROR_ENAMETOOLONG; return SCE_KERNEL_ERROR_ENAMETOOLONG;
} }
*eq = new EqueueInternal; *eq = new EqueueInternal;
@ -35,8 +40,8 @@ int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name) {
return SCE_OK; return SCE_OK;
} }
int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int num, int* out,
int num, int* out, SceKernelUseconds* timo) { SceKernelUseconds* timo) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (eq == nullptr) { if (eq == nullptr) {

View File

@ -8,7 +8,7 @@ using SceKernelUseconds = u32;
using SceKernelEqueue = EqueueInternal*; using SceKernelEqueue = EqueueInternal*;
int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name); int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name);
int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int num, int* out,
int num, int* out, SceKernelUseconds *timo); SceKernelUseconds* timo);
} // namespace Core::Kernel } // namespace Core::Kernel

View File

@ -1,14 +1,14 @@
#include <bit> #include <bit>
#include <magic_enum.hpp>
#include <core/PS4/GPU/gpu_memory.h> #include <core/PS4/GPU/gpu_memory.h>
#include <core/virtual_memory.h> #include <core/virtual_memory.h>
#include "common/log.h" #include <magic_enum.hpp>
#include "common/debug.h" #include "common/debug.h"
#include "common/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/hle/error_codes.h"
#include "core/hle/kernel/Objects/physical_memory.h"
#include "core/hle/kernel/memory_management.h" #include "core/hle/kernel/memory_management.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "core/hle/kernel/Objects/physical_memory.h"
#include "core/hle/error_codes.h"
namespace Core::Kernel { namespace Core::Kernel {
@ -23,24 +23,31 @@ u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
return SCE_KERNEL_MAIN_DMEM_SIZE; return SCE_KERNEL_MAIN_DMEM_SIZE;
} }
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut) { int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
u64 alignment, int memoryType, s64* physAddrOut) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (searchStart < 0 || searchEnd <= searchStart) { if (searchStart < 0 || searchEnd <= searchStart) {
LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL searchStart,searchEnd invalid\n"); LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned "
"SCE_KERNEL_ERROR_EINVAL searchStart,searchEnd invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
bool isInRange = (searchStart < len && searchEnd > len); bool isInRange = (searchStart < len && searchEnd > len);
if (len <= 0 || !is16KBAligned(len) || !isInRange) { if (len <= 0 || !is16KBAligned(len) || !isInRange) {
LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL memory range invalid\n"); LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned "
"SCE_KERNEL_ERROR_EINVAL memory range invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
if ((alignment != 0 || is16KBAligned(alignment)) && !std::has_single_bit(alignment)) { if ((alignment != 0 || is16KBAligned(alignment)) && !std::has_single_bit(alignment)) {
LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n"); LOG_TRACE_IF(
log_file_memory,
"sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
if (physAddrOut == nullptr) { if (physAddrOut == nullptr) {
LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL physAddrOut is null\n"); LOG_TRACE_IF(
log_file_memory,
"sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL physAddrOut is null\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
auto memtype = magic_enum::enum_cast<MemoryTypes>(memoryType); auto memtype = magic_enum::enum_cast<MemoryTypes>(memoryType);
@ -53,8 +60,10 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
u64 physical_addr = 0; u64 physical_addr = 0;
auto* physical_memory = Common::Singleton<PhysicalMemory>::Instance(); auto* physical_memory = Common::Singleton<PhysicalMemory>::Instance();
if (!physical_memory->Alloc(searchStart, searchEnd, len, alignment, &physical_addr, memoryType)) { if (!physical_memory->Alloc(searchStart, searchEnd, len, alignment, &physical_addr,
LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EAGAIN can't allocate physical memory\n"); memoryType)) {
LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned "
"SCE_KERNEL_ERROR_EAGAIN can't allocate physical memory\n");
return SCE_KERNEL_ERROR_EAGAIN; return SCE_KERNEL_ERROR_EAGAIN;
} }
*physAddrOut = static_cast<s64>(physical_addr); *physAddrOut = static_cast<s64>(physical_addr);
@ -62,19 +71,24 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
return SCE_OK; return SCE_OK;
} }
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment) { int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags,
s64 directMemoryStart, u64 alignment) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (len == 0 || !is16KBAligned(len)) { if (len == 0 || !is16KBAligned(len)) {
LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL len invalid\n"); LOG_TRACE_IF(log_file_memory,
"sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL len invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
if (!is16KBAligned(directMemoryStart)) { if (!is16KBAligned(directMemoryStart)) {
LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL directMemoryStart invalid\n"); LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL "
"directMemoryStart invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
if (alignment != 0) { if (alignment != 0) {
if ((!std::has_single_bit(alignment) && !is16KBAligned(alignment))) { if ((!std::has_single_bit(alignment) && !is16KBAligned(alignment))) {
LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n"); LOG_TRACE_IF(
log_file_memory,
"sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n");
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
} }
@ -94,7 +108,8 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl
cpu_mode = VirtualMemory::MemoryMode::ReadWrite; cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
gpu_mode = GPU::MemoryMode::ReadWrite; gpu_mode = GPU::MemoryMode::ReadWrite;
break; break;
default: BREAKPOINT(); default:
BREAKPOINT();
} }
auto in_addr = reinterpret_cast<u64>(*addr); auto in_addr = reinterpret_cast<u64>(*addr);

View File

@ -28,7 +28,9 @@ enum MemoryProtection : u32 {
}; };
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize();
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut); int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment); u64 alignment, int memoryType, s64* physAddrOut);
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags,
s64 directMemoryStart, u64 alignment);
} // namespace Core::Kernel } // namespace Core::Kernel

View File

@ -1,7 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include "common/debug.h" #include "common/debug.h"
#include "common/singleton.h"
#include "common/log.h" #include "common/log.h"
#include "common/singleton.h"
#include "core/hle/libraries/libc/libc.h" #include "core/hle/libraries/libc/libc.h"
#include "core/hle/libraries/libc/libc_cxa.h" #include "core/hle/libraries/libc/libc_cxa.h"
#include "core/hle/libraries/libc/libc_math.h" #include "core/hle/libraries/libc/libc_math.h"
@ -82,44 +82,62 @@ PS4_SYSV_ABI void* ps4__Znwm(u64 count) {
} }
static constexpr u16 lowercaseTable[256] = { static constexpr u16 lowercaseTable[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B,
0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073,
0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083,
0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B,
0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB,
0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
}; };
const PS4_SYSV_ABI u16* ps4__Getptolower() { return &lowercaseTable[0]; } const PS4_SYSV_ABI u16* ps4__Getptolower() {
return &lowercaseTable[0];
}
static constexpr u16 uppercaseTable[256] = { static constexpr u16 uppercaseTable[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B,
0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053,
0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B,
0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083,
0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B,
0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB,
0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
}; };
const PS4_SYSV_ABI u16* ps4__Getptoupper() { return &uppercaseTable[0]; } const PS4_SYSV_ABI u16* ps4__Getptoupper() {
return &uppercaseTable[0];
}
namespace CharacterType { namespace CharacterType {
enum : u16 { enum : u16 {
@ -396,7 +414,9 @@ static constexpr u16 characterTypeTable[256] = {
0, 0,
}; };
const PS4_SYSV_ABI u16* ps4__Getpctype() { return &characterTypeTable[0]; } const PS4_SYSV_ABI u16* ps4__Getpctype() {
return &characterTypeTable[0];
}
void libcSymbolsRegister(Loader::SymbolsResolver* sym) { void libcSymbolsRegister(Loader::SymbolsResolver* sym) {
// cxa functions // cxa functions
@ -441,7 +461,7 @@ void libcSymbolsRegister(Loader::SymbolsResolver* sym) {
// misc // misc
LIB_OBJ("P330P3dFF68", "libc", 1, "libc", 1, 1, &g_need_sceLibc); LIB_OBJ("P330P3dFF68", "libc", 1, "libc", 1, 1, &g_need_sceLibc);
LIB_OBJ("2sWzhYqFH4E","libc", 1, "libc", 1, 1,stdout); LIB_OBJ("2sWzhYqFH4E", "libc", 1, "libc", 1, 1, stdout);
LIB_OBJ("H8AprKeZtNg", "libc", 1, "libc", 1, 1, stderr); LIB_OBJ("H8AprKeZtNg", "libc", 1, "libc", 1, 1, stderr);
LIB_FUNCTION("bzQExy189ZI", "libc", 1, "libc", 1, 1, ps4_init_env); LIB_FUNCTION("bzQExy189ZI", "libc", 1, "libc", 1, 1, ps4_init_env);
LIB_FUNCTION("XKRegsFpEpk", "libc", 1, "libc", 1, 1, ps4_catchReturnFromMain); LIB_FUNCTION("XKRegsFpEpk", "libc", 1, "libc", 1, 1, ps4_catchReturnFromMain);

View File

@ -1,9 +1,10 @@
#include "libc_cxa.h" #include "libc_cxa.h"
#include "common/log.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/log.h"
// adapted from https://opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx.auto.html // adapted from
// https://opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx.auto.html
namespace Core::Libraries::LibC { namespace Core::Libraries::LibC {
@ -55,15 +56,25 @@ __attribute__((noinline)) static pthread_mutex_t* guard_mutex() {
} }
// helper functions for getting/setting flags in guard_object // helper functions for getting/setting flags in guard_object
static bool initializerHasRun(u64* guard_object) { return (*((u08*)guard_object) != 0); } static bool initializerHasRun(u64* guard_object) {
return (*((u08*)guard_object) != 0);
}
static void setInitializerHasRun(u64* guard_object) { *((u08*)guard_object) = 1; } static void setInitializerHasRun(u64* guard_object) {
*((u08*)guard_object) = 1;
}
static bool inUse(u64* guard_object) { return (((u08*)guard_object)[1] != 0); } static bool inUse(u64* guard_object) {
return (((u08*)guard_object)[1] != 0);
}
static void setInUse(u64* guard_object) { ((u08*)guard_object)[1] = 1; } static void setInUse(u64* guard_object) {
((u08*)guard_object)[1] = 1;
}
static void setNotInUse(u64* guard_object) { ((u08*)guard_object)[1] = 0; } static void setNotInUse(u64* guard_object) {
((u08*)guard_object)[1] = 0;
}
// //
// Returns 1 if the caller needs to run the initializer and then either // Returns 1 if the caller needs to run the initializer and then either
@ -75,7 +86,8 @@ static void setNotInUse(u64* guard_object) { ((u08*)guard_object)[1] = 0; }
// //
int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) { int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) {
// Double check that the initializer has not already been run // Double check that the initializer has not already been run
if (initializerHasRun(guard_object)) return 0; if (initializerHasRun(guard_object))
return 0;
// We now need to acquire a lock that allows only one thread // We now need to acquire a lock that allows only one thread
// to run the initializer. If a different thread calls // to run the initializer. If a different thread calls
@ -89,7 +101,8 @@ int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) {
int result = ::pthread_mutex_lock(guard_mutex()); int result = ::pthread_mutex_lock(guard_mutex());
if (result != 0) { if (result != 0) {
LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_lock failed with {}\n", result); LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_lock failed with {}\n",
result);
} }
// At this point all other threads will block in __cxa_guard_acquire() // At this point all other threads will block in __cxa_guard_acquire()
@ -97,7 +110,8 @@ int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) {
if (initializerHasRun(guard_object)) { if (initializerHasRun(guard_object)) {
int result = ::pthread_mutex_unlock(guard_mutex()); int result = ::pthread_mutex_unlock(guard_mutex());
if (result != 0) { if (result != 0) {
LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_unlock failed with {}\n", result); LOG_TRACE_IF(log_file_cxa,
"__cxa_guard_acquire(): pthread_mutex_unlock failed with {}\n", result);
} }
return 0; return 0;
} }
@ -107,7 +121,8 @@ int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) {
// But if the same thread can call __cxa_guard_acquire() on the // But if the same thread can call __cxa_guard_acquire() on the
// *same* guard object again, we call abort(); // *same* guard object again, we call abort();
if (inUse(guard_object)) { if (inUse(guard_object)) {
LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): initializer for function local static variable called enclosing function\n"); LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): initializer for function local static "
"variable called enclosing function\n");
} }
// mark this guard object as being in use // mark this guard object as being in use
@ -129,7 +144,8 @@ void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object) {
// release global mutex // release global mutex
int result = ::pthread_mutex_unlock(guard_mutex()); int result = ::pthread_mutex_unlock(guard_mutex());
if (result != 0) { if (result != 0) {
LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_unlock failed with {}\n", result); LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_unlock failed with {}\n",
result);
} }
} }
@ -139,7 +155,8 @@ void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object) {
void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object) { void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object) {
int result = ::pthread_mutex_unlock(guard_mutex()); int result = ::pthread_mutex_unlock(guard_mutex());
if (result != 0) { if (result != 0) {
LOG_TRACE_IF(log_file_cxa, "__cxa_guard_abort(): pthread_mutex_unlock failed with {}\n", result); LOG_TRACE_IF(log_file_cxa, "__cxa_guard_abort(): pthread_mutex_unlock failed with {}\n",
result);
} }
// now reset state, so possible to try to initialize again // now reset state, so possible to try to initialize again

View File

@ -1,6 +1,6 @@
#include <cstdlib> #include <cstdlib>
#include "common/log.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/log.h"
#include "core/hle/libraries/libc/libc_stdlib.h" #include "core/hle/libraries/libc/libc_stdlib.h"
namespace Core::Libraries::LibC { namespace Core::Libraries::LibC {
@ -35,7 +35,8 @@ int qsort_compair(const void* arg1, const void* arg2) {
return compair_ps4(arg1, arg2); return compair_ps4(arg1, arg2);
} }
void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size, int(PS4_SYSV_ABI* comp)(const void*, const void*)) { void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size,
int(PS4_SYSV_ABI* comp)(const void*, const void*)) {
compair_ps4 = comp; compair_ps4 = comp;
std::qsort(ptr, count, size, qsort_compair); std::qsort(ptr, count, size, qsort_compair);
} }

View File

@ -9,7 +9,8 @@ void PS4_SYSV_ABI ps4_exit(int code);
int PS4_SYSV_ABI ps4_atexit(void (*func)()); int PS4_SYSV_ABI ps4_atexit(void (*func)());
void* PS4_SYSV_ABI ps4_malloc(size_t size); void* PS4_SYSV_ABI ps4_malloc(size_t size);
void PS4_SYSV_ABI ps4_free(void* ptr); void PS4_SYSV_ABI ps4_free(void* ptr);
void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size, int(PS4_SYSV_ABI* comp)(const void*, const void*)); void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size,
int(PS4_SYSV_ABI* comp)(const void*, const void*));
int PS4_SYSV_ABI ps4_rand(); int PS4_SYSV_ABI ps4_rand();
} // namespace Core::Libraries::LibC } // namespace Core::Libraries::LibC

View File

@ -140,7 +140,9 @@ static inline unsigned int _strlen(const char* str) {
// internal test if char is a digit (0-9) // internal test if char is a digit (0-9)
// \return true if char is a digit // \return true if char is a digit
static inline bool _is_digit(char ch) { return (ch >= '0') && (ch <= '9'); } static inline bool _is_digit(char ch) {
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to unsigned int conversion // internal ASCII string to unsigned int conversion
static inline unsigned int _atoi(const char** str) { static inline unsigned int _atoi(const char** str) {
@ -152,7 +154,8 @@ static inline unsigned int _atoi(const char** str) {
} }
// internal itoa format // internal itoa format
static inline size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, static inline size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen,
char* buf, size_t len, bool negative, unsigned int base,
unsigned int prec, unsigned int width, unsigned int flags) { unsigned int prec, unsigned int width, unsigned int flags) {
const size_t start_idx = idx; const size_t start_idx = idx;
@ -160,7 +163,8 @@ static inline size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, si
while (!(flags & FLAGS_LEFT) && (len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { while (!(flags & FLAGS_LEFT) && (len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0'; buf[len++] = '0';
} }
while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) &&
(len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0'; buf[len++] = '0';
} }
@ -220,7 +224,8 @@ static inline size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, si
} }
// internal itoa for 'long' type // internal itoa for 'long' type
static inline size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, static inline size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen,
unsigned long value, bool negative, unsigned long base,
unsigned int prec, unsigned int width, unsigned int flags) { unsigned int prec, unsigned int width, unsigned int flags) {
char buf[PRINTF_NTOA_BUFFER_SIZE]; char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U; size_t len = 0U;
@ -229,18 +234,22 @@ static inline size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size
if (!(flags & FLAGS_PRECISION) || value) { if (!(flags & FLAGS_PRECISION) || value) {
do { do {
const char digit = (char)(value % base); const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; buf[len++] =
digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base; value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
} }
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec,
width, flags);
} }
// internal itoa for 'long long' type // internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG) #if defined(PRINTF_SUPPORT_LONG_LONG)
static inline size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, static inline size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen,
unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) { unsigned long long value, bool negative,
unsigned long long base, unsigned int prec, unsigned int width,
unsigned int flags) {
char buf[PRINTF_NTOA_BUFFER_SIZE]; char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U; size_t len = 0U;
@ -248,18 +257,20 @@ static inline size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx,
if (!(flags & FLAGS_PRECISION) || value) { if (!(flags & FLAGS_PRECISION) || value) {
do { do {
const char digit = (char)(value % base); const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; buf[len++] =
digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base; value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
} }
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec,
width, flags);
} }
#endif // PRINTF_SUPPORT_LONG_LONG #endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT) #if defined(PRINTF_SUPPORT_FLOAT)
static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value,
unsigned int flags) { unsigned int prec, unsigned int width, unsigned int flags) {
char buf[PRINTF_FTOA_BUFFER_SIZE]; char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U; size_t len = 0U;
double diff = 0.0; double diff = 0.0;
@ -268,7 +279,8 @@ static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t ma
const double thres_max = (double)0x7FFFFFFF; const double thres_max = (double)0x7FFFFFFF;
// powers of 10 // powers of 10
static const double pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; static const double pow10[] = {1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000};
// test for negative // test for negative
bool negative = false; bool negative = false;
@ -304,8 +316,9 @@ static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t ma
++frac; ++frac;
} }
// TBD: for very large numbers switch back to native sprintf for exponentials. Anyone want to write code to replace this? // TBD: for very large numbers switch back to native sprintf for exponentials. Anyone want to
// Normal printf behavior is to print EVERY whole number digit which can be 100s of characters overflowing your buffers == bad // write code to replace this? Normal printf behavior is to print EVERY whole number digit which
// can be 100s of characters overflowing your buffers == bad
if (value > thres_max) { if (value > thres_max) {
return 0U; return 0U;
} }
@ -349,7 +362,8 @@ static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t ma
} }
// pad leading zeros // pad leading zeros
while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) &&
(len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0'; buf[len++] = '0';
} }
@ -442,7 +456,9 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
format++; format++;
n = 1U; n = 1U;
break; break;
default: n = 0U; break; default:
n = 0U;
break;
} }
} while (n); } while (n);
@ -470,7 +486,8 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
if (_is_digit(*format)) { if (_is_digit(*format)) {
precision = _atoi(&format); precision = _atoi(&format);
} else if (*format == '*') { } else if (*format == '*') {
precision = vaArgInteger(va_list); // precision = (unsigned int)va.next<int>(cpu, mem); precision =
vaArgInteger(va_list); // precision = (unsigned int)va.next<int>(cpu, mem);
format++; format++;
} }
} }
@ -507,7 +524,8 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++; format++;
break; break;
default: break; default:
break;
} }
// evaluate specifier // evaluate specifier
@ -547,42 +565,55 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
// signed // signed
if (flags & FLAGS_LONG_LONG) { if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG) #if defined(PRINTF_SUPPORT_LONG_LONG)
auto value = vaArgLongLong(va_list); // const long long value = va.next<long long>(cpu, mem); auto value = vaArgLongLong(
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, va_list); // const long long value = va.next<long long>(cpu, mem);
precision, width, flags); idx = _ntoa_long_long(out, buffer, idx, maxlen,
(unsigned long long)(value > 0 ? value : 0 - value),
value < 0, base, precision, width, flags);
#endif #endif
} else if (flags & FLAGS_LONG) { } else if (flags & FLAGS_LONG) {
auto value = vaArgLong(va_list); // const long value = va.next<long>(cpu, mem); auto value = vaArgLong(va_list); // const long value = va.next<long>(cpu, mem);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, idx = _ntoa_long(out, buffer, idx, maxlen,
flags); (unsigned long)(value > 0 ? value : 0 - value), value < 0,
base, precision, width, flags);
} else { } else {
// const int value = (flags & FLAGS_CHAR) ? (char)va.next<int>(cpu, mem) : (flags & FLAGS_SHORT) ? (short // const int value = (flags & FLAGS_CHAR) ? (char)va.next<int>(cpu, mem) :
// int)va.next<int>(cpu, mem): va.next<int>(cpu, mem); // (flags & FLAGS_SHORT) ? (short int)va.next<int>(cpu, mem): va.next<int>(cpu,
const int value = (flags & FLAGS_CHAR) ? static_cast<char>(vaArgInteger(va_list)) // mem);
const int value =
(flags & FLAGS_CHAR) ? static_cast<char>(vaArgInteger(va_list))
: (flags & FLAGS_SHORT) ? static_cast<int16_t>(vaArgInteger(va_list)) : (flags & FLAGS_SHORT) ? static_cast<int16_t>(vaArgInteger(va_list))
: vaArgInteger(va_list); : vaArgInteger(va_list);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, idx = _ntoa_long(out, buffer, idx, maxlen,
flags); (unsigned int)(value > 0 ? value : 0 - value), value < 0, base,
precision, width, flags);
} }
} else { } else {
// unsigned // unsigned
if (flags & FLAGS_LONG_LONG) { if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG) #if defined(PRINTF_SUPPORT_LONG_LONG)
// idx = _ntoa_long_long(out, buffer, idx, maxlen, va.next<unsigned long long>(cpu, mem), false, base, precision, width, // idx = _ntoa_long_long(out, buffer, idx, maxlen, va.next<unsigned long
// flags); // long>(cpu, mem), false, base, precision, width, flags);
idx = idx = _ntoa_long_long(out, buffer, idx, maxlen,
_ntoa_long_long(out, buffer, idx, maxlen, static_cast<u64>(vaArgLongLong(va_list)), false, base, precision, width, flags); static_cast<u64>(vaArgLongLong(va_list)), false, base,
precision, width, flags);
#endif #endif
} else if (flags & FLAGS_LONG) { } else if (flags & FLAGS_LONG) {
// idx = _ntoa_long(out, buffer, idx, maxlen, va.next<unsigned long>(cpu, mem), false, base, precision, width, flags); // idx = _ntoa_long(out, buffer, idx, maxlen, va.next<unsigned long>(cpu, mem),
idx = _ntoa_long(out, buffer, idx, maxlen, static_cast<u32>(vaArgLong(va_list)), false, base, precision, width, flags); // false, base, precision, width, flags);
idx = _ntoa_long(out, buffer, idx, maxlen, static_cast<u32>(vaArgLong(va_list)),
false, base, precision, width, flags);
} else { } else {
// const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va.next<unsigned int>(cpu, mem) : (flags & FLAGS_SHORT) ? // const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned
// (unsigned short int)va.next<unsigned int>(cpu, mem) : va.next<unsigned int>(cpu, mem); // char)va.next<unsigned int>(cpu, mem) : (flags & FLAGS_SHORT) ?
const unsigned int value = (flags & FLAGS_CHAR) ? static_cast<u08>(vaArgInteger(va_list)) // (unsigned short int)va.next<unsigned int>(cpu, mem) : va.next<unsigned
// int>(cpu, mem);
const unsigned int value =
(flags & FLAGS_CHAR) ? static_cast<u08>(vaArgInteger(va_list))
: (flags & FLAGS_SHORT) ? static_cast<u16>(vaArgInteger(va_list)) : (flags & FLAGS_SHORT) ? static_cast<u16>(vaArgInteger(va_list))
: static_cast<u32>(vaArgInteger(va_list)); : static_cast<u32>(vaArgInteger(va_list));
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width,
flags);
} }
} }
format++; format++;
@ -591,7 +622,8 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
#if defined(PRINTF_SUPPORT_FLOAT) #if defined(PRINTF_SUPPORT_FLOAT)
case 'f': case 'f':
case 'F': case 'F':
// idx = _ftoa(out, buffer, idx, maxlen, va.next<double>(cpu, mem), precision, width, flags); // idx = _ftoa(out, buffer, idx, maxlen, va.next<double>(cpu, mem), precision, width,
// flags);
idx = _ftoa(out, buffer, idx, maxlen, vaArgDouble(va_list), precision, width, flags); idx = _ftoa(out, buffer, idx, maxlen, vaArgDouble(va_list), precision, width, flags);
format++; format++;
break; break;
@ -618,7 +650,8 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
} }
case 's': { case 's': {
const char* p = vaArgPtr<const char>(va_list); // const char *p = va.next<Ptr<char>>(cpu, mem).get(mem); const char* p = vaArgPtr<const char>(
va_list); // const char *p = va.next<Ptr<char>>(cpu, mem).get(mem);
p = p != nullptr ? p : "(null)"; p = p != nullptr ? p : "(null)";
unsigned int l = _strlen(p); unsigned int l = _strlen(p);
// pre padding // pre padding
@ -650,16 +683,21 @@ static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format,
#if defined(PRINTF_SUPPORT_LONG_LONG) #if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long); const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) { if (is_ll) {
// idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va.next<Ptr<void>>(cpu, mem).address(), false, 16U, precision, // idx = _ntoa_long_long(out, buffer, idx, maxlen,
// width, flags); // (uintptr_t)va.next<Ptr<void>>(cpu, mem).address(), false, 16U, precision, width,
idx = _ntoa_long_long(out, buffer, idx, maxlen, reinterpret_cast<uintptr_t>(vaArgPtr<void>(va_list)), false, 16U, precision, // flags);
width, flags); idx = _ntoa_long_long(out, buffer, idx, maxlen,
reinterpret_cast<uintptr_t>(vaArgPtr<void>(va_list)), false,
16U, precision, width, flags);
} else { } else {
#endif #endif
// idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va.next<Ptr<void>>(cpu, mem).address()), false, 16U, // idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned
// precision, width, flags); // long)((uintptr_t)va.next<Ptr<void>>(cpu, mem).address()), false, 16U, precision,
idx = _ntoa_long(out, buffer, idx, maxlen, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(vaArgPtr<void>(va_list))), false, // width, flags);
16U, precision, width, flags); idx = _ntoa_long(
out, buffer, idx, maxlen,
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(vaArgPtr<void>(va_list))),
false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG) #if defined(PRINTF_SUPPORT_LONG_LONG)
} }
#endif #endif

View File

@ -1,9 +1,10 @@
#include "common/types.h"
#include <xmmintrin.h> #include <xmmintrin.h>
#include "common/types.h"
#define VA_ARGS \ #define VA_ARGS \
uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, \ uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \
__m128 xmm2, __m128 xmm3, __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ... uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \
__m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
#define VA_CTX(ctx) \ #define VA_CTX(ctx) \
alignas(16) VaCtx ctx; \ alignas(16) VaCtx ctx; \

View File

@ -1,17 +1,18 @@
#include "common/log.h" #include <common/singleton.h>
#include <core/file_sys/fs.h>
#include <core/hle/error_codes.h>
#include "common/debug.h" #include "common/debug.h"
#include "common/log.h"
#include "core/hle/libraries/libkernel/file_system.h" #include "core/hle/libraries/libkernel/file_system.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include <core/file_sys/fs.h>
#include <common/singleton.h>
#include <core/hle/error_codes.h>
namespace Core::Libraries::LibKernel { namespace Core::Libraries::LibKernel {
constexpr bool log_file_fs = true; // disable it to disable logging constexpr bool log_file_fs = true; // disable it to disable logging
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
LOG_INFO_IF(log_file_fs, "sceKernelOpen path = {} flags = {:#x} mode = {:#x}\n", path, flags, mode); LOG_INFO_IF(log_file_fs, "sceKernelOpen path = {} flags = {:#x} mode = {:#x}\n", path, flags,
mode);
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
@ -45,7 +46,7 @@ size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
size_t total_read = 0; size_t total_read = 0;
file->m_mutex.lock(); file->m_mutex.lock();
for (int i = 0; i < iovcnt; i++) { for (int i = 0; i < iovcnt; i++) {
total_read += file->f.readBytes(iov[i].iov_base,iov[i].iov_len).second; total_read += file->f.readBytes(iov[i].iov_base, iov[i].iov_len).second;
} }
file->m_mutex.unlock(); file->m_mutex.unlock();
return total_read; return total_read;
@ -57,7 +58,8 @@ void fileSystemSymbolsRegister(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv); LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv);
// openOrbis (to check if it is valid out of OpenOrbis // openOrbis (to check if it is valid out of OpenOrbis
LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1, posix_open); // _open shoudld be equal to open function LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1,
posix_open); // _open shoudld be equal to open function
} }
} // namespace Core::Libraries::LibKernel } // namespace Core::Libraries::LibKernel

View File

@ -9,14 +9,14 @@ class SymbolsResolver;
namespace Core::Libraries::LibKernel { namespace Core::Libraries::LibKernel {
struct SceKernelIovec { struct SceKernelIovec {
void *iov_base; void* iov_base;
size_t iov_len; size_t iov_len;
}; };
int PS4_SYSV_ABI sceKernelOpen(const char *path, int flags, /* SceKernelMode*/ u16 mode); int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, /* SceKernelMode*/ u16 mode);
int PS4_SYSV_ABI posix_open(const char *path, int flags, /* SceKernelMode*/ u16 mode); int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode);
void fileSystemSymbolsRegister(Loader::SymbolsResolver *sym); void fileSystemSymbolsRegister(Loader::SymbolsResolver* sym);
} // namespace Core::Libraries::LibKernel } // namespace Core::Libraries::LibKernel

View File

@ -13,8 +13,8 @@
#include "core/loader/elf.h" #include "core/loader/elf.h"
#ifdef _WIN64 #ifdef _WIN64
#include <windows.h>
#include <io.h> #include <io.h>
#include <windows.h>
#else #else
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
@ -31,11 +31,17 @@ int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len) {
return 0; return 0;
} }
static PS4_SYSV_ABI void stack_chk_fail() { BREAKPOINT(); } static PS4_SYSV_ABI void stack_chk_fail() {
BREAKPOINT();
}
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) { BREAKPOINT(); } int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) {
BREAKPOINT();
}
void PS4_SYSV_ABI sceKernelUsleep(unsigned int microseconds) { std::this_thread::sleep_for(std::chrono::microseconds(microseconds)); } void PS4_SYSV_ABI sceKernelUsleep(unsigned int microseconds) {
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
}
struct iovec { struct iovec {
void* iov_base; /* Base address. */ void* iov_base; /* Base address. */
@ -43,7 +49,8 @@ struct iovec {
}; };
size_t PS4_SYSV_ABI _writev(int fd, const struct iovec* iov, int iovcn) { size_t PS4_SYSV_ABI _writev(int fd, const struct iovec* iov, int iovcn) {
// weird it gives fd ==0 and writes to stdout , i am not sure if it that is valid (found in openorbis) // weird it gives fd ==0 and writes to stdout , i am not sure if it that is valid (found in
// openorbis)
size_t total_written = 0; size_t total_written = 0;
for (int i = 0; i < iovcn; i++) { for (int i = 0; i < iovcn; i++) {
total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout); total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout);
@ -52,12 +59,15 @@ size_t PS4_SYSV_ABI _writev(int fd, const struct iovec* iov, int iovcn) {
} }
static thread_local int libc_error; static thread_local int libc_error;
int* PS4_SYSV_ABI __Error() { return &libc_error; } int* PS4_SYSV_ABI __Error() {
return &libc_error;
}
#define PROT_READ 0x1 #define PROT_READ 0x1
#define PROT_WRITE 0x2 #define PROT_WRITE 0x2
int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, off_t offset, void** res) { int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, off_t offset,
void** res) {
#ifdef _WIN64 #ifdef _WIN64
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (prot > 3) // READ,WRITE or bitwise READ | WRITE supported if (prot > 3) // READ,WRITE or bitwise READ | WRITE supported
@ -76,7 +86,8 @@ int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd,
mmap_fd = (HANDLE)_get_osfhandle(fd); mmap_fd = (HANDLE)_get_osfhandle(fd);
h = CreateFileMapping(mmap_fd, NULL, flProtect, 0, end, NULL); h = CreateFileMapping(mmap_fd, NULL, flProtect, 0, end, NULL);
int k = GetLastError(); int k = GetLastError();
if (NULL == h) return -1; if (NULL == h)
return -1;
DWORD dwDesiredAccess; DWORD dwDesiredAccess;
if (prot & PROT_WRITE) if (prot & PROT_WRITE)
dwDesiredAccess = FILE_MAP_WRITE; dwDesiredAccess = FILE_MAP_WRITE;
@ -102,7 +113,8 @@ int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd,
PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) { PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) {
void* ptr; void* ptr;
LOG_INFO_IF(log_libkernel_file, "posix mmap redirect to sceKernelMmap\n"); LOG_INFO_IF(log_libkernel_file, "posix mmap redirect to sceKernelMmap\n");
// posix call the difference is that there is a different behaviour when it doesn't return 0 or SCE_OK // posix call the difference is that there is a different behaviour when it doesn't return 0 or
// SCE_OK
int result = sceKernelMmap(addr, len, prot, flags, fd, offset, &ptr); int result = sceKernelMmap(addr, len, prot, flags, fd, offset, &ptr);
if (result != 0) { if (result != 0) {
BREAKPOINT(); BREAKPOINT();
@ -114,9 +126,12 @@ void LibKernel_Register(Loader::SymbolsResolver* sym) {
// obj // obj
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
// memory // memory
LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1, Kernel::sceKernelAllocateDirectMemory); LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1,
LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, Kernel::sceKernelGetDirectMemorySize); Kernel::sceKernelAllocateDirectMemory);
LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, Kernel::sceKernelMapDirectMemory); LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1,
Kernel::sceKernelGetDirectMemorySize);
LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1,
Kernel::sceKernelMapDirectMemory);
LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory); LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory);
LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap); LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap);
// equeue // equeue

View File

@ -49,9 +49,12 @@ int PS4_SYSV_ABI scePthreadAttrInit(ScePthreadAttr* attr) {
result = (result == 0 ? scePthreadAttrSetdetachstate(attr, PTHREAD_CREATE_JOINABLE) : result); result = (result == 0 ? scePthreadAttrSetdetachstate(attr, PTHREAD_CREATE_JOINABLE) : result);
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; return SCE_OK;
default: return SCE_KERNEL_ERROR_EINVAL; case ENOMEM:
return SCE_KERNEL_ERROR_ENOMEM;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
@ -62,12 +65,20 @@ int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachst
int pstate = PTHREAD_CREATE_JOINABLE; int pstate = PTHREAD_CREATE_JOINABLE;
switch (detachstate) { switch (detachstate) {
case 0: pstate = PTHREAD_CREATE_JOINABLE; break; case 0:
case 1: pstate = PTHREAD_CREATE_DETACHED; break; pstate = PTHREAD_CREATE_JOINABLE;
default: LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetdetachstate invalid detachstate: {}\n", detachstate); std::exit(0); break;
case 1:
pstate = PTHREAD_CREATE_DETACHED;
break;
default:
LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetdetachstate invalid detachstate: {}\n",
detachstate);
std::exit(0);
} }
// int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work correctly // int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work
// correctly
int result = 0; int result = 0;
(*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED); (*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED);
@ -82,9 +93,16 @@ int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inherit
int pinherit_sched = PTHREAD_INHERIT_SCHED; int pinherit_sched = PTHREAD_INHERIT_SCHED;
switch (inheritSched) { switch (inheritSched) {
case 0: pinherit_sched = PTHREAD_EXPLICIT_SCHED; break; case 0:
case 4: pinherit_sched = PTHREAD_INHERIT_SCHED; break; pinherit_sched = PTHREAD_EXPLICIT_SCHED;
default: LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetinheritsched invalid inheritSched: {}\n", inheritSched); std::exit(0); break;
case 4:
pinherit_sched = PTHREAD_INHERIT_SCHED;
break;
default:
LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetinheritsched invalid inheritSched: {}\n",
inheritSched);
std::exit(0);
} }
int result = pthread_attr_setinheritsched(&(*attr)->pth_attr, pinherit_sched); int result = pthread_attr_setinheritsched(&(*attr)->pth_attr, pinherit_sched);
@ -92,7 +110,8 @@ int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inherit
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
} }
int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param) { int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr,
const SceKernelSchedParam* param) {
if (param == nullptr || attr == nullptr || *attr == nullptr) { if (param == nullptr || attr == nullptr || *attr == nullptr) {
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
@ -118,7 +137,9 @@ int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy)
int ppolicy = SCHED_OTHER; // winpthreads only supports SCHED_OTHER int ppolicy = SCHED_OTHER; // winpthreads only supports SCHED_OTHER
if (policy != SCHED_OTHER) { if (policy != SCHED_OTHER) {
LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetschedpolicy policy={} not supported by winpthreads\n", policy); LOG_TRACE_IF(log_pthread_file,
"scePthreadAttrSetschedpolicy policy={} not supported by winpthreads\n",
policy);
} }
(*attr)->policy = policy; (*attr)->policy = policy;
@ -126,9 +147,12 @@ int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy)
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
} }
ScePthread PS4_SYSV_ABI scePthreadSelf() { return g_pthread_self; } ScePthread PS4_SYSV_ABI scePthreadSelf() {
return g_pthread_self;
}
int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr, const /*SceKernelCpumask*/ u64 mask) { int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr,
const /*SceKernelCpumask*/ u64 mask) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (pattr == nullptr || *pattr == nullptr) { if (pattr == nullptr || *pattr == nullptr) {
@ -151,7 +175,8 @@ int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpuma
return result; return result;
} }
int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr, pthreadEntryFunc start_routine, void* arg, const char* name) { int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg, const char* name) {
PRINT_DUMMY_FUNCTION_NAME(); PRINT_DUMMY_FUNCTION_NAME();
return 0; return 0;
} }
@ -169,7 +194,8 @@ void* createMutex(void* addr) {
return addr; return addr;
} }
int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr, const char* name) { int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr,
const char* name) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (mutex == nullptr) { if (mutex == nullptr) {
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
@ -192,11 +218,16 @@ int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMut
} }
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
case EAGAIN: return SCE_KERNEL_ERROR_EAGAIN; return SCE_OK;
case EINVAL: return SCE_KERNEL_ERROR_EINVAL; case EAGAIN:
case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; return SCE_KERNEL_ERROR_EAGAIN;
default: return SCE_KERNEL_ERROR_EINVAL; case EINVAL:
return SCE_KERNEL_ERROR_EINVAL;
case ENOMEM:
return SCE_KERNEL_ERROR_ENOMEM;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
@ -209,20 +240,31 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) {
result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result); result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result);
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; return SCE_OK;
default: return SCE_KERNEL_ERROR_EINVAL; case ENOMEM:
return SCE_KERNEL_ERROR_ENOMEM;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) { int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) {
int ptype = PTHREAD_MUTEX_DEFAULT; int ptype = PTHREAD_MUTEX_DEFAULT;
switch (type) { switch (type) {
case 1: ptype = PTHREAD_MUTEX_ERRORCHECK; break; case 1:
case 2: ptype = PTHREAD_MUTEX_RECURSIVE; break; ptype = PTHREAD_MUTEX_ERRORCHECK;
break;
case 2:
ptype = PTHREAD_MUTEX_RECURSIVE;
break;
case 3: case 3:
case 4: ptype = PTHREAD_MUTEX_NORMAL; break; case 4:
default: LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSettype invalid type: {}\n", type); std::exit(0); ptype = PTHREAD_MUTEX_NORMAL;
break;
default:
LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSettype invalid type: {}\n", type);
std::exit(0);
} }
int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype); int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype);
@ -233,13 +275,23 @@ int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type)
int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol) { int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol) {
int pprotocol = PTHREAD_PRIO_NONE; int pprotocol = PTHREAD_PRIO_NONE;
switch (protocol) { switch (protocol) {
case 0: pprotocol = PTHREAD_PRIO_NONE; break; case 0:
case 1: pprotocol = PTHREAD_PRIO_INHERIT; break; pprotocol = PTHREAD_PRIO_NONE;
case 2: pprotocol = PTHREAD_PRIO_PROTECT; break; break;
default: LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSetprotocol invalid protocol: {}\n", protocol); std::exit(0); case 1:
pprotocol = PTHREAD_PRIO_INHERIT;
break;
case 2:
pprotocol = PTHREAD_PRIO_PROTECT;
break;
default:
LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSetprotocol invalid protocol: {}\n",
protocol);
std::exit(0);
} }
int result = 0; // pthread_mutexattr_setprotocol(&(*attr)->p, pprotocol); //it appears that pprotocol has issues in winpthreads int result = 0; // pthread_mutexattr_setprotocol(&(*attr)->p, pprotocol); //it appears that
// pprotocol has issues in winpthreads
(*attr)->pprotocol = pprotocol; (*attr)->pprotocol = pprotocol;
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
@ -253,13 +305,19 @@ int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
} }
int result = pthread_mutex_lock(&(*mutex)->pth_mutex); int result = pthread_mutex_lock(&(*mutex)->pth_mutex);
LOG_INFO_IF(log_pthread_file, "scePthreadMutexLock name={} result={}\n", (*mutex)->name, result); LOG_INFO_IF(log_pthread_file, "scePthreadMutexLock name={} result={}\n", (*mutex)->name,
result);
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
case EAGAIN: return SCE_KERNEL_ERROR_EAGAIN; return SCE_OK;
case EINVAL: return SCE_KERNEL_ERROR_EINVAL; case EAGAIN:
case EDEADLK: return SCE_KERNEL_ERROR_EDEADLK; return SCE_KERNEL_ERROR_EAGAIN;
default: return SCE_KERNEL_ERROR_EINVAL; case EINVAL:
return SCE_KERNEL_ERROR_EINVAL;
case EDEADLK:
return SCE_KERNEL_ERROR_EDEADLK;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) { int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
@ -270,13 +328,18 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
} }
int result = pthread_mutex_unlock(&(*mutex)->pth_mutex); int result = pthread_mutex_unlock(&(*mutex)->pth_mutex);
LOG_INFO_IF(log_pthread_file, "scePthreadMutexUnlock name={} result={}\n", (*mutex)->name, result); LOG_INFO_IF(log_pthread_file, "scePthreadMutexUnlock name={} result={}\n", (*mutex)->name,
result);
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
return SCE_OK;
case EINVAL: return SCE_KERNEL_ERROR_EINVAL; case EINVAL:
case EPERM: return SCE_KERNEL_ERROR_EPERM; return SCE_KERNEL_ERROR_EINVAL;
default: return SCE_KERNEL_ERROR_EINVAL; case EPERM:
return SCE_KERNEL_ERROR_EPERM;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
@ -294,7 +357,8 @@ void* createCond(void* addr) {
return addr; return addr;
} }
int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondattr* attr, const char* name) { int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondattr* attr,
const char* name) {
if (cond == nullptr) { if (cond == nullptr) {
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
@ -318,11 +382,16 @@ int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondat
} }
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
case EAGAIN: return SCE_KERNEL_ERROR_EAGAIN; return SCE_OK;
case EINVAL: return SCE_KERNEL_ERROR_EINVAL; case EAGAIN:
case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; return SCE_KERNEL_ERROR_EAGAIN;
default: return SCE_KERNEL_ERROR_EINVAL; case EINVAL:
return SCE_KERNEL_ERROR_EINVAL;
case ENOMEM:
return SCE_KERNEL_ERROR_ENOMEM;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
@ -332,9 +401,12 @@ int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr) {
int result = pthread_condattr_init(&(*attr)->cond_attr); int result = pthread_condattr_init(&(*attr)->cond_attr);
switch (result) { switch (result) {
case 0: return SCE_OK; case 0:
case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; return SCE_OK;
default: return SCE_KERNEL_ERROR_EINVAL; case ENOMEM:
return SCE_KERNEL_ERROR_ENOMEM;
default:
return SCE_KERNEL_ERROR_EINVAL;
} }
} }
@ -359,7 +431,9 @@ int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthre
LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_init redirect to scePthreadMutexInit\n"); LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_init redirect to scePthreadMutexInit\n");
int result = scePthreadMutexInit(mutex, attr, nullptr); int result = scePthreadMutexInit(mutex, attr, nullptr);
if (result < 0) { if (result < 0) {
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP ? result + -SCE_KERNEL_ERROR_UNKNOWN : POSIX_EOTHER; int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt; return rt;
} }
return result; return result;
@ -369,7 +443,9 @@ int PS4_SYSV_ABI posix_pthread_mutex_lock(ScePthreadMutex* mutex) {
LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_lock redirect to scePthreadMutexLock\n"); LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_lock redirect to scePthreadMutexLock\n");
int result = scePthreadMutexLock(mutex); int result = scePthreadMutexLock(mutex);
if (result < 0) { if (result < 0) {
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP ? result + -SCE_KERNEL_ERROR_UNKNOWN : POSIX_EOTHER; int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt; return rt;
} }
return result; return result;
@ -379,17 +455,22 @@ int PS4_SYSV_ABI posix_pthread_mutex_unlock(ScePthreadMutex* mutex) {
LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_unlock redirect to scePthreadMutexUnlock\n"); LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_unlock redirect to scePthreadMutexUnlock\n");
int result = scePthreadMutexUnlock(mutex); int result = scePthreadMutexUnlock(mutex);
if (result < 0) { if (result < 0) {
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP ? result + -SCE_KERNEL_ERROR_UNKNOWN : POSIX_EOTHER; int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt; return rt;
} }
return result; return result;
} }
int PS4_SYSV_ABI posix_pthread_cond_broadcast(ScePthreadCond* cond) { int PS4_SYSV_ABI posix_pthread_cond_broadcast(ScePthreadCond* cond) {
LOG_INFO_IF(log_pthread_file, "posix posix_pthread_cond_broadcast redirect to scePthreadCondBroadcast\n"); LOG_INFO_IF(log_pthread_file,
"posix posix_pthread_cond_broadcast redirect to scePthreadCondBroadcast\n");
int result = scePthreadCondBroadcast(cond); int result = scePthreadCondBroadcast(cond);
if (result != 0) { if (result != 0) {
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP ? result + -SCE_KERNEL_ERROR_UNKNOWN : POSIX_EOTHER; int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt; return rt;
} }
return result; return result;
@ -412,7 +493,7 @@ void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol); LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol);
LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock); LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock);
LIB_FUNCTION("tn3VlD0hG60", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexUnlock); LIB_FUNCTION("tn3VlD0hG60", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexUnlock);
//cond calls // cond calls
LIB_FUNCTION("2Tb92quprl0", "libkernel", 1, "libkernel", 1, 1, scePthreadCondInit); LIB_FUNCTION("2Tb92quprl0", "libkernel", 1, "libkernel", 1, 1, scePthreadCondInit);
LIB_FUNCTION("m5-2bsNfv7s", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrInit); LIB_FUNCTION("m5-2bsNfv7s", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrInit);
LIB_FUNCTION("JGgj7Uvrl+A", "libkernel", 1, "libkernel", 1, 1, scePthreadCondBroadcast); LIB_FUNCTION("JGgj7Uvrl+A", "libkernel", 1, "libkernel", 1, 1, scePthreadCondBroadcast);

View File

@ -71,13 +71,21 @@ struct PthreadCondAttrInternal {
}; };
class PThreadCxt { class PThreadCxt {
public: public:
ScePthreadMutexattr* getDefaultMutexattr() { return &m_default_mutexattr; } ScePthreadMutexattr* getDefaultMutexattr() {
void setDefaultMutexattr(ScePthreadMutexattr attr) { m_default_mutexattr = attr; } return &m_default_mutexattr;
ScePthreadCondattr* getDefaultCondattr() { return &m_default_condattr; } }
void setDefaultCondattr(ScePthreadCondattr attr) { m_default_condattr = attr; } void setDefaultMutexattr(ScePthreadMutexattr attr) {
m_default_mutexattr = attr;
}
ScePthreadCondattr* getDefaultCondattr() {
return &m_default_condattr;
}
void setDefaultCondattr(ScePthreadCondattr attr) {
m_default_condattr = attr;
}
private: private:
ScePthreadMutexattr m_default_mutexattr = nullptr; ScePthreadMutexattr m_default_mutexattr = nullptr;
ScePthreadCondattr m_default_condattr = nullptr; ScePthreadCondattr m_default_condattr = nullptr;
}; };
@ -88,17 +96,21 @@ void pthreadInitSelfMainThread();
int PS4_SYSV_ABI scePthreadAttrInit(ScePthreadAttr* attr); int PS4_SYSV_ABI scePthreadAttrInit(ScePthreadAttr* attr);
int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate); int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate);
int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched); int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched);
int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param); int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr,
const SceKernelSchedParam* param);
int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy); int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy);
ScePthread PS4_SYSV_ABI scePthreadSelf(); ScePthread PS4_SYSV_ABI scePthreadSelf();
int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr, const /*SceKernelCpumask*/ u64 mask); int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr,
const /*SceKernelCpumask*/ u64 mask);
int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpumask*/ u64 mask); int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpumask*/ u64 mask);
int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr, pthreadEntryFunc start_routine, void* arg, const char* name); int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg, const char* name);
/*** /***
* Mutex calls * Mutex calls
*/ */
int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr, const char* name); int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr,
const char* name);
int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr); int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr);
int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type); int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type);
int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol); int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol);
@ -107,10 +119,11 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex);
/**** /****
* Cond calls * Cond calls
*/ */
int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondattr* attr, const char* name); int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondattr* attr,
const char* name);
int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr); int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr);
int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond); int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond);
/**** /****
* Posix calls * Posix calls
*/ */
int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr); int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr);

View File

@ -28,7 +28,8 @@ void timeSymbolsRegister(Loader::SymbolsResolver* sym) {
initial_ptc = clock->GetUptime(); initial_ptc = clock->GetUptime();
LIB_FUNCTION("4J2sUJmuHZQ", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTime); LIB_FUNCTION("4J2sUJmuHZQ", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTime);
LIB_FUNCTION("fgxnMeTNUtY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTimeCounter); LIB_FUNCTION("fgxnMeTNUtY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTimeCounter);
LIB_FUNCTION("BNowx2l588E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTimeCounterFrequency); LIB_FUNCTION("BNowx2l588E", "libkernel", 1, "libkernel", 1, 1,
sceKernelGetProcessTimeCounterFrequency);
LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc); LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc);
} }

View File

@ -1,9 +1,9 @@
#include "Emulator/Host/controller.h"
#include "common/log.h" #include "common/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/hle/libraries/libpad/pad.h"
#include "core/hle/error_codes.h" #include "core/hle/error_codes.h"
#include "core/hle/libraries/libpad/pad.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "Emulator/Host/controller.h"
namespace Core::Libraries::LibPad { namespace Core::Libraries::LibPad {
@ -13,8 +13,8 @@ int PS4_SYSV_ABI scePadInit() {
return SCE_OK; return SCE_OK;
} }
int PS4_SYSV_ABI scePadOpen(Core::Libraries::LibUserService::SceUserServiceUserId userId, s32 type, s32 index, int PS4_SYSV_ABI scePadOpen(Core::Libraries::LibUserService::SceUserServiceUserId userId, s32 type,
const ScePadOpenParam* pParam) { s32 index, const ScePadOpenParam* pParam) {
LOG_INFO_IF(log_file_pad, "scePadOpen userid = {} type = {} index = {}\n", userId, type, index); LOG_INFO_IF(log_file_pad, "scePadOpen userid = {} type = {} index = {}\n", userId, type, index);
return 1; // dummy return 1; // dummy
} }
@ -32,15 +32,15 @@ int PS4_SYSV_ABI scePadReadState(int32_t handle, ScePadData* pData) {
pData->leftStick.y = 128; // dummy pData->leftStick.y = 128; // dummy
pData->rightStick.x = 0; // dummy pData->rightStick.x = 0; // dummy
pData->rightStick.y = 0; // dummy pData->rightStick.y = 0; // dummy
pData->analogButtons.r2 = 0;//dummy pData->analogButtons.r2 = 0; // dummy
pData->analogButtons.l2 = 0;//dummy pData->analogButtons.l2 = 0; // dummy
pData->orientation.x = 0; pData->orientation.x = 0;
pData->orientation.y = 0; pData->orientation.y = 0;
pData->orientation.z = 0; pData->orientation.z = 0;
pData->orientation.w = 0; pData->orientation.w = 0;
pData->timestamp = state.time; pData->timestamp = state.time;
pData->connected = true; // isConnected; //TODO fix me proper pData->connected = true; // isConnected; //TODO fix me proper
pData->connectedCount = 1;//connectedCount; pData->connectedCount = 1; // connectedCount;
pData->deviceUniqueDataLen = 0; pData->deviceUniqueDataLen = 0;
return SCE_OK; return SCE_OK;
@ -52,4 +52,4 @@ void padSymbolsRegister(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("YndgXqQVV7c", "libScePad", 1, "libScePad", 1, 1, scePadReadState); LIB_FUNCTION("YndgXqQVV7c", "libScePad", 1, "libScePad", 1, 1, scePadReadState);
} }
} // namespace Emulator::HLE::Libraries::LibPad } // namespace Core::Libraries::LibPad

View File

@ -1,11 +1,11 @@
#include "core/hle/libraries/libs.h"
#include "core/PS4/HLE/Graphics/video_out.h" #include "core/PS4/HLE/Graphics/video_out.h"
#include "core/hle/libraries/libkernel/libkernel.h"
#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h"
#include "core/hle/libraries/libuserservice/libuserservice.h"
#include "core/hle/libraries/libpad/pad.h"
#include "core/hle/libraries/libsystemservice/system_service.h"
#include "core/hle/libraries/libc/libc.h" #include "core/hle/libraries/libc/libc.h"
#include "core/hle/libraries/libkernel/libkernel.h"
#include "core/hle/libraries/libpad/pad.h"
#include "core/hle/libraries/libs.h"
#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h"
#include "core/hle/libraries/libsystemservice/system_service.h"
#include "core/hle/libraries/libuserservice/libuserservice.h"
namespace Core::Libraries { namespace Core::Libraries {

View File

@ -4,17 +4,17 @@
#include "core/loader/symbols_resolver.h" #include "core/loader/symbols_resolver.h"
#define LIB_FUNCTION(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \ #define LIB_FUNCTION(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \
{\ { \
Loader::SymbolRes sr{}; \ Loader::SymbolRes sr{}; \
sr.name = nid; \ sr.name = nid; \
sr.library = lib; \ sr.library = lib; \
sr.library_version = libversion;\ sr.library_version = libversion; \
sr.module = mod;\ sr.module = mod; \
sr.module_version_major = moduleVersionMajor;\ sr.module_version_major = moduleVersionMajor; \
sr.module_version_minor = moduleVersionMinor;\ sr.module_version_minor = moduleVersionMinor; \
sr.type = STT_FUN;\ sr.type = STT_FUN; \
auto func = reinterpret_cast<u64>(function);\ auto func = reinterpret_cast<u64>(function); \
sym->AddSymbol(sr, func);\ sym->AddSymbol(sr, func); \
} }
#define LIB_OBJ(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \ #define LIB_OBJ(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \
@ -32,9 +32,7 @@
} }
#define PRINT_FUNCTION_NAME() \ #define PRINT_FUNCTION_NAME() \
{ \ { LOG_INFO_IF(true, "{}()\n", __func__); }
LOG_INFO_IF(true, "{}()\n", __func__); \
}
#define PRINT_DUMMY_FUNCTION_NAME() \ #define PRINT_DUMMY_FUNCTION_NAME() \
{ LOG_WARN_IF(true, "dummy {}()\n", __func__); } { LOG_WARN_IF(true, "dummy {}()\n", __func__); }

View File

@ -1,7 +1,7 @@
#include "common/log.h" #include "common/log.h"
#include "core/PS4/GPU/gpu_memory.h" #include "core/PS4/GPU/gpu_memory.h"
#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h"
#include "emulator.h" #include "emulator.h"
namespace Core::Libraries::LibSceGnmDriver { namespace Core::Libraries::LibSceGnmDriver {
@ -21,4 +21,4 @@ void LibSceGnmDriver_Register(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("iBt3Oe00Kvc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmFlushGarlic); LIB_FUNCTION("iBt3Oe00Kvc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmFlushGarlic);
} }
}; }; // namespace Core::Libraries::LibSceGnmDriver

View File

@ -24,8 +24,10 @@ s32 PS4_SYSV_ABI sceSystemServiceGetStatus(SceSystemServiceStatus* status) {
} }
void systemServiceSymbolsRegister(Loader::SymbolsResolver* sym) { void systemServiceSymbolsRegister(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Vo5V8KAwCmk", "libSceSystemService", 1, "libSceSystemService", 1, 1, sceSystemServiceHideSplashScreen); LIB_FUNCTION("Vo5V8KAwCmk", "libSceSystemService", 1, "libSceSystemService", 1, 1,
LIB_FUNCTION("rPo6tV8D9bM", "libSceSystemService", 1, "libSceSystemService", 1, 1, sceSystemServiceGetStatus); sceSystemServiceHideSplashScreen);
LIB_FUNCTION("rPo6tV8D9bM", "libSceSystemService", 1, "libSceSystemService", 1, 1,
sceSystemServiceGetStatus);
} }
}; // namespace Core::Libraries::LibSystemService }; // namespace Core::Libraries::LibSystemService

View File

@ -1,7 +1,7 @@
#include "common/log.h" #include "common/log.h"
#include "core/hle/libraries/libuserservice/libuserservice.h"
#include "core/hle/error_codes.h" #include "core/hle/error_codes.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "core/hle/libraries/libuserservice/libuserservice.h"
namespace Core::Libraries::LibUserService { namespace Core::Libraries::LibUserService {
@ -21,8 +21,10 @@ s32 PS4_SYSV_ABI sceUserServiceGetLoginUserIdList(SceUserServiceLoginUserIdList*
} }
void userServiceSymbolsRegister(Loader::SymbolsResolver* sym) { void userServiceSymbolsRegister(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("j3YMu1MVNNo", "libSceUserService", 1, "libSceUserService", 1, 1, sceUserServiceInitialize); LIB_FUNCTION("j3YMu1MVNNo", "libSceUserService", 1, "libSceUserService", 1, 1,
LIB_FUNCTION("fPhymKNvK-A", "libSceUserService", 1, "libSceUserService", 1, 1, sceUserServiceGetLoginUserIdList); sceUserServiceInitialize);
LIB_FUNCTION("fPhymKNvK-A", "libSceUserService", 1, "libSceUserService", 1, 1,
sceUserServiceGetLoginUserIdList);
} }
} // namespace Core::Libraries::LibUserService } // namespace Core::Libraries::LibUserService

View File

@ -1,12 +1,11 @@
#pragma once #pragma once
//constants // constants
constexpr int SCE_USER_SERVICE_MAX_LOGIN_USERS = 4; //max users logged in at once
constexpr int SCE_USER_SERVICE_MAX_USER_NAME_LENGTH = 16;//Max length for user name
constexpr int SCE_USER_SERVICE_USER_ID_INVALID = -1;//invalid user ID
constexpr int SCE_USER_SERVICE_USER_ID_SYSTEM = 255; //generic id for device
constexpr int SCE_USER_SERVICE_USER_ID_EVERYONE = 254; // generic id for user (mostly used in common dialogs)
constexpr int SCE_USER_SERVICE_MAX_LOGIN_USERS = 4; // max users logged in at once
constexpr int SCE_USER_SERVICE_MAX_USER_NAME_LENGTH = 16; // Max length for user name
constexpr int SCE_USER_SERVICE_USER_ID_INVALID = -1; // invalid user ID
constexpr int SCE_USER_SERVICE_USER_ID_SYSTEM = 255; // generic id for device
constexpr int SCE_USER_SERVICE_USER_ID_EVERYONE =
254; // generic id for user (mostly used in common dialogs)

View File

@ -1,5 +1,5 @@
#include <fmt/core.h>
#include <Zydis/Zydis.h> #include <Zydis/Zydis.h>
#include <fmt/core.h>
#include "common/log.h" #include "common/log.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/aerolib/aerolib.h" #include "core/aerolib/aerolib.h"
@ -14,21 +14,17 @@ constexpr bool debug_loader = true;
static u64 g_load_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET; static u64 g_load_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET;
static u64 get_aligned_size(const elf_program_header& phdr) static u64 get_aligned_size(const elf_program_header& phdr) {
{ return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1)
return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1) : phdr.p_memsz); : phdr.p_memsz);
} }
static u64 calculate_base_size(const elf_header& ehdr, std::span<const elf_program_header> phdr) static u64 calculate_base_size(const elf_header& ehdr, std::span<const elf_program_header> phdr) {
{
u64 base_size = 0; u64 base_size = 0;
for (u16 i = 0; i < ehdr.e_phnum; i++) for (u16 i = 0; i < ehdr.e_phnum; i++) {
{ if (phdr[i].p_memsz != 0 && (phdr[i].p_type == PT_LOAD || phdr[i].p_type == PT_SCE_RELRO)) {
if (phdr[i].p_memsz != 0 && (phdr[i].p_type == PT_LOAD || phdr[i].p_type == PT_SCE_RELRO))
{
u64 last_addr = phdr[i].p_vaddr + get_aligned_size(phdr[i]); u64 last_addr = phdr[i].p_vaddr + get_aligned_size(phdr[i]);
if (last_addr > base_size) if (last_addr > base_size) {
{
base_size = last_addr; base_size = last_addr;
} }
} }
@ -36,23 +32,16 @@ static u64 calculate_base_size(const elf_header& ehdr, std::span<const elf_progr
return base_size; return base_size;
} }
static std::string encodeId(u64 nVal) static std::string encodeId(u64 nVal) {
{
std::string enc; std::string enc;
const char pCodes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; const char pCodes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
if (nVal < 0x40u) if (nVal < 0x40u) {
{
enc += pCodes[nVal]; enc += pCodes[nVal];
} } else {
else if (nVal < 0x1000u) {
{
if (nVal < 0x1000u)
{
enc += pCodes[static_cast<u16>(nVal >> 6u) & 0x3fu]; enc += pCodes[static_cast<u16>(nVal >> 6u) & 0x3fu];
enc += pCodes[nVal & 0x3fu]; enc += pCodes[nVal & 0x3fu];
} } else {
else
{
enc += pCodes[static_cast<u16>(nVal >> 12u) & 0x3fu]; enc += pCodes[static_cast<u16>(nVal >> 12u) & 0x3fu];
enc += pCodes[static_cast<u16>(nVal >> 6u) & 0x3fu]; enc += pCodes[static_cast<u16>(nVal >> 6u) & 0x3fu];
enc += pCodes[nVal & 0x3fu]; enc += pCodes[nVal & 0x3fu];
@ -65,8 +54,7 @@ Linker::Linker() = default;
Linker::~Linker() = default; Linker::~Linker() = default;
Module* Linker::LoadModule(const std::string& elf_name) Module* Linker::LoadModule(const std::string& elf_name) {
{
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
auto& m = m_modules.emplace_back(); auto& m = m_modules.emplace_back();
@ -86,8 +74,7 @@ Module* Linker::LoadModule(const std::string& elf_name)
return &m; return &m;
} }
Module* Linker::FindModule(/*u32 id*/) Module* Linker::FindModule(/*u32 id*/) {
{
// TODO atm we only have 1 module so we don't need to iterate on vector // TODO atm we only have 1 module so we don't need to iterate on vector
if (m_modules.empty()) [[unlikely]] { if (m_modules.empty()) [[unlikely]] {
return nullptr; return nullptr;
@ -95,7 +82,7 @@ Module* Linker::FindModule(/*u32 id*/)
return &m_modules[0]; return &m_modules[0];
} }
struct TLSPattern{ struct TLSPattern {
uint8_t pattern[5]; uint8_t pattern[5];
uint8_t pattern_size; uint8_t pattern_size;
uint8_t imm_size; uint8_t imm_size;
@ -103,9 +90,15 @@ struct TLSPattern{
}; };
constexpr TLSPattern tls_patterns[] = { constexpr TLSPattern tls_patterns[] = {
{{0x64, 0x48, 0xA1}, 3, 8, 0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm] {{0x64, 0x48, 0xA1},
3,
8,
0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm]
{{0x64, 0x48, 0x8B, 0x4, 0x25}, 5, 4, 0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0] {{0x64, 0x48, 0x8B, 0x4, 0x25},
5,
4,
0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0]
{{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx {{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx
{{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx {{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx
{{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx {{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx
@ -115,12 +108,12 @@ constexpr TLSPattern tls_patterns[] = {
{{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi {{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi
{{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8 {{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8
{{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9 {{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9
{{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10},// r10 {{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10}, // r10
{{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11},// r11 {{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11}, // r11
{{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12},// r12 {{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12}, // r12
{{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13},// r13 {{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13}, // r13
{{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14},// r14 {{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14}, // r14
{{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15},// r15 {{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15}, // r15
}; };
void PatchTLS(u64 segment_addr, u64 segment_size) { void PatchTLS(u64 segment_addr, u64 segment_size) {
@ -133,9 +126,13 @@ void PatchTLS(u64 segment_addr, u64 segment_size) {
if (remaining_size >= total_size) { if (remaining_size >= total_size) {
if (memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) == 0) { if (memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) == 0) {
if (tls_pattern.imm_size == 4) if (tls_pattern.imm_size == 4)
printf("PATTERN32 FOUND @ %p, reg: %d offset: %X\n", code, tls_pattern.target_reg, *(uint32_t*)(code + tls_pattern.pattern_size)); printf("PATTERN32 FOUND @ %p, reg: %d offset: %X\n", code,
tls_pattern.target_reg,
*(uint32_t*)(code + tls_pattern.pattern_size));
else else
printf("PATTERN64 FOUND @ %p, reg: %d offset: %lX\n", code, tls_pattern.target_reg, *(uint64_t*)(code + tls_pattern.pattern_size)); printf("PATTERN64 FOUND @ %p, reg: %d offset: %lX\n", code,
tls_pattern.target_reg,
*(uint64_t*)(code + tls_pattern.pattern_size));
code[0] = 0xcd; code[0] = 0xcd;
code[1] = 0x80 + tls_pattern.target_reg; code[1] = 0x80 + tls_pattern.target_reg;
code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4); code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4);
@ -151,33 +148,34 @@ void PatchTLS(u64 segment_addr, u64 segment_size) {
} }
void Linker::LoadModuleToMemory(Module* m) { void Linker::LoadModuleToMemory(Module* m) {
//get elf header, program header // get elf header, program header
const auto elf_header = m->elf.GetElfHeader(); const auto elf_header = m->elf.GetElfHeader();
const auto elf_pheader = m->elf.GetProgramHeader(); const auto elf_pheader = m->elf.GetProgramHeader();
u64 base_size = calculate_base_size(elf_header, elf_pheader); u64 base_size = calculate_base_size(elf_header, elf_pheader);
m->aligned_base_size = (base_size & ~(static_cast<u64>(0x1000) - 1)) + 0x1000;//align base size to 0x1000 block size (TODO is that the default block size or it can be changed? m->aligned_base_size = (base_size & ~(static_cast<u64>(0x1000) - 1)) +
0x1000; // align base size to 0x1000 block size (TODO is that the default
// block size or it can be changed?
m->base_virtual_addr = VirtualMemory::memory_alloc(g_load_addr, m->aligned_base_size, VirtualMemory::MemoryMode::ExecuteReadWrite); m->base_virtual_addr = VirtualMemory::memory_alloc(g_load_addr, m->aligned_base_size,
VirtualMemory::MemoryMode::ExecuteReadWrite);
LOG_INFO_IF(debug_loader, "====Load Module to Memory ========\n"); LOG_INFO_IF(debug_loader, "====Load Module to Memory ========\n");
LOG_INFO_IF(debug_loader, "base_virtual_addr ......: {:#018x}\n", m->base_virtual_addr); LOG_INFO_IF(debug_loader, "base_virtual_addr ......: {:#018x}\n", m->base_virtual_addr);
LOG_INFO_IF(debug_loader, "base_size ..............: {:#018x}\n", base_size); LOG_INFO_IF(debug_loader, "base_size ..............: {:#018x}\n", base_size);
LOG_INFO_IF(debug_loader, "aligned_base_size ......: {:#018x}\n", m->aligned_base_size); LOG_INFO_IF(debug_loader, "aligned_base_size ......: {:#018x}\n", m->aligned_base_size);
for (u16 i = 0; i < elf_header.e_phnum; i++) for (u16 i = 0; i < elf_header.e_phnum; i++) {
{ switch (elf_pheader[i].p_type) {
switch (elf_pheader[i].p_type)
{
case PT_LOAD: case PT_LOAD:
case PT_SCE_RELRO: case PT_SCE_RELRO:
if (elf_pheader[i].p_memsz != 0) if (elf_pheader[i].p_memsz != 0) {
{
u64 segment_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr; u64 segment_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr;
u64 segment_file_size = elf_pheader[i].p_filesz; u64 segment_file_size = elf_pheader[i].p_filesz;
u64 segment_memory_size = get_aligned_size(elf_pheader[i]); u64 segment_memory_size = get_aligned_size(elf_pheader[i]);
auto segment_mode = m->elf.ElfPheaderFlagsStr(elf_pheader[i].p_flags); auto segment_mode = m->elf.ElfPheaderFlagsStr(elf_pheader[i].p_flags);
LOG_INFO_IF(debug_loader, "program header = [{}] type = {}\n",i,m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); LOG_INFO_IF(debug_loader, "program header = [{}] type = {}\n", i,
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
LOG_INFO_IF(debug_loader, "segment_addr ..........: {:#018x}\n", segment_addr); LOG_INFO_IF(debug_loader, "segment_addr ..........: {:#018x}\n", segment_addr);
LOG_INFO_IF(debug_loader, "segment_file_size .....: {}\n", segment_file_size); LOG_INFO_IF(debug_loader, "segment_file_size .....: {}\n", segment_file_size);
LOG_INFO_IF(debug_loader, "segment_memory_size ...: {}\n", segment_memory_size); LOG_INFO_IF(debug_loader, "segment_memory_size ...: {}\n", segment_memory_size);
@ -188,32 +186,29 @@ void Linker::LoadModuleToMemory(Module* m) {
if (elf_pheader[i].p_flags & PF_EXEC) { if (elf_pheader[i].p_flags & PF_EXEC) {
PatchTLS(segment_addr, segment_file_size); PatchTLS(segment_addr, segment_file_size);
} }
} } else {
else LOG_ERROR_IF(debug_loader, "p_memsz==0 in type {}\n",
{ m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
LOG_ERROR_IF(debug_loader, "p_memsz==0 in type {}\n", m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
} }
break; break;
case PT_DYNAMIC: case PT_DYNAMIC:
if (elf_pheader[i].p_filesz != 0) if (elf_pheader[i].p_filesz != 0) {
{
m->m_dynamic.resize(elf_pheader[i].p_filesz); m->m_dynamic.resize(elf_pheader[i].p_filesz);
m->elf.LoadSegment(reinterpret_cast<u64>(m->m_dynamic.data()), elf_pheader[i].p_offset, elf_pheader[i].p_filesz); m->elf.LoadSegment(reinterpret_cast<u64>(m->m_dynamic.data()),
} elf_pheader[i].p_offset, elf_pheader[i].p_filesz);
else } else {
{ LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n",
LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n", m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
} }
break; break;
case PT_SCE_DYNLIBDATA: case PT_SCE_DYNLIBDATA:
if (elf_pheader[i].p_filesz != 0) if (elf_pheader[i].p_filesz != 0) {
{
m->m_dynamic_data.resize(elf_pheader[i].p_filesz); m->m_dynamic_data.resize(elf_pheader[i].p_filesz);
m->elf.LoadSegment(reinterpret_cast<u64>(m->m_dynamic_data.data()), elf_pheader[i].p_offset, elf_pheader[i].p_filesz); m->elf.LoadSegment(reinterpret_cast<u64>(m->m_dynamic_data.data()),
} elf_pheader[i].p_offset, elf_pheader[i].p_filesz);
else } else {
{ LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n",
LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n", m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
} }
break; break;
case PT_TLS: case PT_TLS:
@ -223,34 +218,37 @@ void Linker::LoadModuleToMemory(Module* m) {
LOG_INFO_IF(debug_loader, "tls image size ={}\n", m->tls.image_size); LOG_INFO_IF(debug_loader, "tls image size ={}\n", m->tls.image_size);
break; break;
default: default:
LOG_ERROR_IF(debug_loader, "Unimplemented type {}\n", m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); LOG_ERROR_IF(debug_loader, "Unimplemented type {}\n",
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
} }
} }
LOG_INFO_IF(debug_loader, "program entry addr ..........: {:#018x}\n", m->elf.GetElfEntry() + m->base_virtual_addr); LOG_INFO_IF(debug_loader, "program entry addr ..........: {:#018x}\n",
m->elf.GetElfEntry() + m->base_virtual_addr);
} }
void Linker::LoadDynamicInfo(Module* m) void Linker::LoadDynamicInfo(Module* m) {
{ for (const auto* dyn = reinterpret_cast<elf_dynamic*>(m->m_dynamic.data());
for (const auto* dyn = reinterpret_cast<elf_dynamic*>(m->m_dynamic.data()); dyn->d_tag != DT_NULL; dyn++) dyn->d_tag != DT_NULL; dyn++) {
{ switch (dyn->d_tag) {
switch (dyn->d_tag) case DT_SCE_HASH: // Offset of the hash table.
{ m->dynamic_info.hash_table =
case DT_SCE_HASH: //Offset of the hash table. reinterpret_cast<void*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr);
m->dynamic_info.hash_table = reinterpret_cast<void*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr);
break; break;
case DT_SCE_HASHSZ: //Size of the hash table case DT_SCE_HASHSZ: // Size of the hash table
m->dynamic_info.hash_table_size = dyn->d_un.d_val; m->dynamic_info.hash_table_size = dyn->d_un.d_val;
break; break;
case DT_SCE_STRTAB://Offset of the string table. case DT_SCE_STRTAB: // Offset of the string table.
m->dynamic_info.str_table = reinterpret_cast<char*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr); m->dynamic_info.str_table =
reinterpret_cast<char*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr);
break; break;
case DT_SCE_STRSZ: //Size of the string table. case DT_SCE_STRSZ: // Size of the string table.
m->dynamic_info.str_table_size = dyn->d_un.d_val; m->dynamic_info.str_table_size = dyn->d_un.d_val;
break; break;
case DT_SCE_SYMTAB://Offset of the symbol table. case DT_SCE_SYMTAB: // Offset of the symbol table.
m->dynamic_info.symbol_table = reinterpret_cast<elf_symbol*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr); m->dynamic_info.symbol_table =
reinterpret_cast<elf_symbol*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr);
break; break;
case DT_SCE_SYMTABSZ://Size of the symbol table. case DT_SCE_SYMTABSZ: // Size of the symbol table.
m->dynamic_info.symbol_table_total_size = dyn->d_un.d_val; m->dynamic_info.symbol_table_total_size = dyn->d_un.d_val;
break; break;
case DT_INIT: case DT_INIT:
@ -259,56 +257,59 @@ void Linker::LoadDynamicInfo(Module* m)
case DT_FINI: case DT_FINI:
m->dynamic_info.fini_virtual_addr = dyn->d_un.d_ptr; m->dynamic_info.fini_virtual_addr = dyn->d_un.d_ptr;
break; break;
case DT_SCE_PLTGOT: //Offset of the global offset table. case DT_SCE_PLTGOT: // Offset of the global offset table.
m->dynamic_info.pltgot_virtual_addr = dyn->d_un.d_ptr; m->dynamic_info.pltgot_virtual_addr = dyn->d_un.d_ptr;
break; break;
case DT_SCE_JMPREL: //Offset of the table containing jump slots. case DT_SCE_JMPREL: // Offset of the table containing jump slots.
m->dynamic_info.jmp_relocation_table = reinterpret_cast<elf_relocation*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr); m->dynamic_info.jmp_relocation_table =
reinterpret_cast<elf_relocation*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr);
break; break;
case DT_SCE_PLTRELSZ: //Size of the global offset table. case DT_SCE_PLTRELSZ: // Size of the global offset table.
m->dynamic_info.jmp_relocation_table_size = dyn->d_un.d_val; m->dynamic_info.jmp_relocation_table_size = dyn->d_un.d_val;
break; break;
case DT_SCE_PLTREL: //The type of relocations in the relocation table. Should be DT_RELA case DT_SCE_PLTREL: // The type of relocations in the relocation table. Should be DT_RELA
m->dynamic_info.jmp_relocation_type = dyn->d_un.d_val; m->dynamic_info.jmp_relocation_type = dyn->d_un.d_val;
if (m->dynamic_info.jmp_relocation_type != DT_RELA) if (m->dynamic_info.jmp_relocation_type != DT_RELA) {
{
LOG_WARN_IF(debug_loader, "DT_SCE_PLTREL is NOT DT_RELA should check!"); LOG_WARN_IF(debug_loader, "DT_SCE_PLTREL is NOT DT_RELA should check!");
} }
break; break;
case DT_SCE_RELA: //Offset of the relocation table. case DT_SCE_RELA: // Offset of the relocation table.
m->dynamic_info.relocation_table = reinterpret_cast<elf_relocation*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr); m->dynamic_info.relocation_table =
reinterpret_cast<elf_relocation*>(m->m_dynamic_data.data() + dyn->d_un.d_ptr);
break; break;
case DT_SCE_RELASZ: //Size of the relocation table. case DT_SCE_RELASZ: // Size of the relocation table.
m->dynamic_info.relocation_table_size = dyn->d_un.d_val; m->dynamic_info.relocation_table_size = dyn->d_un.d_val;
break; break;
case DT_SCE_RELAENT : //The size of relocation table entries. case DT_SCE_RELAENT: // The size of relocation table entries.
m->dynamic_info.relocation_table_entries_size = dyn->d_un.d_val; m->dynamic_info.relocation_table_entries_size = dyn->d_un.d_val;
if (m->dynamic_info.relocation_table_entries_size != 0x18) //this value should always be 0x18 if (m->dynamic_info.relocation_table_entries_size !=
0x18) // this value should always be 0x18
{ {
LOG_WARN_IF(debug_loader, "DT_SCE_RELAENT is NOT 0x18 should check!"); LOG_WARN_IF(debug_loader, "DT_SCE_RELAENT is NOT 0x18 should check!");
} }
break; break;
case DT_INIT_ARRAY:// Address of the array of pointers to initialization functions case DT_INIT_ARRAY: // Address of the array of pointers to initialization functions
m->dynamic_info.init_array_virtual_addr = dyn->d_un.d_ptr; m->dynamic_info.init_array_virtual_addr = dyn->d_un.d_ptr;
break; break;
case DT_FINI_ARRAY: // Address of the array of pointers to termination functions case DT_FINI_ARRAY: // Address of the array of pointers to termination functions
m->dynamic_info.fini_array_virtual_addr = dyn->d_un.d_ptr; m->dynamic_info.fini_array_virtual_addr = dyn->d_un.d_ptr;
break; break;
case DT_INIT_ARRAYSZ://Size in bytes of the array of initialization functions case DT_INIT_ARRAYSZ: // Size in bytes of the array of initialization functions
m->dynamic_info.init_array_size = dyn->d_un.d_val; m->dynamic_info.init_array_size = dyn->d_un.d_val;
break; break;
case DT_FINI_ARRAYSZ://Size in bytes of the array of terminationfunctions case DT_FINI_ARRAYSZ: // Size in bytes of the array of terminationfunctions
m->dynamic_info.fini_array_size = dyn->d_un.d_val; m->dynamic_info.fini_array_size = dyn->d_un.d_val;
break; break;
case DT_PREINIT_ARRAY://Address of the array of pointers to pre - initialization functions case DT_PREINIT_ARRAY: // Address of the array of pointers to pre - initialization functions
m->dynamic_info.preinit_array_virtual_addr = dyn->d_un.d_ptr; m->dynamic_info.preinit_array_virtual_addr = dyn->d_un.d_ptr;
break; break;
case DT_PREINIT_ARRAYSZ://Size in bytes of the array of pre - initialization functions case DT_PREINIT_ARRAYSZ: // Size in bytes of the array of pre - initialization functions
m->dynamic_info.preinit_array_size = dyn->d_un.d_val; m->dynamic_info.preinit_array_size = dyn->d_un.d_val;
break; break;
case DT_SCE_SYMENT: //The size of symbol table entries case DT_SCE_SYMENT: // The size of symbol table entries
m->dynamic_info.symbol_table_entries_size = dyn->d_un.d_val; m->dynamic_info.symbol_table_entries_size = dyn->d_un.d_val;
if (m->dynamic_info.symbol_table_entries_size != 0x18) //this value should always be 0x18 if (m->dynamic_info.symbol_table_entries_size !=
0x18) // this value should always be 0x18
{ {
LOG_WARN_IF(debug_loader, "DT_SCE_SYMENT is NOT 0x18 should check!"); LOG_WARN_IF(debug_loader, "DT_SCE_SYMENT is NOT 0x18 should check!");
} }
@ -321,99 +322,93 @@ void Linker::LoadDynamicInfo(Module* m)
break; break;
case DT_FLAGS: case DT_FLAGS:
m->dynamic_info.flags = dyn->d_un.d_val; m->dynamic_info.flags = dyn->d_un.d_val;
if (m->dynamic_info.flags != 0x04) //this value should always be DF_TEXTREL (0x04) if (m->dynamic_info.flags != 0x04) // this value should always be DF_TEXTREL (0x04)
{ {
LOG_WARN_IF(debug_loader, "DT_FLAGS is NOT 0x04 should check!"); LOG_WARN_IF(debug_loader, "DT_FLAGS is NOT 0x04 should check!");
} }
break; break;
case DT_NEEDED://Offset of the library string in the string table to be linked in. case DT_NEEDED: // Offset of the library string in the string table to be linked in.
if (m->dynamic_info.str_table != nullptr)//in theory this should already be filled from about just make a test case if (m->dynamic_info.str_table !=
nullptr) // in theory this should already be filled from about just make a test case
{ {
m->dynamic_info.needed.push_back(m->dynamic_info.str_table + dyn->d_un.d_val); m->dynamic_info.needed.push_back(m->dynamic_info.str_table + dyn->d_un.d_val);
} } else {
else
{
LOG_ERROR_IF(debug_loader, "DT_NEEDED str table is not loaded should check!"); LOG_ERROR_IF(debug_loader, "DT_NEEDED str table is not loaded should check!");
} }
break; break;
case DT_SCE_NEEDED_MODULE: case DT_SCE_NEEDED_MODULE: {
{
ModuleInfo info{}; ModuleInfo info{};
info.value = dyn->d_un.d_val; info.value = dyn->d_un.d_val;
info.name = m->dynamic_info.str_table + info.name_offset; info.name = m->dynamic_info.str_table + info.name_offset;
info.enc_id = encodeId(info.id); info.enc_id = encodeId(info.id);
m->dynamic_info.import_modules.push_back(info); m->dynamic_info.import_modules.push_back(info);
} } break;
break; case DT_SCE_IMPORT_LIB: {
case DT_SCE_IMPORT_LIB:
{
LibraryInfo info{}; LibraryInfo info{};
info.value = dyn->d_un.d_val; info.value = dyn->d_un.d_val;
info.name = m->dynamic_info.str_table + info.name_offset; info.name = m->dynamic_info.str_table + info.name_offset;
info.enc_id = encodeId(info.id); info.enc_id = encodeId(info.id);
m->dynamic_info.import_libs.push_back(info); m->dynamic_info.import_libs.push_back(info);
} } break;
break;
case DT_SCE_FINGERPRINT: case DT_SCE_FINGERPRINT:
//The fingerprint is a 24 byte (0x18) size buffer that contains a unique identifier for the given app. // The fingerprint is a 24 byte (0x18) size buffer that contains a unique identifier for
//How exactly this is generated isn't known, however it is not necessary to have a valid fingerprint. // the given app. How exactly this is generated isn't known, however it is not necessary
//While an invalid fingerprint will cause a warning to be printed to the kernel log, the ELF will still load and run. // to have a valid fingerprint. While an invalid fingerprint will cause a warning to be
LOG_INFO_IF(debug_loader, "unsupported DT_SCE_FINGERPRINT value = ..........: {:#018x}\n", dyn->d_un.d_val); // printed to the kernel log, the ELF will still load and run.
LOG_INFO_IF(debug_loader,
"unsupported DT_SCE_FINGERPRINT value = ..........: {:#018x}\n",
dyn->d_un.d_val);
break; break;
case DT_SCE_IMPORT_LIB_ATTR: case DT_SCE_IMPORT_LIB_ATTR:
//The upper 32-bits should contain the module index multiplied by 0x10000. The lower 32-bits should be a constant 0x9. // The upper 32-bits should contain the module index multiplied by 0x10000. The lower
LOG_INFO_IF(debug_loader, "unsupported DT_SCE_IMPORT_LIB_ATTR value = ......: {:#018x}\n", dyn->d_un.d_val); // 32-bits should be a constant 0x9.
LOG_INFO_IF(debug_loader,
"unsupported DT_SCE_IMPORT_LIB_ATTR value = ......: {:#018x}\n",
dyn->d_un.d_val);
break; break;
case DT_SCE_ORIGINAL_FILENAME: case DT_SCE_ORIGINAL_FILENAME:
m->dynamic_info.filename = m->dynamic_info.str_table + dyn->d_un.d_val; m->dynamic_info.filename = m->dynamic_info.str_table + dyn->d_un.d_val;
break; break;
case DT_SCE_MODULE_INFO://probably only useable in shared modules case DT_SCE_MODULE_INFO: // probably only useable in shared modules
{ {
ModuleInfo info{}; ModuleInfo info{};
info.value = dyn->d_un.d_val; info.value = dyn->d_un.d_val;
info.name = m->dynamic_info.str_table + info.name_offset; info.name = m->dynamic_info.str_table + info.name_offset;
info.enc_id = encodeId(info.id); info.enc_id = encodeId(info.id);
m->dynamic_info.export_modules.push_back(info); m->dynamic_info.export_modules.push_back(info);
} } break;
break;
case DT_SCE_MODULE_ATTR: case DT_SCE_MODULE_ATTR:
//TODO? // TODO?
LOG_INFO_IF(debug_loader, "unsupported DT_SCE_MODULE_ATTR value = ..........: {:#018x}\n", dyn->d_un.d_val); LOG_INFO_IF(debug_loader,
"unsupported DT_SCE_MODULE_ATTR value = ..........: {:#018x}\n",
dyn->d_un.d_val);
break; break;
case DT_SCE_EXPORT_LIB: case DT_SCE_EXPORT_LIB: {
{
LibraryInfo info{}; LibraryInfo info{};
info.value = dyn->d_un.d_val; info.value = dyn->d_un.d_val;
info.name = m->dynamic_info.str_table + info.name_offset; info.name = m->dynamic_info.str_table + info.name_offset;
info.enc_id = encodeId(info.id); info.enc_id = encodeId(info.id);
m->dynamic_info.export_libs.push_back(info); m->dynamic_info.export_libs.push_back(info);
} } break;
break;
default: default:
LOG_INFO_IF(debug_loader, "unsupported dynamic tag ..........: {:#018x}\n", dyn->d_tag); LOG_INFO_IF(debug_loader, "unsupported dynamic tag ..........: {:#018x}\n", dyn->d_tag);
} }
} }
} }
const ModuleInfo* Linker::FindModule(const Module& m, const std::string& id) const ModuleInfo* Linker::FindModule(const Module& m, const std::string& id) {
{
const auto& import_modules = m.dynamic_info.import_modules; const auto& import_modules = m.dynamic_info.import_modules;
int index = 0; int index = 0;
for (const auto& mod : import_modules) for (const auto& mod : import_modules) {
{ if (mod.enc_id.compare(id) == 0) {
if (mod.enc_id.compare(id) == 0)
{
return &import_modules.at(index); return &import_modules.at(index);
} }
index++; index++;
} }
const auto& export_modules = m.dynamic_info.export_modules; const auto& export_modules = m.dynamic_info.export_modules;
index = 0; index = 0;
for (const auto& mod : export_modules) for (const auto& mod : export_modules) {
{ if (mod.enc_id.compare(id) == 0) {
if (mod.enc_id.compare(id) == 0)
{
return &export_modules.at(index); return &export_modules.at(index);
} }
index++; index++;
@ -421,24 +416,19 @@ const ModuleInfo* Linker::FindModule(const Module& m, const std::string& id)
return nullptr; return nullptr;
} }
const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) {
{
const auto& import_libs = m.dynamic_info.import_libs; const auto& import_libs = m.dynamic_info.import_libs;
int index = 0; int index = 0;
for (const auto& lib : import_libs) for (const auto& lib : import_libs) {
{ if (lib.enc_id.compare(id) == 0) {
if (lib.enc_id.compare(id) == 0)
{
return &import_libs.at(index); return &import_libs.at(index);
} }
index++; index++;
} }
const auto& export_libs = m.dynamic_info.export_libs; const auto& export_libs = m.dynamic_info.export_libs;
index = 0; index = 0;
for (const auto& lib : export_libs) for (const auto& lib : export_libs) {
{ if (lib.enc_id.compare(id) == 0) {
if (lib.enc_id.compare(id) == 0)
{
return &export_libs.at(index); return &export_libs.at(index);
} }
index++; index++;
@ -446,67 +436,63 @@ const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id)
return nullptr; return nullptr;
} }
void Linker::LoadSymbols(Module* m) void Linker::LoadSymbols(Module* m) {
{ if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr ||
if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr || m->dynamic_info.symbol_table_total_size==0) m->dynamic_info.symbol_table_total_size == 0) {
{
LOG_INFO_IF(debug_loader, "Symbol table not found!\n"); LOG_INFO_IF(debug_loader, "Symbol table not found!\n");
return; return;
} }
for (auto* sym = m->dynamic_info.symbol_table; for (auto* sym = m->dynamic_info.symbol_table;
reinterpret_cast<uint8_t*>(sym) < reinterpret_cast<uint8_t*>(m->dynamic_info.symbol_table) + m->dynamic_info.symbol_table_total_size; reinterpret_cast<uint8_t*>(sym) <
sym++) reinterpret_cast<uint8_t*>(m->dynamic_info.symbol_table) +
{ m->dynamic_info.symbol_table_total_size;
sym++) {
std::string id = std::string(m->dynamic_info.str_table + sym->st_name); std::string id = std::string(m->dynamic_info.str_table + sym->st_name);
const auto ids = Common::SplitString(id, '#'); const auto ids = Common::SplitString(id, '#');
if (ids.size() == 3)//symbols are 3 parts name , library , module if (ids.size() == 3) // symbols are 3 parts name , library , module
{ {
const auto* library = FindLibrary(*m, ids.at(1)); const auto* library = FindLibrary(*m, ids.at(1));
const auto* module = FindModule(*m, ids.at(2)); const auto* module = FindModule(*m, ids.at(2));
auto bind = sym->GetBind(); auto bind = sym->GetBind();
auto type = sym->GetType(); auto type = sym->GetType();
auto visibility = sym->GetVisibility(); auto visibility = sym->GetVisibility();
if (library != nullptr || module != nullptr) if (library != nullptr || module != nullptr) {
{ switch (bind) {
switch (bind)
{
case STB_GLOBAL: case STB_GLOBAL:
case STB_WEAK: case STB_WEAK:
break; break;
default: default:
LOG_INFO_IF(debug_loader, "Unsupported bind {} for name symbol {} \n", bind,ids.at(0)); LOG_INFO_IF(debug_loader, "Unsupported bind {} for name symbol {} \n", bind,
ids.at(0));
continue; continue;
} }
switch (type) switch (type) {
{
case STT_OBJECT: case STT_OBJECT:
case STT_FUN: case STT_FUN:
break; break;
default: default:
LOG_INFO_IF(debug_loader, "Unsupported type {} for name symbol {} \n", type, ids.at(0)); LOG_INFO_IF(debug_loader, "Unsupported type {} for name symbol {} \n", type,
ids.at(0));
continue; continue;
} }
switch (visibility) switch (visibility) {
{
case STV_DEFAULT: case STV_DEFAULT:
break; break;
default: default:
LOG_INFO_IF(debug_loader, "Unsupported visibility {} for name symbol {} \n", visibility, ids.at(0)); LOG_INFO_IF(debug_loader, "Unsupported visibility {} for name symbol {} \n",
visibility, ids.at(0));
continue; continue;
} }
//if st_value!=0 then it's export symbol // if st_value!=0 then it's export symbol
bool is_sym_export = sym->st_value != 0; bool is_sym_export = sym->st_value != 0;
std::string nidName = ""; std::string nidName = "";
auto aeronid = AeroLib::FindByNid(ids.at(0).c_str()); auto aeronid = AeroLib::FindByNid(ids.at(0).c_str());
if (aeronid != nullptr) if (aeronid != nullptr) {
{
nidName = aeronid->name; nidName = aeronid->name;
} } else {
else
{
nidName = "UNK"; nidName = "UNK";
} }
@ -520,17 +506,16 @@ void Linker::LoadSymbols(Module* m)
sym_r.module_version_minor = module->version_minor; sym_r.module_version_minor = module->version_minor;
sym_r.type = type; sym_r.type = type;
if (is_sym_export) if (is_sym_export) {
{
m->export_sym.AddSymbol(sym_r, sym->st_value + m->base_virtual_addr); m->export_sym.AddSymbol(sym_r, sym->st_value + m->base_virtual_addr);
} } else {
else m->import_sym.AddSymbol(sym_r, 0);
{
m->import_sym.AddSymbol(sym_r,0);
} }
LOG_INFO_IF(
LOG_INFO_IF(debug_loader, "name {} function {} library {} module {} bind {} type {} visibility {}\n", ids.at(0),nidName,library->name, module->name, bind, type, visibility); debug_loader,
"name {} function {} library {} module {} bind {} type {} visibility {}\n",
ids.at(0), nidName, library->name, module->name, bind, type, visibility);
} }
} }
} }
@ -553,7 +538,8 @@ static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) {
case R_X86_64_RELATIVE: case R_X86_64_RELATIVE:
if (symbol != 0) // should be always zero if (symbol != 0) // should be always zero
{ {
//LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, symbol);//found it openorbis but i am not sure it worth logging // LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type,
// symbol);//found it openorbis but i am not sure it worth logging
} }
rel_value = rel_base_virtual_addr + addend; rel_value = rel_base_virtual_addr + addend;
rel_isResolved = true; rel_isResolved = true;
@ -568,9 +554,14 @@ static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) {
u64 symbol_vitrual_addr = 0; u64 symbol_vitrual_addr = 0;
Loader::SymbolRecord symrec{}; Loader::SymbolRecord symrec{};
switch (sym_type) { switch (sym_type) {
case STT_FUN: rel_sym_type = 2; break; case STT_FUN:
case STT_OBJECT: rel_sym_type = 1; break; rel_sym_type = 2;
default: LOG_INFO_IF(debug_loader, "unknown symbol type {}\n", sym_type); break;
case STT_OBJECT:
rel_sym_type = 1;
break;
default:
LOG_INFO_IF(debug_loader, "unknown symbol type {}\n", sym_type);
} }
if (sym_visibility != 0) // should be zero log if else if (sym_visibility != 0) // should be zero log if else
{ {
@ -589,40 +580,48 @@ static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) {
} }
rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0); rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0);
if (!rel_isResolved) { if (!rel_isResolved) {
LOG_INFO_IF(debug_loader, "R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : {:#010x}\n", sym_type, symbol); LOG_INFO_IF(debug_loader,
"R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : "
"{:#010x}\n",
sym_type, symbol);
} }
break; break;
default: LOG_INFO_IF(debug_loader, "UNK bind {}\n", sym_bind); default:
LOG_INFO_IF(debug_loader, "UNK bind {}\n", sym_bind);
} }
} break; } break;
default: LOG_INFO_IF(debug_loader, "UNK type {:#010x} rel symbol : {:#010x}\n", type, symbol); default:
LOG_INFO_IF(debug_loader, "UNK type {:#010x} rel symbol : {:#010x}\n", type, symbol);
} }
if (rel_isResolved) { if (rel_isResolved) {
VirtualMemory::memory_patch(rel_virtual_addr, rel_value); VirtualMemory::memory_patch(rel_virtual_addr, rel_value);
} } else {
else LOG_INFO_IF(debug_loader, "function not patched! {}\n", rel_name);
{
LOG_INFO_IF(debug_loader, "function not patched! {}\n",rel_name);
} }
} }
void Linker::Relocate(Module* m) void Linker::Relocate(Module* m) {
{
u32 idx = 0; u32 idx = 0;
for (auto* rel = m->dynamic_info.relocation_table; reinterpret_cast<u08*>(rel) < reinterpret_cast<u08*>(m->dynamic_info.relocation_table) + m->dynamic_info.relocation_table_size; rel++, idx++) for (auto* rel = m->dynamic_info.relocation_table;
{ reinterpret_cast<u08*>(rel) < reinterpret_cast<u08*>(m->dynamic_info.relocation_table) +
m->dynamic_info.relocation_table_size;
rel++, idx++) {
relocate(idx, rel, m, false); relocate(idx, rel, m, false);
} }
idx = 0; idx = 0;
for (auto* rel = m->dynamic_info.jmp_relocation_table; reinterpret_cast<u08*>(rel) < reinterpret_cast<u08*>(m->dynamic_info.jmp_relocation_table) + m->dynamic_info.jmp_relocation_table_size; rel++, idx++) for (auto* rel = m->dynamic_info.jmp_relocation_table;
{ reinterpret_cast<u08*>(rel) <
reinterpret_cast<u08*>(m->dynamic_info.jmp_relocation_table) +
m->dynamic_info.jmp_relocation_table_size;
rel++, idx++) {
relocate(idx, rel, m, true); relocate(idx, rel, m, true);
} }
} }
void Linker::Resolve(const std::string& name, int Symtype, Module* m, Loader::SymbolRecord* return_info) { void Linker::Resolve(const std::string& name, int Symtype, Module* m,
Loader::SymbolRecord* return_info) {
const auto ids = Common::SplitString(name, '#'); const auto ids = Common::SplitString(name, '#');
if (ids.size() == 3) // symbols are 3 parts name , library , module if (ids.size() == 3) // symbols are 3 parts name , library , module
{ {
@ -653,19 +652,15 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, Loader::Sy
return_info->virtual_address = AeroLib::GetStub(sr.name.c_str()); return_info->virtual_address = AeroLib::GetStub(sr.name.c_str());
return_info->name = "Unknown !!!"; return_info->name = "Unknown !!!";
} }
LOG_ERROR_IF(debug_loader, "Linker: Stub resolved {} as {} (lib: {}, mod: {}) \n", sr.name, return_info->name, library->name, module->name); LOG_ERROR_IF(debug_loader, "Linker: Stub resolved {} as {} (lib: {}, mod: {}) \n",
sr.name, return_info->name, library->name, module->name);
} }
} } else {
else
{
//__debugbreak();//den tha prepei na ftasoume edo //__debugbreak();//den tha prepei na ftasoume edo
} }
} } else {
else
{
//__debugbreak();//oute edo mallon //__debugbreak();//oute edo mallon
} }
} }
using exit_func_t = PS4_SYSV_ABI void (*)(); using exit_func_t = PS4_SYSV_ABI void (*)();
@ -676,10 +671,10 @@ static PS4_SYSV_ABI void ProgramExitFunc() {
} }
static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) { static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) {
//reinterpret_cast<entry_func_t>(addr)(params, exit_func); // can't be used, stack has to have a specific layout // reinterpret_cast<entry_func_t>(addr)(params, exit_func); // can't be used, stack has to have
// a specific layout
asm volatile ( asm volatile("andq $-16, %%rsp\n" // Align to 16 bytes
"andq $-16, %%rsp\n"// Align to 16 bytes
"subq $8, %%rsp\n" // videoout_basic expects the stack to be misaligned "subq $8, %%rsp\n" // videoout_basic expects the stack to be misaligned
// Kernel also pushes some more things here during process init // Kernel also pushes some more things here during process init
@ -695,15 +690,14 @@ static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func)
// there's no coming back // there's no coming back
: :
: "r"(addr), "r"(params), "r"(exit_func) : "r"(addr), "r"(params), "r"(exit_func)
: "rax", "rsi", "rdi", "rsp", "rbp" : "rax", "rsi", "rdi", "rsp", "rbp");
);
} }
void Linker::Execute() { void Linker::Execute() {
Core::Libraries::LibKernel::pthreadInitSelfMainThread(); Core::Libraries::LibKernel::pthreadInitSelfMainThread();
EntryParams p{}; EntryParams p{};
p.argc = 1; p.argc = 1;
p.argv[0] = "eboot.bin"; //hmm should be ok? p.argv[0] = "eboot.bin"; // hmm should be ok?
const auto& module = m_modules.at(0); const auto& module = m_modules.at(0);
run_main_entry(module.elf.GetElfEntry() + module.base_virtual_addr, &p, ProgramExitFunc); run_main_entry(module.elf.GetElfEntry() + module.base_virtual_addr, &p, ProgramExitFunc);

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <vector>
#include <mutex> #include <mutex>
#include <vector>
#include "core/loader/elf.h" #include "core/loader/elf.h"
#include "core/loader/symbols_resolver.h" #include "core/loader/symbols_resolver.h"
@ -118,9 +118,12 @@ public:
void LoadModuleToMemory(Module* m); void LoadModuleToMemory(Module* m);
void LoadDynamicInfo(Module* m); void LoadDynamicInfo(Module* m);
void LoadSymbols(Module* m); void LoadSymbols(Module* m);
Loader::SymbolsResolver& getHLESymbols() { return m_hle_symbols; } Loader::SymbolsResolver& getHLESymbols() {
return m_hle_symbols;
}
void Relocate(Module* m); void Relocate(Module* m);
void Resolve(const std::string& name, int Symtype, Module* m, Loader::SymbolRecord* return_info); void Resolve(const std::string& name, int Symtype, Module* m,
Loader::SymbolRecord* return_info);
void Execute(); void Execute();
private: private:

View File

@ -1,6 +1,6 @@
#include <fmt/core.h> #include <fmt/core.h>
#include "common/log.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/log.h"
#include "core/loader/elf.h" #include "core/loader/elf.h"
namespace Core::Loader { namespace Core::Loader {
@ -9,112 +9,177 @@ constexpr bool log_file_loader = false; // disable it to disable logging
static std::string_view getProgramTypeName(program_type_es type) { static std::string_view getProgramTypeName(program_type_es type) {
switch (type) { switch (type) {
case PT_FAKE: return "PT_FAKE"; case PT_FAKE:
case PT_NPDRM_EXEC: return "PT_NPDRM_EXEC"; return "PT_FAKE";
case PT_NPDRM_DYNLIB: return "PT_NPDRM_DYNLIB"; case PT_NPDRM_EXEC:
case PT_SYSTEM_EXEC: return "PT_SYSTEM_EXEC"; return "PT_NPDRM_EXEC";
case PT_SYSTEM_DYNLIB: return "PT_SYSTEM_DYNLIB"; case PT_NPDRM_DYNLIB:
case PT_HOST_KERNEL: return "PT_HOST_KERNEL"; return "PT_NPDRM_DYNLIB";
case PT_SECURE_MODULE: return "PT_SECURE_MODULE"; case PT_SYSTEM_EXEC:
case PT_SECURE_KERNEL: return "PT_SECURE_KERNEL"; return "PT_SYSTEM_EXEC";
default: return "INVALID"; case PT_SYSTEM_DYNLIB:
return "PT_SYSTEM_DYNLIB";
case PT_HOST_KERNEL:
return "PT_HOST_KERNEL";
case PT_SECURE_MODULE:
return "PT_SECURE_MODULE";
case PT_SECURE_KERNEL:
return "PT_SECURE_KERNEL";
default:
return "INVALID";
} }
} }
static std::string_view getIdentClassName(ident_class_es elf_class) { static std::string_view getIdentClassName(ident_class_es elf_class) {
switch (elf_class) { switch (elf_class) {
case ELF_CLASS_NONE: return "ELF_CLASS_NONE"; case ELF_CLASS_NONE:
case ELF_CLASS_32: return "ELF_CLASS_32"; return "ELF_CLASS_NONE";
case ELF_CLASS_64: return "ELF_CLASS_64"; case ELF_CLASS_32:
case ELF_CLASS_NUM: return "ELF_CLASS_NUM"; return "ELF_CLASS_32";
default: return "INVALID"; case ELF_CLASS_64:
return "ELF_CLASS_64";
case ELF_CLASS_NUM:
return "ELF_CLASS_NUM";
default:
return "INVALID";
} }
} }
static std::string_view getIdentEndianName(ident_endian_es endian) { static std::string_view getIdentEndianName(ident_endian_es endian) {
switch (endian) { switch (endian) {
case ELF_DATA_NONE: return "ELF_DATA_NONE"; case ELF_DATA_NONE:
case ELF_DATA_2LSB: return "ELF_DATA_2LSB"; return "ELF_DATA_NONE";
case ELF_DATA_2MSB: return "ELF_DATA_2MSB"; case ELF_DATA_2LSB:
case ELF_DATA_NUM: return "ELF_DATA_NUM"; return "ELF_DATA_2LSB";
default: return "INVALID"; case ELF_DATA_2MSB:
return "ELF_DATA_2MSB";
case ELF_DATA_NUM:
return "ELF_DATA_NUM";
default:
return "INVALID";
} }
} }
static std::string_view getIdentVersionName(ident_version_es version) { static std::string_view getIdentVersionName(ident_version_es version) {
switch (version) { switch (version) {
case ELF_VERSION_NONE: return "ELF_VERSION_NONE"; case ELF_VERSION_NONE:
case ELF_VERSION_CURRENT: return "ELF_VERSION_CURRENT"; return "ELF_VERSION_NONE";
case ELF_VERSION_NUM: return "ELF_VERSION_NUM"; case ELF_VERSION_CURRENT:
default: return "INVALID"; return "ELF_VERSION_CURRENT";
case ELF_VERSION_NUM:
return "ELF_VERSION_NUM";
default:
return "INVALID";
} }
} }
static std::string_view getIdentOsabiName(ident_osabi_es osabi) { static std::string_view getIdentOsabiName(ident_osabi_es osabi) {
switch (osabi) { switch (osabi) {
case ELF_OSABI_NONE: return "ELF_OSABI_NONE"; case ELF_OSABI_NONE:
case ELF_OSABI_HPUX: return "ELF_OSABI_HPUX"; return "ELF_OSABI_NONE";
case ELF_OSABI_NETBSD: return "ELF_OSABI_NETBSD"; case ELF_OSABI_HPUX:
case ELF_OSABI_LINUX: return "ELF_OSABI_LINUX"; return "ELF_OSABI_HPUX";
case ELF_OSABI_SOLARIS: return "ELF_OSABI_SOLARIS"; case ELF_OSABI_NETBSD:
case ELF_OSABI_AIX: return "ELF_OSABI_AIX"; return "ELF_OSABI_NETBSD";
case ELF_OSABI_IRIX: return "ELF_OSABI_IRIX"; case ELF_OSABI_LINUX:
case ELF_OSABI_FREEBSD: return "ELF_OSABI_FREEBSD"; return "ELF_OSABI_LINUX";
case ELF_OSABI_TRU64: return "ELF_OSABI_TRU64"; case ELF_OSABI_SOLARIS:
case ELF_OSABI_MODESTO: return "ELF_OSABI_MODESTO"; return "ELF_OSABI_SOLARIS";
case ELF_OSABI_OPENBSD: return "ELF_OSABI_OPENBSD"; case ELF_OSABI_AIX:
case ELF_OSABI_OPENVMS: return "ELF_OSABI_OPENVMS"; return "ELF_OSABI_AIX";
case ELF_OSABI_NSK: return "ELF_OSABI_NSK"; case ELF_OSABI_IRIX:
case ELF_OSABI_AROS: return "ELF_OSABI_AROS"; return "ELF_OSABI_IRIX";
case ELF_OSABI_ARM_AEABI: return "ELF_OSABI_ARM_AEABI"; case ELF_OSABI_FREEBSD:
case ELF_OSABI_ARM: return "ELF_OSABI_ARM"; return "ELF_OSABI_FREEBSD";
case ELF_OSABI_STANDALONE: return "ELF_OSABI_STANDALONE"; case ELF_OSABI_TRU64:
default: return "INVALID"; return "ELF_OSABI_TRU64";
case ELF_OSABI_MODESTO:
return "ELF_OSABI_MODESTO";
case ELF_OSABI_OPENBSD:
return "ELF_OSABI_OPENBSD";
case ELF_OSABI_OPENVMS:
return "ELF_OSABI_OPENVMS";
case ELF_OSABI_NSK:
return "ELF_OSABI_NSK";
case ELF_OSABI_AROS:
return "ELF_OSABI_AROS";
case ELF_OSABI_ARM_AEABI:
return "ELF_OSABI_ARM_AEABI";
case ELF_OSABI_ARM:
return "ELF_OSABI_ARM";
case ELF_OSABI_STANDALONE:
return "ELF_OSABI_STANDALONE";
default:
return "INVALID";
} }
} }
static std::string_view getIdentAbiversionName(ident_abiversion_es version) { static std::string_view getIdentAbiversionName(ident_abiversion_es version) {
switch (version) { switch (version) {
case ELF_ABI_VERSION_AMDGPU_HSA_V2: return "ELF_ABI_VERSION_AMDGPU_HSA_V2"; case ELF_ABI_VERSION_AMDGPU_HSA_V2:
case ELF_ABI_VERSION_AMDGPU_HSA_V3: return "ELF_ABI_VERSION_AMDGPU_HSA_V3"; return "ELF_ABI_VERSION_AMDGPU_HSA_V2";
case ELF_ABI_VERSION_AMDGPU_HSA_V4: return "ELF_ABI_VERSION_AMDGPU_HSA_V4"; case ELF_ABI_VERSION_AMDGPU_HSA_V3:
case ELF_ABI_VERSION_AMDGPU_HSA_V5: return "ELF_ABI_VERSION_AMDGPU_HSA_V5"; return "ELF_ABI_VERSION_AMDGPU_HSA_V3";
default: return "INVALID"; case ELF_ABI_VERSION_AMDGPU_HSA_V4:
return "ELF_ABI_VERSION_AMDGPU_HSA_V4";
case ELF_ABI_VERSION_AMDGPU_HSA_V5:
return "ELF_ABI_VERSION_AMDGPU_HSA_V5";
default:
return "INVALID";
} }
} }
static std::string_view getVersion(e_version_es version) { static std::string_view getVersion(e_version_es version) {
switch (version) { switch (version) {
case EV_NONE: return "EV_NONE"; case EV_NONE:
case EV_CURRENT: return "EV_CURRENT"; return "EV_NONE";
default: return "INVALID"; case EV_CURRENT:
return "EV_CURRENT";
default:
return "INVALID";
} }
} }
static std::string_view getType(e_type_s type) { static std::string_view getType(e_type_s type) {
switch (type) { switch (type) {
case ET_NONE: return "ET_NONE"; case ET_NONE:
case ET_REL: return "ET_REL"; return "ET_NONE";
case ET_EXEC: return "ET_EXEC"; case ET_REL:
case ET_DYN: return "ET_DYN"; return "ET_REL";
case ET_CORE: return "ET_CORE"; case ET_EXEC:
case ET_SCE_EXEC: return "ET_SCE_EXEC"; return "ET_EXEC";
case ET_SCE_STUBLIB: return "ET_SCE_STUBLIB"; case ET_DYN:
case ET_SCE_DYNEXEC: return "ET_SCE_DYNEXEC"; return "ET_DYN";
case ET_SCE_DYNAMIC: return "ET_SCE_DYNAMIC"; case ET_CORE:
default: return "INVALID"; return "ET_CORE";
case ET_SCE_EXEC:
return "ET_SCE_EXEC";
case ET_SCE_STUBLIB:
return "ET_SCE_STUBLIB";
case ET_SCE_DYNEXEC:
return "ET_SCE_DYNEXEC";
case ET_SCE_DYNAMIC:
return "ET_SCE_DYNAMIC";
default:
return "INVALID";
} }
} }
static std::string_view getMachine(e_machine_es machine) { static std::string_view getMachine(e_machine_es machine) {
switch (machine) { switch (machine) {
case EM_X86_64: return "EM_X86_64"; case EM_X86_64:
default: return "INVALID"; return "EM_X86_64";
default:
return "INVALID";
} }
} }
Elf::~Elf() { Reset(); } Elf::~Elf() {
Reset();
}
void Elf::Reset() { m_f.close(); } void Elf::Reset() {
m_f.close();
}
void Elf::Open(const std::string& file_name) { void Elf::Open(const std::string& file_name) {
Reset(); Reset();
@ -169,12 +234,14 @@ void Elf::Open(const std::string& file_name) {
bool Elf::isSelfFile() const { bool Elf::isSelfFile() const {
if (m_self.magic != self_header::signature) [[unlikely]] { if (m_self.magic != self_header::signature) [[unlikely]] {
LOG_ERROR_IF(log_file_loader, "Not a SELF file.Magic file mismatched !current = {:#x} required = {:#x}\n ", m_self.magic, LOG_ERROR_IF(log_file_loader,
self_header::signature); "Not a SELF file.Magic file mismatched !current = {:#x} required = {:#x}\n ",
m_self.magic, self_header::signature);
return false; return false;
} }
if (m_self.version != 0x00 || m_self.mode != 0x01 || m_self.endian != 0x01 || m_self.attributes != 0x12) [[unlikely]] { if (m_self.version != 0x00 || m_self.mode != 0x01 || m_self.endian != 0x01 ||
m_self.attributes != 0x12) [[unlikely]] {
LOG_ERROR_IF(log_file_loader, "Unknown SELF file\n"); LOG_ERROR_IF(log_file_loader, "Unknown SELF file\n");
return false; return false;
} }
@ -188,60 +255,74 @@ bool Elf::isSelfFile() const {
} }
bool Elf::isElfFile() const { bool Elf::isElfFile() const {
if (m_elf_header.e_ident.magic[EI_MAG0] != ELFMAG0 || m_elf_header.e_ident.magic[EI_MAG1] != ELFMAG1 || if (m_elf_header.e_ident.magic[EI_MAG0] != ELFMAG0 ||
m_elf_header.e_ident.magic[EI_MAG2] != ELFMAG2 || m_elf_header.e_ident.magic[EI_MAG3] != ELFMAG3) { m_elf_header.e_ident.magic[EI_MAG1] != ELFMAG1 ||
m_elf_header.e_ident.magic[EI_MAG2] != ELFMAG2 ||
m_elf_header.e_ident.magic[EI_MAG3] != ELFMAG3) {
LOG_ERROR_IF(log_file_loader, "Not an ELF file magic is wrong!\n"); LOG_ERROR_IF(log_file_loader, "Not an ELF file magic is wrong!\n");
return false; return false;
} }
if (m_elf_header.e_ident.ei_class != ELF_CLASS_64) { if (m_elf_header.e_ident.ei_class != ELF_CLASS_64) {
LOG_ERROR_IF(log_file_loader, "e_ident[EI_CLASS] expected 0x02 is ({:#x})\n", static_cast<u32>(m_elf_header.e_ident.ei_class)); LOG_ERROR_IF(log_file_loader, "e_ident[EI_CLASS] expected 0x02 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_ident.ei_class));
return false; return false;
} }
if (m_elf_header.e_ident.ei_data != ELF_DATA_2LSB) { if (m_elf_header.e_ident.ei_data != ELF_DATA_2LSB) {
LOG_ERROR_IF(log_file_loader, "e_ident[EI_DATA] expected 0x01 is ({:#x})\n", static_cast<u32>(m_elf_header.e_ident.ei_data)); LOG_ERROR_IF(log_file_loader, "e_ident[EI_DATA] expected 0x01 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_ident.ei_data));
return false; return false;
} }
if (m_elf_header.e_ident.ei_version != ELF_VERSION_CURRENT) { if (m_elf_header.e_ident.ei_version != ELF_VERSION_CURRENT) {
LOG_ERROR_IF(log_file_loader, "e_ident[EI_VERSION] expected 0x01 is ({:#x})\n", static_cast<u32>(m_elf_header.e_ident.ei_version)); LOG_ERROR_IF(log_file_loader, "e_ident[EI_VERSION] expected 0x01 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_ident.ei_version));
return false; return false;
} }
if (m_elf_header.e_ident.ei_osabi != ELF_OSABI_FREEBSD) { if (m_elf_header.e_ident.ei_osabi != ELF_OSABI_FREEBSD) {
LOG_ERROR_IF(log_file_loader, "e_ident[EI_OSABI] expected 0x09 is ({:#x})\n", static_cast<u32>(m_elf_header.e_ident.ei_osabi)); LOG_ERROR_IF(log_file_loader, "e_ident[EI_OSABI] expected 0x09 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_ident.ei_osabi));
return false; return false;
} }
if (m_elf_header.e_ident.ei_abiversion != ELF_ABI_VERSION_AMDGPU_HSA_V2) { if (m_elf_header.e_ident.ei_abiversion != ELF_ABI_VERSION_AMDGPU_HSA_V2) {
LOG_ERROR_IF(log_file_loader, "e_ident[EI_ABIVERSION] expected 0x00 is ({:#x})\n", static_cast<u32>(m_elf_header.e_ident.ei_abiversion)); LOG_ERROR_IF(log_file_loader, "e_ident[EI_ABIVERSION] expected 0x00 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_ident.ei_abiversion));
return false; return false;
} }
if (m_elf_header.e_type != ET_SCE_DYNEXEC && m_elf_header.e_type != ET_SCE_DYNAMIC && m_elf_header.e_type != ET_SCE_EXEC) { if (m_elf_header.e_type != ET_SCE_DYNEXEC && m_elf_header.e_type != ET_SCE_DYNAMIC &&
LOG_ERROR_IF(log_file_loader, "e_type expected 0xFE10 OR 0xFE18 OR 0xfe00 is ({:#x})\n", static_cast<u32>(m_elf_header.e_type)); m_elf_header.e_type != ET_SCE_EXEC) {
LOG_ERROR_IF(log_file_loader, "e_type expected 0xFE10 OR 0xFE18 OR 0xfe00 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_type));
return false; return false;
} }
if (m_elf_header.e_machine != EM_X86_64) { if (m_elf_header.e_machine != EM_X86_64) {
LOG_ERROR_IF(log_file_loader, "e_machine expected 0x3E is ({:#x})\n", static_cast<u32>(m_elf_header.e_machine)); LOG_ERROR_IF(log_file_loader, "e_machine expected 0x3E is ({:#x})\n",
static_cast<u32>(m_elf_header.e_machine));
return false; return false;
} }
if (m_elf_header.e_version != EV_CURRENT) { if (m_elf_header.e_version != EV_CURRENT) {
LOG_ERROR_IF(log_file_loader, "m_elf_header.e_version expected 0x01 is ({:#x})\n", static_cast<u32>(m_elf_header.e_version)); LOG_ERROR_IF(log_file_loader, "m_elf_header.e_version expected 0x01 is ({:#x})\n",
static_cast<u32>(m_elf_header.e_version));
return false; return false;
} }
if (m_elf_header.e_phentsize != sizeof(elf_program_header)) { if (m_elf_header.e_phentsize != sizeof(elf_program_header)) {
LOG_ERROR_IF(log_file_loader, "e_phentsize ({}) != sizeof(elf_program_header)\n", static_cast<u32>(m_elf_header.e_phentsize)); LOG_ERROR_IF(log_file_loader, "e_phentsize ({}) != sizeof(elf_program_header)\n",
static_cast<u32>(m_elf_header.e_phentsize));
return false; return false;
} }
if (m_elf_header.e_shentsize > 0 && if (m_elf_header.e_shentsize > 0 &&
m_elf_header.e_shentsize != sizeof(elf_section_header)) // Commercial games doesn't appear to have section headers m_elf_header.e_shentsize !=
sizeof(elf_section_header)) // Commercial games doesn't appear to have section headers
{ {
LOG_ERROR_IF(log_file_loader, "e_shentsize ({}) != sizeof(elf_section_header)\n", m_elf_header.e_shentsize); LOG_ERROR_IF(log_file_loader, "e_shentsize ({}) != sizeof(elf_section_header)\n",
m_elf_header.e_shentsize);
return false; return false;
} }
@ -276,7 +357,8 @@ void Elf::DebugDump() {
LOG_INFO_IF(log_file_loader, "sh_size ........: {:#018x}\n", m_elf_shdr[i].sh_size); LOG_INFO_IF(log_file_loader, "sh_size ........: {:#018x}\n", m_elf_shdr[i].sh_size);
LOG_INFO_IF(log_file_loader, "sh_link ........: {:#010x}\n", m_elf_shdr[i].sh_link); LOG_INFO_IF(log_file_loader, "sh_link ........: {:#010x}\n", m_elf_shdr[i].sh_link);
LOG_INFO_IF(log_file_loader, "sh_info ........: {:#010x}\n", m_elf_shdr[i].sh_info); LOG_INFO_IF(log_file_loader, "sh_info ........: {:#010x}\n", m_elf_shdr[i].sh_info);
LOG_INFO_IF(log_file_loader, "sh_addralign ...: {:#018x}\n", m_elf_shdr[i].sh_addralign); LOG_INFO_IF(log_file_loader, "sh_addralign ...: {:#018x}\n",
m_elf_shdr[i].sh_addralign);
LOG_INFO_IF(log_file_loader, "sh_entsize .....: {:#018x}\n", m_elf_shdr[i].sh_entsize); LOG_INFO_IF(log_file_loader, "sh_entsize .....: {:#018x}\n", m_elf_shdr[i].sh_entsize);
} }
} }
@ -284,7 +366,8 @@ void Elf::DebugDump() {
if (is_self) { if (is_self) {
LOG_INFO_IF(log_file_loader, "SELF info:\n"); LOG_INFO_IF(log_file_loader, "SELF info:\n");
LOG_INFO_IF(log_file_loader, "auth id ............: {:#018x}\n", m_self_id_header.authid); LOG_INFO_IF(log_file_loader, "auth id ............: {:#018x}\n", m_self_id_header.authid);
LOG_INFO_IF(log_file_loader, "program type .......: {}\n", getProgramTypeName(m_self_id_header.program_type)); LOG_INFO_IF(log_file_loader, "program type .......: {}\n",
getProgramTypeName(m_self_id_header.program_type));
LOG_INFO_IF(log_file_loader, "app version ........: {:#018x}\n", m_self_id_header.appver); LOG_INFO_IF(log_file_loader, "app version ........: {:#018x}\n", m_self_id_header.appver);
LOG_INFO_IF(log_file_loader, "fw version .........: {:#018x}\n", m_self_id_header.firmver); LOG_INFO_IF(log_file_loader, "fw version .........: {:#018x}\n", m_self_id_header.firmver);
std::string digest; std::string digest;
@ -333,11 +416,16 @@ std::string Elf::ElfHeaderStr() {
} }
header += fmt::format("\n"); header += fmt::format("\n");
header += fmt::format("ident class.......: {}\n", getIdentClassName(m_elf_header.e_ident.ei_class)); header +=
header += fmt::format("ident data .......: {}\n", getIdentEndianName(m_elf_header.e_ident.ei_data)); fmt::format("ident class.......: {}\n", getIdentClassName(m_elf_header.e_ident.ei_class));
header += fmt::format("ident version.....: {}\n", getIdentVersionName(m_elf_header.e_ident.ei_version)); header +=
header += fmt::format("ident osabi .....: {}\n", getIdentOsabiName(m_elf_header.e_ident.ei_osabi)); fmt::format("ident data .......: {}\n", getIdentEndianName(m_elf_header.e_ident.ei_data));
header += fmt::format("ident abiversion..: {}\n", getIdentAbiversionName(m_elf_header.e_ident.ei_abiversion)); header += fmt::format("ident version.....: {}\n",
getIdentVersionName(m_elf_header.e_ident.ei_version));
header +=
fmt::format("ident osabi .....: {}\n", getIdentOsabiName(m_elf_header.e_ident.ei_osabi));
header += fmt::format("ident abiversion..: {}\n",
getIdentAbiversionName(m_elf_header.e_ident.ei_abiversion));
header += fmt::format("ident UNK ........: 0x"); header += fmt::format("ident UNK ........: 0x");
for (auto i : m_elf_header.e_ident.pad) { for (auto i : m_elf_header.e_ident.pad) {
@ -363,26 +451,46 @@ std::string Elf::ElfHeaderStr() {
std::string Elf::ElfPheaderTypeStr(u32 type) { std::string Elf::ElfPheaderTypeStr(u32 type) {
switch (type) { switch (type) {
case PT_NULL: return "Null"; case PT_NULL:
case PT_LOAD: return "Loadable"; return "Null";
case PT_DYNAMIC: return "Dynamic"; case PT_LOAD:
case PT_INTERP: return "Interpreter Path"; return "Loadable";
case PT_NOTE: return "Note"; case PT_DYNAMIC:
case PT_SHLIB: return "Section Header Library"; return "Dynamic";
case PT_PHDR: return "Program Header"; case PT_INTERP:
case PT_TLS: return "Thread-Local Storage"; return "Interpreter Path";
case PT_NUM: return "Defined Sections Number"; case PT_NOTE:
case PT_SCE_RELA: return "SCE Relative"; return "Note";
case PT_SCE_DYNLIBDATA: return "SCE Dynamic Library Data"; case PT_SHLIB:
case PT_SCE_PROCPARAM: return "SCE Processor Parameters"; return "Section Header Library";
case PT_SCE_MODULE_PARAM: return "SCE Module Parameters"; case PT_PHDR:
case PT_SCE_RELRO: return "SCE Read-Only After Relocation"; return "Program Header";
case PT_GNU_EH_FRAME: return "GNU Entry Header Frame"; case PT_TLS:
case PT_GNU_STACK: return "GNU Stack (executability)"; return "Thread-Local Storage";
case PT_GNU_RELRO: return "GNU Read-Only After Relocation"; case PT_NUM:
case PT_SCE_COMMENT: return "SCE Comment"; return "Defined Sections Number";
case PT_SCE_LIBVERSION: return "SCE Library Version"; case PT_SCE_RELA:
default: return "Unknown Section"; return "SCE Relative";
case PT_SCE_DYNLIBDATA:
return "SCE Dynamic Library Data";
case PT_SCE_PROCPARAM:
return "SCE Processor Parameters";
case PT_SCE_MODULE_PARAM:
return "SCE Module Parameters";
case PT_SCE_RELRO:
return "SCE Read-Only After Relocation";
case PT_GNU_EH_FRAME:
return "GNU Entry Header Frame";
case PT_GNU_STACK:
return "GNU Stack (executability)";
case PT_GNU_RELRO:
return "GNU Read-Only After Relocation";
case PT_SCE_COMMENT:
return "SCE Comment";
case PT_SCE_LIBVERSION:
return "SCE Library Version";
default:
return "Unknown Section";
} }
} }

View File

@ -33,7 +33,9 @@ struct self_segment_header {
return (flags & 0x800) != 0; // 0 or 0x800 return (flags & 0x800) != 0; // 0 or 0x800
} }
u32 GetId() const { return (flags >> 20u) & 0xFFFu; } u32 GetId() const {
return (flags >> 20u) & 0xFFFu;
}
bool IsOrdered() const { bool IsOrdered() const {
return (flags & 1) != 0; // 0 or 1 return (flags & 1) != 0; // 0 or 1
@ -181,11 +183,25 @@ typedef enum : u16 {
typedef enum : u32 { EV_NONE = 0x0, EV_CURRENT = 0x1 } e_version_es; typedef enum : u32 { EV_NONE = 0x0, EV_CURRENT = 0x1 } e_version_es;
typedef enum : u08 { ELF_CLASS_NONE = 0x0, ELF_CLASS_32 = 0x1, ELF_CLASS_64 = 0x2, ELF_CLASS_NUM = 0x3 } ident_class_es; typedef enum : u08 {
ELF_CLASS_NONE = 0x0,
ELF_CLASS_32 = 0x1,
ELF_CLASS_64 = 0x2,
ELF_CLASS_NUM = 0x3
} ident_class_es;
typedef enum : u08 { ELF_DATA_NONE = 0x0, ELF_DATA_2LSB = 0x1, ELF_DATA_2MSB = 0x2, ELF_DATA_NUM = 0x3 } ident_endian_es; typedef enum : u08 {
ELF_DATA_NONE = 0x0,
ELF_DATA_2LSB = 0x1,
ELF_DATA_2MSB = 0x2,
ELF_DATA_NUM = 0x3
} ident_endian_es;
typedef enum : u08 { ELF_VERSION_NONE = 0x0, ELF_VERSION_CURRENT = 0x1, ELF_VERSION_NUM = 0x2 } ident_version_es; typedef enum : u08 {
ELF_VERSION_NONE = 0x0,
ELF_VERSION_CURRENT = 0x1,
ELF_VERSION_NUM = 0x2
} ident_version_es;
typedef enum : u08 { typedef enum : u08 {
ELF_OSABI_NONE = 0x0, /* No extensions or unspecified */ ELF_OSABI_NONE = 0x0, /* No extensions or unspecified */
@ -395,9 +411,15 @@ constexpr u08 STV_HIDDEN = 2;
constexpr u08 STV_PROTECTED = 3; constexpr u08 STV_PROTECTED = 3;
struct elf_symbol { struct elf_symbol {
u08 GetBind() const { return st_info >> 4u; } u08 GetBind() const {
u08 GetType() const { return st_info & 0xfu; } return st_info >> 4u;
u08 GetVisibility() const { return st_other & 3u; } }
u08 GetType() const {
return st_info & 0xfu;
}
u08 GetVisibility() const {
return st_other & 3u;
}
u32 st_name; u32 st_name;
u08 st_info; u08 st_info;
@ -408,8 +430,12 @@ struct elf_symbol {
}; };
struct elf_relocation { struct elf_relocation {
u32 GetSymbol() const { return static_cast<u32>(rel_info >> 32u); } u32 GetSymbol() const {
u32 GetType() const { return static_cast<u32>(rel_info & 0xffffffff); } return static_cast<u32>(rel_info >> 32u);
}
u32 GetType() const {
return static_cast<u32>(rel_info & 0xffffffff);
}
u64 rel_offset; u64 rel_offset;
u64 rel_info; u64 rel_info;
@ -424,7 +450,7 @@ constexpr u32 R_X86_64_DTPMOD64 = 16;
namespace Core::Loader { namespace Core::Loader {
class Elf { class Elf {
public: public:
Elf() = default; Elf() = default;
virtual ~Elf(); virtual ~Elf();
@ -433,15 +459,25 @@ class Elf {
bool isElfFile() const; bool isElfFile() const;
void DebugDump(); void DebugDump();
[[nodiscard]] self_header GetSElfHeader() const { return m_self; } [[nodiscard]] self_header GetSElfHeader() const {
return m_self;
}
[[nodiscard]] elf_header GetElfHeader() const { return m_elf_header; } [[nodiscard]] elf_header GetElfHeader() const {
return m_elf_header;
}
[[nodiscard]] std::span<const elf_program_header> GetProgramHeader() const { return m_elf_phdr; } [[nodiscard]] std::span<const elf_program_header> GetProgramHeader() const {
return m_elf_phdr;
}
[[nodiscard]] std::span<const self_segment_header> GetSegmentHeader() const { return m_self_segments; } [[nodiscard]] std::span<const self_segment_header> GetSegmentHeader() const {
return m_self_segments;
}
[[nodiscard]] u64 GetElfEntry() const { return m_elf_header.e_entry; } [[nodiscard]] u64 GetElfEntry() const {
return m_elf_header.e_entry;
}
std::string SElfHeaderStr(); std::string SElfHeaderStr();
std::string SELFSegHeader(u16 no); std::string SELFSegHeader(u16 no);
@ -452,10 +488,10 @@ class Elf {
void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size); void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size);
private: private:
void Reset(); void Reset();
private: private:
Common::FS::File m_f{}; Common::FS::File m_f{};
bool is_self{}; bool is_self{};
self_header m_self{}; self_header m_self{};

View File

@ -12,8 +12,7 @@ void SymbolsResolver::AddSymbol(const SymbolRes& s, u64 virtual_addr) {
} }
std::string SymbolsResolver::GenerateName(const SymbolRes& s) { std::string SymbolsResolver::GenerateName(const SymbolRes& s) {
return fmt::format("{} lib[{}_v{}]mod[{}_v{}.{}]", return fmt::format("{} lib[{}_v{}]mod[{}_v{}.{}]", s.name, s.library, s.library_version,
s.name, s.library, s.library_version,
s.module, s.module_version_major, s.module_version_minor); s.module, s.module_version_major, s.module_version_minor);
} }

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {

View File

@ -22,34 +22,49 @@ enum PosixPageProtection {
namespace VirtualMemory { namespace VirtualMemory {
static u32 convertMemoryMode(MemoryMode mode) { static u32 convertMemoryMode(MemoryMode mode) {
switch (mode) { switch (mode) {
case MemoryMode::Read: return PAGE_READONLY; case MemoryMode::Read:
return PAGE_READONLY;
case MemoryMode::Write: case MemoryMode::Write:
case MemoryMode::ReadWrite: return PAGE_READWRITE; case MemoryMode::ReadWrite:
return PAGE_READWRITE;
case MemoryMode::Execute: return PAGE_EXECUTE; case MemoryMode::Execute:
case MemoryMode::ExecuteRead: return PAGE_EXECUTE_READ; return PAGE_EXECUTE;
case MemoryMode::ExecuteRead:
return PAGE_EXECUTE_READ;
case MemoryMode::ExecuteWrite: case MemoryMode::ExecuteWrite:
case MemoryMode::ExecuteReadWrite: return PAGE_EXECUTE_READWRITE; case MemoryMode::ExecuteReadWrite:
return PAGE_EXECUTE_READWRITE;
case MemoryMode::NoAccess: return PAGE_NOACCESS; case MemoryMode::NoAccess:
default: return PAGE_NOACCESS; return PAGE_NOACCESS;
default:
return PAGE_NOACCESS;
} }
} }
static MemoryMode convertMemoryMode(u32 mode) { static MemoryMode convertMemoryMode(u32 mode) {
switch (mode) { switch (mode) {
case PAGE_NOACCESS: return MemoryMode::NoAccess; case PAGE_NOACCESS:
case PAGE_READONLY: return MemoryMode::Read; return MemoryMode::NoAccess;
case PAGE_READWRITE: return MemoryMode::ReadWrite; case PAGE_READONLY:
case PAGE_EXECUTE: return MemoryMode::Execute; return MemoryMode::Read;
case PAGE_EXECUTE_READ: return MemoryMode::ExecuteRead; case PAGE_READWRITE:
case PAGE_EXECUTE_READWRITE: return MemoryMode::ExecuteReadWrite; return MemoryMode::ReadWrite;
default: return MemoryMode::NoAccess; case PAGE_EXECUTE:
return MemoryMode::Execute;
case PAGE_EXECUTE_READ:
return MemoryMode::ExecuteRead;
case PAGE_EXECUTE_READWRITE:
return MemoryMode::ExecuteReadWrite;
default:
return MemoryMode::NoAccess;
} }
} }
u64 memory_alloc(u64 address, u64 size, MemoryMode mode) { u64 memory_alloc(u64 address, u64 size, MemoryMode mode) {
#ifdef _WIN64 #ifdef _WIN64
auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size, auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc(
reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE), convertMemoryMode(mode))); static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE), convertMemoryMode(mode)));
if (ptr == 0) { if (ptr == 0) {
@ -58,7 +73,8 @@ u64 memory_alloc(u64 address, u64 size, MemoryMode mode) {
} }
#else #else
auto ptr = reinterpret_cast<uintptr_t>( auto ptr = reinterpret_cast<uintptr_t>(
mmap(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); mmap(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), size,
PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
if (ptr == reinterpret_cast<uintptr_t> MAP_FAILED) { if (ptr == reinterpret_cast<uintptr_t> MAP_FAILED) {
LOG_ERROR_IF(true, "mmap() failed: {}\n", std::strerror(errno)); LOG_ERROR_IF(true, "mmap() failed: {}\n", std::strerror(errno));
@ -69,7 +85,8 @@ u64 memory_alloc(u64 address, u64 size, MemoryMode mode) {
bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode) { bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode) {
#ifdef _WIN64 #ifdef _WIN64
DWORD old_protect = 0; DWORD old_protect = 0;
if (VirtualProtect(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size, convertMemoryMode(mode), &old_protect) == 0) { if (VirtualProtect(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
convertMemoryMode(mode), &old_protect) == 0) {
auto err = static_cast<u32>(GetLastError()); auto err = static_cast<u32>(GetLastError());
LOG_ERROR_IF(true, "VirtualProtect() failed: 0x{:X}\n", err); LOG_ERROR_IF(true, "VirtualProtect() failed: 0x{:X}\n", err);
return false; return false;
@ -86,7 +103,9 @@ bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode
bool memory_flush(u64 address, u64 size) { bool memory_flush(u64 address, u64 size) {
#ifdef _WIN64 #ifdef _WIN64
if (::FlushInstructionCache(GetCurrentProcess(), reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size) == 0) { if (::FlushInstructionCache(GetCurrentProcess(),
reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)),
size) == 0) {
auto err = static_cast<u32>(GetLastError()); auto err = static_cast<u32>(GetLastError());
LOG_ERROR_IF(true, "FlushInstructionCache() failed: 0x{:X}\n", err); LOG_ERROR_IF(true, "FlushInstructionCache() failed: 0x{:X}\n", err);
return false; return false;
@ -115,21 +134,27 @@ bool memory_patch(u64 vaddr, u64 value) {
return ret; return ret;
} }
static u64 AlignUp(u64 pos, u64 align) { return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); } static u64 AlignUp(u64 pos, u64 align) {
return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos);
}
u64 memory_alloc_aligned(u64 address, u64 size, MemoryMode mode, u64 alignment) { u64 memory_alloc_aligned(u64 address, u64 size, MemoryMode mode, u64 alignment) {
#ifdef _WIN64 #ifdef _WIN64
// try allocate aligned address inside user area // try allocate aligned address inside user area
MEM_ADDRESS_REQUIREMENTS req{}; MEM_ADDRESS_REQUIREMENTS req{};
MEM_EXTENDED_PARAMETER param{}; MEM_EXTENDED_PARAMETER param{};
req.LowestStartingAddress = (address == 0 ? reinterpret_cast<PVOID>(USER_MIN) : reinterpret_cast<PVOID>(AlignUp(address, alignment))); req.LowestStartingAddress =
(address == 0 ? reinterpret_cast<PVOID>(USER_MIN)
: reinterpret_cast<PVOID>(AlignUp(address, alignment)));
req.HighestEndingAddress = reinterpret_cast<PVOID>(USER_MAX); req.HighestEndingAddress = reinterpret_cast<PVOID>(USER_MAX);
req.Alignment = alignment; req.Alignment = alignment;
param.Type = MemExtendedParameterAddressRequirements; param.Type = MemExtendedParameterAddressRequirements;
param.Pointer = &req; param.Pointer = &req;
auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc2( auto ptr = reinterpret_cast<uintptr_t>(
GetCurrentProcess(), nullptr, size, static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE), convertMemoryMode(mode), &param, 1)); VirtualAlloc2(GetCurrentProcess(), nullptr, size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
convertMemoryMode(mode), &param, 1));
if (ptr == 0) { if (ptr == 0) {
auto err = static_cast<u32>(GetLastError()); auto err = static_cast<u32>(GetLastError());

View File

@ -27,11 +27,16 @@ bool memory_patch(u64 vaddr, u64 value);
inline bool containsExecuteMode(MemoryMode mode) { inline bool containsExecuteMode(MemoryMode mode) {
switch (mode) { switch (mode) {
case MemoryMode::Execute: return true; case MemoryMode::Execute:
case MemoryMode::ExecuteRead: return true; return true;
case MemoryMode::ExecuteWrite: return true; case MemoryMode::ExecuteRead:
case MemoryMode::ExecuteReadWrite: return true; return true;
default: return false; case MemoryMode::ExecuteWrite:
return true;
case MemoryMode::ExecuteReadWrite:
return true;
default:
return false;
} }
} }

View File

@ -1,12 +1,12 @@
#include <fmt/core.h> #include <fmt/core.h>
#include <vulkan_util.h> #include <vulkan_util.h>
#include "Emulator/Host/controller.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "common/version.h" #include "common/version.h"
#include "emulator.h"
#include "core/PS4/HLE/Graphics/graphics_render.h" #include "core/PS4/HLE/Graphics/graphics_render.h"
#include "Emulator/Host/controller.h"
#include "core/PS4/HLE/Graphics/video_out.h" #include "core/PS4/HLE/Graphics/video_out.h"
#include "core/hle/libraries/libpad/pad.h" #include "core/hle/libraries/libpad/pad.h"
#include "emulator.h"
namespace Emu { namespace Emu {
@ -46,10 +46,12 @@ static void CreateSdlWindow(WindowCtx* ctx) {
std::exit(0); std::exit(0);
} }
std::string title = "shadps4 v" + std::string(Common::VERSION); std::string title = "shadps4 v" + std::string(Common::VERSION);
ctx->m_window = SDL_CreateWindowWithPosition(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, ctx->m_window = SDL_CreateWindowWithPosition(
title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height,
(static_cast<uint32_t>(SDL_WINDOW_HIDDEN) | static_cast<uint32_t>(SDL_WINDOW_VULKAN))); (static_cast<uint32_t>(SDL_WINDOW_HIDDEN) | static_cast<uint32_t>(SDL_WINDOW_VULKAN)));
ctx->is_window_hidden = true; // hide window until we need to show something (should draw something in buffers) ctx->is_window_hidden =
true; // hide window until we need to show something (should draw something in buffers)
if (ctx->m_window == nullptr) { if (ctx->m_window == nullptr) {
fmt::print("{}\n", SDL_GetError()); fmt::print("{}\n", SDL_GetError());
@ -83,7 +85,8 @@ static void calculateFps(double game_time_s) {
m_fps_frames_num++; m_fps_frames_num++;
if (m_current_time_seconds - m_fps_start_time > 0.25f) { if (m_current_time_seconds - m_fps_start_time > 0.25f) {
m_current_fps = static_cast<double>(m_fps_frames_num) / (m_current_time_seconds - m_fps_start_time); m_current_fps =
static_cast<double>(m_fps_frames_num) / (m_current_time_seconds - m_fps_start_time);
m_fps_frames_num = 0; m_fps_frames_num = 0;
m_fps_start_time = m_current_time_seconds; m_fps_start_time = m_current_time_seconds;
} }
@ -110,21 +113,29 @@ void emuRun() {
SDL_Event event; SDL_Event event;
if (SDL_PollEvent(&event) != 0) { if (SDL_PollEvent(&event) != 0) {
switch (event.type) { switch (event.type) {
case SDL_EVENT_QUIT: m_emu_needs_exit = true; break; case SDL_EVENT_QUIT:
m_emu_needs_exit = true;
break;
case SDL_EVENT_TERMINATING: m_emu_needs_exit = true; break; case SDL_EVENT_TERMINATING:
m_emu_needs_exit = true;
break;
case SDL_EVENT_WILL_ENTER_BACKGROUND: break; case SDL_EVENT_WILL_ENTER_BACKGROUND:
break;
case SDL_EVENT_DID_ENTER_BACKGROUND: break; case SDL_EVENT_DID_ENTER_BACKGROUND:
break;
case SDL_EVENT_WILL_ENTER_FOREGROUND: break; case SDL_EVENT_WILL_ENTER_FOREGROUND:
break;
case SDL_EVENT_DID_ENTER_FOREGROUND: break; case SDL_EVENT_DID_ENTER_FOREGROUND:
break;
case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_UP: case SDL_EVENT_KEY_UP:
if (event.type == SDL_EVENT_KEY_DOWN){ if (event.type == SDL_EVENT_KEY_DOWN) {
if (event.key.keysym.sym == SDLK_p) { if (event.key.keysym.sym == SDLK_p) {
m_game_is_paused = !m_game_is_paused; m_game_is_paused = !m_game_is_paused;
} }
@ -138,17 +149,25 @@ void emuRun() {
SDL_WaitEvent(&event); SDL_WaitEvent(&event);
switch (event.type) { switch (event.type) {
case SDL_EVENT_QUIT: m_emu_needs_exit = true; break; case SDL_EVENT_QUIT:
m_emu_needs_exit = true;
break;
case SDL_EVENT_TERMINATING: m_emu_needs_exit = true; break; case SDL_EVENT_TERMINATING:
m_emu_needs_exit = true;
break;
case SDL_EVENT_WILL_ENTER_BACKGROUND: break; case SDL_EVENT_WILL_ENTER_BACKGROUND:
break;
case SDL_EVENT_DID_ENTER_BACKGROUND: break; case SDL_EVENT_DID_ENTER_BACKGROUND:
break;
case SDL_EVENT_WILL_ENTER_FOREGROUND: break; case SDL_EVENT_WILL_ENTER_FOREGROUND:
break;
case SDL_EVENT_DID_ENTER_FOREGROUND: break; case SDL_EVENT_DID_ENTER_FOREGROUND:
break;
case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_UP: case SDL_EVENT_KEY_UP:
@ -199,7 +218,8 @@ void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {
window_ctx->swapchain.current_index = static_cast<u32>(-1); window_ctx->swapchain.current_index = static_cast<u32>(-1);
auto result = vkAcquireNextImageKHR(window_ctx->m_graphic_ctx.m_device, window_ctx->swapchain.swapchain, UINT64_MAX, nullptr, auto result = vkAcquireNextImageKHR(window_ctx->m_graphic_ctx.m_device,
window_ctx->swapchain.swapchain, UINT64_MAX, nullptr,
VK_NULL_HANDLE, &window_ctx->swapchain.current_index); VK_NULL_HANDLE, &window_ctx->swapchain.current_index);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
@ -241,8 +261,10 @@ void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {
pre_present_barrier.subresourceRange.levelCount = 1; pre_present_barrier.subresourceRange.levelCount = 1;
pre_present_barrier.subresourceRange.baseArrayLayer = 0; pre_present_barrier.subresourceRange.baseArrayLayer = 0;
pre_present_barrier.subresourceRange.layerCount = 1; pre_present_barrier.subresourceRange.layerCount = 1;
pre_present_barrier.image = window_ctx->swapchain.swapchain_images[window_ctx->swapchain.current_index]; pre_present_barrier.image =
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, window_ctx->swapchain.swapchain_images[window_ctx->swapchain.current_index];
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1,
&pre_present_barrier); &pre_present_barrier);
buffer.end(); buffer.end();
@ -280,19 +302,39 @@ void keyboardEvent(SDL_Event* event) {
if (event->type == SDL_EVENT_KEY_DOWN || event->type == SDL_EVENT_KEY_UP) { if (event->type == SDL_EVENT_KEY_DOWN || event->type == SDL_EVENT_KEY_UP) {
u32 button = 0; u32 button = 0;
switch (event->key.keysym.sym) { switch (event->key.keysym.sym) {
case SDLK_UP: button = ScePadButton::UP; break; case SDLK_UP:
case SDLK_DOWN: button = ScePadButton::DOWN; break; button = ScePadButton::UP;
case SDLK_LEFT: button = ScePadButton::LEFT; break; break;
case SDLK_RIGHT: button = ScePadButton::RIGHT; break; case SDLK_DOWN:
case SDLK_KP_8: button = ScePadButton ::TRIANGLE; break; button = ScePadButton::DOWN;
case SDLK_KP_6: button = ScePadButton ::CIRCLE; break; break;
case SDLK_KP_2: button = ScePadButton ::CROSS; break; case SDLK_LEFT:
case SDLK_KP_4: button = ScePadButton ::SQUARE; break; button = ScePadButton::LEFT;
case SDLK_RETURN: button = ScePadButton ::OPTIONS; break; break;
default: break; case SDLK_RIGHT:
button = ScePadButton::RIGHT;
break;
case SDLK_KP_8:
button = ScePadButton ::TRIANGLE;
break;
case SDLK_KP_6:
button = ScePadButton ::CIRCLE;
break;
case SDLK_KP_2:
button = ScePadButton ::CROSS;
break;
case SDLK_KP_4:
button = ScePadButton ::SQUARE;
break;
case SDLK_RETURN:
button = ScePadButton ::OPTIONS;
break;
default:
break;
} }
if (button != 0) { if (button != 0) {
auto* controller = Common::Singleton<Emulator::Host::Controller::GameController>::Instance(); auto* controller =
Common::Singleton<Emulator::Host::Controller::GameController>::Instance();
controller->checKButton(0, button, event->type == SDL_EVENT_KEY_DOWN); controller->checKButton(0, button, event->type == SDL_EVENT_KEY_DOWN);
} }
} }

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#include <core/PS4/HLE/Graphics/graphics_ctx.h>
#include <SDL.h> #include <SDL.h>
#include <core/PS4/HLE/Graphics/graphics_ctx.h>
#include <mutex>
#include <condition_variable> #include <condition_variable>
#include <mutex>
#include <vector> #include <vector>
namespace Emu { namespace Emu {
@ -85,4 +85,4 @@ void checkAndWaitForGraphicsInit();
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx(); HLE::Libs::Graphics::GraphicCtx* getGraphicCtx();
void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image); void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image);
void keyboardEvent(SDL_Event* event); void keyboardEvent(SDL_Event* event);
} // namespace Emulator } // namespace Emu

View File

@ -6,17 +6,17 @@
#include <cstdio> #include <cstdio>
#include <thread> #include <thread>
#include <core/hle/libraries/libkernel/thread_management.h>
#include "Util/config.h" #include "Util/config.h"
#include "common/discord.h" #include "common/discord.h"
#include "common/log.h" #include "common/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "common/types.h" #include "common/types.h"
#include "core/PS4/HLE/Graphics/video_out.h" #include "core/PS4/HLE/Graphics/video_out.h"
#include "core/file_sys/fs.h"
#include "core/hle/libraries/libs.h" #include "core/hle/libraries/libs.h"
#include "core/linker.h" #include "core/linker.h"
#include "emulator.h" #include "emulator.h"
#include <core/hle/libraries/libkernel/thread_management.h>
#include "core/file_sys/fs.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc == 1) { if (argc == 1) {
@ -41,7 +41,8 @@ int main(int argc, char* argv[]) {
auto linker = Common::Singleton<Core::Linker>::Instance(); auto linker = Common::Singleton<Core::Linker>::Instance();
Core::Libraries::InitHLELibs(&linker->getHLESymbols()); Core::Libraries::InitHLELibs(&linker->getHLESymbols());
linker->LoadModule(path); linker->LoadModule(path);
std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); }, nullptr); std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); },
nullptr);
Discord::RPC discordRPC; Discord::RPC discordRPC;
discordRPC.init(); discordRPC.init();
discordRPC.update(Discord::RPCStatus::Idling, ""); discordRPC.update(Discord::RPCStatus::Idling, "");

View File

@ -1,10 +1,11 @@
#include "gpu_memory.h"
#include <atomic> #include <atomic>
#include <xxh3.h> #include <xxh3.h>
#include "gpu_memory.h"
#include "common/singleton.h" #include "common/singleton.h"
void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size, void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size,
const GPUObject& info) { const GPUObject& info) {
auto* gpumemory = Common::Singleton<GPUMemory>::Instance(); auto* gpumemory = Common::Singleton<GPUMemory>::Instance();
@ -23,9 +24,12 @@ void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) {
gpumemory->m_heaps.push_back(h); gpumemory->m_heaps.push_back(h);
} }
u64 GPU::calculate_hash(const u08* buf, u64 size) { return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0); } u64 GPU::calculate_hash(const u08* buf, u64 size) {
return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0);
}
bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem) { bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx,
HLE::Libs::Graphics::VulkanMemory* mem) {
static std::atomic_uint64_t unique_id = 0; static std::atomic_uint64_t unique_id = 0;
VkPhysicalDeviceMemoryProperties memory_properties{}; VkPhysicalDeviceMemoryProperties memory_properties{};
@ -66,7 +70,8 @@ void GPU::flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx) {
int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) {
int index = 0; int index = 0;
for (const auto& heap : m_heaps) { for (const auto& heap : m_heaps) {
if ((virtual_addr >= heap.allocated_virtual_addr && virtual_addr < heap.allocated_virtual_addr + heap.allocated_size) || if ((virtual_addr >= heap.allocated_virtual_addr &&
virtual_addr < heap.allocated_virtual_addr + heap.allocated_size) ||
((virtual_addr + size - 1) >= heap.allocated_virtual_addr && ((virtual_addr + size - 1) >= heap.allocated_virtual_addr &&
(virtual_addr + size - 1) < heap.allocated_virtual_addr + heap.allocated_size)) { (virtual_addr + size - 1) < heap.allocated_virtual_addr + heap.allocated_size)) {
return index; return index;
@ -76,7 +81,8 @@ int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) {
return -1; return -1;
} }
void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, const u64* virtual_addr, const u64* size, void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
void* todo, const u64* virtual_addr, const u64* size,
int virtual_addr_num, const GPUObject& info) { int virtual_addr_num, const GPUObject& info) {
auto* gpumemory = Common::Singleton<GPUMemory>::Instance(); auto* gpumemory = Common::Singleton<GPUMemory>::Instance();
@ -101,7 +107,8 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
for (int h = 0; h < virtual_addr_num; h++) { for (int h = 0; h < virtual_addr_num; h++) {
if (info.check_hash) { if (info.check_hash) {
objInfo.hash[h] = GPU::calculate_hash(reinterpret_cast<const u08*>(virtual_addr[h]), size[h]); objInfo.hash[h] =
GPU::calculate_hash(reinterpret_cast<const u08*>(virtual_addr[h]), size[h]);
} else { } else {
objInfo.hash[h] = 0; objInfo.hash[h] = 0;
} }
@ -109,7 +116,8 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
objInfo.submit_id = submit_id; objInfo.submit_id = submit_id;
objInfo.check_hash = info.check_hash; objInfo.check_hash = info.check_hash;
objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size, virtual_addr_num, &objInfo.mem); objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size,
virtual_addr_num, &objInfo.mem);
objInfo.update_func = info.getUpdateFunc(); objInfo.update_func = info.getUpdateFunc();
int index = static_cast<int>(heap.objects.size()); int index = static_cast<int>(heap.objects.size());
@ -123,7 +131,8 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
return objInfo.gpu_object.obj; return objInfo.gpu_object.obj;
} }
GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id) { GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u64* size,
int virtual_addr_num, int heap_id, int obj_id) {
auto& heap = m_heaps[heap_id]; auto& heap = m_heaps[heap_id];
GPU::HeapBlock heapBlock{}; GPU::HeapBlock heapBlock{};
@ -135,7 +144,8 @@ GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u6
return heapBlock; return heapBlock;
} }
void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id) { void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id,
int obj_id) {
auto& heap = m_heaps[heap_id]; auto& heap = m_heaps[heap_id];
auto& heapObj = heap.objects[obj_id]; auto& heapObj = heap.objects[obj_id];
@ -147,7 +157,9 @@ void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
for (int i = 0; i < heapObj.block.virtual_addr_num; i++) { for (int i = 0; i < heapObj.block.virtual_addr_num; i++) {
if (objInfo.check_hash) { if (objInfo.check_hash) {
hash[i] = GPU::calculate_hash(reinterpret_cast<const uint8_t*>(heapObj.block.virtual_addr[i]), heapObj.block.size[i]); hash[i] = GPU::calculate_hash(
reinterpret_cast<const uint8_t*>(heapObj.block.virtual_addr[i]),
heapObj.block.size[i]);
} else { } else {
hash[i] = 0; hash[i] = 0;
} }
@ -166,7 +178,8 @@ void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
} }
if (need_update) { if (need_update) {
objInfo.update_func(ctx, objInfo.obj_params, objInfo.gpu_object.obj, heapObj.block.virtual_addr, heapObj.block.size, objInfo.update_func(ctx, objInfo.obj_params, objInfo.gpu_object.obj,
heapObj.block.virtual_addr, heapObj.block.size,
heapObj.block.virtual_addr_num); heapObj.block.virtual_addr_num);
} }
} }

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "common/types.h"
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include "common/types.h"
namespace VideoCore { namespace VideoCore {
@ -65,9 +65,11 @@ public:
GPUMemory() {} GPUMemory() {}
virtual ~GPUMemory() {} virtual ~GPUMemory() {}
int getHeapId(u64 vaddr, u64 size); int getHeapId(u64 vaddr, u64 size);
void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
/*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr,
const u64* size, int virtual_addr_num, const GPUObject& info); const u64* size, int virtual_addr_num, const GPUObject& info);
HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num,
int heap_id, int obj_id);
void update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id); void update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id);
void flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx); void flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx);
@ -77,10 +79,12 @@ private:
}; };
void memorySetAllocArea(u64 virtual_addr, u64 size); void memorySetAllocArea(u64 virtual_addr, u64 size);
void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
/*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size,
const GPUObject& info); const GPUObject& info);
u64 calculate_hash(const u08* buf, u64 size); u64 calculate_hash(const u08* buf, u64 size);
bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem); bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx,
HLE::Libs::Graphics::VulkanMemory* mem);
void flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx); void flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx);
} // namespace VideoCore } // namespace VideoCore

View File

@ -5,7 +5,7 @@
namespace VideoCore { namespace VideoCore {
class TileManager32 { class TileManager32 {
public: public:
u32 m_macro_tile_height = 0; u32 m_macro_tile_height = 0;
u32 m_bank_height = 0; u32 m_bank_height = 0;
u32 m_num_banks = 0; u32 m_num_banks = 0;
@ -60,7 +60,8 @@ class TileManager32 {
return pipe; return pipe;
} }
static u32 GetBankIndex(u32 x, u32 y, u32 bank_width, u32 bank_height, u32 num_banks, u32 num_pipes) { static u32 GetBankIndex(u32 x, u32 y, u32 bank_width, u32 bank_height, u32 num_banks,
u32 num_pipes) {
const u32 x_shift_offset = std::bit_width(bank_width * num_pipes); const u32 x_shift_offset = std::bit_width(bank_width * num_pipes);
const u32 y_shift_offset = std::bit_width(bank_height); const u32 y_shift_offset = std::bit_width(bank_height);
const u32 xs = x >> x_shift_offset; const u32 xs = x >> x_shift_offset;
@ -101,11 +102,13 @@ class TileManager32 {
tile_bytes = 512; tile_bytes = 512;
} }
u64 macro_tile_bytes = (128 / 8) * (m_macro_tile_height / 8) * tile_bytes / (m_num_pipes * m_num_banks); u64 macro_tile_bytes =
(128 / 8) * (m_macro_tile_height / 8) * tile_bytes / (m_num_pipes * m_num_banks);
u64 macro_tiles_per_row = m_padded_width / 128; u64 macro_tiles_per_row = m_padded_width / 128;
u64 macro_tile_row_index = y / m_macro_tile_height; u64 macro_tile_row_index = y / m_macro_tile_height;
u64 macro_tile_column_index = x / 128; u64 macro_tile_column_index = x / 128;
u64 macro_tile_index = (macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index; u64 macro_tile_index =
(macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index;
u64 macro_tile_offset = macro_tile_index * macro_tile_bytes; u64 macro_tile_offset = macro_tile_index * macro_tile_bytes;
u64 macro_tiles_per_slice = macro_tiles_per_row * (m_padded_height / m_macro_tile_height); u64 macro_tiles_per_slice = macro_tiles_per_row * (m_padded_height / m_macro_tile_height);
u64 slice_bytes = macro_tiles_per_slice * macro_tile_bytes; u64 slice_bytes = macro_tiles_per_slice * macro_tile_bytes;
@ -124,13 +127,14 @@ class TileManager32 {
u64 pipe_interleave_offset = total_offset & 0xffu; u64 pipe_interleave_offset = total_offset & 0xffu;
u64 offset = total_offset >> 8u; u64 offset = total_offset >> 8u;
u64 byte_offset = pipe_interleave_offset | (pipe << (8u)) | (bank << (8u + m_pipe_bits)) | (offset << (8u + m_pipe_bits + m_bank_bits)); u64 byte_offset = pipe_interleave_offset | (pipe << (8u)) | (bank << (8u + m_pipe_bits)) |
(offset << (8u + m_pipe_bits + m_bank_bits));
return ((byte_offset << 3u) | bit_offset) / 8; return ((byte_offset << 3u) | bit_offset) / 8;
} }
}; };
void ConvertTileToLinear(u08* dst, const u08* src,u32 width, u32 height, bool is_neo) { void ConvertTileToLinear(u08* dst, const u08* src, u32 width, u32 height, bool is_neo) {
const TileManager32 t{width, height, is_neo}; const TileManager32 t{width, height, is_neo};
for (u32 y = 0; y < height; y++) { for (u32 y = 0; y < height; y++) {
u32 x = 0; u32 x = 0;

View File

@ -1,12 +1,12 @@
#include "vulkan_util.h"
#include <fmt/core.h>
#include <core/PS4/GPU/gpu_memory.h>
#include <SDL_vulkan.h> #include <SDL_vulkan.h>
#include "common/singleton.h" #include <core/PS4/GPU/gpu_memory.h>
#include "common/log.h" #include <fmt/core.h>
#include "common/debug.h"
#include <vulkan/vk_enum_string_helper.h> #include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "common/debug.h"
#include "common/log.h"
#include "common/singleton.h"
#include "vulkan_util.h"
#include <algorithm> #include <algorithm>
@ -44,18 +44,21 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) {
std::exit(0); std::exit(0);
} }
if (SDL_Vulkan_CreateSurface(ctx->m_window, ctx->m_graphic_ctx.m_instance, &ctx->m_surface) == SDL_FALSE) { if (SDL_Vulkan_CreateSurface(ctx->m_window, ctx->m_graphic_ctx.m_instance, &ctx->m_surface) ==
SDL_FALSE) {
LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan surface\n"); LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan surface\n");
std::exit(0); std::exit(0);
} }
// TODO i am not sure if it's that it is neccesary or if it needs more // TODO i am not sure if it's that it is neccesary or if it needs more
std::vector<const char*> device_extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, std::vector<const char*> device_extensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME,
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME, "VK_KHR_maintenance1"}; VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME, "VK_KHR_maintenance1"};
Emu::VulkanQueues queues; Emu::VulkanQueues queues;
vulkanFindCompatiblePhysicalDevice(ctx->m_graphic_ctx.m_instance, ctx->m_surface, device_extensions, &ctx->m_surface_capabilities, vulkanFindCompatiblePhysicalDevice(ctx->m_graphic_ctx.m_instance, ctx->m_surface,
device_extensions, &ctx->m_surface_capabilities,
&ctx->m_graphic_ctx.m_physical_device, &queues); &ctx->m_graphic_ctx.m_physical_device, &queues);
if (ctx->m_graphic_ctx.m_physical_device == nullptr) { if (ctx->m_graphic_ctx.m_physical_device == nullptr) {
@ -68,7 +71,8 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) {
LOG_INFO_IF(log_file_vulkanutil, "GFX device to be used : {}\n", device_properties.deviceName); LOG_INFO_IF(log_file_vulkanutil, "GFX device to be used : {}\n", device_properties.deviceName);
ctx->m_graphic_ctx.m_device = vulkanCreateDevice(ctx->m_graphic_ctx.m_physical_device, ctx->m_surface, &ext, queues, device_extensions); ctx->m_graphic_ctx.m_device = vulkanCreateDevice(
ctx->m_graphic_ctx.m_physical_device, ctx->m_surface, &ext, queues, device_extensions);
if (ctx->m_graphic_ctx.m_device == nullptr) { if (ctx->m_graphic_ctx.m_device == nullptr) {
LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan device\n"); LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan device\n");
std::exit(0); std::exit(0);
@ -78,7 +82,8 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) {
ctx->swapchain = vulkanCreateSwapchain(&ctx->m_graphic_ctx, 2); ctx->swapchain = vulkanCreateSwapchain(&ctx->m_graphic_ctx, 2);
} }
Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) { Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx,
u32 image_count) {
auto window_ctx = Common::Singleton<Emu::WindowCtx>::Instance(); auto window_ctx = Common::Singleton<Emu::WindowCtx>::Instance();
const auto& capabilities = window_ctx->m_surface_capabilities.capabilities; const auto& capabilities = window_ctx->m_surface_capabilities.capabilities;
Emu::VulkanSwapchain s{}; Emu::VulkanSwapchain s{};
@ -128,7 +133,8 @@ Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics
vkGetSwapchainImagesKHR(ctx->m_device, s.swapchain, &s.swapchain_images_count, nullptr); vkGetSwapchainImagesKHR(ctx->m_device, s.swapchain, &s.swapchain_images_count, nullptr);
s.swapchain_images.resize(s.swapchain_images_count); s.swapchain_images.resize(s.swapchain_images_count);
vkGetSwapchainImagesKHR(ctx->m_device, s.swapchain, &s.swapchain_images_count, s.swapchain_images.data()); vkGetSwapchainImagesKHR(ctx->m_device, s.swapchain, &s.swapchain_images_count,
s.swapchain_images.data());
s.swapchain_image_views.resize(s.swapchain_images_count); s.swapchain_image_views.resize(s.swapchain_images_count);
for (uint32_t i = 0; i < s.swapchain_images_count; i++) { for (uint32_t i = 0; i < s.swapchain_images_count; i++) {
@ -163,7 +169,8 @@ Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics
present_complete_info.pNext = nullptr; present_complete_info.pNext = nullptr;
present_complete_info.flags = 0; present_complete_info.flags = 0;
auto result = vkCreateSemaphore(ctx->m_device, &present_complete_info, nullptr, &s.present_complete_semaphore); auto result = vkCreateSemaphore(ctx->m_device, &present_complete_info, nullptr,
&s.present_complete_semaphore);
VkFenceCreateInfo fence_info{}; VkFenceCreateInfo fence_info{};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
@ -179,11 +186,13 @@ Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics
return s; return s;
} }
void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emu::VulkanQueues& queues) { void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx,
const Emu::VulkanQueues& queues) {
auto get_queue = [ctx](int id, const Emu::VulkanQueueInfo& info, bool with_mutex = false) { auto get_queue = [ctx](int id, const Emu::VulkanQueueInfo& info, bool with_mutex = false) {
ctx->queues[id].family = info.family; ctx->queues[id].family = info.family;
ctx->queues[id].index = info.index; ctx->queues[id].index = info.index;
vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue); vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index,
&ctx->queues[id].vk_queue);
if (with_mutex) { if (with_mutex) {
ctx->queues[id].mutex = std::make_unique<std::mutex>(); ctx->queues[id].mutex = std::make_unique<std::mutex>();
} }
@ -199,8 +208,10 @@ void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx,
} }
} }
VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const Emu::VulkanExt* r, VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device,
const Emu::VulkanQueues& queues, const std::vector<const char*>& device_extensions) { VkSurfaceKHR surface, const Emu::VulkanExt* r,
const Emu::VulkanQueues& queues,
const std::vector<const char*>& device_extensions) {
std::vector<VkDeviceQueueCreateInfo> queue_create_info(queues.family_count); std::vector<VkDeviceQueueCreateInfo> queue_create_info(queues.family_count);
std::vector<std::vector<float>> queue_priority(queues.family_count); std::vector<std::vector<float>> queue_priority(queues.family_count);
uint32_t queue_create_info_num = 0; uint32_t queue_create_info_num = 0;
@ -211,12 +222,14 @@ VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device,
queue_priority[queue_create_info_num].push_back(1.0f); queue_priority[queue_create_info_num].push_back(1.0f);
} }
queue_create_info[queue_create_info_num].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_create_info[queue_create_info_num].sType =
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info[queue_create_info_num].pNext = nullptr; queue_create_info[queue_create_info_num].pNext = nullptr;
queue_create_info[queue_create_info_num].flags = 0; queue_create_info[queue_create_info_num].flags = 0;
queue_create_info[queue_create_info_num].queueFamilyIndex = i; queue_create_info[queue_create_info_num].queueFamilyIndex = i;
queue_create_info[queue_create_info_num].queueCount = queues.family_used[i]; queue_create_info[queue_create_info_num].queueCount = queues.family_used[i];
queue_create_info[queue_create_info_num].pQueuePriorities = queue_priority[queue_create_info_num].data(); queue_create_info[queue_create_info_num].pQueuePriorities =
queue_priority[queue_create_info_num].data();
queue_create_info_num++; queue_create_info_num++;
} }
@ -251,13 +264,15 @@ void Graphics::Vulkan::vulkanGetInstanceExtensions(Emu::VulkanExt* ext) {
ext->required_extensions = std::vector<const char*>(required_extensions_count); ext->required_extensions = std::vector<const char*>(required_extensions_count);
result = SDL_Vulkan_GetInstanceExtensions(&required_extensions_count, ext->required_extensions.data()); result = SDL_Vulkan_GetInstanceExtensions(&required_extensions_count,
ext->required_extensions.data());
vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, nullptr); vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, nullptr);
ext->available_extensions = std::vector<VkExtensionProperties>(available_extensions_count); ext->available_extensions = std::vector<VkExtensionProperties>(available_extensions_count);
vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, ext->available_extensions.data()); vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count,
ext->available_extensions.data());
vkEnumerateInstanceLayerProperties(&available_layers_count, nullptr); vkEnumerateInstanceLayerProperties(&available_layers_count, nullptr);
ext->available_layers = std::vector<VkLayerProperties>(available_layers_count); ext->available_layers = std::vector<VkLayerProperties>(available_layers_count);
@ -268,17 +283,19 @@ void Graphics::Vulkan::vulkanGetInstanceExtensions(Emu::VulkanExt* ext) {
} }
for (const auto& ext : ext->available_extensions) { for (const auto& ext : ext->available_extensions) {
LOG_INFO_IF(log_file_vulkanutil, "Vulkan available extension: {}, version = {}\n", ext.extensionName, ext.specVersion); LOG_INFO_IF(log_file_vulkanutil, "Vulkan available extension: {}, version = {}\n",
ext.extensionName, ext.specVersion);
} }
for (const auto& l : ext->available_layers) { for (const auto& l : ext->available_layers) {
LOG_INFO_IF(log_file_vulkanutil, "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}\n", l.layerName, l.specVersion, LOG_INFO_IF(log_file_vulkanutil,
l.implementationVersion, l.description); "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}\n",
l.layerName, l.specVersion, l.implementationVersion, l.description);
} }
} }
void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(
const std::vector<const char*>& device_extensions, VkInstance instance, VkSurfaceKHR surface, const std::vector<const char*>& device_extensions,
Emu::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, Emu::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device,
Emu::VulkanQueues* out_queues) { Emu::VulkanQueues* out_queues) {
u32 count_devices = 0; u32 count_devices = 0;
@ -297,7 +314,8 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V
vkGetPhysicalDeviceProperties(device, &device_properties); vkGetPhysicalDeviceProperties(device, &device_properties);
vkGetPhysicalDeviceFeatures2(device, &device_features2); vkGetPhysicalDeviceFeatures2(device, &device_features2);
if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) { if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
continue; // we don't want integrated gpu for now .Later we will check the requirements and see what we can support (TODO fix me) continue; // we don't want integrated gpu for now .Later we will check the requirements
// and see what we can support (TODO fix me)
} }
LOG_INFO_IF(log_file_vulkanutil, "Vulkan device: {}\n", device_properties.deviceName); LOG_INFO_IF(log_file_vulkanutil, "Vulkan device: {}\n", device_properties.deviceName);
@ -312,7 +330,8 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V
*out_queues = found_best_queues; *out_queues = found_best_queues;
} }
Emu::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface) { Emu::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device,
VkSurfaceKHR surface) {
Emu::VulkanQueues qs; Emu::VulkanQueues qs;
u32 queue_family_count = 0; u32 queue_family_count = 0;
@ -327,7 +346,8 @@ Emu::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, Vk
VkBool32 presentation_supported = VK_FALSE; VkBool32 presentation_supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported); vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported);
LOG_INFO_IF(log_file_vulkanutil, "queue family: {}, count = {}, present = {}\n", string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount, LOG_INFO_IF(log_file_vulkanutil, "queue family: {}, count = {}, present = {}\n",
string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount,
(presentation_supported == VK_TRUE ? "true" : "false")); (presentation_supported == VK_TRUE ? "true" : "false"));
for (uint32_t i = 0; i < f.queueCount; i++) { for (uint32_t i = 0; i < f.queueCount; i++) {
Emu::VulkanQueueInfo info; Emu::VulkanQueueInfo info;
@ -396,7 +416,8 @@ Emu::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, Vk
return qs; return qs;
} }
void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device,
VkSurfaceKHR surface,
Emu::VulkanSurfaceCapabilities* surfaceCap) { Emu::VulkanSurfaceCapabilities* surfaceCap) {
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surfaceCap->capabilities); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surfaceCap->capabilities);
@ -404,28 +425,34 @@ void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_de
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, nullptr); vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, nullptr);
surfaceCap->formats = std::vector<VkSurfaceFormatKHR>(formats_count); surfaceCap->formats = std::vector<VkSurfaceFormatKHR>(formats_count);
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, surfaceCap->formats.data()); vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count,
surfaceCap->formats.data());
uint32_t present_modes_count = 0; uint32_t present_modes_count = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, nullptr); vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count,
nullptr);
surfaceCap->present_modes = std::vector<VkPresentModeKHR>(present_modes_count); surfaceCap->present_modes = std::vector<VkPresentModeKHR>(present_modes_count);
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, surfaceCap->present_modes.data()); vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count,
surfaceCap->present_modes.data());
for (const auto& f : surfaceCap->formats) { for (const auto& f : surfaceCap->formats) {
if (f.format == VK_FORMAT_B8G8R8A8_SRGB && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { if (f.format == VK_FORMAT_B8G8R8A8_SRGB &&
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
surfaceCap->is_format_srgb_bgra32 = true; surfaceCap->is_format_srgb_bgra32 = true;
break; break;
} }
if (f.format == VK_FORMAT_B8G8R8A8_UNORM && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { if (f.format == VK_FORMAT_B8G8R8A8_UNORM &&
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
surfaceCap->is_format_unorm_bgra32 = true; surfaceCap->is_format_unorm_bgra32 = true;
break; break;
} }
} }
} }
static void set_image_layout(VkCommandBuffer buffer, HLE::Libs::Graphics::VulkanImage* dst_image, uint32_t base_level, uint32_t levels, static void set_image_layout(VkCommandBuffer buffer, HLE::Libs::Graphics::VulkanImage* dst_image,
VkImageAspectFlags aspect_mask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) { uint32_t base_level, uint32_t levels, VkImageAspectFlags aspect_mask,
VkImageLayout old_image_layout, VkImageLayout new_image_layout) {
VkImageMemoryBarrier imageMemoryBarrier{}; VkImageMemoryBarrier imageMemoryBarrier{};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.pNext = nullptr; imageMemoryBarrier.pNext = nullptr;
@ -478,12 +505,14 @@ static void set_image_layout(VkCommandBuffer buffer, HLE::Libs::Graphics::Vulkan
VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
vkCmdPipelineBarrier(buffer, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); vkCmdPipelineBarrier(buffer, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1,
&imageMemoryBarrier);
dst_image->layout = new_image_layout; dst_image->layout = new_image_layout;
} }
void Graphics::Vulkan::vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image, void Graphics::Vulkan::vulkanBlitImage(GPU::CommandBuffer* buffer,
HLE::Libs::Graphics::VulkanImage* src_image,
Emu::VulkanSwapchain* dst_swapchain) { Emu::VulkanSwapchain* dst_swapchain) {
auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()]; auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()];
@ -492,9 +521,11 @@ void Graphics::Vulkan::vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Gr
swapchain_image.image = dst_swapchain->swapchain_images[dst_swapchain->current_index]; swapchain_image.image = dst_swapchain->swapchain_images[dst_swapchain->current_index];
swapchain_image.layout = VK_IMAGE_LAYOUT_UNDEFINED; swapchain_image.layout = VK_IMAGE_LAYOUT_UNDEFINED;
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
set_image_layout(vk_buffer, &swapchain_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); set_image_layout(vk_buffer, &swapchain_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkImageBlit region{}; VkImageBlit region{};
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@ -518,22 +549,28 @@ void Graphics::Vulkan::vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Gr
region.dstOffsets[1].y = static_cast<int>(dst_swapchain->swapchain_extent.height); region.dstOffsets[1].y = static_cast<int>(dst_swapchain->swapchain_extent.height);
region.dstOffsets[1].z = 1; region.dstOffsets[1].z = 1;
vkCmdBlitImage(vk_buffer, src_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapchain_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, vkCmdBlitImage(vk_buffer, src_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
&region, VK_FILTER_LINEAR); swapchain_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region,
VK_FILTER_LINEAR);
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
} }
void Graphics::Vulkan::vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data, void Graphics::Vulkan::vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx,
u64 size, u32 src_pitch, u64 dst_layout) { HLE::Libs::Graphics::VulkanImage* dst_image,
const void* src_data, u64 size, u32 src_pitch,
u64 dst_layout) {
HLE::Libs::Graphics::VulkanBuffer staging_buffer{}; HLE::Libs::Graphics::VulkanBuffer staging_buffer{};
staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; staging_buffer.memory.property =
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
vulkanCreateBuffer(ctx, size, &staging_buffer); vulkanCreateBuffer(ctx, size, &staging_buffer);
void* data = nullptr; void* data = nullptr;
vkMapMemory(ctx->m_device, staging_buffer.memory.memory, staging_buffer.memory.offset, staging_buffer.memory.requirements.size, 0, &data); vkMapMemory(ctx->m_device, staging_buffer.memory.memory, staging_buffer.memory.offset,
staging_buffer.memory.requirements.size, 0, &data);
std::memcpy(data, src_data, size); std::memcpy(data, src_data, size);
vkUnmapMemory(ctx->m_device, staging_buffer.memory.memory); vkUnmapMemory(ctx->m_device, staging_buffer.memory.memory);
@ -548,11 +585,15 @@ void Graphics::Vulkan::vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE
vulkanDeleteBuffer(ctx, &staging_buffer); vulkanDeleteBuffer(ctx, &staging_buffer);
} }
void Graphics::Vulkan::vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer, u32 src_pitch, void Graphics::Vulkan::vulkanBufferToImage(GPU::CommandBuffer* buffer,
HLE::Libs::Graphics::VulkanImage* dst_image, u64 dst_layout) { HLE::Libs::Graphics::VulkanBuffer* src_buffer,
u32 src_pitch,
HLE::Libs::Graphics::VulkanImage* dst_image,
u64 dst_layout) {
auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()]; auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()];
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkBufferImageCopy region{}; VkBufferImageCopy region{};
region.bufferOffset = 0; region.bufferOffset = 0;
@ -567,13 +608,15 @@ void Graphics::Vulkan::vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs
region.imageOffset = {0, 0, 0}; region.imageOffset = {0, 0, 0};
region.imageExtent = {dst_image->extent.width, dst_image->extent.height, 1}; region.imageExtent = {dst_image->extent.width, dst_image->extent.height, 1};
vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
static_cast<VkImageLayout>(dst_layout)); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<VkImageLayout>(dst_layout));
} }
void Graphics::Vulkan::vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size, HLE::Libs::Graphics::VulkanBuffer* buffer) { void Graphics::Vulkan::vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size,
HLE::Libs::Graphics::VulkanBuffer* buffer) {
VkBufferCreateInfo buffer_info{}; VkBufferCreateInfo buffer_info{};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size; buffer_info.size = size;
@ -592,7 +635,8 @@ void Graphics::Vulkan::vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx,
vkBindBufferMemory(ctx->m_device, buffer->buffer, buffer->memory.memory, buffer->memory.offset); vkBindBufferMemory(ctx->m_device, buffer->buffer, buffer->memory.memory, buffer->memory.offset);
} }
void Graphics::Vulkan::vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanBuffer* buffer) { void Graphics::Vulkan::vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx,
HLE::Libs::Graphics::VulkanBuffer* buffer) {
vkDestroyBuffer(ctx->m_device, buffer->buffer, nullptr); vkDestroyBuffer(ctx->m_device, buffer->buffer, nullptr);
vkFreeMemory(ctx->m_device, buffer->memory.memory, nullptr); vkFreeMemory(ctx->m_device, buffer->memory.memory, nullptr);
buffer->memory.memory = nullptr; buffer->memory.memory = nullptr;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <core/PS4/HLE/Graphics/graphics_render.h>
#include <SDL.h> #include <SDL.h>
#include <core/PS4/HLE/Graphics/graphics_render.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include <vector> #include <vector>
@ -21,20 +21,29 @@ constexpr int VULKAN_QUEUE_PRESENT = 10;
void vulkanCreate(Emu::WindowCtx* ctx); void vulkanCreate(Emu::WindowCtx* ctx);
void vulkanGetInstanceExtensions(Emu::VulkanExt* ext); void vulkanGetInstanceExtensions(Emu::VulkanExt* ext);
void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector<const char*>& device_extensions, void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
Emu::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, const std::vector<const char*>& device_extensions,
Emu::VulkanSurfaceCapabilities* out_capabilities,
VkPhysicalDevice* out_device,
Emu::VulkanQueues* out_queues); Emu::VulkanQueues* out_queues);
VkDevice vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const Emu::VulkanExt* r, VkDevice vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
const Emu::VulkanQueues& queues, const std::vector<const char*>& device_extensions); const Emu::VulkanExt* r, const Emu::VulkanQueues& queues,
const std::vector<const char*>& device_extensions);
Emu::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); Emu::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface);
void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emu::VulkanSurfaceCapabilities* surfaceCap); void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
Emu::VulkanSurfaceCapabilities* surfaceCap);
void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emu::VulkanQueues& queues); void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emu::VulkanQueues& queues);
Emu::VulkanSwapchain vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count); Emu::VulkanSwapchain vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count);
void vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image, Emu::VulkanSwapchain* dst_swapchain); void vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image,
void vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data, u64 size, u32 src_pitch, Emu::VulkanSwapchain* dst_swapchain);
void vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx,
HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data, u64 size,
u32 src_pitch, u64 dst_layout);
void vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer,
u32 src_pitch, HLE::Libs::Graphics::VulkanImage* dst_image,
u64 dst_layout); u64 dst_layout);
void vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer, u32 src_pitch, void vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size,
HLE::Libs::Graphics::VulkanImage* dst_image, u64 dst_layout); HLE::Libs::Graphics::VulkanBuffer* buffer);
void vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size, HLE::Libs::Graphics::VulkanBuffer* buffer); void vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx,
void vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanBuffer* buffer); HLE::Libs::Graphics::VulkanBuffer* buffer);
}; // namespace Graphics::Vulkan }; // namespace Graphics::Vulkan