Compare commits

...

16 Commits

Author SHA1 Message Date
The-Little-Wolf 5de1f23228 Reapply "Merge remote-tracking branch 'upstream/canary_experimental' into canary_experimental"
This reverts commit fd3484f48753d2690d28a8cdd08f6b26f7c31336.
2025-01-17 15:22:42 -08:00
The-Little-Wolf 4d19245c4a Revert "Merge remote-tracking branch 'upstream/canary_experimental' into canary_experimental"
This reverts commit 6ac1f2b285035350bdbf2ed751d88caec13d60d7, reversing
changes made to 65cf0d7c059d0ed452b177449fe8a1bc57c630d6.
2025-01-17 15:22:42 -08:00
The-Little-Wolf 247d16ffe7 [Xboxkrnl/XConfig] add user audio config
- Allows for user to set their audio type in the config
- Record audio flags and how they function
2025-01-17 15:22:42 -08:00
Gliniak 6ac53cb982 [Emulator] Added logging file extension and magic value 2025-01-17 15:21:51 -08:00
Gliniak 0474053931 [GPU] Improvements to GPU settings modification
- Renamed CommonGPUSetting to GPUSetting
- Removed readback_resolve and memexport from d3d12 exclusive option. In the future it will be available for Vulkan too.
- Removed unused enum class: gpu_cvar
- Removed OS specific code from emulator_window
2025-01-17 20:40:53 +01:00
Gliniak 85695692a7 [Base] Fixed issues with thread priority introduced in previous commit 2025-01-17 19:51:18 +01:00
Marco Rodolfi 55bbb28a80 [threading] Linux fixes on setting an incorrect priority
This call was failing since SCHED_FIFO doesn't support negative priorities, but only positive ones, see third paragraph of scheduling policies: https://man7.org/linux/man-pages/man7/sched.7.html.

Additionally Linux do provice up to 99 levels, but I've limited myself to the required UNIX standard of 32, and split the priority levels evenly from that.

I've also added a couple of rows to debug additional issues in the future like this.
2025-01-17 09:56:43 +01:00
The-Little-Wolf 4d7b30e844 [Xam/XamUser] - Stub XamUserGetOnlineLanguageFromXUID
- Stubs XamUserGetOnlineLanguageFromXUID and have it return cvars::user_language
- Leave notes for future implementation once we have proper profile support
2025-01-17 08:32:46 +01:00
Adrian ae23222ba8 [Emulator] Validate module is an executable before launching 2025-01-17 08:04:49 +01:00
Adrian d99d053408 [Patcher] Replace stoi with from_string for parsing plugin title id 2025-01-16 15:08:20 +01:00
Gliniak 1688ea5d69 [Kernel] Replaced TranslateAnsiString with TranslateAnsiPath for file paths.
This removes paths that starts or ends with whitespace characters
2025-01-14 22:45:43 +01:00
Gliniak e80d4effa1 [Kernel] IsValidPath: Removed ; and = from invalid characters list
Path like: fxprefabs;scale=fx_dropship_02_fade.* is processed as a proper one internally and it expects no file error instead of invalid parameter
2025-01-14 21:05:00 +01:00
Gliniak 57da74814b [XAM] Fixed issue with missing DLCs due to invalid XUID 2025-01-12 17:01:20 +01:00
The-Little-Wolf a77213dcdb [Xam/Xam_Profile] - Stub XamProfileCreate and more
- Move XamProfileFindAccount
- Leave notes for XamProfileOpen
- Stub XamProfileCreate
2025-01-12 16:31:39 +01:00
Adrian e134bbccd1 [App] Fixed RunTitle crash via hotkey 2025-01-12 16:11:16 +01:00
Marco Rodolfi 1822bca890 [BUILD] Fix build test generation for Linux systems
This allows a Linux system to generate all the PPC tests just by running ./xb gentests as on a Windows system. Tested locally.
2025-01-12 13:45:50 +01:00
22 changed files with 230 additions and 103 deletions

View File

