From 4dd2e4cf1f030d654c36cf5911a03529b5674d4f Mon Sep 17 00:00:00 2001
From: Stefanos Kornilios Mitsis Poiitidis <skmp@nilware.io>
Date: Thu, 12 Sep 2024 02:26:12 +0300
Subject: [PATCH] initial hacks for hex-core osx

---
 .gitmodules              |   3 ++
 CMakeLists.txt           |   1 +
 externals/CMakeLists.txt |   5 ++
 externals/hex-emu        |   1 +
 src/core/linker.cpp      | 109 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 119 insertions(+)
 create mode 160000 externals/hex-emu

diff --git a/.gitmodules b/.gitmodules
index b2543534..e13b3201 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -93,3 +93,6 @@
 [submodule "externals/pugixml"]
 	path = externals/pugixml
 	url = https://github.com/zeux/pugixml.git
+[submodule "externals/hex-emu"]
+	path = externals/hex-emu
+	url = git@gitlab.com:hex-emu/hex-emu.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9101af9d..c216980a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -693,6 +693,7 @@ create_target_directory_groups(shadps4)
 
 target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui)
 target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3 pugixml::pugixml)
+target_link_libraries(shadps4 PRIVATE hex-core)
 
 target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
 target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 5410f37e..e6971d3c 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -182,4 +182,9 @@ add_subdirectory(tracy)
 # pugixml
 if (NOT TARGET pugixml::pugixml)
     add_subdirectory(pugixml)
+endif()
+
+# Zydis
+if (NOT TARGET hex-emu::hex-core)
+    add_subdirectory(hex-emu/hex-core)
 endif()
\ No newline at end of file
diff --git a/externals/hex-emu b/externals/hex-emu
new file mode 160000
index 00000000..0e5a75a7
--- /dev/null
+++ b/externals/hex-emu
@@ -0,0 +1 @@
+Subproject commit 0e5a75a7f428d4cb58c44c3ec4c007b60de04dc7
diff --git a/src/core/linker.cpp b/src/core/linker.cpp
index e8aab673..bcc193d2 100644
--- a/src/core/linker.cpp
+++ b/src/core/linker.cpp
@@ -19,6 +19,18 @@
 #include "core/tls.h"
 #include "core/virtual_memory.h"
 
+#include <unistd.h>
+#include <fcntl.h>
+#include "Config/Config.h"
+#include "Config/ConfigLoader.h"
+
+#include "Common/Paths.h"
+
+#include "GuestCPU/Context/Context.h"
+#include "GuestCPU/Context/GuestState.h"
+#include "GuestCPU/Translator/Decoder/X86Tables/X86Tables.h"
+#include "GuestCPU/Translator/OpcodeDispatcher/OpcodeDispatcher.h"
+
 namespace Core {
 
 using ExitFunc = PS4_SYSV_ABI void (*)();
@@ -27,6 +39,57 @@ static PS4_SYSV_ABI void ProgramExitFunc() {
     fmt::print("exit function called\n");
 }
 
+static void InitializeStaticTables(FEXCore::Context::OperatingMode Mode) {
+  FEXCore::X86Tables::InitializeInfoTables(Mode);
+  FEXCore::IR::InstallOpcodeHandlers(Mode);
+}
+
+static int OutputFD {2};
+
+void MsgHandler(LogMan::DebugLevels Level, char const *Message) {
+
+  const char *CharLevel{nullptr};
+
+  switch (Level) {
+  case LogMan::NONE:
+    CharLevel = "NONE";
+    break;
+  case LogMan::ASSERT:
+    CharLevel = "ASSERT";
+    break;
+  case LogMan::ERROR:
+    CharLevel = "ERROR";
+    break;
+  case LogMan::DEBUG:
+    CharLevel = "DEBUG";
+    break;
+  case LogMan::INFO:
+    CharLevel = "Info";
+    break;
+  case LogMan::STDOUT:
+    CharLevel = "STDOUT";
+    break;
+  case LogMan::STDERR:
+    CharLevel = "STDERR";
+    break;
+  default:
+    CharLevel = "???";
+    break;
+  }
+
+  const auto Output = fmt::format("[{}] {}\n", CharLevel, Message);
+  write(OutputFD, Output.c_str(), Output.size());
+  fsync(OutputFD);
+}
+
+void AssertHandler(char const *Message) {
+
+
+  const auto Output = fmt::format("[ASSERT] {}\n", Message);
+  write(OutputFD, Output.c_str(), Output.size());
+  fsync(OutputFD);
+}
+
 static void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc exit_func) {
 #ifdef ARCH_X86_64
     // reinterpret_cast<entry_func_t>(addr)(params, exit_func); // can't be used, stack has to have
@@ -49,6 +112,52 @@ static void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc exit_func) {
                  : "r"(addr), "r"(params), "r"(exit_func)
                  : "rax", "rsi", "rdi");
 #else
+  LogMan::Throw::InstallHandler(AssertHandler);
+  LogMan::Msg::InstallHandler(MsgHandler);
+
+FEXCore::Config::Initialize();
+FEXCore::Config::ReloadMetaLayer();
+     FEXCore::Config::Set(FEXCore::Config::CONFIG_IS64BIT_MODE, "1");
+    InitializeStaticTables(FEXCore::Context::MODE_64BIT);
+
+   auto CTX = new FEXCore::Context::Context();
+   CTX->CPUID.Init(CTX);
+
+    //  SyscallHandler->SetCodeLoader(&Loader);
+
+  
+//   CTX->SignalDelegation = SignalDelegation.get();
+
+//   CTX->SyscallHandler = SyscallHandler.get();
+//   CTX->SourcecodeResolver = SyscallHandler->GetSourcecodeResolver();
+  CTX->X86CodeGen.Init(CTX);
+  uintptr_t stack_top = 8 * 1024 * 1024 + (uintptr_t)malloc(8 * 1024 * 1024);
+  FEXCore::Core::InternalThreadState* thread = CTX->InitCore(addr, stack_top);
+
+ {
+        auto& rsp = thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP];
+        auto& rsi = thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSI];
+        auto& rdi = thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RDI];
+
+        rsp = stack_top;
+
+        rsp = rsp & ~16;
+        rsp = rsp - 8;
+
+        for (int i = params->argc; i > 0; i--) {
+            rsp = rsp - 8;
+            *(void**)rsp = &params->argv[i - 1];
+        }
+
+        rsp = rsp - 8;
+        *(u64*)rsp = params->argc;
+
+        rsi = (u64)params;
+        rdi = (u64)exit_func;
+    }
+
+  CTX->RunUntilExit();
+  
     UNIMPLEMENTED_MSG("Missing RunMainEntry() implementation for target CPU architecture.");
 #endif
 }