Compare commits
1 Commits
5de1f23228
...
f9db312fd0
Author | SHA1 | Date |
---|---|---|
The-Little-Wolf | f9db312fd0 |
|
@ -31,6 +31,7 @@
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
#include "xenia/emulator.h"
|
#include "xenia/emulator.h"
|
||||||
#include "xenia/gpu/command_processor.h"
|
#include "xenia/gpu/command_processor.h"
|
||||||
|
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
|
||||||
#include "xenia/gpu/graphics_system.h"
|
#include "xenia/gpu/graphics_system.h"
|
||||||
#include "xenia/hid/input_system.h"
|
#include "xenia/hid/input_system.h"
|
||||||
#include "xenia/kernel/xam/profile_manager.h"
|
#include "xenia/kernel/xam/profile_manager.h"
|
||||||
|
@ -57,9 +58,7 @@ DECLARE_bool(guide_button);
|
||||||
|
|
||||||
DECLARE_bool(clear_memory_page_state);
|
DECLARE_bool(clear_memory_page_state);
|
||||||
|
|
||||||
DECLARE_bool(readback_resolve);
|
DECLARE_bool(d3d12_readback_resolve);
|
||||||
|
|
||||||
DECLARE_bool(readback_memexport);
|
|
||||||
|
|
||||||
DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.",
|
DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.",
|
||||||
"Display");
|
"Display");
|
||||||
|
@ -1663,19 +1662,14 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
|
||||||
xe::threading::Sleep(delay);
|
xe::threading::Sleep(delay);
|
||||||
break;
|
break;
|
||||||
case ButtonFunctions::RunTitle: {
|
case ButtonFunctions::RunTitle: {
|
||||||
if (selected_title_index == -1) {
|
if (selected_title_index == -1) selected_title_index++;
|
||||||
selected_title_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selected_title_index < recently_launched_titles_.size()) {
|
app_context().CallInUIThread([this]() {
|
||||||
app_context().CallInUIThread([this]() {
|
RunTitle(recently_launched_titles_[selected_title_index].path_to_file);
|
||||||
RunTitle(
|
});
|
||||||
recently_launched_titles_[selected_title_index].path_to_file);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case ButtonFunctions::ClearMemoryPageState:
|
case ButtonFunctions::ClearMemoryPageState:
|
||||||
ToggleGPUSetting(GPUSetting::ClearMemoryPageState);
|
ToggleGPUSetting(gpu_cvar::ClearMemoryPageState);
|
||||||
|
|
||||||
// Assume the user wants ClearCaches as well
|
// Assume the user wants ClearCaches as well
|
||||||
if (cvars::clear_memory_page_state) {
|
if (cvars::clear_memory_page_state) {
|
||||||
|
@ -1690,10 +1684,10 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
|
||||||
xe::threading::Sleep(delay);
|
xe::threading::Sleep(delay);
|
||||||
break;
|
break;
|
||||||
case ButtonFunctions::ReadbackResolve:
|
case ButtonFunctions::ReadbackResolve:
|
||||||
ToggleGPUSetting(GPUSetting::ReadbackResolve);
|
ToggleGPUSetting(gpu_cvar::ReadbackResolve);
|
||||||
|
|
||||||
notificationTitle = "Toggle Readback Resolve";
|
notificationTitle = "Toggle Readback Resolve";
|
||||||
notificationDesc = cvars::readback_resolve ? "Enabled" : "Disabled";
|
notificationDesc = cvars::d3d12_readback_resolve ? "Enabled" : "Disabled";
|
||||||
|
|
||||||
// Extra Sleep
|
// Extra Sleep
|
||||||
xe::threading::Sleep(delay);
|
xe::threading::Sleep(delay);
|
||||||
|
@ -1765,9 +1759,8 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
|
||||||
if ((button_combination.function == ButtonFunctions::IncTitleSelect ||
|
if ((button_combination.function == ButtonFunctions::IncTitleSelect ||
|
||||||
button_combination.function == ButtonFunctions::DecTitleSelect) &&
|
button_combination.function == ButtonFunctions::DecTitleSelect) &&
|
||||||
recently_launched_titles_.size() > 0) {
|
recently_launched_titles_.size() > 0) {
|
||||||
selected_title_index =
|
selected_title_index = std::clamp(
|
||||||
std::clamp(selected_title_index, 0,
|
selected_title_index, 0, (int)recently_launched_titles_.size() - 1);
|
||||||
static_cast<int32_t>(recently_launched_titles_.size() - 1));
|
|
||||||
|
|
||||||
// Must clear dialogs to prevent stacking
|
// Must clear dialogs to prevent stacking
|
||||||
ClearDialogs();
|
ClearDialogs();
|
||||||
|
@ -1863,17 +1856,15 @@ void EmulatorWindow::GamepadHotKeys() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatorWindow::ToggleGPUSetting(gpu::GPUSetting setting) {
|
void EmulatorWindow::ToggleGPUSetting(gpu_cvar value) {
|
||||||
switch (setting) {
|
switch (value) {
|
||||||
case GPUSetting::ClearMemoryPageState:
|
case gpu_cvar::ClearMemoryPageState:
|
||||||
SaveGPUSetting(GPUSetting::ClearMemoryPageState,
|
CommonSaveGPUSetting(CommonGPUSetting::ClearMemoryPageState,
|
||||||
!cvars::clear_memory_page_state);
|
!cvars::clear_memory_page_state);
|
||||||
break;
|
break;
|
||||||
case GPUSetting::ReadbackResolve:
|
case gpu_cvar::ReadbackResolve:
|
||||||
SaveGPUSetting(GPUSetting::ReadbackResolve, !cvars::readback_resolve);
|
D3D12SaveGPUSetting(D3D12GPUSetting::ReadbackResolve,
|
||||||
break;
|
!cvars::d3d12_readback_resolve);
|
||||||
case GPUSetting::ReadbackMemexport:
|
|
||||||
SaveGPUSetting(GPUSetting::ReadbackMemexport, !cvars::readback_memexport);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1918,7 +1909,7 @@ void EmulatorWindow::DisplayHotKeysConfig() {
|
||||||
msg += "\n";
|
msg += "\n";
|
||||||
|
|
||||||
msg += "Readback Resolve: " +
|
msg += "Readback Resolve: " +
|
||||||
xe::string_util::BoolToString(cvars::readback_resolve);
|
xe::string_util::BoolToString(cvars::d3d12_readback_resolve);
|
||||||
msg += "\n";
|
msg += "\n";
|
||||||
|
|
||||||
msg += "Clear Memory Page State: " +
|
msg += "Clear Memory Page State: " +
|
||||||
|
|
|
@ -112,6 +112,11 @@ class EmulatorWindow {
|
||||||
Unknown
|
Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class gpu_cvar {
|
||||||
|
ClearMemoryPageState,
|
||||||
|
ReadbackResolve,
|
||||||
|
};
|
||||||
|
|
||||||
class ControllerHotKey {
|
class ControllerHotKey {
|
||||||
public:
|
public:
|
||||||
// If true the hotkey can be activated while a title is running, otherwise
|
// If true the hotkey can be activated while a title is running, otherwise
|
||||||
|
@ -230,7 +235,7 @@ class EmulatorWindow {
|
||||||
void VibrateController(xe::hid::InputSystem* input_sys, uint32_t user_index,
|
void VibrateController(xe::hid::InputSystem* input_sys, uint32_t user_index,
|
||||||
bool vibrate = true);
|
bool vibrate = true);
|
||||||
void GamepadHotKeys();
|
void GamepadHotKeys();
|
||||||
void ToggleGPUSetting(gpu::GPUSetting setting);
|
void ToggleGPUSetting(gpu_cvar index);
|
||||||
void DisplayHotKeysConfig();
|
void DisplayHotKeysConfig();
|
||||||
|
|
||||||
static std::string CanonicalizeFileExtension(
|
static std::string CanonicalizeFileExtension(
|
||||||
|
|
|
@ -402,7 +402,6 @@ class Timer : public WaitHandle {
|
||||||
virtual bool Cancel() = 0;
|
virtual bool Cancel() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if XE_PLATFORM_WIN32
|
|
||||||
struct ThreadPriority {
|
struct ThreadPriority {
|
||||||
static const int32_t kLowest = -2;
|
static const int32_t kLowest = -2;
|
||||||
static const int32_t kBelowNormal = -1;
|
static const int32_t kBelowNormal = -1;
|
||||||
|
@ -410,15 +409,6 @@ struct ThreadPriority {
|
||||||
static const int32_t kAboveNormal = 1;
|
static const int32_t kAboveNormal = 1;
|
||||||
static const int32_t kHighest = 2;
|
static const int32_t kHighest = 2;
|
||||||
};
|
};
|
||||||
#else
|
|
||||||
struct ThreadPriority {
|
|
||||||
static const int32_t kLowest = 1;
|
|
||||||
static const int32_t kBelowNormal = 8;
|
|
||||||
static const int32_t kNormal = 16;
|
|
||||||
static const int32_t kAboveNormal = 24;
|
|
||||||
static const int32_t kHighest = 32;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Models a Win32-like thread object.
|
// Models a Win32-like thread object.
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "logging.h"
|
|
||||||
|
|
||||||
#if XE_PLATFORM_ANDROID
|
#if XE_PLATFORM_ANDROID
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
@ -662,18 +660,8 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
WaitStarted();
|
WaitStarted();
|
||||||
sched_param param{};
|
sched_param param{};
|
||||||
param.sched_priority = new_priority;
|
param.sched_priority = new_priority;
|
||||||
int res = pthread_setschedparam(thread_, SCHED_FIFO, ¶m);
|
if (pthread_setschedparam(thread_, SCHED_FIFO, ¶m) != 0)
|
||||||
if (res != 0) {
|
assert_always();
|
||||||
switch (res) {
|
|
||||||
case EPERM:
|
|
||||||
XELOGW("Permission denied while setting priority");
|
|
||||||
break;
|
|
||||||
case EINVAL:
|
|
||||||
assert_always();
|
|
||||||
default:
|
|
||||||
XELOGW("Unknown error while setting priority");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueueUserCallback(std::function<void()> callback) {
|
void QueueUserCallback(std::function<void()> callback) {
|
||||||
|
|
|
@ -505,7 +505,6 @@ Emulator::FileSignatureType Emulator::GetFileSignature(
|
||||||
return FileSignatureType::XISO;
|
return FileSignatureType::XISO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XELOGE("{}: {} ({:08X})", __func__, path.extension(), magic_value);
|
XELOGE("{}: {} ({:08X})", __func__, path.extension(), magic_value);
|
||||||
return FileSignatureType::Unknown;
|
return FileSignatureType::Unknown;
|
||||||
}
|
}
|
||||||
|
@ -1373,12 +1372,6 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
||||||
return X_STATUS_NOT_FOUND;
|
return X_STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!module->is_executable()) {
|
|
||||||
kernel_state_->UnloadUserModule(module, false);
|
|
||||||
XELOGE("Failed to load user module {}", path);
|
|
||||||
return X_STATUS_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
X_RESULT result = kernel_state_->ApplyTitleUpdate(module);
|
X_RESULT result = kernel_state_->ApplyTitleUpdate(module);
|
||||||
if (XFAILED(result)) {
|
if (XFAILED(result)) {
|
||||||
XELOGE("Failed to apply title update! Cannot run module {}", path);
|
XELOGE("Failed to apply title update! Cannot run module {}", path);
|
||||||
|
|
|
@ -50,52 +50,17 @@ DEFINE_bool(clear_memory_page_state, false,
|
||||||
"for 'Team Ninja' Games to fix missing character models)",
|
"for 'Team Ninja' Games to fix missing character models)",
|
||||||
"GPU");
|
"GPU");
|
||||||
|
|
||||||
DEFINE_bool(
|
|
||||||
readback_resolve, false,
|
|
||||||
"[D3D12 Only] Read render-to-texture results on the CPU. This may be "
|
|
||||||
"needed in some games, for instance, for screenshots in saved games, but "
|
|
||||||
"causes mid-frame synchronization, so it has a huge performance impact.",
|
|
||||||
"GPU");
|
|
||||||
|
|
||||||
DEFINE_bool(
|
|
||||||
readback_memexport, false,
|
|
||||||
"[D3D12 Only] Read data written by memory export in shaders on the CPU. "
|
|
||||||
"This may be needed in some games (but many only access exported data on "
|
|
||||||
"the GPU, and this flag isn't needed to handle such behavior), but causes "
|
|
||||||
"mid-frame synchronization, so it has a huge performance impact.",
|
|
||||||
"GPU");
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
// This should be written completely differently with support for different
|
void CommonSaveGPUSetting(CommonGPUSetting setting, uint64_t value) {
|
||||||
// types.
|
|
||||||
void SaveGPUSetting(GPUSetting setting, uint64_t value) {
|
|
||||||
switch (setting) {
|
switch (setting) {
|
||||||
case GPUSetting::ClearMemoryPageState:
|
case CommonGPUSetting::ClearMemoryPageState:
|
||||||
OVERRIDE_bool(clear_memory_page_state, static_cast<bool>(value));
|
OVERRIDE_bool(clear_memory_page_state, (bool)value);
|
||||||
break;
|
|
||||||
case GPUSetting::ReadbackResolve:
|
|
||||||
OVERRIDE_bool(readback_resolve, static_cast<bool>(value));
|
|
||||||
break;
|
|
||||||
case GPUSetting::ReadbackMemexport:
|
|
||||||
OVERRIDE_bool(readback_memexport, static_cast<bool>(value));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetGPUSetting(GPUSetting setting) {
|
|
||||||
switch (setting) {
|
|
||||||
case GPUSetting::ClearMemoryPageState:
|
|
||||||
return cvars::clear_memory_page_state;
|
|
||||||
case GPUSetting::ReadbackResolve:
|
|
||||||
return cvars::readback_resolve;
|
|
||||||
case GPUSetting::ReadbackMemexport:
|
|
||||||
return cvars::readback_memexport;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace xe::gpu::xenos;
|
using namespace xe::gpu::xenos;
|
||||||
|
|
||||||
CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system,
|
CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system,
|
||||||
|
|
|
@ -33,14 +33,11 @@ class ByteStream;
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
enum class GPUSetting {
|
enum class CommonGPUSetting {
|
||||||
ClearMemoryPageState,
|
ClearMemoryPageState,
|
||||||
ReadbackResolve,
|
|
||||||
ReadbackMemexport
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void SaveGPUSetting(GPUSetting setting, uint64_t value);
|
void CommonSaveGPUSetting(CommonGPUSetting setting, uint64_t value);
|
||||||
bool GetGPUSetting(GPUSetting setting);
|
|
||||||
|
|
||||||
class GraphicsSystem;
|
class GraphicsSystem;
|
||||||
class Shader;
|
class Shader;
|
||||||
|
|
|
@ -32,7 +32,19 @@ DEFINE_bool(d3d12_bindless, true,
|
||||||
"Use bindless resources where available - may improve performance, "
|
"Use bindless resources where available - may improve performance, "
|
||||||
"but may make debugging more complicated.",
|
"but may make debugging more complicated.",
|
||||||
"D3D12");
|
"D3D12");
|
||||||
|
DEFINE_bool(d3d12_readback_memexport, false,
|
||||||
|
"Read data written by memory export in shaders on the CPU. This "
|
||||||
|
"may be needed in some games (but many only access exported data "
|
||||||
|
"on the GPU, and this flag isn't needed to handle such behavior), "
|
||||||
|
"but causes mid-frame synchronization, so it has a huge "
|
||||||
|
"performance impact.",
|
||||||
|
"D3D12");
|
||||||
|
DEFINE_bool(d3d12_readback_resolve, false,
|
||||||
|
"Read render-to-texture results on the CPU. This may be needed in "
|
||||||
|
"some games, for instance, for screenshots in saved games, but "
|
||||||
|
"causes mid-frame synchronization, so it has a huge performance "
|
||||||
|
"impact.",
|
||||||
|
"D3D12");
|
||||||
DEFINE_bool(d3d12_submit_on_primary_buffer_end, true,
|
DEFINE_bool(d3d12_submit_on_primary_buffer_end, true,
|
||||||
"Submit the command list when a PM4 primary buffer ends if it's "
|
"Submit the command list when a PM4 primary buffer ends if it's "
|
||||||
"possible to submit immediately to try to reduce frame latency.",
|
"possible to submit immediately to try to reduce frame latency.",
|
||||||
|
@ -42,6 +54,15 @@ DECLARE_bool(clear_memory_page_state);
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
void D3D12SaveGPUSetting(D3D12GPUSetting setting, uint64_t value) {
|
||||||
|
switch (setting) {
|
||||||
|
case D3D12GPUSetting::ReadbackResolve:
|
||||||
|
OVERRIDE_bool(d3d12_readback_resolve, (bool)value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
// Generated with `xb buildshaders`.
|
// Generated with `xb buildshaders`.
|
||||||
|
@ -2990,7 +3011,7 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
|
||||||
memexport_range.base_address_dwords << 2, memexport_range.size_bytes,
|
memexport_range.base_address_dwords << 2, memexport_range.size_bytes,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
if (GetGPUSetting(GPUSetting::ReadbackResolve)) {
|
if (cvars::d3d12_readback_memexport) {
|
||||||
// Read the exported data on the CPU.
|
// Read the exported data on the CPU.
|
||||||
uint32_t memexport_total_size = 0;
|
uint32_t memexport_total_size = 0;
|
||||||
for (const draw_util::MemExportRange& memexport_range :
|
for (const draw_util::MemExportRange& memexport_range :
|
||||||
|
@ -3070,7 +3091,7 @@ bool D3D12CommandProcessor::IssueCopy() {
|
||||||
if (!BeginSubmission(true)) {
|
if (!BeginSubmission(true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!GetGPUSetting(GPUSetting::ReadbackResolve)) {
|
if (!cvars::d3d12_readback_resolve) {
|
||||||
uint32_t written_address, written_length;
|
uint32_t written_address, written_length;
|
||||||
return render_target_cache_->Resolve(*memory_, *shared_memory_,
|
return render_target_cache_->Resolve(*memory_, *shared_memory_,
|
||||||
*texture_cache_, written_address,
|
*texture_cache_, written_address,
|
||||||
|
|
|
@ -93,12 +93,6 @@ inline std::string_view TranslateAnsiString(const Memory* memory,
|
||||||
ansi_string->length);
|
ansi_string->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string TranslateAnsiPath(const Memory* memory,
|
|
||||||
const X_ANSI_STRING* ansi_string) {
|
|
||||||
return string_util::trim(
|
|
||||||
std::string(TranslateAnsiString(memory, ansi_string)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string_view TranslateAnsiStringAddress(const Memory* memory,
|
inline std::string_view TranslateAnsiStringAddress(const Memory* memory,
|
||||||
uint32_t guest_address) {
|
uint32_t guest_address) {
|
||||||
if (!guest_address) {
|
if (!guest_address) {
|
||||||
|
|
|
@ -106,12 +106,6 @@ std::filesystem::path ContentManager::ResolvePackagePath(
|
||||||
uint64_t used_xuid =
|
uint64_t used_xuid =
|
||||||
(data.xuid != -1 && data.xuid != 0) ? data.xuid.get() : xuid;
|
(data.xuid != -1 && data.xuid != 0) ? data.xuid.get() : xuid;
|
||||||
|
|
||||||
// All DLCs are stored in common directory, so we need to override xuid for
|
|
||||||
// them and probably some other types.
|
|
||||||
if (data.content_type == XContentType::kMarketplaceContent) {
|
|
||||||
used_xuid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto package_root =
|
auto package_root =
|
||||||
ResolvePackageRoot(used_xuid, title_id, data.content_type);
|
ResolvePackageRoot(used_xuid, title_id, data.content_type);
|
||||||
std::string final_name = xe::string_util::trim(data.file_name());
|
std::string final_name = xe::string_util::trim(data.file_name());
|
||||||
|
|
|
@ -15,40 +15,7 @@ namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xam {
|
namespace xam {
|
||||||
|
|
||||||
dword_result_t XamProfileFindAccount_entry(
|
dword_result_t XamProfileOpen_entry(qword_t xuid, lpstring_t mount_path) {
|
||||||
qword_t offline_xuid, pointer_t<X_XAMACCOUNTINFO> account_ptr,
|
|
||||||
lpdword_t device_id) {
|
|
||||||
if (!account_ptr) {
|
|
||||||
return X_ERROR_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
account_ptr.Zero();
|
|
||||||
|
|
||||||
const auto& account =
|
|
||||||
kernel_state()->xam_state()->profile_manager()->GetAccount(offline_xuid);
|
|
||||||
|
|
||||||
if (!account) {
|
|
||||||
return X_ERROR_NO_SUCH_USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::memcpy(account_ptr, &account, sizeof(X_XAMACCOUNTINFO));
|
|
||||||
|
|
||||||
xe::string_util::copy_and_swap_truncating(
|
|
||||||
account_ptr->gamertag, account->gamertag, sizeof(account->gamertag));
|
|
||||||
|
|
||||||
if (device_id) {
|
|
||||||
*device_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return X_ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
DECLARE_XAM_EXPORT1(XamProfileFindAccount, kUserProfiles, kImplemented);
|
|
||||||
|
|
||||||
dword_result_t XamProfileOpen_entry(qword_t xuid, lpstring_t mount_path,
|
|
||||||
dword_t flags, lpvoid_t content_data) {
|
|
||||||
/* Notes:
|
|
||||||
- If xuid is not local then returns X_ERROR_INVALID_PARAMETER
|
|
||||||
*/
|
|
||||||
const bool result =
|
const bool result =
|
||||||
kernel_state()->xam_state()->profile_manager()->MountProfile(
|
kernel_state()->xam_state()->profile_manager()->MountProfile(
|
||||||
xuid, mount_path.value());
|
xuid, mount_path.value());
|
||||||
|
@ -57,17 +24,6 @@ dword_result_t XamProfileOpen_entry(qword_t xuid, lpstring_t mount_path,
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamProfileOpen, kNone, kImplemented);
|
DECLARE_XAM_EXPORT1(XamProfileOpen, kNone, kImplemented);
|
||||||
|
|
||||||
dword_result_t XamProfileCreate_entry(dword_t flags, lpdword_t device_id,
|
|
||||||
qword_t xuid,
|
|
||||||
pointer_t<X_XAMACCOUNTINFO> account,
|
|
||||||
dword_t unk1, dword_t unk2, dword_t unk3,
|
|
||||||
dword_t unk4) {
|
|
||||||
// **unk4
|
|
||||||
|
|
||||||
return X_ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
DECLARE_XAM_EXPORT1(XamProfileCreate, kNone, kStub);
|
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -799,18 +799,6 @@ dword_result_t XamUserGetUserFlagsFromXUID_entry(qword_t xuid) {
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamUserGetUserFlagsFromXUID, kUserProfiles, kImplemented);
|
DECLARE_XAM_EXPORT1(XamUserGetUserFlagsFromXUID, kUserProfiles, kImplemented);
|
||||||
|
|
||||||
dword_result_t XamUserGetOnlineLanguageFromXUID_entry(qword_t xuid) {
|
|
||||||
/* Notes:
|
|
||||||
- Calls XamUserGetUserFlagsFromXUID and returns (ulonglong)(cached_flag <<
|
|
||||||
0x20) >> 0x39 & 0x1f;
|
|
||||||
- XamUserGetMembershipTierFromXUID and XamUserGetOnlineCountryFromXUID also
|
|
||||||
call it
|
|
||||||
- Removed in metro
|
|
||||||
*/
|
|
||||||
return cvars::user_language;
|
|
||||||
}
|
|
||||||
DECLARE_XAM_EXPORT1(XamUserGetOnlineLanguageFromXUID, kUserProfiles, kStub);
|
|
||||||
|
|
||||||
constexpr uint8_t kStatsMaxAmount = 64;
|
constexpr uint8_t kStatsMaxAmount = 64;
|
||||||
|
|
||||||
struct X_STATS_DETAILS {
|
struct X_STATS_DETAILS {
|
||||||
|
@ -856,6 +844,35 @@ dword_result_t XamUserCreateStatsEnumerator_entry(
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamUserCreateStatsEnumerator, kUserProfiles, kSketchy);
|
DECLARE_XAM_EXPORT1(XamUserCreateStatsEnumerator, kUserProfiles, kSketchy);
|
||||||
|
|
||||||
|
dword_result_t XamProfileFindAccount_entry(
|
||||||
|
qword_t offline_xuid, pointer_t<X_XAMACCOUNTINFO> account_ptr,
|
||||||
|
lpdword_t device_id) {
|
||||||
|
if (!account_ptr) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
account_ptr.Zero();
|
||||||
|
|
||||||
|
const auto& account =
|
||||||
|
kernel_state()->xam_state()->profile_manager()->GetAccount(offline_xuid);
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
return X_ERROR_NO_SUCH_USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(account_ptr, &account, sizeof(X_XAMACCOUNTINFO));
|
||||||
|
|
||||||
|
xe::string_util::copy_and_swap_truncating(
|
||||||
|
account_ptr->gamertag, account->gamertag, sizeof(account->gamertag));
|
||||||
|
|
||||||
|
if (device_id) {
|
||||||
|
*device_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamProfileFindAccount, kUserProfiles, kImplemented);
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -63,7 +63,7 @@ dword_result_t NtCreateFile_entry(lpdword_t handle_out, dword_t desired_access,
|
||||||
vfs::Entry* root_entry = nullptr;
|
vfs::Entry* root_entry = nullptr;
|
||||||
|
|
||||||
// Compute path, possibly attrs relative.
|
// Compute path, possibly attrs relative.
|
||||||
auto target_path = util::TranslateAnsiPath(kernel_memory(), object_name);
|
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
|
||||||
|
|
||||||
// Enforce that the path is ASCII.
|
// Enforce that the path is ASCII.
|
||||||
if (!IsValidPath(target_path, false)) {
|
if (!IsValidPath(target_path, false)) {
|
||||||
|
@ -462,7 +462,7 @@ dword_result_t NtQueryFullAttributesFile_entry(
|
||||||
assert_always();
|
assert_always();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto target_path = util::TranslateAnsiPath(kernel_memory(), object_name);
|
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
|
||||||
|
|
||||||
// Enforce that the path is ASCII.
|
// Enforce that the path is ASCII.
|
||||||
if (!IsValidPath(target_path, false)) {
|
if (!IsValidPath(target_path, false)) {
|
||||||
|
@ -501,7 +501,7 @@ dword_result_t NtQueryDirectoryFile_entry(
|
||||||
uint32_t info = 0;
|
uint32_t info = 0;
|
||||||
|
|
||||||
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
|
||||||
auto name = util::TranslateAnsiPath(kernel_memory(), file_name);
|
auto name = util::TranslateAnsiString(kernel_memory(), file_name);
|
||||||
|
|
||||||
// Enforce that the path is ASCII.
|
// Enforce that the path is ASCII.
|
||||||
if (!IsValidPath(name, true)) {
|
if (!IsValidPath(name, true)) {
|
||||||
|
@ -558,7 +558,7 @@ dword_result_t NtOpenSymbolicLinkObject_entry(
|
||||||
auto object_name =
|
auto object_name =
|
||||||
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
|
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
|
||||||
|
|
||||||
auto target_path = util::TranslateAnsiPath(kernel_memory(), object_name);
|
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
|
||||||
|
|
||||||
// Enforce that the path is ASCII.
|
// Enforce that the path is ASCII.
|
||||||
if (!IsValidPath(target_path, false)) {
|
if (!IsValidPath(target_path, false)) {
|
||||||
|
|
|
@ -234,7 +234,7 @@ dword_result_t NtSetInformationFile_entry(
|
||||||
auto info = info_ptr.as<X_FILE_RENAME_INFORMATION*>();
|
auto info = info_ptr.as<X_FILE_RENAME_INFORMATION*>();
|
||||||
// Compute path, possibly attrs relative.
|
// Compute path, possibly attrs relative.
|
||||||
std::filesystem::path target_path =
|
std::filesystem::path target_path =
|
||||||
util::TranslateAnsiPath(kernel_memory(), &info->ansi_string);
|
util::TranslateAnsiString(kernel_memory(), &info->ansi_string);
|
||||||
|
|
||||||
// Place IsValidPath in path from where it can be accessed everywhere
|
// Place IsValidPath in path from where it can be accessed everywhere
|
||||||
if (!IsValidPath(target_path.string(), false)) {
|
if (!IsValidPath(target_path.string(), false)) {
|
||||||
|
|
|
@ -263,7 +263,7 @@ dword_result_t XexLoadImageHeaders_entry(pointer_t<X_ANSI_STRING> path,
|
||||||
return X_STATUS_BUFFER_TOO_SMALL;
|
return X_STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
auto current_kernel = ctx->kernel_state;
|
auto current_kernel = ctx->kernel_state;
|
||||||
auto target_path = util::TranslateAnsiPath(current_kernel->memory(), path);
|
auto target_path = util::TranslateAnsiString(current_kernel->memory(), path);
|
||||||
|
|
||||||
vfs::File* vfs_file = nullptr;
|
vfs::File* vfs_file = nullptr;
|
||||||
vfs::FileAction file_action;
|
vfs::FileAction file_action;
|
||||||
|
|
|
@ -350,9 +350,9 @@ DECLARE_XBOXKRNL_EXPORT1(ObReferenceObject, kNone, kImplemented);
|
||||||
dword_result_t ObCreateSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr,
|
dword_result_t ObCreateSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr,
|
||||||
pointer_t<X_ANSI_STRING> target_ptr) {
|
pointer_t<X_ANSI_STRING> target_ptr) {
|
||||||
auto path = xe::utf8::canonicalize_guest_path(
|
auto path = xe::utf8::canonicalize_guest_path(
|
||||||
util::TranslateAnsiPath(kernel_memory(), path_ptr));
|
util::TranslateAnsiString(kernel_memory(), path_ptr));
|
||||||
auto target = xe::utf8::canonicalize_guest_path(
|
auto target = xe::utf8::canonicalize_guest_path(
|
||||||
util::TranslateAnsiPath(kernel_memory(), target_ptr));
|
util::TranslateAnsiString(kernel_memory(), target_ptr));
|
||||||
|
|
||||||
if (xe::utf8::starts_with(path, "\\??\\")) {
|
if (xe::utf8::starts_with(path, "\\??\\")) {
|
||||||
path = path.substr(4); // Strip the full qualifier
|
path = path.substr(4); // Strip the full qualifier
|
||||||
|
@ -367,7 +367,7 @@ dword_result_t ObCreateSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr,
|
||||||
DECLARE_XBOXKRNL_EXPORT1(ObCreateSymbolicLink, kNone, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(ObCreateSymbolicLink, kNone, kImplemented);
|
||||||
|
|
||||||
dword_result_t ObDeleteSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr) {
|
dword_result_t ObDeleteSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr) {
|
||||||
auto path = util::TranslateAnsiPath(kernel_memory(), path_ptr);
|
auto path = util::TranslateAnsiString(kernel_memory(), path_ptr);
|
||||||
if (!kernel_state()->file_system()->UnregisterSymbolicLink(path)) {
|
if (!kernel_state()->file_system()->UnregisterSymbolicLink(path)) {
|
||||||
return X_STATUS_UNSUCCESSFUL;
|
return X_STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,9 +98,9 @@ static bool IsValidPath(const std::string_view s, bool is_pattern) {
|
||||||
case '+':
|
case '+':
|
||||||
case ',':
|
case ',':
|
||||||
// case ':':
|
// case ':':
|
||||||
// case ';':
|
case ';':
|
||||||
case '<':
|
case '<':
|
||||||
// case '=':
|
case '=':
|
||||||
case '>':
|
case '>':
|
||||||
// case '?':
|
// case '?':
|
||||||
case '|': {
|
case '|': {
|
||||||
|
|
|
@ -48,8 +48,8 @@ void PluginLoader::LoadConfigs() {
|
||||||
xe::filesystem::FilterByName(dir_files, std::regex("[A-Fa-f0-9]{8}"));
|
xe::filesystem::FilterByName(dir_files, std::regex("[A-Fa-f0-9]{8}"));
|
||||||
|
|
||||||
for (const auto& entry : dir_files) {
|
for (const auto& entry : dir_files) {
|
||||||
const uint32_t title_id = string_util::from_string<uint32_t>(
|
const uint32_t title_id =
|
||||||
entry.name.filename().string(), true);
|
std::stoi(entry.name.filename().string(), nullptr, 16);
|
||||||
|
|
||||||
LoadTitleConfig(title_id);
|
LoadTitleConfig(title_id);
|
||||||
}
|
}
|
||||||
|
|
16
xenia-build
16
xenia-build
|
@ -17,7 +17,6 @@ import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import stat
|
|
||||||
|
|
||||||
__author__ = 'ben.vanik@gmail.com (Ben Vanik)'
|
__author__ = 'ben.vanik@gmail.com (Ben Vanik)'
|
||||||
|
|
||||||
|
@ -1280,25 +1279,12 @@ class GenTestsCommand(Command):
|
||||||
print('Generating test binaries...')
|
print('Generating test binaries...')
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
binutils_path = os.path.join('third_party', 'binutils-ppc-cygwin')
|
||||||
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_as = os.path.join(binutils_path, 'powerpc-none-elf-as')
|
||||||
ppc_ld = os.path.join(binutils_path, 'powerpc-none-elf-ld')
|
ppc_ld = os.path.join(binutils_path, 'powerpc-none-elf-ld')
|
||||||
ppc_objdump = os.path.join(binutils_path, 'powerpc-none-elf-objdump')
|
ppc_objdump = os.path.join(binutils_path, 'powerpc-none-elf-objdump')
|
||||||
ppc_nm = os.path.join(binutils_path, 'powerpc-none-elf-nm')
|
ppc_nm = os.path.join(binutils_path, 'powerpc-none-elf-nm')
|
||||||
|
|
||||||
if not os.path.exists(ppc_as) and sys.platform == 'linux':
|
|
||||||
print('Binaries are missing, binutils build required')
|
|
||||||
print('')
|
|
||||||
shell_script = os.path.join('third_party', 'binutils', 'build.sh')
|
|
||||||
# Set executable bit for build script before running it
|
|
||||||
os.chmod(shell_script, stat.S_IRUSR | stat.S_IWUSR |
|
|
||||||
stat.S_IXUSR | stat.S_IRGRP | stat.S_IROTH)
|
|
||||||
shell_call([shell_script])
|
|
||||||
|
|
||||||
test_src = os.path.join('src', 'xenia', 'cpu', 'ppc', 'testing')
|
test_src = os.path.join('src', 'xenia', 'cpu', 'ppc', 'testing')
|
||||||
test_bin = os.path.join(test_src, 'bin')
|
test_bin = os.path.join(test_src, 'bin')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue