From 5bf0b3444572826441a2b955c10a4830163bd712 Mon Sep 17 00:00:00 2001 From: gibbed Date: Mon, 2 Mar 2020 09:37:11 -0600 Subject: [PATCH] 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. --- premake5.lua | 11 +- src/xenia/app/discord/discord_presence.cc | 7 +- src/xenia/app/discord/discord_presence.h | 4 +- src/xenia/app/emulator_window.cc | 146 +- src/xenia/app/emulator_window.h | 6 +- src/xenia/app/premake5.lua | 1 + src/xenia/app/xenia_main.cc | 62 +- src/xenia/apu/xaudio2/xaudio2_audio_driver.cc | 6 +- src/xenia/apu/xma_decoder.cc | 2 +- src/xenia/base/byte_order.h | 6 +- src/xenia/base/byte_stream.cc | 6 +- src/xenia/base/byte_stream.h | 12 +- src/xenia/base/clock_x64.cc | 12 +- src/xenia/base/cvar.cc | 138 +- src/xenia/base/cvar.h | 55 +- src/xenia/base/filesystem.cc | 96 +- src/xenia/base/filesystem.h | 52 +- src/xenia/base/filesystem_posix.cc | 100 +- src/xenia/base/filesystem_wildcard.cc | 58 +- src/xenia/base/filesystem_wildcard.h | 20 +- src/xenia/base/filesystem_win.cc | 95 +- src/xenia/base/fuzzy.cc | 55 + src/xenia/base/fuzzy.h | 41 + src/xenia/base/logging.cc | 74 +- src/xenia/base/logging.h | 16 +- src/xenia/base/main.h | 6 +- src/xenia/base/main_posix.cc | 7 +- src/xenia/base/main_win.cc | 75 +- src/xenia/base/mapped_memory.h | 22 +- src/xenia/base/mapped_memory_posix.cc | 15 +- src/xenia/base/mapped_memory_win.cc | 26 +- src/xenia/base/memory.h | 39 +- src/xenia/base/memory_posix.cc | 9 +- src/xenia/base/memory_win.cc | 7 +- src/xenia/base/platform.h | 8 +- src/xenia/base/platform_linux.h | 21 +- src/xenia/base/premake5.lua | 3 + src/xenia/base/socket.h | 4 +- src/xenia/base/string.cc | 352 +-- src/xenia/base/string.h | 93 +- src/xenia/base/string_buffer.cc | 19 +- src/xenia/base/string_buffer.h | 20 +- src/xenia/base/string_key.h | 103 + src/xenia/base/string_util.cc | 69 - src/xenia/base/string_util.h | 440 +-- src/xenia/base/{platform_win.cc => system.h} | 17 +- .../{platform_linux.cc => system_linux.cc} | 14 +- src/xenia/base/system_win.cc | 27 + src/xenia/base/utf8.cc | 651 +++++ src/xenia/base/utf8.h | 137 + src/xenia/base/vec128.cc | 8 +- src/xenia/config.cc | 84 +- src/xenia/config.h | 16 +- src/xenia/cpu/backend/code_cache.h | 4 +- src/xenia/cpu/backend/x64/premake5.lua | 1 + src/xenia/cpu/backend/x64/x64_assembler.cc | 6 +- src/xenia/cpu/backend/x64/x64_code_cache.cc | 7 +- src/xenia/cpu/backend/x64/x64_code_cache.h | 6 +- src/xenia/cpu/backend/x64/x64_emitter.cc | 8 +- .../cpu/compiler/passes/finalization_pass.cc | 11 +- src/xenia/cpu/elf_module.cc | 4 +- src/xenia/cpu/elf_module.h | 4 +- src/xenia/cpu/export_resolver.cc | 27 +- src/xenia/cpu/export_resolver.h | 20 +- src/xenia/cpu/hir/hir_builder.cc | 79 +- src/xenia/cpu/hir/hir_builder.h | 18 +- src/xenia/cpu/ppc/ppc_context.cc | 31 +- src/xenia/cpu/ppc/ppc_context.h | 4 +- src/xenia/cpu/ppc/ppc_hir_builder.cc | 15 +- src/xenia/cpu/ppc/ppc_opcode_disasm.cc | 8 +- src/xenia/cpu/ppc/ppc_opcode_disasm_gen.cc | 2548 ++++++++--------- src/xenia/cpu/ppc/ppc_opcode_info.cc | 2 +- src/xenia/cpu/ppc/ppc_translator.cc | 12 +- src/xenia/cpu/ppc/testing/ppc_testing_main.cc | 183 +- .../ppc/testing/ppc_testing_native_main.cc | 4 +- src/xenia/cpu/ppc/testing/premake5.lua | 6 +- src/xenia/cpu/processor.cc | 12 +- src/xenia/cpu/processor.h | 9 +- src/xenia/cpu/raw_module.cc | 15 +- src/xenia/cpu/raw_module.h | 6 +- src/xenia/cpu/symbol.h | 4 +- src/xenia/cpu/test_module.cc | 4 +- src/xenia/cpu/test_module.h | 4 +- src/xenia/cpu/testing/premake5.lua | 1 + src/xenia/cpu/xex_module.cc | 85 +- src/xenia/cpu/xex_module.h | 8 +- src/xenia/debug/ui/debug_window.cc | 23 +- src/xenia/emulator.cc | 63 +- src/xenia/emulator.h | 42 +- src/xenia/gpu/command_processor.cc | 22 +- src/xenia/gpu/command_processor.h | 15 +- .../gpu/d3d12/d3d12_command_processor.cc | 16 +- src/xenia/gpu/d3d12/d3d12_command_processor.h | 8 +- src/xenia/gpu/d3d12/d3d12_graphics_system.cc | 6 +- src/xenia/gpu/d3d12/d3d12_graphics_system.h | 4 +- src/xenia/gpu/d3d12/d3d12_trace_dump_main.cc | 6 +- .../gpu/d3d12/d3d12_trace_viewer_main.cc | 6 +- src/xenia/gpu/d3d12/pipeline_cache.cc | 40 +- src/xenia/gpu/d3d12/pipeline_cache.h | 4 +- src/xenia/gpu/d3d12/premake5.lua | 3 + src/xenia/gpu/dxbc_shader_translator.cc | 2 +- src/xenia/gpu/dxbc_shader_translator_fetch.cc | 12 +- src/xenia/gpu/gpu_flags.cc | 8 +- src/xenia/gpu/gpu_flags.h | 6 +- src/xenia/gpu/graphics_system.cc | 12 +- src/xenia/gpu/graphics_system.h | 6 +- src/xenia/gpu/null/null_graphics_system.h | 4 +- src/xenia/gpu/premake5.lua | 2 + src/xenia/gpu/shader.cc | 37 +- src/xenia/gpu/shader.h | 7 +- src/xenia/gpu/shader_compiler_main.cc | 29 +- src/xenia/gpu/shader_translator.cc | 4 +- src/xenia/gpu/shader_translator_disasm.cc | 78 +- src/xenia/gpu/spirv_shader_translator.cc | 9 +- src/xenia/gpu/trace_dump.cc | 60 +- src/xenia/gpu/trace_dump.h | 10 +- src/xenia/gpu/trace_protocol.h | 4 +- src/xenia/gpu/trace_reader.cc | 8 +- src/xenia/gpu/trace_reader.h | 4 +- src/xenia/gpu/trace_viewer.cc | 33 +- src/xenia/gpu/trace_viewer.h | 8 +- src/xenia/gpu/trace_writer.cc | 10 +- src/xenia/gpu/trace_writer.h | 4 +- src/xenia/gpu/vk/vulkan_graphics_system.cc | 4 +- src/xenia/gpu/vk/vulkan_graphics_system.h | 4 +- src/xenia/gpu/vulkan/premake5.lua | 3 + src/xenia/gpu/vulkan/render_cache.cc | 12 +- src/xenia/gpu/vulkan/texture_cache.cc | 13 +- .../gpu/vulkan/vulkan_command_processor.cc | 5 +- .../gpu/vulkan/vulkan_command_processor.h | 4 +- src/xenia/gpu/vulkan/vulkan_graphics_system.h | 4 +- src/xenia/gpu/vulkan/vulkan_shader.cc | 5 +- .../gpu/vulkan/vulkan_trace_dump_main.cc | 6 +- .../gpu/vulkan/vulkan_trace_viewer_main.cc | 6 +- src/xenia/hid/hid_demo.cc | 4 +- src/xenia/hid/premake5.lua | 1 + src/xenia/hid/sdl/sdl_input_driver.cc | 31 +- src/xenia/kernel/kernel_module.cc | 11 +- src/xenia/kernel/kernel_module.h | 12 +- src/xenia/kernel/kernel_state.cc | 35 +- src/xenia/kernel/kernel_state.h | 13 +- src/xenia/kernel/premake5.lua | 1 + src/xenia/kernel/user_module.cc | 164 +- src/xenia/kernel/user_module.h | 17 +- src/xenia/kernel/util/gameinfo_utils.h | 8 +- src/xenia/kernel/util/object_table.cc | 30 +- src/xenia/kernel/util/object_table.h | 11 +- src/xenia/kernel/util/shim_utils.h | 73 +- src/xenia/kernel/xam/apps/xmp_app.cc | 41 +- src/xenia/kernel/xam/apps/xmp_app.h | 20 +- src/xenia/kernel/xam/content_manager.cc | 90 +- src/xenia/kernel/xam/content_manager.h | 39 +- src/xenia/kernel/xam/user_profile.cc | 18 +- src/xenia/kernel/xam/user_profile.h | 6 +- src/xenia/kernel/xam/xam_content.cc | 16 +- src/xenia/kernel/xam/xam_info.cc | 161 +- src/xenia/kernel/xam/xam_locale.cc | 184 +- src/xenia/kernel/xam/xam_ui.cc | 71 +- src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc | 17 +- src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc | 18 +- src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc | 10 +- src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc | 28 +- src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc | 8 +- src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc | 28 +- src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc | 2 +- src/xenia/kernel/xfile.cc | 8 +- src/xenia/kernel/xfile.h | 4 +- src/xenia/kernel/xmodule.cc | 48 +- src/xenia/kernel/xmodule.h | 16 +- src/xenia/kernel/xsymboliclink.cc | 6 +- src/xenia/kernel/xsymboliclink.h | 8 +- src/xenia/kernel/xthread.cc | 12 +- src/xenia/kernel/xthread.h | 4 +- src/xenia/memory.cc | 7 +- src/xenia/memory.h | 6 +- src/xenia/premake5.lua | 1 + src/xenia/ui/d3d12/d3d12_provider.cc | 10 +- src/xenia/ui/file_picker.h | 25 +- src/xenia/ui/file_picker_gtk.cc | 17 +- src/xenia/ui/file_picker_win.cc | 28 +- src/xenia/ui/imgui_drawer.cc | 4 +- src/xenia/ui/loop_gtk.cc | 5 +- src/xenia/ui/menu_item.cc | 17 +- src/xenia/ui/menu_item.h | 20 +- src/xenia/ui/spirv/spirv_assembler.h | 6 +- src/xenia/ui/ui_event.h | 12 +- src/xenia/ui/vulkan/premake5.lua | 2 + src/xenia/ui/vulkan/vulkan_context.cc | 4 +- src/xenia/ui/vulkan/vulkan_instance.cc | 4 +- src/xenia/ui/vulkan/vulkan_util.cc | 7 +- src/xenia/ui/vulkan/vulkan_window_demo.cc | 7 +- src/xenia/ui/window.cc | 4 +- src/xenia/ui/window.h | 12 +- src/xenia/ui/window_demo.cc | 16 +- src/xenia/ui/window_gtk.cc | 23 +- src/xenia/ui/window_gtk.h | 11 +- src/xenia/ui/window_win.cc | 78 +- src/xenia/ui/window_win.h | 9 +- src/xenia/vfs/device.cc | 4 +- src/xenia/vfs/device.h | 6 +- src/xenia/vfs/devices/disc_image_device.cc | 22 +- src/xenia/vfs/devices/disc_image_device.h | 10 +- src/xenia/vfs/devices/disc_image_entry.cc | 16 +- src/xenia/vfs/devices/disc_image_entry.h | 6 +- src/xenia/vfs/devices/host_path_device.cc | 24 +- src/xenia/vfs/devices/host_path_device.h | 10 +- src/xenia/vfs/devices/host_path_entry.cc | 28 +- src/xenia/vfs/devices/host_path_entry.h | 14 +- .../vfs/devices/stfs_container_device.cc | 72 +- src/xenia/vfs/devices/stfs_container_device.h | 24 +- src/xenia/vfs/devices/stfs_container_entry.cc | 9 +- src/xenia/vfs/devices/stfs_container_entry.h | 6 +- src/xenia/vfs/entry.cc | 25 +- src/xenia/vfs/entry.h | 12 +- src/xenia/vfs/premake5.lua | 1 + src/xenia/vfs/vfs_dump.cc | 26 +- src/xenia/vfs/virtual_file_system.cc | 61 +- src/xenia/vfs/virtual_file_system.h | 21 +- third_party/mspack/logging.cc | 2 + tools/ppc-table-gen | 20 +- 220 files changed, 4944 insertions(+), 4294 deletions(-) create mode 100644 src/xenia/base/fuzzy.cc create mode 100644 src/xenia/base/fuzzy.h create mode 100644 src/xenia/base/string_key.h delete mode 100644 src/xenia/base/string_util.cc rename src/xenia/base/{platform_win.cc => system.h} (57%) rename src/xenia/base/{platform_linux.cc => system_linux.cc} (67%) create mode 100644 src/xenia/base/system_win.cc create mode 100644 src/xenia/base/utf8.cc create mode 100644 src/xenia/base/utf8.h diff --git a/premake5.lua b/premake5.lua index 28fdba89e..be8ffdf80 100644 --- a/premake5.lua +++ b/premake5.lua @@ -91,15 +91,17 @@ filter({"configurations:Release", "platforms:Windows"}) filter("platforms:Linux") system("linux") toolset("clang") + cppdialect("C++17") buildoptions({ -- "-mlzcnt", -- (don't) Assume lzcnt is supported. "`pkg-config --cflags gtk+-x11-3.0`", "-fno-lto", -- Premake doesn't support LTO on clang }) links({ - "pthread", + "stdc++fs", "dl", "lz4", + "pthread", "rt", }) linkoptions({ @@ -110,9 +112,7 @@ filter({"platforms:Linux", "kind:*App"}) linkgroups("On") filter({"platforms:Linux", "language:C++", "toolset:gcc"}) - buildoptions({ - "-std=c++14", - }) + cppdialect("C++17") links({ }) disablewarnings({ @@ -141,13 +141,13 @@ filter({"platforms:Linux", "language:C++", "toolset:clang"}) }) filter({"platforms:Linux", "language:C++", "toolset:clang", "files:*.cc or *.cpp"}) buildoptions({ - "-std=c++14", "-stdlib=libstdc++", }) filter("platforms:Windows") system("windows") toolset("msc") + cppdialect("C++17") buildoptions({ "/MP", -- Multiprocessor compilation. "/wd4100", -- Unreferenced parameters are ok. @@ -214,6 +214,7 @@ solution("xenia") include("third_party/discord-rpc.lua") include("third_party/cxxopts.lua") include("third_party/cpptoml.lua") + include("third_party/fmt.lua") include("third_party/glslang-spirv.lua") include("third_party/imgui.lua") include("third_party/libav.lua") diff --git a/src/xenia/app/discord/discord_presence.cc b/src/xenia/app/discord/discord_presence.cc index 50acd272f..c51e27851 100644 --- a/src/xenia/app/discord/discord_presence.cc +++ b/src/xenia/app/discord/discord_presence.cc @@ -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. * ****************************************************************************** */ @@ -39,11 +39,10 @@ void DiscordPresence::NotPlaying() { Discord_UpdatePresence(&discordPresence); } -void DiscordPresence::PlayingTitle(const std::wstring& game_title) { - auto discord_game_title = xe::to_string(game_title); +void DiscordPresence::PlayingTitle(const std::string_view game_title) { DiscordRichPresence discordPresence = {}; discordPresence.state = "In Game"; - discordPresence.details = discord_game_title.c_str(); + discordPresence.details = std::string(game_title).c_str(); // TODO(gibbed): we don't have state icons yet. // discordPresence.smallImageKey = "app"; // discordPresence.largeImageKey = "state_ingame"; diff --git a/src/xenia/app/discord/discord_presence.h b/src/xenia/app/discord/discord_presence.h index d63ce70c1..141385a7b 100644 --- a/src/xenia/app/discord/discord_presence.h +++ b/src/xenia/app/discord/discord_presence.h @@ -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. * ****************************************************************************** */ @@ -19,7 +19,7 @@ class DiscordPresence { public: static void Initialize(); static void NotPlaying(); - static void PlayingTitle(const std::wstring& game_title); + static void PlayingTitle(const std::string_view game_title); static void Shutdown(); }; diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index ae00cdfaf..e06b2830e 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -9,9 +9,7 @@ #include "xenia/app/emulator_window.h" -// Autogenerated by `xb premake`. -#include "build/version.h" - +#include "third_party/fmt/include/fmt/format.h" #include "third_party/imgui/imgui.h" #include "xenia/base/clock.h" #include "xenia/base/cvar.h" @@ -19,14 +17,17 @@ #include "xenia/base/logging.h" #include "xenia/base/platform.h" #include "xenia/base/profiling.h" +#include "xenia/base/system.h" #include "xenia/base/threading.h" #include "xenia/emulator.h" #include "xenia/gpu/graphics_system.h" - #include "xenia/ui/file_picker.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +// Autogenerated by `xb premake`. +#include "build/version.h" + DECLARE_bool(debug); namespace xe { @@ -38,7 +39,7 @@ using xe::ui::MenuItem; using xe::ui::MouseEvent; using xe::ui::UIEvent; -const std::wstring kBaseTitle = L"xenia"; +const std::string kBaseTitle = "xenia"; EmulatorWindow::EmulatorWindow(Emulator* emulator) : emulator_(emulator), @@ -47,14 +48,13 @@ EmulatorWindow::EmulatorWindow(Emulator* emulator) base_title_ = kBaseTitle + #ifdef DEBUG #if _NO_DEBUG_HEAP == 1 - L" DEBUG" + + " DEBUG" #else - L" CHECKED" + + " CHECKED" #endif #endif - L" (" + xe::to_wstring(XE_BUILD_BRANCH) + L"/" + - xe::to_wstring(XE_BUILD_COMMIT_SHORT) + L"/" + - xe::to_wstring(XE_BUILD_DATE) + L")"; + " (" XE_BUILD_BRANCH "/" XE_BUILD_COMMIT_SHORT "/" XE_BUILD_DATE + ")"; } EmulatorWindow::~EmulatorWindow() { @@ -123,13 +123,13 @@ bool EmulatorWindow::Initialize() { // Save to file // TODO: Choose path based on user input, or from options // TODO: Spawn a new thread to do this. - emulator()->SaveToFile(L"test.sav"); + emulator()->SaveToFile("test.sav"); } break; case 0x77: { // VK_F8 // Restore from file // TODO: Choose path from user // TODO: Spawn a new thread to do this. - emulator()->RestoreFromFile(L"test.sav"); + emulator()->RestoreFromFile("test.sav"); } break; case 0x7A: { // VK_F11 ToggleFullscreen(); @@ -182,105 +182,102 @@ bool EmulatorWindow::Initialize() { // Main menu. // FIXME: This code is really messy. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); - auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File"); + auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { file_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, L"&Open...", L"Ctrl+O", + MenuItem::Create(MenuItem::Type::kString, "&Open...", "Ctrl+O", std::bind(&EmulatorWindow::FileOpen, this))); file_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, L"Close", + MenuItem::Create(MenuItem::Type::kString, "Close", std::bind(&EmulatorWindow::FileClose, this))); file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); file_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"Show content directory...", + MenuItem::Type::kString, "Show content directory...", std::bind(&EmulatorWindow::ShowContentDirectory, this))); file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"E&xit", - L"Alt+F4", + file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "E&xit", + "Alt+F4", [this]() { window_->Close(); })); } main_menu->AddChild(std::move(file_menu)); // CPU menu. - auto cpu_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&CPU"); + auto cpu_menu = MenuItem::Create(MenuItem::Type::kPopup, "&CPU"); { cpu_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"&Reset Time Scalar", L"Numpad *", + MenuItem::Type::kString, "&Reset Time Scalar", "Numpad *", std::bind(&EmulatorWindow::CpuTimeScalarReset, this))); cpu_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"Time Scalar /= 2", L"Numpad -", + MenuItem::Type::kString, "Time Scalar /= 2", "Numpad -", std::bind(&EmulatorWindow::CpuTimeScalarSetHalf, this))); cpu_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"Time Scalar *= 2", L"Numpad +", + MenuItem::Type::kString, "Time Scalar *= 2", "Numpad +", std::bind(&EmulatorWindow::CpuTimeScalarSetDouble, this))); } cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); { cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, - L"Toggle Profiler &Display", L"F3", + "Toggle Profiler &Display", "F3", []() { Profiler::ToggleDisplay(); })); cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, - L"&Pause/Resume Profiler", L"`", + "&Pause/Resume Profiler", "`", []() { Profiler::TogglePause(); })); } cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); { cpu_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"&Break and Show Guest Debugger", - L"Pause/Break", - std::bind(&EmulatorWindow::CpuBreakIntoDebugger, this))); + MenuItem::Type::kString, "&Break and Show Guest Debugger", + "Pause/Break", std::bind(&EmulatorWindow::CpuBreakIntoDebugger, this))); cpu_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"&Break into Host Debugger", - L"Ctrl+Pause/Break", + MenuItem::Type::kString, "&Break into Host Debugger", + "Ctrl+Pause/Break", std::bind(&EmulatorWindow::CpuBreakIntoHostDebugger, this))); } main_menu->AddChild(std::move(cpu_menu)); // GPU menu. - auto gpu_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&GPU"); + auto gpu_menu = MenuItem::Create(MenuItem::Type::kPopup, "&GPU"); { gpu_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, L"&Trace Frame", L"F4", + MenuItem::Create(MenuItem::Type::kString, "&Trace Frame", "F4", std::bind(&EmulatorWindow::GpuTraceFrame, this))); } gpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); { - gpu_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"&Clear Runtime Caches", L"F5", - std::bind(&EmulatorWindow::GpuClearCaches, this))); + gpu_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "&Clear Runtime Caches", "F5", + std::bind(&EmulatorWindow::GpuClearCaches, this))); } main_menu->AddChild(std::move(gpu_menu)); // Window menu. - auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Window"); + auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Window"); { window_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, L"&Fullscreen", L"F11", + MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11", std::bind(&EmulatorWindow::ToggleFullscreen, this))); } main_menu->AddChild(std::move(window_menu)); // Help menu. - auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Help"); + auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Help"); { + help_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "Build commit on GitHub...", + "F2", std::bind(&EmulatorWindow::ShowCommitID, this))); help_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"Build commit on GitHub...", L"F2", - std::bind(&EmulatorWindow::ShowCommitID, this))); - help_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"Recent changes on GitHub...", [this]() { - std::wstring url = - std::wstring(L"https://github.com/xenia-project/xenia/compare/") + - xe::to_wstring(XE_BUILD_COMMIT) + L"..." + - xe::to_wstring(XE_BUILD_BRANCH); - LaunchBrowser(url.c_str()); + MenuItem::Type::kString, "Recent changes on GitHub...", [this]() { + LaunchWebBrowser( + "https://github.com/xenia-project/xenia/compare/" XE_BUILD_COMMIT + "..." XE_BUILD_BRANCH); })); help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); help_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, L"&Website...", L"F1", + MenuItem::Create(MenuItem::Type::kString, "&Website...", "F1", std::bind(&EmulatorWindow::ShowHelpWebsite, this))); help_menu->AddChild(MenuItem::Create( - MenuItem::Type::kString, L"&About...", - [this]() { LaunchBrowser(L"https://xenia.jp/about/"); })); + MenuItem::Type::kString, "&About...", + [this]() { LaunchWebBrowser("https://xenia.jp/about/"); })); } main_menu->AddChild(std::move(help_menu)); @@ -293,7 +290,7 @@ bool EmulatorWindow::Initialize() { return true; } -void EmulatorWindow::FileDrop(const wchar_t* filename) { +void EmulatorWindow::FileDrop(const std::filesystem::path& filename) { auto result = emulator_->LaunchPath(filename); if (XFAILED(result)) { // TODO: Display a message box. @@ -302,19 +299,19 @@ void EmulatorWindow::FileDrop(const wchar_t* filename) { } void EmulatorWindow::FileOpen() { - std::wstring path; + std::filesystem::path path; auto file_picker = xe::ui::FilePicker::Create(); file_picker->set_mode(ui::FilePicker::Mode::kOpen); file_picker->set_type(ui::FilePicker::Type::kFile); file_picker->set_multi_selection(false); - file_picker->set_title(L"Select Content Package"); + file_picker->set_title("Select Content Package"); file_picker->set_extensions({ - {L"Supported Files", L"*.iso;*.xex;*.xcp;*.*"}, - {L"Disc Image (*.iso)", L"*.iso"}, - {L"Xbox Executable (*.xex)", L"*.xex"}, - //{ L"Content Package (*.xcp)", L"*.xcp" }, - {L"All Files (*.*)", L"*.*"}, + {"Supported Files", "*.iso;*.xex;*.xcp;*.*"}, + {"Disc Image (*.iso)", "*.iso"}, + {"Xbox Executable (*.xex)", "*.xex"}, + //{"Content Package (*.xcp)", "*.xcp" }, + {"All Files (*.*)", "*.*"}, }); if (file_picker->Show(window_->native_handle())) { auto selected_files = file_picker->selected_files(); @@ -325,8 +322,7 @@ void EmulatorWindow::FileOpen() { if (!path.empty()) { // Normalize the path and make absolute. - std::wstring abs_path = xe::to_absolute_path(path); - + auto abs_path = std::filesystem::absolute(path); auto result = emulator_->LaunchPath(abs_path); if (XFAILED(result)) { // TODO: Display a message box. @@ -342,16 +338,16 @@ void EmulatorWindow::FileClose() { } void EmulatorWindow::ShowContentDirectory() { - std::wstring target_path; + std::filesystem::path target_path; auto content_root = emulator_->content_root(); if (!emulator_->is_title_open() || !emulator_->kernel_state()) { target_path = content_root; } else { // TODO(gibbed): expose this via ContentManager? - wchar_t title_id[9] = L"00000000"; - std::swprintf(title_id, 9, L"%.8X", emulator_->kernel_state()->title_id()); - auto package_root = xe::join_paths(content_root, title_id); + auto title_id = + fmt::format("{:08X}", emulator_->kernel_state()->title_id()); + auto package_root = content_root / title_id; target_path = package_root; } @@ -359,7 +355,7 @@ void EmulatorWindow::ShowContentDirectory() { xe::filesystem::CreateFolder(target_path); } - LaunchBrowser(target_path.c_str()); + LaunchFileExplorer(target_path); } void EmulatorWindow::CheckHideCursor() { @@ -426,36 +422,36 @@ void EmulatorWindow::ToggleFullscreen() { } } -void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser(L"https://xenia.jp"); } +void EmulatorWindow::ShowHelpWebsite() { LaunchWebBrowser("https://xenia.jp"); } void EmulatorWindow::ShowCommitID() { - std::wstring url = - std::wstring(L"https://github.com/xenia-project/xenia/commit/") + - xe::to_wstring(XE_BUILD_COMMIT) + L"/"; - LaunchBrowser(url.c_str()); + LaunchWebBrowser( + "https://github.com/xenia-project/xenia/commit/" XE_BUILD_COMMIT "/"); } void EmulatorWindow::UpdateTitle() { - std::wstring title(base_title_); + std::string title(base_title_); if (emulator()->is_title_open()) { auto game_title = emulator()->game_title(); - title += xe::format_string(L" | [%.8X] %s", emulator()->title_id(), - game_title.c_str()); + title += fmt::format(" | [{:08X}] {}", emulator()->title_id(), game_title); } auto graphics_system = emulator()->graphics_system(); if (graphics_system) { auto graphics_name = graphics_system->name(); - title += L" <" + graphics_name + L">"; + title += fmt::format(" <{}>", graphics_name); } if (Clock::guest_time_scalar() != 1.0) { - title += xe::format_string(L" (@%.2fx)", Clock::guest_time_scalar()); + title += fmt::format(" (@{:.2f}x)", Clock::guest_time_scalar()); } if (initializing_shader_storage_) { - title += L" (Preloading shaders\u2026)"; + title += + " (Preloading shaders" + u8"\u2026" + ")"; } window_->set_title(title); diff --git a/src/xenia/app/emulator_window.h b/src/xenia/app/emulator_window.h index 6d2c999b1..4d29d9a5b 100644 --- a/src/xenia/app/emulator_window.h +++ b/src/xenia/app/emulator_window.h @@ -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. * ****************************************************************************** */ @@ -44,7 +44,7 @@ class EmulatorWindow { bool Initialize(); - void FileDrop(const wchar_t* filename); + void FileDrop(const std::filesystem::path& filename); void FileOpen(); void FileClose(); void ShowContentDirectory(); @@ -62,7 +62,7 @@ class EmulatorWindow { Emulator* emulator_; std::unique_ptr loop_; std::unique_ptr window_; - std::wstring base_title_; + std::string base_title_; uint64_t cursor_hide_time_ = 0; bool initializing_shader_storage_ = false; }; diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index a385245ac..182779edf 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -10,6 +10,7 @@ project("xenia-app") links({ "aes_128", "capstone", + "fmt", "dxbc", "discord-rpc", "glslang-spirv", diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 6f4d85595..4c1d81e6e 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -44,6 +44,7 @@ #include "xenia/hid/xinput/xinput_hid.h" #endif // XE_PLATFORM_WIN32 +#include "third_party/fmt/include/fmt/format.h" #include "third_party/xbyak/xbyak/xbyak_util.h" DEFINE_string(apu, "any", "Audio system. Use: [any, nop, sdl, xaudio2]", "APU"); @@ -54,13 +55,13 @@ DEFINE_string(hid, "any", "Input system. Use: [any, nop, sdl, winkey, xinput]", DEFINE_bool(fullscreen, false, "Toggles fullscreen", "GPU"); -DEFINE_string( +DEFINE_path( storage_root, "", "Root path for persistent internal data storage (config, etc.), or empty " "to use the path preferred for the OS, such as the documents folder, or " "the emulator executable directory if portable.txt is present in it.", "Storage"); -DEFINE_string( +DEFINE_path( content_root, "", "Root path for guest content storage (saves, etc.), or empty to use the " "content folder under the storage root.", @@ -69,9 +70,9 @@ DEFINE_string( DEFINE_bool(mount_scratch, false, "Enable scratch mount", "Storage"); DEFINE_bool(mount_cache, false, "Enable cache mount", "Storage"); -DEFINE_transient_string(target, "", - "Specifies the target .xex or .iso to execute.", - "General"); +DEFINE_transient_path(target, "", + "Specifies the target .xex or .iso to execute.", + "General"); DECLARE_bool(debug); DEFINE_bool(discord, true, "Enable Discord rich presence", "General"); @@ -91,25 +92,25 @@ class Factory { std::vector creators_; public: - void Add(const std::string& name, std::function is_available, + void Add(const std::string_view name, std::function is_available, std::function(Args...)> instantiate) { - creators_.push_back({name, is_available, instantiate}); + creators_.push_back({std::string(name), is_available, instantiate}); } - void Add(const std::string& name, + void Add(const std::string_view name, std::function(Args...)> instantiate) { auto always_available = []() { return true; }; Add(name, always_available, instantiate); } template - void Add(const std::string& name) { + void Add(const std::string_view name) { Add(name, DT::IsAvailable, [](Args... args) { return std::make_unique
(std::forward(args)...); }); } - std::unique_ptr Create(const std::string& name, Args... args) { + std::unique_ptr Create(const std::string_view name, Args... args) { if (!name.empty() && name != "any") { auto it = std::find_if( creators_.cbegin(), creators_.cend(), @@ -129,7 +130,7 @@ class Factory { } } - std::vector> CreateAll(const std::string& name, + std::vector> CreateAll(const std::string_view name, Args... args) { std::vector> instances; if (!name.empty() && name != "any") { @@ -206,35 +207,34 @@ std::vector> CreateInputDrivers( return drivers; } -int xenia_main(const std::vector& args) { +int xenia_main(const std::vector& args) { Profiler::Initialize(); Profiler::ThreadEnter("main"); // Figure out where internal files and content should go. - std::wstring storage_root = xe::to_wstring(cvars::storage_root); + std::filesystem::path storage_root = cvars::storage_root; if (storage_root.empty()) { storage_root = xe::filesystem::GetExecutableFolder(); - if (!xe::filesystem::PathExists( - xe::join_paths(storage_root, L"portable.txt"))) { + if (!xe::filesystem::PathExists(storage_root / "portable.txt")) { storage_root = xe::filesystem::GetUserFolder(); #if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_LINUX) - storage_root = xe::join_paths(storage_root, L"Xenia"); + storage_root = storage_root / "Xenia"; #else #warning Unhandled platform for the data root. - storage_root = xe::join_paths(storage_root, L"Xenia"); + storage_root = storage_root / "Xenia"; #endif } } - storage_root = xe::to_absolute_path(storage_root); + storage_root = std::filesystem::absolute(storage_root); XELOGI("Storage root: %S", storage_root.c_str()); config::SetupConfig(storage_root); - std::wstring content_root = xe::to_wstring(cvars::content_root); + std::filesystem::path content_root = cvars::content_root; if (content_root.empty()) { - content_root = xe::join_paths(storage_root, L"content"); + content_root = storage_root / "content"; } - content_root = xe::to_absolute_path(content_root); + content_root = std::filesystem::absolute(content_root); XELOGI("Content root: %S", content_root.c_str()); if (cvars::discord) { @@ -243,7 +243,7 @@ int xenia_main(const std::vector& args) { } // Create the emulator but don't initialize so we can setup the window. - auto emulator = std::make_unique(L"", storage_root, content_root); + auto emulator = std::make_unique("", storage_root, content_root); // Main emulator display window. auto emulator_window = EmulatorWindow::Create(emulator.get()); @@ -260,7 +260,7 @@ int xenia_main(const std::vector& args) { if (cvars::mount_scratch) { auto scratch_device = std::make_unique( - "\\SCRATCH", L"scratch", false); + "\\SCRATCH", "scratch", false); if (!scratch_device->Initialize()) { XELOGE("Unable to scan scratch path"); } else { @@ -274,7 +274,7 @@ int xenia_main(const std::vector& args) { if (cvars::mount_cache) { auto cache0_device = - std::make_unique("\\CACHE0", L"cache0", false); + std::make_unique("\\CACHE0", "cache0", false); if (!cache0_device->Initialize()) { XELOGE("Unable to scan cache0 path"); } else { @@ -286,7 +286,7 @@ int xenia_main(const std::vector& args) { } auto cache1_device = - std::make_unique("\\CACHE1", L"cache1", false); + std::make_unique("\\CACHE1", "cache1", false); if (!cache1_device->Initialize()) { XELOGE("Unable to scan cache1 path"); } else { @@ -325,7 +325,7 @@ int xenia_main(const std::vector& args) { emulator->on_launch.AddListener([&](auto title_id, const auto& game_title) { if (cvars::discord) { discord::DiscordPresence::PlayingTitle( - game_title.empty() ? L"Unknown Title" : game_title); + game_title.empty() ? "Unknown Title" : std::string(game_title)); } emulator_window->UpdateTitle(); evt->Set(); @@ -365,9 +365,9 @@ int xenia_main(const std::vector& args) { emulator_window->window()->EnableMainMenu(); // Grab path from the flag or unnamed argument. - std::wstring path; + std::filesystem::path path; if (!cvars::target.empty()) { - path = xe::to_wstring(cvars::target); + path = cvars::target; } // Toggles fullscreen @@ -375,10 +375,10 @@ int xenia_main(const std::vector& args) { if (!path.empty()) { // Normalize the path and make absolute. - std::wstring abs_path = xe::to_absolute_path(path); + auto abs_path = std::filesystem::absolute(path); result = emulator->LaunchPath(abs_path); if (XFAILED(result)) { - xe::FatalError("Failed to launch target: %.8X", result); + xe::FatalError(fmt::format("Failed to launch target: {:08X}", result)); emulator.reset(); emulator_window.reset(); return 1; @@ -416,5 +416,5 @@ int xenia_main(const std::vector& args) { } // namespace app } // namespace xe -DEFINE_ENTRY_POINT(L"xenia", xe::app::xenia_main, "[Path to .iso/.xex]", +DEFINE_ENTRY_POINT("xenia", xe::app::xenia_main, "[Path to .iso/.xex]", "target"); diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc index 1f5d2ffc8..4f385126c 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc +++ b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc @@ -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. * ****************************************************************************** */ @@ -58,11 +58,11 @@ bool XAudio2AudioDriver::Initialize() { // Windows 10 SDK references XAudio2_9.dll in it, which is only available in // Windows 10, and XAudio2_8.dll is linked through a different .lib - // xaudio2_8.lib, so easier not to link the .lib at all. - xaudio2_module_ = reinterpret_cast(LoadLibrary(L"XAudio2_8.dll")); + xaudio2_module_ = reinterpret_cast(LoadLibraryW(L"XAudio2_8.dll")); if (xaudio2_module_) { api_minor_version_ = 8; } else { - xaudio2_module_ = reinterpret_cast(LoadLibrary(L"XAudio2_7.dll")); + xaudio2_module_ = reinterpret_cast(LoadLibraryW(L"XAudio2_7.dll")); if (xaudio2_module_) { api_minor_version_ = 7; } else { diff --git a/src/xenia/apu/xma_decoder.cc b/src/xenia/apu/xma_decoder.cc index 52e0b61a6..85b6d5b5d 100644 --- a/src/xenia/apu/xma_decoder.cc +++ b/src/xenia/apu/xma_decoder.cc @@ -91,7 +91,7 @@ void av_log_callback(void* avcl, int level, const char* fmt, va_list va) { StringBuffer buff; buff.AppendVarargs(fmt, va); - xe::LogLineFormat(log_level, level_char, "libav: %s", buff.GetString()); + xe::LogLineFormat(log_level, level_char, "libav: %s", buff.buffer()); } X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) { diff --git a/src/xenia/base/byte_order.h b/src/xenia/base/byte_order.h index 90fbdc75d..6e2d87cea 100644 --- a/src/xenia/base/byte_order.h +++ b/src/xenia/base/byte_order.h @@ -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. * ****************************************************************************** */ @@ -40,8 +40,8 @@ inline int16_t byte_swap(int16_t value) { inline uint16_t byte_swap(uint16_t value) { return XENIA_BASE_BYTE_SWAP_16(value); } -inline uint16_t byte_swap(wchar_t value) { - return static_cast(XENIA_BASE_BYTE_SWAP_16(value)); +inline uint16_t byte_swap(char16_t value) { + return static_cast(XENIA_BASE_BYTE_SWAP_16(value)); } inline int32_t byte_swap(int32_t value) { return static_cast( diff --git a/src/xenia/base/byte_stream.cc b/src/xenia/base/byte_stream.cc index 652b5c0df..cdd69a1ba 100644 --- a/src/xenia/base/byte_stream.cc +++ b/src/xenia/base/byte_stream.cc @@ -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. * ****************************************************************************** */ @@ -47,8 +47,8 @@ std::string ByteStream::Read() { } template <> -std::wstring ByteStream::Read() { - std::wstring str; +std::u16string ByteStream::Read() { + std::u16string str; uint32_t len = Read(); str.resize(len); diff --git a/src/xenia/base/byte_stream.h b/src/xenia/base/byte_stream.h index d97568b28..c1574739d 100644 --- a/src/xenia/base/byte_stream.h +++ b/src/xenia/base/byte_stream.h @@ -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. * ****************************************************************************** */ @@ -51,14 +51,14 @@ class ByteStream { Write(reinterpret_cast(&data), sizeof(T)); } - void Write(const std::string& str) { + void Write(const std::string_view str) { Write(uint32_t(str.length())); - Write(str.c_str(), str.length()); + Write(str.data(), str.length() * sizeof(char)); } - void Write(const std::wstring& str) { + void Write(const std::u16string_view str) { Write(uint32_t(str.length())); - Write(str.c_str(), str.length() * 2); + Write(str.data(), str.length() * sizeof(char16_t)); } private: @@ -71,7 +71,7 @@ template <> std::string ByteStream::Read(); template <> -std::wstring ByteStream::Read(); +std::u16string ByteStream::Read(); } // namespace xe diff --git a/src/xenia/base/clock_x64.cc b/src/xenia/base/clock_x64.cc index 72a250b9d..3a573f489 100644 --- a/src/xenia/base/clock_x64.cc +++ b/src/xenia/base/clock_x64.cc @@ -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. * ****************************************************************************** */ @@ -36,12 +36,10 @@ #error "No cpu instruction wrappers for current compiler implemented." #endif -#define CLOCK_FATAL(msg) \ - xe::FatalError( \ - "The raw clock source is not supported on your CPU. \n" \ - "%s \n" \ - "Set the cvar 'clock_source_raw' to 'false'.", \ - (msg)); +#define CLOCK_FATAL(msg) \ + xe::FatalError("The raw clock source is not supported on your CPU.\n" msg \ + "\n" \ + "Set the cvar 'clock_source_raw' to 'false'."); namespace xe { // Getting the TSC frequency can be a bit tricky. This method here only works on diff --git a/src/xenia/base/cvar.cc b/src/xenia/base/cvar.cc index c882b265a..b8fec6a71 100644 --- a/src/xenia/base/cvar.cc +++ b/src/xenia/base/cvar.cc @@ -2,13 +2,22 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "cvar.h" +#include "utf8.h" + +#define UTF_CPP_CPLUSPLUS 201703L +#include "third_party/utfcpp/source/utf8.h" + +namespace utfcpp = utf8; + +using u8_citer = utfcpp::iterator; + namespace cvar { cxxopts::Options options("xenia", "Xbox 360 Emulator"); @@ -22,37 +31,45 @@ void PrintHelpAndExit() { exit(0); } -void ParseLaunchArguments(int argc, char** argv, - const std::string& positional_help, +void ParseLaunchArguments(int& argc, char**& argv, + const std::string_view positional_help, const std::vector& positional_options) { options.add_options()("help", "Prints help and exit."); - if (!CmdVars) CmdVars = new std::map(); - if (!ConfigVars) ConfigVars = new std::map(); + + if (!CmdVars) { + CmdVars = new std::map(); + } + + if (!ConfigVars) { + ConfigVars = new std::map(); + } + for (auto& it : *CmdVars) { auto cmdVar = it.second; cmdVar->AddToLaunchOptions(&options); } - std::vector vars; - for (const auto& s : *ConfigVars) vars.push_back(s.second); - for (auto& it : *ConfigVars) { + for (const auto& it : *ConfigVars) { auto configVar = it.second; configVar->AddToLaunchOptions(&options); } + try { - options.positional_help(positional_help); + options.positional_help(std::string(positional_help)); options.parse_positional(positional_options); auto result = options.parse(argc, argv); if (result.count("help")) { PrintHelpAndExit(); } + for (auto& it : *CmdVars) { auto cmdVar = static_cast(it.second); if (result.count(cmdVar->name())) { cmdVar->LoadFromLaunchOptions(&result); } } + for (auto& it : *ConfigVars) { auto configVar = static_cast(it.second); if (result.count(configVar->name())) { @@ -67,48 +84,46 @@ void ParseLaunchArguments(int argc, char** argv, namespace toml { -std::string EscapeBasicString(const std::string& str) { +std::string EscapeBasicString(const std::string_view view) { std::string result; - for (auto c : str) { + auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend()); + auto end = u8_citer(view.cend(), view.cbegin(), view.cend()); + for (auto it = begin; it != end; ++it) { + auto c = *it; if (c == '\b') { - result += "\\b"; + result += u8"\\b"; } else if (c == '\t') { - result += "\\t"; + result += u8"\\t"; } else if (c == '\n') { - result += "\\n"; + result += u8"\\n"; } else if (c == '\f') { - result += "\\f"; + result += u8"\\f"; } else if (c == '\r') { - result += "\\r"; + result += u8"\\r"; } else if (c == '"') { - result += "\\\""; + result += u8"\\\""; } else if (c == '\\') { - result += "\\\\"; - } else if (static_cast(c) < 0x20 || - static_cast(c) == 0x7F) { - auto v = static_cast(c); - int w; - if (v <= 0xFFFF) { - result += "\\u"; - w = 4; + result += u8"\\\\"; + } else if (c < 0x20 || c == 0x7F) { + if (c <= 0xFFFF) { + result += fmt::format(u8"\\u{:04X}", c); } else { - result += "\\U"; - w = 8; + result += fmt::format(u8"\\u{:08X}", c); } - std::stringstream ss; - ss << std::hex << std::setw(w) << std::setfill('0') << v; - result += ss.str(); } else { - result += c; + utfcpp::append(static_cast(c), result); } } return result; } -std::string EscapeMultilineBasicString(const std::string& str) { +std::string EscapeMultilineBasicString(const std::string_view view) { std::string result; int quote_run = 0; - for (char c : str) { + auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend()); + auto end = u8_citer(view.cend(), view.cbegin(), view.cend()); + for (auto it = begin; it != end; ++it) { + auto c = *it; if (quote_run > 0) { if (c == '"') { ++quote_run; @@ -116,74 +131,67 @@ std::string EscapeMultilineBasicString(const std::string& str) { } for (int i = 0; i < quote_run; ++i) { if ((i % 3) == 2) { - result += "\\"; + result += u8"\\"; } - result += '"'; + result += u8"\""; } quote_run = 0; } if (c == '\b') { - result += "\\b"; + result += u8"\\b"; } else if (c == '\t' || c == '\n') { result += c; } else if (c == '\f') { - result += "\\f"; + result += u8"\\f"; } else if (c == '\r') { // Silently drop \r. // result += c; } else if (c == '"') { quote_run = 1; } else if (c == '\\') { - result += "\\\\"; - } else if (static_cast(c) < 0x20 || - static_cast(c) == 0x7F) { - auto v = static_cast(c); - int w; - if (v <= 0xFFFF) { - result += "\\u"; - w = 4; + result += u8"\\\\"; + } else if (c < 0x20 || c == 0x7F) { + if (c <= 0xFFFF) { + result += fmt::format(u8"\\u{:04X}", c); } else { - result += "\\U"; - w = 8; + result += fmt::format(u8"\\u{:08X}", c); } - std::stringstream ss; - ss << std::hex << std::setw(w) << std::setfill('0') << v; - result += ss.str(); } else { - result += c; + utfcpp::append(static_cast(c), result); } } for (int i = 0; i < quote_run; ++i) { if ((i % 3) == 2) { - result += "\\"; + result += u8"\\"; } - result += '"'; + result += u8"\""; } return result; } -std::string EscapeString(const std::string& val) { - const char multiline_chars[] = "\r\n"; - const char escape_chars[] = +std::string EscapeString(const std::string_view view) { + const auto multiline_chars = std::string_view("\r\n"); + const auto escape_chars = std::string_view( "\0\b\v\f" "\x01\x02\x03\x04\x05\x06\x07\x0E\x0F" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" "'" - "\x7F"; - if (val.find_first_of(multiline_chars) == std::string::npos) { + "\x7F"); + + if (xe::utf8::find_any_of(view, multiline_chars) == std::string_view::npos) { // single line - if (val.find_first_of(escape_chars) == std::string::npos) { - return "'" + val + "'"; + if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos) { + return "'" + std::string(view) + "'"; } else { - return "\"" + toml::EscapeBasicString(val) + "\""; + return "\"" + toml::EscapeBasicString(view) + "\""; } } else { // multi line - if (val.find_first_of(escape_chars) == std::string::npos && - val.find("'''") == std::string::npos) { - return "'''\n" + val + "'''"; + if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos && + xe::utf8::find_first_of(view, u8"'''") == std::string_view::npos) { + return "'''\n" + std::string(view) + "'''"; } else { - return "\"\"\"\n" + toml::EscapeMultilineBasicString(val) + "\"\"\""; + return u8"\"\"\"\n" + toml::EscapeMultilineBasicString(view) + u8"\"\"\""; } } } diff --git a/src/xenia/base/cvar.h b/src/xenia/base/cvar.h index 6c55d9f30..d68173ddf 100644 --- a/src/xenia/base/cvar.h +++ b/src/xenia/base/cvar.h @@ -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. * ****************************************************************************** */ @@ -10,18 +10,20 @@ #ifndef XENIA_CVAR_H_ #define XENIA_CVAR_H_ +#include #include #include #include #include "cpptoml/include/cpptoml.h" #include "cxxopts/include/cxxopts.hpp" +#include "xenia/base/filesystem.h" #include "xenia/base/string_util.h" namespace cvar { namespace toml { -std::string EscapeString(const std::string& str); +std::string EscapeString(const std::string_view str); } class ICommandVar { @@ -116,10 +118,22 @@ template void ConfigVar::LoadConfigValue(std::shared_ptr result) { SetConfigValue(*cpptoml::get_impl(result)); } +template <> +inline void ConfigVar::LoadConfigValue( + std::shared_ptr result) { + SetConfigValue( + xe::utf8::fix_path_separators(*cpptoml::get_impl(result))); +} template void ConfigVar::LoadGameConfigValue(std::shared_ptr result) { SetGameConfigValue(*cpptoml::get_impl(result)); } +template <> +inline void ConfigVar::LoadGameConfigValue( + std::shared_ptr result) { + SetGameConfigValue( + xe::utf8::fix_path_separators(*cpptoml::get_impl(result))); +} template CommandVar::CommandVar(const char* name, T* default_value, const char* description) @@ -158,6 +172,11 @@ template <> inline std::string CommandVar::Convert(std::string val) { return val; } +template <> +inline std::filesystem::path CommandVar::Convert( + std::string val) { + return xe::to_path(val); +} template <> inline std::string CommandVar::ToString(bool val) { @@ -167,6 +186,12 @@ template <> inline std::string CommandVar::ToString(std::string val) { return toml::EscapeString(val); } +template <> +inline std::string CommandVar::ToString( + std::filesystem::path val) { + return toml::EscapeString( + xe::utf8::fix_path_separators(xe::path_to_utf8(val), '/')); +} template std::string CommandVar::ToString(T val) { @@ -217,8 +242,8 @@ inline void AddCommandVar(ICommandVar* cv) { if (!CmdVars) CmdVars = new std::map(); CmdVars->insert(std::pair(cv->name(), cv)); } -void ParseLaunchArguments(int argc, char** argv, - const std::string& positional_help, +void ParseLaunchArguments(int& argc, char**& argv, + const std::string_view positional_help, const std::vector& positional_options); template @@ -237,6 +262,9 @@ T* define_cmdvar(const char* name, T* default_value, const char* description) { return default_value; } +#define DEFINE_bool(name, default_value, description, category) \ + DEFINE_CVar(name, default_value, description, category, false, bool) + #define DEFINE_int32(name, default_value, description, category) \ DEFINE_CVar(name, default_value, description, category, false, int32_t) @@ -249,11 +277,16 @@ T* define_cmdvar(const char* name, T* default_value, const char* description) { #define DEFINE_string(name, default_value, description, category) \ DEFINE_CVar(name, default_value, description, category, false, std::string) +#define DEFINE_path(name, default_value, description, category) \ + DEFINE_CVar(name, default_value, description, category, false, \ + std::filesystem::path) + #define DEFINE_transient_string(name, default_value, description, category) \ DEFINE_CVar(name, default_value, description, category, true, std::string) -#define DEFINE_bool(name, default_value, description, category) \ - DEFINE_CVar(name, default_value, description, category, false, bool) +#define DEFINE_transient_path(name, default_value, description, category) \ + DEFINE_CVar(name, default_value, description, category, true, \ + std::filesystem::path) #define DEFINE_CVar(name, default_value, description, category, is_transient, \ type) \ @@ -275,16 +308,18 @@ T* define_cmdvar(const char* name, T* default_value, const char* description) { cvar::define_cmdvar(#name, &cvars::name, description); \ } -#define DECLARE_double(name) DECLARE_CVar(name, double) - #define DECLARE_bool(name) DECLARE_CVar(name, bool) -#define DECLARE_string(name) DECLARE_CVar(name, std::string) - #define DECLARE_int32(name) DECLARE_CVar(name, int32_t) #define DECLARE_uint64(name) DECLARE_CVar(name, uint64_t) +#define DECLARE_double(name) DECLARE_CVar(name, double) + +#define DECLARE_string(name) DECLARE_CVar(name, std::string) + +#define DECLARE_path(name) DECLARE_CVar(name, std::filesystem::path) + #define DECLARE_CVar(name, type) \ namespace cvars { \ extern type name; \ diff --git a/src/xenia/base/filesystem.cc b/src/xenia/base/filesystem.cc index a24bbaf85..c141720fa 100644 --- a/src/xenia/base/filesystem.cc +++ b/src/xenia/base/filesystem.cc @@ -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. * ****************************************************************************** */ @@ -14,96 +14,14 @@ namespace xe { namespace filesystem { -std::string CanonicalizePath(const std::string& original_path) { - char path_sep(xe::kPathSeparator); - std::string path(xe::fix_path_separators(original_path, path_sep)); - - std::vector path_breaks; - - std::string::size_type pos(path.find_first_of(path_sep)); - std::string::size_type pos_n(std::string::npos); - - while (pos != std::string::npos) { - if ((pos_n = path.find_first_of(path_sep, pos + 1)) == std::string::npos) { - pos_n = path.size(); +bool CreateParentFolder(const std::filesystem::path& path) { + if (path.has_parent_path()) { + auto parent_path = path.parent_path(); + if (!PathExists(parent_path)) { + return CreateFolder(parent_path); } - - auto diff(pos_n - pos); - switch (diff) { - case 0: - pos_n = std::string::npos; - break; - case 1: - // Duplicate separators. - path.erase(pos, 1); - pos_n -= 1; - break; - case 2: - // Potential marker for current directory. - if (path[pos + 1] == '.') { - path.erase(pos, 2); - pos_n -= 2; - } else { - path_breaks.push_back(pos); - } - break; - case 3: - // Potential marker for parent directory. - if (path[pos + 1] == '.' && path[pos + 2] == '.') { - if (path_breaks.empty()) { - // Ensure we don't override the device name. - std::string::size_type loc(path.find_first_of(':')); - auto req(pos + 3); - if (loc == std::string::npos || loc > req) { - path.erase(0, req); - pos_n -= req; - } else { - path.erase(loc + 1, req - (loc + 1)); - pos_n -= req - (loc + 1); - } - } else { - auto last(path_breaks.back()); - auto last_diff((pos + 3) - last); - path.erase(last, last_diff); - pos_n = last; - // Also remove path reference. - path_breaks.erase(path_breaks.end() - 1); - } - } else { - path_breaks.push_back(pos); - } - break; - - default: - path_breaks.push_back(pos); - break; - } - - pos = pos_n; - } - - // Remove trailing seperator. - if (!path.empty() && path.back() == path_sep) { - path.erase(path.size() - 1); - } - - // Final sanity check for dead paths. - if ((path.size() == 1 && (path[0] == '.' || path[0] == path_sep)) || - (path.size() == 2 && path[0] == '.' && path[1] == '.')) { - return ""; - } - - return path; -} - -bool CreateParentFolder(const std::wstring& path) { - auto fixed_path = xe::fix_path_separators(path, xe::kWPathSeparator); - auto base_path = xe::find_base_path(fixed_path, xe::kWPathSeparator); - if (!base_path.empty() && !PathExists(base_path)) { - return CreateFolder(base_path); - } else { - return true; } + return true; } } // namespace filesystem diff --git a/src/xenia/base/filesystem.h b/src/xenia/base/filesystem.h index 7a1cdee32..29d144294 100644 --- a/src/xenia/base/filesystem.h +++ b/src/xenia/base/filesystem.h @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_BASE_FILESYSTEM_H_ #define XENIA_BASE_FILESYSTEM_H_ +#include #include #include #include @@ -18,45 +19,48 @@ #include "xenia/base/string.h" namespace xe { + +std::string path_to_utf8(const std::filesystem::path& path); +std::u16string path_to_utf16(const std::filesystem::path& path); +std::filesystem::path to_path(const std::string_view source); +std::filesystem::path to_path(const std::u16string_view source); + namespace filesystem { // Get executable path. -std::wstring GetExecutablePath(); +std::filesystem::path GetExecutablePath(); // Get executable folder. -std::wstring GetExecutableFolder(); +std::filesystem::path GetExecutableFolder(); // Get user folder. -std::wstring GetUserFolder(); - -// Canonicalizes a path, removing ..'s. -std::string CanonicalizePath(const std::string& original_path); +std::filesystem::path GetUserFolder(); // Returns true of the specified path exists as either a directory or file. -bool PathExists(const std::wstring& path); +bool PathExists(const std::filesystem::path& path); // Creates the parent folder of the specified path if needed. // This can be used to ensure the destination path for a new file exists before // attempting to create it. -bool CreateParentFolder(const std::wstring& path); +bool CreateParentFolder(const std::filesystem::path& path); // Creates a folder at the specified path. // Returns true if the path was created. -bool CreateFolder(const std::wstring& path); +bool CreateFolder(const std::filesystem::path& path); // Recursively deletes the files and folders at the specified path. // Returns true if the path was found and removed. -bool DeleteFolder(const std::wstring& path); +bool DeleteFolder(const std::filesystem::path& path); // Returns true if the given path exists and is a folder. -bool IsFolder(const std::wstring& path); +bool IsFolder(const std::filesystem::path& path); // Creates an empty file at the given path. -bool CreateFile(const std::wstring& path); +bool CreateFile(const std::filesystem::path& path); // Opens the file at the given path with the specified mode. // This behaves like fopen and the returned handle can be used with stdio. -FILE* OpenFile(const std::wstring& path, const char* mode); +FILE* OpenFile(const std::filesystem::path& path, const std::string_view mode); // Wrapper for the 64-bit version of fseek, returns true on success. bool Seek(FILE* file, int64_t offset, int origin); @@ -71,7 +75,7 @@ bool TruncateStdioFile(FILE* file, uint64_t length); // Deletes the file at the given path. // Returns true if the file was found and removed. -bool DeleteFile(const std::wstring& path); +bool DeleteFile(const std::filesystem::path& path); struct FileAccess { // Implies kFileReadData. @@ -89,12 +93,12 @@ class FileHandle { public: // Opens the file, failing if it doesn't exist. // The desired_access bitmask denotes the permissions on the file. - static std::unique_ptr OpenExisting(std::wstring path, - uint32_t desired_access); + static std::unique_ptr OpenExisting( + const std::filesystem::path& path, uint32_t desired_access); virtual ~FileHandle() = default; - std::wstring path() const { return path_; } + const std::filesystem::path& path() const { return path_; } // Reads the requested number of bytes from the file starting at the given // offset. The total number of bytes read is returned only if the complete @@ -115,9 +119,9 @@ class FileHandle { virtual void Flush() = 0; protected: - explicit FileHandle(std::wstring path) : path_(std::move(path)) {} + explicit FileHandle(const std::filesystem::path& path) : path_(path) {} - std::wstring path_; + std::filesystem::path path_; }; struct FileInfo { @@ -126,15 +130,15 @@ struct FileInfo { kDirectory, }; Type type; - std::wstring name; - std::wstring path; + std::filesystem::path name; + std::filesystem::path path; size_t total_size; uint64_t create_timestamp; uint64_t access_timestamp; uint64_t write_timestamp; }; -bool GetInfo(const std::wstring& path, FileInfo* out_info); -std::vector ListFiles(const std::wstring& path); +bool GetInfo(const std::filesystem::path& path, FileInfo* out_info); +std::vector ListFiles(const std::filesystem::path& path); } // namespace filesystem } // namespace xe diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index 619af97ac..41e317ec4 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2017 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,54 +26,64 @@ #include namespace xe { + +std::string path_to_utf8(const std::filesystem::path& path) { + return path.string(); +} + +std::u16string path_to_utf16(const std::filesystem::path& path) { + return xe::to_utf16(path.string()); +} + +std::filesystem::path to_path(const std::string_view source) { return source; } + +std::filesystem::path to_path(const std::u16string_view source) { + return xe::to_utf8(source); +} + namespace filesystem { -std::wstring GetExecutablePath() { +std::filesystem::path GetExecutablePath() { char buff[FILENAME_MAX] = ""; readlink("/proc/self/exe", buff, FILENAME_MAX); std::string s(buff); - return to_wstring(s); + return s; } -std::wstring GetExecutableFolder() { - auto path = GetExecutablePath(); - return xe::find_base_path(path); +std::filesystem::path GetExecutableFolder() { + return GetExecutablePath().parent_path(); } -std::wstring GetUserFolder() { +std::filesystem::path GetUserFolder() { // get preferred data home - char* dataHome = std::getenv("XDG_DATA_HOME"); - - // if XDG_DATA_HOME not set, fallback to HOME directory - if (dataHome == NULL) { - dataHome = std::getenv("HOME"); - } else { - std::string home(dataHome); - return to_wstring(home); + char* home = std::getenv("XDG_DATA_HOME"); + if (home) { + return std::string(home); } + // if XDG_DATA_HOME not set, fallback to HOME directory + home = std::getenv("HOME"); + // if HOME not set, fall back to this - if (dataHome == NULL) { + if (home == NULL) { struct passwd pw1; struct passwd* pw; char buf[4096]; // could potentionally lower this getpwuid_r(getuid(), &pw1, buf, sizeof(buf), &pw); assert(&pw1 == pw); // sanity check - dataHome = pw->pw_dir; + home = pw->pw_dir; } - std::string home(dataHome); - return to_wstring(home + "/.local/share"); + return std::filesystem::path(home) / ".local" / "share"; } -bool PathExists(const std::wstring& path) { +bool PathExists(const std::filesystem::path& path) { struct stat st; - return stat(xe::to_string(path).c_str(), &st) == 0; + return stat(path.c_str(), &st) == 0; } -FILE* OpenFile(const std::wstring& path, const char* mode) { - auto fixed_path = xe::fix_path_separators(path); - return fopen(xe::to_string(fixed_path).c_str(), mode); +FILE* OpenFile(const std::filesystem::path& path, const std::string_view mode) { + return fopen(path.c_str(), std::string(mode).c_str()); } bool Seek(FILE* file, int64_t offset, int origin) { @@ -101,8 +111,8 @@ bool TruncateStdioFile(FILE* file, uint64_t length) { return true; } -bool CreateFolder(const std::wstring& path) { - return mkdir(xe::to_string(path).c_str(), 0774); +bool CreateFolder(const std::filesystem::path& path) { + return mkdir(path.c_str(), 0774); } static int removeCallback(const char* fpath, const struct stat* sb, @@ -111,9 +121,8 @@ static int removeCallback(const char* fpath, const struct stat* sb, return rv; } -bool DeleteFolder(const std::wstring& path) { - return nftw(xe::to_string(path).c_str(), removeCallback, 64, - FTW_DEPTH | FTW_PHYS) == 0 +bool DeleteFolder(const std::filesystem::path& path) { + return nftw(path.c_str(), removeCallback, 64, FTW_DEPTH | FTW_PHYS) == 0 ? true : false; } @@ -128,16 +137,16 @@ static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { return filetime; } -bool IsFolder(const std::wstring& path) { +bool IsFolder(const std::filesystem::path& path) { struct stat st; - if (stat(xe::to_string(path).c_str(), &st) == 0) { + if (stat(path.c_str(), &st) == 0) { if (S_ISDIR(st.st_mode)) return true; } return false; } -bool CreateFile(const std::wstring& path) { - int file = creat(xe::to_string(path).c_str(), 0774); +bool CreateFile(const std::filesystem::path& path) { + int file = creat(path.c_str(), 0774); if (file >= 0) { close(file); return true; @@ -145,13 +154,14 @@ bool CreateFile(const std::wstring& path) { return false; } -bool DeleteFile(const std::wstring& path) { - return (xe::to_string(path).c_str()) == 0 ? true : false; +bool DeleteFile(const std::filesystem::path& path) { + // TODO: proper implementation. + return (path.c_str()) == 0 ? true : false; } class PosixFileHandle : public FileHandle { public: - PosixFileHandle(std::wstring path, int handle) + PosixFileHandle(std::filesystem::path path, int handle) : FileHandle(std::move(path)), handle_(handle) {} ~PosixFileHandle() override { close(handle_); @@ -178,8 +188,8 @@ class PosixFileHandle : public FileHandle { int handle_ = -1; }; -std::unique_ptr FileHandle::OpenExisting(std::wstring path, - uint32_t desired_access) { +std::unique_ptr FileHandle::OpenExisting( + const std::filesystem::path& path, uint32_t desired_access) { int open_access = 0; if (desired_access & FileAccess::kGenericRead) { open_access |= O_RDONLY; @@ -202,7 +212,7 @@ std::unique_ptr FileHandle::OpenExisting(std::wstring path, if (desired_access & FileAccess::kFileAppendData) { open_access |= O_APPEND; } - int handle = open(xe::to_string(path).c_str(), open_access); + int handle = open(path.c_str(), open_access); if (handle == -1) { // TODO(benvanik): pick correct response. return nullptr; @@ -210,9 +220,9 @@ std::unique_ptr FileHandle::OpenExisting(std::wstring path, return std::make_unique(path, handle); } -bool GetInfo(const std::wstring& path, FileInfo* out_info) { +bool GetInfo(const std::filesystem::path& path, FileInfo* out_info) { struct stat st; - if (stat(xe::to_string(path).c_str(), &st) == 0) { + if (stat(path.c_str(), &st) == 0) { if (S_ISDIR(st.st_mode)) { out_info->type = FileInfo::Type::kDirectory; } else { @@ -226,10 +236,10 @@ bool GetInfo(const std::wstring& path, FileInfo* out_info) { return false; } -std::vector ListFiles(const std::wstring& path) { +std::vector ListFiles(const std::filesystem::path& path) { std::vector result; - DIR* dir = opendir(xe::to_string(path).c_str()); + DIR* dir = opendir(path.c_str()); if (!dir) { return result; } @@ -237,9 +247,9 @@ std::vector ListFiles(const std::wstring& path) { while (auto ent = readdir(dir)) { FileInfo info; - info.name = xe::to_wstring(ent->d_name); + info.name = ent->d_name; struct stat st; - stat((xe::to_string(path) + xe::to_string(info.name)).c_str(), &st); + stat((path / info.name).c_str(), &st); info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime); info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atime); info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime); diff --git a/src/xenia/base/filesystem_wildcard.cc b/src/xenia/base/filesystem_wildcard.cc index b2b4fc62c..1954060dc 100644 --- a/src/xenia/base/filesystem_wildcard.cc +++ b/src/xenia/base/filesystem_wildcard.cc @@ -2,18 +2,19 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/base/filesystem_wildcard.h" -#include "xenia/base/assert.h" #include -namespace xe { -namespace filesystem { +#include "xenia/base/assert.h" +#include "xenia/base/string.h" + +namespace xe::filesystem { WildcardFlags WildcardFlags::FIRST(true, false, false); WildcardFlags WildcardFlags::LAST(false, true, false); @@ -25,47 +26,45 @@ WildcardFlags::WildcardFlags() WildcardFlags::WildcardFlags(bool start, bool end, bool exact_length) : FromStart(start), ToEnd(end), ExactLength(exact_length) {} -WildcardRule::WildcardRule(const std::string& str_match, +WildcardRule::WildcardRule(const std::string_view match, const WildcardFlags& flags) - : match(str_match), rules(flags) { - std::transform(match.begin(), match.end(), match.begin(), tolower); -} + : match_(utf8::lower_ascii(match)), rules_(flags) {} -bool WildcardRule::Check(const std::string& str_lower, +bool WildcardRule::Check(const std::string_view lower, std::string::size_type* offset) const { - if (match.empty()) { + if (match_.empty()) { return true; } - if ((str_lower.size() - *offset) < match.size()) { + if ((lower.size() - *offset) < match_.size()) { return false; } - if (rules.ExactLength) { - *offset += match.size(); + if (rules_.ExactLength) { + *offset += match_.size(); return true; } - std::string::size_type result(str_lower.find(match, *offset)); + std::string_view::size_type result(lower.find(match_, *offset)); - if (result != std::string::npos) { - if (rules.FromStart && result != *offset) { + if (result != std::string_view::npos) { + if (rules_.FromStart && result != *offset) { return false; } - if (rules.ToEnd && result != (str_lower.size() - match.size())) { + if (rules_.ToEnd && result != (lower.size() - match_.size())) { return false; } - *offset = (result + match.size()); + *offset = (result + match_.size()); return true; } return false; } -void WildcardEngine::PreparePattern(const std::string& pattern) { - rules.clear(); +void WildcardEngine::PreparePattern(const std::string_view pattern) { + rules_.clear(); WildcardFlags flags(WildcardFlags::FIRST); size_t n = 0; @@ -73,12 +72,12 @@ void WildcardEngine::PreparePattern(const std::string& pattern) { while ((n = pattern.find_first_of("*?", last)) != pattern.npos) { if (last != n) { std::string str_str(pattern.substr(last, n - last)); - rules.push_back(WildcardRule(str_str, flags)); + rules_.push_back(WildcardRule(str_str, flags)); } if (pattern[n] == '?') { auto end = pattern.find_first_not_of('?', n + 1); auto count = end == pattern.npos ? (pattern.size() - n) : (end - n); - rules.push_back( + rules_.push_back( WildcardRule(pattern.substr(n, count), WildcardFlags::ANY)); last = n + count; } else if (pattern[n] == '*') { @@ -90,20 +89,18 @@ void WildcardEngine::PreparePattern(const std::string& pattern) { } if (last != pattern.size()) { std::string str_str(pattern.substr(last)); - rules.push_back(WildcardRule(str_str, WildcardFlags::LAST)); + rules_.push_back(WildcardRule(str_str, WildcardFlags::LAST)); } } -void WildcardEngine::SetRule(const std::string& pattern) { +void WildcardEngine::SetRule(const std::string_view pattern) { PreparePattern(pattern); } -bool WildcardEngine::Match(const std::string& str) const { - std::string str_lc; - std::transform(str.begin(), str.end(), std::back_inserter(str_lc), tolower); - +bool WildcardEngine::Match(const std::string_view str) const { + std::string str_lc = utf8::lower_ascii(str); std::string::size_type offset(0); - for (const auto& rule : rules) { + for (const auto& rule : rules_) { if (!(rule.Check(str_lc, &offset))) { return false; } @@ -112,5 +109,4 @@ bool WildcardEngine::Match(const std::string& str) const { return true; } -} // namespace filesystem -} // namespace xe +} // namespace xe::filesystem diff --git a/src/xenia/base/filesystem_wildcard.h b/src/xenia/base/filesystem_wildcard.h index 1ecd452f2..fdad44604 100644 --- a/src/xenia/base/filesystem_wildcard.h +++ b/src/xenia/base/filesystem_wildcard.h @@ -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. * ****************************************************************************** */ @@ -34,25 +34,25 @@ class WildcardFlags { class WildcardRule { public: - WildcardRule(const std::string& str_match, const WildcardFlags& flags); - bool Check(const std::string& str_lower, - std::string::size_type* offset) const; + WildcardRule(const std::string_view match, const WildcardFlags& flags); + bool Check(const std::string_view lower, + std::string_view::size_type* offset) const; private: - std::string match; - WildcardFlags rules; + std::string match_; + WildcardFlags rules_; }; class WildcardEngine { public: - void SetRule(const std::string& pattern); + void SetRule(const std::string_view pattern); // Always ignoring case - bool Match(const std::string& str) const; + bool Match(const std::string_view str) const; private: - std::vector rules; - void PreparePattern(const std::string& pattern); + std::vector rules_; + void PreparePattern(const std::string_view pattern); }; } // namespace filesystem diff --git a/src/xenia/base/filesystem_win.cc b/src/xenia/base/filesystem_win.cc index e38d9c226..6bbc11577 100644 --- a/src/xenia/base/filesystem_win.cc +++ b/src/xenia/base/filesystem_win.cc @@ -2,37 +2,56 @@ ****************************************************************************** * 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. * ****************************************************************************** */ -#include "xenia/base/filesystem.h" -#include "xenia/base/logging.h" - -#include - #include #include +#include + +#undef CreateFile +#undef DeleteFile + +#include "xenia/base/filesystem.h" +#include "xenia/base/logging.h" #include "xenia/base/platform_win.h" +#include "xenia/base/string.h" namespace xe { + +std::string path_to_utf8(const std::filesystem::path& path) { + return xe::to_utf8(path.u16string()); +} + +std::u16string path_to_utf16(const std::filesystem::path& path) { + return path.u16string(); +} + +std::filesystem::path to_path(const std::string_view source) { + return xe::to_utf16(source); +} + +std::filesystem::path to_path(const std::u16string_view source) { + return source; +} + namespace filesystem { -std::wstring GetExecutablePath() { +std::filesystem::path GetExecutablePath() { wchar_t* path; auto error = _get_wpgmptr(&path); - return !error ? std::wstring(path) : std::wstring(); + return !error ? std::filesystem::path(path) : std::filesystem::path(); } -std::wstring GetExecutableFolder() { - auto path = GetExecutablePath(); - return xe::find_base_path(path); +std::filesystem::path GetExecutableFolder() { + return GetExecutablePath().parent_path(); } -std::wstring GetUserFolder() { - std::wstring result; +std::filesystem::path GetUserFolder() { + std::filesystem::path result; PWSTR path; if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &path))) { @@ -42,22 +61,22 @@ std::wstring GetUserFolder() { return result; } -bool PathExists(const std::wstring& path) { +bool PathExists(const std::filesystem::path& path) { DWORD attrib = GetFileAttributes(path.c_str()); return attrib != INVALID_FILE_ATTRIBUTES; } -bool CreateFolder(const std::wstring& path) { - size_t pos = 0; - do { - pos = path.find_first_of(xe::kWPathSeparator, pos + 1); - CreateDirectoryW(path.substr(0, pos).c_str(), nullptr); - } while (pos != std::string::npos); +bool CreateFolder(const std::filesystem::path& path) { + std::filesystem::path create_path; + for (auto it = path.begin(); it != path.end(); ++it) { + create_path /= *it; + CreateDirectoryW(create_path.c_str(), nullptr); + } return PathExists(path); } -bool DeleteFolder(const std::wstring& path) { - auto double_null_path = path + std::wstring(L"\0", 1); +bool DeleteFolder(const std::filesystem::path& path) { + auto double_null_path = path.wstring() + std::wstring(L"\0", 1); SHFILEOPSTRUCT op = {0}; op.wFunc = FO_DELETE; op.pFrom = double_null_path.c_str(); @@ -65,14 +84,13 @@ bool DeleteFolder(const std::wstring& path) { return SHFileOperation(&op) == 0; } -bool IsFolder(const std::wstring& path) { +bool IsFolder(const std::filesystem::path& path) { DWORD attrib = GetFileAttributes(path.c_str()); return attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; } -#undef CreateFile -bool CreateFile(const std::wstring& path) { +bool CreateFile(const std::filesystem::path& path) { auto handle = CreateFileW(path.c_str(), 0, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle == INVALID_HANDLE_VALUE) { @@ -83,9 +101,10 @@ bool CreateFile(const std::wstring& path) { return true; } -FILE* OpenFile(const std::wstring& path, const char* mode) { - auto fixed_path = xe::fix_path_separators(path); - return _wfopen(fixed_path.c_str(), xe::to_wstring(mode).c_str()); +FILE* OpenFile(const std::filesystem::path& path, const std::string_view mode) { + // Dumb, but OK. + const auto wmode = xe::to_utf16(mode); + return _wfopen(path.c_str(), reinterpret_cast(wmode.c_str())); } bool Seek(FILE* file, int64_t offset, int origin) { @@ -114,14 +133,14 @@ bool TruncateStdioFile(FILE* file, uint64_t length) { return true; } -bool DeleteFile(const std::wstring& path) { +bool DeleteFile(const std::filesystem::path& path) { return DeleteFileW(path.c_str()) ? true : false; } class Win32FileHandle : public FileHandle { public: - Win32FileHandle(std::wstring path, HANDLE handle) - : FileHandle(std::move(path)), handle_(handle) {} + Win32FileHandle(const std::filesystem::path& path, HANDLE handle) + : FileHandle(path), handle_(handle) {} ~Win32FileHandle() override { CloseHandle(handle_); handle_ = nullptr; @@ -181,8 +200,8 @@ class Win32FileHandle : public FileHandle { HANDLE handle_ = nullptr; }; -std::unique_ptr FileHandle::OpenExisting(std::wstring path, - uint32_t desired_access) { +std::unique_ptr FileHandle::OpenExisting( + const std::filesystem::path& path, uint32_t desired_access) { DWORD open_access = 0; if (desired_access & FileAccess::kGenericRead) { open_access |= GENERIC_READ; @@ -220,7 +239,7 @@ std::unique_ptr FileHandle::OpenExisting(std::wstring path, #define COMBINE_TIME(t) (((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime) -bool GetInfo(const std::wstring& path, FileInfo* out_info) { +bool GetInfo(const std::filesystem::path& path, FileInfo* out_info) { std::memset(out_info, 0, sizeof(FileInfo)); WIN32_FILE_ATTRIBUTE_DATA data = {0}; if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &data)) { @@ -234,19 +253,19 @@ bool GetInfo(const std::wstring& path, FileInfo* out_info) { out_info->total_size = (data.nFileSizeHigh * (size_t(MAXDWORD) + 1)) + data.nFileSizeLow; } - out_info->path = xe::find_base_path(path); - out_info->name = xe::find_name_from_path(path); + out_info->path = path.parent_path(); + out_info->name = path.filename(); out_info->create_timestamp = COMBINE_TIME(data.ftCreationTime); out_info->access_timestamp = COMBINE_TIME(data.ftLastAccessTime); out_info->write_timestamp = COMBINE_TIME(data.ftLastWriteTime); return true; } -std::vector ListFiles(const std::wstring& path) { +std::vector ListFiles(const std::filesystem::path& path) { std::vector result; WIN32_FIND_DATA ffd; - HANDLE handle = FindFirstFile((path + L"\\*").c_str(), &ffd); + HANDLE handle = FindFirstFileW((path / "*").c_str(), &ffd); if (handle == INVALID_HANDLE_VALUE) { return result; } diff --git a/src/xenia/base/fuzzy.cc b/src/xenia/base/fuzzy.cc new file mode 100644 index 000000000..dca062e66 --- /dev/null +++ b/src/xenia/base/fuzzy.cc @@ -0,0 +1,55 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/fuzzy.h" + +#include +#include + +// TODO(gibbed): UTF8 support. + +namespace xe { + +int fuzzy_match(const std::string_view pattern, const char* value) { + // https://github.com/mattyork/fuzzy/blob/master/lib/fuzzy.js + // TODO(benvanik): look at + // https://github.com/atom/fuzzaldrin/tree/master/src This does not weight + // complete substrings or prefixes right, which kind of sucks. + size_t pattern_index = 0; + size_t value_length = std::strlen(value); + int total_score = 0; + int local_score = 0; + for (size_t i = 0; i < value_length; ++i) { + if (std::tolower(value[i]) == std::tolower(pattern[pattern_index])) { + ++pattern_index; + local_score += 1 + local_score; + } else { + local_score = 0; + } + total_score += local_score; + } + return total_score; +} + +std::vector> fuzzy_filter(const std::string_view pattern, + const void* const* entries, + size_t entry_count, + size_t string_offset) { + std::vector> results; + results.reserve(entry_count); + for (size_t i = 0; i < entry_count; ++i) { + auto entry_value = + reinterpret_cast(entries[i]) + string_offset; + int score = fuzzy_match(pattern, entry_value); + results.emplace_back(i, score); + } + return results; +} + +} // namespace xe diff --git a/src/xenia/base/fuzzy.h b/src/xenia/base/fuzzy.h new file mode 100644 index 000000000..75cb12bb5 --- /dev/null +++ b/src/xenia/base/fuzzy.h @@ -0,0 +1,41 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_BASE_FUZZY_H_ +#define XENIA_BASE_FUZZY_H_ + +#include +#include + +namespace xe { + +// Tests a match against a case-insensitive fuzzy filter. +// Returns the score of the match or 0 if none. +int fuzzy_match(const std::string_view pattern, const char* value); + +// Applies a case-insensitive fuzzy filter to the given entries and ranks +// results. +// Entries is a list of pointers to opaque structs, each of which contains a +// char* string at the given offset. +// Returns an unsorted list of {original index, score}. +std::vector> fuzzy_filter(const std::string_view pattern, + const void* const* entries, + size_t entry_count, + size_t string_offset); +template +std::vector> fuzzy_filter(const std::string_view pattern, + const std::vector& entries, + size_t string_offset) { + return fuzzy_filter(pattern, reinterpret_cast(entries.data()), + entries.size(), string_offset); +} + +} // namespace xe + +#endif // XENIA_BASE_FUZZY_H_ diff --git a/src/xenia/base/logging.cc b/src/xenia/base/logging.cc index 238969513..5e13810ad 100644 --- a/src/xenia/base/logging.cc +++ b/src/xenia/base/logging.cc @@ -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. * ****************************************************************************** */ @@ -24,8 +24,8 @@ #include "xenia/base/math.h" #include "xenia/base/memory.h" #include "xenia/base/ring_buffer.h" +#include "xenia/base/string.h" #include "xenia/base/threading.h" -//#include "xenia/base/cvar.h" // For MessageBox: // TODO(benvanik): generic API? logging_win.cc? @@ -33,7 +33,9 @@ #include "xenia/base/platform_win.h" #endif // XE_PLATFORM_WIN32 -DEFINE_string( +#include "third_party/fmt/include/fmt/format.h" + +DEFINE_path( log_file, "", "Logs are written to the given file (specify stdout for command line)", "Logging"); @@ -54,19 +56,19 @@ thread_local std::vector log_format_buffer_(64 * 1024); class Logger { public: - explicit Logger(const std::wstring& app_name) : running_(true) { + explicit Logger(const std::string_view app_name) : running_(true) { if (cvars::log_file.empty()) { // Default to app name. - auto file_path = app_name + L".log"; + auto file_name = fmt::format("{}.log", app_name); + auto file_path = std::filesystem::path(file_name); xe::filesystem::CreateParentFolder(file_path); file_ = xe::filesystem::OpenFile(file_path, "wt"); } else { if (cvars::log_file == "stdout") { file_ = stdout; } else { - auto file_path = xe::to_wstring(cvars::log_file); - xe::filesystem::CreateParentFolder(file_path); - file_ = xe::filesystem::OpenFile(file_path, "wt"); + xe::filesystem::CreateParentFolder(cvars::log_file); + file_ = xe::filesystem::OpenFile(cvars::log_file, "wt"); } } @@ -243,7 +245,7 @@ class Logger { std::unique_ptr write_thread_; }; -void InitializeLogging(const std::wstring& app_name) { +void InitializeLogging(const std::string_view app_name) { auto mem = memory::AlignedAlloc(0x10); logger_ = new (mem) Logger(app_name); } @@ -294,40 +296,23 @@ void LogLineVarargs(LogLevel log_level, const char prefix_char, const char* fmt, prefix_char, log_format_buffer_.data(), size); } -void LogLine(LogLevel log_level, const char prefix_char, const char* str, - size_t str_length) { - if (!logger_) { - return; - } - - logger_->AppendLine( - xe::threading::current_thread_id(), log_level, prefix_char, str, - str_length == std::string::npos ? std::strlen(str) : str_length); -} - -void LogLine(LogLevel log_level, const char prefix_char, - const std::string& str) { +void logging::AppendLogLine(LogLevel log_level, const char prefix_char, + const std::string_view str) { if (!logger_) { return; } logger_->AppendLine(xe::threading::current_thread_id(), log_level, - prefix_char, str.c_str(), str.length()); + prefix_char, str.data(), str.length()); } -void FatalError(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - LogLineVarargs(LogLevel::Error, 'X', fmt, args); - va_end(args); +void FatalError(const std::string_view str) { + LogLine(LogLevel::Error, 'X', str); + logging::AppendLogLine(LogLevel::Error, 'X', str); #if XE_PLATFORM_WIN32 if (!xe::has_console_attached()) { - va_start(args, fmt); - std::vsnprintf(log_format_buffer_.data(), log_format_buffer_.capacity(), - fmt, args); - va_end(args); - MessageBoxA(NULL, log_format_buffer_.data(), "Xenia Error", + MessageBoxW(NULL, (LPCWSTR)xe::to_utf16(str).c_str(), L"Xenia Error", MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND); } #endif // WIN32 @@ -335,27 +320,4 @@ void FatalError(const char* fmt, ...) { std::exit(1); } -void FatalError(const wchar_t* fmt, ...) { - va_list args; - va_start(args, fmt); - std::vswprintf((wchar_t*)log_format_buffer_.data(), - log_format_buffer_.capacity() >> 1, fmt, args); - va_end(args); - - LogLine(LogLevel::Error, 'X', - xe::to_string((wchar_t*)log_format_buffer_.data())); - -#if XE_PLATFORM_WIN32 - if (!xe::has_console_attached()) { - MessageBoxW(NULL, (wchar_t*)log_format_buffer_.data(), L"Xenia Error", - MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND); - } -#endif // WIN32 - ShutdownLogging(); - std::exit(1); -} - -void FatalError(const std::string& str) { FatalError(str.c_str()); } -void FatalError(const std::wstring& str) { FatalError(str.c_str()); } - } // namespace xe diff --git a/src/xenia/base/logging.h b/src/xenia/base/logging.h index 8c0d0821a..2ac8182b6 100644 --- a/src/xenia/base/logging.h +++ b/src/xenia/base/logging.h @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_BASE_LOGGING_H_ #define XENIA_BASE_LOGGING_H_ +#include #include #include @@ -34,7 +35,7 @@ enum class LogLevel { // Initializes the logging system and any outputs requested. // Must be called on startup. -void InitializeLogging(const std::wstring& app_name); +void InitializeLogging(const std::string_view app_name); void ShutdownLogging(); // Appends a line to the log with printf-style formatting. @@ -43,17 +44,10 @@ void LogLineFormat(LogLevel log_level, const char prefix_char, const char* fmt, void LogLineVarargs(LogLevel log_level, const char prefix_char, const char* fmt, va_list args); // Appends a line to the log. -void LogLine(LogLevel log_level, const char prefix_char, const char* str, - size_t str_length = std::string::npos); -void LogLine(LogLevel log_level, const char prefix_char, - const std::string& str); +void LogLine(LogLevel log_level, const char prefix_char, std::string_view str); -// Logs a fatal error with printf-style formatting and aborts the program. -void FatalError(const char* fmt, ...); -void FatalError(const wchar_t* fmt, ...); // Logs a fatal error and aborts the program. -void FatalError(const std::string& str); -void FatalError(const std::wstring& str); +void FatalError(const std::string_view str); #if XE_OPTION_ENABLE_LOGGING #define XELOGCORE(level, prefix, fmt, ...) \ diff --git a/src/xenia/base/main.h b/src/xenia/base/main.h index 3a58e6bb9..c985eb4de 100644 --- a/src/xenia/base/main.h +++ b/src/xenia/base/main.h @@ -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. * ****************************************************************************** */ @@ -24,10 +24,10 @@ bool has_console_attached(); // Extern defined by user code. This must be present for the application to // launch. struct EntryInfo { - std::wstring name; + std::string name; std::string positional_usage; std::vector positional_options; - int (*entry_point)(const std::vector& args); + int (*entry_point)(const std::vector& args); }; EntryInfo GetEntryInfo(); diff --git a/src/xenia/base/main_posix.cc b/src/xenia/base/main_posix.cc index 8522700f6..673ff0ac4 100644 --- a/src/xenia/base/main_posix.cc +++ b/src/xenia/base/main_posix.cc @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #include "xenia/base/cvar.h" #include "xenia/base/main.h" +#include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/string.h" @@ -25,9 +26,9 @@ extern "C" int main(int argc, char** argv) { cvar::ParseLaunchArguments(argc, argv, entry_info.positional_usage, entry_info.positional_options); - std::vector args; + std::vector args; for (int n = 0; n < argc; n++) { - args.push_back(xe::to_wstring(argv[n])); + args.push_back(argv[n]); } // Initialize logging. Needs parsed FLAGS. diff --git a/src/xenia/base/main_win.cc b/src/xenia/base/main_win.cc index 1cd166393..503936291 100644 --- a/src/xenia/base/main_win.cc +++ b/src/xenia/base/main_win.cc @@ -2,30 +2,31 @@ ****************************************************************************** * 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/base/main.h" - #include #include #include -// Autogenerated by `xb premake`. -#include "build/version.h" - +#include "xenia/base/cvar.h" #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" +#include "xenia/base/main.h" #include "xenia/base/platform_win.h" #include "xenia/base/string.h" -#include "third_party/xbyak/xbyak/xbyak_util.h" +// Autogenerated by `xb premake`. +#include "build/version.h" -#include -#include "xenia/base/cvar.h" +// For RequestHighPerformance. +#include + +// Includes Windows headers, so it goes here. +#include "third_party/xbyak/xbyak/xbyak_util.h" DEFINE_bool(win32_high_freq, true, "Requests high performance from the NT kernel", "Kernel"); @@ -71,9 +72,9 @@ static void RequestHighPerformance() { OUT PULONG CurrentResolution); NtQueryTimerResolution = (decltype(NtQueryTimerResolution))GetProcAddress( - GetModuleHandle(L"ntdll.dll"), "NtQueryTimerResolution"); + GetModuleHandleW(L"ntdll.dll"), "NtQueryTimerResolution"); NtSetTimerResolution = (decltype(NtSetTimerResolution))GetProcAddress( - GetModuleHandle(L"ntdll.dll"), "NtSetTimerResolution"); + GetModuleHandleW(L"ntdll.dll"), "NtSetTimerResolution"); if (!NtQueryTimerResolution || !NtSetTimerResolution) { return; } @@ -85,37 +86,44 @@ static void RequestHighPerformance() { #endif } -int Main() { - auto entry_info = xe::GetEntryInfo(); - - // Convert command line to an argv-like format so we can share code/use +static bool parse_launch_arguments(const xe::EntryInfo& entry_info, + std::vector& args) { auto command_line = GetCommandLineW(); - int argc; - wchar_t** argv = CommandLineToArgvW(command_line, &argc); - if (!argv) { - return 1; + + int wargc; + wchar_t** wargv = CommandLineToArgvW(command_line, &wargc); + if (!wargv) { + return false; } // Convert all args to narrow, as cxxopts doesn't support wchar. - int argca = argc; - char** argva = reinterpret_cast(alloca(sizeof(char*) * argca)); - for (int n = 0; n < argca; n++) { - size_t len = std::wcstombs(nullptr, argv[n], 0); - argva[n] = reinterpret_cast(alloca(sizeof(char) * (len + 1))); - std::wcstombs(argva[n], argv[n], len + 1); + int argc = wargc; + char** argv = reinterpret_cast(alloca(sizeof(char*) * argc)); + for (int n = 0; n < argc; n++) { + size_t len = std::wcstombs(nullptr, wargv[n], 0); + argv[n] = reinterpret_cast(alloca(sizeof(char) * (len + 1))); + std::wcstombs(argv[n], wargv[n], len + 1); } - cvar::ParseLaunchArguments(argca, argva, entry_info.positional_usage, + LocalFree(wargv); + + cvar::ParseLaunchArguments(argc, argv, entry_info.positional_usage, entry_info.positional_options); - // Widen all remaining flags and convert to usable strings. - std::vector args; + args.clear(); for (int n = 0; n < argc; n++) { - size_t len = std::mbstowcs(nullptr, argva[n], 0); - auto argvw = - reinterpret_cast(alloca(sizeof(wchar_t) * (len + 1))); - std::mbstowcs(argvw, argva[n], len + 1); - args.push_back(std::wstring(argvw)); + args.push_back(std::string(argv[n])); + } + + return true; +} + +int Main() { + auto entry_info = xe::GetEntryInfo(); + + std::vector args; + if (!parse_launch_arguments(entry_info, args)) { + return 1; } // Setup COM on the main thread. @@ -147,7 +155,6 @@ int Main() { int result = entry_info.entry_point(args); xe::ShutdownLogging(); - LocalFree(argv); return result; } diff --git a/src/xenia/base/mapped_memory.h b/src/xenia/base/mapped_memory.h index e88a4fff2..203c43918 100644 --- a/src/xenia/base/mapped_memory.h +++ b/src/xenia/base/mapped_memory.h @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_BASE_MAPPED_MEMORY_H_ #define XENIA_BASE_MAPPED_MEMORY_H_ +#include #include #include @@ -22,13 +23,14 @@ class MappedMemory { kReadWrite, }; - static std::unique_ptr Open(const std::wstring& path, Mode mode, - size_t offset = 0, + static std::unique_ptr Open(const std::filesystem::path& path, + Mode mode, size_t offset = 0, size_t length = 0); - MappedMemory(const std::wstring& path, Mode mode) + MappedMemory(const std::filesystem::path& path, Mode mode) : path_(path), mode_(mode), data_(nullptr), size_(0) {} - MappedMemory(const std::wstring& path, Mode mode, void* data, size_t size) + MappedMemory(const std::filesystem::path& path, Mode mode, void* data, + size_t size) : path_(path), mode_(mode), data_(data), size_(size) {} virtual ~MappedMemory() = default; @@ -48,7 +50,7 @@ class MappedMemory { virtual bool Remap(size_t offset, size_t length) { return false; } protected: - std::wstring path_; + std::filesystem::path path_; Mode mode_; void* data_; size_t size_; @@ -59,7 +61,7 @@ class ChunkedMappedMemoryWriter { virtual ~ChunkedMappedMemoryWriter() = default; static std::unique_ptr Open( - const std::wstring& path, size_t chunk_size, + const std::filesystem::path& path, size_t chunk_size, bool low_address_space = false); virtual uint8_t* Allocate(size_t length) = 0; @@ -67,13 +69,13 @@ class ChunkedMappedMemoryWriter { virtual void FlushNew() = 0; protected: - ChunkedMappedMemoryWriter(const std::wstring& path, size_t chunk_size, - bool low_address_space) + ChunkedMappedMemoryWriter(const std::filesystem::path& path, + size_t chunk_size, bool low_address_space) : path_(path), chunk_size_(chunk_size), low_address_space_(low_address_space) {} - std::wstring path_; + std::filesystem::path path_; size_t chunk_size_; bool low_address_space_; }; diff --git a/src/xenia/base/mapped_memory_posix.cc b/src/xenia/base/mapped_memory_posix.cc index acfec7abe..34c530e20 100644 --- a/src/xenia/base/mapped_memory_posix.cc +++ b/src/xenia/base/mapped_memory_posix.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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. * ****************************************************************************** */ @@ -19,7 +19,7 @@ namespace xe { class PosixMappedMemory : public MappedMemory { public: - PosixMappedMemory(const std::wstring& path, Mode mode) + PosixMappedMemory(const std::filesystem::path& path, Mode mode) : MappedMemory(path, mode), file_handle(nullptr) {} ~PosixMappedMemory() override { @@ -34,9 +34,9 @@ class PosixMappedMemory : public MappedMemory { FILE* file_handle; }; -std::unique_ptr MappedMemory::Open(const std::wstring& path, - Mode mode, size_t offset, - size_t length) { +std::unique_ptr MappedMemory::Open( + const std::filesystem::path& path, Mode mode, size_t offset, + size_t length) { const char* mode_str; int prot; switch (mode) { @@ -53,7 +53,7 @@ std::unique_ptr MappedMemory::Open(const std::wstring& path, auto mm = std::unique_ptr(new PosixMappedMemory(path, mode)); - mm->file_handle = fopen(xe::to_string(path).c_str(), mode_str); + mm->file_handle = fopen(path.c_str(), mode_str); if (!mm->file_handle) { return nullptr; } @@ -77,7 +77,8 @@ std::unique_ptr MappedMemory::Open(const std::wstring& path, } std::unique_ptr ChunkedMappedMemoryWriter::Open( - const std::wstring& path, size_t chunk_size, bool low_address_space) { + const std::filesystem::path& path, size_t chunk_size, + bool low_address_space) { // TODO(DrChat) return nullptr; } diff --git a/src/xenia/base/mapped_memory_win.cc b/src/xenia/base/mapped_memory_win.cc index 790c29665..25ec5cb92 100644 --- a/src/xenia/base/mapped_memory_win.cc +++ b/src/xenia/base/mapped_memory_win.cc @@ -2,18 +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/base/mapped_memory.h" - #include #include #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/logging.h" +#include "xenia/base/mapped_memory.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" #include "xenia/base/platform_win.h" @@ -22,7 +22,7 @@ namespace xe { class Win32MappedMemory : public MappedMemory { public: - Win32MappedMemory(const std::wstring& path, Mode mode) + Win32MappedMemory(const std::filesystem::path& path, Mode mode) : MappedMemory(path, mode) {} ~Win32MappedMemory() override { @@ -88,9 +88,9 @@ class Win32MappedMemory : public MappedMemory { DWORD view_access_ = 0; }; -std::unique_ptr MappedMemory::Open(const std::wstring& path, - Mode mode, size_t offset, - size_t length) { +std::unique_ptr MappedMemory::Open( + const std::filesystem::path& path, Mode mode, size_t offset, + size_t length) { DWORD file_access = 0; DWORD file_share = 0; DWORD create_mode = 0; @@ -157,8 +157,8 @@ std::unique_ptr MappedMemory::Open(const std::wstring& path, class Win32ChunkedMappedMemoryWriter : public ChunkedMappedMemoryWriter { public: - Win32ChunkedMappedMemoryWriter(const std::wstring& path, size_t chunk_size, - bool low_address_space) + Win32ChunkedMappedMemoryWriter(const std::filesystem::path& path, + size_t chunk_size, bool low_address_space) : ChunkedMappedMemoryWriter(path, chunk_size, low_address_space) {} ~Win32ChunkedMappedMemoryWriter() override { @@ -175,7 +175,8 @@ class Win32ChunkedMappedMemoryWriter : public ChunkedMappedMemoryWriter { } } auto chunk = std::make_unique(chunk_size_); - auto chunk_path = path_ + L"." + std::to_wstring(chunks_.size()); + auto chunk_path = + path_.replace_extension(fmt::format(".{}", chunks_.size())); if (!chunk->Open(chunk_path, low_address_space_)) { return nullptr; } @@ -221,7 +222,7 @@ class Win32ChunkedMappedMemoryWriter : public ChunkedMappedMemoryWriter { } } - bool Open(const std::wstring& path, bool low_address_space) { + bool Open(const std::filesystem::path& path, bool low_address_space) { DWORD file_access = GENERIC_READ | GENERIC_WRITE; DWORD file_share = FILE_SHARE_READ; DWORD create_mode = CREATE_ALWAYS; @@ -300,7 +301,8 @@ class Win32ChunkedMappedMemoryWriter : public ChunkedMappedMemoryWriter { }; std::unique_ptr ChunkedMappedMemoryWriter::Open( - const std::wstring& path, size_t chunk_size, bool low_address_space) { + const std::filesystem::path& path, size_t chunk_size, + bool low_address_space) { SYSTEM_INFO system_info; GetSystemInfo(&system_info); size_t aligned_chunk_size = diff --git a/src/xenia/base/memory.h b/src/xenia/base/memory.h index 4188af763..e1125a5e3 100644 --- a/src/xenia/base/memory.h +++ b/src/xenia/base/memory.h @@ -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. * ****************************************************************************** */ @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -97,8 +98,9 @@ void AlignedFree(T* ptr) { typedef void* FileMappingHandle; -FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, - PageAccess access, bool commit); +FileMappingHandle CreateFileMappingHandle(const std::filesystem::path& path, + size_t length, PageAccess access, + bool commit); void CloseFileMappingHandle(FileMappingHandle handle); void* MapFileView(FileMappingHandle handle, void* base_address, size_t length, PageAccess access, size_t file_offset); @@ -281,8 +283,8 @@ inline std::string load_and_swap(const void* mem) { return value; } template <> -inline std::wstring load_and_swap(const void* mem) { - std::wstring value; +inline std::u16string load_and_swap(const void* mem) { + std::u16string value; for (int i = 0;; ++i) { auto c = xe::load_and_swap(reinterpret_cast(mem) + i); @@ -337,17 +339,17 @@ inline void store(void* mem, const double& value) { *reinterpret_cast(mem) = value; } template -inline void store(const void* mem, const T& value) { - if (sizeof(T) == 1) { +constexpr inline void store(const void* mem, const T& value) { + if constexpr (sizeof(T) == 1) { store(mem, static_cast(value)); - } else if (sizeof(T) == 2) { + } else if constexpr (sizeof(T) == 2) { store(mem, static_cast(value)); - } else if (sizeof(T) == 4) { + } else if constexpr (sizeof(T) == 4) { store(mem, static_cast(value)); - } else if (sizeof(T) == 8) { + } else if constexpr (sizeof(T) == 8) { store(mem, static_cast(value)); } else { - assert_always("Invalid xe::store size"); + static_assert("Invalid xe::store size"); } } @@ -394,18 +396,29 @@ inline void store_and_swap(void* mem, const double& value) { *reinterpret_cast(mem) = byte_swap(value); } template <> -inline void store_and_swap(void* mem, const std::string& value) { +inline void store_and_swap(void* mem, + const std::string_view& value) { for (auto i = 0; i < value.size(); ++i) { xe::store_and_swap(reinterpret_cast(mem) + i, value[i]); } } template <> -inline void store_and_swap(void* mem, const std::wstring& value) { +inline void store_and_swap(void* mem, const std::string& value) { + return store_and_swap(mem, value); +} +template <> +inline void store_and_swap( + void* mem, const std::u16string_view& value) { for (auto i = 0; i < value.size(); ++i) { xe::store_and_swap(reinterpret_cast(mem) + i, value[i]); } } +template <> +inline void store_and_swap(void* mem, + const std::u16string& value) { + return store_and_swap(mem, value); +} } // namespace xe diff --git a/src/xenia/base/memory_posix.cc b/src/xenia/base/memory_posix.cc index 68fdcd61b..8010e5f18 100644 --- a/src/xenia/base/memory_posix.cc +++ b/src/xenia/base/memory_posix.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2017 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. * ****************************************************************************** */ @@ -61,8 +61,9 @@ bool QueryProtect(void* base_address, size_t& length, PageAccess& access_out) { return false; } -FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, - PageAccess access, bool commit) { +FileMappingHandle CreateFileMappingHandle(const std::filesystem::path& path, + size_t length, PageAccess access, + bool commit) { int oflag; switch (access) { case PageAccess::kNoAccess: @@ -81,7 +82,7 @@ FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, } oflag |= O_CREAT; - int ret = shm_open(xe::to_string(path).c_str(), oflag, 0777); + int ret = shm_open(path.c_str(), oflag, 0777); if (ret > 0) { ftruncate64(ret, length); } diff --git a/src/xenia/base/memory_win.cc b/src/xenia/base/memory_win.cc index 0113c5f6d..13b78a411 100644 --- a/src/xenia/base/memory_win.cc +++ b/src/xenia/base/memory_win.cc @@ -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. * ****************************************************************************** */ @@ -142,8 +142,9 @@ bool QueryProtect(void* base_address, size_t& length, PageAccess& access_out) { return true; } -FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, - PageAccess access, bool commit) { +FileMappingHandle CreateFileMappingHandle(const std::filesystem::path& path, + size_t length, PageAccess access, + bool commit) { DWORD protect = ToWin32ProtectFlags(access) | (commit ? SEC_COMMIT : SEC_RESERVE); return CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, protect, diff --git a/src/xenia/base/platform.h b/src/xenia/base/platform.h index e08443fdc..33083a831 100644 --- a/src/xenia/base/platform.h +++ b/src/xenia/base/platform.h @@ -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. * ****************************************************************************** */ @@ -94,15 +94,11 @@ namespace xe { #if XE_PLATFORM_WIN32 const char kPathSeparator = '\\'; -const wchar_t kWPathSeparator = L'\\'; #else const char kPathSeparator = '/'; -const wchar_t kWPathSeparator = L'/'; -const size_t kMaxPath = 1024; // PATH_MAX #endif // XE_PLATFORM_WIN32 -// Launches a web browser to the given URL. -void LaunchBrowser(const wchar_t* url); +const char kGuestPathSeparator = '\\'; } // namespace xe diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h index ac64879e5..ab86caa68 100644 --- a/src/xenia/base/platform_linux.h +++ b/src/xenia/base/platform_linux.h @@ -2,13 +2,13 @@ ****************************************************************************** * 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. * ****************************************************************************** */ -#ifndef XENIA_BASE_PLATFORM_X11_H_ -#define XENIA_BASE_PLATFORM_X11_H_ +#ifndef XENIA_BASE_PLATFORM_LINUX_H_ +#define XENIA_BASE_PLATFORM_LINUX_H_ // NOTE: if you're including this file it means you are explicitly depending // on Linux headers. Including this file outside of linux platform specific @@ -17,17 +17,4 @@ #include "xenia/base/platform.h" -// Xlib/Xcb is used only for GLX/Vulkan interaction, the window management -// and input events are done with gtk/gdk -#include -#include -#include -#include -#include - -// Used for window management. Gtk is for GUI and wigets, gdk is for lower -// level events like key presses, mouse events, window handles, etc -#include -#include - -#endif // XENIA_BASE_PLATFORM_X11_H_ +#endif // XENIA_BASE_PLATFORM_LINUX_H_ diff --git a/src/xenia/base/premake5.lua b/src/xenia/base/premake5.lua index 3459f66ad..2a731b847 100644 --- a/src/xenia/base/premake5.lua +++ b/src/xenia/base/premake5.lua @@ -5,6 +5,9 @@ project("xenia-base") uuid("aeadaf22-2b20-4941-b05f-a802d5679c11") kind("StaticLib") language("C++") + links({ + "fmt" + }) defines({ }) local_platform_files() diff --git a/src/xenia/base/socket.h b/src/xenia/base/socket.h index 24e9112d5..0c300ef24 100644 --- a/src/xenia/base/socket.h +++ b/src/xenia/base/socket.h @@ -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. * ****************************************************************************** */ @@ -91,7 +91,7 @@ class Socket { // Asynchronously sends a string buffer. // Returns false if the socket is disconnected or the data cannot be sent. - bool Send(const std::string& value) { + bool Send(const std::string_view value) { return Send(value.data(), value.size()); } }; diff --git a/src/xenia/base/string.cc b/src/xenia/base/string.cc index 4610c661e..4fdeb3d0c 100644 --- a/src/xenia/base/string.cc +++ b/src/xenia/base/string.cc @@ -2,359 +2,29 @@ ****************************************************************************** * 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/base/string.h" -// codecvt existence check -#ifdef __clang__ -// using clang -#if (__clang_major__ < 4) // 3.3 has it but I think we need at least 4 anyway -// insufficient clang version -#define NO_CODECVT 1 -#else -#include -#endif -#elif defined(__GNUC__) || defined(__GNUG__) -// using gcc -#if (__GNUC__ < 5) -// insufficient clang version -#define NO_CODECVT 1 -#else -#include -#endif -// since the windows 10 sdk is required, this shouldn't be an issue -#elif defined(_MSC_VER) -#include -#endif - -#include -#include +#include #include +#define UTF_CPP_CPLUSPLUS 201703L +#include "third_party/utfcpp/source/utf8.h" + +namespace utfcpp = utf8; + namespace xe { -std::string to_string(const std::wstring& source) { -#if NO_CODECVT - return std::string(source.begin(), source.end()); -#else - static std::wstring_convert> converter; - return converter.to_bytes(source); -#endif // XE_PLATFORM_LINUX +std::string to_utf8(const std::u16string_view source) { + return utfcpp::utf16to8(source); } -std::wstring to_wstring(const std::string& source) { -#if NO_CODECVT - return std::wstring(source.begin(), source.end()); -#else - static std::wstring_convert> converter; - return converter.from_bytes(source); -#endif // XE_PLATFORM_LINUX -} - -std::string format_string(const char* format, va_list args) { - if (!format) { - return ""; - } - size_t max_len = 64; - std::string new_s; - while (true) { - new_s.resize(max_len); - int ret = - std::vsnprintf(const_cast(new_s.data()), max_len, format, args); - if (ret > max_len) { - // Needed size is known (+2 for termination and avoid ambiguity). - max_len = ret + 2; - } else if (ret == -1 || ret >= max_len - 1) { - // Handle some buggy vsnprintf implementations. - max_len *= 2; - } else { - // Everything fit for sure. - new_s.resize(ret); - return new_s; - } - } -} - -std::wstring format_string(const wchar_t* format, va_list args) { - if (!format) { - return L""; - } - size_t max_len = 64; - std::wstring new_s; - while (true) { - new_s.resize(max_len); - int ret = std::vswprintf(const_cast(new_s.data()), max_len, - format, args); - if (ret > max_len) { - // Needed size is known (+2 for termination and avoid ambiguity). - max_len = ret + 2; - } else if (ret == -1 || ret >= max_len - 1) { - // Handle some buggy vsnprintf implementations. - max_len *= 2; - } else { - // Everything fit for sure. - new_s.resize(ret); - return new_s; - } - } -} - -std::vector split_string(const std::string& path, - const std::string& delimiters) { - std::vector parts; - size_t n = 0; - size_t last = 0; - while ((n = path.find_first_of(delimiters, last)) != path.npos) { - if (last != n) { - parts.push_back(path.substr(last, n - last)); - } - last = n + 1; - } - if (last != path.size()) { - parts.push_back(path.substr(last)); - } - return parts; -} - -std::vector split_string(const std::wstring& path, - const std::wstring& delimiters) { - std::vector parts; - size_t n = 0; - size_t last = 0; - while ((n = path.find_first_of(delimiters, last)) != path.npos) { - if (last != n) { - parts.push_back(path.substr(last, n - last)); - } - last = n + 1; - } - if (last != path.size()) { - parts.push_back(path.substr(last)); - } - return parts; -} - -std::string::size_type find_first_of_case(const std::string& target, - const std::string& search) { - const char* str = target.c_str(); - while (*str) { - if (!strncasecmp(str, search.c_str(), search.size())) { - break; - } - str++; - } - if (*str) { - return str - target.c_str(); - } else { - return std::string::npos; - } -} - -std::wstring to_absolute_path(const std::wstring& path) { -#if XE_PLATFORM_WIN32 - std::wstring result; - wchar_t* buffer = _wfullpath(nullptr, path.c_str(), 0); - if (buffer != nullptr) { - result.assign(buffer); - free(buffer); - } - return result; -#else - char buffer[kMaxPath]; - realpath(xe::to_string(path).c_str(), buffer); - return xe::to_wstring(buffer); -#endif // XE_PLATFORM_WIN32 -} - -std::vector split_path(const std::string& path) { - return split_string(path, "\\/"); -} - -std::vector split_path(const std::wstring& path) { - return split_string(path, L"\\/"); -} - -std::string join_paths(const std::string& left, const std::string& right, - char sep) { - if (!left.size()) { - return right; - } else if (!right.size()) { - return left; - } - if (left[left.size() - 1] == sep) { - return left + right; - } else { - return left + sep + right; - } -} - -std::wstring join_paths(const std::wstring& left, const std::wstring& right, - wchar_t sep) { - if (!left.size()) { - return right; - } else if (!right.size()) { - return left; - } - if (left[left.size() - 1] == sep) { - return left + right; - } else { - return left + sep + right; - } -} - -std::wstring fix_path_separators(const std::wstring& source, wchar_t new_sep) { - // Swap all separators to new_sep. - wchar_t old_sep = new_sep == '\\' ? '/' : '\\'; - std::wstring::size_type pos = 0; - std::wstring dest = source; - while ((pos = source.find_first_of(old_sep, pos)) != std::wstring::npos) { - dest[pos] = new_sep; - ++pos; - } - // Replace redundant separators. - pos = 0; - while ((pos = dest.find_first_of(new_sep, pos)) != std::wstring::npos) { - if (pos < dest.size() - 1) { - if (dest[pos + 1] == new_sep) { - dest.erase(pos + 1, 1); - } - } - ++pos; - } - return dest; -} - -std::string fix_path_separators(const std::string& source, char new_sep) { - // Swap all separators to new_sep. - char old_sep = new_sep == '\\' ? '/' : '\\'; - std::string::size_type pos = 0; - std::string dest = source; - while ((pos = source.find_first_of(old_sep, pos)) != std::string::npos) { - dest[pos] = new_sep; - ++pos; - } - // Replace redundant separators. - pos = 0; - while ((pos = dest.find_first_of(new_sep, pos)) != std::string::npos) { - if (pos < dest.size() - 1) { - if (dest[pos + 1] == new_sep) { - dest.erase(pos + 1, 1); - } - } - ++pos; - } - return dest; -} - -std::string find_name_from_path(const std::string& path, char sep) { - std::string name(path); - if (!path.empty()) { - std::string::size_type from(std::string::npos); - if (path.back() == sep) { - from = path.size() - 2; - } - auto pos(path.find_last_of(sep, from)); - if (pos != std::string::npos) { - if (from == std::string::npos) { - name = path.substr(pos + 1); - } else { - auto len(from - pos); - name = path.substr(pos + 1, len); - } - } - } - return name; -} - -std::wstring find_name_from_path(const std::wstring& path, wchar_t sep) { - std::wstring name(path); - if (!path.empty()) { - std::wstring::size_type from(std::wstring::npos); - if (path.back() == sep) { - from = path.size() - 2; - } - auto pos(path.find_last_of(sep, from)); - if (pos != std::wstring::npos) { - if (from == std::wstring::npos) { - name = path.substr(pos + 1); - } else { - auto len(from - pos); - name = path.substr(pos + 1, len); - } - } - } - return name; -} - -std::string find_base_path(const std::string& path, char sep) { - auto last_slash = path.find_last_of(sep); - if (last_slash == std::string::npos) { - return ""; - } else if (last_slash == path.length() - 1) { - auto prev_slash = path.find_last_of(sep, last_slash - 1); - if (prev_slash == std::string::npos) { - return ""; - } else { - return path.substr(0, prev_slash + 1); - } - } else { - return path.substr(0, last_slash + 1); - } -} - -std::wstring find_base_path(const std::wstring& path, wchar_t sep) { - auto last_slash = path.find_last_of(sep); - if (last_slash == std::wstring::npos) { - return L""; - } else if (last_slash == path.length() - 1) { - auto prev_slash = path.find_last_of(sep, last_slash - 1); - if (prev_slash == std::wstring::npos) { - return L""; - } else { - return path.substr(0, prev_slash + 1); - } - } else { - return path.substr(0, last_slash + 1); - } -} - -int fuzzy_match(const std::string& pattern, const char* value) { - // https://github.com/mattyork/fuzzy/blob/master/lib/fuzzy.js - // TODO(benvanik): look at https://github.com/atom/fuzzaldrin/tree/master/src - // This does not weight complete substrings or prefixes right, which - // kind of sucks. - size_t pattern_index = 0; - size_t value_length = std::strlen(value); - int total_score = 0; - int local_score = 0; - for (size_t i = 0; i < value_length; ++i) { - if (std::tolower(value[i]) == std::tolower(pattern[pattern_index])) { - ++pattern_index; - local_score += 1 + local_score; - } else { - local_score = 0; - } - total_score += local_score; - } - return total_score; -} - -std::vector> fuzzy_filter(const std::string& pattern, - const void* const* entries, - size_t entry_count, - size_t string_offset) { - std::vector> results; - results.reserve(entry_count); - for (size_t i = 0; i < entry_count; ++i) { - auto entry_value = - reinterpret_cast(entries[i]) + string_offset; - int score = fuzzy_match(pattern, entry_value); - results.emplace_back(i, score); - } - return results; +std::u16string to_utf16(const std::string_view source) { + return utfcpp::utf8to16(source); } } // namespace xe diff --git a/src/xenia/base/string.h b/src/xenia/base/string.h index 1ce7dafeb..bed95dce0 100644 --- a/src/xenia/base/string.h +++ b/src/xenia/base/string.h @@ -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. * ****************************************************************************** */ @@ -10,99 +10,14 @@ #ifndef XENIA_BASE_STRING_H_ #define XENIA_BASE_STRING_H_ -#include -#include #include -#include -#include -#include "xenia/base/platform.h" +#include "utf8.h" namespace xe { -std::string to_string(const std::wstring& source); -std::wstring to_wstring(const std::string& source); - -std::string format_string(const char* format, va_list args); -inline std::string format_string(const char* format, ...) { - va_list va; - va_start(va, format); - auto result = format_string(format, va); - va_end(va); - return result; -} -std::wstring format_string(const wchar_t* format, va_list args); -inline std::wstring format_string(const wchar_t* format, ...) { - va_list va; - va_start(va, format); - auto result = format_string(format, va); - va_end(va); - return result; -} - -// Splits the given string on any delimiters and returns all parts. -std::vector split_string(const std::string& path, - const std::string& delimiters); - -std::vector split_string(const std::wstring& path, - const std::wstring& delimiters); - -// find_first_of string, case insensitive. -std::string::size_type find_first_of_case(const std::string& target, - const std::string& search); - -// Converts the given path to an absolute path based on cwd. -std::wstring to_absolute_path(const std::wstring& path); - -// Splits the given path on any valid path separator and returns all parts. -std::vector split_path(const std::string& path); -std::vector split_path(const std::wstring& path); - -// Joins two path segments with the given separator. -std::string join_paths(const std::string& left, const std::string& right, - char sep = xe::kPathSeparator); -std::wstring join_paths(const std::wstring& left, const std::wstring& right, - wchar_t sep = xe::kPathSeparator); - -// Replaces all path separators with the given value and removes redundant -// separators. -std::wstring fix_path_separators(const std::wstring& source, - wchar_t new_sep = xe::kPathSeparator); -std::string fix_path_separators(const std::string& source, - char new_sep = xe::kPathSeparator); - -// Find the top directory name or filename from a path. -std::string find_name_from_path(const std::string& path, - char sep = xe::kPathSeparator); -std::wstring find_name_from_path(const std::wstring& path, - wchar_t sep = xe::kPathSeparator); - -// Get parent path of the given directory or filename. -std::string find_base_path(const std::string& path, - char sep = xe::kPathSeparator); -std::wstring find_base_path(const std::wstring& path, - wchar_t sep = xe::kPathSeparator); - -// Tests a match against a case-insensitive fuzzy filter. -// Returns the score of the match or 0 if none. -int fuzzy_match(const std::string& pattern, const char* value); - -// Applies a case-insensitive fuzzy filter to the given entries and ranks -// results. -// Entries is a list of pointers to opaque structs, each of which contains a -// char* string at the given offset. -// Returns an unsorted list of {original index, score}. -std::vector> fuzzy_filter(const std::string& pattern, - const void* const* entries, - size_t entry_count, - size_t string_offset); -template -std::vector> fuzzy_filter(const std::string& pattern, - const std::vector& entries, - size_t string_offset) { - return fuzzy_filter(pattern, reinterpret_cast(entries.data()), - entries.size(), string_offset); -} +std::string to_utf8(const std::u16string_view source); +std::u16string to_utf16(const std::string_view source); } // namespace xe diff --git a/src/xenia/base/string_buffer.cc b/src/xenia/base/string_buffer.cc index f7b4c8889..5bc3bad0a 100644 --- a/src/xenia/base/string_buffer.cc +++ b/src/xenia/base/string_buffer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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. * ****************************************************************************** */ @@ -52,17 +52,10 @@ void StringBuffer::Append(const char* value) { AppendBytes(reinterpret_cast(value), std::strlen(value)); } -void StringBuffer::Append(const std::string& value) { +void StringBuffer::Append(const std::string_view value) { AppendBytes(reinterpret_cast(value.data()), value.size()); } -void StringBuffer::AppendFormat(const char* format, ...) { - va_list args; - va_start(args, format); - AppendVarargs(format, args); - va_end(args); -} - void StringBuffer::AppendVarargs(const char* format, va_list args) { int length = vsnprintf(nullptr, 0, format, args); Grow(length + 1); @@ -78,15 +71,15 @@ void StringBuffer::AppendBytes(const uint8_t* buffer, size_t length) { buffer_[buffer_offset_] = 0; } -const char* StringBuffer::GetString() const { return buffer_; } - std::string StringBuffer::to_string() { return std::string(buffer_, buffer_offset_); } -char* StringBuffer::ToString() { return strdup(buffer_); } +std::string_view StringBuffer::to_string_view() const { + return std::string_view(buffer_, buffer_offset_); +} -std::vector StringBuffer::ToBytes() const { +std::vector StringBuffer::to_bytes() const { std::vector bytes(buffer_offset_); std::memcpy(bytes.data(), buffer_, buffer_offset_); return bytes; diff --git a/src/xenia/base/string_buffer.h b/src/xenia/base/string_buffer.h index 8c1e32de9..bd6063fe4 100644 --- a/src/xenia/base/string_buffer.h +++ b/src/xenia/base/string_buffer.h @@ -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. * ****************************************************************************** */ @@ -14,6 +14,8 @@ #include #include +#include "third_party/fmt/include/fmt/format.h" + namespace xe { class StringBuffer { @@ -21,21 +23,27 @@ class StringBuffer { explicit StringBuffer(size_t initial_capacity = 0); ~StringBuffer(); + char* buffer() const { return buffer_; } size_t length() const { return buffer_offset_; } void Reset(); void Append(char c); void Append(const char* value); - void Append(const std::string& value); - void AppendFormat(const char* format, ...); + void Append(const std::string_view value); + + template + void AppendFormat(const char* format, const Args&... args) { + auto s = fmt::format(format, args...); + Append(s.c_str()); + } + void AppendVarargs(const char* format, va_list args); void AppendBytes(const uint8_t* buffer, size_t length); - const char* GetString() const; std::string to_string(); - char* ToString(); - std::vector ToBytes() const; + std::string_view to_string_view() const; + std::vector to_bytes() const; private: void Grow(size_t additional_length); diff --git a/src/xenia/base/string_key.h b/src/xenia/base/string_key.h new file mode 100644 index 000000000..adb6f827e --- /dev/null +++ b/src/xenia/base/string_key.h @@ -0,0 +1,103 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_BASE_STRING_KEY_H_ +#define XENIA_BASE_STRING_KEY_H_ + +#include +#include + +#include "utf8.h" + +namespace xe { + +namespace internal { + +struct string_key_base { + private: + std::variant value_; + + public: + explicit string_key_base(const std::string_view value) : value_(value) {} + explicit string_key_base(std::string value) : value_(std::move(value)) {} + + std::string_view view() const { + return std::holds_alternative(value_) + ? std::get(value_) + : std::get(value_); + } +}; + +} // namespace internal + +struct string_key : internal::string_key_base { + public: + explicit string_key(const std::string_view value) : string_key_base(value) {} + explicit string_key(std::string value) : string_key_base(value) {} + + static string_key create(const std::string_view value) { + return string_key(std::string(value)); + } + + static string_key create(std::string value) { return string_key(value); } + + bool operator==(const string_key& other) const { + return other.view() == view(); + } + + size_t hash() const { return utf8::hash_fnv1a(view()); } + + struct Hash { + size_t operator()(const string_key& t) const { return t.hash(); } + }; +}; + +struct string_key_case : internal::string_key_base { + public: + explicit string_key_case(const std::string_view value) + : string_key_base(value) {} + explicit string_key_case(std::string value) : string_key_base(value) {} + + static string_key_case create(const std::string_view value) { + return string_key_case(std::string(value)); + } + + static string_key_case create(std::string value) { + return string_key_case(value); + } + + bool operator==(const string_key_case& other) const { + return utf8::equal_case(other.view(), view()); + } + + size_t hash() const { return utf8::hash_fnv1a_case(view()); } + + struct Hash { + size_t operator()(const string_key_case& t) const { return t.hash(); } + }; +}; + +} // namespace xe + +namespace std { +template <> +struct std::hash { + std::size_t operator()(const xe::string_key& t) const { return t.hash(); } +}; + +template <> +struct std::hash { + std::size_t operator()(const xe::string_key_case& t) const { + return t.hash(); + } +}; + +}; // namespace std + +#endif // XENIA_BASE_STRING_KEY_H_ diff --git a/src/xenia/base/string_util.cc b/src/xenia/base/string_util.cc deleted file mode 100644 index efeee3fda..000000000 --- a/src/xenia/base/string_util.cc +++ /dev/null @@ -1,69 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/base/string_util.h" - -#include -#include -#include -#include -#include - -#include "xenia/base/platform.h" -#include "xenia/base/vec128.h" - -namespace xe { -namespace string_util { - -std::string to_hex_string(uint32_t value) { - char buffer[21]; - std::snprintf(buffer, sizeof(buffer), "%08" PRIX32, value); - return std::string(buffer); -} - -std::string to_hex_string(uint64_t value) { - char buffer[21]; - std::snprintf(buffer, sizeof(buffer), "%016" PRIX64, value); - return std::string(buffer); -} - -std::string to_hex_string(const vec128_t& value) { - char buffer[128]; - std::snprintf(buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", - value.u32[0], value.u32[1], value.u32[2], value.u32[3]); - return std::string(buffer); -} - -#if XE_ARCH_AMD64 - -// TODO(DrChat): This should not exist. Force the caller to use vec128. -std::string to_hex_string(const __m128& value) { - char buffer[128]; - float f[4]; - _mm_storeu_ps(f, value); - std::snprintf( - buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", - *reinterpret_cast(&f[0]), *reinterpret_cast(&f[1]), - *reinterpret_cast(&f[2]), *reinterpret_cast(&f[3])); - return std::string(buffer); -} - -std::string to_string(const __m128& value) { - char buffer[128]; - float f[4]; - _mm_storeu_ps(f, value); - std::snprintf(buffer, sizeof(buffer), "(%F, %F, %F, %F)", f[0], f[1], f[2], - f[3]); - return std::string(buffer); -} - -#endif - -} // namespace string_util -} // namespace xe diff --git a/src/xenia/base/string_util.h b/src/xenia/base/string_util.h index c17d14d61..f1499bb5f 100644 --- a/src/xenia/base/string_util.h +++ b/src/xenia/base/string_util.h @@ -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. * ****************************************************************************** */ @@ -10,214 +10,290 @@ #ifndef XENIA_BASE_STRING_UTIL_H_ #define XENIA_BASE_STRING_UTIL_H_ -#include -#include -#include -#include +#include #include +#include "third_party/fmt/include/fmt/format.h" +#include "xenia/base/assert.h" #include "xenia/base/platform.h" +#include "xenia/base/string.h" #include "xenia/base/vec128.h" +// TODO(gibbed): Clang and GCC don't have std::from_chars for floating point(!) +// despite it being part of the C++17 standard. Check this in the future to see +// if it's been resolved. + +#if XE_COMPILER_CLANG || XE_COMPILER_GNUC +#include +#endif + namespace xe { namespace string_util { -// TODO(gibbed): Figure out why clang doesn't line forward declarations of -// inline functions. +inline std::string to_hex_string(uint32_t value) { + return fmt::format("{:08X}", value); +} -std::string to_hex_string(uint32_t value); -std::string to_hex_string(uint64_t value); +inline std::string to_hex_string(uint64_t value) { + return fmt::format("{:016X}", value); +} inline std::string to_hex_string(float value) { - union { - uint32_t ui; - float flt; - } v; - v.flt = value; - return to_hex_string(v.ui); + static_assert(sizeof(uint32_t) == sizeof(value)); + uint32_t pun; + std::memcpy(&pun, &value, sizeof(value)); + return to_hex_string(pun); } inline std::string to_hex_string(double value) { - union { - uint64_t ui; - double dbl; - } v; - v.dbl = value; - return to_hex_string(v.ui); + static_assert(sizeof(uint64_t) == sizeof(value)); + uint64_t pun; + std::memcpy(&pun, &value, sizeof(value)); + return to_hex_string(pun); } -std::string to_hex_string(const vec128_t& value); - -#if XE_ARCH_AMD64 - -// TODO(DrChat): This should not exist. Force the caller to use vec128. -std::string to_hex_string(const __m128& value); -std::string to_string(const __m128& value); - -#endif +inline std::string to_hex_string(const vec128_t& value) { + return fmt::format("[{:08X} {:08X} {:08X} {:08X} {:08X}]", value.u32[0], + value.u32[1], value.u32[2], value.u32[3]); +} template -inline T from_string(const char* value, bool force_hex = false) { - // Missing implementation for converting type T to string +inline T from_string(const std::string_view value, bool force_hex = false) { + // Missing implementation for converting type T from string throw; } -template <> -inline bool from_string(const char* value, bool force_hex) { - return std::strcmp(value, "true") == 0 || value[0] == '1'; -} +namespace internal { -template <> -inline int32_t from_string(const char* value, bool force_hex) { - if (force_hex || std::strchr(value, 'h') != nullptr) { - return std::strtol(value, nullptr, 16); +template > +inline T make_negative(T value) { + if constexpr (std::is_unsigned_v) { + value = static_cast(-static_cast(value)); } else { - return std::strtol(value, nullptr, 0); + value = -value; } + return value; } -template <> -inline uint32_t from_string(const char* value, bool force_hex) { - if (force_hex || std::strchr(value, 'h') != nullptr) { - return std::strtoul(value, nullptr, 16); - } else { - return std::strtoul(value, nullptr, 0); - } -} - -template <> -inline int64_t from_string(const char* value, bool force_hex) { - if (force_hex || std::strchr(value, 'h') != nullptr) { - return std::strtoll(value, nullptr, 16); - } else { - return std::strtoll(value, nullptr, 0); - } -} - -template <> -inline uint64_t from_string(const char* value, bool force_hex) { - if (force_hex || std::strchr(value, 'h') != nullptr) { - return std::strtoull(value, nullptr, 16); - } else { - return std::strtoull(value, nullptr, 0); - } -} - -template <> -inline float from_string(const char* value, bool force_hex) { - if (force_hex || std::strstr(value, "0x") == value || - std::strchr(value, 'h') != nullptr) { - union { - uint32_t ui; - float flt; - } v; - v.ui = from_string(value, force_hex); - return v.flt; - } - return std::strtof(value, nullptr); -} - -template <> -inline double from_string(const char* value, bool force_hex) { - if (force_hex || std::strstr(value, "0x") == value || - std::strchr(value, 'h') != nullptr) { - union { - uint64_t ui; - double dbl; - } v; - v.ui = from_string(value, force_hex); - return v.dbl; - } - return std::strtod(value, nullptr); -} - -template <> -inline vec128_t from_string(const char* value, bool force_hex) { - vec128_t v; - char* p = const_cast(value); - bool hex_mode = force_hex; - if (*p == '[') { - hex_mode = true; - ++p; - } else if (*p == '(') { - hex_mode = false; - ++p; - } else { - // Assume hex? - hex_mode = true; - ++p; - } - if (hex_mode) { - v.i32[0] = std::strtoul(p, &p, 16); - while (*p == ' ' || *p == ',') ++p; - v.i32[1] = std::strtoul(p, &p, 16); - while (*p == ' ' || *p == ',') ++p; - v.i32[2] = std::strtoul(p, &p, 16); - while (*p == ' ' || *p == ',') ++p; - v.i32[3] = std::strtoul(p, &p, 16); - } else { - v.f32[0] = std::strtof(p, &p); - while (*p == ' ' || *p == ',') ++p; - v.f32[1] = std::strtof(p, &p); - while (*p == ' ' || *p == ',') ++p; - v.f32[2] = std::strtof(p, &p); - while (*p == ' ' || *p == ',') ++p; - v.f32[3] = std::strtof(p, &p); - } - return v; -} - -#if XE_ARCH_AMD64 - -// TODO(DrChat): ?? Why is this here? Force the caller to use vec128. -template <> -inline __m128 from_string<__m128>(const char* value, bool force_hex) { - __m128 v; - float f[4]; - uint32_t u; - char* p = const_cast(value); - bool hex_mode = force_hex; - if (*p == '[') { - hex_mode = true; - ++p; - } else if (*p == '(') { - hex_mode = false; - ++p; - } else { - // Assume hex? - hex_mode = true; - ++p; - } - if (hex_mode) { - u = std::strtoul(p, &p, 16); - f[0] = *reinterpret_cast(&u); - while (*p == ' ' || *p == ',') ++p; - u = std::strtoul(p, &p, 16); - f[1] = *reinterpret_cast(&u); - while (*p == ' ' || *p == ',') ++p; - u = std::strtoul(p, &p, 16); - f[2] = *reinterpret_cast(&u); - while (*p == ' ' || *p == ',') ++p; - u = std::strtoul(p, &p, 16); - f[3] = *reinterpret_cast(&u); - } else { - f[0] = std::strtof(p, &p); - while (*p == ' ' || *p == ',') ++p; - f[1] = std::strtof(p, &p); - while (*p == ' ' || *p == ',') ++p; - f[2] = std::strtof(p, &p); - while (*p == ' ' || *p == ',') ++p; - f[3] = std::strtof(p, &p); - } - v = _mm_loadu_ps(f); - return v; -} - -#endif - +// integral_from_string template -inline T from_string(const std::string& value, bool force_hex = false) { - return from_string(value.c_str(), force_hex); +inline T ifs(const std::string_view value, bool force_hex) { + int base = 10; + std::string_view range = value; + bool is_hex = force_hex; + bool is_negative = false; + if (utf8::starts_with(range, "-")) { + is_negative = true; + range = range.substr(1); + } + if (utf8::starts_with(range, "0x")) { + is_hex = true; + range = range.substr(2); + } + if (utf8::ends_with(range, "h")) { + is_hex = true; + range = range.substr(0, range.length() - 1); + } + T result; + if (is_hex) { + base = 16; + } + // TODO(gibbed): do something more with errors? + auto [p, error] = + std::from_chars(range.data(), range.data() + range.size(), result, base); + if (error != std::errc()) { + assert_always(); + return T(); + } + if (is_negative) { + result = make_negative(result); + } + return result; +} + +// floating_point_from_string +template +inline T fpfs(const std::string_view value, bool force_hex) { + static_assert(sizeof(T) == sizeof(PUN)); + std::string_view range = value; + bool is_hex = force_hex; + bool is_negative = false; + if (utf8::starts_with(range, "-")) { + is_negative = true; + range = range.substr(1); + } + if (utf8::starts_with(range, "0x")) { + is_hex = true; + range = range.substr(2); + } + if (utf8::ends_with(range, "h")) { + is_hex = true; + range = range.substr(0, range.length() - 1); + } + T result; + if (is_hex) { + PUN pun = from_string(range, true); + if (is_negative) { + pun = make_negative(pun); + } + std::memcpy(&result, &pun, sizeof(PUN)); + } else { +#if XE_COMPILER_CLANG || XE_COMPILER_GNUC + auto temp = std::string(range); + result = std::strtof(temp.c_str(), nullptr); +#else + auto [p, error] = std::from_chars(range.data(), range.data() + range.size(), + result, std::chars_format::general); + // TODO(gibbed): do something more with errors? + if (error != std::errc()) { + assert_always(); + return T(); + } +#endif + if (is_negative) { + result = -result; + } + } + return result; +} + +} // namespace internal + +template <> +inline bool from_string(const std::string_view value, bool force_hex) { + return value == "true" || value == "1"; +} + +template <> +inline int8_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline uint8_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline int16_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline uint16_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline int32_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline uint32_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline int64_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline uint64_t from_string(const std::string_view value, + bool force_hex) { + return internal::ifs(value, force_hex); +} + +template <> +inline float from_string(const std::string_view value, bool force_hex) { + return internal::fpfs(value, force_hex); +} + +template <> +inline double from_string(const std::string_view value, + bool force_hex) { + return internal::fpfs(value, force_hex); +} + +template <> +inline vec128_t from_string(const std::string_view value, + bool force_hex) { + if (!value.size()) { + return vec128_t(); + } + vec128_t v; +#if XE_COMPILER_CLANG || XE_COMPILER_GNUC + auto temp = std::string(value); + auto p = temp.c_str(); + auto end = temp.c_str() + temp.size(); +#else + auto p = value.data(); + auto end = value.data() + value.size(); +#endif + bool is_hex = force_hex; + if (p != end && *p == '[') { + is_hex = true; + ++p; + } else if (p != end && *p == '(') { + is_hex = false; + ++p; + } else { + // Assume hex? + is_hex = true; + } + if (p == end) { + assert_always(); + return vec128_t(); + } + if (is_hex) { + for (size_t i = 0; i < 4; i++) { + while (p != end && (*p == ' ' || *p == ',')) { + ++p; + } + if (p == end) { + assert_always(); + return vec128_t(); + } + auto result = std::from_chars(p, end, v.u32[i], 16); + if (result.ec != std::errc()) { + assert_always(); + return vec128_t(); + } + p = result.ptr; + } + } else { + for (size_t i = 0; i < 4; i++) { + while (p != end && (*p == ' ' || *p == ',')) { + ++p; + } + if (p == end) { + assert_always(); + return vec128_t(); + } +#if XE_COMPILER_CLANG || XE_COMPILER_GNUC + char* next_p; + v.f32[i] = std::strtof(p, &next_p); + p = next_p; +#else + auto result = + std::from_chars(p, end, v.f32[i], std::chars_format::general); + if (result.ec != std::errc()) { + assert_always(); + return vec128_t(); + } + p = result.ptr; +#endif + } + } + return v; } } // namespace string_util diff --git a/src/xenia/base/platform_win.cc b/src/xenia/base/system.h similarity index 57% rename from src/xenia/base/platform_win.cc rename to src/xenia/base/system.h index 5b1b9c7e5..9ffbfa88f 100644 --- a/src/xenia/base/platform_win.cc +++ b/src/xenia/base/system.h @@ -2,17 +2,24 @@ ****************************************************************************** * 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. * ****************************************************************************** */ -#include "xenia/base/platform_win.h" +#ifndef XENIA_BASE_SYSTEM_H_ +#define XENIA_BASE_SYSTEM_H_ + +#include +#include + +#include "xenia/base/string.h" namespace xe { -void LaunchBrowser(const wchar_t* url) { - ShellExecuteW(NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); -} +void LaunchWebBrowser(const std::string& url); +void LaunchFileExplorer(const std::filesystem::path& path); } // namespace xe + +#endif // XENIA_BASE_SYSTEM_H_ diff --git a/src/xenia/base/platform_linux.cc b/src/xenia/base/system_linux.cc similarity index 67% rename from src/xenia/base/platform_linux.cc rename to src/xenia/base/system_linux.cc index aae0c7e21..80773618a 100644 --- a/src/xenia/base/platform_linux.cc +++ b/src/xenia/base/system_linux.cc @@ -2,21 +2,27 @@ ****************************************************************************** * 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. * ****************************************************************************** */ -#include "xenia/base/platform_linux.h" #include + #include + +#include "xenia/base/assert.h" +#include "xenia/base/platform_linux.h" #include "xenia/base/string.h" +#include "xenia/base/system.h" namespace xe { -void LaunchBrowser(const wchar_t* url) { - auto cmd = std::string("xdg-open " + xe::to_string(url)); +void LaunchWebBrowser(const std::string& url) { + auto cmd = "xdg-open " + url; system(cmd.c_str()); } +void LaunchFileExplorer(const std::filesystem::path& path) { assert_always(); } + } // namespace xe diff --git a/src/xenia/base/system_win.cc b/src/xenia/base/system_win.cc new file mode 100644 index 000000000..abb699844 --- /dev/null +++ b/src/xenia/base/system_win.cc @@ -0,0 +1,27 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/platform_win.h" +#include "xenia/base/string.h" +#include "xenia/base/system.h" + +namespace xe { + +void LaunchWebBrowser(const std::string& url) { + auto temp = xe::to_utf16(url); + ShellExecuteW(nullptr, L"open", reinterpret_cast(url.c_str()), + nullptr, nullptr, SW_SHOWNORMAL); +} + +void LaunchFileExplorer(const std::filesystem::path& url) { + ShellExecuteW(nullptr, L"explore", url.c_str(), nullptr, nullptr, + SW_SHOWNORMAL); +} + +} // namespace xe diff --git a/src/xenia/base/utf8.cc b/src/xenia/base/utf8.cc new file mode 100644 index 000000000..ab6fd959a --- /dev/null +++ b/src/xenia/base/utf8.cc @@ -0,0 +1,651 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/utf8.h" + +#include +#include +#include + +#define UTF_CPP_CPLUSPLUS 201703L +#include "third_party/utfcpp/source/utf8.h" + +namespace utfcpp = utf8; + +using citer = std::string_view::const_iterator; +using criter = std::string_view::const_reverse_iterator; +using utf8_citer = utfcpp::iterator; +using utf8_criter = utfcpp::iterator; + +namespace xe::utf8 { + +uint32_t lower_ascii(const uint32_t c) { + return c >= 'A' && c <= 'Z' ? c + 32 : c; +} + +uint32_t upper_ascii(const uint32_t c) { + return c >= 'A' && c <= 'Z' ? c + 32 : c; +} + +bool equal_ascii_case(const uint32_t l, const uint32_t r) { + return l == r || lower_ascii(l) == lower_ascii(r); +} + +std::pair make_citer(const std::string_view view) { + return {utf8_citer(view.cbegin(), view.cbegin(), view.cend()), + utf8_citer(view.cend(), view.cbegin(), view.cend())}; +} + +std::pair make_citer(const utf8_citer begin, + const utf8_citer end) { + return {utf8_citer(begin.base(), begin.base(), end.base()), + utf8_citer(end.base(), begin.base(), end.base())}; +} + +std::pair make_criter(const std::string_view view) { + return {utf8_criter(view.crbegin(), view.crbegin(), view.crend()), + utf8_criter(view.crend(), view.crbegin(), view.crend())}; +} + +std::pair make_criter(const utf8_criter begin, + const utf8_criter end) { + return {utf8_criter(begin.base(), begin.base(), end.base()), + utf8_criter(end.base(), begin.base(), end.base())}; +} + +size_t get_count(const std::string_view view) { + return size_t(utfcpp::distance(view.cbegin(), view.cend())); +} + +size_t get_byte_length(utf8_citer begin, utf8_citer end) { + return size_t(std::distance(begin.base(), end.base())); +} + +size_t get_byte_length(utf8_criter begin, utf8_criter end) { + return size_t(std::distance(begin.base(), end.base())); +} + +std::string lower_ascii(const std::string_view view) { + auto [begin, end] = make_citer(view); + std::string result; + for (auto it = begin; it != end; ++it) { + utfcpp::append(char32_t(lower_ascii(*it)), result); + } + return result; +} + +std::string upper_ascii(const std::string_view view) { + auto [begin, end] = make_citer(view); + std::string result; + for (auto it = begin; it != end; ++it) { + utfcpp::append(char32_t(upper_ascii(*it)), result); + } + return result; +} + +template +inline size_t hash_fnv1a(const std::string_view view) { + const size_t offset_basis = 0xCBF29CE484222325ull; + const size_t prime = 0x00000100000001B3ull; + auto work = [&prime](size_t hash, uint8_t byte_of_data) { + hash ^= byte_of_data; + hash *= prime; + return hash; + }; + auto hash = offset_basis; + auto [begin, end] = make_citer(view); + for (auto it = begin; it != end; ++it) { + uint32_t c; + if constexpr (LOWER) { + c = lower_ascii(*it); + } else { + c = *it; + } + hash = work(hash, uint8_t((c >> 0) & 0xFF)); + hash = work(hash, uint8_t((c >> 8) & 0xFF)); + hash = work(hash, uint8_t((c >> 16) & 0xFF)); + hash = work(hash, uint8_t((c >> 24) & 0xFF)); + } + return hash; +} + +size_t hash_fnv1a(const std::string_view view) { + return hash_fnv1a(view); +} + +size_t hash_fnv1a_case(const std::string_view view) { + return hash_fnv1a(view); +} + +// TODO(gibbed): this is a separate inline function instead of inline within +// split due to a Clang bug: reference to local binding 'needle_begin' declared +// in enclosing function 'split'. +inline utf8_citer find_needle(utf8_citer haystack_it, utf8_citer haystack_end, + utf8_citer needle_begin, utf8_citer needle_end) { + return std::find_if(haystack_it, haystack_end, [&](const auto& c) { + for (auto needle = needle_begin; needle != needle_end; ++needle) { + if (c == *needle) { + return true; + } + } + return false; + }); +} + +inline utf8_citer find_needle_case(utf8_citer haystack_it, + utf8_citer haystack_end, + utf8_citer needle_begin, + utf8_citer needle_end) { + return std::find_if(haystack_it, haystack_end, [&](const auto& c) { + for (auto needle = needle_begin; needle != needle_end; ++needle) { + if (equal_ascii_case(c, *needle)) { + return true; + } + } + return false; + }); +} + +std::vector split(const std::string_view haystack, + const std::string_view needles) { + std::vector result; + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needles); + + auto it = haystack_begin; + auto last = it; + for (;;) { + it = find_needle(it, haystack_end, needle_begin, needle_end); + if (it == haystack_end) { + break; + } + + if (it != last) { + auto offset = get_byte_length(haystack_begin, last); + auto length = get_byte_length(haystack_begin, it) - offset; + result.push_back(haystack.substr(offset, length)); + } + + ++it; + last = it; + } + + if (last != haystack_end) { + auto offset = get_byte_length(haystack_begin, last); + result.push_back(haystack.substr(offset)); + } + + return result; +} + +bool equal_z(const std::string_view left, const std::string_view right) { + if (!left.size()) { + return !right.size(); + } else if (!right.size()) { + return false; + } + auto [left_begin, left_end] = make_citer(left); + auto [right_begin, right_end] = make_citer(right); + auto left_it = left_begin; + auto right_it = right_begin; + for (; left_it != left_end && *left_it != 0 && right_it != right_end && + *right_it != 0; + ++left_it, ++right_it) { + if (*left_it != *right_it) { + return false; + } + } + return (left_it == left_end || *left_it == 0) && + (right_it == right_end || *right_it == 0); +} + +bool equal_case(const std::string_view left, const std::string_view right) { + if (!left.size()) { + return !right.size(); + } else if (!right.size()) { + return false; + } + auto [left_begin, left_end] = make_citer(left); + auto [right_begin, right_end] = make_citer(right); + return std::equal(left_begin, left_end, right_begin, right_end, + equal_ascii_case); +} + +bool equal_case_z(const std::string_view left, const std::string_view right) { + if (!left.size()) { + return !right.size(); + } else if (!right.size()) { + return false; + } + auto [left_begin, left_end] = make_citer(left); + auto [right_begin, right_end] = make_citer(right); + auto left_it = left_begin; + auto right_it = right_begin; + for (; left_it != left_end && *left_it != 0 && right_it != right_end && + *right_it != 0; + ++left_it, ++right_it) { + if (!equal_ascii_case(*left_it, *right_it)) { + return false; + } + } + return (left_it == left_end || *left_it == 0) && + (right_it == right_end || *right_it == 0); +} + +std::string_view::size_type find_any_of(const std::string_view haystack, + const std::string_view needles) { + if (needles.empty()) { + return std::string_view::size_type(0); + } else if (haystack.empty()) { + return std::string_view::npos; + } + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needles); + auto needle_count = get_count(needles); + + auto it = find_needle(haystack_begin, haystack_end, needle_begin, needle_end); + if (it == haystack_end) { + return std::string_view::npos; + } + + return std::string_view::size_type(get_byte_length(haystack_begin, it)); +} + +std::string_view::size_type find_any_of_case(const std::string_view haystack, + const std::string_view needles) { + if (needles.empty()) { + return std::string_view::size_type(0); + } else if (haystack.empty()) { + return std::string_view::npos; + } + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needles); + auto needle_count = get_count(needles); + + auto it = + find_needle_case(haystack_begin, haystack_end, needle_begin, needle_end); + if (it == haystack_end) { + return std::string_view::npos; + } + + return std::string_view::size_type(get_byte_length(haystack_begin, it)); +} + +std::string_view::size_type find_first_of(const std::string_view haystack, + const std::string_view needle) { + if (needle.empty()) { + return std::string_view::size_type(0); + } else if (haystack.empty()) { + return std::string_view::npos; + } + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needle); + auto needle_count = get_count(needle); + + auto it = haystack_begin; + for (; it != haystack_end; ++it) { + it = std::find(it, haystack_end, *needle_begin); + if (it == haystack_end) { + return std::string_view::npos; + } + + auto end = it; + for (size_t i = 0; i < needle_count; ++i) { + if (end == haystack_end) { + // not enough room in target for search + return std::string_view::npos; + } + ++end; + } + + auto [sub_start, sub_end] = make_citer(it, end); + if (std::equal(needle_begin, needle_end, sub_start, sub_end)) { + return std::string_view::size_type(get_byte_length(haystack_begin, it)); + } + } + + return std::string_view::npos; +} + +std::string_view::size_type find_first_of_case(const std::string_view haystack, + const std::string_view needle) { + if (needle.empty()) { + return std::string_view::size_type(0); + } else if (haystack.empty()) { + return std::string_view::npos; + } + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needle); + auto needle_count = get_count(needle); + auto nc = *needle_begin; + + auto it = haystack_begin; + for (; it != haystack_end; ++it) { + it = std::find_if(it, haystack_end, [&nc](const uint32_t& c) { + return equal_ascii_case(nc, c); + }); + if (it == haystack_end) { + return std::string_view::npos; + } + + auto end = it; + for (size_t i = 0; i < needle_count; ++i) { + if (end == haystack_end) { + // not enough room in target for search + return std::string_view::npos; + } + ++end; + } + + auto [sub_start, sub_end] = make_citer(it, end); + if (std::equal(needle_begin, needle_end, sub_start, sub_end, + equal_ascii_case)) { + return std::string_view::size_type(get_byte_length(haystack_begin, it)); + } + } + + return std::string_view::npos; +} + +bool starts_with(const std::string_view haystack, + const std::string_view needle) { + if (needle.empty()) { + return true; + } else if (haystack.empty()) { + return false; + } + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needle); + auto needle_count = get_count(needle); + + auto it = haystack_begin; + auto end = it; + for (size_t i = 0; i < needle_count; ++i) { + if (end == haystack_end) { + // not enough room in target for search + return false; + } + ++end; + } + + auto [sub_start, sub_end] = make_citer(it, end); + return std::equal(needle_begin, needle_end, sub_start, sub_end); +} + +bool starts_with_case(const std::string_view haystack, + const std::string_view needle) { + if (needle.empty()) { + return true; + } else if (haystack.empty()) { + return false; + } + + auto [haystack_begin, haystack_end] = make_citer(haystack); + auto [needle_begin, needle_end] = make_citer(needle); + auto needle_count = get_count(needle); + + auto it = haystack_begin; + auto end = it; + for (size_t i = 0; i < needle_count; ++i) { + if (end == haystack_end) { + // not enough room in target for search + return false; + } + ++end; + } + + auto [sub_start, sub_end] = make_citer(it, end); + return std::equal(needle_begin, needle_end, sub_start, sub_end, + equal_ascii_case); +} + +bool ends_with(const std::string_view haystack, const std::string_view needle) { + if (needle.empty()) { + return true; + } else if (haystack.empty()) { + return false; + } + + auto [haystack_begin, haystack_end] = make_criter(haystack); + auto [needle_begin, needle_end] = make_criter(needle); + auto needle_count = get_count(needle); + + auto it = haystack_begin; + auto end = it; + for (size_t i = 0; i < needle_count; ++i) { + if (end == haystack_end) { + // not enough room in target for search + return false; + } + ++end; + } + + auto [sub_start, sub_end] = make_criter(it, end); + return std::equal(needle_begin, needle_end, sub_start, sub_end); +} + +bool ends_with_case(const std::string_view haystack, + const std::string_view needle) { + if (needle.empty()) { + return true; + } else if (haystack.empty()) { + return false; + } + + auto [haystack_begin, haystack_end] = make_criter(haystack); + auto [needle_begin, needle_end] = make_criter(needle); + auto needle_count = get_count(needle); + + auto it = haystack_begin; + auto end = it; + for (size_t i = 0; i < needle_count; ++i) { + if (end == haystack_end) { + // not enough room in target for search + return false; + } + ++end; + } + + auto [sub_start, sub_end] = make_criter(it, end); + return std::equal(needle_begin, needle_end, sub_start, sub_end, + equal_ascii_case); +} + +std::vector split_path(const std::string_view path) { + return split(path, u8"\\/"); +} + +std::string join_paths(const std::string_view left_path, + const std::string_view right_path, char32_t sep) { + if (!left_path.length()) { + return std::string(right_path); + } else if (!right_path.length()) { + return std::string(left_path); + } + + auto [it, end] = make_criter(left_path); + + std::string result = std::string(left_path); + if (*it != static_cast(sep)) { + utfcpp::append(sep, result); + } + return result + std::string(right_path); +} + +std::string join_paths(std::vector paths, char32_t sep) { + std::string result; + for (const auto& path : paths) { + result = join_paths(result, path, sep); + } + return result; +} + +std::string fix_path_separators(const std::string_view path, char32_t new_sep) { + if (path.empty()) { + return std::string(); + } + + // Swap all separators to new_sep. + const char32_t old_sep = new_sep == U'\\' ? U'/' : U'\\'; + + auto [path_begin, path_end] = make_citer(path); + + std::string result; + auto it = path_begin; + auto last = it; + for (;;) { + it = std::find(it, path_end, uint32_t(old_sep)); + if (it == path_end) { + break; + } + + if (it != last) { + auto offset = get_byte_length(path_begin, last); + auto length = get_byte_length(path_begin, it) - offset; + result += path.substr(offset, length); + utfcpp::append(new_sep, result); + } + + ++it; + last = it; + } + + if (last == path_begin) { + return std::string(path); + } + + if (last != path_end) { + auto offset = get_byte_length(path_begin, last); + result += path.substr(offset); + } + + return result; +} + +std::string find_name_from_path(const std::string_view path, char32_t sep) { + if (path.empty()) { + return std::string(); + } + + auto [begin, end] = make_criter(path); + + auto it = begin; + size_t padding = 0; + if (*it == uint32_t(sep)) { + ++it; + padding = 1; + } + + if (it == end) { + return std::string(); + } + + it = std::find(it, end, uint32_t(sep)); + if (it == end) { + return std::string(path.substr(0, path.size() - padding)); + } + + auto length = get_byte_length(begin, it); + auto offset = path.length() - length; + return std::string(path.substr(offset, length - padding)); +} + +std::string find_base_name_from_path(const std::string_view path, + char32_t sep) { + auto name = find_name_from_path(path, sep); + if (!name.size()) { + return std::string(); + } + + auto [begin, end] = make_criter(name); + + auto it = std::find(begin, end, uint32_t('.')); + if (it == end) { + return name; + } + + it++; + if (it == end) { + return std::string(); + } + + auto length = name.length() - get_byte_length(begin, it); + return std::string(name.substr(0, length)); +} + +std::string find_base_path(const std::string_view path, char32_t sep) { + if (path.empty()) { + return std::string(); + } + + auto [begin, end] = make_criter(path); + + auto it = begin; + if (*it == uint32_t(sep)) { + ++it; + } + + it = std::find(it, end, uint32_t(sep)); + if (it == end) { + return std::string(); + } + + ++it; + if (it == end) { + return std::string(); + } + + auto length = path.length() - get_byte_length(begin, it); + return std::string(path.substr(0, length)); +} + +std::string canonicalize_path(const std::string_view path, char32_t sep) { + if (path.empty()) { + return std::string(); + } + + auto parts = split_path(path); + + std::vector::size_type> indices(parts.size()); + std::iota(indices.begin(), indices.end(), 0); + + for (auto it = indices.begin(); it != indices.end();) { + const auto& part = parts[*it]; + if (part == ".") { + // Potential marker for current directory. + it = indices.erase(it); + } else if (part == "..") { + // Ensure we don't override the device name. + if (it != indices.begin()) { + auto prev = std::prev(it); + if (!ends_with(parts[*prev], ":")) { + it = indices.erase(prev); + } + } + it = indices.erase(it); + } else { + ++it; + } + } + + std::string result; + for (auto index : indices) { + result = join_paths(result, parts[index], sep); + } + + return result == "." || result == ".." ? std::string() : result; +} // namespace utf8 + +} // namespace xe::utf8 diff --git a/src/xenia/base/utf8.h b/src/xenia/base/utf8.h new file mode 100644 index 000000000..65c6454fe --- /dev/null +++ b/src/xenia/base/utf8.h @@ -0,0 +1,137 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_BASE_UTF8_H_ +#define XENIA_BASE_UTF8_H_ + +#include +#include + +#include "xenia/base/platform.h" + +namespace xe::utf8 { + +std::string lower_ascii(const std::string_view view); +std::string upper_ascii(const std::string_view view); + +size_t hash_fnv1a(const std::string_view view); +size_t hash_fnv1a_case(const std::string_view view); + +// Splits the given string on any delimiters and returns all parts. +std::vector split(const std::string_view path, + const std::string_view delimiters); + +bool equal_z(const std::string_view left, const std::string_view right); + +bool equal_case(const std::string_view left, const std::string_view right); + +bool equal_case_z(const std::string_view left, const std::string_view right); + +std::string_view::size_type find_any_of(const std::string_view haystack, + const std::string_view needles); + +std::string_view::size_type find_any_of_case(const std::string_view haystack, + const std::string_view needles); + +std::string_view::size_type find_first_of(const std::string_view haystack, + const std::string_view needle); + +// find_first_of string, case insensitive. +std::string_view::size_type find_first_of_case(const std::string_view haystack, + const std::string_view needle); + +bool starts_with(const std::string_view haystack, + const std::string_view needle); + +bool starts_with_case(const std::string_view haystack, + const std::string_view needle); + +bool ends_with(const std::string_view haystack, const std::string_view needle); + +bool ends_with_case(const std::string_view haystack, + const std::string_view needle); + +// Splits the given path on any valid path separator and returns all parts. +std::vector split_path(const std::string_view path); + +// Joins two path segments with the given separator. +std::string join_paths(const std::string_view left_path, + const std::string_view right_path, + char32_t sep = kPathSeparator); + +std::string join_paths(std::vector paths, + char32_t sep = kPathSeparator); + +inline std::string join_paths( + std::initializer_list paths, + char32_t sep = kPathSeparator) { + std::string result; + for (auto path : paths) { + result = join_paths(result, path, sep); + } + return result; +} + +inline std::string join_guest_paths(const std::string_view left_path, + const std::string_view right_path) { + return join_paths(left_path, right_path, kGuestPathSeparator); +} + +inline std::string join_guest_paths(std::vector paths) { + return join_paths(paths, kGuestPathSeparator); +} + +inline std::string join_guest_paths( + std::initializer_list paths) { + return join_paths(paths, kGuestPathSeparator); +} + +// Replaces all path separators with the given value and removes redundant +// separators. +std::string fix_path_separators(const std::string_view path, + char32_t new_sep = kPathSeparator); + +inline std::string fix_guest_path_separators(const std::string_view path) { + return fix_path_separators(path, kGuestPathSeparator); +} + +// Find the top directory name or filename from a path. +std::string find_name_from_path(const std::string_view path, + char32_t sep = kPathSeparator); + +inline std::string find_name_from_guest_path(const std::string_view path) { + return find_name_from_path(path, kGuestPathSeparator); +} + +std::string find_base_name_from_path(const std::string_view path, + char32_t sep = kPathSeparator); + +inline std::string find_base_name_from_guest_path(const std::string_view path) { + return find_base_name_from_path(path, kGuestPathSeparator); +} + +// Get parent path of the given directory or filename. +std::string find_base_path(const std::string_view path, + char32_t sep = kPathSeparator); + +inline std::string find_base_guest_path(const std::string_view path) { + return find_base_path(path, kGuestPathSeparator); +} + +// Canonicalizes a path, removing ..'s. +std::string canonicalize_path(const std::string_view path, + char32_t sep = kPathSeparator); + +inline std::string canonicalize_guest_path(const std::string_view path) { + return canonicalize_path(path, kGuestPathSeparator); +} + +} // namespace xe::utf8 + +#endif // XENIA_BASE_UTF8_H_ diff --git a/src/xenia/base/vec128.cc b/src/xenia/base/vec128.cc index 84bff1457..70562dda1 100644 --- a/src/xenia/base/vec128.cc +++ b/src/xenia/base/vec128.cc @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #include #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/math.h" #include "xenia/base/platform.h" #include "xenia/base/vec128.h" @@ -17,10 +18,7 @@ namespace xe { std::string to_string(const vec128_t& value) { - char buffer[128]; - std::snprintf(buffer, sizeof(buffer), "(%g, %g, %g, %g)", value.x, value.y, - value.z, value.w); - return std::string(buffer); + return fmt::format("({}, {}, {}, {})", value.x, value.y, value.z, value.w); } } // namespace xe diff --git a/src/xenia/config.cc b/src/xenia/config.cc index 92582d08b..a3e57930f 100644 --- a/src/xenia/config.cc +++ b/src/xenia/config.cc @@ -1,18 +1,26 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + #include "config.h" -#include "cpptoml/include/cpptoml.h" + +#include "third_party/cpptoml/include/cpptoml.h" +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/cvar.h" #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/string.h" -std::shared_ptr ParseFile(const std::wstring& filename) { -#if XE_PLATFORM_WIN32 +std::shared_ptr ParseFile( + const std::filesystem::path& filename) { std::ifstream file(filename); -#else - std::ifstream file(xe::to_string(filename)); -#endif if (!file.is_open()) { - throw cpptoml::parse_exception(xe::to_string(filename) + + throw cpptoml::parse_exception(xe::path_to_utf8(filename) + " could not be opened for parsing"); } cpptoml::parser p(file); @@ -21,10 +29,10 @@ std::shared_ptr ParseFile(const std::wstring& filename) { CmdVar(config, "", "Specifies the target config to load."); namespace config { -std::wstring config_name = L"xenia.config.toml"; -std::wstring config_folder; -std::wstring config_path; -std::wstring game_config_suffix = L".config.toml"; +std::string config_name = "xenia.config.toml"; +std::filesystem::path config_folder; +std::filesystem::path config_path; +std::string game_config_suffix = ".config.toml"; bool sortCvar(cvar::IConfigVar* a, cvar::IConfigVar* b) { if (a->category() < b->category()) return true; @@ -33,17 +41,18 @@ bool sortCvar(cvar::IConfigVar* a, cvar::IConfigVar* b) { return false; } -std::shared_ptr ParseConfig(const std::wstring& config_path) { +std::shared_ptr ParseConfig( + const std::filesystem::path& config_path) { try { return ParseFile(config_path); } catch (cpptoml::parse_exception e) { - xe::FatalError(L"Failed to parse config file '%s':\n\n%s", - config_path.c_str(), xe::to_wstring(e.what()).c_str()); + xe::FatalError(fmt::format("Failed to parse config file '{}':\n\n{}", + xe::path_to_utf8(config_path), e.what())); return nullptr; } } -void ReadConfig(const std::wstring& file_path) { +void ReadConfig(const std::filesystem::path& file_path) { const auto config = ParseConfig(file_path); for (auto& it : *cvar::ConfigVars) { auto config_var = static_cast(it.second); @@ -52,10 +61,10 @@ void ReadConfig(const std::wstring& file_path) { config_var->LoadConfigValue(config->get_qualified(config_key)); } } - XELOGI("Loaded config: %S", file_path.c_str()); + XELOGI("Loaded config: %s", xe::path_to_utf8(file_path).c_str()); } -void ReadGameConfig(std::wstring file_path) { +void ReadGameConfig(const std::filesystem::path& file_path) { const auto config = ParseConfig(file_path); for (auto& it : *cvar::ConfigVars) { auto config_var = static_cast(it.second); @@ -64,7 +73,7 @@ void ReadGameConfig(std::wstring file_path) { config_var->LoadGameConfigValue(config->get_qualified(config_key)); } } - XELOGI("Loaded game config: %S", file_path.c_str()); + XELOGI("Loaded game config: %s", xe::path_to_utf8(file_path).c_str()); } void SaveConfig() { @@ -84,31 +93,29 @@ void SaveConfig() { output << std::endl; } last_category = config_var->category(); - output << xe::format_string("[%s]\n", last_category.c_str()); + output << fmt::format("[{}]\n", last_category); } auto value = config_var->config_value(); - if (value.find('\n') == std::string::npos) { + if (xe::utf8::find_any_of(value, "\n") == std::string_view::npos) { output << std::left << std::setw(40) << std::setfill(' ') - << xe::format_string("%s = %s", config_var->name().c_str(), - config_var->config_value().c_str()); + << fmt::format("{} = {}", config_var->name(), + config_var->config_value()); } else { - auto lines = xe::split_string(value, "\n"); + auto lines = xe::utf8::split(value, "\n"); auto first_it = lines.cbegin(); - output << xe::format_string("%s = %s\n", config_var->name().c_str(), - (*first_it).c_str()); + output << fmt::format("{} = {}\n", config_var->name(), *first_it); auto last_it = std::prev(lines.cend()); for (auto it = std::next(first_it); it != last_it; ++it) { - output << (*it).c_str() << "\n"; + output << *it << "\n"; } - output << std::left << std::setw(40) << std::setfill(' ') - << (*last_it).c_str(); + output << std::left << std::setw(40) << std::setfill(' ') << *last_it; } - output << xe::format_string("\t# %s\n", config_var->description().c_str()); + output << fmt::format("\t# {}\n", config_var->description()); } if (xe::filesystem::PathExists(config_path)) { - std::ifstream existingConfigStream(xe::to_string(config_path).c_str()); + std::ifstream existingConfigStream(config_path); const std::string existingConfig( (std::istreambuf_iterator(existingConfigStream)), std::istreambuf_iterator()); @@ -119,20 +126,16 @@ void SaveConfig() { // save the config file xe::filesystem::CreateParentFolder(config_path); std::ofstream file; -#if XE_PLATFORM_WIN32 file.open(config_path, std::ios::out | std::ios::trunc); -#else - file.open(xe::to_string(config_path), std::ios::out | std::ios::trunc); -#endif file << output.str(); file.close(); } -void SetupConfig(const std::wstring& config_folder) { +void SetupConfig(const std::filesystem::path& config_folder) { config::config_folder = config_folder; // check if the user specified a specific config to load if (!cvars::config.empty()) { - config_path = xe::to_wstring(cvars::config); + config_path = xe::to_path(cvars::config); if (xe::filesystem::PathExists(config_path)) { ReadConfig(config_path); return; @@ -141,7 +144,7 @@ void SetupConfig(const std::wstring& config_folder) { // if the user specified a --config argument, but the file doesn't exist, // let's also load the default config if (!config_folder.empty()) { - config_path = xe::join_paths(config_folder, config_name); + config_path = config_folder / config_name; if (xe::filesystem::PathExists(config_path)) { ReadConfig(config_path); } @@ -151,9 +154,10 @@ void SetupConfig(const std::wstring& config_folder) { } } -void LoadGameConfig(const std::wstring& title_id) { - const auto game_config_path = xe::join_paths( - xe::join_paths(config_folder, L"config"), title_id + game_config_suffix); +void LoadGameConfig(const std::string_view title_id) { + const auto game_config_folder = config_folder / "config"; + const auto game_config_path = + game_config_folder / (std::string(title_id) + game_config_suffix); if (xe::filesystem::PathExists(game_config_path)) { ReadGameConfig(game_config_path); } diff --git a/src/xenia/config.h b/src/xenia/config.h index 0a1a1ae5f..63ef265d5 100644 --- a/src/xenia/config.h +++ b/src/xenia/config.h @@ -1,10 +1,20 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + #ifndef XENIA_CONFIG_H_ #define XENIA_CONFIG_H_ -#include + +#include namespace config { -void SetupConfig(const std::wstring& config_folder); -void LoadGameConfig(const std::wstring& title_id); +void SetupConfig(const std::filesystem::path& config_folder); +void LoadGameConfig(const std::string_view title_id); } // namespace config #endif // XENIA_CONFIG_H_ diff --git a/src/xenia/cpu/backend/code_cache.h b/src/xenia/cpu/backend/code_cache.h index d7dab12fd..03d70114f 100644 --- a/src/xenia/cpu/backend/code_cache.h +++ b/src/xenia/cpu/backend/code_cache.h @@ -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. * ****************************************************************************** */ @@ -23,7 +23,7 @@ class CodeCache { CodeCache() = default; virtual ~CodeCache() = default; - virtual std::wstring file_name() const = 0; + virtual const std::filesystem::path& file_name() const = 0; virtual uint32_t base_address() const = 0; virtual uint32_t total_size() const = 0; diff --git a/src/xenia/cpu/backend/x64/premake5.lua b/src/xenia/cpu/backend/x64/premake5.lua index ebbc19765..f2a990f29 100644 --- a/src/xenia/cpu/backend/x64/premake5.lua +++ b/src/xenia/cpu/backend/x64/premake5.lua @@ -8,6 +8,7 @@ project("xenia-cpu-backend-x64") language("C++") links({ "capstone", + "fmt", "xenia-base", "xenia-cpu", }) diff --git a/src/xenia/cpu/backend/x64/x64_assembler.cc b/src/xenia/cpu/backend/x64/x64_assembler.cc index bf9ce1c52..4c50a5177 100644 --- a/src/xenia/cpu/backend/x64/x64_assembler.cc +++ b/src/xenia/cpu/backend/x64/x64_assembler.cc @@ -86,7 +86,7 @@ bool X64Assembler::Assemble(GuestFunction* function, HIRBuilder* builder, if (debug_info_flags & DebugInfoFlags::kDebugInfoDisasmMachineCode) { DumpMachineCode(machine_code, code_size, function->source_map(), &string_buffer_); - debug_info->set_machine_code_disasm(string_buffer_.ToString()); + debug_info->set_machine_code_disasm(strdup(string_buffer_.buffer())); string_buffer_.Reset(); } @@ -126,7 +126,7 @@ void X64Assembler::DumpMachineCode( if (code_offset >= next_code_offset && source_map_index < source_map.size()) { auto& source_map_entry = source_map[source_map_index]; - str->AppendFormat("%.8X ", source_map_entry.guest_address); + str->AppendFormat("{:08X} ", source_map_entry.guest_address); ++source_map_index; next_code_offset = source_map_index < source_map.size() ? source_map[source_map_index].code_offset @@ -135,7 +135,7 @@ void X64Assembler::DumpMachineCode( str->Append(" "); } - str->AppendFormat("%.8X %-6s %s\n", uint32_t(insn.address), + str->AppendFormat("{:08X} {:<6} {}\n", uint32_t(insn.address), insn.mnemonic, insn.op_str); } } diff --git a/src/xenia/cpu/backend/x64/x64_code_cache.cc b/src/xenia/cpu/backend/x64/x64_code_cache.cc index 021d51c62..6903536af 100644 --- a/src/xenia/cpu/backend/x64/x64_code_cache.cc +++ b/src/xenia/cpu/backend/x64/x64_code_cache.cc @@ -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. * ****************************************************************************** */ @@ -17,6 +17,7 @@ #pragma comment(lib, "../third_party/vtune/lib64/jitprofiling.lib") #endif +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/clock.h" #include "xenia/base/logging.h" @@ -61,8 +62,8 @@ bool X64CodeCache::Initialize() { } // Create mmap file. This allows us to share the code cache with the debugger. - file_name_ = std::wstring(L"Local\\xenia_code_cache_") + - std::to_wstring(Clock::QueryHostTickCount()); + file_name_ = + fmt::format("Local\\xenia_code_cache_{}", Clock::QueryHostTickCount()); mapping_ = xe::memory::CreateFileMappingHandle( file_name_, kGeneratedCodeSize, xe::memory::PageAccess::kExecuteReadWrite, false); diff --git a/src/xenia/cpu/backend/x64/x64_code_cache.h b/src/xenia/cpu/backend/x64/x64_code_cache.h index 5593b0911..1f1473094 100644 --- a/src/xenia/cpu/backend/x64/x64_code_cache.h +++ b/src/xenia/cpu/backend/x64/x64_code_cache.h @@ -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,7 +45,7 @@ class X64CodeCache : public CodeCache { virtual bool Initialize(); - std::wstring file_name() const override { return file_name_; } + const std::filesystem::path& file_name() const override { return file_name_; } uint32_t base_address() const override { return kGeneratedCodeBase; } uint32_t total_size() const override { return kGeneratedCodeSize; } @@ -99,7 +99,7 @@ class X64CodeCache : public CodeCache { const EmitFunctionInfo& func_info, void* code_address, UnwindReservation unwind_reservation) {} - std::wstring file_name_; + std::filesystem::path file_name_; xe::memory::FileMappingHandle mapping_ = nullptr; // NOTE: the global critical region must be held when manipulating the offsets diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index 91de2ef9b..2af7dadc2 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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. * ****************************************************************************** */ @@ -10,9 +10,11 @@ #include "xenia/cpu/backend/x64/x64_emitter.h" #include + #include #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/atomic.h" #include "xenia/base/debugging.h" @@ -476,8 +478,8 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, uint64_t UndefinedCallExtern(void* raw_context, uint64_t function_ptr) { auto function = reinterpret_cast(function_ptr); if (!cvars::ignore_undefined_externs) { - xe::FatalError("undefined extern call to %.8X %s", function->address(), - function->name().c_str()); + xe::FatalError(fmt::format("undefined extern call to {:08X} {}", + function->address(), function->name().c_str())); } else { XELOGE("undefined extern call to %.8X %s", function->address(), function->name().c_str()); diff --git a/src/xenia/cpu/compiler/passes/finalization_pass.cc b/src/xenia/cpu/compiler/passes/finalization_pass.cc index f6796822a..ddd22a646 100644 --- a/src/xenia/cpu/compiler/passes/finalization_pass.cc +++ b/src/xenia/cpu/compiler/passes/finalization_pass.cc @@ -2,13 +2,14 @@ ****************************************************************************** * 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/cpu/compiler/passes/finalization_pass.h" +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/profiling.h" #include "xenia/cpu/backend/backend.h" #include "xenia/cpu/compiler/compiler.h" @@ -43,9 +44,11 @@ bool FinalizationPass::Run(HIRBuilder* builder) { auto label = block->label_head; while (label) { if (!label->name) { - const size_t label_len = 6 + 4 + 1; - char* name = reinterpret_cast(arena->Alloc(label_len)); - snprintf(name, label_len, "_label%d", label->id); + const size_t label_len = 6 + 4; + char* name = reinterpret_cast(arena->Alloc(label_len + 1)); + assert_true(label->id <= 9999); + auto end = fmt::format_to_n(name, label_len, "_label{}", label->id); + name[end.size] = '\0'; label->name = name; } label = label->next; diff --git a/src/xenia/cpu/elf_module.cc b/src/xenia/cpu/elf_module.cc index 2093bbe6e..e5c3c565c 100644 --- a/src/xenia/cpu/elf_module.cc +++ b/src/xenia/cpu/elf_module.cc @@ -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. * ****************************************************************************** */ @@ -58,7 +58,7 @@ bool ElfModule::is_executable() const { return hdr->e_entry != 0; } -bool ElfModule::Load(const std::string& name, const std::string& path, +bool ElfModule::Load(const std::string_view name, const std::string_view path, const void* elf_addr, size_t elf_length) { name_ = name; path_ = path; diff --git a/src/xenia/cpu/elf_module.h b/src/xenia/cpu/elf_module.h index c8bbd3cb0..2951e0997 100644 --- a/src/xenia/cpu/elf_module.h +++ b/src/xenia/cpu/elf_module.h @@ -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. * ****************************************************************************** */ @@ -34,7 +34,7 @@ class ElfModule : public xe::cpu::Module { bool is_executable() const override; const std::string& path() const { return path_; } - bool Load(const std::string& name, const std::string& path, + bool Load(const std::string_view name, const std::string_view path, const void* elf_addr, size_t elf_length); bool Unload(); diff --git a/src/xenia/cpu/export_resolver.cc b/src/xenia/cpu/export_resolver.cc index 68028e7a2..31e34feca 100644 --- a/src/xenia/cpu/export_resolver.cc +++ b/src/xenia/cpu/export_resolver.cc @@ -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,20 +11,15 @@ #include "xenia/base/assert.h" #include "xenia/base/math.h" +#include "xenia/base/string.h" namespace xe { namespace cpu { -ExportResolver::Table::Table(const char* module_name, +ExportResolver::Table::Table(const std::string_view module_name, const std::vector* exports_by_ordinal) : exports_by_ordinal_(exports_by_ordinal) { - auto dot_pos = std::strrchr(module_name, '.'); - if (dot_pos != nullptr) { - std::strncpy(module_name_, module_name, - static_cast(dot_pos - module_name)); - } else { - std::strncpy(module_name_, module_name, xe::countof(module_name_) - 1); - } + module_name_ = utf8::find_base_name_from_guest_path(module_name); exports_by_name_.reserve(exports_by_ordinal_->size()); for (size_t i = 0; i < exports_by_ordinal_->size(); ++i) { @@ -43,7 +38,8 @@ ExportResolver::ExportResolver() = default; ExportResolver::~ExportResolver() = default; void ExportResolver::RegisterTable( - const char* module_name, const std::vector* exports) { + const std::string_view module_name, + const std::vector* exports) { tables_.emplace_back(module_name, exports); all_exports_by_name_.reserve(all_exports_by_name_.size() + exports->size()); @@ -58,11 +54,10 @@ void ExportResolver::RegisterTable( [](Export* a, Export* b) { return std::strcmp(a->name, b->name) <= 0; }); } -Export* ExportResolver::GetExportByOrdinal(const char* module_name, +Export* ExportResolver::GetExportByOrdinal(const std::string_view module_name, uint16_t ordinal) { for (const auto& table : tables_) { - if (std::strncmp(module_name, table.module_name(), - std::strlen(table.module_name())) == 0) { + if (xe::utf8::starts_with_case(module_name, table.module_name())) { if (ordinal > table.exports_by_ordinal().size()) { return nullptr; } @@ -72,7 +67,7 @@ Export* ExportResolver::GetExportByOrdinal(const char* module_name, return nullptr; } -void ExportResolver::SetVariableMapping(const char* module_name, +void ExportResolver::SetVariableMapping(const std::string_view module_name, uint16_t ordinal, uint32_t value) { auto export_entry = GetExportByOrdinal(module_name, ordinal); assert_not_null(export_entry); @@ -80,7 +75,7 @@ void ExportResolver::SetVariableMapping(const char* module_name, export_entry->variable_ptr = value; } -void ExportResolver::SetFunctionMapping(const char* module_name, +void ExportResolver::SetFunctionMapping(const std::string_view module_name, uint16_t ordinal, xe_kernel_export_shim_fn shim) { auto export_entry = GetExportByOrdinal(module_name, ordinal); @@ -89,7 +84,7 @@ void ExportResolver::SetFunctionMapping(const char* module_name, export_entry->function_data.shim = shim; } -void ExportResolver::SetFunctionMapping(const char* module_name, +void ExportResolver::SetFunctionMapping(const std::string_view module_name, uint16_t ordinal, ExportTrampoline trampoline) { auto export_entry = GetExportByOrdinal(module_name, ordinal); diff --git a/src/xenia/cpu/export_resolver.h b/src/xenia/cpu/export_resolver.h index c17807a3e..5b1bdc1f8 100644 --- a/src/xenia/cpu/export_resolver.h +++ b/src/xenia/cpu/export_resolver.h @@ -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. * ****************************************************************************** */ @@ -117,9 +117,10 @@ class ExportResolver { public: class Table { public: - Table(const char* module_name, const std::vector* exports); + Table(const std::string_view module_name, + const std::vector* exports); - const char* module_name() const { return module_name_; } + const std::string& module_name() const { return module_name_; } const std::vector& exports_by_ordinal() const { return *exports_by_ordinal_; } @@ -128,7 +129,7 @@ class ExportResolver { } private: - char module_name_[32] = {0}; + std::string module_name_; const std::vector* exports_by_ordinal_ = nullptr; std::vector exports_by_name_; }; @@ -136,20 +137,21 @@ class ExportResolver { ExportResolver(); ~ExportResolver(); - void RegisterTable(const char* module_name, + void RegisterTable(const std::string_view module_name, const std::vector* exports); const std::vector& tables() const { return tables_; } const std::vector& all_exports_by_name() const { return all_exports_by_name_; } - Export* GetExportByOrdinal(const char* module_name, uint16_t ordinal); + Export* GetExportByOrdinal(const std::string_view module_name, + uint16_t ordinal); - void SetVariableMapping(const char* module_name, uint16_t ordinal, + void SetVariableMapping(const std::string_view module_name, uint16_t ordinal, uint32_t value); - void SetFunctionMapping(const char* module_name, uint16_t ordinal, + void SetFunctionMapping(const std::string_view module_name, uint16_t ordinal, xe_kernel_export_shim_fn shim); - void SetFunctionMapping(const char* module_name, uint16_t ordinal, + void SetFunctionMapping(const std::string_view module_name, uint16_t ordinal, ExportTrampoline trampoline); private: diff --git a/src/xenia/cpu/hir/hir_builder.cc b/src/xenia/cpu/hir/hir_builder.cc index 1a1c60b5d..b1a908791 100644 --- a/src/xenia/cpu/hir/hir_builder.cc +++ b/src/xenia/cpu/hir/hir_builder.cc @@ -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. * ****************************************************************************** */ @@ -110,25 +110,25 @@ void HIRBuilder::DumpValue(StringBuffer* str, Value* value) { if (value->IsConstant()) { switch (value->type) { case INT8_TYPE: - str->AppendFormat("%X", value->constant.i8); + str->AppendFormat("{:X}", value->constant.i8); break; case INT16_TYPE: - str->AppendFormat("%X", value->constant.i16); + str->AppendFormat("{:X}", value->constant.i16); break; case INT32_TYPE: - str->AppendFormat("%X", value->constant.i32); + str->AppendFormat("{:X}", value->constant.i32); break; case INT64_TYPE: - str->AppendFormat("%" PRIX64, value->constant.i64); + str->AppendFormat("{:X}", value->constant.i64); break; case FLOAT32_TYPE: - str->AppendFormat("%F", value->constant.f32); + str->AppendFormat("{:F}", value->constant.f32); break; case FLOAT64_TYPE: - str->AppendFormat("%F", value->constant.f64); + str->AppendFormat("{:F}", value->constant.f64); break; case VEC128_TYPE: - str->AppendFormat("(%F,%F,%F,%F)", value->constant.v128.x, + str->AppendFormat("({:F},{:F},{:F},{:F})", value->constant.v128.x, value->constant.v128.y, value->constant.v128.z, value->constant.v128.w); break; @@ -140,10 +140,10 @@ void HIRBuilder::DumpValue(StringBuffer* str, Value* value) { static const char* type_names[] = { "i8", "i16", "i32", "i64", "f32", "f64", "v128", }; - str->AppendFormat("v%d.%s", value->ordinal, type_names[value->type]); + str->AppendFormat("v{}.{}", value->ordinal, type_names[value->type]); } if (value->reg.index != -1) { - str->AppendFormat("<%s%d>", value->reg.set->name, value->reg.index); + str->AppendFormat("<{}{}>", value->reg.set->name, value->reg.index); } } @@ -156,11 +156,11 @@ void HIRBuilder::DumpOp(StringBuffer* str, OpcodeSignatureType sig_type, if (op->label->name) { str->Append(op->label->name); } else { - str->AppendFormat("label%d", op->label->id); + str->AppendFormat("label{}", op->label->id); } break; case OPCODE_SIG_TYPE_O: - str->AppendFormat("+%lld", op->offset); + str->AppendFormat("+{}", op->offset); break; case OPCODE_SIG_TYPE_S: if (true) { @@ -176,7 +176,7 @@ void HIRBuilder::DumpOp(StringBuffer* str, OpcodeSignatureType sig_type, void HIRBuilder::Dump(StringBuffer* str) { if (attributes_) { - str->AppendFormat("; attributes = %.8X\n", attributes_); + str->AppendFormat("; attributes = {:08X}\n", attributes_); } for (auto it = locals_.begin(); it != locals_.end(); ++it) { @@ -192,16 +192,16 @@ void HIRBuilder::Dump(StringBuffer* str) { if (block == block_head_) { str->Append(":\n"); } else if (!block->label_head) { - str->AppendFormat(":\n", block_ordinal); + str->AppendFormat(":\n", block_ordinal); } block_ordinal++; Label* label = block->label_head; while (label) { if (label->name) { - str->AppendFormat("%s:\n", label->name); + str->AppendFormat("{}:\n", label->name); } else { - str->AppendFormat("label%d:\n", label->id); + str->AppendFormat("label{}:\n", label->id); } label = label->next; } @@ -210,13 +210,13 @@ void HIRBuilder::Dump(StringBuffer* str) { while (incoming_edge) { auto src_label = incoming_edge->src->label_head; if (src_label && src_label->name) { - str->AppendFormat(" ; in: %s", src_label->name); + str->AppendFormat(" ; in: {}", src_label->name); } else if (src_label) { - str->AppendFormat(" ; in: label%d", src_label->id); + str->AppendFormat(" ; in: label{}", src_label->id); } else { - str->AppendFormat(" ; in: ", incoming_edge->src->ordinal); + str->AppendFormat(" ; in: ", incoming_edge->src->ordinal); } - str->AppendFormat(", dom:%d, uncond:%d\n", + str->AppendFormat(", dom:{}, uncond:{}\n", (incoming_edge->flags & Edge::DOMINATES) ? 1 : 0, (incoming_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0); incoming_edge = incoming_edge->incoming_next; @@ -225,13 +225,13 @@ void HIRBuilder::Dump(StringBuffer* str) { while (outgoing_edge) { auto dest_label = outgoing_edge->dest->label_head; if (dest_label && dest_label->name) { - str->AppendFormat(" ; out: %s", dest_label->name); + str->AppendFormat(" ; out: {}", dest_label->name); } else if (dest_label) { - str->AppendFormat(" ; out: label%d", dest_label->id); + str->AppendFormat(" ; out: label{}", dest_label->id); } else { - str->AppendFormat(" ; out: ", outgoing_edge->dest->ordinal); + str->AppendFormat(" ; out: ", outgoing_edge->dest->ordinal); } - str->AppendFormat(", dom:%d, uncond:%d\n", + str->AppendFormat(", dom:{}, uncond:{}\n", (outgoing_edge->flags & Edge::DOMINATES) ? 1 : 0, (outgoing_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0); outgoing_edge = outgoing_edge->outgoing_next; @@ -244,7 +244,7 @@ void HIRBuilder::Dump(StringBuffer* str) { continue; } if (i->opcode == &OPCODE_COMMENT_info) { - str->AppendFormat(" ; %s\n", reinterpret_cast(i->src1.offset)); + str->AppendFormat(" ; {}\n", reinterpret_cast(i->src1.offset)); i = i->next; continue; } @@ -260,7 +260,7 @@ void HIRBuilder::Dump(StringBuffer* str) { str->Append(" = "); } if (i->flags) { - str->AppendFormat("%s.%d", info->name, i->flags); + str->AppendFormat("{}.{}", info->name, i->flags); } else { str->Append(info->name); } @@ -734,13 +734,14 @@ Value* HIRBuilder::CloneValue(Value* source) { return value; } -void HIRBuilder::Comment(const char* value) { - size_t length = std::strlen(value); - if (!length) { +void HIRBuilder::Comment(std::string_view value) { + if (value.empty()) { return; } - void* p = arena_->Alloc(length + 1); - std::memcpy(p, value, length + 1); + auto size = value.size(); + auto p = reinterpret_cast(arena_->Alloc(size + 1)); + std::memcpy(p, value.data(), size); + p[size] = '\0'; Instr* i = AppendInstr(OPCODE_COMMENT_info, 0); i->src1.offset = (uint64_t)p; i->src2.value = i->src3.value = NULL; @@ -750,22 +751,16 @@ void HIRBuilder::Comment(const StringBuffer& value) { if (!value.length()) { return; } - void* p = arena_->Alloc(value.length() + 1); - std::memcpy(p, value.GetString(), value.length() + 1); + auto size = value.length(); + auto p = reinterpret_cast(arena_->Alloc(size + 1)); + std::memcpy(p, value.buffer(), size); + p[size] = '\0'; Instr* i = AppendInstr(OPCODE_COMMENT_info, 0); i->src1.offset = (uint64_t)p; i->src2.value = i->src3.value = NULL; } -void HIRBuilder::CommentFormat(const char* format, ...) { - static const uint32_t kMaxCommentSize = 1024; - char* p = reinterpret_cast(arena_->Alloc(kMaxCommentSize)); - va_list args; - va_start(args, format); - size_t chars_written = vsnprintf(p, kMaxCommentSize - 1, format, args); - va_end(args); - size_t rewind = kMaxCommentSize - chars_written - 1; - arena_->Rewind(rewind); +void HIRBuilder::CommentBuffer(const char* p) { Instr* i = AppendInstr(OPCODE_COMMENT_info, 0); i->src1.offset = (uint64_t)p; i->src2.value = i->src3.value = NULL; diff --git a/src/xenia/cpu/hir/hir_builder.h b/src/xenia/cpu/hir/hir_builder.h index d728facbd..00661e4c2 100644 --- a/src/xenia/cpu/hir/hir_builder.h +++ b/src/xenia/cpu/hir/hir_builder.h @@ -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. * ****************************************************************************** */ @@ -12,6 +12,7 @@ #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/arena.h" #include "xenia/base/string_buffer.h" #include "xenia/cpu/hir/block.h" @@ -68,9 +69,19 @@ class HIRBuilder { // static allocations: // Value* AllocStatic(size_t length); - void Comment(const char* value); + void Comment(const std::string_view value); void Comment(const StringBuffer& value); - void CommentFormat(const char* format, ...); + + template + void CommentFormat(const std::string_view format, const Args&... args) { + static const uint32_t kMaxCommentSize = 1024; + char* p = reinterpret_cast(arena_->Alloc(kMaxCommentSize)); + auto result = fmt::format_to_n(p, kMaxCommentSize - 1, format, args...); + p[result.size] = '\0'; + size_t rewind = kMaxCommentSize - 1 - result.size; + arena_->Rewind(rewind); + CommentBuffer(p); + } void Nop(); @@ -261,6 +272,7 @@ class HIRBuilder { void EndBlock(); bool IsUnconditionalJump(Instr* instr); Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags, Value* dest = 0); + void CommentBuffer(const char* p); Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2); Value* VectorCompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2, TypeName part_type); diff --git a/src/xenia/cpu/ppc/ppc_context.cc b/src/xenia/cpu/ppc/ppc_context.cc index cca51098d..17a609acb 100644 --- a/src/xenia/cpu/ppc/ppc_context.cc +++ b/src/xenia/cpu/ppc/ppc_context.cc @@ -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. * ****************************************************************************** */ @@ -143,13 +143,12 @@ void PPCContext::SetRegFromString(const char* name, const char* value) { } bool PPCContext::CompareRegWithString(const char* name, const char* value, - char* out_value, - size_t out_value_size) const { + std::string& result) const { int n; if (sscanf(name, "r%d", &n) == 1) { uint64_t expected = string_util::from_string(value); if (this->r[n] != expected) { - std::snprintf(out_value, out_value_size, "%016" PRIX64, this->r[n]); + result = fmt::format("{:016X}", this->r[n]); return false; } return true; @@ -157,23 +156,17 @@ bool PPCContext::CompareRegWithString(const char* name, const char* value, if (std::strstr(value, "0x")) { // Special case: Treat float as integer. uint64_t expected = string_util::from_string(value, true); - - union { - double f; - uint64_t u; - } f2u; - f2u.f = this->f[n]; - - if (f2u.u != expected) { - std::snprintf(out_value, out_value_size, "%016" PRIX64, f2u.u); + uint64_t pun; + std::memcpy(&pun, &this->f[n], sizeof(pun)); + if (pun != expected) { + result = fmt::format("{:016X}", pun); return false; } } else { double expected = string_util::from_string(value); - // TODO(benvanik): epsilon if (this->f[n] != expected) { - std::snprintf(out_value, out_value_size, "%f", this->f[n]); + result = fmt::format("{:.17f}", this->f[n]); return false; } } @@ -181,9 +174,9 @@ bool PPCContext::CompareRegWithString(const char* name, const char* value, } else if (sscanf(name, "v%d", &n) == 1) { vec128_t expected = string_util::from_string(value); if (this->v[n] != expected) { - std::snprintf(out_value, out_value_size, "[%.8X, %.8X, %.8X, %.8X]", - this->v[n].i32[0], this->v[n].i32[1], this->v[n].i32[2], - this->v[n].i32[3]); + result = + fmt::format("[{:08X}, {:08X}, {:08X}, {:08X}]", this->v[n].i32[0], + this->v[n].i32[1], this->v[n].i32[2], this->v[n].i32[3]); return false; } return true; @@ -191,7 +184,7 @@ bool PPCContext::CompareRegWithString(const char* name, const char* value, uint64_t actual = this->cr(); uint64_t expected = string_util::from_string(value); if (actual != expected) { - std::snprintf(out_value, out_value_size, "%016" PRIX64, actual); + result = fmt::format("{:016X}", actual); return false; } return true; diff --git a/src/xenia/cpu/ppc/ppc_context.h b/src/xenia/cpu/ppc/ppc_context.h index 2732fdc41..4acdaed3c 100644 --- a/src/xenia/cpu/ppc/ppc_context.h +++ b/src/xenia/cpu/ppc/ppc_context.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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. * ****************************************************************************** */ @@ -432,7 +432,7 @@ typedef struct PPCContext_s { void SetRegFromString(const char* name, const char* value); bool CompareRegWithString(const char* name, const char* value, - char* out_value, size_t out_value_size) const; + std::string& result) const; } PPCContext; #pragma pack(pop) static_assert(sizeof(PPCContext) % 64 == 0, "64b padded"); diff --git a/src/xenia/cpu/ppc/ppc_hir_builder.cc b/src/xenia/cpu/ppc/ppc_hir_builder.cc index 284d81c87..a7e189f27 100644 --- a/src/xenia/cpu/ppc/ppc_hir_builder.cc +++ b/src/xenia/cpu/ppc/ppc_hir_builder.cc @@ -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. * ****************************************************************************** */ @@ -12,6 +12,8 @@ #include #include +#include "third_party/fmt/include/fmt/format.h" + #include "xenia/base/byte_order.h" #include "xenia/base/logging.h" #include "xenia/base/memory.h" @@ -48,10 +50,10 @@ void DumpAllOpcodeCounts() { auto& disasm_info = GetOpcodeDisasmInfo(opcode); auto translation_count = opcode_translation_counts[i]; if (translation_count) { - sb.AppendFormat("%8d : %s\n", translation_count, disasm_info.name); + sb.AppendFormat("{:8d} : {}\n", translation_count, disasm_info.name); } } - fprintf(stdout, "%s", sb.GetString()); + fprintf(stdout, "%s", sb.to_string().c_str()); fflush(stdout); } @@ -83,7 +85,7 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) { with_debug_info_ = (flags & EMIT_DEBUG_COMMENTS) == EMIT_DEBUG_COMMENTS; if (with_debug_info_) { - CommentFormat("%s fn %.8X-%.8X %s", function_->module()->name().c_str(), + CommentFormat("{} fn {:08X}-{:08X} {}", function_->module()->name().c_str(), function_->address(), function_->end_address(), function_->name().c_str()); } @@ -127,7 +129,7 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) { AnnotateLabel(address, label); } comment_buffer_.Reset(); - comment_buffer_.AppendFormat("%.8X %.8X ", address, code); + comment_buffer_.AppendFormat("{:08X} {:08X} ", address, code); DisasmPPC(address, code, &comment_buffer_); Comment(comment_buffer_); first_instr = last_instr(); @@ -229,7 +231,8 @@ void PPCHIRBuilder::MaybeBreakOnInstruction(uint32_t address) { void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) { char name_buffer[13]; - snprintf(name_buffer, xe::countof(name_buffer), "loc_%.8X", address); + auto format_result = fmt::format_to_n(name_buffer, 12, "loc_{:08X}", address); + name_buffer[format_result.size] = '\0'; label->name = (char*)arena_->Alloc(sizeof(name_buffer)); memcpy(label->name, name_buffer, sizeof(name_buffer)); } diff --git a/src/xenia/cpu/ppc/ppc_opcode_disasm.cc b/src/xenia/cpu/ppc/ppc_opcode_disasm.cc index c2e988cc1..70fcaf313 100644 --- a/src/xenia/cpu/ppc/ppc_opcode_disasm.cc +++ b/src/xenia/cpu/ppc/ppc_opcode_disasm.cc @@ -148,9 +148,9 @@ void PrintDisasm_bcx(const PPCDecodeData& d, StringBuffer* str) { if (d.B.LK()) str->Append('l'); if (d.B.AA()) str->Append('a'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", bo); + str->AppendFormat("{}", bo); str->Append(", "); - str->AppendFormat("%d", bi); + str->AppendFormat("{}", bi); } else { if (d.B.LK()) str->Append('l'); if (d.B.AA()) str->Append('a'); @@ -162,11 +162,11 @@ void PrintDisasm_bcx(const PPCDecodeData& d, StringBuffer* str) { } PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", bi / 4); + str->AppendFormat("crf{}", bi / 4); } str->Append(", "); - str->AppendFormat("0x%X", addr); + str->AppendFormat("0x{:X}", addr); } } // namespace ppc diff --git a/src/xenia/cpu/ppc/ppc_opcode_disasm_gen.cc b/src/xenia/cpu/ppc/ppc_opcode_disasm_gen.cc index 3bbcaa256..4323bdfac 100644 --- a/src/xenia/cpu/ppc/ppc_opcode_disasm_gen.cc +++ b/src/xenia/cpu/ppc/ppc_opcode_disasm_gen.cc @@ -20,11 +20,11 @@ void PrintDisasm_addcx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_addex(const PPCDecodeData& d, StringBuffer* str) { // adde[OE][Rc] [RD], [RA], [RB] @@ -33,55 +33,55 @@ void PrintDisasm_addex(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_addi(const PPCDecodeData& d, StringBuffer* str) { // addi [RD], [RA0], [SIMM] size_t str_start = str->length(); str->Append("addi"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_addic(const PPCDecodeData& d, StringBuffer* str) { // addic [RD], [RA], [SIMM] size_t str_start = str->length(); str->Append("addic"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_addicx(const PPCDecodeData& d, StringBuffer* str) { // addic. [RD], [RA], [SIMM] size_t str_start = str->length(); str->Append("addic."); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_addis(const PPCDecodeData& d, StringBuffer* str) { // addis [RD], [RA0], [SIMM] size_t str_start = str->length(); str->Append("addis"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_addmex(const PPCDecodeData& d, StringBuffer* str) { // addme[OE][Rc] [RD], [RA] @@ -90,9 +90,9 @@ void PrintDisasm_addmex(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); } void PrintDisasm_addx(const PPCDecodeData& d, StringBuffer* str) { // add[OE][Rc] [RD], [RA], [RB] @@ -101,11 +101,11 @@ void PrintDisasm_addx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_addzex(const PPCDecodeData& d, StringBuffer* str) { // addze[OE][Rc] [RD], [RA] @@ -114,9 +114,9 @@ void PrintDisasm_addzex(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); } void PrintDisasm_andcx(const PPCDecodeData& d, StringBuffer* str) { // andc[Rc] [RA], [RS], [RB] @@ -124,33 +124,33 @@ void PrintDisasm_andcx(const PPCDecodeData& d, StringBuffer* str) { str->Append("andc"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_andisx(const PPCDecodeData& d, StringBuffer* str) { // andis. [RA], [RS], [UIMM] size_t str_start = str->length(); str->Append("andis."); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_andix(const PPCDecodeData& d, StringBuffer* str) { // andi. [RA], [RS], [UIMM] size_t str_start = str->length(); str->Append("andi."); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_andx(const PPCDecodeData& d, StringBuffer* str) { // and[Rc] [RA], [RS], [RB] @@ -158,11 +158,11 @@ void PrintDisasm_andx(const PPCDecodeData& d, StringBuffer* str) { str->Append("and"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_bcctrx(const PPCDecodeData& d, StringBuffer* str) { // bcctr[LK] [BO], [BI] @@ -170,9 +170,9 @@ void PrintDisasm_bcctrx(const PPCDecodeData& d, StringBuffer* str) { str->Append("bcctr"); if (d.XL.LK()) str->Append('l'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.XL.BO()); + str->AppendFormat("{}", d.XL.BO()); str->Append(", "); - str->AppendFormat("%d", d.XL.BI()); + str->AppendFormat("{}", d.XL.BI()); } void PrintDisasm_bclrx(const PPCDecodeData& d, StringBuffer* str) { // bclr[LK] [BO], [BI] @@ -180,9 +180,9 @@ void PrintDisasm_bclrx(const PPCDecodeData& d, StringBuffer* str) { str->Append("bclr"); if (d.XL.LK()) str->Append('l'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.XL.BO()); + str->AppendFormat("{}", d.XL.BO()); str->Append(", "); - str->AppendFormat("%d", d.XL.BI()); + str->AppendFormat("{}", d.XL.BI()); } void PrintDisasm_bx(const PPCDecodeData& d, StringBuffer* str) { // b[LK][AA] [ADDR] @@ -191,68 +191,68 @@ void PrintDisasm_bx(const PPCDecodeData& d, StringBuffer* str) { if (d.I.LK()) str->Append('l'); if (d.I.AA()) str->Append('a'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("0x%X", d.I.ADDR()); + str->AppendFormat("0x{:X}", d.I.ADDR()); } void PrintDisasm_cmp(const PPCDecodeData& d, StringBuffer* str) { // cmp [CRFD], [L], [RA], [RB] size_t str_start = str->length(); str->Append("cmp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); str->Append(", "); - str->AppendFormat("%d", d.X.L()); + str->AppendFormat("{}", d.X.L()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_cmpi(const PPCDecodeData& d, StringBuffer* str) { // cmpi [CRFD], [L], [RA], [SIMM] size_t str_start = str->length(); str->Append("cmpi"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.D.CRFD()); + str->AppendFormat("crf{}", d.D.CRFD()); str->Append(", "); - str->AppendFormat("%d", d.D.L()); + str->AppendFormat("{}", d.D.L()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_cmpl(const PPCDecodeData& d, StringBuffer* str) { // cmpl [CRFD], [L], [RA], [RB] size_t str_start = str->length(); str->Append("cmpl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); str->Append(", "); - str->AppendFormat("%d", d.X.L()); + str->AppendFormat("{}", d.X.L()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_cmpli(const PPCDecodeData& d, StringBuffer* str) { // cmpli [CRFD], [L], [RA], [UIMM] size_t str_start = str->length(); str->Append("cmpli"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.D.CRFD()); + str->AppendFormat("crf{}", d.D.CRFD()); str->Append(", "); - str->AppendFormat("%d", d.D.L()); + str->AppendFormat("{}", d.D.L()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_cntlzdx(const PPCDecodeData& d, StringBuffer* str) { // cntlzd [RA], [RS] size_t str_start = str->length(); str->Append("cntlzd"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_cntlzwx(const PPCDecodeData& d, StringBuffer* str) { // cntlzw[Rc] [RA], [RS] @@ -260,160 +260,160 @@ void PrintDisasm_cntlzwx(const PPCDecodeData& d, StringBuffer* str) { str->Append("cntlzw"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_crand(const PPCDecodeData& d, StringBuffer* str) { // crand [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("crand"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_crandc(const PPCDecodeData& d, StringBuffer* str) { // crandc [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("crandc"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_creqv(const PPCDecodeData& d, StringBuffer* str) { // creqv [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("creqv"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_crnand(const PPCDecodeData& d, StringBuffer* str) { // crnand [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("crnand"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_crnor(const PPCDecodeData& d, StringBuffer* str) { // crnor [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("crnor"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_cror(const PPCDecodeData& d, StringBuffer* str) { // cror [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("cror"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_crorc(const PPCDecodeData& d, StringBuffer* str) { // crorc [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("crorc"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_crxor(const PPCDecodeData& d, StringBuffer* str) { // crxor [CRBD], [CRBA], [CRBB] size_t str_start = str->length(); str->Append("crxor"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crb%d", d.XL.CRBD()); + str->AppendFormat("crb{}", d.XL.CRBD()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBA()); + str->AppendFormat("crb{}", d.XL.CRBA()); str->Append(", "); - str->AppendFormat("crb%d", d.XL.CRBB()); + str->AppendFormat("crb{}", d.XL.CRBB()); } void PrintDisasm_dcbf(const PPCDecodeData& d, StringBuffer* str) { // dcbf [RA0], [RB] size_t str_start = str->length(); str->Append("dcbf"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_dcbi(const PPCDecodeData& d, StringBuffer* str) { // dcbi [RA0], [RB] size_t str_start = str->length(); str->Append("dcbi"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_dcbst(const PPCDecodeData& d, StringBuffer* str) { // dcbst [RA0], [RB] size_t str_start = str->length(); str->Append("dcbst"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_dcbt(const PPCDecodeData& d, StringBuffer* str) { // dcbt [RA0], [RB] size_t str_start = str->length(); str->Append("dcbt"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_dcbtst(const PPCDecodeData& d, StringBuffer* str) { // dcbtst [RA0], [RB] size_t str_start = str->length(); str->Append("dcbtst"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_dcbz(const PPCDecodeData& d, StringBuffer* str) { // dcbz [RA0], [RB] size_t str_start = str->length(); str->Append("dcbz"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DCBZ.RA0()); + str->AppendFormat("r{}", d.DCBZ.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.DCBZ.RB()); + str->AppendFormat("r{}", d.DCBZ.RB()); } void PrintDisasm_dcbz128(const PPCDecodeData& d, StringBuffer* str) { // dcbz128 [RA0], [RB] size_t str_start = str->length(); str->Append("dcbz128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DCBZ.RA0()); + str->AppendFormat("r{}", d.DCBZ.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.DCBZ.RB()); + str->AppendFormat("r{}", d.DCBZ.RB()); } void PrintDisasm_divdux(const PPCDecodeData& d, StringBuffer* str) { // divdu[OE][Rc] [RD], [RA], [RB] @@ -422,11 +422,11 @@ void PrintDisasm_divdux(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_divdx(const PPCDecodeData& d, StringBuffer* str) { // divd[OE][Rc] [RD], [RA], [RB] @@ -435,11 +435,11 @@ void PrintDisasm_divdx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_divwux(const PPCDecodeData& d, StringBuffer* str) { // divwu[OE][Rc] [RD], [RA], [RB] @@ -448,11 +448,11 @@ void PrintDisasm_divwux(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_divwx(const PPCDecodeData& d, StringBuffer* str) { // divw[OE][Rc] [RD], [RA], [RB] @@ -461,11 +461,11 @@ void PrintDisasm_divwx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_eieio(const PPCDecodeData& d, StringBuffer* str) { // eieio @@ -479,11 +479,11 @@ void PrintDisasm_eqvx(const PPCDecodeData& d, StringBuffer* str) { str->Append("eqv"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_extsbx(const PPCDecodeData& d, StringBuffer* str) { // extsb[Rc] [RA], [RS] @@ -491,9 +491,9 @@ void PrintDisasm_extsbx(const PPCDecodeData& d, StringBuffer* str) { str->Append("extsb"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_extshx(const PPCDecodeData& d, StringBuffer* str) { // extsh[Rc] [RA], [RS] @@ -501,9 +501,9 @@ void PrintDisasm_extshx(const PPCDecodeData& d, StringBuffer* str) { str->Append("extsh"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_extswx(const PPCDecodeData& d, StringBuffer* str) { // extsw[Rc] [RA], [RS] @@ -511,9 +511,9 @@ void PrintDisasm_extswx(const PPCDecodeData& d, StringBuffer* str) { str->Append("extsw"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_fabsx(const PPCDecodeData& d, StringBuffer* str) { // fabs[Rc] [FD], [FB] @@ -521,9 +521,9 @@ void PrintDisasm_fabsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fabs"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_faddsx(const PPCDecodeData& d, StringBuffer* str) { // fadds[Rc] [FD], [FA], [FB] @@ -531,11 +531,11 @@ void PrintDisasm_faddsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fadds"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_faddx(const PPCDecodeData& d, StringBuffer* str) { // fadd[Rc] [FD], [FA], [FB] @@ -543,11 +543,11 @@ void PrintDisasm_faddx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fadd"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fcfidx(const PPCDecodeData& d, StringBuffer* str) { // fcfid[Rc] [FD], [FB] @@ -555,31 +555,31 @@ void PrintDisasm_fcfidx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fcfid"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fcmpo(const PPCDecodeData& d, StringBuffer* str) { // fcmpo [CRFD], [FA], [FB] size_t str_start = str->length(); str->Append("fcmpo"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FA()); + str->AppendFormat("fr{}", d.X.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fcmpu(const PPCDecodeData& d, StringBuffer* str) { // fcmpu [CRFD], [FA], [FB] size_t str_start = str->length(); str->Append("fcmpu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FA()); + str->AppendFormat("fr{}", d.X.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fctidx(const PPCDecodeData& d, StringBuffer* str) { // fctid[Rc] [FD], [FB] @@ -587,9 +587,9 @@ void PrintDisasm_fctidx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fctid"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fctidzx(const PPCDecodeData& d, StringBuffer* str) { // fctidz[Rc] [FD], [FB] @@ -597,9 +597,9 @@ void PrintDisasm_fctidzx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fctidz"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fctiwx(const PPCDecodeData& d, StringBuffer* str) { // fctiw[Rc] [FD], [FB] @@ -607,9 +607,9 @@ void PrintDisasm_fctiwx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fctiw"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fctiwzx(const PPCDecodeData& d, StringBuffer* str) { // fctiwz[Rc] [FD], [FB] @@ -617,9 +617,9 @@ void PrintDisasm_fctiwzx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fctiwz"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fdivsx(const PPCDecodeData& d, StringBuffer* str) { // fdivs[Rc] [FD], [FA], [FB] @@ -627,11 +627,11 @@ void PrintDisasm_fdivsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fdivs"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fdivx(const PPCDecodeData& d, StringBuffer* str) { // fdiv[Rc] [FD], [FA], [FB] @@ -639,11 +639,11 @@ void PrintDisasm_fdivx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fdiv"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fmaddsx(const PPCDecodeData& d, StringBuffer* str) { // fmadds[Rc] [FD], [FA], [FC], [FB] @@ -651,13 +651,13 @@ void PrintDisasm_fmaddsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmadds"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fmaddx(const PPCDecodeData& d, StringBuffer* str) { // fmadd[Rc] [FD], [FA], [FC], [FB] @@ -665,13 +665,13 @@ void PrintDisasm_fmaddx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmadd"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fmrx(const PPCDecodeData& d, StringBuffer* str) { // fmr[Rc] [FD], [FB] @@ -679,9 +679,9 @@ void PrintDisasm_fmrx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmr"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fmsubsx(const PPCDecodeData& d, StringBuffer* str) { // fmsubs[Rc] [FD], [FA], [FC], [FB] @@ -689,13 +689,13 @@ void PrintDisasm_fmsubsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmsubs"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fmsubx(const PPCDecodeData& d, StringBuffer* str) { // fmsub[Rc] [FD], [FA], [FC], [FB] @@ -703,13 +703,13 @@ void PrintDisasm_fmsubx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmsub"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fmulsx(const PPCDecodeData& d, StringBuffer* str) { // fmuls[Rc] [FD], [FA], [FC] @@ -717,11 +717,11 @@ void PrintDisasm_fmulsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmuls"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); } void PrintDisasm_fmulx(const PPCDecodeData& d, StringBuffer* str) { // fmul[Rc] [FD], [FA], [FC] @@ -729,11 +729,11 @@ void PrintDisasm_fmulx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fmul"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); } void PrintDisasm_fnabsx(const PPCDecodeData& d, StringBuffer* str) { // fnabs[Rc] [FD], [FB] @@ -741,9 +741,9 @@ void PrintDisasm_fnabsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fnabs"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fnegx(const PPCDecodeData& d, StringBuffer* str) { // fneg[Rc] [FD], [FB] @@ -751,9 +751,9 @@ void PrintDisasm_fnegx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fneg"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_fnmaddsx(const PPCDecodeData& d, StringBuffer* str) { // fnmadds[Rc] [FD], [FA], [FC], [FB] @@ -761,13 +761,13 @@ void PrintDisasm_fnmaddsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fnmadds"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fnmaddx(const PPCDecodeData& d, StringBuffer* str) { // fnmadd[Rc] [FD], [FA], [FC], [FB] @@ -775,13 +775,13 @@ void PrintDisasm_fnmaddx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fnmadd"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fnmsubsx(const PPCDecodeData& d, StringBuffer* str) { // fnmsubs[Rc] [FD], [FA], [FC], [FB] @@ -789,13 +789,13 @@ void PrintDisasm_fnmsubsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fnmsubs"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fnmsubx(const PPCDecodeData& d, StringBuffer* str) { // fnmsub[Rc] [FD], [FA], [FC], [FB] @@ -803,13 +803,13 @@ void PrintDisasm_fnmsubx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fnmsub"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fresx(const PPCDecodeData& d, StringBuffer* str) { // fres[Rc] [FD], [FB] @@ -817,9 +817,9 @@ void PrintDisasm_fresx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fres"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_frspx(const PPCDecodeData& d, StringBuffer* str) { // frsp[Rc] [FD], [FB] @@ -827,9 +827,9 @@ void PrintDisasm_frspx(const PPCDecodeData& d, StringBuffer* str) { str->Append("frsp"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.X.FB()); + str->AppendFormat("fr{}", d.X.FB()); } void PrintDisasm_frsqrtex(const PPCDecodeData& d, StringBuffer* str) { // frsqrte[Rc] [FD], [FB] @@ -837,9 +837,9 @@ void PrintDisasm_frsqrtex(const PPCDecodeData& d, StringBuffer* str) { str->Append("frsqrte"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fselx(const PPCDecodeData& d, StringBuffer* str) { // fsel[Rc] [FD], [FA], [FC], [FB] @@ -847,13 +847,13 @@ void PrintDisasm_fselx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fsel"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FC()); + str->AppendFormat("fr{}", d.A.FC()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fsqrtsx(const PPCDecodeData& d, StringBuffer* str) { // fsqrts[Rc] [FD], [FB] @@ -861,9 +861,9 @@ void PrintDisasm_fsqrtsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fsqrts"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fsqrtx(const PPCDecodeData& d, StringBuffer* str) { // fsqrt[Rc] [FD], [FB] @@ -871,9 +871,9 @@ void PrintDisasm_fsqrtx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fsqrt"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fsubsx(const PPCDecodeData& d, StringBuffer* str) { // fsubs[Rc] [FD], [FA], [FB] @@ -881,11 +881,11 @@ void PrintDisasm_fsubsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fsubs"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_fsubx(const PPCDecodeData& d, StringBuffer* str) { // fsub[Rc] [FD], [FA], [FB] @@ -893,20 +893,20 @@ void PrintDisasm_fsubx(const PPCDecodeData& d, StringBuffer* str) { str->Append("fsub"); if (d.A.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.A.FD()); + str->AppendFormat("fr{}", d.A.FD()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FA()); + str->AppendFormat("fr{}", d.A.FA()); str->Append(", "); - str->AppendFormat("fr%d", d.A.FB()); + str->AppendFormat("fr{}", d.A.FB()); } void PrintDisasm_icbi(const PPCDecodeData& d, StringBuffer* str) { // icbi [RA], [RB] size_t str_start = str->length(); str->Append("icbi"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_isync(const PPCDecodeData& d, StringBuffer* str) { // isync @@ -919,11 +919,11 @@ void PrintDisasm_lbz(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lbz"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_lbzu(const PPCDecodeData& d, StringBuffer* str) { @@ -931,11 +931,11 @@ void PrintDisasm_lbzu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lbzu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_lbzux(const PPCDecodeData& d, StringBuffer* str) { @@ -943,33 +943,33 @@ void PrintDisasm_lbzux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lbzux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lbzx(const PPCDecodeData& d, StringBuffer* str) { // lbzx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lbzx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_ld(const PPCDecodeData& d, StringBuffer* str) { // ld [RD], [ds]([RA0]) size_t str_start = str->length(); str->Append("ld"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DS.RD()); + str->AppendFormat("r{}", d.DS.RD()); str->Append(", "); - str->AppendFormat(d.DS.ds() < 0 ? "-0x%X" : "0x%X", std::abs(d.DS.ds())); + str->AppendFormat(d.DS.ds() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.DS.ds())); str->Append("("); - str->AppendFormat("r%d", d.DS.RA0()); + str->AppendFormat("r{}", d.DS.RA0()); str->Append(")"); } void PrintDisasm_ldarx(const PPCDecodeData& d, StringBuffer* str) { @@ -977,33 +977,33 @@ void PrintDisasm_ldarx(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("ldarx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_ldbrx(const PPCDecodeData& d, StringBuffer* str) { // ldbrx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("ldbrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_ldu(const PPCDecodeData& d, StringBuffer* str) { // ldu [RD], [ds]([RA]) size_t str_start = str->length(); str->Append("ldu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DS.RD()); + str->AppendFormat("r{}", d.DS.RD()); str->Append(", "); - str->AppendFormat(d.DS.ds() < 0 ? "-0x%X" : "0x%X", std::abs(d.DS.ds())); + str->AppendFormat(d.DS.ds() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.DS.ds())); str->Append("("); - str->AppendFormat("r%d", d.DS.RA()); + str->AppendFormat("r{}", d.DS.RA()); str->Append(")"); } void PrintDisasm_ldux(const PPCDecodeData& d, StringBuffer* str) { @@ -1011,33 +1011,33 @@ void PrintDisasm_ldux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("ldux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_ldx(const PPCDecodeData& d, StringBuffer* str) { // ldx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("ldx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lfd(const PPCDecodeData& d, StringBuffer* str) { // lfd [FD], [d]([RA0]) size_t str_start = str->length(); str->Append("lfd"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FD()); + str->AppendFormat("fr{}", d.D.FD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_lfdu(const PPCDecodeData& d, StringBuffer* str) { @@ -1045,11 +1045,11 @@ void PrintDisasm_lfdu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lfdu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FD()); + str->AppendFormat("fr{}", d.D.FD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_lfdux(const PPCDecodeData& d, StringBuffer* str) { @@ -1057,33 +1057,33 @@ void PrintDisasm_lfdux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lfdux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lfdx(const PPCDecodeData& d, StringBuffer* str) { // lfdx [FD], [RA0], [RB] size_t str_start = str->length(); str->Append("lfdx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lfs(const PPCDecodeData& d, StringBuffer* str) { // lfs [FD], [d]([RA0]) size_t str_start = str->length(); str->Append("lfs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FD()); + str->AppendFormat("fr{}", d.D.FD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_lfsu(const PPCDecodeData& d, StringBuffer* str) { @@ -1091,11 +1091,11 @@ void PrintDisasm_lfsu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lfsu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FD()); + str->AppendFormat("fr{}", d.D.FD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_lfsux(const PPCDecodeData& d, StringBuffer* str) { @@ -1103,33 +1103,33 @@ void PrintDisasm_lfsux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lfsux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lfsx(const PPCDecodeData& d, StringBuffer* str) { // lfsx [FD], [RA0], [RB] size_t str_start = str->length(); str->Append("lfsx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FD()); + str->AppendFormat("fr{}", d.X.FD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lha(const PPCDecodeData& d, StringBuffer* str) { // lha [RD], [d]([RA0]) size_t str_start = str->length(); str->Append("lha"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_lhau(const PPCDecodeData& d, StringBuffer* str) { @@ -1137,11 +1137,11 @@ void PrintDisasm_lhau(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lhau"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_lhaux(const PPCDecodeData& d, StringBuffer* str) { @@ -1149,44 +1149,44 @@ void PrintDisasm_lhaux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lhaux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lhax(const PPCDecodeData& d, StringBuffer* str) { // lhax [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lhax"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lhbrx(const PPCDecodeData& d, StringBuffer* str) { // lhbrx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lhbrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lhz(const PPCDecodeData& d, StringBuffer* str) { // lhz [RD], [d]([RA0]) size_t str_start = str->length(); str->Append("lhz"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_lhzu(const PPCDecodeData& d, StringBuffer* str) { @@ -1194,11 +1194,11 @@ void PrintDisasm_lhzu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lhzu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_lhzux(const PPCDecodeData& d, StringBuffer* str) { @@ -1206,253 +1206,253 @@ void PrintDisasm_lhzux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lhzux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lhzx(const PPCDecodeData& d, StringBuffer* str) { // lhzx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lhzx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvebx(const PPCDecodeData& d, StringBuffer* str) { // lvebx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvebx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvehx(const PPCDecodeData& d, StringBuffer* str) { // lvehx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvehx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvewx(const PPCDecodeData& d, StringBuffer* str) { // lvewx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvewx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvewx128(const PPCDecodeData& d, StringBuffer* str) { // lvewx128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvewx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvlx(const PPCDecodeData& d, StringBuffer* str) { // lvlx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvlx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvlx128(const PPCDecodeData& d, StringBuffer* str) { // lvlx128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvlx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvlxl(const PPCDecodeData& d, StringBuffer* str) { // lvlxl [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvlxl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvlxl128(const PPCDecodeData& d, StringBuffer* str) { // lvlxl128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvlxl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvrx(const PPCDecodeData& d, StringBuffer* str) { // lvrx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvrx128(const PPCDecodeData& d, StringBuffer* str) { // lvrx128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvrx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvrxl(const PPCDecodeData& d, StringBuffer* str) { // lvrxl [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvrxl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvrxl128(const PPCDecodeData& d, StringBuffer* str) { // lvrxl128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvrxl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvsl(const PPCDecodeData& d, StringBuffer* str) { // lvsl [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvsl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvsl128(const PPCDecodeData& d, StringBuffer* str) { // lvsl128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvsl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvsr(const PPCDecodeData& d, StringBuffer* str) { // lvsr [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvsr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvsr128(const PPCDecodeData& d, StringBuffer* str) { // lvsr128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvsr128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvx(const PPCDecodeData& d, StringBuffer* str) { // lvx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvx128(const PPCDecodeData& d, StringBuffer* str) { // lvx128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lvxl(const PPCDecodeData& d, StringBuffer* str) { // lvslx [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvslx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VD()); + str->AppendFormat("vr{}", d.X.VD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lvxl128(const PPCDecodeData& d, StringBuffer* str) { // lvxl128 [VD], [RA0], [RB] size_t str_start = str->length(); str->Append("lvxl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VD()); + str->AppendFormat("vr{}", d.VX128_1.VD()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_lwa(const PPCDecodeData& d, StringBuffer* str) { // lwa [RD], [ds]([RA0]) size_t str_start = str->length(); str->Append("lwa"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DS.RD()); + str->AppendFormat("r{}", d.DS.RD()); str->Append(", "); - str->AppendFormat(d.DS.ds() < 0 ? "-0x%X" : "0x%X", std::abs(d.DS.ds())); + str->AppendFormat(d.DS.ds() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.DS.ds())); str->Append("("); - str->AppendFormat("r%d", d.DS.RA0()); + str->AppendFormat("r{}", d.DS.RA0()); str->Append(")"); } void PrintDisasm_lwarx(const PPCDecodeData& d, StringBuffer* str) { @@ -1460,55 +1460,55 @@ void PrintDisasm_lwarx(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lwarx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lwaux(const PPCDecodeData& d, StringBuffer* str) { // lwaux [RD], [RA], [RB] size_t str_start = str->length(); str->Append("lwaux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lwax(const PPCDecodeData& d, StringBuffer* str) { // lwax [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lwax"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lwbrx(const PPCDecodeData& d, StringBuffer* str) { // lwbrx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lwbrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lwz(const PPCDecodeData& d, StringBuffer* str) { // lwz [RD], [d]([RA0]) size_t str_start = str->length(); str->Append("lwz"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_lwzu(const PPCDecodeData& d, StringBuffer* str) { @@ -1516,11 +1516,11 @@ void PrintDisasm_lwzu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lwzu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_lwzux(const PPCDecodeData& d, StringBuffer* str) { @@ -1528,54 +1528,54 @@ void PrintDisasm_lwzux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("lwzux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_lwzx(const PPCDecodeData& d, StringBuffer* str) { // lwzx [RD], [RA0], [RB] size_t str_start = str->length(); str->Append("lwzx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_mcrf(const PPCDecodeData& d, StringBuffer* str) { // mcrf [CRFD], [CRFS] size_t str_start = str->length(); str->Append("mcrf"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.XL.CRFD()); + str->AppendFormat("crf{}", d.XL.CRFD()); str->Append(", "); - str->AppendFormat("crf%d", d.XL.CRFS()); + str->AppendFormat("crf{}", d.XL.CRFS()); } void PrintDisasm_mcrfs(const PPCDecodeData& d, StringBuffer* str) { // mcrfs [CRFD], [CRFS] size_t str_start = str->length(); str->Append("mcrfs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); str->Append(", "); - str->AppendFormat("crf%d", d.X.CRFS()); + str->AppendFormat("crf{}", d.X.CRFS()); } void PrintDisasm_mcrxr(const PPCDecodeData& d, StringBuffer* str) { // mcrxr [CRFD] size_t str_start = str->length(); str->Append("mcrxr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); } void PrintDisasm_mfcr(const PPCDecodeData& d, StringBuffer* str) { // mfcr [RD] size_t str_start = str->length(); str->Append("mfcr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); } void PrintDisasm_mffsx(const PPCDecodeData& d, StringBuffer* str) { // mffs[Rc] [RD] @@ -1583,32 +1583,32 @@ void PrintDisasm_mffsx(const PPCDecodeData& d, StringBuffer* str) { str->Append("mffs"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); } void PrintDisasm_mfmsr(const PPCDecodeData& d, StringBuffer* str) { // mfmsr [RD] size_t str_start = str->length(); str->Append("mfmsr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RD()); + str->AppendFormat("r{}", d.X.RD()); } void PrintDisasm_mfspr(const PPCDecodeData& d, StringBuffer* str) { // mfspr [RD], [SPR] size_t str_start = str->length(); str->Append("mfspr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XFX.RD()); + str->AppendFormat("r{}", d.XFX.RD()); str->Append(", "); - str->AppendFormat("%d", d.XFX.SPR()); + str->AppendFormat("{}", d.XFX.SPR()); } void PrintDisasm_mftb(const PPCDecodeData& d, StringBuffer* str) { // mftb [RD], [TBR] size_t str_start = str->length(); str->Append("mftb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XFX.RD()); + str->AppendFormat("r{}", d.XFX.RD()); str->Append(", "); - str->AppendFormat("%d", d.XFX.TBR()); + str->AppendFormat("{}", d.XFX.TBR()); } void PrintDisasm_mtcrf(const PPCDecodeData& d, StringBuffer* str) { // mtcrf [CRM], [RS] @@ -1617,7 +1617,7 @@ void PrintDisasm_mtcrf(const PPCDecodeData& d, StringBuffer* str) { PadStringBuffer(str, str_start, kNamePad); str->AppendFormat("(UNHANDLED CRM)"); str->Append(", "); - str->AppendFormat("r%d", d.XFX.RS()); + str->AppendFormat("r{}", d.XFX.RS()); } void PrintDisasm_mtfsb0x(const PPCDecodeData& d, StringBuffer* str) { // mtfsb0[Rc] [FPSCRD] @@ -1641,9 +1641,9 @@ void PrintDisasm_mtfsfix(const PPCDecodeData& d, StringBuffer* str) { str->Append("mtfsfi"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("crf%d", d.X.CRFD()); + str->AppendFormat("crf{}", d.X.CRFD()); str->Append(", "); - str->AppendFormat("%d", d.X.IMM()); + str->AppendFormat("{}", d.X.IMM()); } void PrintDisasm_mtfsfx(const PPCDecodeData& d, StringBuffer* str) { // mtfsf[Rc] [FM], [FB] @@ -1651,32 +1651,32 @@ void PrintDisasm_mtfsfx(const PPCDecodeData& d, StringBuffer* str) { str->Append("mtfsf"); if (d.XFL.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.XFL.FM()); + str->AppendFormat("{}", d.XFL.FM()); str->Append(", "); - str->AppendFormat("fr%d", d.XFL.FB()); + str->AppendFormat("fr{}", d.XFL.FB()); } void PrintDisasm_mtmsr(const PPCDecodeData& d, StringBuffer* str) { // mtmsr [RS] size_t str_start = str->length(); str->Append("mtmsr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_mtmsrd(const PPCDecodeData& d, StringBuffer* str) { // mtmsrd [RS] size_t str_start = str->length(); str->Append("mtmsrd"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); } void PrintDisasm_mtspr(const PPCDecodeData& d, StringBuffer* str) { // mtspr [SPR], [RS] size_t str_start = str->length(); str->Append("mtspr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.XFX.SPR()); + str->AppendFormat("{}", d.XFX.SPR()); str->Append(", "); - str->AppendFormat("r%d", d.XFX.RS()); + str->AppendFormat("r{}", d.XFX.RS()); } void PrintDisasm_mulhdux(const PPCDecodeData& d, StringBuffer* str) { // mulhdu[Rc] [RD], [RA], [RB] @@ -1684,11 +1684,11 @@ void PrintDisasm_mulhdux(const PPCDecodeData& d, StringBuffer* str) { str->Append("mulhdu"); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_mulhdx(const PPCDecodeData& d, StringBuffer* str) { // mulhd[Rc] [RD], [RA], [RB] @@ -1696,11 +1696,11 @@ void PrintDisasm_mulhdx(const PPCDecodeData& d, StringBuffer* str) { str->Append("mulhd"); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_mulhwux(const PPCDecodeData& d, StringBuffer* str) { // mulhwu[Rc] [RD], [RA], [RB] @@ -1708,11 +1708,11 @@ void PrintDisasm_mulhwux(const PPCDecodeData& d, StringBuffer* str) { str->Append("mulhwu"); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_mulhwx(const PPCDecodeData& d, StringBuffer* str) { // mulhw[Rc] [RD], [RA], [RB] @@ -1720,11 +1720,11 @@ void PrintDisasm_mulhwx(const PPCDecodeData& d, StringBuffer* str) { str->Append("mulhw"); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_mulldx(const PPCDecodeData& d, StringBuffer* str) { // mulld[OE][Rc] [RD], [RA], [RB] @@ -1733,22 +1733,22 @@ void PrintDisasm_mulldx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_mulli(const PPCDecodeData& d, StringBuffer* str) { // mulli [RD], [RA], [SIMM] size_t str_start = str->length(); str->Append("mulli"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_mullwx(const PPCDecodeData& d, StringBuffer* str) { // mullw[OE][Rc] [RD], [RA], [RB] @@ -1757,11 +1757,11 @@ void PrintDisasm_mullwx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_nandx(const PPCDecodeData& d, StringBuffer* str) { // nand[Rc] [RA], [RS], [RB] @@ -1769,11 +1769,11 @@ void PrintDisasm_nandx(const PPCDecodeData& d, StringBuffer* str) { str->Append("nand"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_negx(const PPCDecodeData& d, StringBuffer* str) { // neg[OE][Rc] [RD], [RA] @@ -1782,9 +1782,9 @@ void PrintDisasm_negx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); } void PrintDisasm_norx(const PPCDecodeData& d, StringBuffer* str) { // nor[Rc] [RA], [RS], [RB] @@ -1792,11 +1792,11 @@ void PrintDisasm_norx(const PPCDecodeData& d, StringBuffer* str) { str->Append("nor"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_orcx(const PPCDecodeData& d, StringBuffer* str) { // orc[Rc] [RA], [RS], [RB] @@ -1804,33 +1804,33 @@ void PrintDisasm_orcx(const PPCDecodeData& d, StringBuffer* str) { str->Append("orc"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_ori(const PPCDecodeData& d, StringBuffer* str) { // ori [RA], [RS], [UIMM] size_t str_start = str->length(); str->Append("ori"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_oris(const PPCDecodeData& d, StringBuffer* str) { // oris [RA], [RS], [UIMM] size_t str_start = str->length(); str->Append("oris"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_orx(const PPCDecodeData& d, StringBuffer* str) { // or[Rc] [RA], [RS], [RB] @@ -1838,11 +1838,11 @@ void PrintDisasm_orx(const PPCDecodeData& d, StringBuffer* str) { str->Append("or"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_rldclx(const PPCDecodeData& d, StringBuffer* str) { // rldcl[Rc] [RA], [RS], [RB], [MB] @@ -1850,13 +1850,13 @@ void PrintDisasm_rldclx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rldcl"); if (d.MDS.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.MDS.RA()); + str->AppendFormat("r{}", d.MDS.RA()); str->Append(", "); - str->AppendFormat("r%d", d.MDS.RS()); + str->AppendFormat("r{}", d.MDS.RS()); str->Append(", "); - str->AppendFormat("r%d", d.MDS.RB()); + str->AppendFormat("r{}", d.MDS.RB()); str->Append(", "); - str->AppendFormat("%d", d.MDS.MB()); + str->AppendFormat("{}", d.MDS.MB()); } void PrintDisasm_rldcrx(const PPCDecodeData& d, StringBuffer* str) { // rldcr[Rc] [RA], [RS], [RB], [ME] @@ -1864,13 +1864,13 @@ void PrintDisasm_rldcrx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rldcr"); if (d.MDS.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.MDS.RA()); + str->AppendFormat("r{}", d.MDS.RA()); str->Append(", "); - str->AppendFormat("r%d", d.MDS.RS()); + str->AppendFormat("r{}", d.MDS.RS()); str->Append(", "); - str->AppendFormat("r%d", d.MDS.RB()); + str->AppendFormat("r{}", d.MDS.RB()); str->Append(", "); - str->AppendFormat("%d", d.MDS.ME()); + str->AppendFormat("{}", d.MDS.ME()); } void PrintDisasm_rldiclx(const PPCDecodeData& d, StringBuffer* str) { // rldicl[Rc] [RA], [RS], [SH], [MB] @@ -1878,13 +1878,13 @@ void PrintDisasm_rldiclx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rldicl"); if (d.MD.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.MD.RA()); + str->AppendFormat("r{}", d.MD.RA()); str->Append(", "); - str->AppendFormat("r%d", d.MD.RS()); + str->AppendFormat("r{}", d.MD.RS()); str->Append(", "); - str->AppendFormat("%d", d.MD.SH()); + str->AppendFormat("{}", d.MD.SH()); str->Append(", "); - str->AppendFormat("%d", d.MD.MB()); + str->AppendFormat("{}", d.MD.MB()); } void PrintDisasm_rldicrx(const PPCDecodeData& d, StringBuffer* str) { // rldicr[Rc] [RA], [RS], [SH], [ME] @@ -1892,13 +1892,13 @@ void PrintDisasm_rldicrx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rldicr"); if (d.MD.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.MD.RA()); + str->AppendFormat("r{}", d.MD.RA()); str->Append(", "); - str->AppendFormat("r%d", d.MD.RS()); + str->AppendFormat("r{}", d.MD.RS()); str->Append(", "); - str->AppendFormat("%d", d.MD.SH()); + str->AppendFormat("{}", d.MD.SH()); str->Append(", "); - str->AppendFormat("%d", d.MD.ME()); + str->AppendFormat("{}", d.MD.ME()); } void PrintDisasm_rldicx(const PPCDecodeData& d, StringBuffer* str) { // rldic[Rc] [RA], [RS], [SH], [MB] @@ -1906,13 +1906,13 @@ void PrintDisasm_rldicx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rldic"); if (d.MD.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.MD.RA()); + str->AppendFormat("r{}", d.MD.RA()); str->Append(", "); - str->AppendFormat("r%d", d.MD.RS()); + str->AppendFormat("r{}", d.MD.RS()); str->Append(", "); - str->AppendFormat("%d", d.MD.SH()); + str->AppendFormat("{}", d.MD.SH()); str->Append(", "); - str->AppendFormat("%d", d.MD.MB()); + str->AppendFormat("{}", d.MD.MB()); } void PrintDisasm_rldimix(const PPCDecodeData& d, StringBuffer* str) { // rldimi[Rc] [RA], [RS], [SH], [MB] @@ -1920,13 +1920,13 @@ void PrintDisasm_rldimix(const PPCDecodeData& d, StringBuffer* str) { str->Append("rldimi"); if (d.MD.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.MD.RA()); + str->AppendFormat("r{}", d.MD.RA()); str->Append(", "); - str->AppendFormat("r%d", d.MD.RS()); + str->AppendFormat("r{}", d.MD.RS()); str->Append(", "); - str->AppendFormat("%d", d.MD.SH()); + str->AppendFormat("{}", d.MD.SH()); str->Append(", "); - str->AppendFormat("%d", d.MD.MB()); + str->AppendFormat("{}", d.MD.MB()); } void PrintDisasm_rlwimix(const PPCDecodeData& d, StringBuffer* str) { // rlwimi[Rc] [RA], [RS], [SH], [MB], [ME] @@ -1934,15 +1934,15 @@ void PrintDisasm_rlwimix(const PPCDecodeData& d, StringBuffer* str) { str->Append("rlwimi"); if (d.M.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.M.RA()); + str->AppendFormat("r{}", d.M.RA()); str->Append(", "); - str->AppendFormat("r%d", d.M.RS()); + str->AppendFormat("r{}", d.M.RS()); str->Append(", "); - str->AppendFormat("%d", d.M.SH()); + str->AppendFormat("{}", d.M.SH()); str->Append(", "); - str->AppendFormat("%d", d.M.MB()); + str->AppendFormat("{}", d.M.MB()); str->Append(", "); - str->AppendFormat("%d", d.M.ME()); + str->AppendFormat("{}", d.M.ME()); } void PrintDisasm_rlwinmx(const PPCDecodeData& d, StringBuffer* str) { // rlwinm[Rc] [RA], [RS], [SH], [MB], [ME] @@ -1950,15 +1950,15 @@ void PrintDisasm_rlwinmx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rlwinm"); if (d.M.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.M.RA()); + str->AppendFormat("r{}", d.M.RA()); str->Append(", "); - str->AppendFormat("r%d", d.M.RS()); + str->AppendFormat("r{}", d.M.RS()); str->Append(", "); - str->AppendFormat("%d", d.M.SH()); + str->AppendFormat("{}", d.M.SH()); str->Append(", "); - str->AppendFormat("%d", d.M.MB()); + str->AppendFormat("{}", d.M.MB()); str->Append(", "); - str->AppendFormat("%d", d.M.ME()); + str->AppendFormat("{}", d.M.ME()); } void PrintDisasm_rlwnmx(const PPCDecodeData& d, StringBuffer* str) { // rlwnm[Rc] [RA], [RS], [RB], [MB], [ME] @@ -1966,22 +1966,22 @@ void PrintDisasm_rlwnmx(const PPCDecodeData& d, StringBuffer* str) { str->Append("rlwnm"); if (d.M.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.M.RA()); + str->AppendFormat("r{}", d.M.RA()); str->Append(", "); - str->AppendFormat("r%d", d.M.RS()); + str->AppendFormat("r{}", d.M.RS()); str->Append(", "); - str->AppendFormat("r%d", d.M.RB()); + str->AppendFormat("r{}", d.M.RB()); str->Append(", "); - str->AppendFormat("%d", d.M.MB()); + str->AppendFormat("{}", d.M.MB()); str->Append(", "); - str->AppendFormat("%d", d.M.ME()); + str->AppendFormat("{}", d.M.ME()); } void PrintDisasm_sc(const PPCDecodeData& d, StringBuffer* str) { // sc [LEV] size_t str_start = str->length(); str->Append("sc"); PadStringBuffer(str, str_start, kNamePad); - if (d.SC.LEV()) str->AppendFormat("%d", d.SC.LEV()); + if (d.SC.LEV()) str->AppendFormat("{}", d.SC.LEV()); } void PrintDisasm_sldx(const PPCDecodeData& d, StringBuffer* str) { // sld[Rc] [RA], [RS], [RB] @@ -1989,11 +1989,11 @@ void PrintDisasm_sldx(const PPCDecodeData& d, StringBuffer* str) { str->Append("sld"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_slwx(const PPCDecodeData& d, StringBuffer* str) { // slw[Rc] [RA], [RS], [RB] @@ -2001,11 +2001,11 @@ void PrintDisasm_slwx(const PPCDecodeData& d, StringBuffer* str) { str->Append("slw"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_sradix(const PPCDecodeData& d, StringBuffer* str) { // sradi[Rc] [RA], [RS], [SH] @@ -2013,11 +2013,11 @@ void PrintDisasm_sradix(const PPCDecodeData& d, StringBuffer* str) { str->Append("sradi"); if (d.XS.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XS.RA()); + str->AppendFormat("r{}", d.XS.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XS.RS()); + str->AppendFormat("r{}", d.XS.RS()); str->Append(", "); - str->AppendFormat("%d", d.XS.SH()); + str->AppendFormat("{}", d.XS.SH()); } void PrintDisasm_sradx(const PPCDecodeData& d, StringBuffer* str) { // srad[Rc] [RA], [RS], [RB] @@ -2025,11 +2025,11 @@ void PrintDisasm_sradx(const PPCDecodeData& d, StringBuffer* str) { str->Append("srad"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_srawix(const PPCDecodeData& d, StringBuffer* str) { // srawi[Rc] [RA], [RS], [SH] @@ -2037,11 +2037,11 @@ void PrintDisasm_srawix(const PPCDecodeData& d, StringBuffer* str) { str->Append("srawi"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("%d", d.X.SH()); + str->AppendFormat("{}", d.X.SH()); } void PrintDisasm_srawx(const PPCDecodeData& d, StringBuffer* str) { // sraw[Rc] [RA], [RS], [RB] @@ -2049,11 +2049,11 @@ void PrintDisasm_srawx(const PPCDecodeData& d, StringBuffer* str) { str->Append("sraw"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_srdx(const PPCDecodeData& d, StringBuffer* str) { // srd[Rc] [RA], [RS], [RB] @@ -2061,11 +2061,11 @@ void PrintDisasm_srdx(const PPCDecodeData& d, StringBuffer* str) { str->Append("srd"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_srwx(const PPCDecodeData& d, StringBuffer* str) { // srw[Rc] [RA], [RS], [RB] @@ -2073,22 +2073,22 @@ void PrintDisasm_srwx(const PPCDecodeData& d, StringBuffer* str) { str->Append("srw"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stb(const PPCDecodeData& d, StringBuffer* str) { // stb [RS], [d]([RA0]) size_t str_start = str->length(); str->Append("stb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_stbu(const PPCDecodeData& d, StringBuffer* str) { @@ -2096,11 +2096,11 @@ void PrintDisasm_stbu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stbu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_stbux(const PPCDecodeData& d, StringBuffer* str) { @@ -2108,33 +2108,33 @@ void PrintDisasm_stbux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stbux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stbx(const PPCDecodeData& d, StringBuffer* str) { // stbx [RS], [RA0], [RB] size_t str_start = str->length(); str->Append("stbx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_std(const PPCDecodeData& d, StringBuffer* str) { // std [RS], [ds]([RA0]) size_t str_start = str->length(); str->Append("std"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DS.RS()); + str->AppendFormat("r{}", d.DS.RS()); str->Append(", "); - str->AppendFormat(d.DS.ds() < 0 ? "-0x%X" : "0x%X", std::abs(d.DS.ds())); + str->AppendFormat(d.DS.ds() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.DS.ds())); str->Append("("); - str->AppendFormat("r%d", d.DS.RA0()); + str->AppendFormat("r{}", d.DS.RA0()); str->Append(")"); } void PrintDisasm_stdbrx(const PPCDecodeData& d, StringBuffer* str) { @@ -2142,33 +2142,33 @@ void PrintDisasm_stdbrx(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stdbrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stdcx(const PPCDecodeData& d, StringBuffer* str) { // stdcx. [RS], [RA0], [RB] size_t str_start = str->length(); str->Append("stdcx."); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stdu(const PPCDecodeData& d, StringBuffer* str) { // stdu [RS], [ds]([RA]) size_t str_start = str->length(); str->Append("stdu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.DS.RS()); + str->AppendFormat("r{}", d.DS.RS()); str->Append(", "); - str->AppendFormat(d.DS.ds() < 0 ? "-0x%X" : "0x%X", std::abs(d.DS.ds())); + str->AppendFormat(d.DS.ds() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.DS.ds())); str->Append("("); - str->AppendFormat("r%d", d.DS.RA()); + str->AppendFormat("r{}", d.DS.RA()); str->Append(")"); } void PrintDisasm_stdux(const PPCDecodeData& d, StringBuffer* str) { @@ -2176,33 +2176,33 @@ void PrintDisasm_stdux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stdux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stdx(const PPCDecodeData& d, StringBuffer* str) { // stdx [RS], [RA0], [RB] size_t str_start = str->length(); str->Append("stdx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stfd(const PPCDecodeData& d, StringBuffer* str) { // stfd [FS], [d]([RA0]) size_t str_start = str->length(); str->Append("stfd"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FS()); + str->AppendFormat("fr{}", d.D.FS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_stfdu(const PPCDecodeData& d, StringBuffer* str) { @@ -2210,11 +2210,11 @@ void PrintDisasm_stfdu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stfdu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FS()); + str->AppendFormat("fr{}", d.D.FS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_stfdux(const PPCDecodeData& d, StringBuffer* str) { @@ -2222,44 +2222,44 @@ void PrintDisasm_stfdux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stfdux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FS()); + str->AppendFormat("fr{}", d.X.FS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stfdx(const PPCDecodeData& d, StringBuffer* str) { // stfdx [FS], [RA0], [RB] size_t str_start = str->length(); str->Append("stfdx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FS()); + str->AppendFormat("fr{}", d.X.FS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stfiwx(const PPCDecodeData& d, StringBuffer* str) { // stfiwx [FS], [RA0], [RB] size_t str_start = str->length(); str->Append("stfiwx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FS()); + str->AppendFormat("fr{}", d.X.FS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stfs(const PPCDecodeData& d, StringBuffer* str) { // stfs [FS], [d]([RA0]) size_t str_start = str->length(); str->Append("stfs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FS()); + str->AppendFormat("fr{}", d.D.FS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_stfsu(const PPCDecodeData& d, StringBuffer* str) { @@ -2267,11 +2267,11 @@ void PrintDisasm_stfsu(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stfsu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.D.FS()); + str->AppendFormat("fr{}", d.D.FS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_stfsux(const PPCDecodeData& d, StringBuffer* str) { @@ -2279,33 +2279,33 @@ void PrintDisasm_stfsux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stfsux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FS()); + str->AppendFormat("fr{}", d.X.FS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stfsx(const PPCDecodeData& d, StringBuffer* str) { // stfsx [FS], [RA], [RB] size_t str_start = str->length(); str->Append("stfsx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("fr%d", d.X.FS()); + str->AppendFormat("fr{}", d.X.FS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_sth(const PPCDecodeData& d, StringBuffer* str) { // sth [RS], [d]([RA0]) size_t str_start = str->length(); str->Append("sth"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_sthbrx(const PPCDecodeData& d, StringBuffer* str) { @@ -2313,22 +2313,22 @@ void PrintDisasm_sthbrx(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("sthbrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_sthu(const PPCDecodeData& d, StringBuffer* str) { // sthu [RS], [d]([RA]) size_t str_start = str->length(); str->Append("sthu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_sthux(const PPCDecodeData& d, StringBuffer* str) { @@ -2336,209 +2336,209 @@ void PrintDisasm_sthux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("sthux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_sthx(const PPCDecodeData& d, StringBuffer* str) { // sthx [RS], [RA0], [RB] size_t str_start = str->length(); str->Append("sthx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvebx(const PPCDecodeData& d, StringBuffer* str) { // stvebx [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvebx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvehx(const PPCDecodeData& d, StringBuffer* str) { // stvehx [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvehx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvewx(const PPCDecodeData& d, StringBuffer* str) { // stvewx [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvewx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvewx128(const PPCDecodeData& d, StringBuffer* str) { // stvewx128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvewx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stvlx(const PPCDecodeData& d, StringBuffer* str) { // stvlx [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvlx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvlx128(const PPCDecodeData& d, StringBuffer* str) { // stvlx128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvlx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stvlxl(const PPCDecodeData& d, StringBuffer* str) { // stvlxl [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvlxl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvlxl128(const PPCDecodeData& d, StringBuffer* str) { // stvlxl128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvlxl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stvrx(const PPCDecodeData& d, StringBuffer* str) { // stvrx [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvrx128(const PPCDecodeData& d, StringBuffer* str) { // stvrx128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvrx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stvrxl(const PPCDecodeData& d, StringBuffer* str) { // stvrxl [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvrxl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvrxl128(const PPCDecodeData& d, StringBuffer* str) { // stvrxl128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvrxl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stvx(const PPCDecodeData& d, StringBuffer* str) { // stvx [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvx128(const PPCDecodeData& d, StringBuffer* str) { // stvx128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvx128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stvxl(const PPCDecodeData& d, StringBuffer* str) { // stvxl [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvxl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.X.VS()); + str->AppendFormat("vr{}", d.X.VS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stvxl128(const PPCDecodeData& d, StringBuffer* str) { // stvxl128 [VS], [RA0], [RB] size_t str_start = str->length(); str->Append("stvxl128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_1.VS()); + str->AppendFormat("vr{}", d.VX128_1.VS()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RA0()); + str->AppendFormat("r{}", d.VX128_1.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.VX128_1.RB()); + str->AppendFormat("r{}", d.VX128_1.RB()); } void PrintDisasm_stw(const PPCDecodeData& d, StringBuffer* str) { // stw [RS], [d]([RA0]) size_t str_start = str->length(); str->Append("stw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA0()); + str->AppendFormat("r{}", d.D.RA0()); str->Append(")"); } void PrintDisasm_stwbrx(const PPCDecodeData& d, StringBuffer* str) { @@ -2546,33 +2546,33 @@ void PrintDisasm_stwbrx(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stwbrx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stwcx(const PPCDecodeData& d, StringBuffer* str) { // stwcx. [RS], [RA0], [RB] size_t str_start = str->length(); str->Append("stwcx."); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stwu(const PPCDecodeData& d, StringBuffer* str) { // stwu [RS], [d]([RA]) size_t str_start = str->length(); str->Append("stwu"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat(d.D.d() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.d())); + str->AppendFormat(d.D.d() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.d())); str->Append("("); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(")"); } void PrintDisasm_stwux(const PPCDecodeData& d, StringBuffer* str) { @@ -2580,22 +2580,22 @@ void PrintDisasm_stwux(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("stwux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_stwx(const PPCDecodeData& d, StringBuffer* str) { // stwx [RS], [RA0], [RB] size_t str_start = str->length(); str->Append("stwx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA0()); + str->AppendFormat("r{}", d.X.RA0()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_subfcx(const PPCDecodeData& d, StringBuffer* str) { // subfc[OE][Rc] [RD], [RA], [RB] @@ -2604,11 +2604,11 @@ void PrintDisasm_subfcx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_subfex(const PPCDecodeData& d, StringBuffer* str) { // subfe[OE][Rc] [RD], [RA], [RB] @@ -2617,22 +2617,22 @@ void PrintDisasm_subfex(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_subficx(const PPCDecodeData& d, StringBuffer* str) { // subfic [RD], [RA], [SIMM] size_t str_start = str->length(); str->Append("subfic"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RD()); + str->AppendFormat("r{}", d.D.RD()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_subfmex(const PPCDecodeData& d, StringBuffer* str) { // subfme[OE][Rc] [RD], [RA] @@ -2641,9 +2641,9 @@ void PrintDisasm_subfmex(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); } void PrintDisasm_subfx(const PPCDecodeData& d, StringBuffer* str) { // subf[OE][Rc] [RD], [RA], [RB] @@ -2652,11 +2652,11 @@ void PrintDisasm_subfx(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RB()); + str->AppendFormat("r{}", d.XO.RB()); } void PrintDisasm_subfzex(const PPCDecodeData& d, StringBuffer* str) { // subfze[OE][Rc] [RD], [RA] @@ -2665,9 +2665,9 @@ void PrintDisasm_subfzex(const PPCDecodeData& d, StringBuffer* str) { if (d.XO.OE()) str->Append('o'); if (d.XO.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.XO.RD()); + str->AppendFormat("r{}", d.XO.RD()); str->Append(", "); - str->AppendFormat("r%d", d.XO.RA()); + str->AppendFormat("r{}", d.XO.RA()); } void PrintDisasm_sync(const PPCDecodeData& d, StringBuffer* str) { // sync @@ -2680,330 +2680,330 @@ void PrintDisasm_td(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("td"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.X.TO()); + str->AppendFormat("{}", d.X.TO()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_tdi(const PPCDecodeData& d, StringBuffer* str) { // tdi [TO], [RA], [SIMM] size_t str_start = str->length(); str->Append("tdi"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.D.TO()); + str->AppendFormat("{}", d.D.TO()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_tw(const PPCDecodeData& d, StringBuffer* str) { // tw [TO], [RA], [RB] size_t str_start = str->length(); str->Append("tw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.X.TO()); + str->AppendFormat("{}", d.X.TO()); str->Append(", "); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } void PrintDisasm_twi(const PPCDecodeData& d, StringBuffer* str) { // tw [TO], [RA], [SIMM] size_t str_start = str->length(); str->Append("tw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.D.TO()); + str->AppendFormat("{}", d.D.TO()); str->Append(", "); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat(d.D.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.D.SIMM())); + str->AppendFormat(d.D.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.D.SIMM())); } void PrintDisasm_vaddcuw(const PPCDecodeData& d, StringBuffer* str) { // vaddcuw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddcuw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vaddfp(const PPCDecodeData& d, StringBuffer* str) { // vaddfp [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddfp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vaddfp128(const PPCDecodeData& d, StringBuffer* str) { // vaddfp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vaddsbs(const PPCDecodeData& d, StringBuffer* str) { // vaddsbs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddsbs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vaddshs(const PPCDecodeData& d, StringBuffer* str) { // vaddshs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddshs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vaddsws(const PPCDecodeData& d, StringBuffer* str) { // vaddsws [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddsws"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vaddubm(const PPCDecodeData& d, StringBuffer* str) { // vaddubm [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddubm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vaddubs(const PPCDecodeData& d, StringBuffer* str) { // vaddubs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vaddubs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vadduhm(const PPCDecodeData& d, StringBuffer* str) { // vadduhm [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vadduhm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vadduhs(const PPCDecodeData& d, StringBuffer* str) { // vadduhs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vadduhs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vadduwm(const PPCDecodeData& d, StringBuffer* str) { // vadduwm [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vadduwm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vadduws(const PPCDecodeData& d, StringBuffer* str) { // vadduws [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vadduws"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vand(const PPCDecodeData& d, StringBuffer* str) { // vand [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vand"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vand128(const PPCDecodeData& d, StringBuffer* str) { // vand128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vand128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vandc(const PPCDecodeData& d, StringBuffer* str) { // vandc [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vandc"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vandc128(const PPCDecodeData& d, StringBuffer* str) { // vandc128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vandc128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vavgsb(const PPCDecodeData& d, StringBuffer* str) { // vavgsb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vavgsb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vavgsh(const PPCDecodeData& d, StringBuffer* str) { // vavgsh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vavgsh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vavgsw(const PPCDecodeData& d, StringBuffer* str) { // vavgsw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vavgsw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vavgub(const PPCDecodeData& d, StringBuffer* str) { // vavgub [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vavgub"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vavguh(const PPCDecodeData& d, StringBuffer* str) { // vavguh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vavguh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vavguw(const PPCDecodeData& d, StringBuffer* str) { // vavguw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vavguw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vcfpsxws128(const PPCDecodeData& d, StringBuffer* str) { // vcfpsxws128 [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vcfpsxws128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX128_3.UIMM()); + str->AppendFormat("0x{:X}", d.VX128_3.UIMM()); } void PrintDisasm_vcfpuxws128(const PPCDecodeData& d, StringBuffer* str) { // vcfpuxws128 [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vcfpuxws128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX128_3.UIMM()); + str->AppendFormat("0x{:X}", d.VX128_3.UIMM()); } void PrintDisasm_vcfsx(const PPCDecodeData& d, StringBuffer* str) { // vcfsx [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vcfsx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vcfux(const PPCDecodeData& d, StringBuffer* str) { // vcfux [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vcfux"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vcmpbfp(const PPCDecodeData& d, StringBuffer* str) { // vcmpbfp[Rc] [VD], [VA], [VB] @@ -3011,11 +3011,11 @@ void PrintDisasm_vcmpbfp(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpbfp"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpbfp128(const PPCDecodeData& d, StringBuffer* str) { // vcmpbfp128[Rc] [VD], [VA], [VB] @@ -3023,11 +3023,11 @@ void PrintDisasm_vcmpbfp128(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpbfp128"); if (d.VX128_R.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_R.VD()); + str->AppendFormat("vr{}", d.VX128_R.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VA()); + str->AppendFormat("vr{}", d.VX128_R.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VB()); + str->AppendFormat("vr{}", d.VX128_R.VB()); } void PrintDisasm_vcmpeqfp(const PPCDecodeData& d, StringBuffer* str) { // vcmpeqfp[Rc] [VD], [VA], [VB] @@ -3035,11 +3035,11 @@ void PrintDisasm_vcmpeqfp(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpeqfp"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpeqfp128(const PPCDecodeData& d, StringBuffer* str) { // vcmpeqfp128[Rc] [VD], [VA], [VB] @@ -3047,11 +3047,11 @@ void PrintDisasm_vcmpeqfp128(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpeqfp128"); if (d.VX128_R.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_R.VD()); + str->AppendFormat("vr{}", d.VX128_R.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VA()); + str->AppendFormat("vr{}", d.VX128_R.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VB()); + str->AppendFormat("vr{}", d.VX128_R.VB()); } void PrintDisasm_vcmpequb(const PPCDecodeData& d, StringBuffer* str) { // vcmpequb[Rc] [VD], [VA], [VB] @@ -3059,11 +3059,11 @@ void PrintDisasm_vcmpequb(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpequb"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpequh(const PPCDecodeData& d, StringBuffer* str) { // vcmpequh[Rc] [VD], [VA], [VB] @@ -3071,11 +3071,11 @@ void PrintDisasm_vcmpequh(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpequh"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpequw(const PPCDecodeData& d, StringBuffer* str) { // vcmpequw[Rc] [VD], [VA], [VB] @@ -3083,11 +3083,11 @@ void PrintDisasm_vcmpequw(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpequw"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpequw128(const PPCDecodeData& d, StringBuffer* str) { // vcmpequw128[Rc] [VD], [VA], [VB] @@ -3095,11 +3095,11 @@ void PrintDisasm_vcmpequw128(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpequw128"); if (d.VX128_R.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_R.VD()); + str->AppendFormat("vr{}", d.VX128_R.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VA()); + str->AppendFormat("vr{}", d.VX128_R.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VB()); + str->AppendFormat("vr{}", d.VX128_R.VB()); } void PrintDisasm_vcmpgefp(const PPCDecodeData& d, StringBuffer* str) { // vcmpgefp[Rc] [VD], [VA], [VB] @@ -3107,11 +3107,11 @@ void PrintDisasm_vcmpgefp(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgefp"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgefp128(const PPCDecodeData& d, StringBuffer* str) { // vcmpgefp128[Rc] [VD], [VA], [VB] @@ -3119,11 +3119,11 @@ void PrintDisasm_vcmpgefp128(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgefp128"); if (d.VX128_R.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_R.VD()); + str->AppendFormat("vr{}", d.VX128_R.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VA()); + str->AppendFormat("vr{}", d.VX128_R.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VB()); + str->AppendFormat("vr{}", d.VX128_R.VB()); } void PrintDisasm_vcmpgtfp(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtfp[Rc] [VD], [VA], [VB] @@ -3131,11 +3131,11 @@ void PrintDisasm_vcmpgtfp(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtfp"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgtfp128(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtfp128[Rc] [VD], [VA], [VB] @@ -3143,11 +3143,11 @@ void PrintDisasm_vcmpgtfp128(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtfp128"); if (d.VX128_R.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_R.VD()); + str->AppendFormat("vr{}", d.VX128_R.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VA()); + str->AppendFormat("vr{}", d.VX128_R.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_R.VB()); + str->AppendFormat("vr{}", d.VX128_R.VB()); } void PrintDisasm_vcmpgtsb(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtsb[Rc] [VD], [VA], [VB] @@ -3155,11 +3155,11 @@ void PrintDisasm_vcmpgtsb(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtsb"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgtsh(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtsh[Rc] [VD], [VA], [VB] @@ -3167,11 +3167,11 @@ void PrintDisasm_vcmpgtsh(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtsh"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgtsw(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtsw[Rc] [VD], [VA], [VB] @@ -3179,11 +3179,11 @@ void PrintDisasm_vcmpgtsw(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtsw"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgtub(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtub[Rc] [VD], [VA], [VB] @@ -3191,11 +3191,11 @@ void PrintDisasm_vcmpgtub(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtub"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgtuh(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtuh[Rc] [VD], [VA], [VB] @@ -3203,11 +3203,11 @@ void PrintDisasm_vcmpgtuh(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtuh"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcmpgtuw(const PPCDecodeData& d, StringBuffer* str) { // vcmpgtuw[Rc] [VD], [VA], [VB] @@ -3215,1150 +3215,1150 @@ void PrintDisasm_vcmpgtuw(const PPCDecodeData& d, StringBuffer* str) { str->Append("vcmpgtuw"); if (d.VC.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VC.VD()); + str->AppendFormat("vr{}", d.VC.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VA()); + str->AppendFormat("vr{}", d.VC.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VC.VB()); + str->AppendFormat("vr{}", d.VC.VB()); } void PrintDisasm_vcsxwfp128(const PPCDecodeData& d, StringBuffer* str) { // vcsxwfp128 [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vcsxwfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX128_3.UIMM()); + str->AppendFormat("0x{:X}", d.VX128_3.UIMM()); } void PrintDisasm_vctsxs(const PPCDecodeData& d, StringBuffer* str) { // vctsxs [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vctsxs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vctuxs(const PPCDecodeData& d, StringBuffer* str) { // vctuxs [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vctuxs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vcuxwfp128(const PPCDecodeData& d, StringBuffer* str) { // vcuxwfp128 [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vcuxwfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX128_3.UIMM()); + str->AppendFormat("0x{:X}", d.VX128_3.UIMM()); } void PrintDisasm_vexptefp(const PPCDecodeData& d, StringBuffer* str) { // vexptefp [VD], [VB] size_t str_start = str->length(); str->Append("vexptefp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vexptefp128(const PPCDecodeData& d, StringBuffer* str) { // vexptefp128 [VD], [VB] size_t str_start = str->length(); str->Append("vexptefp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vlogefp(const PPCDecodeData& d, StringBuffer* str) { // vlogefp [VD], [VB] size_t str_start = str->length(); str->Append("vlogefp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vlogefp128(const PPCDecodeData& d, StringBuffer* str) { // vlogefp128 [VD], [VB] size_t str_start = str->length(); str->Append("vlogefp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vmaddcfp128(const PPCDecodeData& d, StringBuffer* str) { // vmaddcfp128 [VD], [VA], [VD], [VB] size_t str_start = str->length(); str->Append("vmaddcfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmaddfp(const PPCDecodeData& d, StringBuffer* str) { // vmaddfp [VD], [VA], [VC], [VB] size_t str_start = str->length(); str->Append("vmaddfp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); } void PrintDisasm_vmaddfp128(const PPCDecodeData& d, StringBuffer* str) { // vmaddfp128 [VD], [VA], [VB], [VD] size_t str_start = str->length(); str->Append("vmaddfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); } void PrintDisasm_vmaxfp(const PPCDecodeData& d, StringBuffer* str) { // vmaxfp [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxfp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmaxfp128(const PPCDecodeData& d, StringBuffer* str) { // vmaxfp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmaxsb(const PPCDecodeData& d, StringBuffer* str) { // vmaxsb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxsb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmaxsh(const PPCDecodeData& d, StringBuffer* str) { // vmaxsh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxsh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmaxsw(const PPCDecodeData& d, StringBuffer* str) { // vmaxsw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxsw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmaxub(const PPCDecodeData& d, StringBuffer* str) { // vmaxub [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxub"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmaxuh(const PPCDecodeData& d, StringBuffer* str) { // vmaxuh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxuh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmaxuw(const PPCDecodeData& d, StringBuffer* str) { // vmaxuw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmaxuw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmhaddshs(const PPCDecodeData& d, StringBuffer* str) { // vmhaddshs [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmhaddshs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmhraddshs(const PPCDecodeData& d, StringBuffer* str) { // vmhraddshs [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmhraddshs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vminfp(const PPCDecodeData& d, StringBuffer* str) { // vminfp [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminfp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vminfp128(const PPCDecodeData& d, StringBuffer* str) { // vminfp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vminsb(const PPCDecodeData& d, StringBuffer* str) { // vminsb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminsb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vminsh(const PPCDecodeData& d, StringBuffer* str) { // vminsh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminsh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vminsw(const PPCDecodeData& d, StringBuffer* str) { // vminsw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminsw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vminub(const PPCDecodeData& d, StringBuffer* str) { // vminub [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminub"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vminuh(const PPCDecodeData& d, StringBuffer* str) { // vminuh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminuh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vminuw(const PPCDecodeData& d, StringBuffer* str) { // vminuw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vminuw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmladduhm(const PPCDecodeData& d, StringBuffer* str) { // vmladduhm [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmladduhm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmrghb(const PPCDecodeData& d, StringBuffer* str) { // vmrghb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrghb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmrghh(const PPCDecodeData& d, StringBuffer* str) { // vmrghh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrghh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmrghw(const PPCDecodeData& d, StringBuffer* str) { // vmrghw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrghw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmrghw128(const PPCDecodeData& d, StringBuffer* str) { // vmrghw128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrghw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmrglb(const PPCDecodeData& d, StringBuffer* str) { // vmrglb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrglb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmrglh(const PPCDecodeData& d, StringBuffer* str) { // vmrglh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrglh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmrglw(const PPCDecodeData& d, StringBuffer* str) { // vmrglw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrglw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmrglw128(const PPCDecodeData& d, StringBuffer* str) { // vmrglw128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmrglw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmsum3fp128(const PPCDecodeData& d, StringBuffer* str) { // vmsum3fp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmsum3fp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmsum4fp128(const PPCDecodeData& d, StringBuffer* str) { // vmsum4fp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmsum4fp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmsummbm(const PPCDecodeData& d, StringBuffer* str) { // vmsummbm [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmsummbm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmsumshm(const PPCDecodeData& d, StringBuffer* str) { // vmsumshm [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmsumshm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmsumshs(const PPCDecodeData& d, StringBuffer* str) { // vmsumshs [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmsumshs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmsumubm(const PPCDecodeData& d, StringBuffer* str) { // vmsumubm [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmsumubm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmsumuhm(const PPCDecodeData& d, StringBuffer* str) { // vmsumuhm [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmsumuhm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmsumuhs(const PPCDecodeData& d, StringBuffer* str) { // vmsumuhs [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vmsumuhs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vmulesb(const PPCDecodeData& d, StringBuffer* str) { // vmulesb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmulesb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmulesh(const PPCDecodeData& d, StringBuffer* str) { // vmulesh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmulesh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmuleub(const PPCDecodeData& d, StringBuffer* str) { // vmuleub [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmuleub"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmuleuh(const PPCDecodeData& d, StringBuffer* str) { // vmuleuh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmuleuh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmulfp128(const PPCDecodeData& d, StringBuffer* str) { // vmulfp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmulfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vmulosb(const PPCDecodeData& d, StringBuffer* str) { // vmulosb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmulosb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmulosh(const PPCDecodeData& d, StringBuffer* str) { // vmulosh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmulosh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmuloub(const PPCDecodeData& d, StringBuffer* str) { // vmuloub [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmuloub"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vmulouh(const PPCDecodeData& d, StringBuffer* str) { // vmulouh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vmulouh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vnmsubfp(const PPCDecodeData& d, StringBuffer* str) { // vnmsubfp [VD], [VA], [VC], [VB] size_t str_start = str->length(); str->Append("vnmsubfp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); } void PrintDisasm_vnmsubfp128(const PPCDecodeData& d, StringBuffer* str) { // vnmsubfp128 [VD], [VA], [VD], [VB] size_t str_start = str->length(); str->Append("vnmsubfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vnor(const PPCDecodeData& d, StringBuffer* str) { // vnor [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vnor"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vnor128(const PPCDecodeData& d, StringBuffer* str) { // vnor128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vnor128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vor(const PPCDecodeData& d, StringBuffer* str) { // vor [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vor"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vor128(const PPCDecodeData& d, StringBuffer* str) { // vor128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vor128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vperm(const PPCDecodeData& d, StringBuffer* str) { // vperm [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vperm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vperm128(const PPCDecodeData& d, StringBuffer* str) { // vperm128 [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vperm128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_2.VD()); + str->AppendFormat("vr{}", d.VX128_2.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_2.VA()); + str->AppendFormat("vr{}", d.VX128_2.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_2.VB()); + str->AppendFormat("vr{}", d.VX128_2.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_2.VC()); + str->AppendFormat("vr{}", d.VX128_2.VC()); } void PrintDisasm_vpermwi128(const PPCDecodeData& d, StringBuffer* str) { // vpermwi128 [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vpermwi128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_P.VD()); + str->AppendFormat("vr{}", d.VX128_P.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_P.VB()); + str->AppendFormat("vr{}", d.VX128_P.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX128_P.UIMM()); + str->AppendFormat("0x{:X}", d.VX128_P.UIMM()); } void PrintDisasm_vpkpx(const PPCDecodeData& d, StringBuffer* str) { // vpkpx [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkpx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkshss(const PPCDecodeData& d, StringBuffer* str) { // vpkshss [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkshss"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkshss128(const PPCDecodeData& d, StringBuffer* str) { // vpkshss128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkshss128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkshus(const PPCDecodeData& d, StringBuffer* str) { // vpkshus [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkshus"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkshus128(const PPCDecodeData& d, StringBuffer* str) { // vpkshus128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkshus128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkswss(const PPCDecodeData& d, StringBuffer* str) { // vpkswss [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkswss"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkswss128(const PPCDecodeData& d, StringBuffer* str) { // vpkswss128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkswss128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkswus(const PPCDecodeData& d, StringBuffer* str) { // vpkswus [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkswus"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkswus128(const PPCDecodeData& d, StringBuffer* str) { // vpkswus128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkswus128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkuhum(const PPCDecodeData& d, StringBuffer* str) { // vpkuhum [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuhum"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkuhum128(const PPCDecodeData& d, StringBuffer* str) { // vpkuhum128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuhum128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkuhus(const PPCDecodeData& d, StringBuffer* str) { // vpkuhus [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuhus"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkuhus128(const PPCDecodeData& d, StringBuffer* str) { // vpkuhus128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuhus128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkuwum(const PPCDecodeData& d, StringBuffer* str) { // vpkuwum [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuwum"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkuwum128(const PPCDecodeData& d, StringBuffer* str) { // vpkuwum128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuwum128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vpkuwus(const PPCDecodeData& d, StringBuffer* str) { // vpkuwus [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuwus"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vpkuwus128(const PPCDecodeData& d, StringBuffer* str) { // vpkuwus128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vpkuwus128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vrefp(const PPCDecodeData& d, StringBuffer* str) { // vrefp [VD], [VB] size_t str_start = str->length(); str->Append("vrefp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrefp128(const PPCDecodeData& d, StringBuffer* str) { // vrefp128 [VD], [VB] size_t str_start = str->length(); str->Append("vrefp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vrfim(const PPCDecodeData& d, StringBuffer* str) { // vrfim [VD], [VB] size_t str_start = str->length(); str->Append("vrfim"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrfim128(const PPCDecodeData& d, StringBuffer* str) { // vrfim128 [VD], [VB] size_t str_start = str->length(); str->Append("vrfim128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vrfin(const PPCDecodeData& d, StringBuffer* str) { // vrfin [VD], [VB] size_t str_start = str->length(); str->Append("vrfin"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrfin128(const PPCDecodeData& d, StringBuffer* str) { // vrfin128 [VD], [VB] size_t str_start = str->length(); str->Append("vrfin128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vrfip(const PPCDecodeData& d, StringBuffer* str) { // vrfip [VD], [VB] size_t str_start = str->length(); str->Append("vrfip"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrfip128(const PPCDecodeData& d, StringBuffer* str) { // vrfip128 [VD], [VB] size_t str_start = str->length(); str->Append("vrfip128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vrfiz(const PPCDecodeData& d, StringBuffer* str) { // vrfiz [VD], [VB] size_t str_start = str->length(); str->Append("vrfiz"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrfiz128(const PPCDecodeData& d, StringBuffer* str) { // vrfiz128 [VD], [VB] size_t str_start = str->length(); str->Append("vrfiz128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vrlb(const PPCDecodeData& d, StringBuffer* str) { // vrlb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vrlb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrlh(const PPCDecodeData& d, StringBuffer* str) { // vrlh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vrlh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrlimi128(const PPCDecodeData& d, StringBuffer* str) { // vrlimi128 [VD], [VB], [IMM], [z] size_t str_start = str->length(); str->Append("vrlimi128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_4.VD()); + str->AppendFormat("vr{}", d.VX128_4.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_4.VB()); + str->AppendFormat("vr{}", d.VX128_4.VB()); str->Append(", "); - str->AppendFormat("%d", d.VX128_4.IMM()); + str->AppendFormat("{}", d.VX128_4.IMM()); str->Append(", "); - str->AppendFormat("%d", d.VX128_4.z()); + str->AppendFormat("{}", d.VX128_4.z()); } void PrintDisasm_vrlw(const PPCDecodeData& d, StringBuffer* str) { // vrlw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vrlw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrlw128(const PPCDecodeData& d, StringBuffer* str) { // vrlw128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vrlw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vrsqrtefp(const PPCDecodeData& d, StringBuffer* str) { // vrsqrtefp [VD], [VB] size_t str_start = str->length(); str->Append("vrsqrtefp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vrsqrtefp128(const PPCDecodeData& d, StringBuffer* str) { // vrsqrtefp128 [VD], [VB] size_t str_start = str->length(); str->Append("vrsqrtefp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); } void PrintDisasm_vsel(const PPCDecodeData& d, StringBuffer* str) { // vsel [VD], [VA], [VB], [VC] size_t str_start = str->length(); str->Append("vsel"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VC()); + str->AppendFormat("vr{}", d.VA.VC()); } void PrintDisasm_vsel128(const PPCDecodeData& d, StringBuffer* str) { // vsel128 [VD], [VA], [VB], [VD] size_t str_start = str->length(); str->Append("vsel128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); } void PrintDisasm_vsl(const PPCDecodeData& d, StringBuffer* str) { // vsl [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsl"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vslb(const PPCDecodeData& d, StringBuffer* str) { // vslb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vslb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsldoi(const PPCDecodeData& d, StringBuffer* str) { // vsldoi [VD], [VA], [VB], [SHB] size_t str_start = str->length(); str->Append("vsldoi"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VA.VD()); + str->AppendFormat("vr{}", d.VA.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VA()); + str->AppendFormat("vr{}", d.VA.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VA.VB()); + str->AppendFormat("vr{}", d.VA.VB()); str->Append(", "); str->AppendFormat("(UNHANDLED SHB)"); } @@ -4367,11 +4367,11 @@ void PrintDisasm_vsldoi128(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("vsldoi128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_5.VD()); + str->AppendFormat("vr{}", d.VX128_5.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_5.VA()); + str->AppendFormat("vr{}", d.VX128_5.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_5.VB()); + str->AppendFormat("vr{}", d.VX128_5.VB()); str->Append(", "); str->AppendFormat("(UNHANDLED SHB)"); } @@ -4380,559 +4380,559 @@ void PrintDisasm_vslh(const PPCDecodeData& d, StringBuffer* str) { size_t str_start = str->length(); str->Append("vslh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vslo(const PPCDecodeData& d, StringBuffer* str) { // vslo [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vslo"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vslo128(const PPCDecodeData& d, StringBuffer* str) { // vslo128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vslo128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vslw(const PPCDecodeData& d, StringBuffer* str) { // vslw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vslw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vslw128(const PPCDecodeData& d, StringBuffer* str) { // vslw128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vslw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vspltb(const PPCDecodeData& d, StringBuffer* str) { // vspltb [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vspltb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vsplth(const PPCDecodeData& d, StringBuffer* str) { // vsplth [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vsplth"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vspltisb(const PPCDecodeData& d, StringBuffer* str) { // vspltisb [VD], [SIMM] size_t str_start = str->length(); str->Append("vspltisb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat(d.VX.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.VX.SIMM())); + str->AppendFormat(d.VX.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.VX.SIMM())); } void PrintDisasm_vspltish(const PPCDecodeData& d, StringBuffer* str) { // vspltish [VD], [SIMM] size_t str_start = str->length(); str->Append("vspltish"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat(d.VX.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.VX.SIMM())); + str->AppendFormat(d.VX.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.VX.SIMM())); } void PrintDisasm_vspltisw(const PPCDecodeData& d, StringBuffer* str) { // vspltisw [VD], [SIMM] size_t str_start = str->length(); str->Append("vspltisw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat(d.VX.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.VX.SIMM())); + str->AppendFormat(d.VX.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.VX.SIMM())); } void PrintDisasm_vspltisw128(const PPCDecodeData& d, StringBuffer* str) { // vspltisw128 [VD], [SIMM] size_t str_start = str->length(); str->Append("vspltisw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat(d.VX128_3.SIMM() < 0 ? "-0x%X" : "0x%X", std::abs(d.VX128_3.SIMM())); + str->AppendFormat(d.VX128_3.SIMM() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.VX128_3.SIMM())); } void PrintDisasm_vspltw(const PPCDecodeData& d, StringBuffer* str) { // vspltw [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vspltw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX.UIMM()); + str->AppendFormat("0x{:X}", d.VX.UIMM()); } void PrintDisasm_vspltw128(const PPCDecodeData& d, StringBuffer* str) { // vspltw128 [VD], [VB], [UIMM] size_t str_start = str->length(); str->Append("vspltw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128_3.VD()); + str->AppendFormat("vr{}", d.VX128_3.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128_3.VB()); + str->AppendFormat("vr{}", d.VX128_3.VB()); str->Append(", "); - str->AppendFormat("0x%X", d.VX128_3.UIMM()); + str->AppendFormat("0x{:X}", d.VX128_3.UIMM()); } void PrintDisasm_vsr(const PPCDecodeData& d, StringBuffer* str) { // vsr [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsr"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsrab(const PPCDecodeData& d, StringBuffer* str) { // vsrab [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsrab"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsrah(const PPCDecodeData& d, StringBuffer* str) { // vsrah [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsrah"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsraw(const PPCDecodeData& d, StringBuffer* str) { // vsraw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsraw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsraw128(const PPCDecodeData& d, StringBuffer* str) { // vsraw128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsraw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vsrb(const PPCDecodeData& d, StringBuffer* str) { // vsrb [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsrb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsrh(const PPCDecodeData& d, StringBuffer* str) { // vsrh [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsrh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsro(const PPCDecodeData& d, StringBuffer* str) { // vsro [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsro"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsro128(const PPCDecodeData& d, StringBuffer* str) { // vsro128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsro128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vsrw(const PPCDecodeData& d, StringBuffer* str) { // vsrw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsrw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsrw128(const PPCDecodeData& d, StringBuffer* str) { // vsrw128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsrw128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vsubcuw(const PPCDecodeData& d, StringBuffer* str) { // vsubcuw [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubcuw"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubfp(const PPCDecodeData& d, StringBuffer* str) { // vsubfp [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubfp"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubfp128(const PPCDecodeData& d, StringBuffer* str) { // vsubfp128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubfp128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vsubsbs(const PPCDecodeData& d, StringBuffer* str) { // vsubsbs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubsbs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubshs(const PPCDecodeData& d, StringBuffer* str) { // vsubshs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubshs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubsws(const PPCDecodeData& d, StringBuffer* str) { // vsubsws [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubsws"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsububm(const PPCDecodeData& d, StringBuffer* str) { // vsububm [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsububm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsububs(const PPCDecodeData& d, StringBuffer* str) { // vsububs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsububs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubuhm(const PPCDecodeData& d, StringBuffer* str) { // vsubuhm [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubuhm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubuhs(const PPCDecodeData& d, StringBuffer* str) { // vsubuhs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubuhs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubuwm(const PPCDecodeData& d, StringBuffer* str) { // vsubuwm [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubuwm"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsubuws(const PPCDecodeData& d, StringBuffer* str) { // vsubuws [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsubuws"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsum2sws(const PPCDecodeData& d, StringBuffer* str) { // vsum2sws [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsum2sws"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsum4sbs(const PPCDecodeData& d, StringBuffer* str) { // vsum4sbs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsum4sbs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsum4shs(const PPCDecodeData& d, StringBuffer* str) { // vsum4shs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsum4shs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsum4ubs(const PPCDecodeData& d, StringBuffer* str) { // vsum4ubs [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsum4ubs"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vsumsws(const PPCDecodeData& d, StringBuffer* str) { // vsumsws [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vsumsws"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vupkhpx(const PPCDecodeData& d, StringBuffer* str) { // vupkhpx [VD], [VB] size_t str_start = str->length(); str->Append("vupkhpx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vupkhsb(const PPCDecodeData& d, StringBuffer* str) { // vupkhsb [VD], [VB] size_t str_start = str->length(); str->Append("vupkhsb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vupkhsb128(const PPCDecodeData& d, StringBuffer* str) { // vupkhsb128 [VD], [VB] size_t str_start = str->length(); str->Append("vupkhsb128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vupkhsh(const PPCDecodeData& d, StringBuffer* str) { // vupkhsh [VD], [VB] size_t str_start = str->length(); str->Append("vupkhsh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vupklpx(const PPCDecodeData& d, StringBuffer* str) { // vupklpx [VD], [VB] size_t str_start = str->length(); str->Append("vupklpx"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vupklsb(const PPCDecodeData& d, StringBuffer* str) { // vupklsb [VD], [VB] size_t str_start = str->length(); str->Append("vupklsb"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vupklsb128(const PPCDecodeData& d, StringBuffer* str) { // vupklsb128 [VD], [VB] size_t str_start = str->length(); str->Append("vupklsb128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_vupklsh(const PPCDecodeData& d, StringBuffer* str) { // vupklsh [VD], [VB] size_t str_start = str->length(); str->Append("vupklsh"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vxor(const PPCDecodeData& d, StringBuffer* str) { // vxor [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vxor"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX.VD()); + str->AppendFormat("vr{}", d.VX.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VA()); + str->AppendFormat("vr{}", d.VX.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX.VB()); + str->AppendFormat("vr{}", d.VX.VB()); } void PrintDisasm_vxor128(const PPCDecodeData& d, StringBuffer* str) { // vxor128 [VD], [VA], [VB] size_t str_start = str->length(); str->Append("vxor128"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("vr%d", d.VX128.VD()); + str->AppendFormat("vr{}", d.VX128.VD()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VA()); + str->AppendFormat("vr{}", d.VX128.VA()); str->Append(", "); - str->AppendFormat("vr%d", d.VX128.VB()); + str->AppendFormat("vr{}", d.VX128.VB()); } void PrintDisasm_xori(const PPCDecodeData& d, StringBuffer* str) { // xori [RA], [RS], [UIMM] size_t str_start = str->length(); str->Append("xori"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_xoris(const PPCDecodeData& d, StringBuffer* str) { // xoris [RA], [RS], [UIMM] size_t str_start = str->length(); str->Append("xoris"); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.D.RA()); + str->AppendFormat("r{}", d.D.RA()); str->Append(", "); - str->AppendFormat("r%d", d.D.RS()); + str->AppendFormat("r{}", d.D.RS()); str->Append(", "); - str->AppendFormat("0x%X", d.D.UIMM()); + str->AppendFormat("0x{:X}", d.D.UIMM()); } void PrintDisasm_xorx(const PPCDecodeData& d, StringBuffer* str) { // xor[Rc] [RA], [RS], [RB] @@ -4940,11 +4940,11 @@ void PrintDisasm_xorx(const PPCDecodeData& d, StringBuffer* str) { str->Append("xor"); if (d.X.Rc()) str->Append('.'); PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("r%d", d.X.RA()); + str->AppendFormat("r{}", d.X.RA()); str->Append(", "); - str->AppendFormat("r%d", d.X.RS()); + str->AppendFormat("r{}", d.X.RS()); str->Append(", "); - str->AppendFormat("r%d", d.X.RB()); + str->AppendFormat("r{}", d.X.RB()); } #define INIT_LIST(...) {__VA_ARGS__} #define INSTRUCTION(opcode, mnem, form, group, type, desc, reads, writes, fn) \ diff --git a/src/xenia/cpu/ppc/ppc_opcode_info.cc b/src/xenia/cpu/ppc/ppc_opcode_info.cc index 00b90a6bc..be932d4dd 100644 --- a/src/xenia/cpu/ppc/ppc_opcode_info.cc +++ b/src/xenia/cpu/ppc/ppc_opcode_info.cc @@ -28,7 +28,7 @@ bool DisasmPPC(uint32_t address, uint32_t code, StringBuffer* str) { d.code = code; disasm_info.disasm(d, str); } else { - str->AppendFormat("%-8s", disasm_info.name); + str->AppendFormat("{:<8}", disasm_info.name); } return true; } diff --git a/src/xenia/cpu/ppc/ppc_translator.cc b/src/xenia/cpu/ppc/ppc_translator.cc index 94ef275bb..708a4b608 100644 --- a/src/xenia/cpu/ppc/ppc_translator.cc +++ b/src/xenia/cpu/ppc/ppc_translator.cc @@ -155,7 +155,7 @@ bool PPCTranslator::Translate(GuestFunction* function, // Stash source. if (debug_info_flags & DebugInfoFlags::kDebugInfoDisasmSource) { DumpSource(function, &string_buffer_); - debug_info->set_source_disasm(string_buffer_.ToString()); + debug_info->set_source_disasm(strdup(string_buffer_.buffer())); string_buffer_.Reset(); } @@ -171,7 +171,7 @@ bool PPCTranslator::Translate(GuestFunction* function, // Stash raw HIR. if (debug_info_flags & DebugInfoFlags::kDebugInfoDisasmRawHir) { builder_->Dump(&string_buffer_); - debug_info->set_raw_hir_disasm(string_buffer_.ToString()); + debug_info->set_raw_hir_disasm(strdup(string_buffer_.buffer())); string_buffer_.Reset(); } @@ -183,7 +183,7 @@ bool PPCTranslator::Translate(GuestFunction* function, // Stash optimized HIR. if (debug_info_flags & DebugInfoFlags::kDebugInfoDisasmHir) { builder_->Dump(&string_buffer_); - debug_info->set_hir_disasm(string_buffer_.ToString()); + debug_info->set_hir_disasm(strdup(string_buffer_.buffer())); string_buffer_.Reset(); } @@ -201,7 +201,7 @@ void PPCTranslator::DumpSource(GuestFunction* function, Memory* memory = frontend_->memory(); string_buffer->AppendFormat( - "%s fn %.8X-%.8X %s\n", function->module()->name().c_str(), + "{} fn {:08X}-{:08X} {}\n", function->module()->name().c_str(), function->address(), function->end_address(), function->name().c_str()); auto blocks = scanner_->FindBlocks(function); @@ -216,12 +216,12 @@ void PPCTranslator::DumpSource(GuestFunction* function, // Check labels. if (block_it != blocks.end() && block_it->start_address == address) { - string_buffer->AppendFormat("%.8X loc_%.8X:\n", address, + string_buffer->AppendFormat("{:08X} loc_{:08X}:\n", address, address); ++block_it; } - string_buffer->AppendFormat("%.8X %.8X ", address, code); + string_buffer->AppendFormat("{:08X} {:08X} ", address, code); DisasmPPC(address, code, string_buffer); string_buffer->Append('\n'); } diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc index b929707be..992c497fe 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc @@ -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. * ****************************************************************************** */ @@ -23,10 +23,10 @@ #include "xenia/base/platform_win.h" #endif // XE_COMPILER_MSVC -DEFINE_string(test_path, "src/xenia/cpu/ppc/testing/", - "Directory scanned for test files.", "Other"); -DEFINE_string(test_bin_path, "src/xenia/cpu/ppc/testing/bin/", - "Directory with binary outputs of the test files.", "Other"); +DEFINE_path(test_path, "src/xenia/cpu/ppc/testing/", + "Directory scanned for test files.", "Other"); +DEFINE_path(test_bin_path, "src/xenia/cpu/ppc/testing/bin/", + "Directory with binary outputs of the test files.", "Other"); DEFINE_transient_string(test_name, "", "Specifies test name.", "General"); namespace xe { @@ -49,43 +49,45 @@ struct TestCase { class TestSuite { public: - TestSuite(const std::wstring& src_file_path) : src_file_path(src_file_path) { - name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) + - 1); - name = ReplaceExtension(name, L""); - map_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".map"; - bin_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".bin"; + TestSuite(const std::filesystem::path& src_file_path) + : src_file_path_(src_file_path) { + auto name = src_file_path.filename(); + name = name.replace_extension(); + + name_ = xe::path_to_utf8(name); + map_file_path_ = cvars::test_bin_path / name.replace_extension(".map"); + bin_file_path_ = cvars::test_bin_path / name.replace_extension(".bin"); } bool Load() { - if (!ReadMap(map_file_path)) { - XELOGE("Unable to read map for test %ls", src_file_path.c_str()); + if (!ReadMap()) { + XELOGE("Unable to read map for test %s", + xe::path_to_utf8(src_file_path_).c_str()); return false; } - if (!ReadAnnotations(src_file_path)) { - XELOGE("Unable to read annotations for test %ls", src_file_path.c_str()); + if (!ReadAnnotations()) { + XELOGE("Unable to read annotations for test %s", + xe::path_to_utf8(src_file_path_).c_str()); return false; } return true; } - std::wstring name; - std::wstring src_file_path; - std::wstring map_file_path; - std::wstring bin_file_path; - std::vector test_cases; + const std::string& name() const { return name_; } + const std::filesystem::path& src_file_path() const { return src_file_path_; } + const std::filesystem::path& map_file_path() const { return map_file_path_; } + const std::filesystem::path& bin_file_path() const { return bin_file_path_; } + std::vector& test_cases() { return test_cases_; } private: - std::wstring ReplaceExtension(const std::wstring& path, - const std::wstring& new_extension) { - std::wstring result = path; - auto last_dot = result.find_last_of('.'); - result.replace(result.begin() + last_dot, result.end(), new_extension); - return result; - } + std::string name_; + std::filesystem::path src_file_path_; + std::filesystem::path map_file_path_; + std::filesystem::path bin_file_path_; + std::vector test_cases_; - TestCase* FindTestCase(const std::string& name) { - for (auto& test_case : test_cases) { + TestCase* FindTestCase(const std::string_view name) { + for (auto& test_case : test_cases_) { if (test_case.name == name) { return &test_case; } @@ -93,8 +95,8 @@ class TestSuite { return nullptr; } - bool ReadMap(const std::wstring& map_file_path) { - FILE* f = fopen(xe::to_string(map_file_path).c_str(), "r"); + bool ReadMap() { + FILE* f = filesystem::OpenFile(map_file_path_, "r"); if (!f) { return false; } @@ -114,15 +116,16 @@ class TestSuite { } std::string address(line_buffer, t_test_ - line_buffer); std::string name(t_test_ + strlen(" t test_")); - test_cases.emplace_back(START_ADDRESS + std::stoul(address, 0, 16), name); + test_cases_.emplace_back(START_ADDRESS + std::stoul(address, 0, 16), + name); } fclose(f); return true; } - bool ReadAnnotations(const std::wstring& src_file_path) { + bool ReadAnnotations() { TestCase* current_test_case = nullptr; - FILE* f = fopen(xe::to_string(src_file_path).c_str(), "r"); + FILE* f = filesystem::OpenFile(src_file_path_, "r"); if (!f) { return false; } @@ -141,8 +144,8 @@ class TestSuite { std::string label(start + strlen("test_"), strchr(start, ':')); current_test_case = FindTestCase(label); if (!current_test_case) { - XELOGE("Test case %s not found in corresponding map for %ls", - label.c_str(), src_file_path.c_str()); + XELOGE("Test case %s not found in corresponding map for %s", + label.c_str(), xe::path_to_utf8(src_file_path_).c_str()); return false; } } else if (strlen(start) > 3 && start[0] == '#' && start[1] == '_') { @@ -157,8 +160,8 @@ class TestSuite { value.erase(value.end() - 1); } if (!current_test_case) { - XELOGE("Annotation outside of test case in %ls", - src_file_path.c_str()); + XELOGE("Annotation outside of test case in %s", + xe::path_to_utf8(src_file_path_).c_str()); return false; } current_test_case->annotations.emplace_back(key, value); @@ -172,21 +175,20 @@ class TestSuite { class TestRunner { public: - TestRunner() { - memory_size = 64 * 1024 * 1024; - memory.reset(new Memory()); - memory->Initialize(); + TestRunner() : memory_size_(64 * 1024 * 1024) { + memory_.reset(new Memory()); + memory_->Initialize(); } ~TestRunner() { - thread_state.reset(); - processor.reset(); - memory.reset(); + thread_state_.reset(); + processor_.reset(); + memory_.reset(); } bool Setup(TestSuite& suite) { // Reset memory. - memory->Reset(); + memory_->Reset(); std::unique_ptr backend; if (!backend) { @@ -205,23 +207,24 @@ class TestRunner { } // Setup a fresh processor. - processor.reset(new Processor(memory.get(), nullptr)); - processor->Setup(std::move(backend)); - processor->set_debug_info_flags(DebugInfoFlags::kDebugInfoAll); + processor_.reset(new Processor(memory_.get(), nullptr)); + processor_->Setup(std::move(backend)); + processor_->set_debug_info_flags(DebugInfoFlags::kDebugInfoAll); // Load the binary module. - auto module = std::make_unique(processor.get()); - if (!module->LoadFile(START_ADDRESS, suite.bin_file_path)) { - XELOGE("Unable to load test binary %ls", suite.bin_file_path.c_str()); + auto module = std::make_unique(processor_.get()); + if (!module->LoadFile(START_ADDRESS, suite.bin_file_path())) { + XELOGE("Unable to load test binary %s", + xe::path_to_utf8(suite.bin_file_path).c_str()); return false; } - processor->AddModule(std::move(module)); + processor_->AddModule(std::move(module)); - processor->backend()->CommitExecutableRange(START_ADDRESS, - START_ADDRESS + 1024 * 1024); + processor_->backend()->CommitExecutableRange(START_ADDRESS, + START_ADDRESS + 1024 * 1024); // Add dummy space for memory. - processor->memory()->LookupHeap(0)->AllocFixed( + processor_->memory()->LookupHeap(0)->AllocFixed( 0x10001000, 0xEFFF, 0, kMemoryAllocationReserve | kMemoryAllocationCommit, kMemoryProtectRead | kMemoryProtectWrite); @@ -230,8 +233,8 @@ class TestRunner { uint32_t stack_size = 64 * 1024; uint32_t stack_address = START_ADDRESS - stack_size; uint32_t pcr_address = stack_address - 0x1000; - thread_state.reset( - new ThreadState(processor.get(), 0x100, stack_address, pcr_address)); + thread_state_.reset( + new ThreadState(processor_.get(), 0x100, stack_address, pcr_address)); return true; } @@ -244,15 +247,15 @@ class TestRunner { } // Execute test. - auto fn = processor->ResolveFunction(test_case.address); + auto fn = processor_->ResolveFunction(test_case.address); if (!fn) { XELOGE("Entry function not found"); return false; } - auto ctx = thread_state->context(); + auto ctx = thread_state_->context(); ctx->lr = 0xBCBCBCBC; - fn->Call(thread_state.get(), uint32_t(ctx->lr)); + fn->Call(thread_state_.get(), uint32_t(ctx->lr)); // Assert test state expectations. bool result = CheckTestResults(test_case); @@ -267,7 +270,7 @@ class TestRunner { } bool SetupTestState(TestCase& test_case) { - auto ppc_context = thread_state->context(); + auto ppc_context = thread_state_->context(); for (auto& it : test_case.annotations) { if (it.first == "REGISTER_IN") { size_t space_pos = it.second.find(" "); @@ -279,7 +282,7 @@ class TestRunner { auto address_str = it.second.substr(0, space_pos); auto bytes_str = it.second.substr(space_pos + 1); uint32_t address = std::strtoul(address_str.c_str(), nullptr, 16); - auto p = memory->TranslateVirtual(address); + auto p = memory_->TranslateVirtual(address); const char* c = bytes_str.c_str(); while (*c) { while (*c == ' ') ++c; @@ -298,9 +301,7 @@ class TestRunner { } bool CheckTestResults(TestCase& test_case) { - auto ppc_context = thread_state->context(); - - char actual_value[2048]; + auto ppc_context = thread_state_->context(); bool any_failed = false; for (auto& it : test_case.annotations) { @@ -308,9 +309,9 @@ class TestRunner { size_t space_pos = it.second.find(" "); auto reg_name = it.second.substr(0, space_pos); auto reg_value = it.second.substr(space_pos + 1); - if (!ppc_context->CompareRegWithString(reg_name.c_str(), - reg_value.c_str(), actual_value, - xe::countof(actual_value))) { + std::string actual_value; + if (!ppc_context->CompareRegWithString( + reg_name.c_str(), reg_value.c_str(), actual_value)) { any_failed = true; XELOGE("Register %s assert failed:\n", reg_name.c_str()); XELOGE(" Expected: %s == %s\n", reg_name.c_str(), reg_value.c_str()); @@ -321,7 +322,7 @@ class TestRunner { auto address_str = it.second.substr(0, space_pos); auto bytes_str = it.second.substr(space_pos + 1); uint32_t address = std::strtoul(address_str.c_str(), nullptr, 16); - auto base_address = memory->TranslateVirtual(address); + auto base_address = memory_->TranslateVirtual(address); auto p = base_address; const char* c = bytes_str.c_str(); while (*c) { @@ -348,19 +349,18 @@ class TestRunner { return !any_failed; } - size_t memory_size; - std::unique_ptr memory; - std::unique_ptr processor; - std::unique_ptr thread_state; + size_t memory_size_; + std::unique_ptr memory_; + std::unique_ptr processor_; + std::unique_ptr thread_state_; }; -bool DiscoverTests(std::wstring& test_path, - std::vector& test_files) { +bool DiscoverTests(const std::filesystem::path& test_path, + std::vector& test_files) { auto file_infos = xe::filesystem::ListFiles(test_path); for (auto& file_info : file_infos) { - if (file_info.name != L"." && file_info.name != L".." && - file_info.name.rfind(L".s") == file_info.name.size() - 2) { - test_files.push_back(xe::join_paths(test_path, file_info.name)); + if (file_info.name.extension() == ".s") { + test_files.push_back(test_path / file_info.name); } } return true; @@ -401,14 +401,16 @@ void ProtectedRunTest(TestSuite& test_suite, TestRunner& runner, #endif // XE_COMPILER_MSVC } -bool RunTests(const std::wstring& test_name) { +bool RunTests(const std::string_view test_name) { int result_code = 1; int failed_count = 0; int passed_count = 0; - auto test_path_root = - xe::fix_path_separators(xe::to_wstring(cvars::test_path)); - std::vector test_files; + XELOGI("Haswell instruction usage {}.", + cvars::use_haswell_instructions ? "enabled" : "disabled"); + + auto test_path_root = cvars::test_path; + std::vector test_files; if (!DiscoverTests(test_path_root, test_files)) { return false; } @@ -423,11 +425,12 @@ bool RunTests(const std::wstring& test_name) { bool load_failed = false; for (auto& test_path : test_files) { TestSuite test_suite(test_path); - if (!test_name.empty() && test_suite.name != test_name) { + if (!test_name.empty() && test_suite.name() != test_name) { continue; } if (!test_suite.Load()) { - XELOGE("TEST SUITE %ls FAILED TO LOAD", test_path.c_str()); + XELOGE("TEST SUITE %s FAILED TO LOAD", + xe::path_to_utf8(test_path).c_str()); load_failed = true; continue; } @@ -440,9 +443,9 @@ bool RunTests(const std::wstring& test_name) { XELOGI("%d tests loaded.", (int)test_suites.size()); TestRunner runner; for (auto& test_suite : test_suites) { - XELOGI("%ls.s:", test_suite.name.c_str()); + XELOGI("%s.s:", xe::path_to_utf8(test_suite.name()).c_str()); - for (auto& test_case : test_suite.test_cases) { + for (auto& test_case : test_suite.test_cases()) { XELOGI(" - %s", test_case.name.c_str()); ProtectedRunTest(test_suite, runner, test_case, failed_count, passed_count); @@ -459,9 +462,9 @@ bool RunTests(const std::wstring& test_name) { return failed_count ? false : true; } -int main(const std::vector& args) { +int main(const std::vector& args) { // Grab test name, if present. - std::wstring test_name; + std::string test_name; if (args.size() >= 2) { test_name = args[1]; } @@ -473,5 +476,5 @@ int main(const std::vector& args) { } // namespace cpu } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-cpu-ppc-test", xe::cpu::test::main, "[test name]", +DEFINE_ENTRY_POINT("xenia-cpu-ppc-test", xe::cpu::test::main, "[test name]", "test_name"); diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc index 61d38412d..c5f835133 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2017 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. * ****************************************************************************** */ @@ -87,7 +87,7 @@ class TestSuite { return result; } - TestCase* FindTestCase(const std::string& name) { + TestCase* FindTestCase(const std::string_view name) { for (auto& test_case : test_cases) { if (test_case.name == name) { return &test_case; diff --git a/src/xenia/cpu/ppc/testing/premake5.lua b/src/xenia/cpu/ppc/testing/premake5.lua index e318d8db5..b9c007b27 100644 --- a/src/xenia/cpu/ppc/testing/premake5.lua +++ b/src/xenia/cpu/ppc/testing/premake5.lua @@ -7,12 +7,13 @@ project("xenia-cpu-ppc-tests") kind("ConsoleApp") language("C++") links({ + "capstone", -- cpu-backend-x64 + "fmt", + "mspack", "xenia-core", "xenia-cpu-backend-x64", "xenia-cpu", "xenia-base", - "capstone", -- cpu-backend-x64 - "mspack", }) files({ "ppc_testing_main.cc", @@ -40,6 +41,7 @@ project("xenia-cpu-ppc-nativetests") kind("ConsoleApp") language("C++") links({ + "fmt", "xenia-base", }) files({ diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 278c60de8..c36d77a32 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -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. * ****************************************************************************** */ @@ -42,8 +42,8 @@ DEFINE_bool(debug, DEFAULT_DEBUG_FLAG, "Allow debugging and retain debug information.", "General"); -DEFINE_string(trace_function_data_path, "", "File to write trace data to.", - "CPU"); +DEFINE_path(trace_function_data_path, "", "File to write trace data to.", + "CPU"); DEFINE_bool(break_on_start, false, "Break into the debugger on startup.", "CPU"); @@ -140,7 +140,7 @@ bool Processor::Setup(std::unique_ptr backend) { } // Open the trace data path, if requested. - functions_trace_path_ = xe::to_wstring(cvars::trace_function_data_path); + functions_trace_path_ = cvars::trace_function_data_path; if (!functions_trace_path_.empty()) { functions_trace_file_ = ChunkedMappedMemoryWriter::Open( functions_trace_path_, 32 * 1024 * 1024, true); @@ -167,7 +167,7 @@ bool Processor::AddModule(std::unique_ptr module) { return true; } -Module* Processor::GetModule(const char* name) { +Module* Processor::GetModule(const std::string_view name) { auto global_lock = global_critical_region_.Acquire(); for (const auto& module : modules_) { if (module->name() == name) { @@ -186,7 +186,7 @@ std::vector Processor::GetModules() { return clone; } -Function* Processor::DefineBuiltin(const std::string& name, +Function* Processor::DefineBuiltin(const std::string_view name, BuiltinFunction::Handler handler, void* arg0, void* arg1) { uint32_t address = next_builtin_address_; diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index bb8709a72..eb395fb56 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -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. * ****************************************************************************** */ @@ -99,12 +99,11 @@ class Processor { } bool AddModule(std::unique_ptr module); - Module* GetModule(const char* name); - Module* GetModule(const std::string& name) { return GetModule(name.c_str()); } + Module* GetModule(const std::string_view name); std::vector GetModules(); Module* builtin_module() const { return builtin_module_; } - Function* DefineBuiltin(const std::string& name, + Function* DefineBuiltin(const std::string_view name, BuiltinFunction::Handler handler, void* arg0, void* arg1); @@ -245,7 +244,7 @@ class Processor { // Which debug features are enabled in generated code. uint32_t debug_info_flags_ = 0; // If specified, the file trace data gets written to when running. - std::wstring functions_trace_path_; + std::filesystem::path functions_trace_path_; std::unique_ptr functions_trace_file_; std::unique_ptr frontend_; diff --git a/src/xenia/cpu/raw_module.cc b/src/xenia/cpu/raw_module.cc index ae51067c7..9a4e1b8d8 100644 --- a/src/xenia/cpu/raw_module.cc +++ b/src/xenia/cpu/raw_module.cc @@ -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. * ****************************************************************************** */ @@ -23,9 +23,9 @@ RawModule::RawModule(Processor* processor) RawModule::~RawModule() {} -bool RawModule::LoadFile(uint32_t base_address, const std::wstring& path) { - auto fixed_path = xe::fix_path_separators(path); - FILE* file = xe::filesystem::OpenFile(fixed_path, "rb"); +bool RawModule::LoadFile(uint32_t base_address, + const std::filesystem::path& path) { + FILE* file = xe::filesystem::OpenFile(path, "rb"); fseek(file, 0, SEEK_END); uint32_t file_length = static_cast(ftell(file)); fseek(file, 0, SEEK_SET); @@ -48,12 +48,7 @@ bool RawModule::LoadFile(uint32_t base_address, const std::wstring& path) { fclose(file); // Setup debug info. - auto last_slash = fixed_path.find_last_of(xe::kPathSeparator); - if (last_slash != std::string::npos) { - name_ = xe::to_string(fixed_path.substr(last_slash + 1)); - } else { - name_ = xe::to_string(fixed_path); - } + name_ = xe::path_to_utf8(path.filename()); // TODO(benvanik): debug info low_address_ = base_address; diff --git a/src/xenia/cpu/raw_module.h b/src/xenia/cpu/raw_module.h index d7687643e..2853680fb 100644 --- a/src/xenia/cpu/raw_module.h +++ b/src/xenia/cpu/raw_module.h @@ -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,7 +22,7 @@ class RawModule : public Module { explicit RawModule(Processor* processor); ~RawModule() override; - bool LoadFile(uint32_t base_address, const std::wstring& path); + bool LoadFile(uint32_t base_address, const std::filesystem::path& path); // Set address range if you've already allocated memory and placed code // in it. @@ -30,7 +30,7 @@ class RawModule : public Module { const std::string& name() const override { return name_; } bool is_executable() const override { return is_executable_; } - void set_name(const std::string& name) { name_ = name; } + void set_name(const std::string_view name) { name_ = name; } void set_executable(bool is_executable) { is_executable_ = is_executable; } bool ContainsAddress(uint32_t address) override; diff --git a/src/xenia/cpu/symbol.h b/src/xenia/cpu/symbol.h index f4de1d339..10d5add1f 100644 --- a/src/xenia/cpu/symbol.h +++ b/src/xenia/cpu/symbol.h @@ -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. * ****************************************************************************** */ @@ -45,7 +45,7 @@ class Symbol { uint32_t address() const { return address_; } const std::string& name() const { return name_; } - void set_name(const std::string& value) { name_ = value; } + void set_name(const std::string_view value) { name_ = value; } protected: Type type_ = Type::kVariable; diff --git a/src/xenia/cpu/test_module.cc b/src/xenia/cpu/test_module.cc index 7c117ee79..9ad0c12b9 100644 --- a/src/xenia/cpu/test_module.cc +++ b/src/xenia/cpu/test_module.cc @@ -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. * ****************************************************************************** */ @@ -24,7 +24,7 @@ using xe::cpu::compiler::Compiler; using xe::cpu::hir::HIRBuilder; namespace passes = xe::cpu::compiler::passes; -TestModule::TestModule(Processor* processor, const std::string& name, +TestModule::TestModule(Processor* processor, const std::string_view name, std::function contains_address, std::function generate) : Module(processor), diff --git a/src/xenia/cpu/test_module.h b/src/xenia/cpu/test_module.h index c745a55f9..7dc52dbe1 100644 --- a/src/xenia/cpu/test_module.h +++ b/src/xenia/cpu/test_module.h @@ -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. * ****************************************************************************** */ @@ -24,7 +24,7 @@ namespace cpu { class TestModule : public Module { public: - TestModule(Processor* processor, const std::string& name, + TestModule(Processor* processor, const std::string_view name, std::function contains_address, std::function generate); ~TestModule() override; diff --git a/src/xenia/cpu/testing/premake5.lua b/src/xenia/cpu/testing/premake5.lua index a3c2b8566..c951243e0 100644 --- a/src/xenia/cpu/testing/premake5.lua +++ b/src/xenia/cpu/testing/premake5.lua @@ -4,6 +4,7 @@ include(project_root.."/tools/build") test_suite("xenia-cpu-tests", project_root, ".", { links = { "capstone", + "fmt", "xenia-base", "xenia-core", "xenia-cpu", diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 7208b55b9..ed2cce904 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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,8 @@ #include +#include "third_party/fmt/include/fmt/format.h" + #include "xenia/base/byte_order.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -156,7 +158,7 @@ uint32_t XexModule::GetProcAddress(uint16_t ordinal) const { return 0; } -uint32_t XexModule::GetProcAddress(const char* name) const { +uint32_t XexModule::GetProcAddress(const std::string_view name) const { assert_not_zero(base_address_); xex2_opt_data_directory* pe_export_directory = 0; @@ -185,7 +187,7 @@ uint32_t XexModule::GetProcAddress(const char* name) const { auto fn_name = reinterpret_cast(uintptr_t(e) + name_table[i]); uint16_t ordinal = ordinal_table[i]; uint32_t addr = base_address_ + function_table[ordinal]; - if (!std::strcmp(name, fn_name)) { + if (name == std::string_view(fn_name)) { // We have a match! return addr; } @@ -865,7 +867,7 @@ int XexModule::ReadPEHeaders() { return 0; } -bool XexModule::Load(const std::string& name, const std::string& path, +bool XexModule::Load(const std::string_view name, const std::string_view path, const void* xex_addr, size_t xex_length) { auto src_header = reinterpret_cast(xex_addr); @@ -922,8 +924,8 @@ bool XexModule::Load(const std::string& name, const std::string& path, base_address_ = *base_addr_opt; // Setup debug info. - name_ = std::string(name); - path_ = std::string(path); + name_ = name; + path_ = path; uint8_t* data = memory()->TranslateVirtual(base_address_); @@ -1027,7 +1029,8 @@ bool XexModule::LoadContinue() { assert_true(library_name_index < opt_import_libraries->string_table.count); assert_not_null(string_table[library_name_index]); - SetupLibraryImports(string_table[library_name_index], library); + auto library_name = std::string(string_table[library_name_index]); + SetupLibraryImports(library_name, library); library_offset += library->size; } } @@ -1087,7 +1090,7 @@ bool XexModule::Unload() { return true; } -bool XexModule::SetupLibraryImports(const char* name, +bool XexModule::SetupLibraryImports(const std::string_view name, const xex2_import_library* library) { ExportResolver* kernel_resolver = nullptr; if (kernel_state_->IsKernelModule(name)) { @@ -1096,14 +1099,10 @@ bool XexModule::SetupLibraryImports(const char* name, auto user_module = kernel_state_->GetModule(name); - std::string libbasename = name; - auto dot = libbasename.find_last_of('.'); - if (dot != libbasename.npos) { - libbasename = libbasename.substr(0, dot); - } + auto base_name = utf8::find_base_name_from_guest_path(name); ImportLibrary library_info; - library_info.name = libbasename; + library_info.name = base_name; library_info.id = library->id; library_info.version.value = library->version.value; library_info.min_version.value = library->version_min.value; @@ -1135,7 +1134,7 @@ bool XexModule::SetupLibraryImports(const char* name, XELOGW( "WARNING: an import variable was not resolved! (library: %s, import " "lib: %s, ordinal: %.3X)", - name_.c_str(), name, ordinal); + name_.c_str(), name.c_str(), ordinal); } StringBuffer import_name; @@ -1147,11 +1146,11 @@ bool XexModule::SetupLibraryImports(const char* name, import_info.value_address = record_addr; library_info.imports.push_back(import_info); - import_name.AppendFormat("__imp__"); + import_name.Append("__imp__"); if (kernel_export) { - import_name.AppendFormat("%s", kernel_export->name); + import_name.Append(kernel_export->name); } else { - import_name.AppendFormat("%s_%.3X", libbasename.c_str(), ordinal); + import_name.AppendFormat("{}_{:03X}", base_name, ordinal); } if (kernel_export) { @@ -1180,7 +1179,7 @@ bool XexModule::SetupLibraryImports(const char* name, // Setup a variable and define it. Symbol* var_info; DeclareVariable(record_addr, &var_info); - var_info->set_name(import_name.GetString()); + var_info->set_name(import_name.to_string_view()); var_info->set_status(Symbol::Status::kDeclared); DefineVariable(var_info); var_info->set_status(Symbol::Status::kDefined); @@ -1194,15 +1193,15 @@ bool XexModule::SetupLibraryImports(const char* name, } if (kernel_export) { - import_name.AppendFormat("%s", kernel_export->name); + import_name.Append(kernel_export->name); } else { - import_name.AppendFormat("__%s_%.3X", libbasename.c_str(), ordinal); + import_name.AppendFormat("__{}_{:03X}", base_name, ordinal); } Function* function; DeclareFunction(record_addr, &function); function->set_end_address(record_addr + 16 - 4); - function->set_name(import_name.GetString()); + function->set_name(import_name.to_string_view()); if (user_export_addr) { // Rewrite PPC code to set r11 to the target address @@ -1253,7 +1252,7 @@ bool XexModule::SetupLibraryImports(const char* name, } } else { XELOGW("WARNING: Imported kernel function %s is unimplemented!", - import_name.GetString()); + import_name.buffer()); } static_cast(function)->SetupExtern(handler, kernel_export); @@ -1488,11 +1487,12 @@ bool XexModule::FindSaveRest() { if (gplr_start) { uint32_t address = gplr_start; for (int n = 14; n <= 31; n++) { - snprintf(name, xe::countof(name), "__savegprlr_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__savegprlr_{}", n); Function* function; DeclareFunction(address, &function); function->set_end_address(address + (31 - n) * 4 + 2 * 4); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveGprLr; function->set_behavior(Function::Behavior::kProlog); @@ -1501,11 +1501,12 @@ bool XexModule::FindSaveRest() { } address = gplr_start + 20 * 4; for (int n = 14; n <= 31; n++) { - snprintf(name, xe::countof(name), "__restgprlr_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__restgprlr_{}", n); Function* function; DeclareFunction(address, &function); function->set_end_address(address + (31 - n) * 4 + 3 * 4); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestGprLr; function->set_behavior(Function::Behavior::kEpilogReturn); @@ -1516,11 +1517,12 @@ bool XexModule::FindSaveRest() { if (fpr_start) { uint32_t address = fpr_start; for (int n = 14; n <= 31; n++) { - snprintf(name, xe::countof(name), "__savefpr_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__savefpr_{}", n); Function* function; DeclareFunction(address, &function); function->set_end_address(address + (31 - n) * 4 + 1 * 4); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveFpr; function->set_behavior(Function::Behavior::kProlog); @@ -1529,11 +1531,12 @@ bool XexModule::FindSaveRest() { } address = fpr_start + (18 * 4) + (1 * 4); for (int n = 14; n <= 31; n++) { - snprintf(name, xe::countof(name), "__restfpr_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__restfpr_{}", n); Function* function; DeclareFunction(address, &function); function->set_end_address(address + (31 - n) * 4 + 1 * 4); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestFpr; function->set_behavior(Function::Behavior::kEpilog); @@ -1549,10 +1552,11 @@ bool XexModule::FindSaveRest() { // 64-127 rest uint32_t address = vmx_start; for (int n = 14; n <= 31; n++) { - snprintf(name, xe::countof(name), "__savevmx_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__savevmx_{}", n); Function* function; DeclareFunction(address, &function); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx; function->set_behavior(Function::Behavior::kProlog); @@ -1561,10 +1565,11 @@ bool XexModule::FindSaveRest() { } address += 4; for (int n = 64; n <= 127; n++) { - snprintf(name, xe::countof(name), "__savevmx_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__savevmx_{}", n); Function* function; DeclareFunction(address, &function); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx; function->set_behavior(Function::Behavior::kProlog); @@ -1573,10 +1578,11 @@ bool XexModule::FindSaveRest() { } address = vmx_start + (18 * 2 * 4) + (1 * 4) + (64 * 2 * 4) + (1 * 4); for (int n = 14; n <= 31; n++) { - snprintf(name, xe::countof(name), "__restvmx_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__restvmx_{}", n); Function* function; DeclareFunction(address, &function); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx; function->set_behavior(Function::Behavior::kEpilog); @@ -1585,10 +1591,11 @@ bool XexModule::FindSaveRest() { } address += 4; for (int n = 64; n <= 127; n++) { - snprintf(name, xe::countof(name), "__restvmx_%d", n); + auto format_result = + fmt::format_to_n(name, xe::countof(name), "__restvmx_{}", n); Function* function; DeclareFunction(address, &function); - function->set_name(name); + function->set_name(std::string_view(name, format_result.size)); // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx; function->set_behavior(Function::Behavior::kEpilog); diff --git a/src/xenia/cpu/xex_module.h b/src/xenia/cpu/xex_module.h index e2c5f5a3b..207d7a1ac 100644 --- a/src/xenia/cpu/xex_module.h +++ b/src/xenia/cpu/xex_module.h @@ -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. * ****************************************************************************** */ @@ -132,10 +132,10 @@ class XexModule : public xe::cpu::Module { const PESection* GetPESection(const char* name); uint32_t GetProcAddress(uint16_t ordinal) const; - uint32_t GetProcAddress(const char* name) const; + uint32_t GetProcAddress(const std::string_view name) const; int ApplyPatch(XexModule* module); - bool Load(const std::string& name, const std::string& path, + bool Load(const std::string_view name, const std::string_view path, const void* xex_addr, size_t xex_length); bool LoadContinue(); bool Unload(); @@ -177,7 +177,7 @@ class XexModule : public xe::cpu::Module { int ReadPEHeaders(); - bool SetupLibraryImports(const char* name, + bool SetupLibraryImports(const std::string_view name, const xex2_import_library* library); bool FindSaveRest(); diff --git a/src/xenia/debug/ui/debug_window.cc b/src/xenia/debug/ui/debug_window.cc index 2fd758d24..590a66062 100644 --- a/src/xenia/debug/ui/debug_window.cc +++ b/src/xenia/debug/ui/debug_window.cc @@ -18,6 +18,7 @@ #include "third_party/imgui/imgui.h" #include "third_party/imgui/imgui_internal.h" #include "xenia/base/clock.h" +#include "xenia/base/fuzzy.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/platform.h" @@ -47,7 +48,7 @@ using xe::ui::MenuItem; using xe::ui::MouseEvent; using xe::ui::UIEvent; -const std::wstring kBaseTitle = L"Xenia Debugger"; +const std::string kBaseTitle = "Xenia Debugger"; DebugWindow::DebugWindow(Emulator* emulator, xe::ui::Loop* loop) : emulator_(emulator), @@ -90,10 +91,10 @@ bool DebugWindow::Initialize() { // Main menu. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); - auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File"); + auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"&Close", - L"Alt+F4", + file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close", + "Alt+F4", [this]() { window_->Close(); })); } main_menu->AddChild(std::move(file_menu)); @@ -291,7 +292,7 @@ void DebugWindow::DrawToolbar() { ++i; } if (ImGui::Combo("##thread_combo", ¤t_thread_index, - thread_combo.GetString(), 10)) { + thread_combo.buffer(), 10)) { // Thread changed. SelectThreadStackFrame(cache_.thread_debug_infos[current_thread_index], 0, true); @@ -509,7 +510,7 @@ void DebugWindow::DrawGuestFunctionSource() { uint32_t code = xe::load_and_swap(memory->TranslateVirtual(address)); cpu::ppc::DisasmPPC(address, code, &str); - ImGui::Text("%.8X %.8X %s", address, code, str.GetString()); + ImGui::Text("%.8X %.8X %s", address, code, str.buffer()); str.Reset(); if (is_current_instr) { @@ -1425,19 +1426,19 @@ void DebugWindow::UpdateCache() { auto object_table = kernel_state->object_table(); loop_->Post([this]() { - std::wstring title = kBaseTitle; + std::string title = kBaseTitle; switch (processor_->execution_state()) { case cpu::ExecutionState::kEnded: - title += L" (ended)"; + title += " (ended)"; break; case cpu::ExecutionState::kPaused: - title += L" (paused)"; + title += " (paused)"; break; case cpu::ExecutionState::kRunning: - title += L" (running)"; + title += " (running)"; break; case cpu::ExecutionState::kStepping: - title += L" (stepping)"; + title += " (stepping)"; break; } window_->set_title(title); diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 9f33b784c..e7833826c 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -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. * ****************************************************************************** */ @@ -12,6 +12,7 @@ #include #include "config.h" +#include "third_party/fmt/include/fmt/format.h" #include "xenia/apu/audio_system.h" #include "xenia/base/assert.h" #include "xenia/base/byte_stream.h" @@ -56,9 +57,9 @@ DEFINE_string( namespace xe { -Emulator::Emulator(const std::wstring& command_line, - const std::wstring& storage_root, - const std::wstring& content_root) +Emulator::Emulator(const std::filesystem::path& command_line, + const std::filesystem::path& storage_root, + const std::filesystem::path& content_root) : on_launch(), on_terminate(), on_exit(), @@ -241,27 +242,22 @@ X_STATUS Emulator::TerminateTitle() { kernel_state_->TerminateTitle(); title_id_ = 0; - game_title_ = L""; + game_title_ = ""; on_terminate(); return X_STATUS_SUCCESS; } -X_STATUS Emulator::LaunchPath(std::wstring path) { +X_STATUS Emulator::LaunchPath(const std::filesystem::path& path) { // Launch based on file type. // This is a silly guess based on file extension. - auto last_slash = path.find_last_of(xe::kPathSeparator); - auto last_dot = path.find_last_of('.'); - if (last_dot < last_slash) { - last_dot = std::wstring::npos; - } - if (last_dot == std::wstring::npos) { + if (!path.has_extension()) { // Likely an STFS container. return LaunchStfsContainer(path); }; - auto extension = path.substr(last_dot); + auto extension = xe::path_to_utf8(path.extension()); std::transform(extension.begin(), extension.end(), extension.begin(), tolower); - if (extension == L".xex" || extension == L".elf" || extension == L".exe") { + if (extension == ".xex" || extension == ".elf" || extension == ".exe") { // Treat as a naked xex file. return LaunchXexFile(path); } else { @@ -270,7 +266,7 @@ X_STATUS Emulator::LaunchPath(std::wstring path) { } } -X_STATUS Emulator::LaunchXexFile(std::wstring path) { +X_STATUS Emulator::LaunchXexFile(const std::filesystem::path& path) { // We create a virtual filesystem pointing to its directory and symlink // that to the game filesystem. // e.g., /my/files/foo.xex will get a local fs at: @@ -281,7 +277,7 @@ X_STATUS Emulator::LaunchXexFile(std::wstring path) { auto mount_path = "\\Device\\Harddisk0\\Partition0"; // Register the local directory in the virtual filesystem. - auto parent_path = xe::find_base_path(path); + auto parent_path = path.parent_path(); auto device = std::make_unique(mount_path, parent_path, true); if (!device->Initialize()) { @@ -298,14 +294,14 @@ X_STATUS Emulator::LaunchXexFile(std::wstring path) { file_system_->RegisterSymbolicLink("d:", mount_path); // Get just the filename (foo.xex). - auto file_name = xe::find_name_from_path(path); + auto file_name = path.filename(); // Launch the game. - std::string fs_path = "game:\\" + xe::to_string(file_name); + auto fs_path = "game:\\" + xe::path_to_utf8(file_name); return CompleteLaunch(path, fs_path); } -X_STATUS Emulator::LaunchDiscImage(std::wstring path) { +X_STATUS Emulator::LaunchDiscImage(const std::filesystem::path& path) { auto mount_path = "\\Device\\Cdrom0"; // Register the disc image in the virtual filesystem. @@ -328,7 +324,7 @@ X_STATUS Emulator::LaunchDiscImage(std::wstring path) { return CompleteLaunch(path, module_path); } -X_STATUS Emulator::LaunchStfsContainer(std::wstring path) { +X_STATUS Emulator::LaunchStfsContainer(const std::filesystem::path& path) { auto mount_path = "\\Device\\Cdrom0"; // Register the container in the virtual filesystem. @@ -407,7 +403,7 @@ void Emulator::Resume() { } } -bool Emulator::SaveToFile(const std::wstring& path) { +bool Emulator::SaveToFile(const std::filesystem::path& path) { Pause(); filesystem::CreateFile(path); @@ -435,7 +431,7 @@ bool Emulator::SaveToFile(const std::wstring& path) { return true; } -bool Emulator::RestoreFromFile(const std::wstring& path) { +bool Emulator::RestoreFromFile(const std::filesystem::path& path) { // Restore the emulator state from a file auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite); if (!map) { @@ -509,7 +505,7 @@ void Emulator::LaunchNextTitle() { auto xam = kernel_state()->GetKernelModule("xam.xex"); auto next_title = xam->loader_data().launch_path; - CompleteLaunch(L"", next_title); + CompleteLaunch("", next_title); } bool Emulator::ExceptionCallbackThunk(Exception* ex, void* data) { @@ -642,20 +638,20 @@ std::string Emulator::FindLaunchModule() { return path + default_module; } -X_STATUS Emulator::CompleteLaunch(const std::wstring& path, - const std::string& module_path) { +X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, + const std::string_view module_path) { // Reset state. title_id_ = 0; - game_title_ = L""; + game_title_ = ""; display_window_->SetIcon(nullptr, 0); // Allow xam to request module loads. auto xam = kernel_state()->GetKernelModule("xam.xex"); XELOGI("Launching module %s", module_path.c_str()); - auto module = kernel_state_->LoadUserModule(module_path.c_str()); + auto module = kernel_state_->LoadUserModule(module_path); if (!module) { - XELOGE("Failed to load user module %S", path.c_str()); + XELOGE("Failed to load user module %s", xe::path_to_utf8(path).c_str()); return X_STATUS_NOT_FOUND; } @@ -668,17 +664,16 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path, // Try and load the resource database (xex only). if (module->title_id()) { - char title_id[9] = {0}; - std::snprintf(title_id, xe::countof(title_id), "%08X", module->title_id()); - config::LoadGameConfig(xe::to_wstring(title_id)); + auto title_id = fmt::format("{:08X}", module->title_id()); + config::LoadGameConfig(title_id); uint32_t resource_data = 0; uint32_t resource_size = 0; - if (XSUCCEEDED( - module->GetSection(title_id, &resource_data, &resource_size))) { + if (XSUCCEEDED(module->GetSection(title_id.c_str(), &resource_data, + &resource_size))) { kernel::util::XdbfGameData db( module->memory()->TranslateVirtual(resource_data), resource_size); if (db.is_valid()) { - game_title_ = xe::to_wstring(db.title()); + game_title_ = db.title(); auto icon_block = db.icon(); if (icon_block) { display_window_->SetIcon(icon_block.buffer, icon_block.size); diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index f973b6220..df5426227 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -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. * ****************************************************************************** */ @@ -47,22 +47,22 @@ namespace xe { // This is responsible for initializing and managing all the various subsystems. class Emulator { public: - explicit Emulator(const std::wstring& command_line, - const std::wstring& storage_root, - const std::wstring& content_root); + explicit Emulator(const std::filesystem::path& command_line, + const std::filesystem::path& storage_root, + const std::filesystem::path& content_root); ~Emulator(); // Full command line used when launching the process. - const std::wstring& command_line() const { return command_line_; } + const std::filesystem::path& command_line() const { return command_line_; } // Folder persistent internal emulator data is stored in. - const std::wstring& storage_root() const { return storage_root_; } + const std::filesystem::path& storage_root() const { return storage_root_; } // Folder guest content is stored in. - const std::wstring& content_root() const { return content_root_; } + const std::filesystem::path& content_root() const { return content_root_; } // Title of the game in the default language. - const std::wstring& game_title() const { return game_title_; } + const std::string& game_title() const { return game_title_; } // Currently running title ID uint32_t title_id() const { return title_id_; } @@ -123,24 +123,24 @@ class Emulator { // Launches a game from the given file path. // This will attempt to infer the type of the given file (such as an iso, etc) // using heuristics. - X_STATUS LaunchPath(std::wstring path); + X_STATUS LaunchPath(const std::filesystem::path& path); // Launches a game from a .xex file by mounting the containing folder as if it // was an extracted STFS container. - X_STATUS LaunchXexFile(std::wstring path); + X_STATUS LaunchXexFile(const std::filesystem::path& path); // Launches a game from a disc image file (.iso, etc). - X_STATUS LaunchDiscImage(std::wstring path); + X_STATUS LaunchDiscImage(const std::filesystem::path& path); // Launches a game from an STFS container file. - X_STATUS LaunchStfsContainer(std::wstring path); + X_STATUS LaunchStfsContainer(const std::filesystem::path& path); void Pause(); void Resume(); bool is_paused() const { return paused_; } - bool SaveToFile(const std::wstring& path); - bool RestoreFromFile(const std::wstring& path); + bool SaveToFile(const std::filesystem::path& path); + bool RestoreFromFile(const std::filesystem::path& path); // The game can request another title to be loaded. bool TitleRequested(); @@ -149,7 +149,7 @@ class Emulator { void WaitUntilExit(); public: - xe::Delegate on_launch; + xe::Delegate on_launch; xe::Delegate on_shader_storage_initialization; xe::Delegate<> on_terminate; xe::Delegate<> on_exit; @@ -160,14 +160,14 @@ class Emulator { std::string FindLaunchModule(); - X_STATUS CompleteLaunch(const std::wstring& path, - const std::string& module_path); + X_STATUS CompleteLaunch(const std::filesystem::path& path, + const std::string_view module_path); - std::wstring command_line_; - std::wstring storage_root_; - std::wstring content_root_; + std::filesystem::path command_line_; + std::filesystem::path storage_root_; + std::filesystem::path content_root_; - std::wstring game_title_; + std::string game_title_; ui::Window* display_window_; diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index 6ceddfea3..8f935f7e6 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -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. * ****************************************************************************** */ @@ -13,6 +13,7 @@ #include #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/byte_stream.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -87,11 +88,12 @@ void CommandProcessor::Shutdown() { worker_thread_.reset(); } -void CommandProcessor::InitializeShaderStorage(const std::wstring& storage_root, - uint32_t title_id, - bool blocking) {} +void CommandProcessor::InitializeShaderStorage( + const std::filesystem::path& storage_root, uint32_t title_id, + bool blocking) {} -void CommandProcessor::RequestFrameTrace(const std::wstring& root_path) { +void CommandProcessor::RequestFrameTrace( + const std::filesystem::path& root_path) { if (trace_state_ == TraceState::kStreaming) { XELOGE("Streaming trace; cannot also trace frame."); return; @@ -104,7 +106,7 @@ void CommandProcessor::RequestFrameTrace(const std::wstring& root_path) { trace_frame_path_ = root_path; } -void CommandProcessor::BeginTracing(const std::wstring& root_path) { +void CommandProcessor::BeginTracing(const std::filesystem::path& root_path) { if (trace_state_ == TraceState::kStreaming) { XELOGE("Streaming already active; ignoring request."); return; @@ -440,8 +442,8 @@ uint32_t CommandProcessor::ExecutePrimaryBuffer(uint32_t read_index, uint32_t title_id = kernel_state_->GetExecutableModule() ? kernel_state_->GetExecutableModule()->title_id() : 0; - auto file_name = xe::format_string(L"%8X_stream.xtr", title_id); - auto path = trace_stream_path_ + file_name; + auto file_name = fmt::format("{:8X}_stream.xtr", title_id); + auto path = trace_stream_path_ / file_name; trace_writer_.Open(path, title_id); InitializeTrace(); } @@ -754,8 +756,8 @@ bool CommandProcessor::ExecutePacketType3(RingBuffer* reader, uint32_t packet) { } else if (trace_state_ == TraceState::kSingleFrame) { // New trace request - we only start tracing at the beginning of a frame. uint32_t title_id = kernel_state_->GetExecutableModule()->title_id(); - auto file_name = xe::format_string(L"%8X_%u.xtr", title_id, counter_ - 1); - auto path = trace_frame_path_ + file_name; + auto file_name = fmt::format("{:8X}_{}.xtr", title_id, counter_ - 1); + auto path = trace_frame_path_ / file_name; trace_writer_.Open(path, title_id); InitializeTrace(); } diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h index 1be5345f6..ec1fcd76d 100644 --- a/src/xenia/gpu/command_processor.h +++ b/src/xenia/gpu/command_processor.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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. * ****************************************************************************** */ @@ -133,11 +133,12 @@ class CommandProcessor { // May be called not only from the command processor thread when the command // processor is paused, and the termination of this function may be explicitly // awaited. - virtual void InitializeShaderStorage(const std::wstring& storage_root, - uint32_t title_id, bool blocking); + virtual void InitializeShaderStorage( + const std::filesystem::path& storage_root, uint32_t title_id, + bool blocking); - virtual void RequestFrameTrace(const std::wstring& root_path); - virtual void BeginTracing(const std::wstring& root_path); + virtual void RequestFrameTrace(const std::filesystem::path& root_path); + virtual void BeginTracing(const std::filesystem::path& root_path); virtual void EndTracing(); virtual void TracePlaybackWroteMemory(uint32_t base_ptr, uint32_t length) = 0; @@ -264,8 +265,8 @@ class CommandProcessor { kSingleFrame, }; TraceState trace_state_ = TraceState::kDisabled; - std::wstring trace_stream_path_; - std::wstring trace_frame_path_; + std::filesystem::path trace_stream_path_; + std::filesystem::path trace_frame_path_; std::atomic worker_running_; kernel::object_ref worker_thread_; diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 9700d6314..ff1c0f567 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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. * ****************************************************************************** */ @@ -85,12 +85,14 @@ void D3D12CommandProcessor::ClearCaches() { } void D3D12CommandProcessor::InitializeShaderStorage( - const std::wstring& storage_root, uint32_t title_id, bool blocking) { + const std::filesystem::path& storage_root, uint32_t title_id, + bool blocking) { CommandProcessor::InitializeShaderStorage(storage_root, title_id, blocking); pipeline_cache_->InitializeShaderStorage(storage_root, title_id, blocking); } -void D3D12CommandProcessor::RequestFrameTrace(const std::wstring& root_path) { +void D3D12CommandProcessor::RequestFrameTrace( + const std::filesystem::path& root_path) { // Capture with PIX if attached. if (GetD3D12Context()->GetD3D12Provider()->GetGraphicsAnalysis() != nullptr) { pix_capture_requested_.store(true, std::memory_order_relaxed); @@ -668,16 +670,16 @@ void D3D12CommandProcessor::SetExternalGraphicsPipeline( } } -std::wstring D3D12CommandProcessor::GetWindowTitleText() const { +std::string D3D12CommandProcessor::GetWindowTitleText() const { if (IsROVUsedForEDRAM()) { // Currently scaling is only supported with ROV. if (texture_cache_ != nullptr && texture_cache_->IsResolutionScale2X()) { - return L"Direct3D 12 - ROV 2x"; + return "Direct3D 12 - ROV 2x"; } else { - return L"Direct3D 12 - ROV"; + return "Direct3D 12 - ROV"; } } else { - return L"Direct3D 12 - RTV/DSV"; + return "Direct3D 12 - RTV/DSV"; } } diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.h b/src/xenia/gpu/d3d12/d3d12_command_processor.h index 717dce6ef..d5bd3e3a8 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.h +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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,10 +43,10 @@ class D3D12CommandProcessor : public CommandProcessor { void ClearCaches() override; - void InitializeShaderStorage(const std::wstring& storage_root, + void InitializeShaderStorage(const std::filesystem::path& storage_root, uint32_t title_id, bool blocking) override; - void RequestFrameTrace(const std::wstring& root_path) override; + void RequestFrameTrace(const std::filesystem::path& root_path) override; void TracePlaybackWroteMemory(uint32_t base_ptr, uint32_t length) override; @@ -154,7 +154,7 @@ class D3D12CommandProcessor : public CommandProcessor { bool changing_stencil_ref = false); // Returns the text to display in the GPU backend name in the window title. - std::wstring GetWindowTitleText() const; + std::string GetWindowTitleText() const; std::unique_ptr Capture(); diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc index efba957b3..ca056e65e 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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,13 +31,13 @@ bool D3D12GraphicsSystem::IsAvailable() { return xe::ui::d3d12::D3D12Provider::IsD3D12APIAvailable(); } -std::wstring D3D12GraphicsSystem::name() const { +std::string D3D12GraphicsSystem::name() const { auto d3d12_command_processor = static_cast(command_processor()); if (d3d12_command_processor != nullptr) { return d3d12_command_processor->GetWindowTitleText(); } - return L"Direct3D 12"; + return "Direct3D 12"; } X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor, diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.h b/src/xenia/gpu/d3d12/d3d12_graphics_system.h index 93c585406..00faeb34f 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.h +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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,7 +28,7 @@ class D3D12GraphicsSystem : public GraphicsSystem { static bool IsAvailable(); - std::wstring name() const override; + std::string name() const override; X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, ui::Window* target_window) override; diff --git a/src/xenia/gpu/d3d12/d3d12_trace_dump_main.cc b/src/xenia/gpu/d3d12/d3d12_trace_dump_main.cc index c68b29788..127a2226f 100644 --- a/src/xenia/gpu/d3d12/d3d12_trace_dump_main.cc +++ b/src/xenia/gpu/d3d12/d3d12_trace_dump_main.cc @@ -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,7 +45,7 @@ class D3D12TraceDump : public TraceDump { } }; -int trace_dump_main(const std::vector& args) { +int trace_dump_main(const std::vector& args) { D3D12TraceDump trace_dump; return trace_dump.Main(args); } @@ -54,6 +54,6 @@ int trace_dump_main(const std::vector& args) { } // namespace gpu } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-gpu-d3d12-trace-dump", +DEFINE_ENTRY_POINT("xenia-gpu-d3d12-trace-dump", xe::gpu::d3d12::trace_dump_main, "some.trace", "target_trace_file"); diff --git a/src/xenia/gpu/d3d12/d3d12_trace_viewer_main.cc b/src/xenia/gpu/d3d12/d3d12_trace_viewer_main.cc index 064c92d44..52643bc2e 100644 --- a/src/xenia/gpu/d3d12/d3d12_trace_viewer_main.cc +++ b/src/xenia/gpu/d3d12/d3d12_trace_viewer_main.cc @@ -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. * ****************************************************************************** */ @@ -47,7 +47,7 @@ class D3D12TraceViewer : public TraceViewer { } }; -int trace_viewer_main(const std::vector& args) { +int trace_viewer_main(const std::vector& args) { D3D12TraceViewer trace_viewer; return trace_viewer.Main(args); } @@ -56,6 +56,6 @@ int trace_viewer_main(const std::vector& args) { } // namespace gpu } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-gpu-d3d12-trace-viewer", +DEFINE_ENTRY_POINT("xenia-gpu-d3d12-trace-viewer", xe::gpu::d3d12::trace_viewer_main, "some.trace", "target_trace_file"); diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index 5371bd56d..859cc713d 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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. * ****************************************************************************** */ @@ -18,8 +18,8 @@ #include #include +#include "third_party/fmt/include/fmt/format.h" #include "third_party/xxhash/xxhash.h" - #include "xenia/base/assert.h" #include "xenia/base/byte_order.h" #include "xenia/base/clock.h" @@ -138,7 +138,7 @@ void PipelineCache::Shutdown() { void PipelineCache::ClearCache(bool shutting_down) { bool reinitialize_shader_storage = !shutting_down && storage_write_thread_ != nullptr; - std::wstring shader_storage_root; + std::filesystem::path shader_storage_root; uint32_t shader_storage_title_id = shader_storage_title_id_; if (reinitialize_shader_storage) { shader_storage_root = shader_storage_root_; @@ -188,19 +188,19 @@ void PipelineCache::ClearCache(bool shutting_down) { } } -void PipelineCache::InitializeShaderStorage(const std::wstring& storage_root, - uint32_t title_id, bool blocking) { +void PipelineCache::InitializeShaderStorage( + const std::filesystem::path& storage_root, uint32_t title_id, + bool blocking) { ShutdownShaderStorage(); - auto shader_storage_root = xe::join_paths(storage_root, L"shaders"); + auto shader_storage_root = storage_root / "shaders"; // For files that can be moved between different hosts. // Host PSO blobs - if ever added - should be stored in shaders/local/ (they // currently aren't used because because they may be not very practical - // would need to invalidate them every commit likely, and additional I/O // cost - though D3D's internal validation would possibly be enough to ensure // they are up to date). - auto shader_storage_shareable_root = - xe::join_paths(shader_storage_root, L"shareable"); + auto shader_storage_shareable_root = shader_storage_root / "shareable"; if (!xe::filesystem::CreateFolder(shader_storage_shareable_root)) { return; } @@ -215,8 +215,7 @@ void PipelineCache::InitializeShaderStorage(const std::wstring& storage_root, uint64_t shader_storage_initialization_start = xe::Clock::QueryHostTickCount(); shader_storage_file_ = xe::filesystem::OpenFile( - xe::join_paths(shader_storage_shareable_root, - xe::format_string(L"%.8X.xsh", title_id)), + shader_storage_shareable_root / fmt::format("{:08X}.xsh", title_id), "a+b"); if (!shader_storage_file_) { return; @@ -388,11 +387,11 @@ void PipelineCache::InitializeShaderStorage(const std::wstring& storage_root, // Initialize the pipeline state storage stream. uint64_t pipeline_state_storage_initialization_start_ = xe::Clock::QueryHostTickCount(); - pipeline_state_storage_file_ = xe::filesystem::OpenFile( - xe::join_paths(shader_storage_shareable_root, - xe::format_string(L"%.8X.%s.d3d12.xpso", title_id, - edram_rov_used_ ? L"rov" : L"rtv")), - "a+b"); + pipeline_state_storage_file_ = + xe::filesystem::OpenFile(shader_storage_shareable_root / + fmt::format("{:08X}.{}.d3d12.xpso", title_id, + edram_rov_used_ ? "rov" : "rtv"), + "a+b"); if (!pipeline_state_storage_file_) { fclose(shader_storage_file_); shader_storage_file_ = nullptr; @@ -1694,13 +1693,12 @@ ID3D12PipelineState* PipelineCache::CreateD3D12PipelineState( } std::wstring name; if (runtime_description.pixel_shader != nullptr) { - name = - xe::format_string(L"VS %.16I64X, PS %.16I64X", - runtime_description.vertex_shader->ucode_data_hash(), - runtime_description.pixel_shader->ucode_data_hash()); + name = fmt::format(L"VS {:016X}, PS {:016X}", + runtime_description.vertex_shader->ucode_data_hash(), + runtime_description.pixel_shader->ucode_data_hash()); } else { - name = xe::format_string( - L"VS %.16I64X", runtime_description.vertex_shader->ucode_data_hash()); + name = fmt::format(L"VS {:016X}", + runtime_description.vertex_shader->ucode_data_hash()); } state->SetName(name.c_str()); return state; diff --git a/src/xenia/gpu/d3d12/pipeline_cache.h b/src/xenia/gpu/d3d12/pipeline_cache.h index b9295b288..eabd7d6e6 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.h +++ b/src/xenia/gpu/d3d12/pipeline_cache.h @@ -46,7 +46,7 @@ class PipelineCache { void Shutdown(); void ClearCache(bool shutting_down = false); - void InitializeShaderStorage(const std::wstring& storage_root, + void InitializeShaderStorage(const std::filesystem::path& storage_root, uint32_t title_id, bool blocking); void ShutdownShaderStorage(); @@ -262,7 +262,7 @@ class PipelineCache { PipelineState* current_pipeline_state_ = nullptr; // Currently open shader storage path. - std::wstring shader_storage_root_; + std::filesystem::path shader_storage_root_; uint32_t shader_storage_title_id_ = 0; // Shader storage output stream, for preload in the next emulator runs. diff --git a/src/xenia/gpu/d3d12/premake5.lua b/src/xenia/gpu/d3d12/premake5.lua index c0e87106f..812e3cc85 100644 --- a/src/xenia/gpu/d3d12/premake5.lua +++ b/src/xenia/gpu/d3d12/premake5.lua @@ -7,6 +7,7 @@ project("xenia-gpu-d3d12") kind("StaticLib") language("C++") links({ + "fmt", "xenia-base", "xenia-gpu", "xenia-ui", @@ -27,6 +28,7 @@ project("xenia-gpu-d3d12-trace-viewer") "aes_128", "capstone", "dxbc", + "fmt", "imgui", "libavcodec", "libavutil", @@ -71,6 +73,7 @@ project("xenia-gpu-d3d12-trace-dump") "aes_128", "capstone", "dxbc", + "fmt", "imgui", "libavcodec", "libavutil", diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index 8dbf40f55..a29ca2a12 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -1618,7 +1618,7 @@ void DxbcShaderTranslator::EmitInstructionDisassembly() { return; } - const char* source = instruction_disassembly_buffer_.GetString(); + const char* source = instruction_disassembly_buffer_.buffer(); uint32_t length = uint32_t(instruction_disassembly_buffer_.length()); // Trim leading spaces and trailing new line. while (length != 0 && source[0] == ' ') { diff --git a/src/xenia/gpu/dxbc_shader_translator_fetch.cc b/src/xenia/gpu/dxbc_shader_translator_fetch.cc index c2478424b..c7d7854e1 100644 --- a/src/xenia/gpu/dxbc_shader_translator_fetch.cc +++ b/src/xenia/gpu/dxbc_shader_translator_fetch.cc @@ -2,21 +2,20 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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/gpu/dxbc_shader_translator.h" - #include #include #include #include "third_party/dxbc/d3d12TokenizedProgramFormat.hpp" - +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/string.h" +#include "xenia/gpu/dxbc_shader_translator.h" namespace xe { namespace gpu { @@ -791,9 +790,8 @@ uint32_t DxbcShaderTranslator::FindOrAddTextureSRV(uint32_t fetch_constant, default: dimension_name = "2d"; } - new_texture_srv.name = - xe::format_string("xe_texture%u_%s_%c", fetch_constant, dimension_name, - is_signed ? 's' : 'u'); + new_texture_srv.name = fmt::format("xe_texture{}_{}_{}", fetch_constant, + dimension_name, is_signed ? 's' : 'u'); uint32_t srv_register = 1 + uint32_t(texture_srvs_.size()); texture_srvs_.emplace_back(std::move(new_texture_srv)); return srv_register; diff --git a/src/xenia/gpu/gpu_flags.cc b/src/xenia/gpu/gpu_flags.cc index 41490a7bd..7652fd711 100644 --- a/src/xenia/gpu/gpu_flags.cc +++ b/src/xenia/gpu/gpu_flags.cc @@ -2,18 +2,18 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/gpu/gpu_flags.h" -DEFINE_string(trace_gpu_prefix, "scratch/gpu/", - "Prefix path for GPU trace files.", "GPU"); +DEFINE_path(trace_gpu_prefix, "scratch/gpu/", + "Prefix path for GPU trace files.", "GPU"); DEFINE_bool(trace_gpu_stream, false, "Trace all GPU packets.", "GPU"); -DEFINE_string( +DEFINE_path( dump_shaders, "", "For shader debugging, path to dump GPU shaders to as they are compiled.", "GPU"); diff --git a/src/xenia/gpu/gpu_flags.h b/src/xenia/gpu/gpu_flags.h index 7f1d1815e..19b786e35 100644 --- a/src/xenia/gpu/gpu_flags.h +++ b/src/xenia/gpu/gpu_flags.h @@ -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,10 +11,10 @@ #define XENIA_GPU_GPU_FLAGS_H_ #include "xenia/base/cvar.h" -DECLARE_string(trace_gpu_prefix); +DECLARE_path(trace_gpu_prefix); DECLARE_bool(trace_gpu_stream); -DECLARE_string(dump_shaders); +DECLARE_path(dump_shaders); DECLARE_bool(vsync); diff --git a/src/xenia/gpu/graphics_system.cc b/src/xenia/gpu/graphics_system.cc index cbfc2cc9b..26046d88e 100644 --- a/src/xenia/gpu/graphics_system.cc +++ b/src/xenia/gpu/graphics_system.cc @@ -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. * ****************************************************************************** */ @@ -275,8 +275,9 @@ void GraphicsSystem::ClearCaches() { [&]() { command_processor_->ClearCaches(); }); } -void GraphicsSystem::InitializeShaderStorage(const std::wstring& storage_root, - uint32_t title_id, bool blocking) { +void GraphicsSystem::InitializeShaderStorage( + const std::filesystem::path& storage_root, uint32_t title_id, + bool blocking) { if (!cvars::store_shaders) { return; } @@ -304,12 +305,11 @@ void GraphicsSystem::InitializeShaderStorage(const std::wstring& storage_root, } void GraphicsSystem::RequestFrameTrace() { - command_processor_->RequestFrameTrace( - xe::to_wstring(cvars::trace_gpu_prefix)); + command_processor_->RequestFrameTrace(cvars::trace_gpu_prefix); } void GraphicsSystem::BeginTracing() { - command_processor_->BeginTracing(xe::to_wstring(cvars::trace_gpu_prefix)); + command_processor_->BeginTracing(cvars::trace_gpu_prefix); } void GraphicsSystem::EndTracing() { command_processor_->EndTracing(); } diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index 42bfe87d4..47a4d3f7b 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -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. * ****************************************************************************** */ @@ -35,7 +35,7 @@ class GraphicsSystem { public: virtual ~GraphicsSystem(); - virtual std::wstring name() const = 0; + virtual std::string name() const = 0; Memory* memory() const { return memory_; } cpu::Processor* processor() const { return processor_; } @@ -63,7 +63,7 @@ class GraphicsSystem { virtual void ClearCaches(); - void InitializeShaderStorage(const std::wstring& storage_root, + void InitializeShaderStorage(const std::filesystem::path& storage_root, uint32_t title_id, bool blocking); void RequestFrameTrace(); diff --git a/src/xenia/gpu/null/null_graphics_system.h b/src/xenia/gpu/null/null_graphics_system.h index d15527a9d..640a0424f 100644 --- a/src/xenia/gpu/null/null_graphics_system.h +++ b/src/xenia/gpu/null/null_graphics_system.h @@ -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. * ****************************************************************************** */ @@ -26,7 +26,7 @@ class NullGraphicsSystem : public GraphicsSystem { static bool IsAvailable() { return true; } - std::wstring name() const override { return L"null"; } + std::string name() const override { return "null"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, ui::Window* target_window) override; diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 3dff786a0..33c6a228d 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -8,6 +8,7 @@ project("xenia-gpu") language("C++") links({ "dxbc", + "fmt", "glslang-spirv", "snappy", "spirv-tools", @@ -32,6 +33,7 @@ project("xenia-gpu-shader-compiler") language("C++") links({ "dxbc", + "fmt", "glslang-spirv", "spirv-tools", "xenia-base", diff --git a/src/xenia/gpu/shader.cc b/src/xenia/gpu/shader.cc index 69fa065a3..15d59c375 100644 --- a/src/xenia/gpu/shader.cc +++ b/src/xenia/gpu/shader.cc @@ -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. * ****************************************************************************** */ @@ -12,6 +12,7 @@ #include #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/filesystem.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -40,30 +41,32 @@ std::string Shader::GetTranslatedBinaryString() const { return result; } -std::pair Shader::Dump(const std::string& base_path, - const char* path_prefix) { +std::pair Shader::Dump( + const std::filesystem::path& base_path, const char* path_prefix) { // Ensure target path exists. - auto target_path = xe::to_wstring(base_path); + auto target_path = base_path; if (!target_path.empty()) { - target_path = xe::to_absolute_path(target_path); + target_path = std::filesystem::absolute(target_path); xe::filesystem::CreateFolder(target_path); } - const std::string file_name_no_extension = - xe::format_string("%s/shader_%s_%.16" PRIX64, base_path.c_str(), - path_prefix, ucode_data_hash_); - - std::string txt_file_name, bin_file_name; + auto base_name = + fmt::format("shader_{}_{:016X}", path_prefix, ucode_data_hash_); + std::string txt_name, bin_name; if (shader_type_ == ShaderType::kVertex) { - txt_file_name = file_name_no_extension + ".vert"; - bin_file_name = file_name_no_extension + ".bin.vert"; + txt_name = base_name + ".vert"; + bin_name = base_name + ".bin.vert"; } else { - txt_file_name = file_name_no_extension + ".frag"; - bin_file_name = file_name_no_extension + ".bin.frag"; + txt_name = base_name + ".frag"; + bin_name = base_name + ".bin.frag"; } - FILE* f = fopen(txt_file_name.c_str(), "wb"); + std::filesystem::path txt_path, bin_path; + txt_path = base_path / txt_name; + bin_path = base_path / bin_name; + + FILE* f = filesystem::OpenFile(txt_path, "wb"); if (f) { fwrite(translated_binary_.data(), 1, translated_binary_.size(), f); fprintf(f, "\n\n"); @@ -81,13 +84,13 @@ std::pair Shader::Dump(const std::string& base_path, fclose(f); } - f = fopen(bin_file_name.c_str(), "wb"); + f = filesystem::OpenFile(bin_path, "wb"); if (f) { fwrite(ucode_data_.data(), 4, ucode_data_.size(), f); fclose(f); } - return {std::move(txt_file_name), std::move(bin_file_name)}; + return {std::move(txt_path), std::move(bin_path)}; } } // namespace gpu diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h index 50372ae12..b1502ce1e 100644 --- a/src/xenia/gpu/shader.h +++ b/src/xenia/gpu/shader.h @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_GPU_SHADER_H_ #define XENIA_GPU_SHADER_H_ +#include #include #include @@ -685,8 +686,8 @@ class Shader { // Both the ucode binary and disassembled and translated shader will be // written. // Returns the filename of the shader and the binary. - std::pair Dump(const std::string& base_path, - const char* path_prefix); + std::pair Dump( + const std::filesystem::path& base_path, const char* path_prefix); protected: friend class ShaderTranslator; diff --git a/src/xenia/gpu/shader_compiler_main.cc b/src/xenia/gpu/shader_compiler_main.cc index f30818a98..ab67e9d15 100644 --- a/src/xenia/gpu/shader_compiler_main.cc +++ b/src/xenia/gpu/shader_compiler_main.cc @@ -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. * ****************************************************************************** */ @@ -27,11 +27,11 @@ #include "xenia/ui/d3d12/d3d12_api.h" #endif // XE_PLATFORM_WIN32 -DEFINE_string(shader_input, "", "Input shader binary file path.", "GPU"); +DEFINE_path(shader_input, "", "Input shader binary file path.", "GPU"); DEFINE_string(shader_input_type, "", "'vs', 'ps', or unspecified to infer from the given filename.", "GPU"); -DEFINE_string(shader_output, "", "Output shader file path.", "GPU"); +DEFINE_path(shader_output, "", "Output shader file path.", "GPU"); DEFINE_string(shader_output_type, "ucode", "Translator to use: [ucode, spirv, spirvtext, dxbc, dxbctext].", "GPU"); @@ -48,7 +48,7 @@ DEFINE_bool(shader_output_dxbc_rov, false, namespace xe { namespace gpu { -int shader_compiler_main(const std::vector& args) { +int shader_compiler_main(const std::vector& args) { ShaderType shader_type; if (!cvars::shader_input_type.empty()) { if (cvars::shader_input_type == "vs") { @@ -60,13 +60,13 @@ int shader_compiler_main(const std::vector& args) { return 1; } } else { - auto last_dot = cvars::shader_input.find_last_of('.'); bool valid_type = false; - if (last_dot != std::string::npos) { - if (cvars::shader_input.substr(last_dot) == ".vs") { + if (cvars::shader_input.has_extension()) { + auto extension = cvars::shader_input.extension(); + if (extension == ".vs") { shader_type = ShaderType::kVertex; valid_type = true; - } else if (cvars::shader_input.substr(last_dot) == ".ps") { + } else if (extension == ".ps") { shader_type = ShaderType::kPixel; valid_type = true; } @@ -79,9 +79,10 @@ int shader_compiler_main(const std::vector& args) { } } - auto input_file = fopen(cvars::shader_input.c_str(), "rb"); + auto input_file = filesystem::OpenFile(cvars::shader_input, "rb"); if (!input_file) { - XELOGE("Unable to open input file: %s", cvars::shader_input.c_str()); + XELOGE("Unable to open input file: %s", + xe::path_to_utf8(cvars::shader_input).c_str()); return 1; } fseek(input_file, 0, SEEK_END); @@ -92,7 +93,7 @@ int shader_compiler_main(const std::vector& args) { fclose(input_file); XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).", - cvars::shader_input.c_str(), + xe::path_to_utf8(cvars::shader_input).c_str(), shader_type == ShaderType::kVertex ? "vertex" : "pixel", ucode_dwords.size(), ucode_dwords.size() * 4); @@ -153,7 +154,7 @@ int shader_compiler_main(const std::vector& args) { #if XE_PLATFORM_WIN32 ID3DBlob* dxbc_disasm_blob = nullptr; if (cvars::shader_output_type == "dxbctext") { - HMODULE d3d_compiler = LoadLibrary(L"D3DCompiler_47.dll"); + HMODULE d3d_compiler = LoadLibraryW(L"D3DCompiler_47.dll"); if (d3d_compiler != nullptr) { pD3DDisassemble d3d_disassemble = pD3DDisassemble(GetProcAddress(d3d_compiler, "D3DDisassemble")); @@ -180,7 +181,7 @@ int shader_compiler_main(const std::vector& args) { #endif // XE_PLATFORM_WIN32 if (!cvars::shader_output.empty()) { - auto output_file = fopen(cvars::shader_output.c_str(), "wb"); + auto output_file = filesystem::OpenFile(cvars::shader_output, "wb"); fwrite(source_data, 1, source_data_size, output_file); fclose(output_file); } @@ -197,5 +198,5 @@ int shader_compiler_main(const std::vector& args) { } // namespace gpu } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-gpu-shader-compiler", xe::gpu::shader_compiler_main, +DEFINE_ENTRY_POINT("xenia-gpu-shader-compiler", xe::gpu::shader_compiler_main, "shader.bin", "shader_input"); diff --git a/src/xenia/gpu/shader_translator.cc b/src/xenia/gpu/shader_translator.cc index e4adc6a5d..4d4285092 100644 --- a/src/xenia/gpu/shader_translator.cc +++ b/src/xenia/gpu/shader_translator.cc @@ -224,7 +224,7 @@ bool ShaderTranslator::TranslateInternal( } void ShaderTranslator::MarkUcodeInstruction(uint32_t dword_offset) { - auto disasm = ucode_disasm_buffer_.GetString(); + auto disasm = ucode_disasm_buffer_.buffer(); size_t current_offset = ucode_disasm_buffer_.length(); for (size_t i = previous_ucode_disasm_scan_offset_; i < current_offset; ++i) { if (disasm[i] == '\n') { @@ -568,7 +568,7 @@ bool ShaderTranslator::TranslateBlocks() { } std::vector UcodeShaderTranslator::CompleteTranslation() { - return ucode_disasm_buffer().ToBytes(); + return ucode_disasm_buffer().to_bytes(); } void ShaderTranslator::TranslateControlFlowInstruction( diff --git a/src/xenia/gpu/shader_translator_disasm.cc b/src/xenia/gpu/shader_translator_disasm.cc index ddd5e433e..7a0bdf179 100644 --- a/src/xenia/gpu/shader_translator_disasm.cc +++ b/src/xenia/gpu/shader_translator_disasm.cc @@ -46,7 +46,7 @@ void DisassembleResultOperand(const InstructionResult& result, uses_storage_index = true; break; case InstructionStorageTarget::kColorTarget: - out->AppendFormat("oC"); + out->Append("oC"); uses_storage_index = true; break; case InstructionStorageTarget::kDepth: @@ -58,13 +58,13 @@ void DisassembleResultOperand(const InstructionResult& result, if (uses_storage_index) { switch (result.storage_addressing_mode) { case InstructionStorageAddressingMode::kStatic: - out->AppendFormat("%d", result.storage_index); + out->AppendFormat("{}", result.storage_index); break; case InstructionStorageAddressingMode::kAddressAbsolute: - out->AppendFormat("[%d+a0]", result.storage_index); + out->AppendFormat("[{}+a0]", result.storage_index); break; case InstructionStorageAddressingMode::kAddressRelative: - out->AppendFormat("[%d+aL]", result.storage_index); + out->AppendFormat("[{}+aL]", result.storage_index); break; } } @@ -104,16 +104,16 @@ void DisassembleSourceOperand(const InstructionOperand& op, StringBuffer* out) { switch (op.storage_addressing_mode) { case InstructionStorageAddressingMode::kStatic: if (op.is_absolute_value) { - out->AppendFormat("[%d]", op.storage_index); + out->AppendFormat("[{}]", op.storage_index); } else { - out->AppendFormat("%d", op.storage_index); + out->AppendFormat("{}", op.storage_index); } break; case InstructionStorageAddressingMode::kAddressAbsolute: - out->AppendFormat("[%d+a0]", op.storage_index); + out->AppendFormat("[{}+a0]", op.storage_index); break; case InstructionStorageAddressingMode::kAddressRelative: - out->AppendFormat("[%d+aL]", op.storage_index); + out->AppendFormat("[{}+aL]", op.storage_index); break; } if (!op.is_standard_swizzle()) { @@ -134,18 +134,18 @@ void DisassembleSourceOperand(const InstructionOperand& op, StringBuffer* out) { void ParsedExecInstruction::Disassemble(StringBuffer* out) const { switch (type) { case Type::kUnconditional: - out->AppendFormat(" %s ", opcode_name); + out->AppendFormat(" {} ", opcode_name); break; case Type::kPredicated: out->Append(condition ? " (p0) " : "(!p0) "); - out->AppendFormat("%s ", opcode_name); + out->AppendFormat("{} ", opcode_name); break; case Type::kConditional: - out->AppendFormat(" %s ", opcode_name); + out->AppendFormat(" {} ", opcode_name); if (!condition) { out->Append('!'); } - out->AppendFormat("b%u", bool_constant_index); + out->AppendFormat("b{}", bool_constant_index); break; } if (is_yield) { @@ -159,7 +159,7 @@ void ParsedExecInstruction::Disassemble(StringBuffer* out) const { void ParsedLoopStartInstruction::Disassemble(StringBuffer* out) const { out->Append(" loop "); - out->AppendFormat("i%u, L%u", loop_constant_index, loop_skip_address); + out->AppendFormat("i{}, L{}", loop_constant_index, loop_skip_address); if (is_repeat) { out->Append(", Repeat=true"); } @@ -172,7 +172,7 @@ void ParsedLoopEndInstruction::Disassemble(StringBuffer* out) const { } else { out->Append(" "); } - out->AppendFormat("endloop i%u, L%u", loop_constant_index, loop_body_address); + out->AppendFormat("endloop i{}, L{}", loop_constant_index, loop_body_address); out->Append('\n'); } @@ -190,10 +190,10 @@ void ParsedCallInstruction::Disassemble(StringBuffer* out) const { if (!condition) { out->Append('!'); } - out->AppendFormat("b%u, ", bool_constant_index); + out->AppendFormat("b{}, ", bool_constant_index); break; } - out->AppendFormat("L%u", target_address); + out->AppendFormat("L{}", target_address); out->Append('\n'); } @@ -215,10 +215,10 @@ void ParsedJumpInstruction::Disassemble(StringBuffer* out) const { if (!condition) { out->Append('!'); } - out->AppendFormat("b%u, ", bool_constant_index); + out->AppendFormat("b{}, ", bool_constant_index); break; } - out->AppendFormat("L%u", target_address); + out->AppendFormat("L{}", target_address); out->Append('\n'); } @@ -228,7 +228,7 @@ void ParsedAllocInstruction::Disassemble(StringBuffer* out) const { case AllocType::kNone: break; case AllocType::kVsPosition: - out->AppendFormat("position"); + out->Append("position"); break; case AllocType::kVsInterpolators: // or AllocType::kPsColors if (is_vertex_shader) { @@ -238,7 +238,7 @@ void ParsedAllocInstruction::Disassemble(StringBuffer* out) const { } break; case AllocType::kMemory: - out->AppendFormat("export = %d", count); + out->AppendFormat("export = {}", count); break; } out->Append('\n'); @@ -315,32 +315,32 @@ void ParsedVertexFetchInstruction::Disassemble(StringBuffer* out) const { } else { out->Append(" "); } - out->AppendFormat(opcode_name); + out->Append(opcode_name); out->Append(' '); DisassembleResultOperand(result, out); if (!is_mini_fetch) { out->Append(", "); DisassembleSourceOperand(operands[0], out); out->Append(", "); - out->AppendFormat("vf%d", 95 - operands[1].storage_index); + out->AppendFormat("vf{}", 95 - operands[1].storage_index); } if (attributes.is_index_rounded) { out->Append(", RoundIndex=true"); } if (attributes.exp_adjust) { - out->AppendFormat(", ExpAdjust=%d", attributes.exp_adjust); + out->AppendFormat(", ExpAdjust={}", attributes.exp_adjust); } if (attributes.offset) { - out->AppendFormat(", Offset=%d", attributes.offset); + out->AppendFormat(", Offset={}", attributes.offset); } if (attributes.data_format != VertexFormat::kUndefined) { out->AppendFormat( - ", DataFormat=%s", - kVertexFetchDataFormats[static_cast(attributes.data_format)]); + ", DataFormat={}", + kVertexFetchDataFormats[static_cast(attributes.data_format)].name); } if (!is_mini_fetch && attributes.stride) { - out->AppendFormat(", Stride=%d", attributes.stride); + out->AppendFormat(", Stride={}", attributes.stride); } if (attributes.is_signed) { out->Append(", Signed=true"); @@ -349,7 +349,7 @@ void ParsedVertexFetchInstruction::Disassemble(StringBuffer* out) const { out->Append(", NumFormat=integer"); } if (attributes.prefetch_count) { - out->AppendFormat(", PrefetchCount=%u", attributes.prefetch_count + 1); + out->AppendFormat(", PrefetchCount={}", attributes.prefetch_count + 1); } out->Append('\n'); @@ -388,7 +388,7 @@ void ParsedTextureFetchInstruction::Disassemble(StringBuffer* out) const { if (needs_comma) { out->Append(", "); } - out->AppendFormat("tf%u", operands[1].storage_index); + out->AppendFormat("tf{}", operands[1].storage_index); } if (!attributes.fetch_valid_only) { @@ -399,32 +399,32 @@ void ParsedTextureFetchInstruction::Disassemble(StringBuffer* out) const { } if (attributes.mag_filter != TextureFilter::kUseFetchConst) { out->AppendFormat( - ", MagFilter=%s", + ", MagFilter={}", kTextureFilterNames[static_cast(attributes.mag_filter)]); } if (attributes.min_filter != TextureFilter::kUseFetchConst) { out->AppendFormat( - ", MinFilter=%s", + ", MinFilter={}", kTextureFilterNames[static_cast(attributes.min_filter)]); } if (attributes.mip_filter != TextureFilter::kUseFetchConst) { out->AppendFormat( - ", MipFilter=%s", + ", MipFilter={}", kTextureFilterNames[static_cast(attributes.mip_filter)]); } if (attributes.aniso_filter != AnisoFilter::kUseFetchConst) { out->AppendFormat( - ", AnisoFilter=%s", + ", AnisoFilter={}", kAnisoFilterNames[static_cast(attributes.aniso_filter)]); } if (attributes.vol_mag_filter != TextureFilter::kUseFetchConst) { out->AppendFormat( - ", VolMagFilter=%s", + ", VolMagFilter={}", kTextureFilterNames[static_cast(attributes.vol_mag_filter)]); } if (attributes.vol_min_filter != TextureFilter::kUseFetchConst) { out->AppendFormat( - ", VolMinFilter=%s", + ", VolMinFilter={}", kTextureFilterNames[static_cast(attributes.vol_min_filter)]); } if (!attributes.use_computed_lod) { @@ -437,17 +437,17 @@ void ParsedTextureFetchInstruction::Disassemble(StringBuffer* out) const { out->Append(", UseRegisterGradients=true"); } if (attributes.lod_bias != 0.0f) { - out->AppendFormat(", LODBias=%g", attributes.lod_bias); + out->AppendFormat(", LODBias={:g}", attributes.lod_bias); } int component_count = GetTextureDimensionComponentCount(dimension); if (attributes.offset_x != 0.0f) { - out->AppendFormat(", OffsetX=%g", attributes.offset_x); + out->AppendFormat(", OffsetX={:g}", attributes.offset_x); } if (component_count > 1 && attributes.offset_y != 0.0f) { - out->AppendFormat(", OffsetY=%g", attributes.offset_y); + out->AppendFormat(", OffsetY={:g}", attributes.offset_y); } if (component_count > 2 && attributes.offset_z != 0.0f) { - out->AppendFormat(", OffsetZ=%g", attributes.offset_z); + out->AppendFormat(", OffsetZ={:g}", attributes.offset_z); } out->Append('\n'); diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index ea54f736c..67fbb585e 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2017 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 #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -232,9 +233,9 @@ void SpirvShaderTranslator::StartTranslation() { // Create 3 texture types, all aliased on the same binding for (int i = 0; i < 3; i++) { - tex_[i] = b.createVariable( - spv::StorageClass::StorageClassUniformConstant, tex_a_t[i], - xe::format_string("textures%dD", i + 2).c_str()); + tex_[i] = b.createVariable(spv::StorageClass::StorageClassUniformConstant, + tex_a_t[i], + fmt::format("textures{}D", i + 2).c_str()); b.addDecoration(tex_[i], spv::Decoration::DecorationDescriptorSet, 1); b.addDecoration(tex_[i], spv::Decoration::DecorationBinding, 0); } diff --git a/src/xenia/gpu/trace_dump.cc b/src/xenia/gpu/trace_dump.cc index 0915613b1..0d9405fa1 100644 --- a/src/xenia/gpu/trace_dump.cc +++ b/src/xenia/gpu/trace_dump.cc @@ -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. * ****************************************************************************** */ @@ -26,9 +26,8 @@ #undef _CRT_NONSTDC_NO_DEPRECATE #include "third_party/stb/stb_image_write.h" -DEFINE_string(target_trace_file, "", "Specifies the trace file to load.", - "GPU"); -DEFINE_string(trace_dump_path, "", "Output path for dumped files.", "GPU"); +DEFINE_path(target_trace_file, "", "Specifies the trace file to load.", "GPU"); +DEFINE_path(trace_dump_path, "", "Output path for dumped files.", "GPU"); namespace xe { namespace gpu { @@ -39,21 +38,21 @@ TraceDump::TraceDump() = default; TraceDump::~TraceDump() = default; -int TraceDump::Main(const std::vector& args) { +int TraceDump::Main(const std::vector& args) { // Grab path from the flag or unnamed argument. - std::wstring path; - std::wstring output_path; + std::filesystem::path path; + std::filesystem::path output_path; if (!cvars::target_trace_file.empty()) { // Passed as a named argument. // TODO(benvanik): find something better than gflags that supports // unicode. - path = xe::to_wstring(cvars::target_trace_file); + path = cvars::target_trace_file; } else if (args.size() >= 2) { // Passed as an unnamed argument. - path = args[1]; + path = xe::to_path(args[1]); if (args.size() >= 3) { - output_path = args[2]; + output_path = xe::to_path(args[2]); } } @@ -63,8 +62,8 @@ int TraceDump::Main(const std::vector& args) { } // Normalize the path and make absolute. - auto abs_path = xe::to_absolute_path(path); - XELOGI("Loading trace file %ls...", abs_path.c_str()); + auto abs_path = std::filesystem::absolute(path); + XELOGI("Loading trace file %s...", xe::path_to_utf8(abs_path).c_str()); if (!Setup()) { XELOGE("Unable to setup trace dump tool"); @@ -77,21 +76,12 @@ int TraceDump::Main(const std::vector& args) { // Root file name for outputs. if (output_path.empty()) { - base_output_path_ = - xe::fix_path_separators(xe::to_wstring(cvars::trace_dump_path)); + base_output_path_ = cvars::trace_dump_path; + auto output_name = path.filename().replace_extension(); - std::wstring output_name = - xe::find_name_from_path(xe::fix_path_separators(path)); - - // Strip the extension from the filename. - auto last_dot = output_name.find_last_of(L"."); - if (last_dot != std::string::npos) { - output_name = output_name.substr(0, last_dot); - } - - base_output_path_ = xe::join_paths(base_output_path_, output_name); + base_output_path_ = base_output_path_ / output_name; } else { - base_output_path_ = xe::fix_path_separators(output_path); + base_output_path_ = output_path; } // Ensure output path exists. @@ -102,7 +92,7 @@ int TraceDump::Main(const std::vector& args) { bool TraceDump::Setup() { // Create the emulator but don't initialize so we can setup the window. - emulator_ = std::make_unique(L"", L"", L""); + emulator_ = std::make_unique("", "", ""); X_STATUS result = emulator_->Setup( nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr); if (XFAILED(result)) { @@ -114,8 +104,8 @@ bool TraceDump::Setup() { return true; } -bool TraceDump::Load(std::wstring trace_file_path) { - trace_file_path_ = std::move(trace_file_path); +bool TraceDump::Load(const std::filesystem::path& trace_file_path) { + trace_file_path_ = trace_file_path; if (!player_->Open(trace_file_path_)) { XELOGE("Could not load trace file"); @@ -138,10 +128,16 @@ int TraceDump::Run() { auto raw_image = graphics_system_->Capture(); if (raw_image) { // Save framebuffer png. - std::string png_path = xe::to_string(base_output_path_ + L".png"); - stbi_write_png(png_path.c_str(), static_cast(raw_image->width), - static_cast(raw_image->height), 4, - raw_image->data.data(), static_cast(raw_image->stride)); + auto png_path = base_output_path_.replace_extension(".png"); + auto handle = filesystem::OpenFile(png_path, "wb"); + auto callback = [](void* context, void* data, int size) { + fwrite(data, 1, size, (FILE*)context); + }; + stbi_write_png_to_func(callback, handle, static_cast(raw_image->width), + static_cast(raw_image->height), 4, + raw_image->data.data(), + static_cast(raw_image->stride)); + fclose(handle); } else { result = 1; } diff --git a/src/xenia/gpu/trace_dump.h b/src/xenia/gpu/trace_dump.h index f2e4c7347..b05d11950 100644 --- a/src/xenia/gpu/trace_dump.h +++ b/src/xenia/gpu/trace_dump.h @@ -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. * ****************************************************************************** */ @@ -36,7 +36,7 @@ class TraceDump { public: virtual ~TraceDump(); - int Main(const std::vector& args); + int Main(const std::vector& args); protected: TraceDump(); @@ -52,11 +52,11 @@ class TraceDump { private: bool Setup(); - bool Load(std::wstring trace_file_path); + bool Load(const std::filesystem::path& trace_file_path); int Run(); - std::wstring trace_file_path_; - std::wstring base_output_path_; + std::filesystem::path trace_file_path_; + std::filesystem::path base_output_path_; }; } // namespace gpu diff --git a/src/xenia/gpu/trace_protocol.h b/src/xenia/gpu/trace_protocol.h index 147895cc7..274dd7bce 100644 --- a/src/xenia/gpu/trace_protocol.h +++ b/src/xenia/gpu/trace_protocol.h @@ -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. * ****************************************************************************** */ @@ -16,7 +16,7 @@ namespace xe { namespace gpu { // Trace file extension. -static const wchar_t kTraceExtension[] = L"xtr"; +static const char kTraceExtension[] = "xtr"; // Any byte changes to the files should bump this version. // Only builds with matching versions will work. diff --git a/src/xenia/gpu/trace_reader.cc b/src/xenia/gpu/trace_reader.cc index 1555ac152..26fdd3abe 100644 --- a/src/xenia/gpu/trace_reader.cc +++ b/src/xenia/gpu/trace_reader.cc @@ -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. * ****************************************************************************** */ @@ -12,7 +12,7 @@ #include #include "third_party/snappy/snappy.h" - +#include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/mapped_memory.h" #include "xenia/base/math.h" @@ -23,7 +23,7 @@ namespace xe { namespace gpu { -bool TraceReader::Open(const std::wstring& path) { +bool TraceReader::Open(const std::filesystem::path& path) { Close(); mmap_ = MappedMemory::Open(path, MappedMemory::Mode::kRead); @@ -45,7 +45,7 @@ bool TraceReader::Open(const std::wstring& path) { return false; } - auto path_str = xe::to_string(path); + auto path_str = xe::path_to_utf8(path); XELOGI("Mapped %" PRId64 "b trace from %s", trace_size_, path_str.c_str()); XELOGI(" Version: %u", header->version); auto commit_str = std::string(header->build_commit_sha, diff --git a/src/xenia/gpu/trace_reader.h b/src/xenia/gpu/trace_reader.h index b3245da46..7480d3e4a 100644 --- a/src/xenia/gpu/trace_reader.h +++ b/src/xenia/gpu/trace_reader.h @@ -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. * ****************************************************************************** */ @@ -129,7 +129,7 @@ class TraceReader { const Frame* frame(int n) const { return &frames_[n]; } int frame_count() const { return int(frames_.size()); } - bool Open(const std::wstring& path); + bool Open(const std::filesystem::path& path); void Close(); diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index db3fc2da8..e30ce4428 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -31,8 +31,7 @@ #include "xenia/ui/window.h" #include "xenia/xbox.h" -DEFINE_string(target_trace_file, "", "Specifies the trace file to load.", - "GPU"); +DEFINE_path(target_trace_file, "", "Specifies the trace file to load.", "GPU"); namespace xe { namespace gpu { @@ -50,17 +49,17 @@ TraceViewer::TraceViewer() = default; TraceViewer::~TraceViewer() = default; -int TraceViewer::Main(const std::vector& args) { +int TraceViewer::Main(const std::vector& args) { // Grab path from the flag or unnamed argument. - std::wstring path; + std::filesystem::path path; if (!cvars::target_trace_file.empty()) { // Passed as a named argument. // TODO(benvanik): find something better than gflags that supports // unicode. - path = xe::to_wstring(cvars::target_trace_file); + path = cvars::target_trace_file; } else if (args.size() >= 2) { // Passed as an unnamed argument. - path = args[1]; + path = xe::to_path(args[1]); } // If no path passed, ask the user. @@ -69,10 +68,10 @@ int TraceViewer::Main(const std::vector& args) { file_picker->set_mode(ui::FilePicker::Mode::kOpen); file_picker->set_type(ui::FilePicker::Type::kFile); file_picker->set_multi_selection(false); - file_picker->set_title(L"Select Trace File"); + file_picker->set_title("Select Trace File"); file_picker->set_extensions({ - {L"Supported Files", L"*.xtr"}, - {L"All Files (*.*)", L"*.*"}, + {"Supported Files", "*.xtr"}, + {"All Files (*.*)", "*.*"}, }); if (file_picker->Show()) { auto selected_files = file_picker->selected_files(); @@ -88,7 +87,7 @@ int TraceViewer::Main(const std::vector& args) { } // Normalize the path and make absolute. - auto abs_path = xe::to_absolute_path(path); + auto abs_path = std::filesystem::absolute(path); if (!Setup()) { xe::FatalError("Unable to setup trace viewer"); @@ -105,7 +104,7 @@ int TraceViewer::Main(const std::vector& args) { bool TraceViewer::Setup() { // Main display window. loop_ = ui::Loop::Create(); - window_ = xe::ui::Window::Create(loop_.get(), L"xenia-gpu-trace-viewer"); + window_ = xe::ui::Window::Create(loop_.get(), "xenia-gpu-trace-viewer"); loop_->PostSynchronous([&]() { xe::threading::set_name("Win32 Loop"); if (!window_->Initialize()) { @@ -122,7 +121,7 @@ bool TraceViewer::Setup() { window_->Resize(1920, 1200); // Create the emulator but don't initialize so we can setup the window. - emulator_ = std::make_unique(L"", L"", L""); + emulator_ = std::make_unique("", "", ""); X_STATUS result = emulator_->Setup( window_.get(), nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr); @@ -155,9 +154,9 @@ bool TraceViewer::Setup() { return true; } -bool TraceViewer::Load(std::wstring trace_file_path) { - auto file_name = xe::find_name_from_path(trace_file_path); - window_->set_title(std::wstring(L"Xenia GPU Trace Viewer: ") + file_name); +bool TraceViewer::Load(const std::filesystem::path& trace_file_path) { + auto file_name = trace_file_path.filename(); + window_->set_title("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name)); if (!player_->Open(trace_file_path)) { XELOGE("Could not load trace file"); @@ -177,7 +176,7 @@ void TraceViewer::Run() { loop_.reset(); } -void TraceViewer::DrawMultilineString(const std::string& str) { +void TraceViewer::DrawMultilineString(const std::string_view str) { size_t i = 0; bool done = false; while (!done && i < str.size()) { @@ -187,7 +186,7 @@ void TraceViewer::DrawMultilineString(const std::string& str) { next_i = str.size() - 1; } auto line = str.substr(i, next_i - i); - ImGui::Text("%s", line.c_str()); + ImGui::Text("%s", std::string(line).c_str()); i = next_i + 1; } } diff --git a/src/xenia/gpu/trace_viewer.h b/src/xenia/gpu/trace_viewer.h index 7e82ad831..3c18fc809 100644 --- a/src/xenia/gpu/trace_viewer.h +++ b/src/xenia/gpu/trace_viewer.h @@ -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. * ****************************************************************************** */ @@ -36,14 +36,14 @@ class TraceViewer { public: virtual ~TraceViewer(); - int Main(const std::vector& args); + int Main(const std::vector& args); protected: TraceViewer(); virtual std::unique_ptr CreateGraphicsSystem() = 0; - void DrawMultilineString(const std::string& str); + void DrawMultilineString(const std::string_view str); virtual uintptr_t GetColorRenderTarget(uint32_t pitch, MsaaSamples samples, uint32_t base, @@ -74,7 +74,7 @@ class TraceViewer { kHostDisasm, }; - bool Load(std::wstring trace_file_path); + bool Load(const std::filesystem::path& trace_file_path); void Run(); void DrawUI(); diff --git a/src/xenia/gpu/trace_writer.cc b/src/xenia/gpu/trace_writer.cc index a4318965d..d2d0e52fb 100644 --- a/src/xenia/gpu/trace_writer.cc +++ b/src/xenia/gpu/trace_writer.cc @@ -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. * ****************************************************************************** */ @@ -27,12 +27,12 @@ TraceWriter::TraceWriter(uint8_t* membase) TraceWriter::~TraceWriter() = default; -bool TraceWriter::Open(const std::wstring& path, uint32_t title_id) { +bool TraceWriter::Open(const std::filesystem::path& path, uint32_t title_id) { Close(); - auto canonical_path = xe::to_absolute_path(path); - auto base_path = xe::find_base_path(canonical_path); - if (!base_path.empty()) { + auto canonical_path = std::filesystem::absolute(path); + if (canonical_path.has_parent_path()) { + auto base_path = canonical_path.parent_path(); xe::filesystem::CreateFolder(base_path); } diff --git a/src/xenia/gpu/trace_writer.h b/src/xenia/gpu/trace_writer.h index 792fd9554..84d49a1ef 100644 --- a/src/xenia/gpu/trace_writer.h +++ b/src/xenia/gpu/trace_writer.h @@ -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. * ****************************************************************************** */ @@ -26,7 +26,7 @@ class TraceWriter { bool is_open() const { return file_ != nullptr; } - bool Open(const std::wstring& path, uint32_t title_id); + bool Open(const std::filesystem::path& path, uint32_t title_id); void Flush(); void Close(); diff --git a/src/xenia/gpu/vk/vulkan_graphics_system.cc b/src/xenia/gpu/vk/vulkan_graphics_system.cc index 3cb40579a..021cda52e 100644 --- a/src/xenia/gpu/vk/vulkan_graphics_system.cc +++ b/src/xenia/gpu/vk/vulkan_graphics_system.cc @@ -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. * ****************************************************************************** */ @@ -19,7 +19,7 @@ VulkanGraphicsSystem::VulkanGraphicsSystem() {} VulkanGraphicsSystem::~VulkanGraphicsSystem() {} -std::wstring VulkanGraphicsSystem::name() const { return L"Vulkan Prototype"; } +std::string VulkanGraphicsSystem::name() const { return "Vulkan Prototype"; } X_STATUS VulkanGraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, diff --git a/src/xenia/gpu/vk/vulkan_graphics_system.h b/src/xenia/gpu/vk/vulkan_graphics_system.h index 617fd49a3..447bb5f51 100644 --- a/src/xenia/gpu/vk/vulkan_graphics_system.h +++ b/src/xenia/gpu/vk/vulkan_graphics_system.h @@ -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. * ****************************************************************************** */ @@ -27,7 +27,7 @@ class VulkanGraphicsSystem : public GraphicsSystem { static bool IsAvailable() { return true; } - std::wstring name() const override; + std::string name() const override; X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, ui::Window* target_window) override; diff --git a/src/xenia/gpu/vulkan/premake5.lua b/src/xenia/gpu/vulkan/premake5.lua index 2be22502e..fada8e143 100644 --- a/src/xenia/gpu/vulkan/premake5.lua +++ b/src/xenia/gpu/vulkan/premake5.lua @@ -7,6 +7,7 @@ project("xenia-gpu-vulkan") kind("StaticLib") language("C++") links({ + "fmt", "volk", "xenia-base", "xenia-gpu", @@ -31,6 +32,7 @@ project("xenia-gpu-vulkan-trace-viewer") links({ "aes_128", "capstone", + "fmt", "glslang-spirv", "imgui", "libavcodec", @@ -97,6 +99,7 @@ project("xenia-gpu-vulkan-trace-dump") links({ "aes_128", "capstone", + "fmt", "glslang-spirv", "imgui", "libavcodec", diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index 58106cc31..eabdddf8d 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -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. * ****************************************************************************** */ @@ -11,6 +11,7 @@ #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -231,10 +232,11 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { device_->DbgSetObjectName( reinterpret_cast(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - xe::format_string("RT(d): 0x%.8X 0x%.8X(%d) 0x%.8X(%d) %d %d %d", - key.tile_offset, key.tile_width, key.tile_width, - key.tile_height, key.tile_height, key.color_or_depth, - key.msaa_samples, key.edram_format)); + fmt::format("RT(d): {:#.8X} {:#.8X}({}) {:#.8X}({}) {} {} {}", + uint32_t(key.tile_offset), uint32_t(key.tile_width), + uint32_t(key.tile_width), uint32_t(key.tile_height), + uint32_t(key.tile_height), uint32_t(key.color_or_depth), + uint32_t(key.msaa_samples), uint32_t(key.edram_format))); VkMemoryRequirements memory_requirements; vkGetImageMemoryRequirements(*device_, image, &memory_requirements); diff --git a/src/xenia/gpu/vulkan/texture_cache.cc b/src/xenia/gpu/vulkan/texture_cache.cc index 92cca8d36..c6c4c18f2 100644 --- a/src/xenia/gpu/vulkan/texture_cache.cc +++ b/src/xenia/gpu/vulkan/texture_cache.cc @@ -2,16 +2,16 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/gpu/vulkan/texture_cache.h" -#include "xenia/gpu/vulkan/texture_config.h" #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -20,6 +20,7 @@ #include "xenia/gpu/sampler_info.h" #include "xenia/gpu/texture_conversion.h" #include "xenia/gpu/texture_info.h" +#include "xenia/gpu/vulkan/texture_config.h" #include "xenia/gpu/vulkan/vulkan_gpu_flags.h" #include "xenia/ui/vulkan/vulkan_mem_alloc.h" @@ -522,8 +523,8 @@ TextureCache::Texture* TextureCache::DemandResolveTexture( device_->DbgSetObjectName( reinterpret_cast(texture->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - xe::format_string( - "RT: 0x%.8X - 0x%.8X (%s, %s)", texture_info.memory.base_address, + fmt::format( + "RT: {:#.8X} - {:#.8X} ({}, {})", texture_info.memory.base_address, texture_info.memory.base_address + texture_info.memory.base_size, texture_info.format_info()->name, get_dimension_name(texture_info.dimension))); @@ -605,8 +606,8 @@ TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info, device_->DbgSetObjectName( reinterpret_cast(texture->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - xe::format_string( - "T: 0x%.8X - 0x%.8X (%s, %s)", texture_info.memory.base_address, + fmt::format( + "T: {:#.8X} - {:#.8X} ({}, {})", texture_info.memory.base_address, texture_info.memory.base_address + texture_info.memory.base_size, texture_info.format_info()->name, get_dimension_name(texture_info.dimension))); diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index 43f734a62..4f9ba2f3f 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -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. * ****************************************************************************** */ @@ -38,7 +38,8 @@ VulkanCommandProcessor::VulkanCommandProcessor( VulkanCommandProcessor::~VulkanCommandProcessor() = default; -void VulkanCommandProcessor::RequestFrameTrace(const std::wstring& root_path) { +void VulkanCommandProcessor::RequestFrameTrace( + const std::filesystem::path& root_path) { // Override traces if renderdoc is attached. if (device_->is_renderdoc_attached()) { trace_requested_ = true; diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.h b/src/xenia/gpu/vulkan/vulkan_command_processor.h index c4959fd0a..365aea7f4 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.h +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.h @@ -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. * ****************************************************************************** */ @@ -50,7 +50,7 @@ class VulkanCommandProcessor : public CommandProcessor { kernel::KernelState* kernel_state); ~VulkanCommandProcessor() override; - void RequestFrameTrace(const std::wstring& root_path) override; + void RequestFrameTrace(const std::filesystem::path& root_path) override; void TracePlaybackWroteMemory(uint32_t base_ptr, uint32_t length) override; void RestoreEDRAMSnapshot(const void* snapshot) override; void ClearCaches() override; diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.h b/src/xenia/gpu/vulkan/vulkan_graphics_system.h index c5d1b680e..0342c1cc5 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.h +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.h @@ -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. * ****************************************************************************** */ @@ -26,7 +26,7 @@ class VulkanGraphicsSystem : public GraphicsSystem { static bool IsAvailable() { return true; } - std::wstring name() const override { return L"Vulkan"; } + std::string name() const override { return "Vulkan"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, ui::Window* target_window) override; diff --git a/src/xenia/gpu/vulkan/vulkan_shader.cc b/src/xenia/gpu/vulkan/vulkan_shader.cc index ca0918e2d..bb6888063 100644 --- a/src/xenia/gpu/vulkan/vulkan_shader.cc +++ b/src/xenia/gpu/vulkan/vulkan_shader.cc @@ -2,13 +2,14 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/gpu/vulkan/vulkan_shader.h" +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -54,7 +55,7 @@ bool VulkanShader::Prepare() { : shader_type_ == ShaderType::kVertex ? 'v' : 'u'; device_->DbgSetObjectName( uint64_t(shader_module_), VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - xe::format_string("S(%c): %.16llX", typeChar, ucode_data_hash())); + fmt::format("S({}): {:016X}", typeChar, ucode_data_hash())); return status == VK_SUCCESS; } diff --git a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc index a895b6e42..16c1f34b8 100644 --- a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc +++ b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc @@ -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 @@ class VulkanTraceDump : public TraceDump { } }; -int trace_dump_main(const std::vector& args) { +int trace_dump_main(const std::vector& args) { VulkanTraceDump trace_dump; return trace_dump.Main(args); } @@ -55,6 +55,6 @@ int trace_dump_main(const std::vector& args) { } // namespace gpu } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-gpu-vulkan-trace-dump", +DEFINE_ENTRY_POINT("xenia-gpu-vulkan-trace-dump", xe::gpu::vulkan::trace_dump_main, "some.trace", "target_trace_file"); diff --git a/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc index 191536eb7..a810f38dc 100644 --- a/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc +++ b/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc @@ -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. * ****************************************************************************** */ @@ -62,7 +62,7 @@ class VulkanTraceViewer : public TraceViewer { } }; -int trace_viewer_main(const std::vector& args) { +int trace_viewer_main(const std::vector& args) { VulkanTraceViewer trace_viewer; return trace_viewer.Main(args); } @@ -71,6 +71,6 @@ int trace_viewer_main(const std::vector& args) { } // namespace gpu } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-gpu-vulkan-trace-viewer", +DEFINE_ENTRY_POINT("xenia-gpu-vulkan-trace-viewer", xe::gpu::vulkan::trace_viewer_main, "some.trace", "target_trace_file"); diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index 74c894b01..b9c62bd0e 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -88,7 +88,7 @@ std::unique_ptr CreateDemoGraphicsProvider( void DrawInputStatus(); -int hid_demo_main(const std::vector& args) { +int hid_demo_main(const std::vector& args) { // Create run loop and the window. auto loop = ui::Loop::Create(); auto window = xe::ui::Window::Create(loop.get(), GetEntryInfo().name); @@ -231,4 +231,4 @@ void DrawInputStatus() { } // namespace hid } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-hid-demo", xe::hid::hid_demo_main, ""); +DEFINE_ENTRY_POINT("xenia-hid-demo", xe::hid::hid_demo_main, ""); diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index d7f7b8066..e0148d9c7 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -20,6 +20,7 @@ project("xenia-hid-demo") kind("WindowedApp") language("C++") links({ + "fmt", "imgui", "volk", "xenia-base", diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index c73151c1c..3c55d2c76 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -14,12 +14,13 @@ #endif // XE_PLATFORM_WIN32 #include "xenia/base/cvar.h" +#include "xenia/base/logging.h" #include "xenia/ui/window.h" // TODO(joellinn) make this path relative to the config folder. -DEFINE_string(mappings_file, "gamecontrollerdb.txt", - "Filename of a database with custom game controller mappings.", - "SDL"); +DEFINE_path(mappings_file, "gamecontrollerdb.txt", + "Filename of a database with custom game controller mappings.", + "SDL"); namespace xe { namespace hid { @@ -118,7 +119,29 @@ X_STATUS SDLInputDriver::Setup() { } sdl_gamecontroller_initialized_ = true; - SDL_GameControllerAddMappingsFromFile(cvars::mappings_file.c_str()); + if (!cvars::mappings_file.empty()) { + if (!filesystem::PathExists(cvars::mappings_file)) { + XELOGW("SDL GameControllerDB: file '%s' does not exist.", + xe::path_to_utf8(cvars::mappings_file).c_str()); + } else { + auto mappings_file = filesystem::OpenFile(cvars::mappings_file, "rb"); + if (!mappings_file) { + XELOGE("SDL GameControllerDB: failed to open file '%s'.", + xe::path_to_utf8(cvars::mappings_file).c_str()); + } else { + auto mappings_result = SDL_GameControllerAddMappingsFromRW( + SDL_RWFromFP(mappings_file, SDL_TRUE), 1); + if (mappings_result < 0) { + XELOGE("SDL GameControllerDB: error loading file '%s': %d.", + xe::path_to_utf8(cvars::mappings_file).c_str(), + mappings_result); + } else { + XELOGI("SDL GameControllerDB: loaded %d mappings.", + mappings_result); + } + } + } + } }); return sdl_events_initialized_ && sdl_gamecontroller_initialized_; } diff --git a/src/xenia/kernel/kernel_module.cc b/src/xenia/kernel/kernel_module.cc index 69c958a08..8860fcc1a 100644 --- a/src/xenia/kernel/kernel_module.cc +++ b/src/xenia/kernel/kernel_module.cc @@ -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; diff --git a/src/xenia/kernel/kernel_module.h b/src/xenia/kernel/kernel_module.h index c560a0c65..09d62e95d 100644 --- a/src/xenia/kernel/kernel_module.h +++ b/src/xenia/kernel/kernel_module.h @@ -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; diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 9366c1160..0867aa068 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -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 +#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(); 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(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 KernelState::GetKernelModule(const char* name) { +object_ref KernelState::GetKernelModule( + const std::string_view name) { assert_true(IsKernelModule(name)); for (auto kernel_module : kernel_modules_) { @@ -191,12 +193,13 @@ object_ref KernelState::GetKernelModule(const char* name) { return nullptr; } -object_ref KernelState::GetModule(const char* name, bool user_only) { - if (!name) { +object_ref 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 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 KernelState::LaunchModule(object_ref 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 kernel_module) { kernel_modules_.push_back(std::move(kernel_module)); } -object_ref KernelState::LoadUserModule(const char* raw_name, - bool call_entry) { +object_ref 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 module; diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index 95ce08fb9..32d4e2a91 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -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 module); void UnregisterUserModule(UserModule* module); - bool IsKernelModule(const char* name); - object_ref GetModule(const char* name, bool user_only = false); + bool IsKernelModule(const std::string_view name); + object_ref GetModule(const std::string_view name, + bool user_only = false); object_ref LaunchModule(object_ref module); object_ref GetExecutableModule(); void SetExecutableModule(object_ref module); - object_ref LoadUserModule(const char* name, + object_ref LoadUserModule(const std::string_view name, bool call_entry = true); void UnloadUserModule(const object_ref& module, bool call_entry = true); - object_ref GetKernelModule(const char* name); + object_ref GetKernelModule(const std::string_view name); template object_ref LoadKernelModule() { auto kernel_module = object_ref(new T(emulator_, this)); @@ -142,7 +143,7 @@ class KernelState { return kernel_module; } template - object_ref GetKernelModule(const char* name) { + object_ref GetKernelModule(const std::string_view name) { auto module = GetKernelModule(name); return object_ref(reinterpret_cast(module.release())); } diff --git a/src/xenia/kernel/premake5.lua b/src/xenia/kernel/premake5.lua index 808dc8899..1061c24ea 100644 --- a/src/xenia/kernel/premake5.lua +++ b/src/xenia/kernel/premake5.lua @@ -8,6 +8,7 @@ project("xenia-kernel") language("C++") links({ "aes_128", + "fmt", "xenia-apu", "xenia-base", "xenia-cpu", diff --git a/src/xenia/kernel/user_module.cc b/src/xenia/kernel/user_module.cc index 58ab9f36c..518eaa42b 100644 --- a/src/xenia/kernel/user_module.cc +++ b/src/xenia/kernel/user_module.cc @@ -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::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(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(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(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(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(library->version.value); version_min.value = xe::byte_swap(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(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(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(library.version_major), static_cast(library.version_minor), static_cast(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(opt_header_ptr); - sb.AppendFormat(" Slot Count: %d\n", + sb.AppendFormat(" Slot Count: {}\n", static_cast(opt_tls_info->slot_count)); - sb.AppendFormat(" Raw Data Address: %.8X\n", + sb.AppendFormat(" Raw Data Address: {:08X}\n", static_cast(opt_tls_info->raw_data_address)); - sb.AppendFormat(" Data Size: %d\n", + sb.AppendFormat(" Data Size: {}\n", static_cast(opt_tls_info->data_size)); - sb.AppendFormat(" Raw Data Size: %d\n", + sb.AppendFormat(" Raw Data Size: {}\n", static_cast(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(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(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(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(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(opt_header_ptr); - sb.AppendFormat(" Media ID: %.8X\n", + sb.AppendFormat(" Media ID: {:08X}\n", static_cast(opt_exec_info->media_id)); - sb.AppendFormat(" Title ID: %.8X\n", + sb.AppendFormat(" Title ID: {:08X}\n", static_cast(opt_exec_info->title_id)); - sb.AppendFormat(" Savegame ID: %.8X\n", + sb.AppendFormat(" Savegame ID: {:08X}\n", static_cast(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(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(opt_header_ptr); @@ -650,16 +649,17 @@ void UserModule::Dump() { auto name = reinterpret_cast(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::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::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(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(known_count / total_count), known_count, unknown_count); sb.AppendFormat( - " Implemented: %3d%% (%d implemented, %d unimplemented)\n", + " Implemented: {:3}% ({} implemented, {} unimplemented)\n", static_cast(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 diff --git a/src/xenia/kernel/user_module.h b/src/xenia/kernel/user_module.h index d6c92ba94..f904f8a4f 100644 --- a/src/xenia/kernel/user_module.h +++ b/src/xenia/kernel/user_module.h @@ -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 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; diff --git a/src/xenia/kernel/util/gameinfo_utils.h b/src/xenia/kernel/util/gameinfo_utils.h index 189ac46ef..7108ac8f0 100644 --- a/src/xenia/kernel/util/gameinfo_utils.h +++ b/src/xenia/kernel/util/gameinfo_utils.h @@ -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 title[128]; - xe::be description[256]; - xe::be publisher[256]; // assumed field name from wxPirs + xe::be title[128]; + xe::be description[256]; + xe::be publisher[256]; // assumed field name from wxPirs }; private: diff --git a/src/xenia/kernel/util/object_table.cc b/src/xenia/kernel/util/object_table.cc index c8f33ed19..08db10241 100644 --- a/src/xenia/kernel/util/object_table.cc +++ b/src/xenia/kernel/util/object_table.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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; diff --git a/src/xenia/kernel/util/object_table.h b/src/xenia/kernel/util/object_table.h index 32e48f997..061124047 100644 --- a/src/xenia/kernel/util/object_table.h +++ b/src/xenia/kernel/util/object_table.h @@ -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 #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 std::vector> GetObjectsByType(XObject::Type type) { std::vector> results; @@ -99,7 +100,7 @@ class ObjectTable { uint32_t table_capacity_ = 0; ObjectTableEntry* table_ = nullptr; uint32_t last_free_entry_ = 0; - std::unordered_map name_table_; + std::unordered_map name_table_; }; // Generic lookup diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 60e7525c5..3d9383f6d 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -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 #include +#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(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* guest_string = memory->TranslateVirtual*>( 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&; using lpfloat_t = const shim::PrimitivePointerParam&; using lpdouble_t = const shim::PrimitivePointerParam&; using lpstring_t = const shim::StringPointerParam&; -using lpwstring_t = const shim::StringPointerParam&; +using lpu16string_t = const shim::StringPointerParam&; using function_t = const shim::ParamBase&; using unknown_t = const shim::ParamBase&; 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(param)); + string_buffer->AppendFormat("{:G}", static_cast(param)); } inline void AppendParam(StringBuffer* string_buffer, double_t param) { - string_buffer->AppendFormat("%G", static_cast(param)); + string_buffer->AppendFormat("{:G}", static_cast(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 record) { - string_buffer->AppendFormat("%.8X", record.guest_address()); + string_buffer->AppendFormat("{:08X}", record.guest_address()); if (record) { auto name_string = kernel_memory()->TranslateVirtual(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 reg) { - string_buffer->AppendFormat("%.8X(%.8X, %.8X)", reg.guest_address(), + string_buffer->AppendFormat("{:08X}({:08X}, {:08X})", reg.guest_address(), static_cast(reg->notification_routine), static_cast(reg->priority)); } inline void AppendParam(StringBuffer* string_buffer, pointer_t record) { - string_buffer->AppendFormat("%.8X(%.8X)", record.guest_address(), + string_buffer->AppendFormat("{:08X}({:08X})", record.guest_address(), uint32_t(record->exception_code)); } template void AppendParam(StringBuffer* string_buffer, pointer_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()); } } diff --git a/src/xenia/kernel/xam/apps/xmp_app.cc b/src/xenia/kernel/xam/apps/xmp_app.cc index ec02f6acf..b715623f2 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.cc +++ b/src/xenia/kernel/xam/apps/xmp_app.cc @@ -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->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(memory_->TranslateVirtual( + xe::load_and_swap(memory_->TranslateVirtual( xe::load_and_swap(song_base + 0))); - song->name = xe::load_and_swap(memory_->TranslateVirtual( + song->name = xe::load_and_swap(memory_->TranslateVirtual( xe::load_and_swap(song_base + 4))); - song->artist = xe::load_and_swap(memory_->TranslateVirtual( - xe::load_and_swap(song_base + 8))); - song->album = xe::load_and_swap(memory_->TranslateVirtual( + song->artist = + xe::load_and_swap(memory_->TranslateVirtual( + xe::load_and_swap(song_base + 8))); + song->album = xe::load_and_swap(memory_->TranslateVirtual( xe::load_and_swap(song_base + 12))); song->album_artist = - xe::load_and_swap(memory_->TranslateVirtual( + xe::load_and_swap(memory_->TranslateVirtual( xe::load_and_swap(song_base + 16))); - song->genre = xe::load_and_swap(memory_->TranslateVirtual( + song->genre = xe::load_and_swap(memory_->TranslateVirtual( xe::load_and_swap(song_base + 20))); song->track_number = xe::load_and_swap(song_base + 24); song->duration_ms = xe::load_and_swap(song_base + 28); @@ -310,11 +311,11 @@ X_RESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, xe::store_and_swap( 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( + playlist_name = xe::load_and_swap( 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(info + 0, song->handle); - xe::store_and_swap(info + 4 + 572 + 0, song->name); - xe::store_and_swap(info + 4 + 572 + 40, song->artist); - xe::store_and_swap(info + 4 + 572 + 80, song->album); - xe::store_and_swap(info + 4 + 572 + 120, - song->album_artist); - xe::store_and_swap(info + 4 + 572 + 160, song->genre); + xe::store_and_swap(info + 4 + 572 + 0, song->name); + xe::store_and_swap(info + 4 + 572 + 40, song->artist); + xe::store_and_swap(info + 4 + 572 + 80, song->album); + xe::store_and_swap(info + 4 + 572 + 120, + song->album_artist); + xe::store_and_swap(info + 4 + 572 + 160, song->genre); xe::store_and_swap(info + 4 + 572 + 200, song->track_number); xe::store_and_swap(info + 4 + 572 + 204, song->duration_ms); xe::store_and_swap(info + 4 + 572 + 208, diff --git a/src/xenia/kernel/xam/apps/xmp_app.h b/src/xenia/kernel/xam/apps/xmp_app.h index 751323909..de341a143 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.h +++ b/src/xenia/kernel/xam/apps/xmp_app.h @@ -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> 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); diff --git a/src/xenia/kernel/xam/content_manager.cc b/src/xenia/kernel/xam/content_manager.cc index 2ca34f716..a62fd31e1 100644 --- a/src/xenia/kernel/xam/content_manager.cc +++ b/src/xenia/kernel/xam/content_manager.cc @@ -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 +#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 ContentManager::ListContent(uint32_t device_id, @@ -114,8 +111,8 @@ std::vector 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 ContentManager::ListContent(uint32_t device_id, } std::unique_ptr 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* 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 diff --git a/src/xenia/kernel/xam/content_manager.h b/src/xenia/kernel/xam/content_manager.h index 179939b80..5d0cb7b24 100644 --- a/src/xenia/kernel/xam/content_manager.h +++ b/src/xenia/kernel/xam/content_manager.h @@ -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(ptr + 0); content_type = xe::load_and_swap(ptr + 4); - display_name = xe::load_and_swap(ptr + 8); + display_name = xe::load_and_swap(ptr + 8); file_name = xe::load_and_swap(ptr + 8 + 128 * 2); } void Write(uint8_t* ptr) { xe::store_and_swap(ptr + 0, device_id); xe::store_and_swap(ptr + 4, content_type); - xe::store_and_swap(ptr + 8, display_name); + xe::store_and_swap(ptr + 8, display_name); xe::store_and_swap(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 ListContent(uint32_t device_id, uint32_t content_type); - std::unique_ptr ResolvePackage(std::string root_name, - const XCONTENT_DATA& data); + std::unique_ptr 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* buffer); X_RESULT SetContentThumbnail(const XCONTENT_DATA& data, std::vector 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 open_packages_; + std::unordered_map open_packages_; }; } // namespace xam diff --git a/src/xenia/kernel/xam/user_profile.cc b/src/xenia/kernel/xam/user_profile.cc index 6471b3d1e..1fe8af1a8 100644 --- a/src/xenia/kernel/xam/user_profile.cc +++ b/src/xenia/kernel/xam/user_profile.cc @@ -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 +#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(0x1004000E, 0x64)); // XPROFILE_GAMERCARD_MOTTO - AddSetting(std::make_unique(0x402C0011, L"")); + AddSetting(std::make_unique(0x402C0011, u"")); // XPROFILE_GAMERCARD_TITLES_PLAYED AddSetting(std::make_unique(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(0x4064000F, L"gamercard_picture_key")); + std::make_unique(0x4064000F, u"gamercard_picture_key")); // XPROFILE_TITLE_SPECIFIC1 AddSetting(std::make_unique(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); diff --git a/src/xenia/kernel/xam/user_profile.h b/src/xenia/kernel/xam/user_profile.h index f8f2dacd8..a5c03f254 100644 --- a/src/xenia/kernel/xam/user_profile.h +++ b/src/xenia/kernel/xam/user_profile.h @@ -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(value.size()) + 1); } diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index fb81ce848..98e74fcad 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -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(name_buffer, name); - ((wchar_t*)name_buffer)[name.size()] = 0; + xe::store_and_swap(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(&device_data->name[0], device_info.name); + xe::store_and_swap(&device_data->name[0], device_info.name); return X_ERROR_SUCCESS; } DECLARE_XAM_EXPORT1(XamContentGetDeviceData, kContent, kImplemented); diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index dfb78654c..189d3ca1f 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 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(), 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(), 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(), 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("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; } diff --git a/src/xenia/kernel/xam/xam_locale.cc b/src/xenia/kernel/xam/xam_locale.cc index 9cd5125df..880e5c003 100644 --- a/src/xenia/kernel/xam/xam_locale.cc +++ b/src/xenia/kernel/xam/xam_locale.cc @@ -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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(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(buffer, value); - static_cast(buffer)[value.size()] = 0; + xe::store_and_swap(buffer, value); + static_cast(buffer)[value.size()] = 0; return X_E_SUCCESS; } DECLARE_XAM_EXPORT1(XamGetOnlineLanguageString, kLocale, kImplemented); diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 7df8d194c..85026852d 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -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 buttons, - uint32_t default_button, uint32_t* out_chosen_button) + MessageBoxDialog(xe::ui::Window* window, std::u16string title, + std::u16string description, + std::vector 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(i); @@ -84,34 +85,34 @@ class MessageBoxDialog : public xe::ui::ImGuiDialog { bool has_opened_ = false; std::string title_; std::string description_; - std::vector buttons_; + std::vector 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 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 buttons; - std::wstring all_buttons; + std::vector 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( + auto button = xe::load_and_swap( 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 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 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(buffer, default_text.value()); + xe::store_and_swap(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(buffer, out_text); + xe::store_and_swap(buffer, out_text); // Broadcast XN_SYS_UI = false kernel_state()->BroadcastNotification(0x9, false); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc index ecc7e062b..5dbcf3c82 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc @@ -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(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( @@ -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 } diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc index 21676c425..65a90c566 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc @@ -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 +#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(scratch + 0); - auto command = memory_->TranslateVirtual(scratch + 260); + auto response = reinterpret_cast(scratch + 0); + auto command = reinterpret_cast(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; diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc index 5c5ed2177..41f4b5d54 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc @@ -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, §ion_data, §ion_size); + result = module->GetSection(name.value(), §ion_data, §ion_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 diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc index 9ab490ff5..dc4c67dc2 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc @@ -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 path, - pointer_t 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 path_ptr, + pointer_t 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 path, } DECLARE_XBOXKRNL_EXPORT1(ObCreateSymbolicLink, kNone, kImplemented); -dword_result_t ObDeleteSymbolicLink(pointer_t path) { - auto path_str = util::TranslateAnsiString(kernel_memory(), path); - if (!kernel_state()->file_system()->UnregisterSymbolicLink(path_str)) { +dword_result_t ObDeleteSymbolicLink(pointer_t path_ptr) { + auto path = util::TranslateAnsiString(kernel_memory(), path_ptr); + if (!kernel_state()->file_system()->UnregisterSymbolicLink(path)) { return X_STATUS_UNSUCCESSFUL; } diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc index 22170cb1f..e06daba48 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc @@ -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 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; } diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc index 88b59c74e..be0a94eb6 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc @@ -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 output_; }; class WideCountFormatData : public FormatData { diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc index b6913e528..d003e22be 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc @@ -294,7 +294,7 @@ struct BufferScaling { }; void AppendParam(StringBuffer* string_buffer, pointer_t 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)); } diff --git a/src/xenia/kernel/xfile.cc b/src/xenia/kernel/xfile.cc index 857b7444a..0e1846a4d 100644 --- a/src/xenia/kernel/xfile.cc +++ b/src/xenia/kernel/xfile.cc @@ -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); diff --git a/src/xenia/kernel/xfile.h b/src/xenia/kernel/xfile.h index 2e4feb87a..53bc5fa0d 100644 --- a/src/xenia/kernel/xfile.h +++ b/src/xenia/kernel/xfile.h @@ -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 diff --git a/src/xenia/kernel/xmodule.cc b/src/xenia/kernel/xmodule.cc index 0d734bad4..d8af132ef 100644 --- a/src/xenia/kernel/xmodule.cc +++ b/src/xenia/kernel/xmodule.cc @@ -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::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; diff --git a/src/xenia/kernel/xmodule.h b/src/xenia/kernel/xmodule.h index baaf0256f..2fbd6b9d5 100644 --- a/src/xenia/kernel/xmodule.h +++ b/src/xenia/kernel/xmodule.h @@ -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 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_; diff --git a/src/xenia/kernel/xsymboliclink.cc b/src/xenia/kernel/xsymboliclink.cc index 0908375ca..557a4a3c1 100644 --- a/src/xenia/kernel/xsymboliclink.cc +++ b/src/xenia/kernel/xsymboliclink.cc @@ -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); diff --git a/src/xenia/kernel/xsymboliclink.h b/src/xenia/kernel/xsymboliclink.h index 7ca5dc58e..2d37dfd72 100644 --- a/src/xenia/kernel/xsymboliclink.h +++ b/src/xenia/kernel/xsymboliclink.h @@ -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 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(); diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index 4028765a8..7eb155e0a 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -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 #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()->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) { diff --git a/src/xenia/kernel/xthread.h b/src/xenia/kernel/xthread.h index cfb53967e..2b6518703 100644 --- a/src/xenia/kernel/xthread.h +++ b/src/xenia/kernel/xthread.h @@ -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); diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index 256360a5a..15d788c28 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -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 #include +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" @@ -124,8 +125,8 @@ Memory::~Memory() { } bool Memory::Initialize() { - file_name_ = std::wstring(L"Local\\xenia_memory_") + - std::to_wstring(Clock::QueryHostTickCount()); + file_name_ = + fmt::format("Local\\xenia_memory_{}", Clock::QueryHostTickCount()); // Create main page file-backed mapping. This is all reserved but // uncommitted (so it shouldn't expand page file). diff --git a/src/xenia/memory.h b/src/xenia/memory.h index a10bce5f1..fa0c62f4c 100644 --- a/src/xenia/memory.h +++ b/src/xenia/memory.h @@ -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. * ****************************************************************************** */ @@ -300,7 +300,7 @@ class Memory { void Reset(); // Full file name and path of the memory-mapped file backing all memory. - const std::wstring& file_name() const { return file_name_; } + const std::filesystem::path& file_name() const { return file_name_; } // Base address of virtual memory in the host address space. // This is often something like 0x100000000. @@ -485,7 +485,7 @@ class Memory { std::unique_lock global_lock_locked_once, void* context, void* host_address, bool is_write); - std::wstring file_name_; + std::filesystem::path file_name_; uint32_t system_page_size_ = 0; uint32_t system_allocation_granularity_ = 0; uint8_t* virtual_membase_ = nullptr; diff --git a/src/xenia/premake5.lua b/src/xenia/premake5.lua index b403f42f9..4d01ea74e 100644 --- a/src/xenia/premake5.lua +++ b/src/xenia/premake5.lua @@ -7,6 +7,7 @@ project("xenia-core") kind("StaticLib") language("C++") links({ + "fmt", "xenia-base", }) defines({ diff --git a/src/xenia/ui/d3d12/d3d12_provider.cc b/src/xenia/ui/d3d12/d3d12_provider.cc index d1a9194ca..ece3beed4 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.cc +++ b/src/xenia/ui/d3d12/d3d12_provider.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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,7 +28,7 @@ namespace ui { namespace d3d12 { bool D3D12Provider::IsD3D12APIAvailable() { - HMODULE library_d3d12 = LoadLibrary(L"D3D12.dll"); + HMODULE library_d3d12 = LoadLibraryW(L"D3D12.dll"); if (!library_d3d12) { return false; } @@ -82,9 +82,9 @@ D3D12Provider::~D3D12Provider() { bool D3D12Provider::Initialize() { // Load the libraries. - library_dxgi_ = LoadLibrary(L"dxgi.dll"); - library_d3d12_ = LoadLibrary(L"D3D12.dll"); - library_d3dcompiler_ = LoadLibrary(L"D3DCompiler_47.dll"); + library_dxgi_ = LoadLibraryW(L"dxgi.dll"); + library_d3d12_ = LoadLibraryW(L"D3D12.dll"); + library_d3dcompiler_ = LoadLibraryW(L"D3DCompiler_47.dll"); if (library_dxgi_ == nullptr || library_d3d12_ == nullptr || library_d3dcompiler_ == nullptr) { XELOGE("Failed to load dxgi.dll, D3D12.dll and D3DCompiler_47.dll."); diff --git a/src/xenia/ui/file_picker.h b/src/xenia/ui/file_picker.h index aa0a7607a..6a2259007 100644 --- a/src/xenia/ui/file_picker.h +++ b/src/xenia/ui/file_picker.h @@ -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. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_UI_FILE_PICKER_H_ #define XENIA_UI_FILE_PICKER_H_ +#include #include #include #include @@ -34,7 +35,7 @@ class FilePicker { FilePicker() : mode_(Mode::kOpen), type_(Type::kFile), - title_(L"Select Files"), + title_("Select Files"), multi_selection_(false) {} virtual ~FilePicker() = default; @@ -44,14 +45,14 @@ class FilePicker { Type type() const { return type_; } void set_type(Type type) { type_ = type; } - std::wstring title() const { return title_; } - void set_title(std::wstring title) { title_ = std::move(title); } + const std::string& title() const { return title_; } + void set_title(std::string title) { title_ = std::move(title); } - std::vector> extensions() const { + std::vector> extensions() const { return extensions_; } void set_extensions( - std::vector> extensions) { + std::vector> extensions) { extensions_ = std::move(extensions); } @@ -60,8 +61,10 @@ class FilePicker { multi_selection_ = multi_selection; } - std::vector selected_files() const { return selected_files_; } - void set_selected_files(std::vector selected_files) { + std::vector selected_files() const { + return selected_files_; + } + void set_selected_files(std::vector selected_files) { selected_files_ = std::move(selected_files); } @@ -70,11 +73,11 @@ class FilePicker { private: Mode mode_; Type type_; - std::wstring title_; - std::vector> extensions_; + std::string title_; + std::vector> extensions_; bool multi_selection_; - std::vector selected_files_; + std::vector selected_files_; }; } // namespace ui diff --git a/src/xenia/ui/file_picker_gtk.cc b/src/xenia/ui/file_picker_gtk.cc index dce28772d..456582906 100644 --- a/src/xenia/ui/file_picker_gtk.cc +++ b/src/xenia/ui/file_picker_gtk.cc @@ -2,18 +2,23 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/ui/file_picker.h" -#include -#include +#include #include + +#include +#include + #include "xenia/base/assert.h" +#include "xenia/base/filesystem.h" #include "xenia/base/platform_linux.h" +#include "xenia/base/string.h" namespace xe { namespace ui { @@ -54,10 +59,8 @@ bool GtkFilePicker::Show(void* parent_window_handle) { if (res == GTK_RESPONSE_ACCEPT) { GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog); filename = gtk_file_chooser_get_filename(chooser); - std::vector selected_files; - std::wstring_convert> converter; - std::wstring ws_filename = converter.from_bytes(filename); - selected_files.push_back(ws_filename); + std::vector selected_files; + selected_files.push_back(xe::to_path(std::string(filename))); set_selected_files(selected_files); gtk_widget_destroy(dialog); return true; diff --git a/src/xenia/ui/file_picker_win.cc b/src/xenia/ui/file_picker_win.cc index e90f2c478..7af0fd57e 100644 --- a/src/xenia/ui/file_picker_win.cc +++ b/src/xenia/ui/file_picker_win.cc @@ -2,15 +2,15 @@ ****************************************************************************** * 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. * ****************************************************************************** */ -#include "xenia/ui/file_picker.h" - #include "xenia/base/assert.h" #include "xenia/base/platform_win.h" +#include "xenia/base/string.h" +#include "xenia/ui/file_picker.h" namespace xe { namespace ui { @@ -136,7 +136,7 @@ bool Win32FilePicker::Show(void* parent_window_handle) { return false; } - hr = file_dialog->SetTitle(title().c_str()); + hr = file_dialog->SetTitle((LPCWSTR)xe::to_utf16(title()).c_str()); if (!SUCCEEDED(hr)) { return false; } @@ -159,13 +159,17 @@ bool Win32FilePicker::Show(void* parent_window_handle) { } // Set the file types to display only. Notice that this is a 1-based array. - std::vector save_types; - auto extensions = this->extensions(); - for (auto& extension : extensions) { - save_types.push_back({extension.first.c_str(), extension.second.c_str()}); + std::vector> file_pairs; + std::vector file_types; + for (const auto& extension : this->extensions()) { + const auto& file_pair = + file_pairs.emplace_back(std::move(xe::to_utf16(extension.first)), + std::move(xe::to_utf16(extension.second))); + file_types.push_back( + {(LPCWSTR)file_pair.first.c_str(), (LPCWSTR)file_pair.second.c_str()}); } - hr = file_dialog->SetFileTypes(static_cast(save_types.size()), - save_types.data()); + hr = file_dialog->SetFileTypes(static_cast(file_types.size()), + file_types.data()); if (!SUCCEEDED(hr)) { return false; } @@ -209,8 +213,8 @@ bool Win32FilePicker::Show(void* parent_window_handle) { if (!SUCCEEDED(hr)) { return false; } - std::vector selected_files; - selected_files.push_back(std::wstring(file_path)); + std::vector selected_files; + selected_files.push_back(std::filesystem::path(file_path)); set_selected_files(selected_files); CoTaskMemFree(file_path); diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 3f0c0b9f8..2027512e3 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -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. * ****************************************************************************** */ @@ -136,7 +136,7 @@ void ImGuiDrawer::SetupFont() { // TODO(benvanik): jp font on other platforms? // https://github.com/Koruri/kibitaki looks really good, but is 1.5MiB. const char* jp_font_path = "C:\\Windows\\Fonts\\msgothic.ttc"; - if (xe::filesystem::PathExists(xe::to_wstring(jp_font_path))) { + if (xe::filesystem::PathExists(jp_font_path)) { ImFontConfig jp_font_config; jp_font_config.MergeMode = true; jp_font_config.OversampleH = jp_font_config.OversampleV = 1; diff --git a/src/xenia/ui/loop_gtk.cc b/src/xenia/ui/loop_gtk.cc index 8beb967e5..4a753c853 100644 --- a/src/xenia/ui/loop_gtk.cc +++ b/src/xenia/ui/loop_gtk.cc @@ -2,13 +2,16 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/ui/loop_gtk.h" +#include +#include + #include "xenia/base/assert.h" namespace xe { diff --git a/src/xenia/ui/menu_item.cc b/src/xenia/ui/menu_item.cc index da3195105..5563b8760 100644 --- a/src/xenia/ui/menu_item.cc +++ b/src/xenia/ui/menu_item.cc @@ -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. * ****************************************************************************** */ @@ -13,21 +13,20 @@ namespace xe { namespace ui { std::unique_ptr MenuItem::Create(Type type) { - return MenuItem::Create(type, L"", L"", nullptr); + return MenuItem::Create(type, "", "", nullptr); } -std::unique_ptr MenuItem::Create(Type type, - const std::wstring& text) { - return MenuItem::Create(type, text, L"", nullptr); +std::unique_ptr MenuItem::Create(Type type, const std::string& text) { + return MenuItem::Create(type, text, "", nullptr); } -std::unique_ptr MenuItem::Create(Type type, const std::wstring& text, +std::unique_ptr MenuItem::Create(Type type, const std::string& text, std::function callback) { - return MenuItem::Create(type, text, L"", std::move(callback)); + return MenuItem::Create(type, text, "", std::move(callback)); } -MenuItem::MenuItem(Type type, const std::wstring& text, - const std::wstring& hotkey, std::function callback) +MenuItem::MenuItem(Type type, const std::string& text, + const std::string& hotkey, std::function callback) : type_(type), parent_item_(nullptr), text_(text), diff --git a/src/xenia/ui/menu_item.h b/src/xenia/ui/menu_item.h index ca45a5b8b..8b61f040a 100644 --- a/src/xenia/ui/menu_item.h +++ b/src/xenia/ui/menu_item.h @@ -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. * ****************************************************************************** */ @@ -34,19 +34,19 @@ class MenuItem { }; static std::unique_ptr Create(Type type); - static std::unique_ptr Create(Type type, const std::wstring& text); - static std::unique_ptr Create(Type type, const std::wstring& text, + static std::unique_ptr Create(Type type, const std::string& text); + static std::unique_ptr Create(Type type, const std::string& text, std::function callback); - static std::unique_ptr Create(Type type, const std::wstring& text, - const std::wstring& hotkey, + static std::unique_ptr Create(Type type, const std::string& text, + const std::string& hotkey, std::function callback); virtual ~MenuItem(); MenuItem* parent_item() const { return parent_item_; } Type type() { return type_; } - const std::wstring& text() { return text_; } - const std::wstring& hotkey() { return hotkey_; } + const std::string& text() { return text_; } + const std::string& hotkey() { return hotkey_; } void AddChild(MenuItem* child_item); void AddChild(std::unique_ptr child_item); @@ -58,7 +58,7 @@ class MenuItem { virtual void DisableMenuItem(Window& window) = 0; protected: - MenuItem(Type type, const std::wstring& text, const std::wstring& hotkey, + MenuItem(Type type, const std::string& text, const std::string& hotkey, std::function callback); virtual void OnChildAdded(MenuItem* child_item) {} @@ -69,8 +69,8 @@ class MenuItem { Type type_; MenuItem* parent_item_; std::vector children_; - std::wstring text_; - std::wstring hotkey_; + std::string text_; + std::string hotkey_; std::function callback_; }; diff --git a/src/xenia/ui/spirv/spirv_assembler.h b/src/xenia/ui/spirv/spirv_assembler.h index f33515c6c..3fabc5d61 100644 --- a/src/xenia/ui/spirv/spirv_assembler.h +++ b/src/xenia/ui/spirv/spirv_assembler.h @@ -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. * ****************************************************************************** */ @@ -54,8 +54,8 @@ class SpirvAssembler { // The return may have an error set on it if the source text is malformed. std::unique_ptr Assemble(const char* source_text, size_t source_text_length); - std::unique_ptr Assemble(const std::string& source_text) { - return Assemble(source_text.c_str(), source_text.size()); + std::unique_ptr Assemble(const std::string_view source_text) { + return Assemble(source_text.data(), source_text.size()); } private: diff --git a/src/xenia/ui/ui_event.h b/src/xenia/ui/ui_event.h index db494a1c6..9fd4734ba 100644 --- a/src/xenia/ui/ui_event.h +++ b/src/xenia/ui/ui_event.h @@ -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. * ****************************************************************************** */ @@ -10,6 +10,8 @@ #ifndef XENIA_UI_UI_EVENT_H_ #define XENIA_UI_UI_EVENT_H_ +#include + namespace xe { namespace ui { @@ -28,14 +30,14 @@ class UIEvent { class FileDropEvent : public UIEvent { public: - FileDropEvent(Window* target, const wchar_t* filename) - : UIEvent(target), filename_(filename) {} + FileDropEvent(Window* target, std::filesystem::path filename) + : UIEvent(target), filename_(std::move(filename)) {} ~FileDropEvent() override = default; - const wchar_t* filename() const { return filename_; } + const std::filesystem::path& filename() const { return filename_; } private: - const wchar_t* filename_ = nullptr; + const std::filesystem::path filename_; }; class KeyEvent : public UIEvent { diff --git a/src/xenia/ui/vulkan/premake5.lua b/src/xenia/ui/vulkan/premake5.lua index 5d04b98d2..d93f98af6 100644 --- a/src/xenia/ui/vulkan/premake5.lua +++ b/src/xenia/ui/vulkan/premake5.lua @@ -7,6 +7,7 @@ project("xenia-ui-vulkan") kind("StaticLib") language("C++") links({ + "fmt", "xenia-base", "xenia-ui", "xenia-ui-spirv", @@ -28,6 +29,7 @@ project("xenia-ui-window-vulkan-demo") kind("WindowedApp") language("C++") links({ + "fmt", "imgui", "volk", "xenia-base", diff --git a/src/xenia/ui/vulkan/vulkan_context.cc b/src/xenia/ui/vulkan/vulkan_context.cc index 0df97b4b3..339f099ef 100644 --- a/src/xenia/ui/vulkan/vulkan_context.cc +++ b/src/xenia/ui/vulkan/vulkan_context.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2017 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. * ****************************************************************************** */ @@ -27,6 +27,8 @@ #if XE_PLATFORM_LINUX #include "xenia/ui/window_gtk.h" + +#include #endif namespace xe { diff --git a/src/xenia/ui/vulkan/vulkan_instance.cc b/src/xenia/ui/vulkan/vulkan_instance.cc index fd265a405..782d73f2b 100644 --- a/src/xenia/ui/vulkan/vulkan_instance.cc +++ b/src/xenia/ui/vulkan/vulkan_instance.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2017 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. * ****************************************************************************** */ @@ -106,7 +106,7 @@ bool VulkanInstance::EnableRenderDoc() { // RenderDoc injects itself into our process, so we should be able to get it. pRENDERDOC_GetAPI get_api = nullptr; #if XE_PLATFORM_WIN32 - auto module_handle = GetModuleHandle(L"renderdoc.dll"); + auto module_handle = GetModuleHandleW(L"renderdoc.dll"); if (!module_handle) { XELOGI("RenderDoc support requested but it is not attached"); return false; diff --git a/src/xenia/ui/vulkan/vulkan_util.cc b/src/xenia/ui/vulkan/vulkan_util.cc index 2682077e5..a5dceff46 100644 --- a/src/xenia/ui/vulkan/vulkan_util.cc +++ b/src/xenia/ui/vulkan/vulkan_util.cc @@ -2,13 +2,14 @@ ****************************************************************************** * 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. * ****************************************************************************** */ #include "xenia/ui/vulkan/vulkan_util.h" +#include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/logging.h" @@ -29,8 +30,8 @@ Version Version::Parse(uint32_t value) { version.major = VK_VERSION_MAJOR(value); version.minor = VK_VERSION_MINOR(value); version.patch = VK_VERSION_PATCH(value); - version.pretty_string = xe::format_string("%u.%u.%u", version.major, - version.minor, version.patch); + version.pretty_string = + fmt::format("{}.{}.{}", version.major, version.minor, version.patch); return version; } diff --git a/src/xenia/ui/vulkan/vulkan_window_demo.cc b/src/xenia/ui/vulkan/vulkan_window_demo.cc index 6f2fa4464..12965197b 100644 --- a/src/xenia/ui/vulkan/vulkan_window_demo.cc +++ b/src/xenia/ui/vulkan/vulkan_window_demo.cc @@ -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. * ****************************************************************************** */ @@ -17,7 +17,7 @@ namespace xe { namespace ui { -int window_demo_main(const std::vector& args); +int window_demo_main(const std::vector& args); std::unique_ptr CreateDemoGraphicsProvider(Window* window) { return xe::ui::vulkan::VulkanProvider::Create(window); @@ -26,5 +26,4 @@ std::unique_ptr CreateDemoGraphicsProvider(Window* window) { } // namespace ui } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-ui-window-vulkan-demo", xe::ui::window_demo_main, - ""); +DEFINE_ENTRY_POINT("xenia-ui-window-vulkan-demo", xe::ui::window_demo_main, ""); diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index c039cec0a..8be8900c8 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -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. * ****************************************************************************** */ @@ -31,7 +31,7 @@ constexpr double kDoubleClickDistance = 5; constexpr int32_t kMouseWheelDetent = 120; -Window::Window(Loop* loop, const std::wstring& title) +Window::Window(Loop* loop, const std::string& title) : loop_(loop), title_(title) {} Window::~Window() { diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index 2cb5c8c34..4814dee0c 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -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. * ****************************************************************************** */ @@ -30,7 +30,7 @@ class ImGuiDrawer; class Window { public: - static std::unique_ptr Create(Loop* loop, const std::wstring& title); + static std::unique_ptr Create(Loop* loop, const std::string& title); virtual ~Window(); @@ -47,8 +47,8 @@ class Window { virtual void EnableMainMenu() = 0; virtual void DisableMainMenu() = 0; - const std::wstring& title() const { return title_; } - virtual bool set_title(const std::wstring& title) { + const std::string& title() const { return title_; } + virtual bool set_title(const std::string& title) { if (title == title_) { return false; } @@ -131,7 +131,7 @@ class Window { Delegate on_mouse_wheel; protected: - Window(Loop* loop, const std::wstring& title); + Window(Loop* loop, const std::string& title); void ForEachListener(std::function fn); void TryForEachListener(std::function fn); @@ -168,7 +168,7 @@ class Window { Loop* loop_ = nullptr; std::unique_ptr main_menu_; - std::wstring title_; + std::string title_; int32_t width_ = 0; int32_t height_ = 0; bool has_focus_ = true; diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc index edb6654dc..a6a05140a 100644 --- a/src/xenia/ui/window_demo.cc +++ b/src/xenia/ui/window_demo.cc @@ -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. * ****************************************************************************** */ @@ -26,7 +26,7 @@ namespace ui { // Implemented in one of the window_*_demo.cc files under a subdir. std::unique_ptr CreateDemoGraphicsProvider(Window* window); -int window_demo_main(const std::vector& args) { +int window_demo_main(const std::vector& args) { Profiler::Initialize(); Profiler::ThreadEnter("main"); @@ -44,20 +44,20 @@ int window_demo_main(const std::vector& args) { // Main menu. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); - auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File"); + auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"&Close", - L"Alt+F4", + file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close", + "Alt+F4", [&window]() { window->Close(); })); } main_menu->AddChild(std::move(file_menu)); - auto debug_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Debug"); + auto debug_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Debug"); { debug_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, - L"Toggle Profiler &Display", L"F3", + "Toggle Profiler &Display", "F3", []() { Profiler::ToggleDisplay(); })); debug_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, - L"&Pause/Resume Profiler", L"`", + "&Pause/Resume Profiler", "`", []() { Profiler::TogglePause(); })); } main_menu->AddChild(std::move(debug_menu)); diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc index 2e94f6ddc..a6ca2087b 100644 --- a/src/xenia/ui/window_gtk.cc +++ b/src/xenia/ui/window_gtk.cc @@ -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. * ****************************************************************************** */ @@ -26,11 +26,11 @@ class FnWrapper { std::function fn_; }; -std::unique_ptr Window::Create(Loop* loop, const std::wstring& title) { +std::unique_ptr Window::Create(Loop* loop, const std::string& title) { return std::make_unique(loop, title); } -GTKWindow::GTKWindow(Loop* loop, const std::wstring& title) +GTKWindow::GTKWindow(Loop* loop, const std::string& title) : Window(loop, title) {} GTKWindow::~GTKWindow() { @@ -99,7 +99,7 @@ void GTKWindow::OnClose() { super::OnClose(); } -bool GTKWindow::set_title(const std::wstring& title) { +bool GTKWindow::set_title(const std::string& title) { if (!super::set_title(title)) { return false; } @@ -368,8 +368,8 @@ bool GTKWindow::HandleKeyboard(GdkEventKey* event) { } std::unique_ptr MenuItem::Create(Type type, - const std::wstring& text, - const std::wstring& hotkey, + const std::string& text, + const std::string& hotkey, std::function callback) { return std::make_unique(type, text, hotkey, callback); } @@ -380,8 +380,8 @@ static void _menu_activate_callback(GtkWidget* menu, gpointer data) { delete fn; } -GTKMenuItem::GTKMenuItem(Type type, const std::wstring& text, - const std::wstring& hotkey, +GTKMenuItem::GTKMenuItem(Type type, const std::string& text, + const std::string& hotkey, std::function callback) : MenuItem(type, text, hotkey, std::move(callback)) { switch (type) { @@ -390,7 +390,7 @@ GTKMenuItem::GTKMenuItem(Type type, const std::wstring& text, menu_ = gtk_menu_bar_new(); break; case MenuItem::Type::kPopup: - menu_ = gtk_menu_item_new_with_label((gchar*)xe::to_string(text).c_str()); + menu_ = gtk_menu_item_new_with_label((gchar*)text.c_str()); break; case MenuItem::Type::kSeparator: menu_ = gtk_separator_menu_item_new(); @@ -398,10 +398,9 @@ GTKMenuItem::GTKMenuItem(Type type, const std::wstring& text, case MenuItem::Type::kString: auto full_name = text; if (!hotkey.empty()) { - full_name += L"\t" + hotkey; + full_name += "\t" + hotkey; } - menu_ = gtk_menu_item_new_with_label( - (gchar*)xe::to_string(full_name).c_str()); + menu_ = gtk_menu_item_new_with_label((gchar*)full_name.c_str()); break; } if (GTK_IS_MENU_ITEM(menu_)) diff --git a/src/xenia/ui/window_gtk.h b/src/xenia/ui/window_gtk.h index 22921a5e1..af842cf15 100644 --- a/src/xenia/ui/window_gtk.h +++ b/src/xenia/ui/window_gtk.h @@ -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. * ****************************************************************************** */ @@ -13,6 +13,9 @@ #include #include +#include +#include + #include "xenia/base/platform_linux.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/window.h" @@ -24,7 +27,7 @@ class GTKWindow : public Window { using super = Window; public: - GTKWindow(Loop* loop, const std::wstring& title); + GTKWindow(Loop* loop, const std::string& title); ~GTKWindow() override; NativePlatformHandle native_platform_handle() const override { @@ -35,7 +38,7 @@ class GTKWindow : public Window { void EnableMainMenu() override {} void DisableMainMenu() override {} - bool set_title(const std::wstring& title) override; + bool set_title(const std::string& title) override; bool SetIcon(const void* buffer, size_t size) override; @@ -82,7 +85,7 @@ class GTKWindow : public Window { class GTKMenuItem : public MenuItem { public: - GTKMenuItem(Type type, const std::wstring& text, const std::wstring& hotkey, + GTKMenuItem(Type type, const std::string& text, const std::string& hotkey, std::function callback); ~GTKMenuItem() override; diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index 2912ec4a0..aadd27c3f 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -2,27 +2,30 @@ ****************************************************************************** * 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/ui/window_win.h" + #include + #include #include "xenia/base/assert.h" +#include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/platform_win.h" -#include "xenia/ui/window_win.h" namespace xe { namespace ui { -std::unique_ptr Window::Create(Loop* loop, const std::wstring& title) { +std::unique_ptr Window::Create(Loop* loop, const std::string& title) { return std::make_unique(loop, title); } -Win32Window::Win32Window(Loop* loop, const std::wstring& title) +Win32Window::Win32Window(Loop* loop, const std::string& title) : Window(loop, title) {} Win32Window::~Win32Window() { @@ -48,7 +51,7 @@ bool Win32Window::OnCreate() { HINSTANCE hInstance = GetModuleHandle(nullptr); if (!SetProcessDpiAwareness_ || !GetDpiForMonitor_) { - auto shcore = GetModuleHandle(L"shcore.dll"); + auto shcore = GetModuleHandleW(L"shcore.dll"); if (shcore) { SetProcessDpiAwareness_ = GetProcAddress(shcore, "SetProcessDpiAwareness"); @@ -74,8 +77,8 @@ bool Win32Window::OnCreate() { wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(hInstance, L"MAINICON"); - wcex.hIconSm = NULL; // LoadIcon(hInstance, L"MAINICON"); + wcex.hIcon = LoadIconW(hInstance, L"MAINICON"); + wcex.hIconSm = NULL; // LoadIconW(hInstance, L"MAINICON"); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = nullptr; @@ -94,16 +97,18 @@ bool Win32Window::OnCreate() { AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); // Create window. - hwnd_ = CreateWindowEx(window_ex_style, L"XeniaWindowClass", title_.c_str(), - window_style, rc.left, rc.top, rc.right - rc.left, - rc.bottom - rc.top, nullptr, nullptr, hInstance, this); + hwnd_ = + CreateWindowExW(window_ex_style, L"XeniaWindowClass", + reinterpret_cast(xe::to_utf16(title_).c_str()), + window_style, rc.left, rc.top, rc.right - rc.left, + rc.bottom - rc.top, nullptr, nullptr, hInstance, this); if (!hwnd_) { XELOGE("CreateWindow failed"); return false; } // Disable flicks. - ATOM atom = GlobalAddAtom(L"MicrosoftTabletPenServiceProperty"); + ATOM atom = GlobalAddAtomW(L"MicrosoftTabletPenServiceProperty"); const DWORD_PTR dwHwndTabletProperty = TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) // gesture @@ -114,8 +119,8 @@ bool Win32Window::OnCreate() { // drag up) TABLET_DISABLE_TOUCHSWITCH | TABLET_DISABLE_SMOOTHSCROLLING | TABLET_DISABLE_TOUCHUIFORCEON | TABLET_ENABLE_MULTITOUCHDATA; - SetProp(hwnd_, L"MicrosoftTabletPenServiceProperty", - reinterpret_cast(dwHwndTabletProperty)); + SetPropW(hwnd_, L"MicrosoftTabletPenServiceProperty", + reinterpret_cast(dwHwndTabletProperty)); GlobalDeleteAtom(atom); // Enable DWM elevation. @@ -140,7 +145,7 @@ bool Win32Window::OnCreate() { } void Win32Window::EnableMMCSS() { - HMODULE hLibrary = LoadLibrary(L"DWMAPI.DLL"); + HMODULE hLibrary = LoadLibraryW(L"DWMAPI.DLL"); if (!hLibrary) { return; } @@ -193,11 +198,11 @@ void Win32Window::DisableMainMenu() { } } -bool Win32Window::set_title(const std::wstring& title) { +bool Win32Window::set_title(const std::string& title) { if (!super::set_title(title)) { return false; } - SetWindowText(hwnd_, title.c_str()); + SetWindowTextW(hwnd_, reinterpret_cast(xe::to_utf16(title).c_str())); return true; } @@ -208,11 +213,11 @@ bool Win32Window::SetIcon(const void* buffer, size_t size) { } // Reset icon to default. - auto default_icon = LoadIcon(GetModuleHandle(nullptr), L"MAINICON"); - SendMessage(hwnd_, WM_SETICON, ICON_BIG, - reinterpret_cast(default_icon)); - SendMessage(hwnd_, WM_SETICON, ICON_SMALL, - reinterpret_cast(default_icon)); + auto default_icon = LoadIconW(GetModuleHandle(nullptr), L"MAINICON"); + SendMessageW(hwnd_, WM_SETICON, ICON_BIG, + reinterpret_cast(default_icon)); + SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, + reinterpret_cast(default_icon)); if (!buffer || !size) { return true; } @@ -223,8 +228,9 @@ bool Win32Window::SetIcon(const void* buffer, size_t size) { static_cast(size), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); if (icon_) { - SendMessage(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon_)); - SendMessage(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast(icon_)); + SendMessageW(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon_)); + SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, + reinterpret_cast(icon_)); } return false; @@ -493,7 +499,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, switch (message) { case WM_DROPFILES: { HDROP hDrop = reinterpret_cast(wParam); - std::wstring path; + std::u16string path; // Get required buffer size UINT buf_size = DragQueryFileW(hDrop, 0, nullptr, 0); @@ -501,8 +507,8 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, path.resize(buf_size + 1); // Give space for a null terminator // Only getting first file dropped (other files ignored) - if (DragQueryFileW(hDrop, 0, &path[0], buf_size + 1)) { - auto e = FileDropEvent(this, path.c_str()); + if (DragQueryFileW(hDrop, 0, (LPWSTR)&path[0], buf_size + 1)) { + auto e = FileDropEvent(this, xe::to_path(path)); OnFileDrop(&e); } } @@ -512,7 +518,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, case WM_NCCREATE: { // Tell Windows to automatically scale non-client areas on different DPIs. auto en = (BOOL(WINAPI*)(HWND hwnd))GetProcAddress( - GetModuleHandle(L"user32.dll"), "EnableNonClientDpiScaling"); + GetModuleHandleW(L"user32.dll"), "EnableNonClientDpiScaling"); if (en) { en(hWnd); } @@ -716,14 +722,14 @@ bool Win32Window::HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam) { } std::unique_ptr MenuItem::Create(Type type, - const std::wstring& text, - const std::wstring& hotkey, + const std::string& text, + const std::string& hotkey, std::function callback) { return std::make_unique(type, text, hotkey, callback); } -Win32MenuItem::Win32MenuItem(Type type, const std::wstring& text, - const std::wstring& hotkey, +Win32MenuItem::Win32MenuItem(Type type, const std::string& text, + const std::string& hotkey, std::function callback) : MenuItem(type, text, hotkey, std::move(callback)) { switch (type) { @@ -777,9 +783,9 @@ void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) { // Nothing special. break; case MenuItem::Type::kPopup: - AppendMenuW(handle_, MF_POPUP, - reinterpret_cast(child_item->handle()), - child_item->text().c_str()); + AppendMenuW( + handle_, MF_POPUP, reinterpret_cast(child_item->handle()), + reinterpret_cast(xe::to_utf16(child_item->text()).c_str())); break; case MenuItem::Type::kSeparator: AppendMenuW(handle_, MF_SEPARATOR, UINT_PTR(child_item->handle_), 0); @@ -787,10 +793,10 @@ void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) { case MenuItem::Type::kString: auto full_name = child_item->text(); if (!child_item->hotkey().empty()) { - full_name += L"\t" + child_item->hotkey(); + full_name += "\t" + child_item->hotkey(); } AppendMenuW(handle_, MF_STRING, UINT_PTR(child_item->handle_), - full_name.c_str()); + reinterpret_cast(xe::to_utf16(full_name).c_str())); break; } } diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index d885042ea..dc8868431 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -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. * ****************************************************************************** */ @@ -13,6 +13,7 @@ #include #include +#include "xenia/base/platform_win.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/window.h" @@ -23,7 +24,7 @@ class Win32Window : public Window { using super = Window; public: - Win32Window(Loop* loop, const std::wstring& title); + Win32Window(Loop* loop, const std::string& title); ~Win32Window() override; NativePlatformHandle native_platform_handle() const override; @@ -33,7 +34,7 @@ class Win32Window : public Window { void EnableMainMenu() override; void DisableMainMenu() override; - bool set_title(const std::wstring& title) override; + bool set_title(const std::string& title) override; bool SetIcon(const void* buffer, size_t size) override; @@ -92,7 +93,7 @@ class Win32Window : public Window { class Win32MenuItem : public MenuItem { public: - Win32MenuItem(Type type, const std::wstring& text, const std::wstring& hotkey, + Win32MenuItem(Type type, const std::string& text, const std::string& hotkey, std::function callback); ~Win32MenuItem() override; diff --git a/src/xenia/vfs/device.cc b/src/xenia/vfs/device.cc index 8531e46a4..251207167 100644 --- a/src/xenia/vfs/device.cc +++ b/src/xenia/vfs/device.cc @@ -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. * ****************************************************************************** */ @@ -14,7 +14,7 @@ namespace xe { namespace vfs { -Device::Device(const std::string& mount_path) : mount_path_(mount_path) {} +Device::Device(const std::string_view mount_path) : mount_path_(mount_path) {} Device::~Device() = default; } // namespace vfs diff --git a/src/xenia/vfs/device.h b/src/xenia/vfs/device.h index 310cc6426..de4ca9879 100644 --- a/src/xenia/vfs/device.h +++ b/src/xenia/vfs/device.h @@ -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,7 +22,7 @@ namespace vfs { class Device { public: - explicit Device(const std::string& path); + explicit Device(const std::string_view mount_path); virtual ~Device(); virtual bool Initialize() = 0; @@ -31,7 +31,7 @@ class Device { virtual bool is_read_only() const { return true; } virtual void Dump(StringBuffer* string_buffer) = 0; - virtual Entry* ResolvePath(const std::string& path) = 0; + virtual Entry* ResolvePath(const std::string_view path) = 0; virtual uint32_t total_allocation_units() const = 0; virtual uint32_t available_allocation_units() const = 0; diff --git a/src/xenia/vfs/devices/disc_image_device.cc b/src/xenia/vfs/devices/disc_image_device.cc index 025686ce0..d473eb10d 100644 --- a/src/xenia/vfs/devices/disc_image_device.cc +++ b/src/xenia/vfs/devices/disc_image_device.cc @@ -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. * ****************************************************************************** */ @@ -18,14 +18,14 @@ namespace vfs { const size_t kXESectorSize = 2048; -DiscImageDevice::DiscImageDevice(const std::string& mount_path, - const std::wstring& local_path) - : Device(mount_path), local_path_(local_path) {} +DiscImageDevice::DiscImageDevice(const std::string_view mount_path, + const std::filesystem::path& host_path) + : Device(mount_path), host_path_(host_path) {} DiscImageDevice::~DiscImageDevice() = default; bool DiscImageDevice::Initialize() { - mmap_ = MappedMemory::Open(local_path_, MappedMemory::Mode::kRead); + mmap_ = MappedMemory::Open(host_path_, MappedMemory::Mode::kRead); if (!mmap_) { XELOGE("Disc image could not be mapped"); return false; @@ -54,7 +54,7 @@ void DiscImageDevice::Dump(StringBuffer* string_buffer) { root_entry_->Dump(string_buffer, 0); } -Entry* DiscImageDevice::ResolvePath(const std::string& path) { +Entry* DiscImageDevice::ResolvePath(const std::string_view path) { // The filesystem will have stripped our prefix off already, so the path will // be in the form: // some\PATH.foo @@ -63,8 +63,7 @@ Entry* DiscImageDevice::ResolvePath(const std::string& path) { // Walk the path, one separator at a time. auto entry = root_entry_.get(); - auto path_parts = xe::split_path(path); - for (auto& part : path_parts) { + for (const auto& part : xe::utf8::split_path(path)) { entry = entry->GetChild(part); if (!entry) { // Not found. @@ -142,14 +141,15 @@ bool DiscImageDevice::ReadEntry(ParseState* state, const uint8_t* buffer, size_t length = xe::load(p + 8); uint8_t attributes = xe::load(p + 12); uint8_t name_length = xe::load(p + 13); - auto name = reinterpret_cast(p + 14); + auto name_buffer = reinterpret_cast(p + 14); if (node_l && !ReadEntry(state, buffer, node_l, parent)) { return false; } - auto entry = DiscImageEntry::Create( - this, parent, std::string(name, name_length), mmap_.get()); + auto name = std::string(name_buffer, name_length); + + auto entry = DiscImageEntry::Create(this, parent, name, mmap_.get()); entry->attributes_ = attributes | kFileAttributeReadOnly; entry->size_ = length; entry->allocation_size_ = xe::round_up(length, bytes_per_sector()); diff --git a/src/xenia/vfs/devices/disc_image_device.h b/src/xenia/vfs/devices/disc_image_device.h index 9b26a74a2..6b756b19a 100644 --- a/src/xenia/vfs/devices/disc_image_device.h +++ b/src/xenia/vfs/devices/disc_image_device.h @@ -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. * ****************************************************************************** */ @@ -23,13 +23,13 @@ class DiscImageEntry; class DiscImageDevice : public Device { public: - DiscImageDevice(const std::string& mount_path, - const std::wstring& local_path); + DiscImageDevice(const std::string_view mount_path, + const std::filesystem::path& host_path); ~DiscImageDevice() override; bool Initialize() override; void Dump(StringBuffer* string_buffer) override; - Entry* ResolvePath(const std::string& path) override; + Entry* ResolvePath(const std::string_view path) override; uint32_t total_allocation_units() const override { return uint32_t(mmap_->size() / sectors_per_allocation_unit() / @@ -48,7 +48,7 @@ class DiscImageDevice : public Device { kErrorDamagedFile = -31, }; - std::wstring local_path_; + std::filesystem::path host_path_; std::unique_ptr root_entry_; std::unique_ptr mmap_; diff --git a/src/xenia/vfs/devices/disc_image_entry.cc b/src/xenia/vfs/devices/disc_image_entry.cc index 5997c0875..e8450bd73 100644 --- a/src/xenia/vfs/devices/disc_image_entry.cc +++ b/src/xenia/vfs/devices/disc_image_entry.cc @@ -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. * ****************************************************************************** */ @@ -17,8 +17,8 @@ namespace xe { namespace vfs { -DiscImageEntry::DiscImageEntry(Device* device, Entry* parent, std::string path, - MappedMemory* mmap) +DiscImageEntry::DiscImageEntry(Device* device, Entry* parent, + const std::string_view path, MappedMemory* mmap) : Entry(device, parent, path), mmap_(mmap), data_offset_(0), @@ -26,13 +26,11 @@ DiscImageEntry::DiscImageEntry(Device* device, Entry* parent, std::string path, DiscImageEntry::~DiscImageEntry() = default; -std::unique_ptr DiscImageEntry::Create(Device* device, - Entry* parent, - std::string name, - MappedMemory* mmap) { - auto path = xe::join_paths(parent->path(), name); +std::unique_ptr DiscImageEntry::Create( + Device* device, Entry* parent, const std::string_view name, + MappedMemory* mmap) { + auto path = xe::utf8::join_guest_paths(parent->path(), name); auto entry = std::make_unique(device, parent, path, mmap); - return std::move(entry); } diff --git a/src/xenia/vfs/devices/disc_image_entry.h b/src/xenia/vfs/devices/disc_image_entry.h index 99de02706..32b7ddef6 100644 --- a/src/xenia/vfs/devices/disc_image_entry.h +++ b/src/xenia/vfs/devices/disc_image_entry.h @@ -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. * ****************************************************************************** */ @@ -24,12 +24,12 @@ class DiscImageDevice; class DiscImageEntry : public Entry { public: - DiscImageEntry(Device* device, Entry* parent, std::string path, + DiscImageEntry(Device* device, Entry* parent, const std::string_view path, MappedMemory* mmap); ~DiscImageEntry() override; static std::unique_ptr Create(Device* device, Entry* parent, - std::string name, + const std::string_view name, MappedMemory* mmap); MappedMemory* mmap() const { return mmap_; } diff --git a/src/xenia/vfs/devices/host_path_device.cc b/src/xenia/vfs/devices/host_path_device.cc index e61d2a6c0..4b7d22528 100644 --- a/src/xenia/vfs/devices/host_path_device.cc +++ b/src/xenia/vfs/devices/host_path_device.cc @@ -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. * ****************************************************************************** */ @@ -18,24 +18,25 @@ namespace xe { namespace vfs { -HostPathDevice::HostPathDevice(const std::string& mount_path, - const std::wstring& local_path, bool read_only) - : Device(mount_path), local_path_(local_path), read_only_(read_only) {} +HostPathDevice::HostPathDevice(const std::string_view mount_path, + const std::filesystem::path& host_path, + bool read_only) + : Device(mount_path), host_path_(host_path), read_only_(read_only) {} HostPathDevice::~HostPathDevice() = default; bool HostPathDevice::Initialize() { - if (!xe::filesystem::PathExists(local_path_)) { + if (!xe::filesystem::PathExists(host_path_)) { if (!read_only_) { // Create the path. - xe::filesystem::CreateFolder(local_path_); + xe::filesystem::CreateFolder(host_path_); } else { XELOGE("Host path does not exist"); return false; } } - auto root_entry = new HostPathEntry(this, nullptr, "", local_path_); + auto root_entry = new HostPathEntry(this, nullptr, "", host_path_); root_entry->attributes_ = kFileAttributeDirectory; root_entry_ = std::unique_ptr(root_entry); PopulateEntry(root_entry); @@ -48,7 +49,7 @@ void HostPathDevice::Dump(StringBuffer* string_buffer) { root_entry_->Dump(string_buffer, 0); } -Entry* HostPathDevice::ResolvePath(const std::string& path) { +Entry* HostPathDevice::ResolvePath(const std::string_view path) { // The filesystem will have stripped our prefix off already, so the path will // be in the form: // some\PATH.foo @@ -57,7 +58,7 @@ Entry* HostPathDevice::ResolvePath(const std::string& path) { // Walk the path, one separator at a time. auto entry = root_entry_.get(); - auto path_parts = xe::split_path(path); + auto path_parts = xe::utf8::split_path(path); for (auto& part : path_parts) { entry = entry->GetChild(part); if (!entry) { @@ -70,11 +71,10 @@ Entry* HostPathDevice::ResolvePath(const std::string& path) { } void HostPathDevice::PopulateEntry(HostPathEntry* parent_entry) { - auto child_infos = xe::filesystem::ListFiles(parent_entry->local_path()); + auto child_infos = xe::filesystem::ListFiles(parent_entry->host_path()); for (auto& child_info : child_infos) { auto child = HostPathEntry::Create( - this, parent_entry, - xe::join_paths(parent_entry->local_path(), child_info.name), + this, parent_entry, parent_entry->host_path() / child_info.name, child_info); parent_entry->children_.push_back(std::unique_ptr(child)); diff --git a/src/xenia/vfs/devices/host_path_device.h b/src/xenia/vfs/devices/host_path_device.h index d000a43a3..88a5578f1 100644 --- a/src/xenia/vfs/devices/host_path_device.h +++ b/src/xenia/vfs/devices/host_path_device.h @@ -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. * ****************************************************************************** */ @@ -21,13 +21,13 @@ class HostPathEntry; class HostPathDevice : public Device { public: - HostPathDevice(const std::string& mount_path, const std::wstring& local_path, - bool read_only); + HostPathDevice(const std::string_view mount_path, + const std::filesystem::path& host_path, bool read_only); ~HostPathDevice() override; bool Initialize() override; void Dump(StringBuffer* string_buffer) override; - Entry* ResolvePath(const std::string& path) override; + Entry* ResolvePath(const std::string_view path) override; bool is_read_only() const override { return read_only_; } @@ -39,7 +39,7 @@ class HostPathDevice : public Device { private: void PopulateEntry(HostPathEntry* parent_entry); - std::wstring local_path_; + std::filesystem::path host_path_; std::unique_ptr root_entry_; bool read_only_; }; diff --git a/src/xenia/vfs/devices/host_path_entry.cc b/src/xenia/vfs/devices/host_path_entry.cc index 10b19fb03..b349bcbe0 100644 --- a/src/xenia/vfs/devices/host_path_entry.cc +++ b/src/xenia/vfs/devices/host_path_entry.cc @@ -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. * ****************************************************************************** */ @@ -20,16 +20,18 @@ namespace xe { namespace vfs { -HostPathEntry::HostPathEntry(Device* device, Entry* parent, std::string path, - const std::wstring& local_path) - : Entry(device, parent, path), local_path_(local_path) {} +HostPathEntry::HostPathEntry(Device* device, Entry* parent, + const std::string_view path, + const std::filesystem::path& host_path) + : Entry(device, parent, path), host_path_(host_path) {} HostPathEntry::~HostPathEntry() = default; HostPathEntry* HostPathEntry::Create(Device* device, Entry* parent, - const std::wstring& full_path, + const std::filesystem::path& full_path, xe::filesystem::FileInfo file_info) { - auto path = xe::join_paths(parent->path(), xe::to_string(file_info.name)); + auto path = xe::utf8::join_guest_paths(parent->path(), + xe::path_to_utf8(file_info.name)); auto entry = new HostPathEntry(device, parent, path, full_path); entry->create_timestamp_ = file_info.create_timestamp; @@ -56,7 +58,7 @@ X_STATUS HostPathEntry::Open(uint32_t desired_access, File** out_file) { return X_STATUS_ACCESS_DENIED; } auto file_handle = - xe::filesystem::FileHandle::OpenExisting(local_path_, desired_access); + xe::filesystem::FileHandle::OpenExisting(host_path_, desired_access); if (!file_handle) { // TODO(benvanik): pick correct response. return X_STATUS_NO_SUCH_FILE; @@ -68,12 +70,12 @@ X_STATUS HostPathEntry::Open(uint32_t desired_access, File** out_file) { std::unique_ptr HostPathEntry::OpenMapped(MappedMemory::Mode mode, size_t offset, size_t length) { - return MappedMemory::Open(local_path_, mode, offset, length); + return MappedMemory::Open(host_path_, mode, offset, length); } -std::unique_ptr HostPathEntry::CreateEntryInternal(std::string name, - uint32_t attributes) { - auto full_path = xe::join_paths(local_path_, xe::to_wstring(name)); +std::unique_ptr HostPathEntry::CreateEntryInternal( + const std::string_view name, uint32_t attributes) { + auto full_path = host_path_ / xe::to_path(name); if (attributes & kFileAttributeDirectory) { if (!xe::filesystem::CreateFolder(full_path)) { return nullptr; @@ -94,7 +96,7 @@ std::unique_ptr HostPathEntry::CreateEntryInternal(std::string name, } bool HostPathEntry::DeleteEntryInternal(Entry* entry) { - auto full_path = xe::join_paths(local_path_, xe::to_wstring(entry->name())); + auto full_path = host_path_ / xe::to_path(entry->name()); if (entry->attributes() & kFileAttributeDirectory) { // Delete entire directory and contents. return xe::filesystem::DeleteFolder(full_path); @@ -106,7 +108,7 @@ bool HostPathEntry::DeleteEntryInternal(Entry* entry) { void HostPathEntry::update() { xe::filesystem::FileInfo file_info; - if (!xe::filesystem::GetInfo(local_path_, &file_info)) { + if (!xe::filesystem::GetInfo(host_path_, &file_info)) { return; } if (file_info.type == xe::filesystem::FileInfo::Type::kFile) { diff --git a/src/xenia/vfs/devices/host_path_entry.h b/src/xenia/vfs/devices/host_path_entry.h index a3d01e0e3..bb12b7a14 100644 --- a/src/xenia/vfs/devices/host_path_entry.h +++ b/src/xenia/vfs/devices/host_path_entry.h @@ -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,15 +22,15 @@ class HostPathDevice; class HostPathEntry : public Entry { public: - HostPathEntry(Device* device, Entry* parent, std::string path, - const std::wstring& local_path); + HostPathEntry(Device* device, Entry* parent, const std::string_view path, + const std::filesystem::path& host_path); ~HostPathEntry() override; static HostPathEntry* Create(Device* device, Entry* parent, - const std::wstring& full_path, + const std::filesystem::path& full_path, xe::filesystem::FileInfo file_info); - const std::wstring& local_path() { return local_path_; } + const std::filesystem::path& host_path() { return host_path_; } X_STATUS Open(uint32_t desired_access, File** out_file) override; @@ -43,11 +43,11 @@ class HostPathEntry : public Entry { private: friend class HostPathDevice; - std::unique_ptr CreateEntryInternal(std::string name, + std::unique_ptr CreateEntryInternal(const std::string_view name, uint32_t attributes) override; bool DeleteEntryInternal(Entry* entry) override; - std::wstring local_path_; + std::filesystem::path host_path_; }; } // namespace vfs diff --git a/src/xenia/vfs/devices/stfs_container_device.cc b/src/xenia/vfs/devices/stfs_container_device.cc index e4fb3bd94..92bd765b7 100644 --- a/src/xenia/vfs/devices/stfs_container_device.cc +++ b/src/xenia/vfs/devices/stfs_container_device.cc @@ -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. * ****************************************************************************** */ @@ -53,22 +53,23 @@ uint64_t decode_fat_timestamp(uint32_t date, uint32_t time) { return (timet + 11644473600LL) * 10000000; } -StfsContainerDevice::StfsContainerDevice(const std::string& mount_path, - const std::wstring& local_path) - : Device(mount_path), local_path_(local_path) {} +StfsContainerDevice::StfsContainerDevice(const std::string_view mount_path, + const std::filesystem::path& host_path) + : Device(mount_path), host_path_(host_path) {} StfsContainerDevice::~StfsContainerDevice() = default; bool StfsContainerDevice::Initialize() { // Resolve a valid STFS file if a directory is given. - if (filesystem::IsFolder(local_path_) && !ResolveFromFolder(local_path_)) { - XELOGE("Could not resolve an STFS container given path %ls", - local_path_.c_str()); + if (filesystem::IsFolder(host_path_) && !ResolveFromFolder(host_path_)) { + XELOGE("Could not resolve an STFS container given path %s", + xe::path_to_utf8(host_path_).c_str()); return false; } - if (!filesystem::PathExists(local_path_)) { - XELOGE("Path to STFS container does not exist: %ls", local_path_.c_str()); + if (!filesystem::PathExists(host_path_)) { + XELOGE("Path to STFS container does not exist: %s", + xe::path_to_utf8(host_path_).c_str()); return false; } @@ -93,8 +94,8 @@ bool StfsContainerDevice::Initialize() { StfsContainerDevice::Error StfsContainerDevice::MapFiles() { // Map the file containing the STFS Header and read it. - XELOGI("Mapping STFS Header file: %ls", local_path_.c_str()); - auto header_map = MappedMemory::Open(local_path_, MappedMemory::Mode::kRead); + XELOGI("Mapping STFS Header file: %s", xe::path_to_utf8(host_path_).c_str()); + auto header_map = MappedMemory::Open(host_path_, MappedMemory::Mode::kRead); if (!header_map) { XELOGE("Error mapping STFS Header file."); return Error::kErrorReadError; @@ -118,10 +119,10 @@ StfsContainerDevice::Error StfsContainerDevice::MapFiles() { // If the STFS package is multi-file, it is an SVOD system. We need to map // the files in the .data folder and can discard the header. - auto data_fragment_path = local_path_ + L".data"; + auto data_fragment_path = host_path_ / ".data"; if (!filesystem::PathExists(data_fragment_path)) { - XELOGE("STFS container is multi-file, but path %ls does not exist.", - xe::to_string(data_fragment_path).c_str()); + XELOGE("STFS container is multi-file, but path %s does not exist.", + xe::path_to_utf8(data_fragment_path).c_str()); return Error::kErrorFileMismatch; } @@ -140,10 +141,10 @@ StfsContainerDevice::Error StfsContainerDevice::MapFiles() { for (size_t i = 0; i < fragment_files.size(); i++) { auto file = fragment_files.at(i); - auto path = xe::join_paths(file.path, file.name); + auto path = file.path / file.name; auto data = MappedMemory::Open(path, MappedMemory::Mode::kRead); if (!data) { - XELOGI("Failed to map SVOD file %ls.", path.c_str()); + XELOGI("Failed to map SVOD file %s.", xe::path_to_utf8(path).c_str()); mmap_.clear(); return Error::kErrorReadError; } @@ -158,7 +159,7 @@ void StfsContainerDevice::Dump(StringBuffer* string_buffer) { root_entry_->Dump(string_buffer, 0); } -Entry* StfsContainerDevice::ResolvePath(const std::string& path) { +Entry* StfsContainerDevice::ResolvePath(const std::string_view path) { // The filesystem will have stripped our prefix off already, so the path will // be in the form: // some\PATH.foo @@ -167,7 +168,7 @@ Entry* StfsContainerDevice::ResolvePath(const std::string& path) { // Walk the path, one separator at a time. auto entry = root_entry_.get(); - auto path_parts = xe::split_path(path); + auto path_parts = xe::utf8::split_path(path); for (auto& part : path_parts) { entry = entry->GetChild(part); if (!entry) { @@ -339,8 +340,8 @@ StfsContainerDevice::Error StfsContainerDevice::ReadEntrySVOD( uint32_t length = xe::load(data + 0x08); uint8_t attributes = xe::load(data + 0x0C); uint8_t name_length = xe::load(data + 0x0D); - auto name = reinterpret_cast(data + 0x0E); - auto name_str = std::string(name, name_length); + auto name_buffer = reinterpret_cast(data + 0x0E); + auto name = std::string(name_buffer, name_length); // Read the left node if (node_l) { @@ -358,7 +359,7 @@ StfsContainerDevice::Error StfsContainerDevice::ReadEntrySVOD( // NOTE: SVOD entries don't have timestamps for individual files, which can // cause issues when decrypting games. Using the root entry's timestamp // solves this issues. - auto entry = StfsContainerEntry::Create(this, parent, name_str, &mmap_); + auto entry = StfsContainerEntry::Create(this, parent, name, &mmap_); if (attributes & kFileAttributeDirectory) { // Entry is a directory entry->attributes_ = kFileAttributeDirectory | kFileAttributeReadOnly; @@ -507,12 +508,12 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() { for (size_t n = 0; n < volume_descriptor.file_table_block_count; n++) { const uint8_t* p = data + BlockToOffsetSTFS(table_block_index); for (size_t m = 0; m < 0x1000 / 0x40; m++) { - const uint8_t* filename = p; // 0x28b - if (filename[0] == 0) { + const uint8_t* name_buffer = p; // 0x28b + if (name_buffer[0] == 0) { // Done. break; } - uint8_t filename_length_flags = xe::load_and_swap(p + 0x28); + uint8_t name_length_flags = xe::load_and_swap(p + 0x28); // TODO(benvanik): use for allocation_size_? // uint32_t allocated_block_count = load_uint24_le(p + 0x29); uint32_t start_block_index = load_uint24_le(p + 0x2F); @@ -533,13 +534,12 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() { parent_entry = all_entries[path_indicator]; } - std::string name_str(reinterpret_cast(filename), - filename_length_flags & 0x3F); - auto entry = - StfsContainerEntry::Create(this, parent_entry, name_str, &mmap_); + std::string name(reinterpret_cast(name_buffer), + name_length_flags & 0x3F); + auto entry = StfsContainerEntry::Create(this, parent_entry, name, &mmap_); // bit 0x40 = consecutive blocks (not fragmented?) - if (filename_length_flags & 0x80) { + if (name_length_flags & 0x80) { entry->attributes_ = kFileAttributeDirectory; } else { entry->attributes_ = kFileAttributeNormal | kFileAttributeReadOnly; @@ -739,12 +739,12 @@ bool StfsHeader::Read(const uint8_t* p) { return true; } -bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) { +bool StfsContainerDevice::ResolveFromFolder(const std::filesystem::path& path) { // Scan through folders until a file with magic is found std::queue queue; filesystem::FileInfo folder; - filesystem::GetInfo(local_path_, &folder); + filesystem::GetInfo(host_path_, &folder); queue.push(folder); while (!queue.empty()) { @@ -752,25 +752,25 @@ bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) { queue.pop(); if (current_file.type == filesystem::FileInfo::Type::kDirectory) { - auto path = xe::join_paths(current_file.path, current_file.name); + auto path = current_file.path / current_file.name; auto child_files = filesystem::ListFiles(path); for (auto file : child_files) { queue.push(file); } } else { // Try to read the file's magic - auto path = xe::join_paths(current_file.path, current_file.name); + auto path = current_file.path / current_file.name; auto map = MappedMemory::Open(path, MappedMemory::Mode::kRead, 0, 4); if (map && ReadPackageType(map->data(), map->size(), nullptr) == Error::kSuccess) { - local_path_ = xe::join_paths(current_file.path, current_file.name); - XELOGI("STFS Package found: %ls", local_path_.c_str()); + host_path_ = current_file.path / current_file.name; + XELOGI("STFS Package found: %s", xe::path_to_utf8(host_path_).c_str()); return true; } } } - if (local_path_ == path) { + if (host_path_ == path) { // Could not find a suitable container file return false; } diff --git a/src/xenia/vfs/devices/stfs_container_device.h b/src/xenia/vfs/devices/stfs_container_device.h index 624393e01..9d0bba0d8 100644 --- a/src/xenia/vfs/devices/stfs_container_device.h +++ b/src/xenia/vfs/devices/stfs_container_device.h @@ -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. * ****************************************************************************** */ @@ -144,10 +144,10 @@ class StfsHeader { uint64_t data_file_combined_size; StfsDescriptorType descriptor_type; uint8_t device_id[0x14]; - wchar_t display_names[0x900 / 2]; - wchar_t display_descs[0x900 / 2]; - wchar_t publisher_name[0x80 / 2]; - wchar_t title_name[0x80 / 2]; + char16_t display_names[0x900 / 2]; + char16_t display_descs[0x900 / 2]; + char16_t publisher_name[0x80 / 2]; + char16_t title_name[0x80 / 2]; uint8_t transfer_flags; uint32_t thumbnail_image_size; uint32_t title_thumbnail_image_size; @@ -159,19 +159,19 @@ class StfsHeader { uint8_t season_id[0x10]; int16_t season_number; int16_t episode_number; - wchar_t additonal_display_names[0x300 / 2]; - wchar_t additional_display_descriptions[0x300 / 2]; + char16_t additonal_display_names[0x300 / 2]; + char16_t additional_display_descriptions[0x300 / 2]; }; class StfsContainerDevice : public Device { public: - StfsContainerDevice(const std::string& mount_path, - const std::wstring& local_path); + StfsContainerDevice(const std::string_view mount_path, + const std::filesystem::path& host_path); ~StfsContainerDevice() override; bool Initialize() override; void Dump(StringBuffer* string_buffer) override; - Entry* ResolvePath(const std::string& path) override; + Entry* ResolvePath(const std::string_view path) override; uint32_t total_allocation_units() const override { return uint32_t(mmap_total_size_ / sectors_per_allocation_unit() / @@ -197,7 +197,7 @@ class StfsContainerDevice : public Device { const uint32_t kSTFSHashSpacing = 170; - bool ResolveFromFolder(const std::wstring& path); + bool ResolveFromFolder(const std::filesystem::path& path); Error MapFiles(); static Error ReadPackageType(const uint8_t* map_ptr, size_t map_size, @@ -215,7 +215,7 @@ class StfsContainerDevice : public Device { BlockHash GetBlockHash(const uint8_t* map_ptr, uint32_t block_index, uint32_t table_offset); - std::wstring local_path_; + std::filesystem::path host_path_; std::map> mmap_; size_t mmap_total_size_; diff --git a/src/xenia/vfs/devices/stfs_container_entry.cc b/src/xenia/vfs/devices/stfs_container_entry.cc index 63c1a4df1..023af8fec 100644 --- a/src/xenia/vfs/devices/stfs_container_entry.cc +++ b/src/xenia/vfs/devices/stfs_container_entry.cc @@ -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. * ****************************************************************************** */ @@ -17,7 +17,7 @@ namespace xe { namespace vfs { StfsContainerEntry::StfsContainerEntry(Device* device, Entry* parent, - std::string path, + const std::string_view path, MultifileMemoryMap* mmap) : Entry(device, parent, path), mmap_(mmap), @@ -27,8 +27,9 @@ StfsContainerEntry::StfsContainerEntry(Device* device, Entry* parent, StfsContainerEntry::~StfsContainerEntry() = default; std::unique_ptr StfsContainerEntry::Create( - Device* device, Entry* parent, std::string name, MultifileMemoryMap* mmap) { - auto path = xe::join_paths(parent->path(), name); + Device* device, Entry* parent, const std::string_view name, + MultifileMemoryMap* mmap) { + auto path = xe::utf8::join_guest_paths(parent->path(), name); auto entry = std::make_unique(device, parent, path, mmap); return std::move(entry); diff --git a/src/xenia/vfs/devices/stfs_container_entry.h b/src/xenia/vfs/devices/stfs_container_entry.h index 4ffe13423..b8c4ed818 100644 --- a/src/xenia/vfs/devices/stfs_container_entry.h +++ b/src/xenia/vfs/devices/stfs_container_entry.h @@ -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. * ****************************************************************************** */ @@ -27,13 +27,13 @@ class StfsContainerDevice; class StfsContainerEntry : public Entry { public: - StfsContainerEntry(Device* device, Entry* parent, std::string path, + StfsContainerEntry(Device* device, Entry* parent, const std::string_view path, MultifileMemoryMap* mmap); ~StfsContainerEntry() override; static std::unique_ptr Create(Device* device, Entry* parent, - std::string name, + const std::string_view name, MultifileMemoryMap* mmap); MultifileMemoryMap* mmap() const { return mmap_; } diff --git a/src/xenia/vfs/entry.cc b/src/xenia/vfs/entry.cc index d07795520..1ce80b9bf 100644 --- a/src/xenia/vfs/entry.cc +++ b/src/xenia/vfs/entry.cc @@ -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. * ****************************************************************************** */ @@ -16,7 +16,7 @@ namespace xe { namespace vfs { -Entry::Entry(Device* device, Entry* parent, const std::string& path) +Entry::Entry(Device* device, Entry* parent, const std::string_view path) : device_(device), parent_(parent), path_(path), @@ -27,8 +27,8 @@ Entry::Entry(Device* device, Entry* parent, const std::string& path) access_timestamp_(0), write_timestamp_(0) { assert_not_null(device); - absolute_path_ = xe::join_paths(device->mount_path(), path); - name_ = xe::find_name_from_path(path); + absolute_path_ = xe::utf8::join_guest_paths(device->mount_path(), path); + name_ = xe::utf8::find_name_from_guest_path(path); } Entry::~Entry() = default; @@ -46,15 +46,16 @@ void Entry::Dump(xe::StringBuffer* string_buffer, int indent) { bool Entry::is_read_only() const { return device_->is_read_only(); } -Entry* Entry::GetChild(std::string name) { +Entry* Entry::GetChild(const std::string_view name) { auto global_lock = global_critical_region_.Acquire(); - // TODO(benvanik): a faster search - for (auto& child : children_) { - if (strcasecmp(child->name().c_str(), name.c_str()) == 0) { - return child.get(); - } + auto it = std::find_if(children_.cbegin(), children_.cend(), + [&](const auto& child) { + return xe::utf8::equal_case(child->name(), name); + }); + if (it == children_.cend()) { + return nullptr; } - return nullptr; + return (*it).get(); } Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine, @@ -70,7 +71,7 @@ Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine, return nullptr; } -Entry* Entry::CreateEntry(std::string name, uint32_t attributes) { +Entry* Entry::CreateEntry(const std::string_view name, uint32_t attributes) { auto global_lock = global_critical_region_.Acquire(); if (is_read_only()) { return nullptr; diff --git a/src/xenia/vfs/entry.h b/src/xenia/vfs/entry.h index bdbf7de3a..e5325f115 100644 --- a/src/xenia/vfs/entry.h +++ b/src/xenia/vfs/entry.h @@ -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 Entry { bool is_read_only() const; - Entry* GetChild(std::string name); + Entry* GetChild(const std::string_view name); const std::vector>& children() const { return children_; @@ -105,7 +105,7 @@ class Entry { Entry* IterateChildren(const xe::filesystem::WildcardEngine& engine, size_t* current_index); - Entry* CreateEntry(std::string name, uint32_t attributes); + Entry* CreateEntry(const std::string_view name, uint32_t attributes); bool Delete(Entry* entry); bool Delete(); void Touch(); @@ -123,10 +123,10 @@ class Entry { virtual void update() { return; } protected: - Entry(Device* device, Entry* parent, const std::string& path); + Entry(Device* device, Entry* parent, const std::string_view path); - virtual std::unique_ptr CreateEntryInternal(std::string name, - uint32_t attributes) { + virtual std::unique_ptr CreateEntryInternal( + const std::string_view name, uint32_t attributes) { return nullptr; } virtual bool DeleteEntryInternal(Entry* entry) { return false; } diff --git a/src/xenia/vfs/premake5.lua b/src/xenia/vfs/premake5.lua index fc8b4a545..94b666dce 100644 --- a/src/xenia/vfs/premake5.lua +++ b/src/xenia/vfs/premake5.lua @@ -19,6 +19,7 @@ project("xenia-vfs-dump") kind("ConsoleApp") language("C++") links({ + "fmt", "xenia-base", "xenia-vfs", }) diff --git a/src/xenia/vfs/vfs_dump.cc b/src/xenia/vfs/vfs_dump.cc index b46bcca9b..4f7b268c2 100644 --- a/src/xenia/vfs/vfs_dump.cc +++ b/src/xenia/vfs/vfs_dump.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 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,23 +21,23 @@ namespace xe { namespace vfs { -DEFINE_transient_string(source, "", "Specifies the file to dump from.", - "General"); +DEFINE_transient_path(source, "", "Specifies the file to dump from.", + "General"); -DEFINE_transient_string(dump_path, "", - "Specifies the directory to dump files to.", "General"); +DEFINE_transient_path(dump_path, "", + "Specifies the directory to dump files to.", "General"); -int vfs_dump_main(const std::vector& args) { - if (args.size() <= 2) { - XELOGE("Usage: %S [source] [dump_path]", args[0].c_str()); +int vfs_dump_main(const std::vector& args) { + if (cvars::source.empty() || cvars::dump_path.empty()) { + XELOGE("Usage: %s [source] [dump_path]", xe::path_to_utf8(args[0]).c_str()); return 1; } - std::wstring base_path = args[2]; + std::filesystem::path base_path = cvars::dump_path; std::unique_ptr device; // TODO: Flags specifying the type of device. - device = std::make_unique("", args[1]); + device = std::make_unique("", cvars::source); if (!device->Initialize()) { XELOGE("Failed to initialize device"); return 1; @@ -60,9 +60,9 @@ int vfs_dump_main(const std::vector& args) { } XELOGI("%s", entry->path().c_str()); - auto dest_name = xe::join_paths(base_path, xe::to_wstring(entry->path())); + auto dest_name = base_path / xe::to_path(entry->path()); if (entry->attributes() & kFileAttributeDirectory) { - xe::filesystem::CreateFolder(dest_name + L"\\"); + xe::filesystem::CreateFolder(dest_name); continue; } @@ -113,5 +113,5 @@ int vfs_dump_main(const std::vector& args) { } // namespace vfs } // namespace xe -DEFINE_ENTRY_POINT(L"xenia-vfs-dump", xe::vfs::vfs_dump_main, +DEFINE_ENTRY_POINT("xenia-vfs-dump", xe::vfs::vfs_dump_main, "[source] [dump_path]", "source", "dump_path"); diff --git a/src/xenia/vfs/virtual_file_system.cc b/src/xenia/vfs/virtual_file_system.cc index aae42a1f0..f625d90e1 100644 --- a/src/xenia/vfs/virtual_file_system.cc +++ b/src/xenia/vfs/virtual_file_system.cc @@ -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. * ****************************************************************************** */ @@ -32,7 +32,7 @@ bool VirtualFileSystem::RegisterDevice(std::unique_ptr device) { return true; } -bool VirtualFileSystem::UnregisterDevice(const std::string& path) { +bool VirtualFileSystem::UnregisterDevice(const std::string_view path) { auto global_lock = global_critical_region_.Acquire(); for (auto it = devices_.begin(); it != devices_.end(); ++it) { if ((*it)->mount_path() == path) { @@ -44,18 +44,21 @@ bool VirtualFileSystem::UnregisterDevice(const std::string& path) { return false; } -bool VirtualFileSystem::RegisterSymbolicLink(const std::string& path, - const std::string& target) { +bool VirtualFileSystem::RegisterSymbolicLink(const std::string_view path, + const std::string_view target) { auto global_lock = global_critical_region_.Acquire(); - symlinks_.insert({path, target}); - XELOGD("Registered symbolic link: %s => %s", path.c_str(), target.c_str()); + symlinks_.insert({std::string(path), std::string(target)}); + XELOGD("Registered symbolic link: %s => %s", std::string(path).c_str(), + std::string(target).c_str()); return true; } -bool VirtualFileSystem::UnregisterSymbolicLink(const std::string& path) { +bool VirtualFileSystem::UnregisterSymbolicLink(const std::string_view path) { auto global_lock = global_critical_region_.Acquire(); - auto it = symlinks_.find(path); + auto it = std::find_if( + symlinks_.cbegin(), symlinks_.cend(), + [&](const auto& s) { return xe::utf8::equal_case(path, s.first); }); if (it == symlinks_.end()) { return false; } @@ -66,12 +69,11 @@ bool VirtualFileSystem::UnregisterSymbolicLink(const std::string& path) { return true; } -bool VirtualFileSystem::FindSymbolicLink(const std::string& path, +bool VirtualFileSystem::FindSymbolicLink(const std::string_view path, std::string& target) { - auto it = - std::find_if(symlinks_.cbegin(), symlinks_.cend(), [&](const auto& s) { - return xe::find_first_of_case(path, s.first) == 0; - }); + auto it = std::find_if( + symlinks_.cbegin(), symlinks_.cend(), + [&](const auto& s) { return xe::utf8::starts_with_case(path, s.first); }); if (it == symlinks_.cend()) { return false; } @@ -79,14 +81,14 @@ bool VirtualFileSystem::FindSymbolicLink(const std::string& path, return true; } -bool VirtualFileSystem::ResolveSymbolicLink(const std::string& path, +bool VirtualFileSystem::ResolveSymbolicLink(const std::string_view path, std::string& result) { result = path; bool was_resolved = false; while (true) { auto it = std::find_if(symlinks_.cbegin(), symlinks_.cend(), [&](const auto& s) { - return xe::find_first_of_case(result, s.first) == 0; + return xe::utf8::starts_with_case(result, s.first); }); if (it == symlinks_.cend()) { break; @@ -100,11 +102,11 @@ bool VirtualFileSystem::ResolveSymbolicLink(const std::string& path, return was_resolved; } -Entry* VirtualFileSystem::ResolvePath(const std::string& path) { +Entry* VirtualFileSystem::ResolvePath(const std::string_view path) { auto global_lock = global_critical_region_.Acquire(); // Resolve relative paths - std::string normalized_path(xe::filesystem::CanonicalizePath(path)); + auto normalized_path(xe::utf8::canonicalize_guest_path(path)); // Resolve symlinks. std::string resolved_path; @@ -115,10 +117,11 @@ Entry* VirtualFileSystem::ResolvePath(const std::string& path) { // Find the device. auto it = std::find_if(devices_.cbegin(), devices_.cend(), [&](const auto& d) { - return xe::find_first_of_case(normalized_path, d->mount_path()) == 0; + return xe::utf8::starts_with(normalized_path, d->mount_path()); }); if (it == devices_.cend()) { - XELOGE("ResolvePath(%s) failed - device not found", path.c_str()); + XELOGE("ResolvePath(%s) failed - device not found", + std::string(path).c_str()); return nullptr; } @@ -127,26 +130,26 @@ Entry* VirtualFileSystem::ResolvePath(const std::string& path) { return device->ResolvePath(relative_path); } -Entry* VirtualFileSystem::ResolveBasePath(const std::string& path) { - auto base_path = xe::find_base_path(path); +Entry* VirtualFileSystem::ResolveBasePath(const std::string_view path) { + auto base_path = xe::utf8::find_base_guest_path(path); return ResolvePath(base_path); } -Entry* VirtualFileSystem::CreatePath(const std::string& path, +Entry* VirtualFileSystem::CreatePath(const std::string_view path, uint32_t attributes) { // Create all required directories recursively. - auto path_parts = xe::split_path(path); + auto path_parts = xe::utf8::split_path(path); if (path_parts.empty()) { return nullptr; } - auto partial_path = path_parts[0]; + auto partial_path = std::string(path_parts[0]); auto partial_entry = ResolvePath(partial_path); if (!partial_entry) { return nullptr; } auto parent_entry = partial_entry; for (size_t i = 1; i < path_parts.size() - 1; ++i) { - partial_path = xe::join_paths(partial_path, path_parts[i]); + partial_path = xe::utf8::join_guest_paths(partial_path, path_parts[i]); auto child_entry = ResolvePath(partial_path); if (!child_entry) { child_entry = @@ -161,7 +164,7 @@ Entry* VirtualFileSystem::CreatePath(const std::string& path, attributes); } -bool VirtualFileSystem::DeletePath(const std::string& path) { +bool VirtualFileSystem::DeletePath(const std::string_view path) { auto entry = ResolvePath(path); if (!entry) { return false; @@ -174,7 +177,7 @@ bool VirtualFileSystem::DeletePath(const std::string& path) { return parent->Delete(entry); } -X_STATUS VirtualFileSystem::OpenFile(const std::string& path, +X_STATUS VirtualFileSystem::OpenFile(const std::string_view path, FileDisposition creation_disposition, uint32_t desired_access, bool is_directory, File** out_file, FileAction* out_action) { @@ -196,14 +199,14 @@ X_STATUS VirtualFileSystem::OpenFile(const std::string& path, // If no device or parent, fail. Entry* parent_entry = nullptr; Entry* entry = nullptr; - if (!xe::find_base_path(path).empty()) { + if (!xe::utf8::find_base_guest_path(path).empty()) { parent_entry = ResolveBasePath(path); if (!parent_entry) { *out_action = FileAction::kDoesNotExist; return X_STATUS_NO_SUCH_FILE; } - auto file_name = xe::find_name_from_path(path); + auto file_name = xe::utf8::find_name_from_guest_path(path); entry = parent_entry->GetChild(file_name); } else { entry = ResolvePath(path); diff --git a/src/xenia/vfs/virtual_file_system.h b/src/xenia/vfs/virtual_file_system.h index 523299ad7..9f52f9d6f 100644 --- a/src/xenia/vfs/virtual_file_system.h +++ b/src/xenia/vfs/virtual_file_system.h @@ -29,19 +29,20 @@ class VirtualFileSystem { ~VirtualFileSystem(); bool RegisterDevice(std::unique_ptr device); - bool UnregisterDevice(const std::string& path); + bool UnregisterDevice(const std::string_view path); - bool RegisterSymbolicLink(const std::string& path, const std::string& target); - bool UnregisterSymbolicLink(const std::string& path); - bool FindSymbolicLink(const std::string& path, std::string& target); + bool RegisterSymbolicLink(const std::string_view path, + const std::string_view target); + bool UnregisterSymbolicLink(const std::string_view path); + bool FindSymbolicLink(const std::string_view path, std::string& target); - Entry* ResolvePath(const std::string& path); - Entry* ResolveBasePath(const std::string& path); + Entry* ResolvePath(const std::string_view path); + Entry* ResolveBasePath(const std::string_view path); - Entry* CreatePath(const std::string& path, uint32_t attributes); - bool DeletePath(const std::string& path); + Entry* CreatePath(const std::string_view path, uint32_t attributes); + bool DeletePath(const std::string_view path); - X_STATUS OpenFile(const std::string& path, + X_STATUS OpenFile(const std::string_view path, FileDisposition creation_disposition, uint32_t desired_access, bool is_directory, File** out_file, FileAction* out_action); @@ -51,7 +52,7 @@ class VirtualFileSystem { std::vector> devices_; std::unordered_map symlinks_; - bool ResolveSymbolicLink(const std::string& path, std::string& result); + bool ResolveSymbolicLink(const std::string_view path, std::string& result); }; } // namespace vfs diff --git a/third_party/mspack/logging.cc b/third_party/mspack/logging.cc index ae70478d0..0cc4009cd 100644 --- a/third_party/mspack/logging.cc +++ b/third_party/mspack/logging.cc @@ -1,5 +1,7 @@ #include "xenia/base/logging.h" +#include + extern "C" void xenia_log(const char* fmt, ...) { char buffer[128]; va_list args; diff --git a/tools/ppc-table-gen b/tools/ppc-table-gen index e81194b14..2375b0217 100644 --- a/tools/ppc-table-gen +++ b/tools/ppc-table-gen @@ -253,25 +253,25 @@ def generate_token_append(i, token): elif token == 'AA': return 'if (d.%s.AA()) str->Append(\'a\');' % (i.o_form) elif token in ['RA', 'RA0', 'RB', 'RC', 'RT', 'RS', 'RD']: - return 'str->AppendFormat("r%%d", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("r{}", d.%s.%s());' % (i.o_form, token) elif token in ['FA', 'FB', 'FC', 'FT', 'FS', 'FD']: - return 'str->AppendFormat("fr%%d", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("fr{}", d.%s.%s());' % (i.o_form, token) elif token in ['VA', 'VB', 'VC', 'VT', 'VS', 'VD']: - return 'str->AppendFormat("vr%%d", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("vr{}", d.%s.%s());' % (i.o_form, token) elif token in ['CRFD', 'CRFS']: - return 'str->AppendFormat("crf%%d", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("crf{}", d.%s.%s());' % (i.o_form, token) elif token in ['CRBA', 'CRBB', 'CRBD']: - return 'str->AppendFormat("crb%%d", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("crb{}", d.%s.%s());' % (i.o_form, token) elif token in ['BO', 'BI', 'TO', 'SPR', 'TBR', 'L', 'FM', 'MB', 'ME', 'SH', 'IMM', 'z']: - return 'str->AppendFormat("%%d", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("{}", d.%s.%s());' % (i.o_form, token) elif token == 'UIMM': - return 'str->AppendFormat("0x%%X", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("0x{:X}", d.%s.%s());' % (i.o_form, token) elif token in ['d', 'ds', 'SIMM']: - return 'str->AppendFormat(d.%s.%s() < 0 ? "-0x%%X" : "0x%%X", std::abs(d.%s.%s()));' % (i.o_form, token, i.o_form, token) + return 'str->AppendFormat(d.%s.%s() < 0 ? "-0x{:X}" : "0x{:X}", std::abs(d.%s.%s()));' % (i.o_form, token, i.o_form, token) elif token == 'ADDR': - return 'str->AppendFormat("0x%%X", d.%s.%s());' % (i.o_form, token) + return 'str->AppendFormat("0x{:X}", d.%s.%s());' % (i.o_form, token) elif token == 'LEV': - return 'if (d.%s.%s()) str->AppendFormat("%%d", d.%s.%s());' % (i.o_form, token, i.o_form, token) + return 'if (d.%s.%s()) str->AppendFormat("{}", d.%s.%s());' % (i.o_form, token, i.o_form, token) return 'str->AppendFormat("(UNHANDLED %s)");' % token