File xenia-canary_PR198.patch of Package xenia-canary

From 6c471d47987fc9944cf58df230d257d7a07e3842 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Wed, 17 May 2023 17:14:39 +0200
Subject: [PATCH 01/16] Initial linux wip

---
 premake5.lua                                  | 13 +++-
 src/xenia/app/emulator_window.cc              | 17 +++--
 src/xenia/apu/conversion.h                    |  4 +-
 src/xenia/apu/xma_context.cc                  |  4 ++
 src/xenia/base/clock_posix.cc                 |  5 ++
 src/xenia/base/demangle.h                     | 19 ++++++
 src/xenia/base/demangle_posix.cc              | 26 +++++++
 src/xenia/base/demangle_win.cc                | 16 +++++
 src/xenia/base/filesystem_posix.cc            | 59 +++++++++-------
 src/xenia/base/memory.cc                      | 16 ++++-
 src/xenia/base/memory.h                       |  7 ++
 src/xenia/base/memory_posix.cc                | 10 ++-
 src/xenia/base/platform.h                     |  2 +-
 src/xenia/base/platform_amd64.cc              |  1 +
 src/xenia/base/platform_linux.h               | 23 +++++++
 src/xenia/base/premake5.lua                   |  2 +-
 src/xenia/base/string_buffer.cc               | 14 ++--
 src/xenia/base/system_gnulinux.cc             |  2 +-
 src/xenia/base/testing/filesystem_test.cc     | 58 ++++++++++++++++
 src/xenia/base/testing/memory_test.cc         |  2 +-
 src/xenia/base/testing/premake5.lua           |  7 ++
 src/xenia/base/testing/res/test_file          |  1 +
 src/xenia/base/testing/string_test.cc         | 34 ++++++++++
 src/xenia/cpu/backend/x64/x64_backend.cc      | 44 ++++++------
 src/xenia/cpu/backend/x64/x64_emitter.cc      | 50 ++++++++++----
 src/xenia/cpu/backend/x64/x64_emitter.h       | 12 ++++
 src/xenia/cpu/backend/x64/x64_tracers.cc      |  2 +-
 src/xenia/cpu/backend/x64/x64_tracers.h       |  2 +-
 src/xenia/cpu/hir/value.cc                    |  2 +-
 src/xenia/cpu/hir/value.h                     |  1 +
 src/xenia/cpu/ppc/ppc_context.h               |  4 +-
 src/xenia/cpu/ppc/ppc_frontend.cc             |  8 +--
 src/xenia/cpu/ppc/ppc_translator.cc           |  4 ++
 src/xenia/cpu/testing/util.h                  |  1 -
 src/xenia/cpu/xex_module.cc                   |  4 ++
 src/xenia/gpu/command_processor.h             |  4 +-
 src/xenia/gpu/draw_util.cc                    |  7 ++
 src/xenia/gpu/draw_util.h                     |  8 +--
 src/xenia/gpu/pm4_command_processor_declare.h | 68 +++++++++----------
 .../gpu/pm4_command_processor_implement.h     | 66 +++++++++---------
 src/xenia/gpu/register_file.cc                |  1 +
 src/xenia/gpu/shared_memory.cc                |  3 +-
 src/xenia/kernel/achievement_manager.cc       |  6 +-
 src/xenia/kernel/premake5.lua                 |  3 +
 src/xenia/kernel/util/object_table.cc         |  7 +-
 src/xenia/kernel/xam/xam_info.cc              |  2 +
 src/xenia/kernel/xobject.cc                   | 10 +--
 src/xenia/kernel/xsocket.cc                   |  5 ++
 src/xenia/memory.cc                           |  2 +-
 src/xenia/memory.h                            |  2 +-
 src/xenia/ui/imgui_notification.cc            | 24 +++++++
 xenia-build                                   |  5 +-
 52 files changed, 523 insertions(+), 176 deletions(-)
 create mode 100644 src/xenia/base/demangle.h
 create mode 100644 src/xenia/base/demangle_posix.cc
 create mode 100644 src/xenia/base/demangle_win.cc
 create mode 100644 src/xenia/base/testing/filesystem_test.cc
 create mode 100644 src/xenia/base/testing/res/test_file
 create mode 100644 src/xenia/base/testing/string_test.cc

diff --git a/premake5.lua b/premake5.lua
index 71efb4a85d..f547d867cf 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -100,6 +100,10 @@ filter("configurations:Release")
   -- including handling of specials since games make assumptions about them.
 filter("platforms:Linux")
   system("linux")
