diff --git a/src/xenia/base/clock_posix.cc b/src/xenia/base/clock_posix.cc index 73a23dc76..f5e2f6805 100644 --- a/src/xenia/base/clock_posix.cc +++ b/src/xenia/base/clock_posix.cc @@ -53,4 +53,7 @@ uint64_t Clock::QueryHostUptimeMillis() { return host_tick_count_platform() * 1000 / host_tick_frequency_platform(); } +uint64_t Clock::QueryHostInterruptTime() { + return host_tick_count_platform(); +} } // namespace xe diff --git a/src/xenia/base/filesystem.cc b/src/xenia/base/filesystem.cc index d7b7b647d..b3515e9cc 100644 --- a/src/xenia/base/filesystem.cc +++ b/src/xenia/base/filesystem.cc @@ -24,5 +24,28 @@ bool CreateParentFolder(const std::filesystem::path& path) { return true; } +std::vector ListDirectories(const std::filesystem::path& path) { + std::vector files = ListFiles(path); + std::vector directories = {}; + + std::copy_if( + files.cbegin(), files.cend(), std::back_inserter(directories), + [](const FileInfo& file) { return file.type == FileInfo::Type::kDirectory; }); + + return std::move(directories); +} + +std::vector FilterByName(const std::vector& files, + const std::regex pattern) { + std::vector filtered_entries = {}; + + std::copy_if(files.cbegin(), files.cend(), + std::back_inserter(filtered_entries), [pattern](const FileInfo& file) { + return std::regex_match(file.name.filename().string(), + pattern); + }); + return std::move(filtered_entries); +} + } // namespace filesystem } // namespace xe diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index 73b06271c..e3addec4b 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -192,20 +192,27 @@ std::unique_ptr FileHandle::OpenExisting( return std::make_unique(path, handle); } -bool GetInfo(const std::filesystem::path& path, FileInfo* out_info) { +std::optional GetInfo(const std::filesystem::path& path) { + FileInfo info{}; struct stat st; if (stat(path.c_str(), &st) == 0) { if (S_ISDIR(st.st_mode)) { - out_info->type = FileInfo::Type::kDirectory; + info.type = FileInfo::Type::kDirectory; + // On Linux st.st_size can have non-zero size (generally 4096) so make 0 + info.total_size = 0; } else { - out_info->type = FileInfo::Type::kFile; + info.type = FileInfo::Type::kFile; + 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); - return true; + info.path = path.parent_path(); + info.name = path.filename(); + info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime); + info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atime); + info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime); + return std::move(info); } - return false; + return {}; } std::vector ListFiles(const std::filesystem::path& path) { @@ -240,7 +247,7 @@ std::vector ListFiles(const std::filesystem::path& path) { result.push_back(info); } closedir(dir); - return result; + return std::move(result); } bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) { diff --git a/src/xenia/base/main_init_posix.cc b/src/xenia/base/main_init_posix.cc new file mode 100644 index 000000000..1d125cc8e --- /dev/null +++ b/src/xenia/base/main_init_posix.cc @@ -0,0 +1,46 @@ +/** +****************************************************************************** +* 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 +#include +#include + +#include "xenia/ui/window_gtk.h" + +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 diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 733592800..dcd374f16 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -161,6 +161,10 @@ void Sleep(std::chrono::microseconds duration) { } while (ret == -1 && errno == EINTR); } +void NanoSleep(int64_t duration) { + Sleep(std::chrono::nanoseconds(duration)); +} + // TODO(bwrsandman) Implement by allowing alert interrupts from IO operations thread_local bool alertable_state_ = false; SleepResult AlertableSleep(std::chrono::microseconds duration) {