C++17ification.

C++17ification!

- Filesystem interaction now uses std::filesystem::path.
- Usage of const char*, std::string have been changed to
  std::string_view where appropriate.
- Usage of printf-style functions changed to use fmt.
This commit is contained in:
gibbed
2020-03-02 09:37:11 -06:00
committed by Rick Gibbed
parent 114cea6fb7
commit 5bf0b34445
220 changed files with 4944 additions and 4294 deletions

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -19,14 +19,15 @@
namespace xe {
namespace kernel {
KernelModule::KernelModule(KernelState* kernel_state, const char* path)
KernelModule::KernelModule(KernelState* kernel_state,
const std::string_view path)
: XModule(kernel_state, ModuleType::kKernelModule) {
emulator_ = kernel_state->emulator();
memory_ = emulator_->memory();
export_resolver_ = kernel_state->emulator()->export_resolver();
path_ = path;
name_ = NameFromPath(path);
name_ = utf8::find_base_name_from_guest_path(path);
// Persist this object through reloads.
host_object_ = true;
@@ -48,7 +49,7 @@ KernelModule::KernelModule(KernelState* kernel_state, const char* path)
emulator_->processor()->AddModule(std::move(module));
} else {
XELOGW("KernelModule %s could not allocate trampoline for GetProcAddress!",
path);
path.c_str());
}
OnLoad();
@@ -143,7 +144,7 @@ uint32_t KernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
}
}
uint32_t KernelModule::GetProcAddressByName(const char* name) {
uint32_t KernelModule::GetProcAddressByName(const std::string_view name) {
// TODO: Does this even work for kernel modules?
XELOGE("KernelModule::GetProcAddressByName not implemented");
return 0;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -26,17 +26,23 @@ class KernelState;
class KernelModule : public XModule {
public:
KernelModule(KernelState* kernel_state, const char* path);
KernelModule(KernelState* kernel_state, const std::string_view path);
~KernelModule() override;
const std::string& path() const override { return path_; }
const std::string& name() const override { return name_; }
uint32_t GetProcAddressByOrdinal(uint16_t ordinal) override;
uint32_t GetProcAddressByName(const char* name) override;
uint32_t GetProcAddressByName(const std::string_view name) override;
protected:
Emulator* emulator_;
Memory* memory_;
xe::cpu::ExportResolver* export_resolver_;
std::string name_;
std::string path_;
// Guest trampoline for GetProcAddress
static const uint32_t kTrampolineSize = 400 * 8;
uint32_t guest_trampoline_ = 0;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -11,6 +11,7 @@
#include <string>
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/base/assert.h"
#include "xenia/base/byte_stream.h"
#include "xenia/base/logging.h"
@@ -51,7 +52,7 @@ KernelState::KernelState(Emulator* emulator)
user_profile_ = std::make_unique<xam::UserProfile>();
auto content_root = emulator_->content_root();
content_root = xe::to_absolute_path(content_root);
content_root = std::filesystem::absolute(content_root);
content_manager_ = std::make_unique<xam::ContentManager>(this, content_root);
assert_null(shared_kernel_state_);
@@ -165,8 +166,8 @@ void KernelState::UnregisterUserModule(UserModule* module) {
}
}
bool KernelState::IsKernelModule(const char* name) {
if (!name) {
bool KernelState::IsKernelModule(const std::string_view name) {
if (name.empty()) {
// Executing module isn't a kernel module.
return false;
}
@@ -179,7 +180,8 @@ bool KernelState::IsKernelModule(const char* name) {
return false;
}
object_ref<KernelModule> KernelState::GetKernelModule(const char* name) {
object_ref<KernelModule> KernelState::GetKernelModule(
const std::string_view name) {
assert_true(IsKernelModule(name));
for (auto kernel_module : kernel_modules_) {
@@ -191,12 +193,13 @@ object_ref<KernelModule> KernelState::GetKernelModule(const char* name) {
return nullptr;
}
object_ref<XModule> KernelState::GetModule(const char* name, bool user_only) {
if (!name) {
object_ref<XModule> KernelState::GetModule(const std::string_view name,
bool user_only) {
if (name.empty()) {
// NULL name = self.
// TODO(benvanik): lookup module from caller address.
return GetExecutableModule();
} else if (strcasecmp(name, "kernel32.dll") == 0) {
} else if (xe::utf8::equal_case(name, "kernel32.dll")) {
// Some games request this, for some reason. wtf.
return nullptr;
}
@@ -211,7 +214,7 @@ object_ref<XModule> KernelState::GetModule(const char* name, bool user_only) {
}
}
std::string path(name);
auto path(name);
// Resolve the path to an absolute path.
auto entry = file_system_->ResolvePath(name);
@@ -242,10 +245,7 @@ object_ref<XThread> KernelState::LaunchModule(object_ref<UserModule> module) {
module->entry_point(), 0, X_CREATE_SUSPENDED, true, true));
// We know this is the 'main thread'.
char thread_name[32];
std::snprintf(thread_name, xe::countof(thread_name), "Main XThread%08X",
thread->handle());
thread->set_name(thread_name);
thread->set_name(fmt::format("Main XThread{:08X}", thread->handle()));
X_STATUS result = thread->Create();
if (XFAILED(result)) {
@@ -350,14 +350,15 @@ void KernelState::LoadKernelModule(object_ref<KernelModule> kernel_module) {
kernel_modules_.push_back(std::move(kernel_module));
}
object_ref<UserModule> KernelState::LoadUserModule(const char* raw_name,
bool call_entry) {
object_ref<UserModule> KernelState::LoadUserModule(
const std::string_view raw_name, bool call_entry) {
// Some games try to load relative to launch module, others specify full path.
std::string name = xe::find_name_from_path(raw_name);
auto name = xe::utf8::find_name_from_guest_path(raw_name);
std::string path(raw_name);
if (name == raw_name) {
assert_not_null(executable_module_);
path = xe::join_paths(xe::find_base_path(executable_module_->path()), name);
path = xe::utf8::join_guest_paths(
xe::utf8::find_base_guest_path(executable_module_->path()), name);
}
object_ref<UserModule> module;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -123,18 +123,19 @@ class KernelState {
void UnregisterModule(XModule* module);
bool RegisterUserModule(object_ref<UserModule> module);
void UnregisterUserModule(UserModule* module);
bool IsKernelModule(const char* name);
object_ref<XModule> GetModule(const char* name, bool user_only = false);
bool IsKernelModule(const std::string_view name);
object_ref<XModule> GetModule(const std::string_view name,
bool user_only = false);
object_ref<XThread> LaunchModule(object_ref<UserModule> module);
object_ref<UserModule> GetExecutableModule();
void SetExecutableModule(object_ref<UserModule> module);
object_ref<UserModule> LoadUserModule(const char* name,
object_ref<UserModule> LoadUserModule(const std::string_view name,
bool call_entry = true);
void UnloadUserModule(const object_ref<UserModule>& module,
bool call_entry = true);
object_ref<KernelModule> GetKernelModule(const char* name);
object_ref<KernelModule> GetKernelModule(const std::string_view name);
template <typename T>
object_ref<KernelModule> LoadKernelModule() {
auto kernel_module = object_ref<KernelModule>(new T(emulator_, this));
@@ -142,7 +143,7 @@ class KernelState {
return kernel_module;
}
template <typename T>
object_ref<T> GetKernelModule(const char* name) {
object_ref<T> GetKernelModule(const std::string_view name) {
auto module = GetKernelModule(name);
return object_ref<T>(reinterpret_cast<T*>(module.release()));
}

View File

@@ -8,6 +8,7 @@ project("xenia-kernel")
language("C++")
links({
"aes_128",
"fmt",
"xenia-apu",
"xenia-base",
"xenia-cpu",

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -48,7 +48,7 @@ uint32_t UserModule::title_id() const {
return 0;
}
X_STATUS UserModule::LoadFromFile(std::string path) {
X_STATUS UserModule::LoadFromFile(const std::string_view path) {
X_STATUS result = X_STATUS_UNSUCCESSFUL;
// Resolve the file to open.
@@ -60,7 +60,7 @@ X_STATUS UserModule::LoadFromFile(std::string path) {
}
path_ = fs_entry->absolute_path();
name_ = NameFromPath(path_);
name_ = utf8::find_base_name_from_guest_path(path_);
// If the FS supports mapping, map the file in and load from that.
if (fs_entry->can_map()) {
@@ -258,11 +258,12 @@ uint32_t UserModule::GetProcAddressByOrdinal(uint16_t ordinal) {
return xex_module()->GetProcAddress(ordinal);
}
uint32_t UserModule::GetProcAddressByName(const char* name) {
uint32_t UserModule::GetProcAddressByName(std::string_view name) {
return xex_module()->GetProcAddress(name);
}
X_STATUS UserModule::GetSection(const char* name, uint32_t* out_section_data,
X_STATUS UserModule::GetSection(const std::string_view name,
uint32_t* out_section_data,
uint32_t* out_section_size) {
xex2_opt_resource_info* resource_header = nullptr;
if (!cpu::XexModule::GetOptHeader(xex_header(), XEX_HEADER_RESOURCE_INFO,
@@ -270,15 +271,13 @@ X_STATUS UserModule::GetSection(const char* name, uint32_t* out_section_data,
// No resources.
return X_STATUS_NOT_FOUND;
}
uint32_t count = (resource_header->size - 4) / sizeof(xex2_resource);
for (uint32_t i = 0; i < count; i++) {
auto& res = resource_header->resources[i];
if (std::strncmp(name, res.name, 8) == 0) {
if (utf8::equal_z(name, std::string_view(res.name, 8))) {
// Found!
*out_section_data = res.address;
*out_section_size = res.size;
return X_STATUS_SUCCESS;
}
}
@@ -366,7 +365,7 @@ bool UserModule::Save(ByteStream* stream) {
object_ref<UserModule> UserModule::Restore(KernelState* kernel_state,
ByteStream* stream,
std::string path) {
const std::string_view path) {
auto module = new UserModule(kernel_state);
// XModule::Save took care of this earlier...
@@ -403,23 +402,23 @@ void UserModule::Dump() {
auto header = xex_header();
// XEX header.
sb.AppendFormat("Module %s:\n", path_.c_str());
sb.AppendFormat(" Module Flags: %.8X\n", (uint32_t)header->module_flags);
sb.AppendFormat("Module {}:\n", path_);
sb.AppendFormat(" Module Flags: {:08X}\n", (uint32_t)header->module_flags);
// Security header
auto security_info = xex_module()->xex_security_info();
sb.AppendFormat("Security Header:\n");
sb.AppendFormat(" Image Flags: %.8X\n",
sb.Append("Security Header:\n");
sb.AppendFormat(" Image Flags: {:08X}\n",
(uint32_t)security_info->image_flags);
sb.AppendFormat(" Load Address: %.8X\n",
sb.AppendFormat(" Load Address: {:08X}\n",
(uint32_t)security_info->load_address);
sb.AppendFormat(" Image Size: %.8X\n",
sb.AppendFormat(" Image Size: {:08X}\n",
(uint32_t)security_info->image_size);
sb.AppendFormat(" Export Table: %.8X\n",
sb.AppendFormat(" Export Table: {:08X}\n",
(uint32_t)security_info->export_table);
// Optional headers
sb.AppendFormat("Optional Header Count: %d\n",
sb.AppendFormat("Optional Header Count: {}\n",
(uint32_t)header->header_count);
for (uint32_t i = 0; i < header->header_count; i++) {
@@ -430,7 +429,7 @@ void UserModule::Dump() {
reinterpret_cast<const uint8_t*>(header) + opt_header.offset;
switch (opt_header.key) {
case XEX_HEADER_RESOURCE_INFO: {
sb.AppendFormat(" XEX_HEADER_RESOURCE_INFO:\n");
sb.Append(" XEX_HEADER_RESOURCE_INFO:\n");
auto opt_resource_info =
reinterpret_cast<const xex2_opt_resource_info*>(opt_header_ptr);
@@ -444,36 +443,36 @@ void UserModule::Dump() {
name[8] = 0;
sb.AppendFormat(
" %-8s %.8X-%.8X, %db\n", name, (uint32_t)res.address,
" {:<8} {:08X}-{:08X}, {}b\n", name, (uint32_t)res.address,
(uint32_t)res.address + (uint32_t)res.size, (uint32_t)res.size);
}
} break;
case XEX_HEADER_FILE_FORMAT_INFO: {
sb.AppendFormat(" XEX_HEADER_FILE_FORMAT_INFO (TODO):\n");
sb.Append(" XEX_HEADER_FILE_FORMAT_INFO (TODO):\n");
} break;
case XEX_HEADER_DELTA_PATCH_DESCRIPTOR: {
sb.AppendFormat(" XEX_HEADER_DELTA_PATCH_DESCRIPTOR (TODO):\n");
sb.Append(" XEX_HEADER_DELTA_PATCH_DESCRIPTOR (TODO):\n");
} break;
case XEX_HEADER_BOUNDING_PATH: {
auto opt_bound_path =
reinterpret_cast<const xex2_opt_bound_path*>(opt_header_ptr);
sb.AppendFormat(" XEX_HEADER_BOUNDING_PATH: %s\n",
sb.AppendFormat(" XEX_HEADER_BOUNDING_PATH: {}\n",
opt_bound_path->path);
} break;
case XEX_HEADER_ORIGINAL_BASE_ADDRESS: {
sb.AppendFormat(" XEX_HEADER_ORIGINAL_BASE_ADDRESS: %.8X\n",
sb.AppendFormat(" XEX_HEADER_ORIGINAL_BASE_ADDRESS: {:08X}\n",
(uint32_t)opt_header.value);
} break;
case XEX_HEADER_ENTRY_POINT: {
sb.AppendFormat(" XEX_HEADER_ENTRY_POINT: %.8X\n",
sb.AppendFormat(" XEX_HEADER_ENTRY_POINT: {:08X}\n",
(uint32_t)opt_header.value);
} break;
case XEX_HEADER_IMAGE_BASE_ADDRESS: {
sb.AppendFormat(" XEX_HEADER_IMAGE_BASE_ADDRESS: %.8X\n",
sb.AppendFormat(" XEX_HEADER_IMAGE_BASE_ADDRESS: {:08X}\n",
(uint32_t)opt_header.value);
} break;
case XEX_HEADER_IMPORT_LIBRARIES: {
sb.AppendFormat(" XEX_HEADER_IMPORT_LIBRARIES:\n");
sb.Append(" XEX_HEADER_IMPORT_LIBRARIES:\n");
auto opt_import_libraries =
reinterpret_cast<const xex2_opt_import_libraries*>(opt_header_ptr);
@@ -509,7 +508,7 @@ void UserModule::Dump() {
}
auto name = string_table[library->name_index & 0xFF];
assert_not_null(name);
sb.AppendFormat(" %s - %d imports\n", name,
sb.AppendFormat(" {} - {} imports\n", name,
(uint16_t)library->count);
// Manually byteswap these because of the bitfields.
@@ -517,9 +516,9 @@ void UserModule::Dump() {
version.value = xe::byte_swap<uint32_t>(library->version.value);
version_min.value =
xe::byte_swap<uint32_t>(library->version_min.value);
sb.AppendFormat(" Version: %d.%d.%d.%d\n", version.major,
sb.AppendFormat(" Version: {}.{}.{}.{}\n", version.major,
version.minor, version.build, version.qfe);
sb.AppendFormat(" Min Version: %d.%d.%d.%d\n", version_min.major,
sb.AppendFormat(" Min Version: {}.{}.{}.{}\n", version_min.major,
version_min.minor, version_min.build,
version_min.qfe);
@@ -527,23 +526,23 @@ void UserModule::Dump() {
}
} break;
case XEX_HEADER_CHECKSUM_TIMESTAMP: {
sb.AppendFormat(" XEX_HEADER_CHECKSUM_TIMESTAMP (TODO):\n");
sb.Append(" XEX_HEADER_CHECKSUM_TIMESTAMP (TODO):\n");
} break;
case XEX_HEADER_ORIGINAL_PE_NAME: {
auto opt_pe_name =
reinterpret_cast<const xex2_opt_original_pe_name*>(opt_header_ptr);
sb.AppendFormat(" XEX_HEADER_ORIGINAL_PE_NAME: %s\n",
sb.AppendFormat(" XEX_HEADER_ORIGINAL_PE_NAME: {}\n",
opt_pe_name->name);
} break;
case XEX_HEADER_STATIC_LIBRARIES: {
sb.AppendFormat(" XEX_HEADER_STATIC_LIBRARIES:\n");
sb.Append(" XEX_HEADER_STATIC_LIBRARIES:\n");
auto opt_static_libraries =
reinterpret_cast<const xex2_opt_static_libraries*>(opt_header_ptr);
uint32_t count = (opt_static_libraries->size - 4) / 0x10;
for (uint32_t l = 0; l < count; l++) {
auto& library = opt_static_libraries->libraries[l];
sb.AppendFormat(" %-8s : %d.%d.%d.%d\n", library.name,
sb.AppendFormat(" {:<8} : {}.{}.{}.{}\n", library.name,
static_cast<uint16_t>(library.version_major),
static_cast<uint16_t>(library.version_minor),
static_cast<uint16_t>(library.version_build),
@@ -551,84 +550,84 @@ void UserModule::Dump() {
}
} break;
case XEX_HEADER_TLS_INFO: {
sb.AppendFormat(" XEX_HEADER_TLS_INFO:\n");
sb.Append(" XEX_HEADER_TLS_INFO:\n");
auto opt_tls_info =
reinterpret_cast<const xex2_opt_tls_info*>(opt_header_ptr);
sb.AppendFormat(" Slot Count: %d\n",
sb.AppendFormat(" Slot Count: {}\n",
static_cast<uint32_t>(opt_tls_info->slot_count));
sb.AppendFormat(" Raw Data Address: %.8X\n",
sb.AppendFormat(" Raw Data Address: {:08X}\n",
static_cast<uint32_t>(opt_tls_info->raw_data_address));
sb.AppendFormat(" Data Size: %d\n",
sb.AppendFormat(" Data Size: {}\n",
static_cast<uint32_t>(opt_tls_info->data_size));
sb.AppendFormat(" Raw Data Size: %d\n",
sb.AppendFormat(" Raw Data Size: {}\n",
static_cast<uint32_t>(opt_tls_info->raw_data_size));
} break;
case XEX_HEADER_DEFAULT_STACK_SIZE: {
sb.AppendFormat(" XEX_HEADER_DEFAULT_STACK_SIZE: %d\n",
sb.AppendFormat(" XEX_HEADER_DEFAULT_STACK_SIZE: {}\n",
static_cast<uint32_t>(opt_header.value));
} break;
case XEX_HEADER_DEFAULT_FILESYSTEM_CACHE_SIZE: {
sb.AppendFormat(" XEX_HEADER_DEFAULT_FILESYSTEM_CACHE_SIZE: %d\n",
sb.AppendFormat(" XEX_HEADER_DEFAULT_FILESYSTEM_CACHE_SIZE: {}\n",
static_cast<uint32_t>(opt_header.value));
} break;
case XEX_HEADER_DEFAULT_HEAP_SIZE: {
sb.AppendFormat(" XEX_HEADER_DEFAULT_HEAP_SIZE: %d\n",
sb.AppendFormat(" XEX_HEADER_DEFAULT_HEAP_SIZE: {}\n",
static_cast<uint32_t>(opt_header.value));
} break;
case XEX_HEADER_PAGE_HEAP_SIZE_AND_FLAGS: {
sb.AppendFormat(" XEX_HEADER_PAGE_HEAP_SIZE_AND_FLAGS (TODO):\n");
sb.Append(" XEX_HEADER_PAGE_HEAP_SIZE_AND_FLAGS (TODO):\n");
} break;
case XEX_HEADER_SYSTEM_FLAGS: {
sb.AppendFormat(" XEX_HEADER_SYSTEM_FLAGS: %.8X\n",
sb.AppendFormat(" XEX_HEADER_SYSTEM_FLAGS: {:08X}\n",
static_cast<uint32_t>(opt_header.value));
} break;
case XEX_HEADER_EXECUTION_INFO: {
sb.AppendFormat(" XEX_HEADER_EXECUTION_INFO:\n");
sb.Append(" XEX_HEADER_EXECUTION_INFO:\n");
auto opt_exec_info =
reinterpret_cast<const xex2_opt_execution_info*>(opt_header_ptr);
sb.AppendFormat(" Media ID: %.8X\n",
sb.AppendFormat(" Media ID: {:08X}\n",
static_cast<uint32_t>(opt_exec_info->media_id));
sb.AppendFormat(" Title ID: %.8X\n",
sb.AppendFormat(" Title ID: {:08X}\n",
static_cast<uint32_t>(opt_exec_info->title_id));
sb.AppendFormat(" Savegame ID: %.8X\n",
sb.AppendFormat(" Savegame ID: {:08X}\n",
static_cast<uint32_t>(opt_exec_info->title_id));
sb.AppendFormat(" Disc Number / Total: %d / %d\n",
sb.AppendFormat(" Disc Number / Total: {} / {}\n",
opt_exec_info->disc_number, opt_exec_info->disc_count);
} break;
case XEX_HEADER_TITLE_WORKSPACE_SIZE: {
sb.AppendFormat(" XEX_HEADER_TITLE_WORKSPACE_SIZE: %d\n",
sb.AppendFormat(" XEX_HEADER_TITLE_WORKSPACE_SIZE: {}\n",
uint32_t(opt_header.value));
} break;
case XEX_HEADER_GAME_RATINGS: {
sb.AppendFormat(" XEX_HEADER_GAME_RATINGS (TODO):\n");
sb.Append(" XEX_HEADER_GAME_RATINGS (TODO):\n");
} break;
case XEX_HEADER_LAN_KEY: {
sb.AppendFormat(" XEX_HEADER_LAN_KEY:");
sb.Append(" XEX_HEADER_LAN_KEY:");
auto opt_lan_key =
reinterpret_cast<const xex2_opt_lan_key*>(opt_header_ptr);
for (int l = 0; l < 16; l++) {
sb.AppendFormat(" %.2X", opt_lan_key->key[l]);
sb.AppendFormat(" {:02X}", opt_lan_key->key[l]);
}
sb.Append("\n");
} break;
case XEX_HEADER_XBOX360_LOGO: {
sb.AppendFormat(" XEX_HEADER_XBOX360_LOGO (TODO):\n");
sb.Append(" XEX_HEADER_XBOX360_LOGO (TODO):\n");
} break;
case XEX_HEADER_MULTIDISC_MEDIA_IDS: {
sb.AppendFormat(" XEX_HEADER_MULTIDISC_MEDIA_IDS (TODO):\n");
sb.Append(" XEX_HEADER_MULTIDISC_MEDIA_IDS (TODO):\n");
} break;
case XEX_HEADER_ALTERNATE_TITLE_IDS: {
sb.AppendFormat(" XEX_HEADER_ALTERNATE_TITLE_IDS (TODO):\n");
sb.Append(" XEX_HEADER_ALTERNATE_TITLE_IDS (TODO):\n");
} break;
case XEX_HEADER_ADDITIONAL_TITLE_MEMORY: {
sb.AppendFormat(" XEX_HEADER_ADDITIONAL_TITLE_MEMORY: %d\n",
sb.AppendFormat(" XEX_HEADER_ADDITIONAL_TITLE_MEMORY: {}\n",
uint32_t(opt_header.value));
} break;
case XEX_HEADER_EXPORTS_BY_NAME: {
sb.AppendFormat(" XEX_HEADER_EXPORTS_BY_NAME:\n");
sb.Append(" XEX_HEADER_EXPORTS_BY_NAME:\n");
auto dir =
reinterpret_cast<const xex2_opt_data_directory*>(opt_header_ptr);
@@ -650,16 +649,17 @@ void UserModule::Dump() {
auto name = reinterpret_cast<const char*>(e_base + name_table[n]);
uint16_t ordinal = ordinal_table[n];
uint32_t addr = exe_address + function_table[ordinal];
sb.AppendFormat(" %-28s - %.3X - %.8X\n", name, ordinal, addr);
sb.AppendFormat(" {:<28} - {:03X} - {:08X}\n", name, ordinal,
addr);
}
} break;
default: {
sb.AppendFormat(" Unknown Header %.8X\n", (uint32_t)opt_header.key);
sb.AppendFormat(" Unknown Header {:08X}\n", (uint32_t)opt_header.key);
} break;
}
}
sb.AppendFormat("Sections:\n");
sb.Append("Sections:\n");
for (uint32_t i = 0, page = 0; i < security_info->page_descriptor_count;
i++) {
// Manually byteswap the bitfield data.
@@ -686,8 +686,8 @@ void UserModule::Dump() {
uint32_t end_address =
start_address + (page_descriptor.page_count * page_size);
sb.AppendFormat(" %3u %s %3u pages %.8X - %.8X (%d bytes)\n", page,
type, page_descriptor.page_count, start_address,
sb.AppendFormat(" {:3} {} {:3} pages {:08X} - {:08X} ({} bytes)\n",
page, type, page_descriptor.page_count, start_address,
end_address, page_descriptor.page_count * page_size);
page += page_descriptor.page_count;
}
@@ -696,20 +696,20 @@ void UserModule::Dump() {
auto import_libs = xex_module()->import_libraries();
sb.AppendFormat("Imports:\n");
sb.Append("Imports:\n");
for (std::vector<cpu::XexModule::ImportLibrary>::const_iterator library =
import_libs->begin();
library != import_libs->end(); ++library) {
if (library->imports.size() > 0) {
sb.AppendFormat(" %s - %lld imports\n", library->name.c_str(),
sb.AppendFormat(" {} - {} imports\n", library->name,
library->imports.size());
sb.AppendFormat(" Version: %d.%d.%d.%d\n", library->version.major,
sb.AppendFormat(" Version: {}.{}.{}.{}\n", library->version.major,
library->version.minor, library->version.build,
library->version.qfe);
sb.AppendFormat(" Min Version: %d.%d.%d.%d\n",
sb.AppendFormat(" Min Version: {}.{}.{}.{}\n",
library->min_version.major, library->min_version.minor,
library->min_version.build, library->min_version.qfe);
sb.AppendFormat("\n");
sb.Append("\n");
// Counts.
int known_count = 0;
@@ -720,9 +720,9 @@ void UserModule::Dump() {
for (std::vector<cpu::XexModule::ImportLibraryFn>::const_iterator info =
library->imports.begin();
info != library->imports.end(); ++info) {
if (kernel_state_->IsKernelModule(library->name.c_str())) {
auto kernel_export = export_resolver->GetExportByOrdinal(
library->name.c_str(), info->ordinal);
if (kernel_state_->IsKernelModule(library->name)) {
auto kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
if (kernel_export) {
known_count++;
if (kernel_export->is_implemented()) {
@@ -735,7 +735,7 @@ void UserModule::Dump() {
unimpl_count++;
}
} else {
auto module = kernel_state_->GetModule(library->name.c_str());
auto module = kernel_state_->GetModule(library->name);
if (module) {
uint32_t export_addr =
module->GetProcAddressByOrdinal(info->ordinal);
@@ -753,12 +753,12 @@ void UserModule::Dump() {
}
}
float total_count = static_cast<float>(library->imports.size()) / 100.0f;
sb.AppendFormat(" Total: %4llu\n", library->imports.size());
sb.AppendFormat(" Known: %3d%% (%d known, %d unknown)\n",
sb.AppendFormat(" Total: {:4}\n", library->imports.size());
sb.AppendFormat(" Known: {:3}% ({} known, {} unknown)\n",
static_cast<int>(known_count / total_count), known_count,
unknown_count);
sb.AppendFormat(
" Implemented: %3d%% (%d implemented, %d unimplemented)\n",
" Implemented: {:3}% ({} implemented, {} unimplemented)\n",
static_cast<int>(impl_count / total_count), impl_count, unimpl_count);
sb.AppendFormat("\n");
@@ -770,15 +770,15 @@ void UserModule::Dump() {
bool implemented = false;
cpu::Export* kernel_export = nullptr;
if (kernel_state_->IsKernelModule(library->name.c_str())) {
kernel_export = export_resolver->GetExportByOrdinal(
library->name.c_str(), info->ordinal);
if (kernel_state_->IsKernelModule(library->name)) {
kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
if (kernel_export) {
name = kernel_export->name;
implemented = kernel_export->is_implemented();
}
} else {
auto module = kernel_state_->GetModule(library->name.c_str());
auto module = kernel_state_->GetModule(library->name);
if (module && module->GetProcAddressByOrdinal(info->ordinal)) {
// TODO(benvanik): name lookup.
implemented = true;
@@ -786,11 +786,11 @@ void UserModule::Dump() {
}
if (kernel_export &&
kernel_export->type == cpu::Export::Type::kVariable) {
sb.AppendFormat(" V %.8X %.3X (%4d) %s %s\n",
sb.AppendFormat(" V {:08X} {:03X} ({:4}) {} {}\n",
info->value_address, info->ordinal, info->ordinal,
implemented ? " " : "!!", name);
} else if (info->thunk_address) {
sb.AppendFormat(" F %.8X %.8X %.3X (%4d) %s %s\n",
sb.AppendFormat(" F {:08X} {:08X} {:03X} ({:4}) {} {}\n",
info->value_address, info->thunk_address,
info->ordinal, info->ordinal,
implemented ? " " : "!!", name);
@@ -798,10 +798,10 @@ void UserModule::Dump() {
}
}
sb.AppendFormat("\n");
sb.Append("\n");
}
xe::LogLine(xe::LogLevel::Info, 'i', sb.GetString());
xe::LogLine(xe::LogLevel::Info, 'i', sb.to_string_view());
}
} // namespace kernel

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -36,6 +36,9 @@ class UserModule : public XModule {
UserModule(KernelState* kernel_state);
~UserModule() override;
const std::string& path() const override { return path_; }
const std::string& name() const override { return name_; }
enum ModuleFormat {
kModuleFormatUndefined = 0,
kModuleFormatXex,
@@ -61,13 +64,13 @@ class UserModule : public XModule {
uint32_t entry_point() const { return entry_point_; }
uint32_t stack_size() const { return stack_size_; }
X_STATUS LoadFromFile(std::string path);
X_STATUS LoadFromFile(const std::string_view path);
X_STATUS LoadFromMemory(const void* addr, const size_t length);
X_STATUS Unload();
uint32_t GetProcAddressByOrdinal(uint16_t ordinal) override;
uint32_t GetProcAddressByName(const char* name) override;
X_STATUS GetSection(const char* name, uint32_t* out_section_data,
uint32_t GetProcAddressByName(const std::string_view name) override;
X_STATUS GetSection(const std::string_view name, uint32_t* out_section_data,
uint32_t* out_section_size) override;
// Get optional header - FOR HOST USE ONLY!
@@ -89,11 +92,15 @@ class UserModule : public XModule {
bool Save(ByteStream* stream) override;
static object_ref<UserModule> Restore(KernelState* kernel_state,
ByteStream* stream, std::string path);
ByteStream* stream,
const std::string_view path);
private:
X_STATUS LoadXexContinue();
std::string name_;
std::string path_;
uint32_t guest_xex_header_ = 0;
ModuleFormat module_format_ = kModuleFormatUndefined;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2016 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -48,9 +48,9 @@ class GameInfoWrapper {
static_assert_size(GameInfoBlockComm, 4);
struct GameInfoBlockTitl {
xe::be<wchar_t> title[128];
xe::be<wchar_t> description[256];
xe::be<wchar_t> publisher[256]; // assumed field name from wxPirs
xe::be<char16_t> title[128];
xe::be<char16_t> description[256];
xe::be<char16_t> publisher[256]; // assumed field name from wxPirs
};
private:

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -328,42 +328,30 @@ X_HANDLE ObjectTable::TranslateHandle(X_HANDLE handle) {
}
}
X_STATUS ObjectTable::AddNameMapping(const std::string& name, X_HANDLE handle) {
// Names are case-insensitive.
std::string lower_name = name;
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(),
tolower);
X_STATUS ObjectTable::AddNameMapping(const std::string_view name,
X_HANDLE handle) {
auto global_lock = global_critical_region_.Acquire();
if (name_table_.count(lower_name)) {
if (name_table_.count(string_key_case(name))) {
return X_STATUS_OBJECT_NAME_COLLISION;
}
name_table_.insert({lower_name, handle});
name_table_.insert({string_key_case::create(name), handle});
return X_STATUS_SUCCESS;
}
void ObjectTable::RemoveNameMapping(const std::string& name) {
void ObjectTable::RemoveNameMapping(const std::string_view name) {
// Names are case-insensitive.
std::string lower_name = name;
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(),
tolower);
auto global_lock = global_critical_region_.Acquire();
auto it = name_table_.find(lower_name);
auto it = name_table_.find(string_key_case(name));
if (it != name_table_.end()) {
name_table_.erase(it);
}
}
X_STATUS ObjectTable::GetObjectByName(const std::string& name,
X_STATUS ObjectTable::GetObjectByName(const std::string_view name,
X_HANDLE* out_handle) {
// Names are case-insensitive.
std::string lower_name = name;
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(),
tolower);
auto global_lock = global_critical_region_.Acquire();
auto it = name_table_.find(lower_name);
auto it = name_table_.find(string_key_case(name));
if (it == name_table_.end()) {
*out_handle = X_INVALID_HANDLE_VALUE;
return X_STATUS_OBJECT_NAME_NOT_FOUND;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -15,6 +15,7 @@
#include <vector>
#include "xenia/base/mutex.h"
#include "xenia/base/string_key.h"
#include "xenia/kernel/xobject.h"
#include "xenia/xbox.h"
@@ -57,9 +58,9 @@ class ObjectTable {
return result;
}
X_STATUS AddNameMapping(const std::string& name, X_HANDLE handle);
void RemoveNameMapping(const std::string& name);
X_STATUS GetObjectByName(const std::string& name, X_HANDLE* out_handle);
X_STATUS AddNameMapping(const std::string_view name, X_HANDLE handle);
void RemoveNameMapping(const std::string_view name);
X_STATUS GetObjectByName(const std::string_view name, X_HANDLE* out_handle);
template <typename T>
std::vector<object_ref<T>> GetObjectsByType(XObject::Type type) {
std::vector<object_ref<T>> results;
@@ -99,7 +100,7 @@ class ObjectTable {
uint32_t table_capacity_ = 0;
ObjectTableEntry* table_ = nullptr;
uint32_t last_free_entry_ = 0;
std::unordered_map<std::string, X_HANDLE> name_table_;
std::unordered_map<string_key_case, X_HANDLE> name_table_;
};
// Generic lookup

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -13,6 +13,7 @@
#include <cstring>
#include <string>
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/base/byte_order.h"
#include "xenia/base/logging.h"
#include "xenia/base/memory.h"
@@ -101,22 +102,22 @@ inline std::string TranslateAnsiStringAddress(const Memory* memory,
memory, memory->TranslateVirtual<const X_ANSI_STRING*>(guest_address));
}
inline std::wstring TranslateUnicodeString(
inline std::u16string TranslateUnicodeString(
const Memory* memory, const X_UNICODE_STRING* unicode_string) {
if (!unicode_string) {
return L"";
return u"";
}
uint16_t length = unicode_string->length;
if (!length) {
return L"";
return u"";
}
const xe::be<uint16_t>* guest_string =
memory->TranslateVirtual<const xe::be<uint16_t>*>(
unicode_string->pointer);
std::wstring translated_string;
std::u16string translated_string;
translated_string.reserve(length);
for (uint16_t i = 0; i < length; ++i) {
translated_string += wchar_t(uint16_t(guest_string[i]));
translated_string += char16_t(uint16_t(guest_string[i]));
}
return translated_string;
}
@@ -352,7 +353,7 @@ using lpqword_t = const shim::PrimitivePointerParam<uint64_t>&;
using lpfloat_t = const shim::PrimitivePointerParam<float>&;
using lpdouble_t = const shim::PrimitivePointerParam<double>&;
using lpstring_t = const shim::StringPointerParam<char, std::string>&;
using lpwstring_t = const shim::StringPointerParam<wchar_t, std::wstring>&;
using lpu16string_t = const shim::StringPointerParam<char16_t, std::u16string>&;
using function_t = const shim::ParamBase<uint32_t>&;
using unknown_t = const shim::ParamBase<uint32_t>&;
using lpunknown_t = const shim::PointerParam&;
@@ -371,65 +372,65 @@ inline Memory* kernel_memory() { return kernel_state()->memory(); }
namespace shim {
inline void AppendParam(StringBuffer* string_buffer, int_t param) {
string_buffer->AppendFormat("%d", int32_t(param));
string_buffer->AppendFormat("{}", int32_t(param));
}
inline void AppendParam(StringBuffer* string_buffer, word_t param) {
string_buffer->AppendFormat("%.4X", uint16_t(param));
string_buffer->AppendFormat("{:04X}", uint16_t(param));
}
inline void AppendParam(StringBuffer* string_buffer, dword_t param) {
string_buffer->AppendFormat("%.8X", uint32_t(param));
string_buffer->AppendFormat("{:08X}", uint32_t(param));
}
inline void AppendParam(StringBuffer* string_buffer, qword_t param) {
string_buffer->AppendFormat("%.16llX", uint64_t(param));
string_buffer->AppendFormat("{:016X}", uint64_t(param));
}
inline void AppendParam(StringBuffer* string_buffer, float_t param) {
string_buffer->AppendFormat("%G", static_cast<float>(param));
string_buffer->AppendFormat("{:G}", static_cast<float>(param));
}
inline void AppendParam(StringBuffer* string_buffer, double_t param) {
string_buffer->AppendFormat("%G", static_cast<double>(param));
string_buffer->AppendFormat("{:G}", static_cast<double>(param));
}
inline void AppendParam(StringBuffer* string_buffer, lpvoid_t param) {
string_buffer->AppendFormat("%.8X", uint32_t(param));
string_buffer->AppendFormat("{:08X}", uint32_t(param));
}
inline void AppendParam(StringBuffer* string_buffer, lpdword_t param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
string_buffer->AppendFormat("{:08X}", param.guest_address());
if (param) {
string_buffer->AppendFormat("(%.8X)", param.value());
string_buffer->AppendFormat("({:08X})", param.value());
}
}
inline void AppendParam(StringBuffer* string_buffer, lpqword_t param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
string_buffer->AppendFormat("{:08X}", param.guest_address());
if (param) {
string_buffer->AppendFormat("(%.16llX)", param.value());
string_buffer->AppendFormat("({:016X})", param.value());
}
}
inline void AppendParam(StringBuffer* string_buffer, lpfloat_t param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
string_buffer->AppendFormat("{:08X}", param.guest_address());
if (param) {
string_buffer->AppendFormat("(%G)", param.value());
string_buffer->AppendFormat("({:G})", param.value());
}
}
inline void AppendParam(StringBuffer* string_buffer, lpdouble_t param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
string_buffer->AppendFormat("{:08X}", param.guest_address());
if (param) {
string_buffer->AppendFormat("(%G)", param.value());
string_buffer->AppendFormat("({:G})", param.value());
}
}
inline void AppendParam(StringBuffer* string_buffer, lpstring_t param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
string_buffer->AppendFormat("{:08X}", param.guest_address());
if (param) {
string_buffer->AppendFormat("(%s)", param.value().c_str());
string_buffer->AppendFormat("({})", param.value());
}
}
inline void AppendParam(StringBuffer* string_buffer, lpwstring_t param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
inline void AppendParam(StringBuffer* string_buffer, lpu16string_t param) {
string_buffer->AppendFormat("{:08X}", param.guest_address());
if (param) {
string_buffer->AppendFormat("(%S)", param.value().c_str());
string_buffer->AppendFormat("({})", xe::to_utf8(param.value()));
}
}
inline void AppendParam(StringBuffer* string_buffer,
pointer_t<X_OBJECT_ATTRIBUTES> record) {
string_buffer->AppendFormat("%.8X", record.guest_address());
string_buffer->AppendFormat("{:08X}", record.guest_address());
if (record) {
auto name_string =
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(record->name_ptr);
@@ -437,25 +438,25 @@ inline void AppendParam(StringBuffer* string_buffer,
name_string == nullptr
? "(null)"
: util::TranslateAnsiString(kernel_memory(), name_string);
string_buffer->AppendFormat("(%.8X,%s,%.8X)",
uint32_t(record->root_directory), name.c_str(),
string_buffer->AppendFormat("({:08X},{},{:08X})",
uint32_t(record->root_directory), name,
uint32_t(record->attributes));
}
}
inline void AppendParam(StringBuffer* string_buffer,
pointer_t<X_EX_TITLE_TERMINATE_REGISTRATION> reg) {
string_buffer->AppendFormat("%.8X(%.8X, %.8X)", reg.guest_address(),
string_buffer->AppendFormat("{:08X}({:08X}, {:08X})", reg.guest_address(),
static_cast<uint32_t>(reg->notification_routine),
static_cast<uint32_t>(reg->priority));
}
inline void AppendParam(StringBuffer* string_buffer,
pointer_t<X_EXCEPTION_RECORD> record) {
string_buffer->AppendFormat("%.8X(%.8X)", record.guest_address(),
string_buffer->AppendFormat("{:08X}({:08X})", record.guest_address(),
uint32_t(record->exception_code));
}
template <typename T>
void AppendParam(StringBuffer* string_buffer, pointer_t<T> param) {
string_buffer->AppendFormat("%.8X", param.guest_address());
string_buffer->AppendFormat("{:08X}", param.guest_address());
}
enum class KernelModuleId {
@@ -493,11 +494,9 @@ void PrintKernelCall(cpu::Export* export_entry, const Tuple& params) {
AppendKernelCallParams(string_buffer, export_entry, params);
string_buffer.Append(')');
if (export_entry->tags & xe::cpu::ExportTag::kImportant) {
xe::LogLine(xe::LogLevel::Info, 'i', string_buffer.GetString(),
string_buffer.length());
xe::LogLine(xe::LogLevel::Info, 'i', string_buffer.to_string_view());
} else {
xe::LogLine(xe::LogLevel::Debug, 'd', string_buffer.GetString(),
string_buffer.length());
xe::LogLine(xe::LogLevel::Debug, 'd', string_buffer.to_string_view());
}
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -43,17 +43,17 @@ X_RESULT XmpApp::XMPGetStatus(uint32_t state_ptr) {
X_RESULT XmpApp::XMPCreateTitlePlaylist(uint32_t songs_ptr, uint32_t song_count,
uint32_t playlist_name_ptr,
std::wstring playlist_name,
const std::u16string& playlist_name,
uint32_t flags,
uint32_t out_song_handles,
uint32_t out_playlist_handle) {
XELOGD("XMPCreateTitlePlaylist(%.8X, %.8X, %.8X(%s), %.8X, %.8X, %.8X)",
songs_ptr, song_count, playlist_name_ptr,
xe::to_string(playlist_name).c_str(), flags, out_song_handles,
xe::to_utf8(playlist_name).c_str(), flags, out_song_handles,
out_playlist_handle);
auto playlist = std::make_unique<Playlist>();
playlist->handle = ++next_playlist_handle_;
playlist->name = std::move(playlist_name);
playlist->name = playlist_name;
playlist->flags = flags;
if (songs_ptr) {
for (uint32_t i = 0; i < song_count; ++i) {
@@ -61,18 +61,19 @@ X_RESULT XmpApp::XMPCreateTitlePlaylist(uint32_t songs_ptr, uint32_t song_count,
song->handle = ++next_song_handle_;
uint8_t* song_base = memory_->TranslateVirtual(songs_ptr + (i * 36));
song->file_path =
xe::load_and_swap<std::wstring>(memory_->TranslateVirtual(
xe::load_and_swap<std::u16string>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 0)));
song->name = xe::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->name = xe::load_and_swap<std::u16string>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 4)));
song->artist = xe::load_and_swap<std::wstring>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 8)));
song->album = xe::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->artist =
xe::load_and_swap<std::u16string>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 8)));
song->album = xe::load_and_swap<std::u16string>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 12)));
song->album_artist =
xe::load_and_swap<std::wstring>(memory_->TranslateVirtual(
xe::load_and_swap<std::u16string>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 16)));
song->genre = xe::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->genre = xe::load_and_swap<std::u16string>(memory_->TranslateVirtual(
xe::load_and_swap<uint32_t>(song_base + 20)));
song->track_number = xe::load_and_swap<uint32_t>(song_base + 24);
song->duration_ms = xe::load_and_swap<uint32_t>(song_base + 28);
@@ -310,11 +311,11 @@ X_RESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
xe::store_and_swap<uint32_t>(
memory_->TranslateVirtual(playlist_handle_ptr), storage_ptr);
assert_true(xmp_client == 0x00000002);
std::wstring playlist_name;
std::u16string playlist_name;
if (!playlist_name_ptr) {
playlist_name = L"";
playlist_name = u"";
} else {
playlist_name = xe::load_and_swap<std::wstring>(
playlist_name = xe::load_and_swap<std::u16string>(
memory_->TranslateVirtual(playlist_name_ptr));
}
// dummy_alloc_ptr is the result of a XamAlloc of storage_size.
@@ -337,12 +338,12 @@ X_RESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
}
auto& song = active_playlist_->songs[active_song_index_];
xe::store_and_swap<uint32_t>(info + 0, song->handle);
xe::store_and_swap<std::wstring>(info + 4 + 572 + 0, song->name);
xe::store_and_swap<std::wstring>(info + 4 + 572 + 40, song->artist);
xe::store_and_swap<std::wstring>(info + 4 + 572 + 80, song->album);
xe::store_and_swap<std::wstring>(info + 4 + 572 + 120,
song->album_artist);
xe::store_and_swap<std::wstring>(info + 4 + 572 + 160, song->genre);
xe::store_and_swap<std::u16string>(info + 4 + 572 + 0, song->name);
xe::store_and_swap<std::u16string>(info + 4 + 572 + 40, song->artist);
xe::store_and_swap<std::u16string>(info + 4 + 572 + 80, song->album);
xe::store_and_swap<std::u16string>(info + 4 + 572 + 120,
song->album_artist);
xe::store_and_swap<std::u16string>(info + 4 + 572 + 160, song->genre);
xe::store_and_swap<uint32_t>(info + 4 + 572 + 200, song->track_number);
xe::store_and_swap<uint32_t>(info + 4 + 572 + 204, song->duration_ms);
xe::store_and_swap<uint32_t>(info + 4 + 572 + 208,

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -49,19 +49,19 @@ class XmpApp : public App {
};
uint32_t handle;
std::wstring file_path;
std::wstring name;
std::wstring artist;
std::wstring album;
std::wstring album_artist;
std::wstring genre;
std::u16string file_path;
std::u16string name;
std::u16string artist;
std::u16string album;
std::u16string album_artist;
std::u16string genre;
uint32_t track_number;
uint32_t duration_ms;
Format format;
};
struct Playlist {
uint32_t handle;
std::wstring name;
std::u16string name;
uint32_t flags;
std::vector<std::unique_ptr<Song>> songs;
};
@@ -72,8 +72,8 @@ class XmpApp : public App {
X_RESULT XMPCreateTitlePlaylist(uint32_t songs_ptr, uint32_t song_count,
uint32_t playlist_name_ptr,
std::wstring playlist_name, uint32_t flags,
uint32_t out_song_handles,
const std::u16string& playlist_name,
uint32_t flags, uint32_t out_song_handles,
uint32_t out_playlist_handle);
X_RESULT XMPDeleteTitlePlaylist(uint32_t playlist_handle);
X_RESULT XMPPlayTitlePlaylist(uint32_t playlist_handle, uint32_t song_handle);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -11,6 +11,7 @@
#include <string>
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/base/filesystem.h"
#include "xenia/base/string.h"
#include "xenia/kernel/kernel_state.h"
@@ -21,18 +22,18 @@ namespace xe {
namespace kernel {
namespace xam {
static const wchar_t* kThumbnailFileName = L"__thumbnail.png";
static const char* kThumbnailFileName = "__thumbnail.png";
static const wchar_t* kGameUserContentDirName = L"profile";
static const char* kGameUserContentDirName = "profile";
static int content_device_id_ = 0;
ContentPackage::ContentPackage(KernelState* kernel_state, std::string root_name,
ContentPackage::ContentPackage(KernelState* kernel_state,
const std::string_view root_name,
const XCONTENT_DATA& data,
std::wstring package_path)
: kernel_state_(kernel_state), root_name_(std::move(root_name)) {
device_path_ = std::string("\\Device\\Content\\") +
std::to_string(++content_device_id_) + "\\";
const std::filesystem::path& package_path)
: kernel_state_(kernel_state), root_name_(root_name) {
device_path_ = fmt::format("\\Device\\Content\\{0}\\", ++content_device_id_);
auto fs = kernel_state_->file_system();
auto device =
@@ -49,53 +50,49 @@ ContentPackage::~ContentPackage() {
}
ContentManager::ContentManager(KernelState* kernel_state,
std::wstring root_path)
: kernel_state_(kernel_state), root_path_(std::move(root_path)) {}
const std::filesystem::path& root_path)
: kernel_state_(kernel_state), root_path_(root_path) {}
ContentManager::~ContentManager() = default;
std::wstring ContentManager::ResolvePackageRoot(uint32_t content_type) {
wchar_t title_id[9] = L"00000000";
std::swprintf(title_id, 9, L"%.8X", kernel_state_->title_id());
std::filesystem::path ContentManager::ResolvePackageRoot(
uint32_t content_type) {
auto title_id = fmt::format("{:8X}", kernel_state_->title_id());
std::wstring type_name;
std::string type_name;
switch (content_type) {
case 1:
// Save games.
type_name = L"00000001";
type_name = "00000001";
break;
case 2:
// DLC from the marketplace.
type_name = L"00000002";
type_name = "00000002";
break;
case 3:
// Publisher content?
type_name = L"00000003";
type_name = "00000003";
break;
case 0x000D0000:
// ???
type_name = L"000D0000";
type_name = "000D0000";
break;
default:
assert_unhandled_case(data.content_type);
return nullptr;
return std::filesystem::path();
}
// Package root path:
// content_root/title_id/type_name/
auto package_root =
xe::join_paths(root_path_, xe::join_paths(title_id, type_name));
return package_root + xe::kWPathSeparator;
return root_path_ / title_id / type_name;
}
std::wstring ContentManager::ResolvePackagePath(const XCONTENT_DATA& data) {
std::filesystem::path ContentManager::ResolvePackagePath(
const XCONTENT_DATA& data) {
// Content path:
// content_root/title_id/type_name/data_file_name/
auto package_root = ResolvePackageRoot(data.content_type);
auto package_path =
xe::join_paths(package_root, xe::to_wstring(data.file_name));
package_path += xe::kPathSeparator;
return package_path;
return package_root / xe::to_path(data.file_name);
}
std::vector<XCONTENT_DATA> ContentManager::ListContent(uint32_t device_id,
@@ -114,8 +111,8 @@ std::vector<XCONTENT_DATA> ContentManager::ListContent(uint32_t device_id,
XCONTENT_DATA content_data;
content_data.device_id = device_id;
content_data.content_type = content_type;
content_data.display_name = file_info.name;
content_data.file_name = xe::to_string(file_info.name);
content_data.display_name = xe::path_to_utf16(file_info.name);
content_data.file_name = xe::path_to_utf8(file_info.name);
result.emplace_back(std::move(content_data));
}
@@ -123,7 +120,7 @@ std::vector<XCONTENT_DATA> ContentManager::ListContent(uint32_t device_id,
}
std::unique_ptr<ContentPackage> ContentManager::ResolvePackage(
std::string root_name, const XCONTENT_DATA& data) {
const std::string_view root_name, const XCONTENT_DATA& data) {
auto package_path = ResolvePackagePath(data);
if (!xe::filesystem::PathExists(package_path)) {
return nullptr;
@@ -141,11 +138,11 @@ bool ContentManager::ContentExists(const XCONTENT_DATA& data) {
return xe::filesystem::PathExists(path);
}
X_RESULT ContentManager::CreateContent(std::string root_name,
X_RESULT ContentManager::CreateContent(const std::string_view root_name,
const XCONTENT_DATA& data) {
auto global_lock = global_critical_region_.Acquire();
if (open_packages_.count(root_name)) {
if (open_packages_.count(string_key(root_name))) {
// Already content open with this root name.
return X_ERROR_ALREADY_EXISTS;
}
@@ -163,16 +160,16 @@ X_RESULT ContentManager::CreateContent(std::string root_name,
auto package = ResolvePackage(root_name, data);
assert_not_null(package);
open_packages_.insert({root_name, package.release()});
open_packages_.insert({string_key::create(root_name), package.release()});
return X_ERROR_SUCCESS;
}
X_RESULT ContentManager::OpenContent(std::string root_name,
X_RESULT ContentManager::OpenContent(const std::string_view root_name,
const XCONTENT_DATA& data) {
auto global_lock = global_critical_region_.Acquire();
if (open_packages_.count(root_name)) {
if (open_packages_.count(string_key(root_name))) {
// Already content open with this root name.
return X_ERROR_ALREADY_EXISTS;
}
@@ -187,15 +184,15 @@ X_RESULT ContentManager::OpenContent(std::string root_name,
auto package = ResolvePackage(root_name, data);
assert_not_null(package);
open_packages_.insert({root_name, package.release()});
open_packages_.insert({string_key::create(root_name), package.release()});
return X_ERROR_SUCCESS;
}
X_RESULT ContentManager::CloseContent(std::string root_name) {
X_RESULT ContentManager::CloseContent(const std::string_view root_name) {
auto global_lock = global_critical_region_.Acquire();
auto it = open_packages_.find(root_name);
auto it = open_packages_.find(string_key(root_name));
if (it == open_packages_.end()) {
return X_ERROR_FILE_NOT_FOUND;
}
@@ -211,7 +208,7 @@ X_RESULT ContentManager::GetContentThumbnail(const XCONTENT_DATA& data,
std::vector<uint8_t>* buffer) {
auto global_lock = global_critical_region_.Acquire();
auto package_path = ResolvePackagePath(data);
auto thumb_path = xe::join_paths(package_path, kThumbnailFileName);
auto thumb_path = package_path / kThumbnailFileName;
if (xe::filesystem::PathExists(thumb_path)) {
auto file = xe::filesystem::OpenFile(thumb_path, "rb");
fseek(file, 0, SEEK_END);
@@ -232,7 +229,7 @@ X_RESULT ContentManager::SetContentThumbnail(const XCONTENT_DATA& data,
auto package_path = ResolvePackagePath(data);
xe::filesystem::CreateFolder(package_path);
if (xe::filesystem::PathExists(package_path)) {
auto thumb_path = xe::join_paths(package_path, kThumbnailFileName);
auto thumb_path = package_path / kThumbnailFileName;
auto file = xe::filesystem::OpenFile(thumb_path, "wb");
fwrite(buffer.data(), 1, buffer.size(), file);
fclose(file);
@@ -254,18 +251,13 @@ X_RESULT ContentManager::DeleteContent(const XCONTENT_DATA& data) {
}
}
std::wstring ContentManager::ResolveGameUserContentPath() {
wchar_t title_id[9] = L"00000000";
std::swprintf(title_id, 9, L"%.8X", kernel_state_->title_id());
auto user_name = xe::to_wstring(kernel_state_->user_profile()->name());
std::filesystem::path ContentManager::ResolveGameUserContentPath() {
auto title_id = fmt::format("{:8X}", kernel_state_->title_id());
auto user_name = xe::to_path(kernel_state_->user_profile()->name());
// Per-game per-profile data location:
// content_root/title_id/profile/user_name
auto package_root = xe::join_paths(
root_path_,
xe::join_paths(title_id,
xe::join_paths(kGameUserContentDirName, user_name)));
return package_root + xe::kWPathSeparator;
return root_path_ / title_id / kGameUserContentDirName / user_name;
}
} // namespace xam

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -17,6 +17,7 @@
#include "xenia/base/memory.h"
#include "xenia/base/mutex.h"
#include "xenia/base/string_key.h"
#include "xenia/xbox.h"
namespace xe {
@@ -33,29 +34,30 @@ struct XCONTENT_DATA {
static const size_t kSize = 4 + 4 + 128 * 2 + 42 + 2; // = 306 + 2b padding
uint32_t device_id;
uint32_t content_type;
std::wstring display_name; // 128 chars
std::u16string display_name; // 128 chars
std::string file_name;
XCONTENT_DATA() = default;
explicit XCONTENT_DATA(const uint8_t* ptr) {
device_id = xe::load_and_swap<uint32_t>(ptr + 0);
content_type = xe::load_and_swap<uint32_t>(ptr + 4);
display_name = xe::load_and_swap<std::wstring>(ptr + 8);
display_name = xe::load_and_swap<std::u16string>(ptr + 8);
file_name = xe::load_and_swap<std::string>(ptr + 8 + 128 * 2);
}
void Write(uint8_t* ptr) {
xe::store_and_swap<uint32_t>(ptr + 0, device_id);
xe::store_and_swap<uint32_t>(ptr + 4, content_type);
xe::store_and_swap<std::wstring>(ptr + 8, display_name);
xe::store_and_swap<std::u16string>(ptr + 8, display_name);
xe::store_and_swap<std::string>(ptr + 8 + 128 * 2, file_name);
}
};
class ContentPackage {
public:
ContentPackage(KernelState* kernel_state, std::string root_name,
const XCONTENT_DATA& data, std::wstring package_path);
ContentPackage(KernelState* kernel_state, const std::string_view root_name,
const XCONTENT_DATA& data,
const std::filesystem::path& package_path);
~ContentPackage();
private:
@@ -66,36 +68,39 @@ class ContentPackage {
class ContentManager {
public:
ContentManager(KernelState* kernel_state, std::wstring root_path);
ContentManager(KernelState* kernel_state,
const std::filesystem::path& root_path);
~ContentManager();
std::vector<XCONTENT_DATA> ListContent(uint32_t device_id,
uint32_t content_type);
std::unique_ptr<ContentPackage> ResolvePackage(std::string root_name,
const XCONTENT_DATA& data);
std::unique_ptr<ContentPackage> ResolvePackage(
const std::string_view root_name, const XCONTENT_DATA& data);
bool ContentExists(const XCONTENT_DATA& data);
X_RESULT CreateContent(std::string root_name, const XCONTENT_DATA& data);
X_RESULT OpenContent(std::string root_name, const XCONTENT_DATA& data);
X_RESULT CloseContent(std::string root_name);
X_RESULT CreateContent(const std::string_view root_name,
const XCONTENT_DATA& data);
X_RESULT OpenContent(const std::string_view root_name,
const XCONTENT_DATA& data);
X_RESULT CloseContent(const std::string_view root_name);
X_RESULT GetContentThumbnail(const XCONTENT_DATA& data,
std::vector<uint8_t>* buffer);
X_RESULT SetContentThumbnail(const XCONTENT_DATA& data,
std::vector<uint8_t> buffer);
X_RESULT DeleteContent(const XCONTENT_DATA& data);
std::wstring ResolveGameUserContentPath();
std::filesystem::path ResolveGameUserContentPath();
private:
std::wstring ResolvePackageRoot(uint32_t content_type);
std::wstring ResolvePackagePath(const XCONTENT_DATA& data);
std::filesystem::path ResolvePackageRoot(uint32_t content_type);
std::filesystem::path ResolvePackagePath(const XCONTENT_DATA& data);
KernelState* kernel_state_;
std::wstring root_path_;
std::filesystem::path root_path_;
// TODO(benvanik): remove use of global lock, it's bad here!
xe::global_critical_region global_critical_region_;
std::unordered_map<std::string, ContentPackage*> open_packages_;
std::unordered_map<string_key, ContentPackage*> open_packages_;
};
} // namespace xam

View File

@@ -2,16 +2,18 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/kernel/xam/user_profile.h"
#include <sstream>
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/user_profile.h"
namespace xe {
namespace kernel {
@@ -42,7 +44,7 @@ UserProfile::UserProfile() {
// XPROFILE_OPTION_VOICE_VOLUME
AddSetting(std::make_unique<Int32Setting>(0x1004000E, 0x64));
// XPROFILE_GAMERCARD_MOTTO
AddSetting(std::make_unique<UnicodeSetting>(0x402C0011, L""));
AddSetting(std::make_unique<UnicodeSetting>(0x402C0011, u""));
// XPROFILE_GAMERCARD_TITLES_PLAYED
AddSetting(std::make_unique<Int32Setting>(0x10040012, 1));
// XPROFILE_GAMERCARD_ACHIEVEMENTS_EARNED
@@ -77,7 +79,7 @@ UserProfile::UserProfile() {
// If we set this, games will try to get it.
// XPROFILE_GAMERCARD_PICTURE_KEY
AddSetting(
std::make_unique<UnicodeSetting>(0x4064000F, L"gamercard_picture_key"));
std::make_unique<UnicodeSetting>(0x4064000F, u"gamercard_picture_key"));
// XPROFILE_TITLE_SPECIFIC1
AddSetting(std::make_unique<BinarySetting>(0x63E83FFF));
@@ -130,8 +132,8 @@ void UserProfile::LoadSetting(UserProfile::Setting* setting) {
if (setting->is_title_specific()) {
auto content_dir =
kernel_state()->content_manager()->ResolveGameUserContentPath();
auto setting_id = xe::format_string(L"%.8X", setting->setting_id);
auto file_path = xe::join_paths(content_dir, setting_id);
auto setting_id = fmt::format("{:08X}", setting->setting_id);
auto file_path = content_dir / setting_id;
auto file = xe::filesystem::OpenFile(file_path, "rb");
if (file) {
fseek(file, 0, SEEK_END);
@@ -157,8 +159,8 @@ void UserProfile::SaveSetting(UserProfile::Setting* setting) {
auto content_dir =
kernel_state()->content_manager()->ResolveGameUserContentPath();
xe::filesystem::CreateFolder(content_dir);
auto setting_id = xe::format_string(L"%.8X", setting->setting_id);
auto file_path = xe::join_paths(content_dir, setting_id);
auto setting_id = fmt::format("{:08X}", setting->setting_id);
auto file_path = content_dir / setting_id;
auto file = xe::filesystem::OpenFile(file_path, "wb");
fwrite(serialized_setting.data(), 1, serialized_setting.size(), file);
fclose(file);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -110,9 +110,9 @@ class UserProfile {
}
};
struct UnicodeSetting : public Setting {
UnicodeSetting(uint32_t setting_id, const std::wstring& value)
UnicodeSetting(uint32_t setting_id, const std::u16string& value)
: Setting(setting_id, Type::WSTRING, 8, true), value(value) {}
std::wstring value;
std::u16string value;
size_t extra_size() const override {
return value.empty() ? 0 : 2 * (static_cast<int32_t>(value.size()) + 1);
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -31,7 +31,7 @@ struct DeviceInfo {
uint32_t device_type;
uint64_t total_bytes;
uint64_t free_bytes;
wchar_t name[28];
char16_t name[28];
};
// TODO(gibbed): real information.
@@ -48,7 +48,7 @@ static const DeviceInfo dummy_device_info_ = {
0xF00D0000, 1,
4ull * ONE_GB, // 4GB
3ull * ONE_GB, // 3GB, so it looks a little used.
L"Dummy HDD",
u"Dummy HDD",
};
#undef ONE_GB
@@ -70,19 +70,19 @@ dword_result_t XamContentGetLicenseMask(lpdword_t mask_ptr,
DECLARE_XAM_EXPORT2(XamContentGetLicenseMask, kContent, kStub, kHighFrequency);
dword_result_t XamContentGetDeviceName(dword_t device_id,
lpwstring_t name_buffer,
lpu16string_t name_buffer,
dword_t name_capacity) {
if ((device_id & 0xFFFF0000) != dummy_device_info_.device_id) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
auto name = std::wstring(dummy_device_info_.name);
auto name = std::u16string(dummy_device_info_.name);
if (name_capacity < name.size() + 1) {
return X_ERROR_INSUFFICIENT_BUFFER;
}
xe::store_and_swap<std::wstring>(name_buffer, name);
((wchar_t*)name_buffer)[name.size()] = 0;
xe::store_and_swap<std::u16string>(name_buffer, name);
((char16_t*)name_buffer)[name.size()] = 0;
return X_ERROR_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamContentGetDeviceName, kContent, kImplemented);
@@ -132,7 +132,7 @@ dword_result_t XamContentGetDeviceData(
device_data->unknown = device_id & 0xFFFF; // Fake it.
device_data->total_bytes = device_info.total_bytes;
device_data->free_bytes = device_info.free_bytes;
xe::store_and_swap<std::wstring>(&device_data->name[0], device_info.name);
xe::store_and_swap<std::u16string>(&device_data->name[0], device_info.name);
return X_ERROR_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamContentGetDeviceData, kContent, kImplemented);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2019 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -21,6 +21,8 @@
#include "xenia/base/platform_win.h"
#endif
#include "third_party/fmt/include/fmt/format.h"
namespace xe {
namespace kernel {
namespace xam {
@@ -56,54 +58,48 @@ dword_result_t XamGetOnlineSchema() {
}
DECLARE_XAM_EXPORT1(XamGetOnlineSchema, kNone, kImplemented);
void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t buffer,
dword_t buffer_length) {
std::memset(buffer, 0, buffer_length * 2);
// TODO: implement this for other platforms
#if XE_PLATFORM_WIN32
static SYSTEMTIME xeGetLocalSystemTime(uint64_t filetime) {
FILETIME t;
t.dwHighDateTime = filetime >> 32;
t.dwLowDateTime = (uint32_t)filetime;
SYSTEMTIME st;
SYSTEMTIME stLocal;
SYSTEMTIME local_st;
FileTimeToSystemTime(&t, &st);
SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal);
SystemTimeToTzSpecificLocalTime(NULL, &st, &local_st);
return local_st;
}
#endif
wchar_t buf[256];
void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t output_buffer,
dword_t output_count) {
std::memset(output_buffer, 0, output_count * 2);
// TODO: implement this for other platforms
#if XE_PLATFORM_WIN32
auto st = xeGetLocalSystemTime(filetime);
// TODO: format this depending on users locale?
swprintf(buf, 256, L"%02d/%02d/%d", stLocal.wMonth, stLocal.wDay,
stLocal.wYear);
xe::copy_and_swap((wchar_t*)buffer.host_address(), buf, buffer_length);
auto str = fmt::format(u"{:02d}/{:02d}/{}", st.wMonth, st.wDay, st.wYear);
auto copy_length = std::min(size_t(output_count), str.size()) * 2;
xe::copy_and_swap(output_buffer.as<char16_t*>(), str.c_str(), copy_length);
#else
assert_always();
#endif
}
DECLARE_XAM_EXPORT1(XamFormatDateString, kNone, kImplemented);
void XamFormatTimeString(dword_t unk, qword_t filetime, lpvoid_t buffer,
dword_t buffer_length) {
std::memset(buffer, 0, buffer_length * 2);
void XamFormatTimeString(dword_t unk, qword_t filetime, lpvoid_t output_buffer,
dword_t output_count) {
std::memset(output_buffer, 0, output_count * 2);
// TODO: implement this for other platforms
#if XE_PLATFORM_WIN32
FILETIME t;
t.dwHighDateTime = filetime >> 32;
t.dwLowDateTime = (uint32_t)filetime;
SYSTEMTIME st;
SYSTEMTIME stLocal;
FileTimeToSystemTime(&t, &st);
SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal);
wchar_t buf[256];
swprintf(buf, 256, L"%02d:%02d", stLocal.wHour, stLocal.wMinute);
xe::copy_and_swap((wchar_t*)buffer.host_address(), buf, buffer_length);
auto st = xeGetLocalSystemTime(filetime);
// TODO: format this depending on users locale?
auto str = fmt::format(u"{:02d}:{:02d}", st.wHour, st.wMinute);
auto copy_count = std::min(size_t(output_count), str.size());
xe::copy_and_swap(output_buffer.as<char16_t*>(), str.c_str(), copy_count);
#else
assert_always();
#endif
@@ -111,38 +107,36 @@ void XamFormatTimeString(dword_t unk, qword_t filetime, lpvoid_t buffer,
DECLARE_XAM_EXPORT1(XamFormatTimeString, kNone, kImplemented);
dword_result_t keXamBuildResourceLocator(uint64_t module,
const wchar_t* container,
const wchar_t* resource,
lpvoid_t buffer,
uint32_t buffer_length) {
wchar_t buf[256];
const std::u16string& container,
const std::u16string& resource,
lpvoid_t buffer_ptr,
uint32_t buffer_count) {
std::u16string path;
if (!module) {
swprintf(buf, 256, L"file://media:/%s.xzp#%s", container, resource);
XELOGD(
"XamBuildResourceLocator(%ws) returning locator to local file %ws.xzp",
container, container);
path = fmt::format(u"file://media:/{0}.xzp#{0}", container, resource);
XELOGD("XamBuildResourceLocator(%s) returning locator to local file %s.xzp",
xe::to_utf8(container).c_str(), xe::to_utf8(container).c_str());
} else {
swprintf(buf, 256, L"section://%X,%s#%s", (uint32_t)module, container,
resource);
path = fmt::format(u"section://{:X},{}#{}", (uint32_t)module, container,
resource);
}
xe::copy_and_swap((wchar_t*)buffer.host_address(), buf, buffer_length);
auto copy_count = std::min(size_t(buffer_count), path.size());
xe::copy_and_swap(buffer_ptr.as<char16_t*>(), path.c_str(), copy_count);
return 0;
}
dword_result_t XamBuildResourceLocator(qword_t module, lpwstring_t container,
lpwstring_t resource, lpvoid_t buffer,
dword_t buffer_length) {
return keXamBuildResourceLocator(module, container.value().c_str(),
resource.value().c_str(), buffer,
buffer_length);
dword_result_t XamBuildResourceLocator(qword_t module, lpu16string_t container,
lpu16string_t resource,
lpvoid_t buffer_ptr,
dword_t buffer_count) {
return keXamBuildResourceLocator(module, container.value(), resource.value(),
buffer_ptr, buffer_count);
}
DECLARE_XAM_EXPORT1(XamBuildResourceLocator, kNone, kImplemented);
dword_result_t XamBuildGamercardResourceLocator(lpwstring_t filename,
lpvoid_t buffer,
dword_t buffer_length) {
dword_result_t XamBuildGamercardResourceLocator(lpu16string_t filename,
lpvoid_t buffer_ptr,
dword_t buffer_count) {
// On an actual xbox these funcs would return a locator to xam.xex resources,
// but for Xenia we can return a locator to the resources as local files. (big
// thanks to MS for letting XamBuildResourceLocator return local file
@@ -151,31 +145,33 @@ dword_result_t XamBuildGamercardResourceLocator(lpwstring_t filename,
// If you're running an app that'll need them, make sure to extract xam.xex
// resources with xextool ("xextool -d . xam.xex") and add a .xzp extension.
return keXamBuildResourceLocator(0, L"gamercrd", filename.value().c_str(),
buffer, buffer_length);
return keXamBuildResourceLocator(0, u"gamercrd", filename.value(), buffer_ptr,
buffer_count);
}
DECLARE_XAM_EXPORT1(XamBuildGamercardResourceLocator, kNone, kImplemented);
dword_result_t XamBuildSharedSystemResourceLocator(lpwstring_t filename,
lpvoid_t buffer,
dword_t buffer_length) {
dword_result_t XamBuildSharedSystemResourceLocator(lpu16string_t filename,
lpvoid_t buffer_ptr,
dword_t buffer_count) {
// see notes inside XamBuildGamercardResourceLocator above
return keXamBuildResourceLocator(0, L"shrdres", filename.value().c_str(),
buffer, buffer_length);
return keXamBuildResourceLocator(0, u"shrdres", filename.value(), buffer_ptr,
buffer_count);
}
DECLARE_XAM_EXPORT1(XamBuildSharedSystemResourceLocator, kNone, kImplemented);
dword_result_t XamBuildLegacySystemResourceLocator(lpwstring_t filename,
lpvoid_t buffer,
dword_t buffer_length) {
return XamBuildSharedSystemResourceLocator(filename, buffer, buffer_length);
dword_result_t XamBuildLegacySystemResourceLocator(lpu16string_t filename,
lpvoid_t buffer_ptr,
dword_t buffer_count) {
return XamBuildSharedSystemResourceLocator(filename, buffer_ptr,
buffer_count);
}
DECLARE_XAM_EXPORT1(XamBuildLegacySystemResourceLocator, kNone, kImplemented);
dword_result_t XamBuildXamResourceLocator(lpwstring_t filename, lpvoid_t buffer,
dword_t buffer_length) {
return keXamBuildResourceLocator(0, L"xam", filename.value().c_str(), buffer,
buffer_length);
dword_result_t XamBuildXamResourceLocator(lpu16string_t filename,
lpvoid_t buffer_ptr,
dword_t buffer_count) {
return keXamBuildResourceLocator(0, u"xam", filename.value(), buffer_ptr,
buffer_count);
}
DECLARE_XAM_EXPORT1(XamBuildXamResourceLocator, kNone, kImplemented);
@@ -285,25 +281,26 @@ dword_result_t XamLoaderGetLaunchData(lpvoid_t buffer_ptr,
}
DECLARE_XAM_EXPORT1(XamLoaderGetLaunchData, kNone, kSketchy);
void XamLoaderLaunchTitle(lpstring_t raw_name, dword_t flags) {
void XamLoaderLaunchTitle(lpstring_t raw_name_ptr, dword_t flags) {
auto xam = kernel_state()->GetKernelModule<XamModule>("xam.xex");
auto& loader_data = xam->loader_data();
loader_data.launch_flags = flags;
// Translate the launch path to a full path.
if (raw_name && raw_name.value() == "") {
loader_data.launch_path = "game:\\default.xex";
} else if (raw_name) {
std::string name = xe::find_name_from_path(std::string(raw_name));
std::string path(raw_name);
if (name == std::string(raw_name)) {
path = xe::join_paths(
xe::find_base_path(kernel_state()->GetExecutableModule()->path()),
name);
if (raw_name_ptr) {
auto path = raw_name_ptr.value();
if (path.empty()) {
loader_data.launch_path = "game:\\default.xex";
} else {
if (xe::utf8::find_name_from_guest_path(path) == path) {
path = xe::utf8::join_guest_paths(
xe::utf8::find_base_guest_path(
kernel_state()->GetExecutableModule()->path()),
path);
}
loader_data.launch_path = path;
}
loader_data.launch_path = path;
} else {
assert_always("Game requested exit to dashboard via XamLoaderLaunchTitle");
}
@@ -422,7 +419,7 @@ dword_result_t XamGetPrivateEnumStructureFromHandle(unknown_t unk1,
}
DECLARE_XAM_EXPORT1(XamGetPrivateEnumStructureFromHandle, kNone, kStub);
dword_result_t XamQueryLiveHiveW(lpwstring_t name, lpvoid_t out_buf,
dword_result_t XamQueryLiveHiveW(lpu16string_t name, lpvoid_t out_buf,
dword_t out_size, dword_t type /* guess */) {
return X_STATUS_INVALID_PARAMETER_1;
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2019 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -45,75 +45,75 @@ uint8_t xeXamGetOnlineCountryFromLocale(uint8_t id) {
return id < xe::countof(table) ? table[id] : 0;
}
const wchar_t* xeXamGetOnlineCountryString(uint8_t id) {
static const wchar_t* const table[] = {
L"ZZ", L"AE", L"AL", L"AM", L"AR", L"AT", L"AU", L"AZ", L"BE",
L"BG", L"BH", L"BN", L"BO", L"BR", L"BY", L"BZ", L"CA", nullptr,
L"CH", L"CL", L"CN", L"CO", L"CR", L"CZ", L"DE", L"DK", L"DO",
L"DZ", L"EC", L"EE", L"EG", L"ES", L"FI", L"FO", L"FR", L"GB",
L"GE", L"GR", L"GT", L"HK", L"HN", L"HR", L"HU", L"ID", L"IE",
L"IL", L"IN", L"IQ", L"IR", L"IS", L"IT", L"JM", L"JO", L"JP",
L"KE", L"KG", L"KR", L"KW", L"KZ", L"LB", L"LI", L"LT", L"LU",
L"LV", L"LY", L"MA", L"MC", L"MK", L"MN", L"MO", L"MV", L"MX",
L"MY", L"NI", L"NL", L"NO", L"NZ", L"OM", L"PA", L"PE", L"PH",
L"PK", L"PL", L"PR", L"PT", L"PY", L"QA", L"RO", L"RU", L"SA",
L"SE", L"SG", L"SI", L"SK", nullptr, L"SV", L"SY", L"TH", L"TN",
L"TR", L"TT", L"TW", L"UA", L"US", L"UY", L"UZ", L"VE", L"VN",
L"YE", L"ZA", L"ZW", L"AF", nullptr, L"AD", L"AO", L"AI", nullptr,
L"AG", L"AW", L"BS", L"BD", L"BB", L"BJ", L"BM", L"BT", L"BA",
L"BW", L"BF", L"BI", L"KH", L"CM", L"CV", L"KY", L"CF", L"TD",
L"CX", L"CC", L"KM", L"CG", L"CD", L"CK", L"CI", L"CY", L"DJ",
L"DM", nullptr, L"GQ", L"ER", L"ET", L"FK", L"FJ", L"GF", L"PF",
L"GA", L"GM", L"GH", L"GI", L"GL", L"GD", L"GP", nullptr, L"GG",
L"GN", L"GW", L"GY", L"HT", L"JE", L"KI", L"LA", L"LS", L"LR",
L"MG", L"MW", L"ML", L"MT", L"MH", L"MQ", L"MR", L"MU", L"YT",
L"FM", L"MD", L"ME", L"MS", L"MZ", L"MM", L"NA", L"NR", L"NP",
L"AN", L"NC", L"NE", L"NG", L"NU", L"NF", nullptr, L"PW", L"PS",
L"PG", L"PN", L"RE", L"RW", L"WS", L"SM", L"ST", L"SN", L"RS",
L"SC", L"SL", L"SB", L"SO", L"LK", L"SH", L"KN", L"LC", L"PM",
L"VC", L"SR", L"SZ", L"TJ", L"TZ", L"TL", L"TG", L"TK", L"TO",
L"TM", L"TC", L"TV", L"UG", L"VU", L"VA", nullptr, L"VG", L"WF",
L"EH", L"ZM", L"ZZ",
const char16_t* xeXamGetOnlineCountryString(uint8_t id) {
static const char16_t* const table[] = {
u"ZZ", u"AE", u"AL", u"AM", u"AR", u"AT", u"AU", u"AZ", u"BE",
u"BG", u"BH", u"BN", u"BO", u"BR", u"BY", u"BZ", u"CA", nullptr,
u"CH", u"CL", u"CN", u"CO", u"CR", u"CZ", u"DE", u"DK", u"DO",
u"DZ", u"EC", u"EE", u"EG", u"ES", u"FI", u"FO", u"FR", u"GB",
u"GE", u"GR", u"GT", u"HK", u"HN", u"HR", u"HU", u"ID", u"IE",
u"IL", u"IN", u"IQ", u"IR", u"IS", u"IT", u"JM", u"JO", u"JP",
u"KE", u"KG", u"KR", u"KW", u"KZ", u"LB", u"LI", u"LT", u"LU",
u"LV", u"LY", u"MA", u"MC", u"MK", u"MN", u"MO", u"MV", u"MX",
u"MY", u"NI", u"NL", u"NO", u"NZ", u"OM", u"PA", u"PE", u"PH",
u"PK", u"PL", u"PR", u"PT", u"PY", u"QA", u"RO", u"RU", u"SA",
u"SE", u"SG", u"SI", u"SK", nullptr, u"SV", u"SY", u"TH", u"TN",
u"TR", u"TT", u"TW", u"UA", u"US", u"UY", u"UZ", u"VE", u"VN",
u"YE", u"ZA", u"ZW", u"AF", nullptr, u"AD", u"AO", u"AI", nullptr,
u"AG", u"AW", u"BS", u"BD", u"BB", u"BJ", u"BM", u"BT", u"BA",
u"BW", u"BF", u"BI", u"KH", u"CM", u"CV", u"KY", u"CF", u"TD",
u"CX", u"CC", u"KM", u"CG", u"CD", u"CK", u"CI", u"CY", u"DJ",
u"DM", nullptr, u"GQ", u"ER", u"ET", u"FK", u"FJ", u"GF", u"PF",
u"GA", u"GM", u"GH", u"GI", u"GL", u"GD", u"GP", nullptr, u"GG",
u"GN", u"GW", u"GY", u"HT", u"JE", u"KI", u"LA", u"LS", u"LR",
u"MG", u"MW", u"ML", u"MT", u"MH", u"MQ", u"MR", u"MU", u"YT",
u"FM", u"MD", u"ME", u"MS", u"MZ", u"MM", u"NA", u"NR", u"NP",
u"AN", u"NC", u"NE", u"NG", u"NU", u"NF", nullptr, u"PW", u"PS",
u"PG", u"PN", u"RE", u"RW", u"WS", u"SM", u"ST", u"SN", u"RS",
u"SC", u"SL", u"SB", u"SO", u"LK", u"SH", u"KN", u"LC", u"PM",
u"VC", u"SR", u"SZ", u"TJ", u"TZ", u"TL", u"TG", u"TK", u"TO",
u"TM", u"TC", u"TV", u"UG", u"VU", u"VA", nullptr, u"VG", u"WF",
u"EH", u"ZM", u"ZZ",
};
#pragma warning(suppress : 6385)
return id < xe::countof(table) ? table[id] : nullptr;
}
const wchar_t* xeXamGetCountryString(uint8_t id) {
static const wchar_t* const table[] = {
L"ZZ", L"AE", L"AL", L"AM", L"AR", L"AT", L"AU", L"AZ", L"BE", L"BG",
L"BH", L"BN", L"BO", L"BR", L"BY", L"BZ", L"CA", nullptr, L"CH", L"CL",
L"CN", L"CO", L"CR", L"CZ", L"DE", L"DK", L"DO", L"DZ", L"EC", L"EE",
L"EG", L"ES", L"FI", L"FO", L"FR", L"GB", L"GE", L"GR", L"GT", L"HK",
L"HN", L"HR", L"HU", L"ID", L"IE", L"IL", L"IN", L"IQ", L"IR", L"IS",
L"IT", L"JM", L"JO", L"JP", L"KE", L"KG", L"KR", L"KW", L"KZ", L"LB",
L"LI", L"LT", L"LU", L"LV", L"LY", L"MA", L"MC", L"MK", L"MN", L"MO",
L"MV", L"MX", L"MY", L"NI", L"NL", L"NO", L"NZ", L"OM", L"PA", L"PE",
L"PH", L"PK", L"PL", L"PR", L"PT", L"PY", L"QA", L"RO", L"RU", L"SA",
L"SE", L"SG", L"SI", L"SK", nullptr, L"SV", L"SY", L"TH", L"TN", L"TR",
L"TT", L"TW", L"UA", L"US", L"UY", L"UZ", L"VE", L"VN", L"YE", L"ZA",
L"ZW", L"ZZ",
const char16_t* xeXamGetCountryString(uint8_t id) {
static const char16_t* const table[] = {
u"ZZ", u"AE", u"AL", u"AM", u"AR", u"AT", u"AU", u"AZ", u"BE", u"BG",
u"BH", u"BN", u"BO", u"BR", u"BY", u"BZ", u"CA", nullptr, u"CH", u"CL",
u"CN", u"CO", u"CR", u"CZ", u"DE", u"DK", u"DO", u"DZ", u"EC", u"EE",
u"EG", u"ES", u"FI", u"FO", u"FR", u"GB", u"GE", u"GR", u"GT", u"HK",
u"HN", u"HR", u"HU", u"ID", u"IE", u"IL", u"IN", u"IQ", u"IR", u"IS",
u"IT", u"JM", u"JO", u"JP", u"KE", u"KG", u"KR", u"KW", u"KZ", u"LB",
u"LI", u"LT", u"LU", u"LV", u"LY", u"MA", u"MC", u"MK", u"MN", u"MO",
u"MV", u"MX", u"MY", u"NI", u"NL", u"NO", u"NZ", u"OM", u"PA", u"PE",
u"PH", u"PK", u"PL", u"PR", u"PT", u"PY", u"QA", u"RO", u"RU", u"SA",
u"SE", u"SG", u"SI", u"SK", nullptr, u"SV", u"SY", u"TH", u"TN", u"TR",
u"TT", u"TW", u"UA", u"US", u"UY", u"UZ", u"VE", u"VN", u"YE", u"ZA",
u"ZW", u"ZZ",
};
#pragma warning(suppress : 6385)
return id < xe::countof(table) ? table[id] : nullptr;
}
const wchar_t* xeXamGetLanguageString(uint8_t id) {
static const wchar_t* const table[] = {
L"zz", L"en", L"ja", L"de", L"fr", L"es", L"it", L"ko", L"zh",
L"pt", nullptr, L"pl", L"ru", L"sv", L"tr", L"nb", L"nl", L"zh",
const char16_t* xeXamGetLanguageString(uint8_t id) {
static const char16_t* const table[] = {
u"zz", u"en", u"ja", u"de", u"fr", u"es", u"it", u"ko", u"zh",
u"pt", nullptr, u"pl", u"ru", u"sv", u"tr", u"nb", u"nl", u"zh",
};
#pragma warning(suppress : 6385)
return id < xe::countof(table) ? table[id] : nullptr;
}
const wchar_t* xeXamGetLocaleString(uint8_t id) {
static const wchar_t* const table[] = {
L"ZZ", L"AU", L"AT", L"BE", L"BR", L"CA", L"CL", L"CN", L"CO",
L"CZ", L"DK", L"FI", L"FR", L"DE", L"GR", L"HK", L"HU", L"IN",
L"IE", L"IT", L"JP", L"KR", L"MX", L"NL", L"NZ", L"NO", L"PL",
L"PT", L"SG", L"SK", L"ZA", L"ES", L"SE", L"CH", L"TW", L"GB",
L"US", L"RU", L"ZZ", L"TR", L"AR", L"SA", L"IL", L"AE",
const char16_t* xeXamGetLocaleString(uint8_t id) {
static const char16_t* const table[] = {
u"ZZ", u"AU", u"AT", u"BE", u"BR", u"CA", u"CL", u"CN", u"CO",
u"CZ", u"DK", u"FI", u"FR", u"DE", u"GR", u"HK", u"HU", u"IN",
u"IE", u"IT", u"JP", u"KR", u"MX", u"NL", u"NZ", u"NO", u"PL",
u"PT", u"SG", u"SK", u"ZA", u"ES", u"SE", u"CH", u"TW", u"GB",
u"US", u"RU", u"ZZ", u"TR", u"AR", u"SA", u"IL", u"AE",
};
#pragma warning(suppress : 6385)
return id < xe::countof(table) ? table[id] : nullptr;
@@ -149,15 +149,15 @@ uint8_t xeXamGetLanguageFromOnlineLanguage(uint8_t id) {
return id < xe::countof(table) ? table[id] : 0;
}
const wchar_t* xeXamGetOnlineLanguageString(uint8_t id) {
static const wchar_t* const table[] = {
L"zz", L"en", L"ja", L"de", L"fr", L"es", L"it", L"ko", L"zh",
L"pt", L"zh", L"pl", L"ru", L"da", L"fi", L"nb", L"nl", L"sv",
L"cs", L"el", L"hu", L"sk", L"id", L"ms", L"ar", L"bg", L"et",
L"hr", L"he", L"is", L"kk", L"lt", L"lv", L"ro", L"sl", L"th",
L"tr", L"uk", L"vi", L"ps", L"sq", L"hy", L"bn", L"be", L"km",
L"am", L"fo", L"ka", L"kl", L"sw", L"ky", L"lb", L"mk", L"mt",
L"mn", L"ne", L"ur", L"rw", L"wo", L"si", L"tk",
const char16_t* xeXamGetOnlineLanguageString(uint8_t id) {
static const char16_t* const table[] = {
u"zz", u"en", u"ja", u"de", u"fr", u"es", u"it", u"ko", u"zh",
u"pt", u"zh", u"pl", u"ru", u"da", u"fi", u"nb", u"nl", u"sv",
u"cs", u"el", u"hu", u"sk", u"id", u"ms", u"ar", u"bg", u"et",
u"hr", u"he", u"is", u"kk", u"lt", u"lv", u"ro", u"sl", u"th",
u"tr", u"uk", u"vi", u"ps", u"sq", u"hy", u"bn", u"be", u"km",
u"am", u"fo", u"ka", u"kl", u"sw", u"ky", u"lb", u"mk", u"mt",
u"mn", u"ne", u"ur", u"rw", u"wo", u"si", u"tk",
};
#pragma warning(suppress : 6385)
return id < xe::countof(table) ? table[id] : nullptr;
@@ -235,7 +235,7 @@ dword_result_t XamGetOnlineCountryFromLocale(dword_t id) {
DECLARE_XAM_EXPORT1(XamGetOnlineCountryFromLocale, kLocale, kImplemented);
dword_result_t XamGetOnlineCountryString(dword_t id, dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -245,19 +245,19 @@ dword_result_t XamGetOnlineCountryString(dword_t id, dword_t buffer_length,
return X_E_NOTFOUND;
}
const auto value = std::wstring(str);
const auto value = std::u16string(str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetOnlineCountryString, kLocale, kImplemented);
dword_result_t XamGetCountryString(dword_t id, dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -267,19 +267,19 @@ dword_result_t XamGetCountryString(dword_t id, dword_t buffer_length,
return X_E_NOTFOUND;
}
const auto value = std::wstring(str);
const auto value = std::u16string(str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetCountryString, kLocale, kImplemented);
dword_result_t XamGetLanguageString(dword_t id, dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -289,13 +289,13 @@ dword_result_t XamGetLanguageString(dword_t id, dword_t buffer_length,
return X_E_NOTFOUND;
}
const auto value = std::wstring(str);
const auto value = std::u16string(str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetLanguageString, kLocale, kImplemented);
@@ -303,7 +303,7 @@ DECLARE_XAM_EXPORT1(XamGetLanguageString, kLocale, kImplemented);
dword_result_t XamGetLanguageLocaleString(dword_t language_id,
dword_t locale_id,
dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -319,13 +319,13 @@ dword_result_t XamGetLanguageLocaleString(dword_t language_id,
}
const auto value =
std::wstring(language_str) + L"-" + std::wstring(locale_str);
std::u16string(language_str) + u"-" + std::u16string(locale_str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetLanguageLocaleString, kLocale, kImplemented);
@@ -333,7 +333,7 @@ DECLARE_XAM_EXPORT1(XamGetLanguageLocaleString, kLocale, kImplemented);
dword_result_t XamGetOnlineLanguageAndCountryString(dword_t language_id,
dword_t country_id,
dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -351,20 +351,20 @@ dword_result_t XamGetOnlineLanguageAndCountryString(dword_t language_id,
}
const auto value =
std::wstring(language_str) + L"-" + std::wstring(country_str);
std::u16string(language_str) + u"-" + std::u16string(country_str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetOnlineLanguageAndCountryString, kLocale,
kImplemented);
dword_result_t XamGetLocaleString(dword_t id, dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -374,13 +374,13 @@ dword_result_t XamGetLocaleString(dword_t id, dword_t buffer_length,
return X_E_NOTFOUND;
}
const auto value = std::wstring(str);
const auto value = std::u16string(str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetLocaleString, kLocale, kImplemented);
@@ -396,7 +396,7 @@ dword_result_t XamGetLanguageFromOnlineLanguage(dword_t id) {
DECLARE_XAM_EXPORT1(XamGetLanguageFromOnlineLanguage, kLocale, kImplemented);
dword_result_t XamGetOnlineLanguageString(dword_t id, dword_t buffer_length,
lpwstring_t buffer) {
lpu16string_t buffer) {
if (buffer_length >= 0x80000000u) {
return X_E_INVALIDARG;
}
@@ -406,13 +406,13 @@ dword_result_t XamGetOnlineLanguageString(dword_t id, dword_t buffer_length,
return X_E_NOTFOUND;
}
const auto value = std::wstring(str);
const auto value = std::u16string(str);
if (value.size() + 1 > buffer_length) {
return X_HRESULT_FROM_WIN32(X_ERROR_INSUFFICIENT_BUFFER);
}
xe::store_and_swap<std::wstring>(buffer, value);
static_cast<wchar_t*>(buffer)[value.size()] = 0;
xe::store_and_swap<std::u16string>(buffer, value);
static_cast<char16_t*>(buffer)[value.size()] = 0;
return X_E_SUCCESS;
}
DECLARE_XAM_EXPORT1(XamGetOnlineLanguageString, kLocale, kImplemented);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -29,12 +29,13 @@ DECLARE_XAM_EXPORT2(XamIsUIActive, kUI, kImplemented, kHighFrequency);
class MessageBoxDialog : public xe::ui::ImGuiDialog {
public:
MessageBoxDialog(xe::ui::Window* window, std::wstring title,
std::wstring description, std::vector<std::wstring> buttons,
uint32_t default_button, uint32_t* out_chosen_button)
MessageBoxDialog(xe::ui::Window* window, std::u16string title,
std::u16string description,
std::vector<std::u16string> buttons, uint32_t default_button,
uint32_t* out_chosen_button)
: ImGuiDialog(window),
title_(xe::to_string(title)),
description_(xe::to_string(description)),
title_(xe::to_utf8(title)),
description_(xe::to_utf8(description)),
buttons_(std::move(buttons)),
default_button_(default_button),
out_chosen_button_(out_chosen_button) {
@@ -62,7 +63,7 @@ class MessageBoxDialog : public xe::ui::ImGuiDialog {
ImGui::SetKeyboardFocusHere();
}
for (size_t i = 0; i < buttons_.size(); ++i) {
auto button_name = xe::to_string(buttons_[i]);
auto button_name = xe::to_utf8(buttons_[i]);
if (ImGui::Button(button_name.c_str())) {
if (out_chosen_button_) {
*out_chosen_button_ = static_cast<uint32_t>(i);
@@ -84,34 +85,34 @@ class MessageBoxDialog : public xe::ui::ImGuiDialog {
bool has_opened_ = false;
std::string title_;
std::string description_;
std::vector<std::wstring> buttons_;
std::vector<std::u16string> buttons_;
uint32_t default_button_ = 0;
uint32_t* out_chosen_button_ = nullptr;
};
// https://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/
dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
lpwstring_t text_ptr, dword_t button_count,
dword_result_t XamShowMessageBoxUI(dword_t user_index, lpu16string_t title_ptr,
lpu16string_t text_ptr, dword_t button_count,
lpdword_t button_ptrs, dword_t active_button,
dword_t flags, lpdword_t result_ptr,
pointer_t<XAM_OVERLAPPED> overlapped) {
std::wstring title;
std::u16string title;
if (title_ptr) {
title = title_ptr.value();
} else {
title = L""; // TODO(gibbed): default title based on flags?
title = u""; // TODO(gibbed): default title based on flags?
}
auto text = text_ptr.value();
std::vector<std::wstring> buttons;
std::wstring all_buttons;
std::vector<std::u16string> buttons;
std::u16string all_buttons;
for (uint32_t j = 0; j < button_count; ++j) {
uint32_t button_ptr = button_ptrs[j];
auto button = xe::load_and_swap<std::wstring>(
auto button = xe::load_and_swap<std::u16string>(
kernel_state()->memory()->TranslateVirtual(button_ptr));
all_buttons.append(button);
if (j + 1 < button_count) {
all_buttons.append(L" | ");
all_buttons.append(u" | ");
}
buttons.push_back(button);
}
@@ -166,13 +167,13 @@ DECLARE_XAM_EXPORT1(XamShowMessageBoxUI, kUI, kImplemented);
class KeyboardInputDialog : public xe::ui::ImGuiDialog {
public:
KeyboardInputDialog(xe::ui::Window* window, std::wstring title,
std::wstring description, std::wstring default_text,
std::wstring* out_text, size_t max_length)
KeyboardInputDialog(xe::ui::Window* window, std::u16string title,
std::u16string description, std::u16string default_text,
std::u16string* out_text, size_t max_length)
: ImGuiDialog(window),
title_(xe::to_string(title)),
description_(xe::to_string(description)),
default_text_(xe::to_string(default_text)),
title_(xe::to_utf8(title)),
description_(xe::to_utf8(description)),
default_text_(xe::to_utf8(default_text)),
out_text_(out_text),
max_length_(max_length) {
if (!title_.size()) {
@@ -209,14 +210,16 @@ class KeyboardInputDialog : public xe::ui::ImGuiDialog {
if (ImGui::InputText("##body", text_buffer_.data(), text_buffer_.size(),
ImGuiInputTextFlags_EnterReturnsTrue)) {
if (out_text_) {
*out_text_ = xe::to_wstring(text_buffer_.data());
*out_text_ = xe::to_utf16(
std::string_view(text_buffer_.data(), text_buffer_.size()));
}
ImGui::CloseCurrentPopup();
Close();
}
if (ImGui::Button("OK")) {
if (out_text_) {
*out_text_ = xe::to_wstring(text_buffer_.data());
*out_text_ = xe::to_utf16(
std::string_view(text_buffer_.data(), text_buffer_.size()));
}
ImGui::CloseCurrentPopup();
Close();
@@ -238,16 +241,16 @@ class KeyboardInputDialog : public xe::ui::ImGuiDialog {
std::string title_;
std::string description_;
std::string default_text_;
std::wstring* out_text_ = nullptr;
std::u16string* out_text_ = nullptr;
std::vector<char> text_buffer_;
size_t max_length_ = 0;
};
// https://www.se7ensins.com/forums/threads/release-how-to-use-xshowkeyboardui-release.906568/
dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
lpwstring_t default_text, lpwstring_t title,
lpwstring_t description, lpwstring_t buffer,
dword_t buffer_length,
lpu16string_t default_text,
lpu16string_t title, lpu16string_t description,
lpu16string_t buffer, dword_t buffer_length,
pointer_t<XAM_OVERLAPPED> overlapped) {
if (!buffer) {
return X_ERROR_INVALID_PARAMETER;
@@ -260,7 +263,7 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
// Redirect default_text back into the buffer.
std::memset(buffer, 0, buffer_length * 2);
if (default_text) {
xe::store_and_swap<std::wstring>(buffer, default_text.value());
xe::store_and_swap<std::u16string>(buffer, default_text.value());
}
// Broadcast XN_SYS_UI = false
@@ -274,14 +277,14 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
}
}
std::wstring out_text;
std::u16string out_text;
auto display_window = kernel_state()->emulator()->display_window();
xe::threading::Fence fence;
display_window->loop()->PostSynchronous([&]() {
(new KeyboardInputDialog(display_window, title ? title.value() : L"",
description ? description.value() : L"",
default_text ? default_text.value() : L"",
(new KeyboardInputDialog(display_window, title ? title.value() : u"",
description ? description.value() : u"",
default_text ? default_text.value() : u"",
&out_text, buffer_length))
->Then(&fence);
});
@@ -294,7 +297,7 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
// Truncate the string.
out_text = out_text.substr(0, buffer_length - 1);
xe::store_and_swap<std::wstring>(buffer, out_text);
xe::store_and_swap<std::u16string>(buffer, out_text);
// Broadcast XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, false);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -91,8 +91,7 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
// Compute path, possibly attrs relative.
std::string target_path =
util::TranslateAnsiString(kernel_memory(), object_name);
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices
object_attrs->root_directory != 0) {
auto root_file = kernel_state()->object_table()->LookupObject<XFile>(
@@ -102,8 +101,8 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
// Resolve the file using the device the root directory is part of.
auto device = root_file->device();
target_path = xe::join_paths(
device->mount_path(), xe::join_paths(root_file->path(), target_path));
target_path = xe::utf8::join_guest_paths(
{device->mount_path(), root_file->path(), target_path});
}
// Attempt open (or create).
@@ -686,9 +685,8 @@ dword_result_t NtQueryDirectoryFile(
auto name = util::TranslateAnsiString(kernel_memory(), file_name);
if (file) {
X_FILE_DIRECTORY_INFORMATION dir_info = {0};
result = file->QueryDirectory(file_info_ptr, length,
!name.empty() ? name.c_str() : nullptr,
restart_scan != 0);
result =
file->QueryDirectory(file_info_ptr, length, name, restart_scan != 0);
if (XSUCCEEDED(result)) {
info = length;
}
@@ -741,8 +739,7 @@ dword_result_t NtOpenSymbolicLinkObject(
assert_always();
}
auto pos = target_path.find("\\??\\");
if (pos != target_path.npos && pos == 0) {
if (utf8::starts_with(target_path, "\\??\\")) {
target_path = target_path.substr(4); // Strip the full qualifier
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2019 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -11,6 +11,7 @@
#include <vector>
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/base/clock.h"
#include "xenia/base/debugging.h"
#include "xenia/base/logging.h"
@@ -47,15 +48,18 @@ bool XboxkrnlModule::SendPIXCommand(const char* cmd) {
return false;
}
auto scratch = memory_->SystemHeapAlloc(260 + 260);
uint32_t scratch_size = 260 + 260;
auto scratch_ptr = memory_->SystemHeapAlloc(scratch_size);
auto scratch = memory_->TranslateVirtual(scratch_ptr);
std::memset(scratch, 0, scratch_size);
auto response = memory_->TranslateVirtual<const char*>(scratch + 0);
auto command = memory_->TranslateVirtual<char*>(scratch + 260);
auto response = reinterpret_cast<char*>(scratch + 0);
auto command = reinterpret_cast<char*>(scratch + 260);
std::snprintf(command, 260, "PIX!m!%s", cmd);
fmt::format_to_n(command, 259, "PIX!m!{}", cmd);
global_lock.unlock();
uint64_t args[] = {scratch + 260, scratch, 260};
uint64_t args[] = {scratch_ptr + 260, scratch_ptr, 260};
auto result = kernel_state_->processor()->Execute(
XThread::GetCurrentThread()->thread_state(), pix_function_, args,
xe::countof(args));
@@ -64,7 +68,7 @@ bool XboxkrnlModule::SendPIXCommand(const char* cmd) {
XELOGD("PIX(command): %s", cmd);
XELOGD("PIX(response): %s", response);
memory_->SystemHeapFree(scratch);
memory_->SystemHeapFree(scratch_ptr);
if (XSUCCEEDED(result)) {
return true;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2019 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -46,7 +46,7 @@ dword_result_t XexGetModuleHandle(lpstring_t module_name,
if (!module_name) {
module = kernel_state()->GetExecutableModule();
} else {
module = kernel_state()->GetModule(module_name);
module = kernel_state()->GetModule(module_name.value());
}
if (!module) {
@@ -69,7 +69,7 @@ dword_result_t XexGetModuleSection(lpvoid_t hmodule, lpstring_t name,
if (module) {
uint32_t section_data = 0;
uint32_t section_size = 0;
result = module->GetSection(name, &section_data, &section_size);
result = module->GetSection(name.value(), &section_data, &section_size);
if (XSUCCEEDED(result)) {
*data_ptr = section_data;
*size_ptr = section_size;
@@ -87,14 +87,14 @@ dword_result_t XexLoadImage(lpstring_t module_name, dword_t module_flags,
X_STATUS result = X_STATUS_NO_SUCH_FILE;
uint32_t hmodule = 0;
auto module = kernel_state()->GetModule(module_name);
auto module = kernel_state()->GetModule(module_name.value());
if (module) {
// Existing module found.
hmodule = module->hmodule_ptr();
result = X_STATUS_SUCCESS;
} else {
// Not found; attempt to load as a user module.
auto user_module = kernel_state()->LoadUserModule(module_name);
auto user_module = kernel_state()->LoadUserModule(module_name.value());
if (user_module) {
// Give up object ownership, this reference will be released by the last
// XexUnloadImage call

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -141,20 +141,18 @@ dword_result_t ObDereferenceObject(dword_t native_ptr) {
}
DECLARE_XBOXKRNL_EXPORT1(ObDereferenceObject, kNone, kImplemented);
dword_result_t ObCreateSymbolicLink(pointer_t<X_ANSI_STRING> path,
pointer_t<X_ANSI_STRING> target) {
auto path_str = util::TranslateAnsiString(kernel_memory(), path);
auto target_str = util::TranslateAnsiString(kernel_memory(), target);
path_str = filesystem::CanonicalizePath(path_str);
target_str = filesystem::CanonicalizePath(target_str);
dword_result_t ObCreateSymbolicLink(pointer_t<X_ANSI_STRING> path_ptr,
pointer_t<X_ANSI_STRING> target_ptr) {
auto path = util::TranslateAnsiString(kernel_memory(), path_ptr);
auto target = util::TranslateAnsiString(kernel_memory(), target_ptr);
path = xe::utf8::canonicalize_guest_path(path);
target = xe::utf8::canonicalize_guest_path(target);
auto pos = path_str.find("\\??\\");
if (pos != path_str.npos && pos == 0) {
path_str = path_str.substr(4); // Strip the full qualifier
if (xe::utf8::starts_with(path, u8"\\??\\")) {
path = path.substr(4); // Strip the full qualifier
}
if (!kernel_state()->file_system()->RegisterSymbolicLink(path_str,
target_str)) {
if (!kernel_state()->file_system()->RegisterSymbolicLink(path, target)) {
return X_STATUS_UNSUCCESSFUL;
}
@@ -162,9 +160,9 @@ dword_result_t ObCreateSymbolicLink(pointer_t<X_ANSI_STRING> path,
}
DECLARE_XBOXKRNL_EXPORT1(ObCreateSymbolicLink, kNone, kImplemented);
dword_result_t ObDeleteSymbolicLink(pointer_t<X_ANSI_STRING> path) {
auto path_str = util::TranslateAnsiString(kernel_memory(), path);
if (!kernel_state()->file_system()->UnregisterSymbolicLink(path_str)) {
dword_result_t ObDeleteSymbolicLink(pointer_t<X_ANSI_STRING> path_ptr) {
auto path = util::TranslateAnsiString(kernel_memory(), path_ptr);
if (!kernel_state()->file_system()->UnregisterSymbolicLink(path)) {
return X_STATUS_UNSUCCESSFUL;
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -165,7 +165,7 @@ DECLARE_XBOXKRNL_EXPORT1(RtlFreeAnsiString, kNone, kImplemented);
// https://msdn.microsoft.com/en-us/library/ff561934
void RtlInitUnicodeString(pointer_t<X_UNICODE_STRING> destination,
lpwstring_t source) {
lpu16string_t source) {
if (source) {
destination->length = (uint16_t)source.value().size() * 2;
destination->maximum_length = (uint16_t)(source.value().size() + 1) * 2;
@@ -229,9 +229,9 @@ dword_result_t RtlUnicodeStringToAnsiString(
// _In_ PCUNICODE_STRING SourceString,
// _In_ BOOLEAN AllocateDestinationString
std::wstring unicode_str =
std::u16string unicode_str =
util::TranslateUnicodeString(kernel_memory(), source_ptr);
std::string ansi_str = xe::to_string(unicode_str);
std::string ansi_str = xe::to_utf8(unicode_str);
if (ansi_str.size() > 0xFFFF - 1) {
return X_STATUS_INVALID_PARAMETER_2;
}

View File

@@ -117,8 +117,8 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
const bool wide) {
int32_t count = 0;
char work[512];
wchar_t wwork[4];
char work8[512];
char16_t work16[4];
struct {
const void* buffer;
@@ -339,13 +339,13 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
auto value = args.get32();
if (!is_wide) {
work[0] = (uint8_t)value;
text.buffer = &work[0];
work8[0] = (uint8_t)value;
text.buffer = &work8[0];
text.length = 1;
text.is_wide = false;
} else {
wwork[0] = (uint16_t)value;
text.buffer = &wwork[0];
work16[0] = (uint16_t)value;
text.buffer = &work16[0];
text.length = 1;
text.is_wide = true;
text.swap_wide = false;
@@ -378,7 +378,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
}
if (precision >= 0) {
precision = std::min(precision, (int32_t)xe::countof(work));
precision = std::min(precision, (int32_t)xe::countof(work8));
} else {
precision = 1;
}
@@ -396,7 +396,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
prefix.length = 0;
}
char* end = &work[xe::countof(work) - 1];
char* end = &work8[xe::countof(work8) - 1];
char* start = end;
start[0] = '\0';
@@ -471,9 +471,9 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
auto s = format_double(value, precision, c, flags);
auto length = (int32_t)s.size();
assert_true(length < xe::countof(work));
assert_true(length < xe::countof(work8));
auto start = &work[0];
auto start = &work8[0];
auto end = &start[length];
std::memcpy(start, s.c_str(), length);
@@ -637,7 +637,7 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
}
}
} else {
// it's a const wchar_t*
// it's a const char16_t*
auto b = (const uint16_t*)text.buffer;
if (text.swap_wide) {
while (remaining-- > 0) {
@@ -768,15 +768,15 @@ class WideStringFormatData : public FormatData {
}
bool put(uint16_t c) {
output_ << (wchar_t)c;
output_ << (char16_t)c;
return true;
}
std::wstring wstr() const { return output_.str(); }
std::u16string wstr() const { return output_.str(); }
private:
const uint16_t* input_;
std::wostringstream output_;
std::basic_stringstream<char16_t> output_;
};
class WideCountFormatData : public FormatData {

View File

@@ -294,7 +294,7 @@ struct BufferScaling {
};
void AppendParam(StringBuffer* string_buffer, pointer_t<BufferScaling> param) {
string_buffer->AppendFormat(
"%.8X(scale %dx%d -> %dx%d))", param.guest_address(),
"{:08X}(scale {}x{} -> {}x{}))", param.guest_address(),
uint16_t(param->bb_width), uint16_t(param->bb_height),
uint16_t(param->fb_width), uint16_t(param->fb_height));
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -37,15 +37,15 @@ XFile::~XFile() {
}
X_STATUS XFile::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info,
size_t length, const char* file_name,
size_t length, const std::string_view file_name,
bool restart) {
assert_not_null(out_info);
vfs::Entry* entry = nullptr;
if (file_name != nullptr) {
if (!file_name.empty()) {
// Only queries in the current directory are supported for now.
assert_true(std::strchr(file_name, '\\') == nullptr);
assert_true(utf8::find_any_of(file_name, "\\") == std::string_view::npos);
find_engine_.SetRule(file_name);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -96,7 +96,7 @@ class XFile : public XObject {
void set_position(uint64_t value) { position_ = value; }
X_STATUS QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info, size_t length,
const char* file_name, bool restart);
const std::string_view file_name, bool restart);
// Don't do within the global critical region because invalidation callbacks
// may be triggered (as per the usual rule of not doing I/O within the global

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -39,24 +39,19 @@ XModule::~XModule() {
memory()->SystemHeapFree(hmodule_ptr_);
}
bool XModule::Matches(const std::string& name) const {
if (strcasecmp(xe::find_name_from_path(path_).c_str(), name.c_str()) == 0) {
return true;
}
if (strcasecmp(name_.c_str(), name.c_str()) == 0) {
return true;
}
if (strcasecmp(path_.c_str(), name.c_str()) == 0) {
return true;
}
return false;
}
bool XModule::Matches(const std::string_view name) const {
return xe::utf8::equal_case(xe::utf8::find_name_from_guest_path(path()),
name) ||
xe::utf8::equal_case(this->name(), name) ||
xe::utf8::equal_case(path(), name);
} // namespace kernel
void XModule::OnLoad() { kernel_state_->RegisterModule(this); }
void XModule::OnUnload() { kernel_state_->UnregisterModule(this); }
X_STATUS XModule::GetSection(const char* name, uint32_t* out_section_data,
X_STATUS XModule::GetSection(const std::string_view name,
uint32_t* out_section_data,
uint32_t* out_section_size) {
return X_STATUS_UNSUCCESSFUL;
}
@@ -73,31 +68,12 @@ uint32_t XModule::GetHandleFromHModule(void* hmodule) {
return ldr_data->checksum;
}
std::string XModule::NameFromPath(std::string path) {
std::string name;
auto last_slash = path.find_last_of('/');
if (last_slash == path.npos) {
last_slash = path.find_last_of('\\');
}
if (last_slash == path.npos) {
name = path;
} else {
name = path.substr(last_slash + 1);
}
auto dot = name.find_last_of('.');
if (dot != name.npos) {
name = name.substr(0, dot);
}
return name;
}
bool XModule::Save(ByteStream* stream) {
XELOGD("XModule %.8X (%s)", handle(), path_.c_str());
XELOGD("XModule %.8X (%s)", handle(), path().c_str());
stream->Write('XMOD');
stream->Write(path_);
stream->Write(path());
stream->Write(hmodule_ptr_);
if (!SaveObject(stream)) {
@@ -123,7 +99,7 @@ object_ref<XModule> XModule::Restore(KernelState* kernel_state,
return nullptr;
}
XELOGD("XModule %.8X (%s)", module->handle(), module->path_.c_str());
XELOGD("XModule %.8X (%s)", module->handle(), module->path().c_str());
module->hmodule_ptr_ = hmodule_ptr;
return module;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -63,16 +63,17 @@ class XModule : public XObject {
virtual ~XModule();
ModuleType module_type() const { return module_type_; }
const std::string& path() const { return path_; }
const std::string& name() const { return name_; }
bool Matches(const std::string& name) const;
virtual const std::string& path() const = 0;
virtual const std::string& name() const = 0;
bool Matches(const std::string_view name) const;
xe::cpu::Module* processor_module() const { return processor_module_; }
uint32_t hmodule_ptr() const { return hmodule_ptr_; }
virtual uint32_t GetProcAddressByOrdinal(uint16_t ordinal) = 0;
virtual uint32_t GetProcAddressByName(const char* name) = 0;
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
virtual uint32_t GetProcAddressByName(const std::string_view name) = 0;
virtual X_STATUS GetSection(const std::string_view name,
uint32_t* out_section_data,
uint32_t* out_section_size);
static object_ref<XModule> GetFromHModule(KernelState* kernel_state,
@@ -86,11 +87,8 @@ class XModule : public XObject {
protected:
void OnLoad();
void OnUnload();
static std::string NameFromPath(std::string path);
ModuleType module_type_;
std::string name_;
std::string path_;
xe::cpu::Module* processor_module_;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -22,8 +22,8 @@ XSymbolicLink::XSymbolicLink() : XObject(kType), path_(), target_() {}
XSymbolicLink::~XSymbolicLink() {}
void XSymbolicLink::Initialize(const std::string& path,
const std::string& target) {
void XSymbolicLink::Initialize(const std::string_view path,
const std::string_view target) {
path_ = path;
target_ = target;
// TODO(gibbed): kernel_state_->RegisterSymbolicLink(this);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -28,14 +28,14 @@ class XSymbolicLink : public XObject {
explicit XSymbolicLink(KernelState* kernel_state);
~XSymbolicLink() override;
void Initialize(const std::string& path, const std::string& target);
void Initialize(const std::string_view path, const std::string_view target);
bool Save(ByteStream* stream) override;
static object_ref<XSymbolicLink> Restore(KernelState* kernel_state,
ByteStream* stream);
const std ::string& path() const { return path_; }
const std ::string& target() const { return target_; }
const std::string& path() const { return path_; }
const std::string& target() const { return target_; }
private:
XSymbolicLink();

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2019 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -15,6 +15,7 @@
#include <objbase.h>
#endif
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
@@ -145,8 +146,8 @@ void XThread::set_last_error(uint32_t error_code) {
guest_object<X_KTHREAD>()->last_error = error_code;
}
void XThread::set_name(const std::string& name) {
thread_name_ = xe::format_string("%s (%.8X)", name.c_str(), handle());
void XThread::set_name(const std::string_view name) {
thread_name_ = fmt::format("{} ({:08X})", name, handle());
if (thread_) {
// May be getting set before the thread is created.
@@ -420,10 +421,7 @@ X_STATUS XThread::Create() {
// Set the thread name based on host ID (for easier debugging).
if (thread_name_.empty()) {
char thread_name[32];
snprintf(thread_name, xe::countof(thread_name), "XThread%.04X",
thread_->system_id());
set_name(thread_name);
set_name(fmt::format("XThread{:04X}", thread_->system_id()));
}
if (creation_params_.creation_flags & 0x60) {

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -142,7 +142,7 @@ class XThread : public XObject, public cpu::Thread {
uint32_t thread_id() const { return thread_id_; }
uint32_t last_error();
void set_last_error(uint32_t error_code);
void set_name(const std::string& name);
void set_name(const std::string_view name);
X_STATUS Create();
X_STATUS Exit(int exit_code);