+-- Ccache seems to randomly break the build process, disable it
+  defines({
+    "CCACHE_DISABLE=1"
+  })
   toolset("clang")
   buildoptions({
     -- "-mlzcnt",  -- (don't) Assume lzcnt is supported.
@@ -135,8 +139,15 @@ filter({"platforms:Linux", "toolset:gcc"})
 
 filter({"platforms:Linux", "language:C++", "toolset:clang"})
   disablewarnings({
-    "deprecated-register"
+    "deprecated-register",
+    "attributes"
+  })
+  removeflags({
+    "FatalWarnings"
   })
+  --buildoptions({
+  --  "-fpermissive"
+  --})
 filter({"platforms:Linux", "language:C++", "toolset:clang", "files:*.cc or *.cpp"})
   buildoptions({
     "-stdlib=libstdc++",
diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc
index 90257d45d0..c4c3e4155c 100644
--- a/src/xenia/app/emulator_window.cc
+++ b/src/xenia/app/emulator_window.cc
@@ -31,7 +31,9 @@
 #include "xenia/cpu/processor.h"
 #include "xenia/emulator.h"
 #include "xenia/gpu/command_processor.h"
+#ifdef XE_PLATFORM_WINDOWS
 #include "xenia/gpu/d3d12/d3d12_command_processor.h"
+#endif
 #include "xenia/gpu/graphics_system.h"
 #include "xenia/hid/input_system.h"
 #include "xenia/ui/file_picker.h"
@@ -1255,11 +1257,12 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
     case ButtonFunctions::ClearMemoryPageState:
       ToggleGPUSetting(gpu_cvar::ClearMemoryPageState);
 
+#ifdef XE_PLATFORM_WINDOWS
       // Assume the user wants ClearCaches as well
       if (cvars::d3d12_clear_memory_page_state) {
         GpuClearCaches();
       }
-
+#endif
       // Extra Sleep
       xe::threading::Sleep(delay);
       break;
@@ -1385,6 +1388,7 @@ void EmulatorWindow::GamepadHotKeys() {
 }
 
 void EmulatorWindow::ToggleGPUSetting(gpu_cvar value) {
+#ifdef XE_PLATFORM_WINDOWS
   switch (value) {
     case gpu_cvar::ClearMemoryPageState:
       D3D12SaveGPUSetting(D3D12GPUSetting::ClearMemoryPageState,
@@ -1395,6 +1399,7 @@ void EmulatorWindow::ToggleGPUSetting(gpu_cvar value) {
                           !cvars::d3d12_readback_resolve);
       break;
   }
+#endif
 }
 
 // Determine if the Xbox Gamebar is enabled via the Windows registry
@@ -1431,7 +1436,11 @@ void EmulatorWindow::DisplayHotKeysConfig() {
     if (!guide_enabled) {
       pretty_text = std::regex_replace(
           pretty_text,
+#ifdef XE_PLATFORM_WINDOWS
           std::regex("Guide", std::regex_constants::syntax_option_type::icase),
+#else
+          std::regex("Guide", std::regex_constants::icase),
+#endif
           "Back");
     }
 
@@ -1457,14 +1466,14 @@ void EmulatorWindow::DisplayHotKeysConfig() {
   msg_passthru += "\n";
   msg.insert(0, msg_passthru);
   msg += "\n";
-
+#ifdef XE_PLATFORM_WINDOWS
   msg += "Readback Resolve: " + BoolToString(cvars::d3d12_readback_resolve);
   msg += "\n";
 
   msg += "Clear Memory Page State: " +
          BoolToString(cvars::d3d12_clear_memory_page_state);
   msg += "\n";
-
+#endif
   msg += "Controller Hotkeys: " + BoolToString(cvars::controller_hotkeys);
 
   imgui_drawer_.get()->ClearDialogs();
@@ -1476,7 +1485,7 @@ xe::X_STATUS EmulatorWindow::RunTitle(std::filesystem::path path_to_file) {
   bool titleExists = !std::filesystem::exists(path_to_file);
 
   if (path_to_file.empty() || titleExists) {
-    char* log_msg = path_to_file.empty()
+    const char* log_msg = path_to_file.empty()
                         ? "Failed to launch title path is empty."
                         : "Failed to launch title path is invalid.";
 
diff --git a/src/xenia/apu/conversion.h b/src/xenia/apu/conversion.h
index 672a6e0c65..7318c54290 100644
--- a/src/xenia/apu/conversion.h
+++ b/src/xenia/apu/conversion.h
@@ -36,8 +36,10 @@ static void _generic_sequential_6_BE_to_interleaved_6_LE(
     }
   }
 }
-#if XE_COMPILER_CLANG_CL != 1
+#if XE_COMPILER_CLANG_CL != 1 && !XE_PLATFORM_LINUX
 // load_be_u32 unavailable on clang-cl
+// TODO(RodoMa92): Reimplement _load_be_u32 with __builtin_bswap32 from
+// GCC, which seems the closest candidate as an equivalent call
 XE_NOINLINE
 static void _movbe_sequential_6_BE_to_interleaved_6_LE(
     float* XE_RESTRICT output, const float* XE_RESTRICT input,
diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc
index a619e8b31e..d6473807e0 100644
--- a/src/xenia/apu/xma_context.cc
+++ b/src/xenia/apu/xma_context.cc
@@ -691,6 +691,10 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) {
       data->output_buffer_write_offset = output_rb.write_offset() / 256;
 
       total_samples += id_ == 0 ? kSamplesPerFrame : 0;
+//FIXME(RodoMa92): Linux errors out with undef ref to kBitsPerHeader, for whatever reason
+#ifdef XE_PLATFORM_LINUX
+      static const uint32_t kBitsPerHeader = 32;
+#endif
 
       uint32_t offset =
           std::max(kBitsPerHeader, data->input_buffer_read_offset);
diff --git a/src/xenia/base/clock_posix.cc b/src/xenia/base/clock_posix.cc
index 73a23dc760..c0ebc2ada9 100644
--- a/src/xenia/base/clock_posix.cc
+++ b/src/xenia/base/clock_posix.cc
@@ -9,6 +9,7 @@
 
 #include <sys/time.h>
 
+#include "platform_linux.h"
 #include "xenia/base/assert.h"
 #include "xenia/base/clock.h"
 
@@ -53,4 +54,8 @@ uint64_t Clock::QueryHostUptimeMillis() {
   return host_tick_count_platform() * 1000 / host_tick_frequency_platform();
 }
 
+uint64_t Clock::QueryHostInterruptTime() {
+  return *reinterpret_cast<uint64_t*>(KUserShared() +
+                                      KUSER_SHARED_INTERRUPTTIME_OFFSET);
+}
 }  // namespace xe
diff --git a/src/xenia/base/demangle.h b/src/xenia/base/demangle.h
new file mode 100644
index 0000000000..6fbdab9a9e
--- /dev/null
+++ b/src/xenia/base/demangle.h
@@ -0,0 +1,19 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project                                 *
+ ******************************************************************************
+ * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#ifndef XENIA_BASE_DEMANGLE_H_
+#define XENIA_BASE_DEMANGLE_H_
+
+#include <string>
+
+namespace xe {
+std::string Demangle(const std::string& mangled_name);
+}
+
+#endif  // XENIA_BASE_DEMANGLE_H_
diff --git a/src/xenia/base/demangle_posix.cc b/src/xenia/base/demangle_posix.cc
new file mode 100644
index 0000000000..4e50e3dbb7
--- /dev/null
+++ b/src/xenia/base/demangle_posix.cc
@@ -0,0 +1,26 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project                                 *
+ ******************************************************************************
+ * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#include "xenia/base/demangle.h"
+
+#include <cxxabi.h>
+#include <memory>
+
+namespace xe {
+
+std::string Demangle(const std::string& mangled_name) {
+  std::size_t len = 0;
+  int status = 0;
+  std::unique_ptr<char, decltype(&std::free)> ptr(
+      __cxxabiv1::__cxa_demangle(mangled_name.c_str(), nullptr, &len, &status),
+      &std::free);
+  return ptr ? std::string("class ") + ptr.get() : "";
+}
+
+}  // namespace xe
diff --git a/src/xenia/base/demangle_win.cc b/src/xenia/base/demangle_win.cc
new file mode 100644
index 0000000000..84a46a437e
--- /dev/null
+++ b/src/xenia/base/demangle_win.cc
@@ -0,0 +1,16 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project                                 *
+ ******************************************************************************
+ * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#include "xenia/base/demangle.h"
+
+namespace xe {
+
+std::string Demangle(const std::string& name) { return name; }
+
+}  // namespace xe
diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc
index 2e9ddb2c5b..34b186a810 100644
--- a/src/xenia/base/filesystem_posix.cc
+++ b/src/xenia/base/filesystem_posix.cc
@@ -9,21 +9,18 @@
 
 #include "xenia/base/assert.h"
 #include "xenia/base/filesystem.h"
-#include "xenia/base/logging.h"
 #include "xenia/base/string.h"
 
-#include <assert.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <ftw.h>
-#include <libgen.h>
 #include <pwd.h>
-#include <stdio.h>
-#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <iostream>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 
 namespace xe {
 
@@ -65,12 +62,12 @@ std::filesystem::path GetUserFolder() {
   home = std::getenv("HOME");
 
   // if HOME not set, fall back to this
-  if (home == NULL) {
+  if (home == nullptr) {
     struct passwd pw1;
     struct passwd* pw;
-    char buf[4096];  // could potentionally lower this
+    char buf[4096];  // could potentially lower this
     getpwuid_r(getuid(), &pw1, buf, sizeof(buf), &pw);
-    assert(&pw1 == pw);  // sanity check
+    assert_true(&pw1 == pw);  // sanity check
     home = pw->pw_dir;
   }
 
@@ -112,13 +109,14 @@ static int removeCallback(const char* fpath, const struct stat* sb,
   return rv;
 }
 
-static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) {
-  // Linux uses number of seconds since 1/1/1970, and Windows uses
+static uint64_t convertUnixtimeToWinFiletime(const timespec& unixtime) {
+  // Linux uses number of nanoseconds since 1/1/1970, and Windows uses
   // number of nanoseconds since 1/1/1601
-  // so we convert linux time to nanoseconds and then add the number of
-  // nanoseconds from 1601 to 1970
+  // so we add the number of nanoseconds from 1601 to 1970
+  // and return in the format of 10ns intervals
   // see https://msdn.microsoft.com/en-us/library/ms724228
-  uint64_t filetime = filetime = (unixtime * 10000000) + 116444736000000000;
+  uint64_t filetime = (unixtime.tv_sec * 10000000) + unixtime.tv_nsec / 100 +
+                      116444736000000000;
   return filetime;
 }
 
@@ -143,16 +141,16 @@ class PosixFileHandle : public FileHandle {
             size_t* out_bytes_read) override {
     ssize_t out = pread(handle_, buffer, buffer_length, file_offset);
     *out_bytes_read = out;
-    return out >= 0 ? true : false;
+    return out >= 0;
   }
   bool Write(size_t file_offset, const void* buffer, size_t buffer_length,
              size_t* out_bytes_written) override {
     ssize_t out = pwrite(handle_, buffer, buffer_length, file_offset);
     *out_bytes_written = out;
-    return out >= 0 ? true : false;
+    return out >= 0;
   }
   bool SetLength(size_t length) override {
-    return ftruncate(handle_, length) >= 0 ? true : false;
+    return ftruncate(handle_, length) >= 0;
   }
   void Flush() override { fsync(handle_); }
 
@@ -197,12 +195,17 @@ bool GetInfo(const std::filesystem::path& path, FileInfo* out_info) {
   if (stat(path.c_str(), &st) == 0) {
     if (S_ISDIR(st.st_mode)) {
       out_info->type = FileInfo::Type::kDirectory;
+      // On Linux st.st_size can have non-zero size (generally 4096) so make 0
+      out_info->total_size = 0;
     } else {
       out_info->type = FileInfo::Type::kFile;
+      out_info->total_size = st.st_size;
     }
-    out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime);
-    out_info->access_timestamp = convertUnixtimeToWinFiletime(st.st_atime);
-    out_info->write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime);
+    out_info->path = path.parent_path();
+    out_info->name = path.filename();
+    out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctim);
+    out_info->access_timestamp = convertUnixtimeToWinFiletime(st.st_atim);
+    out_info->write_timestamp = convertUnixtimeToWinFiletime(st.st_mtim);
     return true;
   }
   return false;
@@ -217,20 +220,26 @@ std::vector<FileInfo> ListFiles(const std::filesystem::path& path) {
   }
 
   while (auto ent = readdir(dir)) {
+    if (std::strcmp(ent->d_name, ".") == 0 ||
+        std::strcmp(ent->d_name, "..") == 0) {
+      continue;
+    }
+
     FileInfo info;
 
     info.name = ent->d_name;
     struct stat st;
-    stat((path / info.name).c_str(), &st);
-    info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime);
-    info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atime);
-    info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime);
+    auto ret = stat((path / info.name).c_str(), &st);
+    assert_zero(ret);
+    info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctim);
+    info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atim);
+    info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtim);
     if (ent->d_type == DT_DIR) {
       info.type = FileInfo::Type::kDirectory;
       info.total_size = 0;
     } else {
       info.type = FileInfo::Type::kFile;
-      info.total_size = st.st_size;
+      info.total_size = static_cast<size_t>(st.st_size);
     }
     result.push_back(info);
   }
diff --git a/src/xenia/base/memory.cc b/src/xenia/base/memory.cc
index 4fb5372264..c8fab9ad96 100644
--- a/src/xenia/base/memory.cc
+++ b/src/xenia/base/memory.cc
@@ -77,6 +77,9 @@ static void XeCopy16384StreamingAVX(CacheLine* XE_RESTRICT to,
   XE_MSVC_REORDER_BARRIER();
 }
 XE_FORCEINLINE
+#ifdef XE_PLATFORM_LINUX
+__attribute__((__target__("movdir64b")))
+#endif
 static void XeCopy16384Movdir64M(CacheLine* XE_RESTRICT to,
                                  CacheLine* XE_RESTRICT from) {
   uint32_t num_lines_for_8k = 4096 / XE_HOST_CACHE_LINE_SIZE;
@@ -142,7 +145,9 @@ static void vastcpy_impl_avx(CacheLine* XE_RESTRICT physaddr,
     xe::swcache::WriteLineNT(physaddr + i, &line0);
   }
 }
-
+#ifdef XE_PLATFORM_LINUX
+__attribute__((__target__("movdir64b")))
+#endif
 static void vastcpy_impl_movdir64m(CacheLine* XE_RESTRICT physaddr,
                                    CacheLine* XE_RESTRICT rdmapping,
                                    uint32_t written_length) {
@@ -176,8 +181,12 @@ static void vastcpy_impl_movdir64m(CacheLine* XE_RESTRICT physaddr,
 static void vastcpy_impl_repmovs(CacheLine* XE_RESTRICT physaddr,
                                  CacheLine* XE_RESTRICT rdmapping,
                                  uint32_t written_length) {
+#if XE_PLATFORM_WINDOWS
   __movsq((unsigned long long*)physaddr, (unsigned long long*)rdmapping,
           written_length / 8);
+#else
+  memcpy(physaddr, rdmapping, written_length);
+#endif
 }
 XE_COLD
 static void first_vastcpy(CacheLine* XE_RESTRICT physaddr,
@@ -305,6 +314,11 @@ void copy_and_swap_32_aligned(void* dest_ptr, const void* src_ptr,
   }
 }
 
+
+
+#ifdef XE_PLATFORM_LINUX
+__attribute__((__target__("avx2")))
+#endif
 void copy_and_swap_32_unaligned(void* dest_ptr, const void* src_ptr,
                                 size_t count) {
   auto dest = reinterpret_cast<uint32_t*>(dest_ptr);
diff --git a/src/xenia/base/memory.h b/src/xenia/base/memory.h
index 178d88fb73..e449746574 100644
--- a/src/xenia/base/memory.h
+++ b/src/xenia/base/memory.h
@@ -701,10 +701,17 @@ static void ReadLineNT(CacheLine* XE_RESTRICT destination,
                        const CacheLine* XE_RESTRICT source) {
   assert_true((reinterpret_cast<uintptr_t>(source) & 63ULL) == 0);
 
+#ifdef XE_PLATFORM_WINDOWS
   __m128i first = _mm_stream_load_si128(&source->xmms[0]);
   __m128i second = _mm_stream_load_si128(&source->xmms[1]);
   __m128i third = _mm_stream_load_si128(&source->xmms[2]);
   __m128i fourth = _mm_stream_load_si128(&source->xmms[3]);
+#else
+  __m128i first = _mm_stream_load_si128((__m128i *) &source->xmms[0]);
+  __m128i second = _mm_stream_load_si128((__m128i *) &source->xmms[1]);
+  __m128i third = _mm_stream_load_si128((__m128i *) &source->xmms[2]);
+  __m128i fourth = _mm_stream_load_si128((__m128i *) &source->xmms[3]);
+#endif
 
   destination->xmms[0] = first;
   destination->xmms[1] = second;
diff --git a/src/xenia/base/memory_posix.cc b/src/xenia/base/memory_posix.cc
index 2ff36a603d..d3043bfc2a 100644
--- a/src/xenia/base/memory_posix.cc
+++ b/src/xenia/base/memory_posix.cc
@@ -85,8 +85,14 @@ void* AllocFixed(void* base_address, size_t length,
                  AllocationType allocation_type, PageAccess access) {
   // mmap does not support reserve / commit, so ignore allocation_type.
   uint32_t prot = ToPosixProtectFlags(access);
-  void* result = mmap(base_address, length, prot,
-                      MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+  void * result;
+  if (base_address) {
+    result = mmap(base_address, length, prot,
+                  MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+  } else {
+    result = mmap(base_address, length, prot,
+                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  }
   if (result == MAP_FAILED) {
     return nullptr;
   } else {
diff --git a/src/xenia/base/platform.h b/src/xenia/base/platform.h
index c258ad08fd..0c7475b580 100644
--- a/src/xenia/base/platform.h
+++ b/src/xenia/base/platform.h
@@ -166,7 +166,7 @@
 
 #define XE_RESTRICT __restrict
 #else
-#define XE_RESTRICT
+#define XE_RESTRICT __restrict__
 #endif
 
 #if XE_ARCH_AMD64 == 1
diff --git a/src/xenia/base/platform_amd64.cc b/src/xenia/base/platform_amd64.cc
index 48b1c6102e..7bced939e7 100644
--- a/src/xenia/base/platform_amd64.cc
+++ b/src/xenia/base/platform_amd64.cc
@@ -36,6 +36,7 @@ namespace amd64 {
 static uint64_t g_feature_flags = 0U;
 static bool g_did_initialize_feature_flags = false;
 uint64_t GetFeatureFlags() {
+  InitFeatureFlags();
   xenia_assert(g_did_initialize_feature_flags);
   return g_feature_flags;
 }
diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h
index ab86caa686..b23719f7f9 100644
--- a/src/xenia/base/platform_linux.h
+++ b/src/xenia/base/platform_linux.h
@@ -17,4 +17,27 @@
 
 #include "xenia/base/platform.h"
 
+#include <cstdint>
+#include <glib.h>
+
+typedef uint8_t BYTE;
+typedef uint32_t DWORD;
+typedef int32_t LONG;
+typedef int64_t LONGLONG;
+
+typedef union _LARGE_INTEGER {
+  struct {
+    DWORD LowPart;
+    LONG  HighPart;
+  };
+  struct {
+    DWORD LowPart;
+    LONG  HighPart;
+  } u;
+  LONGLONG QuadPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+
+static constexpr size_t KUSER_SHARED_INTERRUPTTIME_OFFSET = 8;
+static unsigned char* KUserShared() { return (unsigned char*)0x7FFE0000ULL; }
+
 #endif  // XENIA_BASE_PLATFORM_LINUX_H_
diff --git a/src/xenia/base/premake5.lua b/src/xenia/base/premake5.lua
index d53c34351b..6bec1bf483 100644
--- a/src/xenia/base/premake5.lua
+++ b/src/xenia/base/premake5.lua
@@ -17,4 +17,4 @@ project("xenia-base")
     "debug_visualizers.natvis",
   })
 
-include("testing")
+include("testing")
\ No newline at end of file
diff --git a/src/xenia/base/string_buffer.cc b/src/xenia/base/string_buffer.cc
index b3a9270a81..f94fd6c880 100644
--- a/src/xenia/base/string_buffer.cc
+++ b/src/xenia/base/string_buffer.cc
@@ -71,13 +71,15 @@ void StringBuffer::Append(const std::string_view value) {
 }
 
 void StringBuffer::AppendVarargs(const char* format, va_list args) {
-  int result = vsnprintf(nullptr, 0, format, args);
-  if (result <= 0) {
-    return;
-  }
-  auto length = static_cast<size_t>(result);
+  va_list size_args;
+  va_copy(size_args, args);  // arg is indeterminate after the return so copy it
+  int length = vsnprintf(nullptr, 0, format, size_args);
+  assert_true(length >= 0);
+  va_end(size_args);
   Grow(length + 1);
-  vsnprintf(buffer_ + buffer_offset_, buffer_capacity_, format, args);
+  int result = vsnprintf(buffer_ + buffer_offset_,
+                         buffer_capacity_ - buffer_offset_, format, args);
+  assert_true(result == length);
   buffer_offset_ += length;
   buffer_[buffer_offset_] = 0;
 }
diff --git a/src/xenia/base/system_gnulinux.cc b/src/xenia/base/system_gnulinux.cc
index 920c9ab9e0..403e9b01ff 100644
--- a/src/xenia/base/system_gnulinux.cc
+++ b/src/xenia/base/system_gnulinux.cc
@@ -9,7 +9,7 @@
 
 #include <alloca.h>
 #include <dlfcn.h>
-#include <stdlib.h>
+#include <cstdlib>
 
 #include <cstring>
 
diff --git a/src/xenia/base/testing/filesystem_test.cc b/src/xenia/base/testing/filesystem_test.cc
new file mode 100644
index 0000000000..2829e6b9d5
--- /dev/null
+++ b/src/xenia/base/testing/filesystem_test.cc
@@ -0,0 +1,58 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project                                 *
+ ******************************************************************************
+ * Copyright 2019 Ben Vanik. All rights reserved.                             *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#include "xenia/base/filesystem.h"
+
+#include <filesystem>
+
+#include "third_party/catch/include/catch.hpp"
+
+namespace xe {
+namespace base {
+namespace test {
+
+TEST_CASE("file_get_info", "Get Info") {
+  auto test_file_name = std::filesystem::path("test_file");
+  auto test_file_dir = std::filesystem::path("src/xenia/base/testing/res");
+  auto test_file_path = test_file_dir / test_file_name;
+
+  filesystem::FileInfo info = {};
+
+  REQUIRE(filesystem::GetInfo(test_file_path, &info));
+
+  CHECK(info.type == filesystem::FileInfo::Type::kFile);
+  CHECK(info.name == test_file_name);
+  CHECK(info.path == test_file_dir);
+  CHECK(info.total_size == 81);
+  CHECK(info.create_timestamp > 132111406279379842);
+  CHECK(info.access_timestamp > 132111406279379842);
+  CHECK(info.write_timestamp > 132111406279379842);
+}
+
+TEST_CASE("folder_get_info", "Get Info") {
+  auto test_folder_name = std::filesystem::path("res");
+  auto test_folder_dir = std::filesystem::path("src/xenia/base/testing");
+  auto test_folder_path = test_folder_dir / test_folder_name;
+
+  filesystem::FileInfo info = {};
+
+  REQUIRE(filesystem::GetInfo(test_folder_path, &info));
+
+  CHECK(info.type == filesystem::FileInfo::Type::kDirectory);
+  CHECK(info.name == test_folder_name);
+  CHECK(info.path == test_folder_dir);
+  CHECK(info.total_size == 0);
+  CHECK(info.create_timestamp > 132111406279379842);
+  CHECK(info.access_timestamp > 132111406279379842);
+  CHECK(info.write_timestamp > 132111406279379842);
+}
+
+}  // namespace test
+}  // namespace base
+}  // namespace xe
diff --git a/src/xenia/base/testing/memory_test.cc b/src/xenia/base/testing/memory_test.cc
index 3f3c1f9639..c670a65a24 100644
--- a/src/xenia/base/testing/memory_test.cc
+++ b/src/xenia/base/testing/memory_test.cc
@@ -506,7 +506,7 @@ TEST_CASE("copy_and_swap_16_in_32_unaligned", "[copy_and_swap]") {
   }
 }
 
-TEST_CASE("create_and_close_file_mapping", "Virtual Memory Mapping") {
+TEST_CASE("create_and_close_file_mapping", "[virtual_memory_mapping]") {
   auto path = fmt::format("xenia_test_{}", Clock::QueryHostTickCount());
   auto memory = xe::memory::CreateFileMappingHandle(
       path, 0x100, xe::memory::PageAccess::kReadWrite, true);
diff --git a/src/xenia/base/testing/premake5.lua b/src/xenia/base/testing/premake5.lua
index 74d39aa651..61194c98a8 100644
--- a/src/xenia/base/testing/premake5.lua
+++ b/src/xenia/base/testing/premake5.lua
@@ -7,3 +7,10 @@ test_suite("xenia-base-tests", project_root, ".", {
     "xenia-base",
   },
 })
+  files({
+    "res/*",
+  })
+  filter("files:res/*")
+    flags({"ExcludeFromBuild"})
+  filter("platforms:Windows")
+    debugdir(project_root)
\ No newline at end of file
diff --git a/src/xenia/base/testing/res/test_file b/src/xenia/base/testing/res/test_file
new file mode 100644
index 0000000000..c94444439f
--- /dev/null
+++ b/src/xenia/base/testing/res/test_file
@@ -0,0 +1 @@
+Test file to test the xe::filesystem::GetInfo function on both Windows and Linux
diff --git a/src/xenia/base/testing/string_test.cc b/src/xenia/base/testing/string_test.cc
new file mode 100644
index 0000000000..654f7d440a
--- /dev/null
+++ b/src/xenia/base/testing/string_test.cc
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Xenia : Xbox 360 Emulator Research Project                                 *
+******************************************************************************
+* Copyright 2019 Ben Vanik. All rights reserved.                             *
+* Released under the BSD license - see LICENSE in the root for more details. *
+******************************************************************************
+*/
+
+#include "xenia/base/string.h"
+#include "xenia/base/string_buffer.h"
+
+#include "third_party/catch/include/catch.hpp"
+
+namespace xe {
+namespace base {
+namespace test {
+
+TEST_CASE("StringBuffer") {
+  StringBuffer sb;
+  uint32_t module_flags = 0x1000000;
+
+  std::string path_(R"(\Device\Cdrom0\default.xex)");
+  sb.AppendFormat("Module {}:\n", path_.c_str());
+  REQUIRE(sb.to_string() == "Module \\Device\\Cdrom0\\default.xex:\n");
+  sb.AppendFormat("    Module Flags: {:08X}\n", module_flags);
+  REQUIRE(
+      sb.to_string() ==
+      "Module \\Device\\Cdrom0\\default.xex:\n    Module Flags: 01000000\n");
+}
+
+}  // namespace test
+}  // namespace base
+}  // namespace xe
diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc
index 1e1f3fedb2..e05d5d6e7e 100644
--- a/src/xenia/cpu/backend/x64/x64_backend.cc
+++ b/src/xenia/cpu/backend/x64/x64_backend.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2019 Ben Vanik. All rights reserved.                             *
+ * Copyright 2022 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
@@ -576,9 +576,10 @@ void* X64HelperEmitter::EmitCurrentForOffsets(const _code_offsets& code_offsets,
   return fn;
 }
 HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
-  // rcx = target
-  // rdx = arg0 (context)
-  // r8 = arg1 (guest return address)
+  // 1st native reg = target
+  // 2nd native reg = arg0 (context)
+  // 3rd native reg = arg1 (guest return address)
+
 
   _code_offsets code_offsets = {};
 
@@ -587,10 +588,10 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
   code_offsets.prolog = getSize();
 
   // rsp + 0 = return address
-  mov(qword[rsp + 8 * 3], r8);
-  mov(qword[rsp + 8 * 2], rdx);
-  mov(qword[rsp + 8 * 1], rcx);
   sub(rsp, stack_size);
+  mov(qword[rsp + offsetof(StackLayout::Thunk, arg_temp[2])], GetNativeReg(2));
+  mov(qword[rsp + offsetof(StackLayout::Thunk, arg_temp[1])], GetNativeReg(1));
+  mov(qword[rsp + offsetof(StackLayout::Thunk, arg_temp[0])], GetNativeReg(0));
 
   code_offsets.prolog_stack_alloc = getSize();
   code_offsets.body = getSize();
@@ -598,10 +599,10 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
   // Save nonvolatile registers.
   EmitSaveNonvolatileRegs();
 
-  mov(rax, rcx);
-  mov(rsi, rdx);                                                    // context
+  mov(rax, GetNativeReg(0));
+  mov(rsi, GetNativeReg(1));                                                    // context
   mov(rdi, ptr[rdx + offsetof(ppc::PPCContext, virtual_membase)]);  // membase
-  mov(rcx, r8);  // return address
+  mov(rcx, GetNativeReg(2));  // return address
   call(rax);
   vzeroupper();
   EmitLoadNonvolatileRegs();
@@ -609,9 +610,9 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
   code_offsets.epilog = getSize();
 
   add(rsp, stack_size);
-  mov(rcx, qword[rsp + 8 * 1]);
-  mov(rdx, qword[rsp + 8 * 2]);
-  mov(r8, qword[rsp + 8 * 3]);
+  mov(GetNativeReg(0), qword[rsp + offsetof(StackLayout::Thunk, arg_temp[0])]);
+  mov(GetNativeReg(1), qword[rsp + offsetof(StackLayout::Thunk, arg_temp[1])]);
+  mov(GetNativeReg(2), qword[rsp + offsetof(StackLayout::Thunk, arg_temp[2])]);
   ret();
 
   code_offsets.tail = getSize();
@@ -632,11 +633,10 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
 }
 
 GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
-  // rcx = target function
-  // rdx = arg0
-  // r8  = arg1
-  // r9  = arg2
-
+  // 1st native reg = target function
+  // 2nd native reg = arg0
+  // 3rd native reg = arg1
+  // 4th native reg = arg2
   _code_offsets code_offsets = {};
 
   const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
@@ -653,8 +653,8 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
   // Save off volatile registers.
   EmitSaveVolatileRegs();
 
-  mov(rax, rcx);              // function
-  mov(rcx, GetContextReg());  // context
+  mov(rax, GetNativeReg(0));              // function
+  mov(GetNativeReg(0), GetContextReg());  // context
   call(rax);
 
   EmitLoadVolatileRegs();
@@ -703,8 +703,8 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
   // Save volatile registers
   EmitSaveVolatileRegs();
 
-  mov(rcx, rsi);  // context
-  mov(rdx, rbx);
+  mov(GetNativeReg(0), GetContextReg());  // context
+  mov(GetNativeReg(1), rbx);
   mov(rax, reinterpret_cast<uint64_t>(&ResolveFunction));
   call(rax);
 
diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc
index da9816a35d..7265eb8f4b 100644
--- a/src/xenia/cpu/backend/x64/x64_emitter.cc
+++ b/src/xenia/cpu/backend/x64/x64_emitter.cc
@@ -78,8 +78,10 @@ static const size_t kMaxCodeSize = 1_MiB;
 
 const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
     Xbyak::Operand::RBX, Xbyak::Operand::R10, Xbyak::Operand::R11,
-    Xbyak::Operand::R12, Xbyak::Operand::R13, Xbyak::Operand::R14,
-    Xbyak::Operand::R15,
+    Xbyak::Operand::R12, Xbyak::Operand::R13,
+#if XE_PLATFORM_WIN32
+    Xbyak::Operand::R14, Xbyak::Operand::R15,
+#endif
 };
 
 const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
@@ -224,7 +226,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, EmitFunctionInfo& func_info) {
   mov(qword[rsp + StackLayout::GUEST_CTX_HOME], GetContextReg());
   */
 
-  mov(qword[rsp + StackLayout::GUEST_RET_ADDR], rcx);
+  mov(qword[rsp + StackLayout::GUEST_RET_ADDR], GetNativeReg(0));
 
   mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], rax);  // 0
 
@@ -691,7 +693,7 @@ void X64Emitter::Call(const hir::Instr* instr, GuestFunction* function) {
       EmitTraceUserCallReturn();
       EmitProfilerEpilogue();
       // Pass the callers return address over.
-      mov(rcx, qword[rsp + StackLayout::GUEST_RET_ADDR]);
+      mov(GetNativeReg(0), qword[rsp + StackLayout::GUEST_RET_ADDR]);
 
       add(rsp, static_cast<uint32_t>(stack_size()));
       PopStackpoint();
@@ -718,7 +720,7 @@ void X64Emitter::Call(const hir::Instr* instr, GuestFunction* function) {
     EmitTraceUserCallReturn();
     EmitProfilerEpilogue();
     // Pass the callers return address over.
-    mov(rcx, qword[rsp + StackLayout::GUEST_RET_ADDR]);
+    mov(GetNativeReg(0), qword[rsp + StackLayout::GUEST_RET_ADDR]);
 
     add(rsp, static_cast<uint32_t>(stack_size()));
     PopStackpoint();
@@ -752,9 +754,13 @@ void X64Emitter::CallIndirect(const hir::Instr* instr,
   } else {
     // Old-style resolve.
     // Not too important because indirection table is almost always available.
+#if XE_PLATFORM_WIN32
     mov(edx, reg.cvt32());
+#else
+    mov(esi, reg.cvt32());
+#endif
     mov(rax, reinterpret_cast<uint64_t>(ResolveFunction));
-    mov(rcx, GetContextReg());
+    mov(GetNativeReg(0), GetContextReg());
     call(rax);
   }
 
@@ -764,14 +770,14 @@ void X64Emitter::CallIndirect(const hir::Instr* instr,
     EmitTraceUserCallReturn();
     EmitProfilerEpilogue();
     // Pass the callers return address over.
-    mov(rcx, qword[rsp + StackLayout::GUEST_RET_ADDR]);
+    mov(GetNativeReg(0), qword[rsp + StackLayout::GUEST_RET_ADDR]);
 
     add(rsp, static_cast<uint32_t>(stack_size()));
     PopStackpoint();
     jmp(rax);
   } else {
     // Return address is from the previous SET_RETURN_ADDRESS.
-    mov(rcx, qword[rsp + StackLayout::GUEST_CALL_RET_ADDR]);
+    mov(GetNativeReg(0), qword[rsp + StackLayout::GUEST_CALL_RET_ADDR]);
 
     call(rax);
     synchronize_stack_on_next_instruction_ = true;
@@ -857,16 +863,36 @@ void X64Emitter::SetReturnAddress(uint64_t value) {
   mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], rax);
 }
 
-Xbyak::Reg64 X64Emitter::GetNativeParam(uint32_t param) {
-  if (param == 0)
+Xbyak::Reg64 X64Emitter::GetNativeReg(uint32_t reg) {
+#if XE_PLATFORM_WIN32
+  if (reg == 0)
+    return rcx;
+  else if (reg == 1)
     return rdx;
-  else if (param == 1)
+  else if (reg == 2)
     return r8;
-  else if (param == 2)
+  else if (reg == 3)
     return r9;
 
   assert_always();
   return r9;
+#else
+  if (reg == 0)
+    return rdi;
+  else if (reg == 1)
+    return rsi;
+  else if (reg == 2)
+    return rdx;
+  else if (reg == 3)
+    return rcx;
+
+  assert_always();
+  return rcx;
+#endif
+}
+
+Xbyak::Reg64 X64Emitter::GetNativeParam(uint32_t param) {
+  return GetNativeReg(param + 1);
 }
 
 // Important: If you change these, you must update the thunks in x64_backend.cc!
diff --git a/src/xenia/cpu/backend/x64/x64_emitter.h b/src/xenia/cpu/backend/x64/x64_emitter.h
index 4fdeab4a4b..1ddd44b5db 100644
--- a/src/xenia/cpu/backend/x64/x64_emitter.h
+++ b/src/xenia/cpu/backend/x64/x64_emitter.h
@@ -217,6 +217,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
             std::vector<SourceMapEntry>* out_source_map);
 
  public:
+#if XE_PLATFORM_WIN32
   // Reserved:  rsp, rsi, rdi
   // Scratch:   rax/rcx/rdx
   //            xmm0-2
@@ -224,6 +225,15 @@ class X64Emitter : public Xbyak::CodeGenerator {
   //            xmm4-xmm15 (save to get xmm3)
   static const int GPR_COUNT = 7;
   static const int XMM_COUNT = 12;
+#else
+  // Reserved:  rsp, r14, r15
+  // Scratch:   rax/rdi/rsi/rcx/rdx
+  //            xmm0-2
+  // Available: rbx, r10-r13
+  //            xmm4-xmm15 (save to get xmm3)
+  static const int GPR_COUNT = 5;
+  static const int XMM_COUNT = 12;
+#endif
   static constexpr size_t kStashOffset = 32;
   static void SetupReg(const hir::Value* v, Xbyak::Reg8& r) {
     auto idx = gpr_reg_map_[v->reg.index];
@@ -263,8 +273,10 @@ class X64Emitter : public Xbyak::CodeGenerator {
   void CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0),
                   uint64_t arg0);
   void CallNativeSafe(void* fn);
+
   void SetReturnAddress(uint64_t value);
 
+  Xbyak::Reg64 GetNativeReg(uint32_t reg);
   Xbyak::Reg64 GetNativeParam(uint32_t param);
 
   Xbyak::Reg64 GetContextReg() const;
diff --git a/src/xenia/cpu/backend/x64/x64_tracers.cc b/src/xenia/cpu/backend/x64/x64_tracers.cc
index afe27ec21e..727808225e 100644
--- a/src/xenia/cpu/backend/x64/x64_tracers.cc
+++ b/src/xenia/cpu/backend/x64/x64_tracers.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2014 Ben Vanik. All rights reserved.                             *
+ * Copyright 2022 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/backend/x64/x64_tracers.h b/src/xenia/cpu/backend/x64/x64_tracers.h
index 20a6710984..4a6d0c18f6 100644
--- a/src/xenia/cpu/backend/x64/x64_tracers.h
+++ b/src/xenia/cpu/backend/x64/x64_tracers.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2014 Ben Vanik. All rights reserved.                             *
+ * Copyright 2022 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/hir/value.cc b/src/xenia/cpu/hir/value.cc
index 84b28a8f23..c05d442ac8 100644
--- a/src/xenia/cpu/hir/value.cc
+++ b/src/xenia/cpu/hir/value.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2022 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/hir/value.h b/src/xenia/cpu/hir/value.h
index 3a1cd442e2..15eaf7827f 100644
--- a/src/xenia/cpu/hir/value.h
+++ b/src/xenia/cpu/hir/value.h
@@ -10,6 +10,7 @@
 #ifndef XENIA_CPU_HIR_VALUE_H_
 #define XENIA_CPU_HIR_VALUE_H_
 
+#include <climits>
 #include "xenia/base/arena.h"
 #include "xenia/base/assert.h"
 #include "xenia/base/vec128.h"
diff --git a/src/xenia/cpu/ppc/ppc_context.h b/src/xenia/cpu/ppc/ppc_context.h
index 629b28392a..5122b5673d 100644
--- a/src/xenia/cpu/ppc/ppc_context.h
+++ b/src/xenia/cpu/ppc/ppc_context.h
@@ -438,8 +438,8 @@ typedef struct alignas(64) PPCContext_s {
     }
     return reinterpret_cast<T>(host_address);
 #else
-    return processor->memory()->TranslateVirtual<T>(guest_address);
-
+    uint8_t* host_address = virtual_membase + guest_address;
+    return reinterpret_cast<T>(host_address);
 #endif
   }
   //for convenience in kernel functions, version that auto narrows to uint32
diff --git a/src/xenia/cpu/ppc/ppc_frontend.cc b/src/xenia/cpu/ppc/ppc_frontend.cc
index b2c1094ced..d7d839573c 100644
--- a/src/xenia/cpu/ppc/ppc_frontend.cc
+++ b/src/xenia/cpu/ppc/ppc_frontend.cc
@@ -57,15 +57,15 @@ Memory* PPCFrontend::memory() const { return processor_->memory(); }
 // Checks the state of the global lock and sets scratch to the current MSR
 // value.
 void CheckGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
-  auto global_mutex = reinterpret_cast<xe_global_mutex*>(arg0);
+  auto global_mutex = reinterpret_cast<global_mutex_type *>(arg0);
   auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
-  std::lock_guard<xe_global_mutex> lock(*global_mutex);
+  std::lock_guard<global_mutex_type> lock(*global_mutex);
   ppc_context->scratch = *global_lock_count ? 0 : 0x8000;
 }
 
 // Enters the global lock. Safe to recursion.
 void EnterGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
-  auto global_mutex = reinterpret_cast<xe_global_mutex*>(arg0);
+  auto global_mutex = reinterpret_cast<global_mutex_type *>(arg0);
   auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
   global_mutex->lock();
   xe::atomic_inc(global_lock_count);
@@ -73,7 +73,7 @@ void EnterGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
 
 // Leaves the global lock. Safe to recursion.
 void LeaveGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
-  auto global_mutex = reinterpret_cast<xe_global_mutex*>(arg0);
+  auto global_mutex = reinterpret_cast<global_mutex_type *>(arg0);
   auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
   auto new_lock_count = xe::atomic_dec(global_lock_count);
   assert_true(new_lock_count >= 0);
diff --git a/src/xenia/cpu/ppc/ppc_translator.cc b/src/xenia/cpu/ppc/ppc_translator.cc
index 69b0da4e3a..d01213a07b 100644
--- a/src/xenia/cpu/ppc/ppc_translator.cc
+++ b/src/xenia/cpu/ppc/ppc_translator.cc
@@ -139,7 +139,11 @@ void PPCTranslator::DumpHIR(GuestFunction* function, PPCHIRBuilder* builder) {
 
     {
       wchar_t tmpbuf[64];
+#ifdef XE_PLATFORM_WINDOWS
       _snwprintf(tmpbuf, 64, L"%X", function->address());
+#else
+      swprintf(tmpbuf, 64, L"%X", function->address());
+#endif
       folder_path.append(&tmpbuf[0]);
     }
 
diff --git a/src/xenia/cpu/testing/util.h b/src/xenia/cpu/testing/util.h
index 8f6df2d577..34e80157bc 100644
--- a/src/xenia/cpu/testing/util.h
+++ b/src/xenia/cpu/testing/util.h
@@ -74,7 +74,6 @@ class TestFunction {
       uint32_t stack_address = memory_size - stack_size;
       uint32_t thread_state_address = stack_address - 0x1000;
       auto thread_state = std::make_unique<ThreadState>(processor.get(), 0x100);
-      assert_always();  // TODO: Allocate a thread stack!!!
       auto ctx = thread_state->context();
       ctx->lr = 0xBCBCBCBC;
 
diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc
index de9ddf26da..cdba1c97c4 100644
--- a/src/xenia/cpu/xex_module.cc
+++ b/src/xenia/cpu/xex_module.cc
@@ -1114,7 +1114,11 @@ void XexModule::Precompile() {
   char fmtbuf[16];
 
   for (unsigned i = 0; i < 16; ++i) {
+#ifdef XE_PLATFORM_WINDOWS
     sprintf_s(fmtbuf, "%X", image_sha_bytes_[i]);
+#else
+    sprintf(fmtbuf, "%X", image_sha_bytes_[i]);
+#endif
     image_sha_str_ += &fmtbuf[0];
   }
 
diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h
index 46ce73d9e1..d7a4220975 100644
--- a/src/xenia/gpu/command_processor.h
+++ b/src/xenia/gpu/command_processor.h
@@ -164,8 +164,10 @@ class CommandProcessor {
   XE_FORCEINLINE
   virtual void WriteRegistersFromMem(uint32_t start_index, uint32_t* base,
                                      uint32_t num_registers);
-
+  //FIXME(RodoMa92): This errors out if forced inline on linux
+#ifdef XE_PLATFORM_WINDOWS
   XE_FORCEINLINE
+#endif
   virtual void WriteRegisterRangeFromRing(xe::RingBuffer* ring, uint32_t base,
                                           uint32_t num_registers);
 
diff --git a/src/xenia/gpu/draw_util.cc b/src/xenia/gpu/draw_util.cc
index e6461e8bd3..43413efb1d 100644
--- a/src/xenia/gpu/draw_util.cc
+++ b/src/xenia/gpu/draw_util.cc
@@ -765,6 +765,13 @@ uint32_t GetNormalizedColorMask(const RegisterFile& regs,
   }
   return normalized_color_mask;
 }
+XE_FORCEINLINE
+bool IsPrimitivePolygonal(const RegisterFile& regs) {
+  return IsPrimitivePolygonal(
+      regs.Get<reg::VGT_OUTPUT_PATH_CNTL>().path_select ==
+          xenos::VGTOutputPath::kTessellationEnable,
+      regs.Get<reg::VGT_DRAW_INITIATOR>().prim_type);
+}
 XE_NOINLINE
 XE_NOALIAS
 xenos::CopySampleSelect SanitizeCopySampleSelect(
diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h
index 8196830b80..bff56c6b2c 100644
--- a/src/xenia/gpu/draw_util.h
+++ b/src/xenia/gpu/draw_util.h
@@ -98,13 +98,7 @@ constexpr bool IsPrimitivePolygonal(bool vgt_output_path_is_tessellation_enable,
 
   return (primitive_polygonal_table & (1U << static_cast<uint32_t>(type))) != 0;
 }
-XE_FORCEINLINE
-bool IsPrimitivePolygonal(const RegisterFile& regs) {
-  return IsPrimitivePolygonal(
-      regs.Get<reg::VGT_OUTPUT_PATH_CNTL>().path_select ==
-          xenos::VGTOutputPath::kTessellationEnable,
-      regs.Get<reg::VGT_DRAW_INITIATOR>().prim_type);
-}
+bool IsPrimitivePolygonal(const RegisterFile& regs);
 
 // Whether with the current state, any samples to rasterize (for any reason, not
 // only to write something to a render target, but also to do sample counting or
diff --git a/src/xenia/gpu/pm4_command_processor_declare.h b/src/xenia/gpu/pm4_command_processor_declare.h
index 5f3e45a764..00cc3752cc 100644
--- a/src/xenia/gpu/pm4_command_processor_declare.h
+++ b/src/xenia/gpu/pm4_command_processor_declare.h
@@ -6,9 +6,9 @@
 #define PM4_OVERRIDE
 #endif
 void ExecuteIndirectBuffer(uint32_t ptr,
-                           uint32_t count) XE_RESTRICT;
+                           uint32_t count);
 virtual uint32_t ExecutePrimaryBuffer(uint32_t start_index, uint32_t end_index)
-    XE_RESTRICT PM4_OVERRIDE;
+    PM4_OVERRIDE;
 virtual bool ExecutePacket() PM4_OVERRIDE;
 
 public:
@@ -16,100 +16,100 @@ void ExecutePacket(uint32_t ptr, uint32_t count);
 
 protected:
 XE_NOINLINE
-void DisassembleCurrentPacket() XE_RESTRICT;
+void DisassembleCurrentPacket();
 XE_NOINLINE
-bool ExecutePacketType0( uint32_t packet) XE_RESTRICT;
+bool ExecutePacketType0( uint32_t packet);
 XE_NOINLINE
-bool ExecutePacketType1( uint32_t packet) XE_RESTRICT;
+bool ExecutePacketType1( uint32_t packet);
 
-bool ExecutePacketType2( uint32_t packet) XE_RESTRICT;
+bool ExecutePacketType2( uint32_t packet);
 XE_NOINLINE
-bool ExecutePacketType3( uint32_t packet) XE_RESTRICT;
+bool ExecutePacketType3( uint32_t packet);
 XE_NOINLINE
 bool ExecutePacketType3_ME_INIT( uint32_t packet,
-                                uint32_t count) XE_RESTRICT;
+                                uint32_t count);
 bool ExecutePacketType3_NOP( uint32_t packet,
-                            uint32_t count) XE_RESTRICT;
+                            uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_INTERRUPT( uint32_t packet,
-                                  uint32_t count) XE_RESTRICT;
+                                  uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_XE_SWAP( uint32_t packet,
-                                uint32_t count) XE_RESTRICT;
+                                uint32_t count);
 
 bool ExecutePacketType3_INDIRECT_BUFFER( uint32_t packet,
-                                        uint32_t count) XE_RESTRICT;
+                                        uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_WAIT_REG_MEM( uint32_t packet,
-                                     uint32_t count) XE_RESTRICT;
+                                     uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_REG_RMW( uint32_t packet,
-                                uint32_t count) XE_RESTRICT;
+                                uint32_t count);
 
 bool ExecutePacketType3_REG_TO_MEM( uint32_t packet,
-                                   uint32_t count) XE_RESTRICT;
+                                   uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_MEM_WRITE( uint32_t packet,
-                                  uint32_t count) XE_RESTRICT;
+                                  uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_COND_WRITE( uint32_t packet,
-                                   uint32_t count) XE_RESTRICT;
+                                   uint32_t count);
 
 bool ExecutePacketType3_EVENT_WRITE( uint32_t packet,
-                                    uint32_t count) XE_RESTRICT;
+                                    uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_EVENT_WRITE_SHD( uint32_t packet,
-                                        uint32_t count) XE_RESTRICT;
+                                        uint32_t count);
 
 bool ExecutePacketType3_EVENT_WRITE_EXT( uint32_t packet,
-                                        uint32_t count) XE_RESTRICT;
+                                        uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_EVENT_WRITE_ZPD( uint32_t packet,
-                                        uint32_t count) XE_RESTRICT;
+                                        uint32_t count);
 
 bool ExecutePacketType3Draw( uint32_t packet,
                             const char* opcode_name,
                             uint32_t viz_query_condition,
-                            uint32_t count_remaining) XE_RESTRICT;
+                            uint32_t count_remaining);
 
 bool ExecutePacketType3_DRAW_INDX( uint32_t packet,
-                                  uint32_t count) XE_RESTRICT;
+                                  uint32_t count);
 
 bool ExecutePacketType3_DRAW_INDX_2( uint32_t packet,
-                                    uint32_t count) XE_RESTRICT;
+                                    uint32_t count);
 XE_FORCEINLINE
 bool ExecutePacketType3_SET_CONSTANT( uint32_t packet,
-                                     uint32_t count) XE_RESTRICT;
+                                     uint32_t count);
 XE_NOINLINE
 bool ExecutePacketType3_SET_CONSTANT2( uint32_t packet,
-                                      uint32_t count) XE_RESTRICT;
+                                      uint32_t count);
 XE_FORCEINLINE
 bool ExecutePacketType3_LOAD_ALU_CONSTANT( uint32_t packet,
-                                          uint32_t count) XE_RESTRICT;
+                                          uint32_t count);
 
 bool ExecutePacketType3_SET_SHADER_CONSTANTS(
                                              uint32_t packet,
-                                             uint32_t count) XE_RESTRICT;
+                                             uint32_t count);
 
 bool ExecutePacketType3_IM_LOAD( uint32_t packet,
-                                uint32_t count) XE_RESTRICT;
+                                uint32_t count);
 
 bool ExecutePacketType3_IM_LOAD_IMMEDIATE( uint32_t packet,
-                                          uint32_t count) XE_RESTRICT;
+                                          uint32_t count);
 
 bool ExecutePacketType3_INVALIDATE_STATE( uint32_t packet,
-                                         uint32_t count) XE_RESTRICT;
+                                         uint32_t count);
 
 bool ExecutePacketType3_VIZ_QUERY( uint32_t packet,
-                                  uint32_t count) XE_RESTRICT;
+                                  uint32_t count);
 
 
 XE_FORCEINLINE