@ -31,7 +31,6 @@
#include "xenia/cpu/processor.h"
#include "xenia/emulator.h"
#include "xenia/gpu/command_processor.h"
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/hid/input_system.h"
#include "xenia/kernel/xam/profile_manager.h"
@ -58,7 +57,9 @@ DECLARE_bool(guide_button);
DECLARE_bool(clear_memory_page_state);
DECLARE_bool(d3d12_readback_resolve);
DECLARE_bool(readback_resolve);
DECLARE_bool(readback_memexport);
DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.",
"Display");
@ -1662,14 +1663,19 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
xe::threading::Sleep(delay);
break;
case ButtonFunctions::RunTitle: {
if (selected_title_index == -1) selected_title_index++;
if (selected_title_index == -1) {
selected_title_index++;
}
app_context().CallInUIThread([this]() {
RunTitle(recently_launched_titles_[selected_title_index].path_to_file);
});
if (selected_title_index < recently_launched_titles_.size()) {
app_context().CallInUIThread([this]() {
RunTitle(
recently_launched_titles_[selected_title_index].path_to_file);
});
}
} break;
case ButtonFunctions::ClearMemoryPageState:
ToggleGPUSetting(gpu_cvar::ClearMemoryPageState);
ToggleGPUSetting(GPUSetting::ClearMemoryPageState);
// Assume the user wants ClearCaches as well
if (cvars::clear_memory_page_state) {
@ -1684,10 +1690,10 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
xe::threading::Sleep(delay);
break;
case ButtonFunctions::ReadbackResolve:
ToggleGPUSetting(gpu_cvar::ReadbackResolve);
ToggleGPUSetting(GPUSetting::ReadbackResolve);
notificationTitle = "Toggle Readback Resolve";
notificationDesc = cvars::d3d12_readback_resolve ? "Enabled" : "Disabled";
notificationDesc = cvars::readback_resolve ? "Enabled" : "Disabled";
// Extra Sleep
xe::threading::Sleep(delay);
@ -1759,8 +1765,9 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
if ((button_combination.function == ButtonFunctions::IncTitleSelect ||
button_combination.function == ButtonFunctions::DecTitleSelect) &&
recently_launched_titles_.size() > 0) {
selected_title_index = std::clamp(
selected_title_index, 0, (int)recently_launched_titles_.size() - 1);
selected_title_index =
std::clamp(selected_title_index, 0,
static_cast<int32_t>(recently_launched_titles_.size() - 1));
// Must clear dialogs to prevent stacking
ClearDialogs();
@ -1856,15 +1863,17 @@ void EmulatorWindow::GamepadHotKeys() {
}
}
void EmulatorWindow::ToggleGPUSetting(gpu_cvar value) {
switch (value) {
case gpu_cvar::ClearMemoryPageState:
CommonSaveGPUSetting(CommonGPUSetting::ClearMemoryPageState,
!cvars::clear_memory_page_state);
void EmulatorWindow::ToggleGPUSetting(gpu::GPUSetting setting) {
switch (setting) {
case GPUSetting::ClearMemoryPageState:
SaveGPUSetting(GPUSetting::ClearMemoryPageState,
!cvars::clear_memory_page_state);
break;
case gpu_cvar::ReadbackResolve:
D3D12SaveGPUSetting(D3D12GPUSetting::ReadbackResolve,
!cvars::d3d12_readback_resolve);
case GPUSetting::ReadbackResolve:
SaveGPUSetting(GPUSetting::ReadbackResolve, !cvars::readback_resolve);
break;
case GPUSetting::ReadbackMemexport:
SaveGPUSetting(GPUSetting::ReadbackMemexport, !cvars::readback_memexport);
break;
}
}
@ -1909,7 +1918,7 @@ void EmulatorWindow::DisplayHotKeysConfig() {
msg += "\n";
msg += "Readback Resolve: " +
xe::string_util::BoolToString(cvars::d3d12_readback_resolve);
xe::string_util::BoolToString(cvars::readback_resolve);
msg += "\n";
msg += "Clear Memory Page State: " +

View File

@ -112,11 +112,6 @@ class EmulatorWindow {
Unknown
};
enum class gpu_cvar {
ClearMemoryPageState,
ReadbackResolve,
};
class ControllerHotKey {
public:
// If true the hotkey can be activated while a title is running, otherwise
@ -235,7 +230,7 @@ class EmulatorWindow {
void VibrateController(xe::hid::InputSystem* input_sys, uint32_t user_index,
bool vibrate = true);
void GamepadHotKeys();
void ToggleGPUSetting(gpu_cvar index);
void ToggleGPUSetting(gpu::GPUSetting setting);
void DisplayHotKeysConfig();
static std::string CanonicalizeFileExtension(

View File

@ -402,6 +402,7 @@ class Timer : public WaitHandle {
virtual bool Cancel() = 0;
};
#if XE_PLATFORM_WIN32
struct ThreadPriority {
static const int32_t kLowest = -2;
static const int32_t kBelowNormal = -1;
@ -409,6 +410,15 @@ struct ThreadPriority {
static const int32_t kAboveNormal = 1;
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.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx

View File

@ -27,6 +27,8 @@
#include <ctime>
#include <memory>
#include "logging.h"
#if XE_PLATFORM_ANDROID
#include <dlfcn.h>
@ -660,8 +662,18 @@ class PosixCondition<Thread> : public PosixConditionBase {
WaitStarted();
sched_param param{};
param.sched_priority = new_priority;
if (pthread_setschedparam(thread_, SCHED_FIFO, &param) != 0)
assert_always();
int res = pthread_setschedparam(thread_, SCHED_FIFO, &param);
if (res != 0) {
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) {

View File

@ -505,6 +505,7 @@ Emulator::FileSignatureType Emulator::GetFileSignature(
return FileSignatureType::XISO;
}
XELOGE("{}: {} ({:08X})", __func__, path.extension(), magic_value);
return FileSignatureType::Unknown;
}
@ -1372,6 +1373,12 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
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);
if (XFAILED(result)) {
XELOGE("Failed to apply title update! Cannot run module {}", path);

View File

@ -50,17 +50,52 @@ DEFINE_bool(clear_memory_page_state, false,
"for 'Team Ninja' Games to fix missing character models)",
"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 gpu {
void CommonSaveGPUSetting(CommonGPUSetting setting, uint64_t value) {
// This should be written completely differently with support for different
// types.
void SaveGPUSetting(GPUSetting setting, uint64_t value) {
switch (setting) {
case CommonGPUSetting::ClearMemoryPageState:
OVERRIDE_bool(clear_memory_page_state, (bool)value);
case GPUSetting::ClearMemoryPageState:
OVERRIDE_bool(clear_memory_page_state, static_cast<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;
}
}
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;
CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system,

View File

@ -33,11 +33,14 @@ class ByteStream;
namespace gpu {
enum class CommonGPUSetting {
enum class GPUSetting {
ClearMemoryPageState,
ReadbackResolve,
ReadbackMemexport
};
void CommonSaveGPUSetting(CommonGPUSetting setting, uint64_t value);
void SaveGPUSetting(GPUSetting setting, uint64_t value);
bool GetGPUSetting(GPUSetting setting);
class GraphicsSystem;
class Shader;

View File

@ -32,19 +32,7 @@ DEFINE_bool(d3d12_bindless, true,
"Use bindless resources where available - may improve performance, "
"but may make debugging more complicated.",
"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,
"Submit the command list when a PM4 primary buffer ends if it's "
"possible to submit immediately to try to reduce frame latency.",
@ -54,15 +42,6 @@ DECLARE_bool(clear_memory_page_state);
namespace xe {
namespace gpu {
void D3D12SaveGPUSetting(D3D12GPUSetting setting, uint64_t value) {
switch (setting) {
case D3D12GPUSetting::ReadbackResolve:
OVERRIDE_bool(d3d12_readback_resolve, (bool)value);
break;
}
}
namespace d3d12 {
// Generated with `xb buildshaders`.
@ -3011,7 +2990,7 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
memexport_range.base_address_dwords << 2, memexport_range.size_bytes,
false);
}
if (cvars::d3d12_readback_memexport) {
if (GetGPUSetting(GPUSetting::ReadbackResolve)) {
// Read the exported data on the CPU.
uint32_t memexport_total_size = 0;
for (const draw_util::MemExportRange& memexport_range :
@ -3091,7 +3070,7 @@ bool D3D12CommandProcessor::IssueCopy() {
if (!BeginSubmission(true)) {
return false;
}
if (!cvars::d3d12_readback_resolve) {
if (!GetGPUSetting(GPUSetting::ReadbackResolve)) {
uint32_t written_address, written_length;
return render_target_cache_->Resolve(*memory_, *shared_memory_,
*texture_cache_, written_address,

View File

@ -93,6 +93,12 @@ inline std::string_view TranslateAnsiString(const Memory* memory,
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,
uint32_t guest_address) {
if (!guest_address) {

View File

@ -106,6 +106,12 @@ std::filesystem::path ContentManager::ResolvePackagePath(
uint64_t used_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 =
ResolvePackageRoot(used_xuid, title_id, data.content_type);
std::string final_name = xe::string_util::trim(data.file_name());

View File

@ -44,6 +44,7 @@ DEFINE_int32(avpack, 8,
"Video");
DECLARE_int32(user_country);
DECLARE_int32(user_language);
DECLARE_uint32(audio_flag);
DEFINE_bool(staging_mode, 0,
"Enables preview mode in dashboards to render debug information.",
@ -648,7 +649,7 @@ dword_result_t lstrlenW_entry(lpu16string_t string) {
}
DECLARE_XAM_EXPORT1(lstrlenW, kNone, kImplemented);
dword_result_t XGetAudioFlags_entry() { return 65537; }
dword_result_t XGetAudioFlags_entry() { return cvars::audio_flag; }
DECLARE_XAM_EXPORT1(XGetAudioFlags, kNone, kStub);
/*

View File

@ -15,7 +15,40 @@ namespace xe {
namespace kernel {
namespace xam {
dword_result_t XamProfileOpen_entry(qword_t xuid, lpstring_t mount_path) {
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);
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 =
kernel_state()->xam_state()->profile_manager()->MountProfile(
xuid, mount_path.value());
@ -24,6 +57,17 @@ dword_result_t XamProfileOpen_entry(qword_t xuid, lpstring_t mount_path) {
}
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 kernel
} // namespace xe

View File

@ -799,6 +799,18 @@ dword_result_t XamUserGetUserFlagsFromXUID_entry(qword_t xuid) {
}
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;
struct X_STATS_DETAILS {
@ -844,35 +856,6 @@ dword_result_t XamUserCreateStatsEnumerator_entry(
}
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 kernel
} // namespace xe

View File

@ -15,12 +15,14 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/xbox.h"
DECLARE_uint32(audio_flag);
namespace xe {
namespace kernel {
namespace xboxkrnl {
dword_result_t XAudioGetSpeakerConfig_entry(lpdword_t config_ptr) {
*config_ptr = 0x00010001;
*config_ptr = cvars::audio_flag;
return X_ERROR_SUCCESS;
}
DECLARE_XBOXKRNL_EXPORT1(XAudioGetSpeakerConfig, kAudio, kImplemented);

View File

@ -63,7 +63,7 @@ dword_result_t NtCreateFile_entry(lpdword_t handle_out, dword_t desired_access,
vfs::Entry* root_entry = nullptr;
// Compute path, possibly attrs relative.
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
auto target_path = util::TranslateAnsiPath(kernel_memory(), object_name);
// Enforce that the path is ASCII.
if (!IsValidPath(target_path, false)) {
@ -462,7 +462,7 @@ dword_result_t NtQueryFullAttributesFile_entry(
assert_always();
}
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
auto target_path = util::TranslateAnsiPath(kernel_memory(), object_name);
// Enforce that the path is ASCII.
if (!IsValidPath(target_path, false)) {
@ -501,7 +501,7 @@ dword_result_t NtQueryDirectoryFile_entry(
uint32_t info = 0;
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
auto name = util::TranslateAnsiString(kernel_memory(), file_name);
auto name = util::TranslateAnsiPath(kernel_memory(), file_name);
// Enforce that the path is ASCII.
if (!IsValidPath(name, true)) {
@ -558,7 +558,7 @@ dword_result_t NtOpenSymbolicLinkObject_entry(
auto object_name =
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
auto target_path = util::TranslateAnsiPath(kernel_memory(), object_name);
// Enforce that the path is ASCII.
if (!IsValidPath(target_path, false)) {

View File

@ -234,7 +234,7 @@ dword_result_t NtSetInformationFile_entry(
auto info = info_ptr.as<X_FILE_RENAME_INFORMATION*>();
// Compute path, possibly attrs relative.
std::filesystem::path target_path =
util::TranslateAnsiString(kernel_memory(), &info->ansi_string);
util::TranslateAnsiPath(kernel_memory(), &info->ansi_string);
// Place IsValidPath in path from where it can be accessed everywhere
if (!IsValidPath(target_path.string(), false)) {

View File

@ -263,7 +263,7 @@ dword_result_t XexLoadImageHeaders_entry(pointer_t<X_ANSI_STRING> path,
return X_STATUS_BUFFER_TOO_SMALL;
}
auto current_kernel = ctx->kernel_state;
auto target_path = util::TranslateAnsiString(current_kernel->memory(), path);
auto target_path = util::TranslateAnsiPath(current_kernel->memory(), path);
vfs::File* vfs_file = nullptr;
vfs::FileAction file_action;

View File

@ -350,9 +350,9 @@ DECLARE_XBOXKRNL_EXPORT1(ObReferenceObject, kNone, kImplemented);
dword_result_t ObCreateSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr,
pointer_t<X_ANSI_STRING> target_ptr) {
auto path = xe::utf8::canonicalize_guest_path(
util::TranslateAnsiString(kernel_memory(), path_ptr));
util::TranslateAnsiPath(kernel_memory(), path_ptr));
auto target = xe::utf8::canonicalize_guest_path(
util::TranslateAnsiString(kernel_memory(), target_ptr));
util::TranslateAnsiPath(kernel_memory(), target_ptr));
if (xe::utf8::starts_with(path, "\\??\\")) {
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);
dword_result_t ObDeleteSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr) {
auto path = util::TranslateAnsiString(kernel_memory(), path_ptr);
auto path = util::TranslateAnsiPath(kernel_memory(), path_ptr);
if (!kernel_state()->file_system()->UnregisterSymbolicLink(path)) {
return X_STATUS_UNSUCCESSFUL;
}

View File

@ -37,6 +37,23 @@ DEFINE_int32(user_country, 103,
" 102=UA 103=US 104=UY 105=UZ 106=VE 107=VN 108=YE 109=ZA\n",
"XConfig");
DEFINE_uint32(
audio_flag, 0x00010001,
"Audio Mode Analog.\n"
" 0x00000001 = Dolby Pro Logic\n"
" 0x00000002 = Analog Mono\n"
"Audio Mode Digital.\n"
" 0x00000000 = Digital Stereo (choose one of the above by itself)\n"
" 0x00010000 = Dolby Digital\n"
" 0x00030000 = Dolby Digital with WMA PRO\n"
"Special Flags.\n"
" 0x00000003 = Stereo Bypass\n"
" 0x80000000 = Low Latency\n"
" This Config requires you to pair an analog and digitial flag together\n"
" while digital stereo only requires an analog flag. Bonus flags are\n"
" optional. Ex) 0x00010001\n",
"XConfig");
DECLARE_bool(widescreen);
DECLARE_bool(use_50Hz_mode);
DECLARE_int32(video_standard);
@ -109,6 +126,10 @@ X_STATUS xeExGetXConfigSetting(uint16_t category, uint16_t setting,
xe::store_and_swap<uint32_t>(
value, cvars::widescreen ? 0x00050000 : 0x00040000);
break;
case 0x000B: // XCONFIG_USER_AUDIO_FLAGS
setting_size = 4;
xe::store_and_swap<uint32_t>(value, cvars::audio_flag);
break;
case 0x000C: // XCONFIG_USER_RETAIL_FLAGS
setting_size = 4;
// TODO(benvanik): get this value.

View File

@ -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 '|': {

View File

@ -48,8 +48,8 @@ void PluginLoader::LoadConfigs() {
xe::filesystem::FilterByName(dir_files, std::regex("[A-Fa-f0-9]{8}"));
for (const auto& entry : dir_files) {
const uint32_t title_id =
std::stoi(entry.name.filename().string(), nullptr, 16);
const uint32_t title_id = string_util::from_string<uint32_t>(
entry.name.filename().string(), true);
LoadTitleConfig(title_id);
}

View File

@ -17,6 +17,7 @@ import re
import shutil
import subprocess
import sys
import stat
__author__ = 'ben.vanik@gmail.com (Ben Vanik)'
@ -1279,12 +1280,25 @@ 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')
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_bin = os.path.join(test_src, 'bin')