-void WriteEventInitiator(uint32_t value) XE_RESTRICT;
+void WriteEventInitiator(uint32_t value);
 
 XE_NOINLINE
 XE_COLD
-bool HitUnimplementedOpcode(uint32_t opcode, uint32_t count) XE_RESTRICT;
+bool HitUnimplementedOpcode(uint32_t opcode, uint32_t count);
 
 XE_FORCEINLINE
 XE_NOALIAS
diff --git a/src/xenia/gpu/pm4_command_processor_implement.h b/src/xenia/gpu/pm4_command_processor_implement.h
index 62e2b1f647..565cf9b31f 100644
--- a/src/xenia/gpu/pm4_command_processor_implement.h
+++ b/src/xenia/gpu/pm4_command_processor_implement.h
@@ -6,7 +6,7 @@
 
 using namespace xe::gpu::xenos;
 void COMMAND_PROCESSOR::ExecuteIndirectBuffer(uint32_t ptr,
-                                              uint32_t count) XE_RESTRICT {
+                                              uint32_t count) {
   SCOPE_profile_cpu_f("gpu");
 
   trace_writer_.WriteIndirectBufferStart(ptr, count * sizeof(uint32_t));
@@ -79,7 +79,7 @@ std::string GenerateRegnameForPm4Print(uint32_t reg) {
 }
 
 XE_NOINLINE
-void COMMAND_PROCESSOR::DisassembleCurrentPacket() XE_RESTRICT {
+void COMMAND_PROCESSOR::DisassembleCurrentPacket() {
   xe::gpu::PacketInfo packet_info;
 
   logging::LoggerBatch<LogLevel::Debug> logger{};
@@ -325,7 +325,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType0_CountOverflow(uint32_t count) {
    the most frequently called functions for PM4
 */
 XE_NOINLINE
-bool COMMAND_PROCESSOR::ExecutePacketType0(uint32_t packet) XE_RESTRICT {
+bool COMMAND_PROCESSOR::ExecutePacketType0(uint32_t packet) {
   // Type-0 packet.
   // Write count registers in sequence to the registers starting at
   // (base_index << 2).
@@ -354,7 +354,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType0(uint32_t packet) XE_RESTRICT {
   }
 }
 XE_NOINLINE
-bool COMMAND_PROCESSOR::ExecutePacketType1(uint32_t packet) XE_RESTRICT {
+bool COMMAND_PROCESSOR::ExecutePacketType1(uint32_t packet) {
   // Type-1 packet.
   // Contains two registers of data. Type-0 should be more common.
   trace_writer_.WritePacketStart(uint32_t(reader_.read_ptr() - 4), 3);
@@ -368,7 +368,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType1(uint32_t packet) XE_RESTRICT {
   return true;
 }
 
-bool COMMAND_PROCESSOR::ExecutePacketType2(uint32_t packet) XE_RESTRICT {
+bool COMMAND_PROCESSOR::ExecutePacketType2(uint32_t packet) {
   // Type-2 packet.
   // No-op. Do nothing.
   trace_writer_.WritePacketStart(uint32_t(reader_.read_ptr() - 4), 1);
@@ -389,7 +389,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_CountOverflow(uint32_t count) {
   return false;
 }
 XE_NOINLINE
-bool COMMAND_PROCESSOR::ExecutePacketType3(uint32_t packet) XE_RESTRICT {
+bool COMMAND_PROCESSOR::ExecutePacketType3(uint32_t packet) {
   // Type-3 packet.
   uint32_t opcode = (packet >> 8) & 0x7F;
   uint32_t count = ((packet >> 16) & 0x3FFF) + 1;
@@ -601,7 +601,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3(uint32_t packet) XE_RESTRICT {
 XE_NOINLINE
 XE_COLD
 bool COMMAND_PROCESSOR::HitUnimplementedOpcode(uint32_t opcode,
-                                               uint32_t count) XE_RESTRICT {
+                                               uint32_t count) {
   XELOGGPU("Unimplemented GPU OPCODE: 0x{:02X}\t\tCOUNT: {}\n", opcode, count);
   assert_always();
   reader_.AdvanceRead(count * sizeof(uint32_t));
@@ -610,7 +610,7 @@ bool COMMAND_PROCESSOR::HitUnimplementedOpcode(uint32_t opcode,
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_ME_INIT(uint32_t packet,
-                                                   uint32_t count) XE_RESTRICT {
+                                                   uint32_t count) {
   // initialize CP's micro-engine
   me_bin_.resize(count);
   for (uint32_t i = 0; i < count; i++) {
@@ -620,7 +620,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_ME_INIT(uint32_t packet,
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_NOP(uint32_t packet,
-                                               uint32_t count) XE_RESTRICT {
+                                               uint32_t count) {
   // skip N 32-bit words to get to the next packet
   // No-op, ignore some data.
   reader_.AdvanceRead(count * sizeof(uint32_t));
@@ -628,7 +628,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_NOP(uint32_t packet,
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_INTERRUPT(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   SCOPE_profile_cpu_f("gpu");
 
   // generate interrupt from the command stream
@@ -642,7 +642,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_INTERRUPT(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_XE_SWAP(uint32_t packet,
-                                                   uint32_t count) XE_RESTRICT {
+                                                   uint32_t count) {
   SCOPE_profile_cpu_f("gpu");
 
   Profiler::Flip();
@@ -668,7 +668,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_XE_SWAP(uint32_t packet,
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_INDIRECT_BUFFER(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // indirect buffer dispatch
   uint32_t list_ptr = CpuToGpu(reader_.ReadAndSwap<uint32_t>());
   uint32_t list_length = reader_.ReadAndSwap<uint32_t>();
@@ -721,7 +721,7 @@ static bool MatchValueAndRef(uint32_t value, uint32_t ref, uint32_t wait_info) {
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_WAIT_REG_MEM(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   SCOPE_profile_cpu_f("gpu");
 
   // wait until a register or memory location is a specific value
@@ -776,7 +776,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_WAIT_REG_MEM(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_REG_RMW(uint32_t packet,
-                                                   uint32_t count) XE_RESTRICT {
+                                                   uint32_t count) {
   // register read/modify/write
   // ? (used during shader upload and edram setup)
   uint32_t rmw_info = reader_.ReadAndSwap<uint32_t>();
@@ -802,7 +802,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_REG_RMW(uint32_t packet,
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_REG_TO_MEM(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // Copy Register to Memory (?)
   // Count is 2, assuming a Register Addr and a Memory Addr.
 
@@ -824,7 +824,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_REG_TO_MEM(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_MEM_WRITE(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   uint32_t write_addr = reader_.ReadAndSwap<uint32_t>();
   for (uint32_t i = 0; i < count - 1; i++) {
     uint32_t write_data = reader_.ReadAndSwap<uint32_t>();
@@ -841,7 +841,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_MEM_WRITE(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_COND_WRITE(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // conditional write to memory or register
   uint32_t wait_info = reader_.ReadAndSwap<uint32_t>();
   uint32_t poll_reg_addr = reader_.ReadAndSwap<uint32_t>();
@@ -881,11 +881,11 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_COND_WRITE(
   return true;
 }
 XE_FORCEINLINE
-void COMMAND_PROCESSOR::WriteEventInitiator(uint32_t value) XE_RESTRICT {
+void COMMAND_PROCESSOR::WriteEventInitiator(uint32_t value) {
   register_file_->values[XE_GPU_REG_VGT_EVENT_INITIATOR].u32 = value;
 }
 bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // generate an event that creates a write to memory when completed
   uint32_t initiator = reader_.ReadAndSwap<uint32_t>();
   // Writeback initiator.
@@ -902,7 +902,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_SHD(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // generate a VS|PS_done event
   uint32_t initiator = reader_.ReadAndSwap<uint32_t>();
   uint32_t address = reader_.ReadAndSwap<uint32_t>();
@@ -926,7 +926,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_SHD(
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_EXT(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // generate a screen extent event
   uint32_t initiator = reader_.ReadAndSwap<uint32_t>();
   uint32_t address = reader_.ReadAndSwap<uint32_t>();
@@ -962,7 +962,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_EXT(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_ZPD(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // Set by D3D as BE but struct ABI is LE
   const uint32_t kQueryFinished = xe::byte_swap(0xFFFFFEED);
   assert_true(count == 1);
@@ -997,7 +997,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_ZPD(
 
 bool COMMAND_PROCESSOR::ExecutePacketType3Draw(
     uint32_t packet, const char* opcode_name, uint32_t viz_query_condition,
-    uint32_t count_remaining) XE_RESTRICT {
+    uint32_t count_remaining) {
   // if viz_query_condition != 0, this is a conditional draw based on viz query.
   // This ID matches the one issued in PM4_VIZ_QUERY
   // uint32_t viz_id = viz_query_condition & 0x3F;
@@ -1112,7 +1112,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3Draw(
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_DRAW_INDX(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // "initiate fetch of index buffer and draw"
   // Generally used by Xbox 360 Direct3D 9 for kDMA and kAutoIndex sources.
   // With a viz query token as the first one.
@@ -1129,7 +1129,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_DRAW_INDX(
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_DRAW_INDX_2(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // "draw using supplied indices in packet"
   // Generally used by Xbox 360 Direct3D 9 for kAutoIndex source.
   // No viz query token.
@@ -1138,7 +1138,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_DRAW_INDX_2(
 }
 XE_FORCEINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_SET_CONSTANT(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // load constant into chip and to memory
   // PM4_REG(reg) ((0x4 << 16) | (GSL_HAL_SUBBLOCK_OFFSET(reg)))
   //                                     reg - 0x2000
@@ -1181,7 +1181,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_SET_CONSTANT(
 }
 XE_NOINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_SET_CONSTANT2(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   uint32_t offset_type = reader_.ReadAndSwap<uint32_t>();
   uint32_t index = offset_type & 0xFFFF;
   uint32_t countm1 = count - 1;
@@ -1192,7 +1192,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_SET_CONSTANT2(
 }
 XE_FORCEINLINE
 bool COMMAND_PROCESSOR::ExecutePacketType3_LOAD_ALU_CONSTANT(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // load constants from memory
   uint32_t address = reader_.ReadAndSwap<uint32_t>();
   address &= 0x3FFFFFFF;
@@ -1245,7 +1245,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_LOAD_ALU_CONSTANT(
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_SET_SHADER_CONSTANTS(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   uint32_t offset_type = reader_.ReadAndSwap<uint32_t>();
   uint32_t index = offset_type & 0xFFFF;
   uint32_t countm1 = count - 1;
@@ -1255,7 +1255,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_SET_SHADER_CONSTANTS(
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_IM_LOAD(uint32_t packet,
-                                                   uint32_t count) XE_RESTRICT {
+                                                   uint32_t count) {
   SCOPE_profile_cpu_f("gpu");
 
   // load sequencer instruction memory (pointer-based)
@@ -1285,7 +1285,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_IM_LOAD(uint32_t packet,
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_IM_LOAD_IMMEDIATE(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   SCOPE_profile_cpu_f("gpu");
 
   // load sequencer instruction memory (code embedded in packet)
@@ -1321,7 +1321,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_IM_LOAD_IMMEDIATE(
 */
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_INVALIDATE_STATE(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // selective invalidation of state pointers
   /*uint32_t mask =*/reader_.ReadAndSwap<uint32_t>();
   // driver_->InvalidateState(mask);
@@ -1329,7 +1329,7 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_INVALIDATE_STATE(
 }
 
 bool COMMAND_PROCESSOR::ExecutePacketType3_VIZ_QUERY(
-    uint32_t packet, uint32_t count) XE_RESTRICT {
+    uint32_t packet, uint32_t count) {
   // begin/end initiator for viz query extent processing
   // https://www.google.com/patents/US20050195186
   assert_true(count == 1);
diff --git a/src/xenia/gpu/register_file.cc b/src/xenia/gpu/register_file.cc
index 5dd580e077..ecc21c6dbd 100644
--- a/src/xenia/gpu/register_file.cc
+++ b/src/xenia/gpu/register_file.cc
@@ -9,6 +9,7 @@
 
 #include "xenia/gpu/register_file.h"
 #include <array>
+#include <climits>
 #include <cstring>
 
 #include "xenia/base/math.h"
diff --git a/src/xenia/gpu/shared_memory.cc b/src/xenia/gpu/shared_memory.cc
index a94aa053bc..416a27bd95 100644
--- a/src/xenia/gpu/shared_memory.cc
+++ b/src/xenia/gpu/shared_memory.cc
@@ -482,7 +482,8 @@ void SharedMemory::TryFindUploadRange(const uint32_t& block_first,
 }
 
 static bool UploadRange_DoBestScanForward(uint64_t v, uint32_t* out) {
-#if XE_ARCH_AMD64 == 1
+//_BitScanForward64 is a Microsoft specific function
+#if XE_ARCH_AMD64 == 1 && XE_PLATFORM_WINDOWS
   if (!v) {
     return false;
   }
diff --git a/src/xenia/kernel/achievement_manager.cc b/src/xenia/kernel/achievement_manager.cc
index e58965b84b..6217a2795d 100644
--- a/src/xenia/kernel/achievement_manager.cc
+++ b/src/xenia/kernel/achievement_manager.cc
@@ -53,12 +53,14 @@ void AchievementManager::EarnAchievement(uint64_t xuid, uint32_t title_id,
       if (!cvars::show_achievement_notification) {
         continue;
       }
-
+      //FIXME(RodoMa92): This call fails to compile under linux, disabled for now
+#ifdef XE_PLATFORM_WINDOWS
       app_context.CallInUIThread([imgui_drawer, description]() {
-        new xe::ui::AchievementNotificationWindow(
+        new ui::AchievementNotificationWindow(
             imgui_drawer, "Achievement unlocked", description, 0,
             kernel_state()->notification_position_);
       });
+#endif
     }
   }
 }
diff --git a/src/xenia/kernel/premake5.lua b/src/xenia/kernel/premake5.lua
index 1061c24ea5..5da51373a5 100644
--- a/src/xenia/kernel/premake5.lua
+++ b/src/xenia/kernel/premake5.lua
@@ -17,6 +17,9 @@ project("xenia-kernel")
   })
   defines({
   })
+  includedirs({
+    project_root.."/xenia/base/",
+  })
   recursive_platform_files()
   files({
     "debug_visualizers.natvis",
diff --git a/src/xenia/kernel/util/object_table.cc b/src/xenia/kernel/util/object_table.cc
index 4568c72d15..cf707ea10d 100644
--- a/src/xenia/kernel/util/object_table.cc
+++ b/src/xenia/kernel/util/object_table.cc
@@ -13,6 +13,7 @@
 #include <cstring>
 
 #include "xenia/base/byte_stream.h"
+#include "xenia/base/demangle.h"
 #include "xenia/base/logging.h"
 #include "xenia/kernel/xobject.h"
 #include "xenia/kernel/xthread.h"
@@ -144,7 +145,8 @@ X_STATUS ObjectTable::AddHandle(XObject* object, X_HANDLE* out_handle) {
       // Retain so long as the object is in the table.
       object->Retain();
 
-      XELOGI("Added handle:{:08X} for {}", handle, typeid(*object).name());
+      XELOGI("Added handle:{:08X} for {}", handle,
+             Demangle(typeid(*object).name()));
     }
   }
 
@@ -231,7 +233,8 @@ X_STATUS ObjectTable::RemoveHandle(X_HANDLE handle) {
       object->handles().erase(handle_entry);
     }
 
-    XELOGI("Removed handle:{:08X} for {}", handle, typeid(*object).name());
+    XELOGI("Removed handle:{:08X} for {}", handle,
+           Demangle(typeid(*object).name()).c_str());
 
     // Remove object name from mapping to prevent naming collision.
     if (!object->name().empty()) {
diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc
index 6ffaccc2e6..580c599686 100644
--- a/src/xenia/kernel/xam/xam_info.cc
+++ b/src/xenia/kernel/xam/xam_info.cc
@@ -23,6 +23,8 @@
 
 #if XE_PLATFORM_WIN32
 #include "xenia/base/platform_win.h"
+#elif XE_PLATFORM_LINUX
+#include "xenia/base/platform_linux.h"
 #endif
 
 #include "third_party/fmt/include/fmt/format.h"
diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc
index cee06c07a2..7a0fd0ec52 100644
--- a/src/xenia/kernel/xobject.cc
+++ b/src/xenia/kernel/xobject.cc
@@ -447,12 +447,12 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
     StashHandle(header, object->handle());
     result = object;
 
-  return_result:
-    if (!already_locked) {
-      global_critical_region::mutex().unlock();
-    }
-    return object_ref<XObject>(result);
   }
+return_result:
+  if (!already_locked) {
+    global_critical_region::mutex().unlock();
+  }
+  return object_ref<XObject>(result);
 }
 
 }  // namespace kernel
diff --git a/src/xenia/kernel/xsocket.cc b/src/xenia/kernel/xsocket.cc
index 3e8f754b86..6667ab8100 100644
--- a/src/xenia/kernel/xsocket.cc
+++ b/src/xenia/kernel/xsocket.cc
@@ -75,8 +75,13 @@ X_STATUS XSocket::Close() {
 
 X_STATUS XSocket::GetOption(uint32_t level, uint32_t optname, void* optval_ptr,
                             int* optlen) {
+#ifdef XE_PLATFORM_WINDOWS
   int ret =
       getsockopt(native_handle_, level, optname, (char*)optval_ptr, optlen);
+#else
+  int ret =
+      getsockopt(native_handle_, level, optname, (char*)optval_ptr, (unsigned int *)optlen);
+#endif
   if (ret < 0) {
     // TODO: WSAGetLastError()
     return X_STATUS_UNSUCCESSFUL;
diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc
index 6384f49960..b67a38ad64 100644
--- a/src/xenia/memory.cc
+++ b/src/xenia/memory.cc
@@ -1714,7 +1714,7 @@ void PhysicalHeap::EnableAccessCallbacks(uint32_t physical_address,
 template <bool enable_invalidation_notifications>
 XE_NOINLINE void PhysicalHeap::EnableAccessCallbacksInner(
     const uint32_t system_page_first, const uint32_t system_page_last,
-    xe::memory::PageAccess protect_access) XE_RESTRICT {
+    xe::memory::PageAccess protect_access) {
   uint8_t* protect_base = membase_ + heap_base_;
   uint32_t protect_system_page_first = UINT32_MAX;
 
diff --git a/src/xenia/memory.h b/src/xenia/memory.h
index 77b8ff44f1..992f859a3f 100644
--- a/src/xenia/memory.h
+++ b/src/xenia/memory.h
@@ -274,7 +274,7 @@ class PhysicalHeap : public BaseHeap {
   template <bool enable_invalidation_notifications>
   XE_NOINLINE void EnableAccessCallbacksInner(
       const uint32_t system_page_first, const uint32_t system_page_last,
-      xe::memory::PageAccess protect_access) XE_RESTRICT;
+      xe::memory::PageAccess protect_access);
 
   // Returns true if any page in the range was watched.
   bool TriggerCallbacks(global_unique_lock_type global_lock_locked_once,
diff --git a/src/xenia/ui/imgui_notification.cc b/src/xenia/ui/imgui_notification.cc
index d22ac032a1..aa2ded56be 100644
--- a/src/xenia/ui/imgui_notification.cc
+++ b/src/xenia/ui/imgui_notification.cc
@@ -13,6 +13,7 @@
 #include "xenia/base/logging.h"
 #include "xenia/base/platform.h"
 #include "xenia/ui/imgui_notification.h"
+#include "xenia/cpu/ppc/ppc_context.h"
 
 #if XE_PLATFORM_WIN32
 #include <playsoundapi.h>
@@ -89,6 +90,9 @@ const ImVec2 CalculateNotificationScreenPosition(
 }
 
 const ImVec2 CalculateNotificationSize(ImVec2 text_size, float scale) {
+  //FIXME(RodoMa92): Workaround a GCC bug where floorf is not defined in the
+  //std namespace (ref:https://stackoverflow.com/questions/54623100/c-gcc-floorf-not-a-member-of-std)
+#ifdef XE_PLATFORM_WINDOWS
   const ImVec2 result =
       ImVec2(std::floorf((default_notification_icon_size.x +
                           default_notification_margin_size.x) *
@@ -97,6 +101,16 @@ const ImVec2 CalculateNotificationSize(ImVec2 text_size, float scale) {
              std::floorf((default_notification_icon_size.y +
                           default_notification_margin_size.y) *
                          scale));
+#else
+  const ImVec2 result =
+      ImVec2(floorf((default_notification_icon_size.x +
+                          default_notification_margin_size.x) *
+                         scale) +
+                 text_size.x,
+             floorf((default_notification_icon_size.y +
+                          default_notification_margin_size.y) *
+                         scale));
+#endif
 
   return result;
 }
@@ -200,13 +214,23 @@ void AchievementNotificationWindow::OnDraw(ImGuiIO& io) {
   const ImVec2 notification_position = CalculateNotificationScreenPosition(
       screen_size, final_notification_size, GetPositionId());
 
+#ifdef XE_PLATFORM_WINDOWS
   if (isnan(notification_position.x) || isnan(notification_position.y)) {
     return;
   }
+#else
+  if (std::isnan(notification_position.x) || std::isnan(notification_position.y)) {
+    return;
+  }
+#endif
 
   ImVec2 current_notification_size = final_notification_size;
   current_notification_size.x *= notification_draw_progress_;
+#ifdef XE_PLATFORM_WINDOWS
   current_notification_size.x = std::floorf(current_notification_size.x);
+#else
+  current_notification_size.x = floorf(current_notification_size.x);
+#endif
 
   // Initialize position and window size
   ImGui::SetNextWindowSize(current_notification_size);
diff --git a/xenia-build b/xenia-build
index 0bdbd2004a..5e5e55c1b6 100755
--- a/xenia-build
+++ b/xenia-build
@@ -1271,7 +1271,10 @@ class GenTestsCommand(Command):
         print('Generating test binaries...')
         print('')
 
-        binutils_path = os.path.join('third_party', 'binutils-ppc-cygwin')
+        if sys.platform == 'win32':
+            binutils_path = os.path.join('third_party', 'binutils-ppc-cygwin')
+        else:
+            binutils_path = os.path.join('third_party', 'binutils', 'bin')
         ppc_as = os.path.join(binutils_path, 'powerpc-none-elf-as')
         ppc_ld = os.path.join(binutils_path, 'powerpc-none-elf-ld')
         ppc_objdump = os.path.join(binutils_path, 'powerpc-none-elf-objdump')

From ec4576eba6c1f01787588779e2d1c7414491185a Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Wed, 17 May 2023 17:18:48 +0200
Subject: [PATCH 02/16] Reverted small test change

---
 src/xenia/base/platform_amd64.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/xenia/base/platform_amd64.cc b/src/xenia/base/platform_amd64.cc
index 7bced939e7..48b1c6102e 100644
--- a/src/xenia/base/platform_amd64.cc
+++ b/src/xenia/base/platform_amd64.cc
@@ -36,7 +36,6 @@ namespace amd64 {
 static uint64_t g_feature_flags = 0U;
 static bool g_did_initialize_feature_flags = false;
 uint64_t GetFeatureFlags() {
-  InitFeatureFlags();
   xenia_assert(g_did_initialize_feature_flags);
   return g_feature_flags;
 }

From f888b6276d1e03581a5fbac91c913c04ee845cfe Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Wed, 17 May 2023 18:53:53 +0200
Subject: [PATCH 03/16] Implemented QueryHostInterruptTime under linux

---
 src/xenia/base/clock_posix.cc   | 3 +--
 src/xenia/base/platform_linux.h | 3 ---
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/xenia/base/clock_posix.cc b/src/xenia/base/clock_posix.cc
index c0ebc2ada9..0ec830e90d 100644
--- a/src/xenia/base/clock_posix.cc
+++ b/src/xenia/base/clock_posix.cc
@@ -55,7 +55,6 @@ uint64_t Clock::QueryHostUptimeMillis() {
 }
 
 uint64_t Clock::QueryHostInterruptTime() {
-  return *reinterpret_cast<uint64_t*>(KUserShared() +
-                                      KUSER_SHARED_INTERRUPTTIME_OFFSET);
+    return host_tick_count_platform();
 }
 }  // namespace xe
diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h
index b23719f7f9..643d38bbb7 100644
--- a/src/xenia/base/platform_linux.h
+++ b/src/xenia/base/platform_linux.h
@@ -37,7 +37,4 @@ typedef union _LARGE_INTEGER {
   LONGLONG QuadPart;
 } LARGE_INTEGER, *PLARGE_INTEGER;
 
-static constexpr size_t KUSER_SHARED_INTERRUPTTIME_OFFSET = 8;
-static unsigned char* KUserShared() { return (unsigned char*)0x7FFE0000ULL; }
-
 #endif  // XENIA_BASE_PLATFORM_LINUX_H_

From e4396f2bd4d9c343900a5c2cf4c99fcf2050b6d5 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Wed, 28 Jun 2023 15:24:00 +0200
Subject: [PATCH 04/16] Implement LaunchFileExplorer for GNU Linux

---
 src/xenia/base/system_gnulinux.cc | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/xenia/base/system_gnulinux.cc b/src/xenia/base/system_gnulinux.cc
index 403e9b01ff..91ba0a580f 100644
--- a/src/xenia/base/system_gnulinux.cc
+++ b/src/xenia/base/system_gnulinux.cc
@@ -29,7 +29,11 @@ void LaunchWebBrowser(const std::string_view url) {
   system(cmd.c_str());
 }
 
-void LaunchFileExplorer(const std::filesystem::path& path) { assert_always(); }
+void LaunchFileExplorer(const std::filesystem::path& path) {
+  auto cmd = std::string("xdg-open ");
+  cmd.append(path);
+  system(cmd.c_str());
+}
 
 void ShowSimpleMessageBox(SimpleMessageBoxType type, std::string_view message) {
   void* libsdl2 = dlopen("libSDL2.so", RTLD_LAZY | RTLD_LOCAL);

From 13777cab66a915a412b8a2da945942c4bbd0319d Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Fri, 30 Jun 2023 13:49:37 +0200
Subject: [PATCH 05/16] Implement argument parsing and logging initialization
 for GNU Linux

---
 src/xenia/base/main_gnulinux.cc | 84 +++++++++++++++++++++++++++++++++
 src/xenia/base/main_gnulinux.h  | 29 ++++++++++++
 2 files changed, 113 insertions(+)
 create mode 100644 src/xenia/base/main_gnulinux.cc
 create mode 100644 src/xenia/base/main_gnulinux.h

diff --git a/src/xenia/base/main_gnulinux.cc b/src/xenia/base/main_gnulinux.cc
new file mode 100644
index 0000000000..bf40d30933
--- /dev/null
+++ b/src/xenia/base/main_gnulinux.cc
@@ -0,0 +1,84 @@
+/**
+******************************************************************************
+* Xenia : Xbox 360 Emulator Research Project                                 *
+******************************************************************************
+* Copyright 2023 Marco Rodolfi. All rights reserved.                         *
+* Released under the BSD license - see LICENSE in the root for more details. *
+******************************************************************************
+*/
+
+#include "main_gnulinux.h"
+#include <filesystem>
+#include <fstream>
+#include <regex>
+#include "cvar.h"
+#include "logging.h"
+
+// Autogenerated by `xb premake`.
+#include "build/version.h"
+
+namespace xe {
+  bool ParseGNULinuxLaunchArguments(
+      bool transparent_options, const std::string_view positional_usage,
+      const std::vector<std::string>& positional_options,
+      std::vector<std::string>* args_out) {
+    auto size = static_cast<std::streamsize>(std::filesystem::file_size("/proc/self/cmdline"));
+    std::ifstream ifs("/proc/self/cmdline", std::ifstream::in);
+    std::regex del("\0");
+    std::string raw_par(size, '\0');
+    std::vector<std::string> arg_split(size);
+    int argc = 0;
+    while (ifs.read(raw_par.data(), size)) {
+      auto split_arg = std::vector<std::string>(std::sregex_token_iterator(raw_par.begin(), raw_par.end(), del, -1),
+                                                std::sregex_token_iterator());
+      bool par_found = false;
+      for (auto & elem : arg_split){
+        if (elem.find("xenia-app")){
+          par_found = true;
+        } else if (par_found){
+          arg_split.push_back(elem);
+          argc += 1;
+        }
+      }
+    }
+    ifs.close();
+
+    char** argv = reinterpret_cast<char**>(alloca(sizeof(char*) * argc));
+    for (int n = 0; n < argc; n++) {
+      size_t len = strlen(arg_split[n].c_str());
+      argv[n] = reinterpret_cast<char*>(alloca(sizeof(char) * (len + 1)));
+      strcpy(argv[n], arg_split[n].c_str());
+    }
+    if (!transparent_options) {
+      cvar::ParseLaunchArguments(argc, argv, positional_usage,
+                                 positional_options);
+    }
+    if (args_out) {
+      args_out->clear();
+      for (int n = 0; n < argc; n++) {
+        args_out->push_back(std::string(argv[n]));
+      }
+    }
+
+    return true;
+  }
+  int InitializeGNULinuxApp(const std::string_view app_name) {
+    // Initialize logging. Needs parsed FLAGS.
+    xe::InitializeLogging(app_name);
+
+    // Print version info.
+    XELOGI(
+        "Build: "
+    #ifdef XE_BUILD_IS_PR
+        "PR#" XE_BUILD_PR_NUMBER " " XE_BUILD_PR_REPO " " XE_BUILD_PR_BRANCH
+        "@" XE_BUILD_PR_COMMIT_SHORT " against "
+    #endif
+        XE_BUILD_BRANCH "@" XE_BUILD_COMMIT_SHORT " on " XE_BUILD_DATE);
+
+    return 0;
+  }
+
+  void ShutdownGNULinuxApp() {
+    xe::ShutdownLogging();
+  }
+}
\ No newline at end of file
diff --git a/src/xenia/base/main_gnulinux.h b/src/xenia/base/main_gnulinux.h
new file mode 100644
index 0000000000..529605e875
--- /dev/null
+++ b/src/xenia/base/main_gnulinux.h
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Xenia : Xbox 360 Emulator Research Project                                 *
+******************************************************************************
+* Copyright 2021 Ben Vanik. All rights reserved.                             *
+* Released under the BSD license - see LICENSE in the root for more details. *
+******************************************************************************
+*/
+
+#ifndef XENIA_BASE_MAIN_GNULINUX_H_
+#define XENIA_BASE_MAIN_GNULINUX_H_
+
+#include <string>
+#include <vector>
+
+namespace xe {
+
+// Functions for calling in both windowed and console entry points.
+bool ParseGNULinuxLaunchArguments(
+   bool transparent_options, std::string_view positional_usage,
+   const std::vector<std::string>& positional_options,
+   std::vector<std::string>* args_out);
+// InitializeWin32App uses cvars, call ParseWin32LaunchArguments before.
+int InitializeGNULinuxApp(std::string_view app_name);
+void ShutdownGNULinuxApp();
+
+}  // namespace xe
+
+#endif  // XENIA_BASE_MAIN_GNULINUX_H_

From 7b5d3a99231858a09822328e37e6b738bc70098d Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 09:25:51 +0200
Subject: [PATCH 06/16] Remove unneeded argument parting in main_gnulinux since
 it's already handled in the actual main portion.

---
 src/xenia/base/main_gnulinux.cc | 44 ---------------------------------
 1 file changed, 44 deletions(-)

diff --git a/src/xenia/base/main_gnulinux.cc b/src/xenia/base/main_gnulinux.cc
index bf40d30933..9165746c79 100644
--- a/src/xenia/base/main_gnulinux.cc
+++ b/src/xenia/base/main_gnulinux.cc
@@ -18,50 +18,6 @@
 #include "build/version.h"
 
 namespace xe {
-  bool ParseGNULinuxLaunchArguments(
-      bool transparent_options, const std::string_view positional_usage,
-      const std::vector<std::string>& positional_options,
-      std::vector<std::string>* args_out) {
-    auto size = static_cast<std::streamsize>(std::filesystem::file_size("/proc/self/cmdline"));
-    std::ifstream ifs("/proc/self/cmdline", std::ifstream::in);
-    std::regex del("\0");
-    std::string raw_par(size, '\0');
-    std::vector<std::string> arg_split(size);
-    int argc = 0;
-    while (ifs.read(raw_par.data(), size)) {
-      auto split_arg = std::vector<std::string>(std::sregex_token_iterator(raw_par.begin(), raw_par.end(), del, -1),
-                                                std::sregex_token_iterator());
-      bool par_found = false;
-      for (auto & elem : arg_split){
-        if (elem.find("xenia-app")){
-          par_found = true;
-        } else if (par_found){
-          arg_split.push_back(elem);
-          argc += 1;
-        }
-      }
-    }
-    ifs.close();
-
-    char** argv = reinterpret_cast<char**>(alloca(sizeof(char*) * argc));
-    for (int n = 0; n < argc; n++) {
-      size_t len = strlen(arg_split[n].c_str());
-      argv[n] = reinterpret_cast<char*>(alloca(sizeof(char) * (len + 1)));
-      strcpy(argv[n], arg_split[n].c_str());
-    }
-    if (!transparent_options) {
-      cvar::ParseLaunchArguments(argc, argv, positional_usage,
-                                 positional_options);
-    }
-    if (args_out) {
-      args_out->clear();
-      for (int n = 0; n < argc; n++) {
-        args_out->push_back(std::string(argv[n]));
-      }
-    }
-
-    return true;
-  }
   int InitializeGNULinuxApp(const std::string_view app_name) {
     // Initialize logging. Needs parsed FLAGS.
     xe::InitializeLogging(app_name);

From 68f663c66e97bb39d4f38675f1c86b06a1169954 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 09:26:40 +0200
Subject: [PATCH 07/16] Remove unneeded argument parting in main_gnulinux since
 it's already handled in the actual main portion.

---
 src/xenia/base/main_gnulinux.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/src/xenia/base/main_gnulinux.h b/src/xenia/base/main_gnulinux.h
index 529605e875..e5af826a68 100644
--- a/src/xenia/base/main_gnulinux.h
+++ b/src/xenia/base/main_gnulinux.h
@@ -15,12 +15,6 @@
 
 namespace xe {
 
-// Functions for calling in both windowed and console entry points.
-bool ParseGNULinuxLaunchArguments(
-   bool transparent_options, std::string_view positional_usage,
-   const std::vector<std::string>& positional_options,
-   std::vector<std::string>* args_out);
-// InitializeWin32App uses cvars, call ParseWin32LaunchArguments before.
 int InitializeGNULinuxApp(std::string_view app_name);
 void ShutdownGNULinuxApp();
 

From 50d9004305302b178a3fe2d0aead984bf8d2a3cb Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 09:29:29 +0200
Subject: [PATCH 08/16] Generic cleanup

---
 src/xenia/base/console_posix.cc           |  2 +-
 src/xenia/base/exception_handler_posix.cc |  2 +-
 src/xenia/base/mapped_memory_posix.cc     |  2 +-
 src/xenia/base/threading_posix.cc         | 36 ++++++++++++-----------
 4 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/src/xenia/base/console_posix.cc b/src/xenia/base/console_posix.cc
index 0f8cf38f97..adfa4c73cb 100644
--- a/src/xenia/base/console_posix.cc
+++ b/src/xenia/base/console_posix.cc
@@ -7,7 +7,7 @@
  ******************************************************************************
  */
 
-#include <stdio.h>
+#include <cstdio>
 #include <unistd.h>
 
 #include "xenia/base/console.h"
diff --git a/src/xenia/base/exception_handler_posix.cc b/src/xenia/base/exception_handler_posix.cc
index 0b11003ffa..d7a8a2d5ab 100644
--- a/src/xenia/base/exception_handler_posix.cc
+++ b/src/xenia/base/exception_handler_posix.cc
@@ -9,7 +9,7 @@
 
 #include "xenia/base/exception_handler.h"
 
-#include <signal.h>
+#include <csignal>
 #include <ucontext.h>
 #include <cstdint>
 
diff --git a/src/xenia/base/mapped_memory_posix.cc b/src/xenia/base/mapped_memory_posix.cc
index 330ced53fa..09cd5a962a 100644
--- a/src/xenia/base/mapped_memory_posix.cc
+++ b/src/xenia/base/mapped_memory_posix.cc
@@ -48,7 +48,7 @@ class PosixMappedMemory : public MappedMemory {
 
     size_t map_length = length;
     if (!length) {
-      struct stat64 file_stat;
+      struct stat64 file_stat{};
       if (fstat64(file_descriptor, &file_stat)) {
         close(file_descriptor);
         return nullptr;
diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc
index 604e332d5c..4e041ef67f 100644
--- a/src/xenia/base/threading_posix.cc
+++ b/src/xenia/base/threading_posix.cc
@@ -16,7 +16,7 @@
 
 #include <pthread.h>
 #include <sched.h>
-#include <signal.h>
+#include <csignal>
 #include <sys/eventfd.h>
 #include <sys/syscall.h>
 #include <sys/time.h>
@@ -129,8 +129,10 @@ void install_signal_handler(SignalType type) {
     signal_handler_installed[static_cast<size_t>(type)] = true;
 }
 
-// TODO(dougvj)
-void EnableAffinityConfiguration() {}
+// FIXME: The process is already enabled to run all all cores of the machine
+// by default.
+void EnableAffinityConfiguration() {
+}
 
 // uint64_t ticks() { return mach_absolute_time(); }
 
@@ -219,7 +221,7 @@ class PosixConditionBase {
   static std::pair<WaitResult, size_t> WaitMultiple(
       std::vector<PosixConditionBase*>&& handles, bool wait_all,
       std::chrono::milliseconds timeout) {
-    assert_true(handles.size() > 0);
+    assert_true(!handles.empty());
 
     // Construct a condition for all or any depending on wait_all
     std::function<bool()> predicate;
@@ -267,10 +269,10 @@ class PosixConditionBase {
     }
   }
 
-  virtual void* native_handle() const { return cond_.native_handle(); }
+  [[nodiscard]] virtual void* native_handle() const { return cond_.native_handle(); }
 
  protected:
-  inline virtual bool signaled() const = 0;
+  [[nodiscard]] inline virtual bool signaled() const = 0;
   inline virtual void post_execution() = 0;
   static std::condition_variable cond_;
   static std::mutex mutex_;
@@ -306,7 +308,7 @@ class PosixCondition<Event> : public PosixConditionBase {
   }
 
  private:
-  inline bool signaled() const override { return signal_; }
+  [[nodiscard]] inline bool signaled() const override { return signal_; }
   inline void post_execution() override {
     if (!manual_reset_) {
       signal_ = false;
@@ -336,7 +338,7 @@ class PosixCondition<Semaphore> : public PosixConditionBase {
   }
 
  private:
-  inline bool signaled() const override { return count_ > 0; }
+  [[nodiscard]] inline bool signaled() const override { return count_ > 0; }
   inline void post_execution() override {
     count_--;
     cond_.notify_all();
@@ -370,10 +372,10 @@ class PosixCondition<Mutant> : public PosixConditionBase {
     return false;
   }
 
-  void* native_handle() const override { return mutex_.native_handle(); }
+  [[nodiscard]] void* native_handle() const override { return mutex_.native_handle(); }
 
  private:
-  inline bool signaled() const override {
+  [[nodiscard]] inline bool signaled() const override {
     return count_ == 0 || owner_ == std::this_thread::get_id();
   }
   inline void post_execution() override {
@@ -429,7 +431,7 @@ class PosixCondition<Timer> : public PosixConditionBase {
     }
   }
 
-  void* native_handle() const override {
+  [[nodiscard]] void* native_handle() const override {
     assert_always();
     return nullptr;
   }
@@ -451,7 +453,7 @@ class PosixCondition<Timer> : public PosixConditionBase {
   }
 
  private:
-  inline bool signaled() const override { return signal_; }
+  [[nodiscard]] inline bool signaled() const override { return signal_; }
   inline void post_execution() override {
     if (!manual_reset_) {
       signal_ = false;
@@ -601,7 +603,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
 
   uint32_t system_id() const { return static_cast<uint32_t>(thread_); }
 
-  uint64_t affinity_mask() {
+  uint64_t affinity_mask() const {
     WaitStarted();
     cpu_set_t cpu_set;
 #if XE_PLATFORM_ANDROID
@@ -623,7 +625,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
     return result;
   }
 
-  void set_affinity_mask(uint64_t mask) {
+  void set_affinity_mask(uint64_t mask) const {
     WaitStarted();
     cpu_set_t cpu_set;
     CPU_ZERO(&cpu_set);
@@ -644,7 +646,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
 #endif
   }
 
-  int priority() {
+  int priority() const {
     WaitStarted();
     int policy;
     sched_param param{};
@@ -656,7 +658,7 @@ class PosixCondition<Thread> : public PosixConditionBase {
     return param.sched_priority;
   }
 
-  void set_priority(int new_priority) {
+  void set_priority(int new_priority) const {
     WaitStarted();
     sched_param param{};
     param.sched_priority = new_priority;
@@ -817,7 +819,7 @@ class PosixConditionHandle : public T, public PosixWaitHandle {
   ~PosixConditionHandle() override = default;
 
   PosixCondition<T>& condition() override { return handle_; }
-  void* native_handle() const override { return handle_.native_handle(); }
+  [[nodiscard]] void* native_handle() const override { return handle_.native_handle(); }
 
  protected:
   PosixCondition<T> handle_;

From 48df797ec683c1f642cddae96c4de1cd9c246fa8 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 09:30:36 +0200
Subject: [PATCH 09/16] Additional memory checks for posix systems

---
 src/xenia/base/memory_posix.cc | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/xenia/base/memory_posix.cc b/src/xenia/base/memory_posix.cc
index d3043bfc2a..30a8ceb0ec 100644
--- a/src/xenia/base/memory_posix.cc
+++ b/src/xenia/base/memory_posix.cc
@@ -61,7 +61,7 @@ void AndroidShutdown() {
 size_t page_size() { return getpagesize(); }
 size_t allocation_granularity() { return page_size(); }
 
-uint32_t ToPosixProtectFlags(PageAccess access) {
+int32_t ToPosixProtectFlags(PageAccess access) {
   switch (access) {
     case PageAccess::kNoAccess:
       return PROT_NONE;
@@ -84,9 +84,9 @@ bool IsWritableExecutableMemorySupported() { return true; }
 void* AllocFixed(void* base_address, size_t length,
                  AllocationType allocation_type, PageAccess access) {
   // mmap does not support reserve / commit, so ignore allocation_type.
-  uint32_t prot = ToPosixProtectFlags(access);
+  int32_t prot = ToPosixProtectFlags(access);
   void * result;
-  if (base_address) {
+  if (base_address != nullptr) {
     result = mmap(base_address, length, prot,
                   MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
   } else {
@@ -94,6 +94,7 @@ void* AllocFixed(void* base_address, size_t length,
                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   }
   if (result == MAP_FAILED) {
+    assert_always();
     return nullptr;
   } else {
     return result;
@@ -110,7 +111,7 @@ bool Protect(void* base_address, size_t length, PageAccess access,
   // Linux does not have a syscall to query memory permissions.
   assert_null(out_old_access);
 
-  uint32_t prot = ToPosixProtectFlags(access);
+  int32_t prot = ToPosixProtectFlags(access);
   return mprotect(base_address, length, prot) == 0;
 }
 
@@ -183,7 +184,7 @@ void CloseFileMappingHandle(FileMappingHandle handle,
 
 void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
                   PageAccess access, size_t file_offset) {
-  uint32_t prot = ToPosixProtectFlags(access);
+  int32_t prot = ToPosixProtectFlags(access);
   return mmap64(base_address, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, handle,
                 file_offset);
 }

From 103ed1a53c71ae701e92518916831032cd16e737 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 13:09:58 +0200
Subject: [PATCH 10/16] Stylisting fixes

---
 premake5.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/premake5.lua b/premake5.lua
index f547d867cf..406d6ca782 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -100,7 +100,7 @@ filter("configurations:Release")
   -- including handling of specials since games make assumptions about them.
 filter("platforms:Linux")
   system("linux")
--- Ccache seems to randomly break the build process, disable it
+  -- Ccache seems to randomly break the build process, disable it
   defines({
     "CCACHE_DISABLE=1"
   })

From fdd44e32a8c58b0050696594a55988ea5a538525 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 13:10:33 +0200
Subject: [PATCH 11/16] Implement ListDirectories and FilterByName in
 filesystem_posix.cc

---
 src/xenia/base/filesystem_posix.cc | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc
index 34b186a810..e38cc2a142 100644
--- a/src/xenia/base/filesystem_posix.cc
+++ b/src/xenia/base/filesystem_posix.cc
@@ -246,6 +246,29 @@ std::vector<FileInfo> ListFiles(const std::filesystem::path& path) {
 
   return result;
 }
+std::vector<FileInfo> ListDirectories(const std::filesystem::path& path) {
+  std::vector<FileInfo> files = ListFiles(path);
+  std::vector<FileInfo> directories = {};
+
+  std::copy_if(
+      files.cbegin(), files.cend(), std::back_inserter(directories),
+      [](FileInfo file) { return file.type == FileInfo::Type::kDirectory; });
+
+  return directories;
+}
+
+std::vector<FileInfo> FilterByName(const std::vector<FileInfo>& files,
+                                   const std::regex pattern) {
+  std::vector<FileInfo> filtered_entries = {};
+
+  std::copy_if(files.cbegin(), files.cend(),
+               std::back_inserter(filtered_entries), [pattern](FileInfo file) {
+                 return std::regex_match(file.name.filename().string(),
+                                         pattern);
+               });
+
+  return filtered_entries;
+}
 
 }  // namespace filesystem
 }  // namespace xe

From f682c947ee4fdf126877e7f7cffe6315afe8d27c Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 13:11:01 +0200
Subject: [PATCH 12/16] Add AVX CPU checks for posix systems

---
 src/xenia/base/main_init_posix.cc | 39 ++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/xenia/base/main_init_posix.cc b/src/xenia/base/main_init_posix.cc
index 28b9767310..0c6e50d14e 100644
--- a/src/xenia/base/main_init_posix.cc
+++ b/src/xenia/base/main_init_posix.cc
@@ -1,3 +1,9 @@
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <xbyak/xbyak/xbyak_util.h>
+
+#include "xenia/ui/window_gtk.h"
+
 /**
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
@@ -7,4 +13,35 @@
  ******************************************************************************
  */
 
-// Nothing. Stub.
+class StartupCpuFeatureCheck {
+ public:
+  StartupCpuFeatureCheck() {
+    Xbyak::util::Cpu cpu;
+    const char* error_message = nullptr;
+    if (!cpu.has(Xbyak::util::Cpu::tAVX)) {
+      error_message =
+          "Your CPU does not support AVX, which is required by Xenia. See "
+          "the "
+          "FAQ for system requirements at https://xenia.jp";
+    }
+    if (error_message == nullptr) {
+      return;
+    } else {
+      GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
+      auto dialog =
+          gtk_message_dialog_new(nullptr, flags, GTK_MESSAGE_ERROR,
+                                 GTK_BUTTONS_CLOSE,error_message);
+      gtk_dialog_run(GTK_DIALOG(dialog));
+      gtk_widget_destroy(dialog);
+      exit(1);
+    }
+  }
+};
+
+// This is a hack to get an instance of StartupAvxCheck
+// constructed before any initialization code,
+// where the AVX check then happens in the constructor.
+// Ref:
+// https://reviews.llvm.org/D12689#243295
+__attribute__((init_priority(101)))
+static StartupCpuFeatureCheck gStartupAvxCheck;
\ No newline at end of file

From 45e26333db6fc54623bf3041239690b0613165a4 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 13:11:54 +0200
Subject: [PATCH 13/16] Redirect console_app_main_posix.cc to a function
 equivalent call for posix systems

---
 src/xenia/base/console_app_main_posix.cc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/xenia/base/console_app_main_posix.cc b/src/xenia/base/console_app_main_posix.cc
index 29a3ae6abd..cb24c36623 100644
--- a/src/xenia/base/console_app_main_posix.cc
+++ b/src/xenia/base/console_app_main_posix.cc
@@ -12,7 +12,7 @@
 
 #include "xenia/base/console_app_main.h"
 #include "xenia/base/cvar.h"
-#include "xenia/base/logging.h"
+#include "xenia/base/main_gnulinux.h"
 
 extern "C" int main(int argc, char** argv) {
   xe::ConsoleAppEntryInfo entry_info = xe::GetConsoleAppEntryInfo();
@@ -23,7 +23,7 @@ extern "C" int main(int argc, char** argv) {
   }
 
   // Initialize logging. Needs parsed cvars.
-  xe::InitializeLogging(entry_info.name);
+  xe::InitializeGNULinuxApp(entry_info.name);
 
   std::vector<std::string> args;
   for (int n = 0; n < argc; n++) {
@@ -32,7 +32,7 @@ extern "C" int main(int argc, char** argv) {
 
   int result = entry_info.entry_point(args);
 
-  xe::ShutdownLogging();
+  xe::ShutdownGNULinuxApp();
 
   return result;
 }

From e07ea71be0aaa0177959ae18f6a1d8fe03499902 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 13:28:21 +0200
Subject: [PATCH 14/16] Implement message box disclaimer for posix systems

---
 src/xenia/emulator.cc | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc
index f929d8d4a2..f902831cf1 100644
--- a/src/xenia/emulator.cc
+++ b/src/xenia/emulator.cc
@@ -12,6 +12,10 @@
 #include <algorithm>
 #include <cinttypes>
 
+#ifdef XE_PLATFORM_LINUX
+#include "xenia/ui/window_gtk.h"
+#endif
+
 #include "config.h"
 #include "third_party/fmt/include/fmt/format.h"
 #include "xenia/apu/audio_system.h"
@@ -137,6 +141,28 @@ Emulator::Emulator(const std::filesystem::path& command_line,
     SetPersistentEmulatorFlags(persistent_flags |
                                EmulatorFlagDisclaimerAcknowledged);
   }
+#else
+  uint64_t persistent_flags = GetPersistentEmulatorFlags();
+  if (!(persistent_flags & EmulatorFlagDisclaimerAcknowledged)) {
+    auto dialog =
+        gtk_message_dialog_new(
+            nullptr, GTK_DIALOG_DESTROY_WITH_PARENT,
+            GTK_MESSAGE_QUESTION,GTK_BUTTONS_YES_NO,
+            "DISCLAIMER: Xenia is not for enabling illegal activity, and "
+            "support is unavailable for illegally obtained software.\n\n"
+            "Please respect this policy as no further reminders will be "
+            "given.\n\nThe quickstart guide explains how to use digital or "
+            "physical games from your Xbox 360 console.\n\nWould you like "
+            "to open it?");
+    if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES) {
+      LaunchWebBrowser(
+          "https://github.com/xenia-project/xenia/wiki/"
+          "Quickstart#how-to-rip-games");
+    };
+    gtk_widget_destroy(dialog);
+    SetPersistentEmulatorFlags(persistent_flags |
+                               EmulatorFlagDisclaimerAcknowledged);
+  }
 #endif
 }
 

From 61ae650c037ef97218659fa1250a03a5e8288ccd Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 13:36:09 +0200
Subject: [PATCH 15/16] Now the achievement code compiles fine on linux, remove
 the ifdefs

---
 src/xenia/kernel/achievement_manager.cc | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/xenia/kernel/achievement_manager.cc b/src/xenia/kernel/achievement_manager.cc
index 6217a2795d..2f66ea9a47 100644
--- a/src/xenia/kernel/achievement_manager.cc
+++ b/src/xenia/kernel/achievement_manager.cc
@@ -53,14 +53,11 @@ void AchievementManager::EarnAchievement(uint64_t xuid, uint32_t title_id,
       if (!cvars::show_achievement_notification) {
         continue;
       }
-      //FIXME(RodoMa92): This call fails to compile under linux, disabled for now
-#ifdef XE_PLATFORM_WINDOWS
       app_context.CallInUIThread([imgui_drawer, description]() {
         new ui::AchievementNotificationWindow(
             imgui_drawer, "Achievement unlocked", description, 0,
             kernel_state()->notification_position_);
       });
-#endif
     }
   }
 }

From cb38522908a6e2d17f1b23caadd14fcb6cc26cf0 Mon Sep 17 00:00:00 2001
From: RodoMa92 <marco.rodolfi@tuta.io>
Date: Sat, 12 Aug 2023 14:01:09 +0200
Subject: [PATCH 16/16] Update copyright year

---
 src/xenia/app/emulator_window.cc          |  2 +-
 src/xenia/apu/conversion.h                |  2 +-
 src/xenia/apu/xma_context.cc              |  2 +-
 src/xenia/base/clock_posix.cc             |  2 +-
 src/xenia/base/console_app_main_posix.cc  |  2 +-
 src/xenia/base/console_posix.cc           |  2 +-
 src/xenia/base/demangle.h                 |  2 +-
 src/xenia/base/demangle_posix.cc          |  2 +-
 src/xenia/base/demangle_win.cc            |  2 +-
 src/xenia/base/exception_handler_posix.cc |  2 +-
 src/xenia/base/filesystem_posix.cc        |  2 +-
 src/xenia/base/main_gnulinux.cc           |  2 +-
 src/xenia/base/main_gnulinux.h            |  2 +-
 src/xenia/base/main_init_posix.cc         | 17 ++++++++---------
 src/xenia/base/mapped_memory_posix.cc     |  2 +-
 src/xenia/base/memory.cc                  |  2 +-
 src/xenia/base/memory.h                   |  2 +-
 src/xenia/base/memory_posix.cc            |  2 +-
 src/xenia/base/platform.h                 |  2 +-
 src/xenia/base/string_buffer.cc           |  2 +-
 src/xenia/base/system_gnulinux.cc         |  2 +-
 src/xenia/base/testing/filesystem_test.cc |  2 +-
 src/xenia/base/testing/memory_test.cc     |  2 +-
 src/xenia/base/testing/string_test.cc     |  2 +-
 src/xenia/base/testing/threading_test.cc  |  2 +-
 src/xenia/base/threading_posix.cc         |  2 +-
 src/xenia/cpu/backend/x64/x64_backend.cc  |  2 +-
 src/xenia/cpu/backend/x64/x64_emitter.cc  |  2 +-
 src/xenia/cpu/backend/x64/x64_emitter.h   |  2 +-
 src/xenia/cpu/backend/x64/x64_tracers.cc  |  2 +-
 src/xenia/cpu/backend/x64/x64_tracers.h   |  2 +-
 src/xenia/cpu/hir/value.cc                |  2 +-
 src/xenia/cpu/hir/value.h                 |  2 +-
 src/xenia/cpu/ppc/ppc_context.h           |  2 +-
 src/xenia/cpu/ppc/ppc_frontend.cc         |  2 +-
 src/xenia/cpu/ppc/ppc_translator.cc       |  2 +-
 src/xenia/cpu/testing/util.h              |  2 +-
 src/xenia/cpu/xex_module.cc               |  2 +-
 src/xenia/emulator.cc                     |  2 +-
 src/xenia/gpu/command_processor.h         |  2 +-
 src/xenia/gpu/draw_util.cc                |  2 +-
 src/xenia/gpu/draw_util.h                 |  2 +-
 src/xenia/gpu/register_file.cc            |  2 +-
 src/xenia/gpu/shared_memory.cc            |  2 +-
 src/xenia/kernel/util/object_table.cc     |  2 +-
 src/xenia/kernel/xam/xam_info.cc          |  2 +-
 src/xenia/kernel/xobject.cc               |  2 +-
 src/xenia/kernel/xsocket.cc               |  2 +-
 src/xenia/memory.cc                       |  2 +-
 src/xenia/memory.h                        |  2 +-
 50 files changed, 57 insertions(+), 58 deletions(-)

diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc
index 4d5293c96b..de17f1d3fe 100644
--- a/src/xenia/app/emulator_window.cc
+++ b/src/xenia/app/emulator_window.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/apu/conversion.h b/src/xenia/apu/conversion.h
index 7318c54290..0ad1dcad01 100644
--- a/src/xenia/apu/conversion.h
+++ b/src/xenia/apu/conversion.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc
index d6473807e0..6cbfd23f64 100644
--- a/src/xenia/apu/xma_context.cc
+++ b/src/xenia/apu/xma_context.cc
@@ -2,7 +2,7 @@
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
-* Copyright 2021 Ben Vanik. All rights reserved.                             *
+* Copyright 2023 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */
diff --git a/src/xenia/base/clock_posix.cc b/src/xenia/base/clock_posix.cc
index 0ec830e90d..edd321efe7 100644
--- a/src/xenia/base/clock_posix.cc
+++ b/src/xenia/base/clock_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/console_app_main_posix.cc b/src/xenia/base/console_app_main_posix.cc
index cb24c36623..f35212c370 100644
--- a/src/xenia/base/console_app_main_posix.cc
+++ b/src/xenia/base/console_app_main_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/console_posix.cc b/src/xenia/base/console_posix.cc
index adfa4c73cb..bee4ac17f9 100644
--- a/src/xenia/base/console_posix.cc
+++ b/src/xenia/base/console_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/demangle.h b/src/xenia/base/demangle.h
index 6fbdab9a9e..29162878af 100644
--- a/src/xenia/base/demangle.h
+++ b/src/xenia/base/demangle.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/demangle_posix.cc b/src/xenia/base/demangle_posix.cc
index 4e50e3dbb7..310edd5a9a 100644
--- a/src/xenia/base/demangle_posix.cc
+++ b/src/xenia/base/demangle_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/demangle_win.cc b/src/xenia/base/demangle_win.cc
index 84a46a437e..6fe811fe82 100644
--- a/src/xenia/base/demangle_win.cc
+++ b/src/xenia/base/demangle_win.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/exception_handler_posix.cc b/src/xenia/base/exception_handler_posix.cc
index d7a8a2d5ab..5c659f6ad9 100644
--- a/src/xenia/base/exception_handler_posix.cc
+++ b/src/xenia/base/exception_handler_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc
index e38cc2a142..b6327706dd 100644
--- a/src/xenia/base/filesystem_posix.cc
+++ b/src/xenia/base/filesystem_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/main_gnulinux.cc b/src/xenia/base/main_gnulinux.cc
index 9165746c79..90e43a5be2 100644
--- a/src/xenia/base/main_gnulinux.cc
+++ b/src/xenia/base/main_gnulinux.cc
@@ -2,7 +2,7 @@
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
-* Copyright 2023 Marco Rodolfi. All rights reserved.                         *
+* Copyright 2023 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */
diff --git a/src/xenia/base/main_gnulinux.h b/src/xenia/base/main_gnulinux.h
index e5af826a68..937d7606c3 100644
--- a/src/xenia/base/main_gnulinux.h
+++ b/src/xenia/base/main_gnulinux.h
@@ -2,7 +2,7 @@
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
-* Copyright 2021 Ben Vanik. All rights reserved.                             *
+* Copyright 2023 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */
diff --git a/src/xenia/base/main_init_posix.cc b/src/xenia/base/main_init_posix.cc
index 0c6e50d14e..1d125cc8e0 100644
--- a/src/xenia/base/main_init_posix.cc
+++ b/src/xenia/base/main_init_posix.cc
@@ -1,18 +1,17 @@
+/**
+******************************************************************************
+* Xenia : Xbox 360 Emulator Research Project                                 *
+******************************************************************************
+* Copyright 2023 Ben Vanik. All rights reserved.                             *
+* Released under the BSD license - see LICENSE in the root for more details. *
+******************************************************************************
+*/
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <xbyak/xbyak/xbyak_util.h>
 
 #include "xenia/ui/window_gtk.h"
 
-/**
- ******************************************************************************
- * Xenia : Xbox 360 Emulator Research Project                                 *
- ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
- * Released under the BSD license - see LICENSE in the root for more details. *
- ******************************************************************************
- */
-
 class StartupCpuFeatureCheck {
  public:
   StartupCpuFeatureCheck() {
diff --git a/src/xenia/base/mapped_memory_posix.cc b/src/xenia/base/mapped_memory_posix.cc
index 09cd5a962a..4d2b760189 100644
--- a/src/xenia/base/mapped_memory_posix.cc
+++ b/src/xenia/base/mapped_memory_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/memory.cc b/src/xenia/base/memory.cc
index c8fab9ad96..daf7fc7e3c 100644
--- a/src/xenia/base/memory.cc
+++ b/src/xenia/base/memory.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/memory.h b/src/xenia/base/memory.h
index e449746574..446e477b7b 100644
--- a/src/xenia/base/memory.h
+++ b/src/xenia/base/memory.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/memory_posix.cc b/src/xenia/base/memory_posix.cc
index 30a8ceb0ec..71110e9f28 100644
--- a/src/xenia/base/memory_posix.cc
+++ b/src/xenia/base/memory_posix.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/platform.h b/src/xenia/base/platform.h
index 0c7475b580..6a77aa749e 100644
--- a/src/xenia/base/platform.h
+++ b/src/xenia/base/platform.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/string_buffer.cc b/src/xenia/base/string_buffer.cc
index f94fd6c880..0fdb4b5b48 100644
--- a/src/xenia/base/string_buffer.cc
+++ b/src/xenia/base/string_buffer.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/system_gnulinux.cc b/src/xenia/base/system_gnulinux.cc
index 91ba0a580f..c8c84b353a 100644
--- a/src/xenia/base/system_gnulinux.cc
+++ b/src/xenia/base/system_gnulinux.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/testing/filesystem_test.cc b/src/xenia/base/testing/filesystem_test.cc
index 2829e6b9d5..6d7ca64cfb 100644
--- a/src/xenia/base/testing/filesystem_test.cc
+++ b/src/xenia/base/testing/filesystem_test.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2019 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/testing/memory_test.cc b/src/xenia/base/testing/memory_test.cc
index c670a65a24..6830547fb9 100644
--- a/src/xenia/base/testing/memory_test.cc
+++ b/src/xenia/base/testing/memory_test.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/base/testing/string_test.cc b/src/xenia/base/testing/string_test.cc
index 654f7d440a..ad1a1a50ed 100644
--- a/src/xenia/base/testing/string_test.cc
+++ b/src/xenia/base/testing/string_test.cc
@@ -2,7 +2,7 @@
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
-* Copyright 2019 Ben Vanik. All rights reserved.                             *
+* Copyright 2023 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */
diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc
index f19af2647b..21d6677401 100644
--- a/src/xenia/base/testing/threading_test.cc
+++ b/src/xenia/base/testing/threading_test.cc
@@ -2,7 +2,7 @@
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
-* Copyright 2022 Ben Vanik. All rights reserved.                             *
+* Copyright 2023 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */
diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc
index 4e041ef67f..e5c4c8cd41 100644
--- a/src/xenia/base/threading_posix.cc
+++ b/src/xenia/base/threading_posix.cc
@@ -129,7 +129,7 @@ void install_signal_handler(SignalType type) {
     signal_handler_installed[static_cast<size_t>(type)] = true;
 }
 
-// FIXME: The process is already enabled to run all all cores of the machine
+// FIXME: The process is already enabled to run on all cores of the machine
 // by default.
 void EnableAffinityConfiguration() {
 }
diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc
index e05d5d6e7e..54a3ac62d3 100644
--- a/src/xenia/cpu/backend/x64/x64_backend.cc
+++ b/src/xenia/cpu/backend/x64/x64_backend.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc
index 7265eb8f4b..eade73f89a 100644
--- a/src/xenia/cpu/backend/x64/x64_emitter.cc
+++ b/src/xenia/cpu/backend/x64/x64_emitter.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/backend/x64/x64_emitter.h b/src/xenia/cpu/backend/x64/x64_emitter.h
index 1ddd44b5db..5811ed647f 100644
--- a/src/xenia/cpu/backend/x64/x64_emitter.h
+++ b/src/xenia/cpu/backend/x64/x64_emitter.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/backend/x64/x64_tracers.cc b/src/xenia/cpu/backend/x64/x64_tracers.cc
index 727808225e..31b1eb9781 100644
--- a/src/xenia/cpu/backend/x64/x64_tracers.cc
+++ b/src/xenia/cpu/backend/x64/x64_tracers.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/backend/x64/x64_tracers.h b/src/xenia/cpu/backend/x64/x64_tracers.h
index 4a6d0c18f6..12304c63fd 100644
--- a/src/xenia/cpu/backend/x64/x64_tracers.h
+++ b/src/xenia/cpu/backend/x64/x64_tracers.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/hir/value.cc b/src/xenia/cpu/hir/value.cc
index c05d442ac8..4c1f5b71a6 100644
--- a/src/xenia/cpu/hir/value.cc
+++ b/src/xenia/cpu/hir/value.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/hir/value.h b/src/xenia/cpu/hir/value.h
index 15eaf7827f..b9b718c15b 100644
--- a/src/xenia/cpu/hir/value.h
+++ b/src/xenia/cpu/hir/value.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2013 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/ppc/ppc_context.h b/src/xenia/cpu/ppc/ppc_context.h
index 5122b5673d..c78b4ce50c 100644
--- a/src/xenia/cpu/ppc/ppc_context.h
+++ b/src/xenia/cpu/ppc/ppc_context.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/ppc/ppc_frontend.cc b/src/xenia/cpu/ppc/ppc_frontend.cc
index d7d839573c..5ec46fe8a2 100644
--- a/src/xenia/cpu/ppc/ppc_frontend.cc
+++ b/src/xenia/cpu/ppc/ppc_frontend.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2013 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/ppc/ppc_translator.cc b/src/xenia/cpu/ppc/ppc_translator.cc
index d01213a07b..b7ea5cd389 100644
--- a/src/xenia/cpu/ppc/ppc_translator.cc
+++ b/src/xenia/cpu/ppc/ppc_translator.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2013 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/testing/util.h b/src/xenia/cpu/testing/util.h
index 34e80157bc..d6f40c930f 100644
--- a/src/xenia/cpu/testing/util.h
+++ b/src/xenia/cpu/testing/util.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2014 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc
index 2e7d2863da..be8f8429ba 100644
--- a/src/xenia/cpu/xex_module.cc
+++ b/src/xenia/cpu/xex_module.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc
index f902831cf1..7b8f503812 100644
--- a/src/xenia/emulator.cc
+++ b/src/xenia/emulator.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2021 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h
index 7c2e5d3d63..b0a01d400a 100644
--- a/src/xenia/gpu/command_processor.h
+++ b/src/xenia/gpu/command_processor.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/gpu/draw_util.cc b/src/xenia/gpu/draw_util.cc
index 43413efb1d..0c61f4ed5f 100644
--- a/src/xenia/gpu/draw_util.cc
+++ b/src/xenia/gpu/draw_util.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h
index bff56c6b2c..524850d071 100644
--- a/src/xenia/gpu/draw_util.h
+++ b/src/xenia/gpu/draw_util.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/gpu/register_file.cc b/src/xenia/gpu/register_file.cc
index ecc21c6dbd..9ba9d6a5ff 100644
--- a/src/xenia/gpu/register_file.cc
+++ b/src/xenia/gpu/register_file.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2014 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/gpu/shared_memory.cc b/src/xenia/gpu/shared_memory.cc
index 416a27bd95..7d68c38e9f 100644
--- a/src/xenia/gpu/shared_memory.cc
+++ b/src/xenia/gpu/shared_memory.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/kernel/util/object_table.cc b/src/xenia/kernel/util/object_table.cc
index cf707ea10d..8875264d99 100644
--- a/src/xenia/kernel/util/object_table.cc
+++ b/src/xenia/kernel/util/object_table.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc
index f749251261..3cd20fe0ac 100644
--- a/src/xenia/kernel/xam/xam_info.cc
+++ b/src/xenia/kernel/xam/xam_info.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc
index 7a0fd0ec52..a2a9290e8a 100644
--- a/src/xenia/kernel/xobject.cc
+++ b/src/xenia/kernel/xobject.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2022 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/kernel/xsocket.cc b/src/xenia/kernel/xsocket.cc
index 6667ab8100..01c3df5315 100644
--- a/src/xenia/kernel/xsocket.cc
+++ b/src/xenia/kernel/xsocket.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2013 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc
index b67a38ad64..b63f21b81c 100644
--- a/src/xenia/memory.cc
+++ b/src/xenia/memory.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
diff --git a/src/xenia/memory.h b/src/xenia/memory.h
index 992f859a3f..60ef96eef7 100644
--- a/src/xenia/memory.h
+++ b/src/xenia/memory.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * Xenia : Xbox 360 Emulator Research Project                                 *
  ******************************************************************************
- * Copyright 2020 Ben Vanik. All rights reserved.                             *
+ * Copyright 2023 Ben Vanik. All rights reserved.                             *
  * Released under the BSD license - see LICENSE in the root for more details. *
  ******************************************************************************
  */
openSUSE Build Service is sponsored by