<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 <NAME>. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/app/emulator_window.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h"
#include "xenia/base/logging.h"
#include "xenia/base/main.h"
#include "xenia/base/profiling.h"
#include "xenia/base/threading.h"
#include "xenia/debug/ui/debug_window.h"
#include "xenia/emulator.h"
#include "xenia/ui/file_picker.h"
#include "xenia/vfs/devices/host_path_device.h"

// Available audio systems:
#include "xenia/apu/nop/nop_audio_system.h"
#if XE_PLATFORM_WIN32
#include "xenia/apu/xaudio2/xaudio2_audio_system.h"
#endif  // XE_PLATFORM_WIN32

// Available graphics systems:
#include "xenia/gpu/null/null_graphics_system.h"
#include "xenia/gpu/vulkan/vulkan_graphics_system.h"

// Available input drivers:
#include "xenia/hid/nop/nop_hid.h"
#if XE_PLATFORM_WIN32
#include "xenia/hid/winkey/winkey_hid.h"
#include "xenia/hid/xinput/xinput_hid.h"
#endif  // XE_PLATFORM_WIN32

#include "third_party/xbyak/xbyak/xbyak_util.h"

DEFINE_string(apu, "any", "Audio system. Use: [any, nop, xaudio2]", "General");
DEFINE_string(gpu, "any", "Graphics system. Use: [any, vulkan, null]",
              "General");
DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]",
              "General");

DEFINE_bool(fullscreen, false, "Toggles fullscreen", "General");

DEFINE_string(content_root, "", "Root path for content (save/etc) storage.",
              "General");

DEFINE_bool(mount_scratch, false, "Enable scratch mount", "General");
DEFINE_bool(mount_cache, false, "Enable cache mount", "General");

CmdVar(target, "", "Specifies the target .xex or .iso to execute.");
DECLARE_bool(debug);

namespace xe {
namespace app {

std::unique_ptr<apu::AudioSystem> CreateAudioSystem(cpu::Processor* processor) {
  if (cvars::apu.compare("nop") == 0) {
    return apu::nop::NopAudioSystem::Create(processor);
#if XE_PLATFORM_WIN32
  } else if (cvars::apu.compare("xaudio2") == 0) {
    return apu::xaudio2::XAudio2AudioSystem::Create(processor);
#endif  // XE_PLATFORM_WIN32
  } else {
    // Create best available.
    std::unique_ptr<apu::AudioSystem> best;

#if XE_PLATFORM_WIN32
    best = apu::xaudio2::XAudio2AudioSystem::Create(processor);
    if (best) {
      return best;
    }
#endif  // XE_PLATFORM_WIN32

    // Fallback to nop.
    return apu::nop::NopAudioSystem::Create(processor);
  }
}

std::unique_ptr<gpu::GraphicsSystem> CreateGraphicsSystem() {
  if (cvars::gpu.compare("vulkan") == 0) {
    return std::unique_ptr<gpu::GraphicsSystem>(
        new xe::gpu::vulkan::VulkanGraphicsSystem());
  } else if (cvars::gpu.compare("null") == 0) {
    return std::unique_ptr<gpu::GraphicsSystem>(
        new xe::gpu::null::NullGraphicsSystem());
  } else {
    // Create best available.
    std::unique_ptr<gpu::GraphicsSystem> best;

    best = std::unique_ptr<gpu::GraphicsSystem>(
        new xe::gpu::vulkan::VulkanGraphicsSystem());
    if (best) {
      return best;
    }

    // Nothing!
    return nullptr;
  }
}

std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
    ui::Window* window) {
  std::vector<std::unique_ptr<hid::InputDriver>> drivers;
  if (cvars::hid.compare("nop") == 0) {
    drivers.emplace_back(xe::hid::nop::Create(window));
#if XE_PLATFORM_WIN32
  } else if (cvars::hid.compare("winkey") == 0) {
    drivers.emplace_back(xe::hid::winkey::Create(window));
  } else if (cvars::hid.compare("xinput") == 0) {
    drivers.emplace_back(xe::hid::xinput::Create(window));
#endif  // XE_PLATFORM_WIN32
  } else {
#if XE_PLATFORM_WIN32
    auto xinput_driver = xe::hid::xinput::Create(window);
    if (xinput_driver) {
      drivers.emplace_back(std::move(xinput_driver));
    }
    auto winkey_driver = xe::hid::winkey::Create(window);
    if (winkey_driver) {
      drivers.emplace_back(std::move(winkey_driver));
    }
#endif  // XE_PLATFORM_WIN32
  }
  for (auto it = drivers.begin(); it != drivers.end();) {
    if (XFAILED((*it)->Setup())) {
      it = drivers.erase(it);
    } else {
      ++it;
    }
  }
  if (drivers.empty()) {
    // Fallback to nop if none created.
    drivers.emplace_back(xe::hid::nop::Create(window));
  }
  return drivers;
}

int xenia_main(const std::vector<std::wstring>& args) {
  Profiler::Initialize();
  Profiler::ThreadEnter("main");

  // Figure out where content should go.
  std::wstring content_root = xe::to_wstring(cvars::content_root);

  if (content_root.empty()) {
    auto base_path = xe::filesystem::GetExecutableFolder();
    base_path = xe::to_absolute_path(base_path);

    auto portable_path = xe::join_paths(base_path, L"portable.txt");
    if (xe::filesystem::PathExists(portable_path)) {
      content_root = xe::join_paths(base_path, L"content");
    } else {
      content_root = xe::filesystem::GetUserFolder();
#if defined(XE_PLATFORM_WIN32)
      content_root = xe::join_paths(content_root, L"Xenia");
#elif defined(XE_PLATFORM_LINUX)
      content_root = xe::join_paths(content_root, L"Xenia");
#else
#warning Unhandled platform for content root.
      content_root = xe::join_paths(content_root, L"Xenia");
#endif
      content_root = xe::join_paths(content_root, L"content");
    }
  }
  content_root = xe::to_absolute_path(content_root);
  XELOGI("Content root: %S", content_root.c_str());

  // Create the emulator but don't initialize so we can setup the window.
  auto emulator = std::make_unique<Emulator>(L"", content_root);

  // Main emulator display window.
  auto emulator_window = EmulatorWindow::Create(emulator.get());

  // Setup and initialize all subsystems. If we can't do something
  // (unsupported system, memory issues, etc) this will fail early.
  X_STATUS result =
      emulator->Setup(emulator_window->window(), CreateAudioSystem,
                      CreateGraphicsSystem, CreateInputDrivers);
  if (XFAILED(result)) {
    XELOGE("Failed to setup emulator: %.8X", result);
    return 1;
  }

  if (cvars::mount_scratch) {
    auto scratch_device = std::make_unique<xe::vfs::HostPathDevice>(
        "\\SCRATCH", L"scratch", false);
    if (!scratch_device->Initialize()) {<commit_msg>[App] Initialize config on emulator startup<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 <NAME>. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/app/emulator_window.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h"
#include "xenia/base/logging.h"
#include "xenia/base/main.h"
#include "xenia/base/profiling.h"
#include "xenia/base/threading.h"
#include "xenia/config.h"
#include "xenia/debug/ui/debug_window.h"
#include "xenia/emulator.h"
#include "xenia/ui/file_picker.h"
#include "xenia/vfs/devices/host_path_device.h"

// Available audio systems:
#include "xenia/apu/nop/nop_audio_system.h"
#if XE_PLATFORM_WIN32
#include "xenia/apu/xaudio2/xaudio2_audio_system.h"
#endif  // XE_PLATFORM_WIN32

// Available graphics systems:
#include "xenia/gpu/null/null_graphics_system.h"
#include "xenia/gpu/vulkan/vulkan_graphics_system.h"

// Available input drivers:
#include "xenia/hid/nop/nop_hid.h"
#if XE_PLATFORM_WIN32
#include "xenia/hid/winkey/winkey_hid.h"
#include "xenia/hid/xinput/xinput_hid.h"
#endif  // XE_PLATFORM_WIN32

#include "third_party/xbyak/xbyak/xbyak_util.h"

DEFINE_string(apu, "any", "Audio system. Use: [any, nop, xaudio2]", "General");
DEFINE_string(gpu, "any", "Graphics system. Use: [any, vulkan, null]",
              "General");
DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]",
              "General");

DEFINE_bool(fullscreen, false, "Toggles fullscreen", "General");

DEFINE_string(content_root, "", "Root path for content (save/etc) storage.",
              "General");

DEFINE_bool(mount_scratch, false, "Enable scratch mount", "General");
DEFINE_bool(mount_cache, false, "Enable cache mount", "General");

CmdVar(target, "", "Specifies the target .xex or .iso to execute.");
DECLARE_bool(debug);

namespace xe {
namespace app {

std::unique_ptr<apu::AudioSystem> CreateAudioSystem(cpu::Processor* processor) {
  if (cvars::apu.compare("nop") == 0) {
    return apu::nop::NopAudioSystem::Create(processor);
#if XE_PLATFORM_WIN32
  } else if (cvars::apu.compare("xaudio2") == 0) {
    return apu::xaudio2::XAudio2AudioSystem::Create(processor);
#endif  // XE_PLATFORM_WIN32
  } else {
    // Create best available.
    std::unique_ptr<apu::AudioSystem> best;

#if XE_PLATFORM_WIN32
    best = apu::xaudio2::XAudio2AudioSystem::Create(processor);
    if (best) {
      return best;
    }
#endif  // XE_PLATFORM_WIN32

    // Fallback to nop.
    return apu::nop::NopAudioSystem::Create(processor);
  }
}

std::unique_ptr<gpu::GraphicsSystem> CreateGraphicsSystem() {
  if (cvars::gpu.compare("vulkan") == 0) {
    return std::unique_ptr<gpu::GraphicsSystem>(
        new xe::gpu::vulkan::VulkanGraphicsSystem());
  } else if (cvars::gpu.compare("null") == 0) {
    return std::unique_ptr<gpu::GraphicsSystem>(
        new xe::gpu::null::NullGraphicsSystem());
  } else {
    // Create best available.
    std::unique_ptr<gpu::GraphicsSystem> best;

    best = std::unique_ptr<gpu::GraphicsSystem>(
        new xe::gpu::vulkan::VulkanGraphicsSystem());
    if (best) {
      return best;
    }

    // Nothing!
    return nullptr;
  }
}

std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
    ui::Window* window) {
  std::vector<std::unique_ptr<hid::InputDriver>> drivers;
  if (cvars::hid.compare("nop") == 0) {
    drivers.emplace_back(xe::hid::nop::Create(window));
#if XE_PLATFORM_WIN32
  } else if (cvars::hid.compare("winkey") == 0) {
    drivers.emplace_back(xe::hid::winkey::Create(window));
  } else if (cvars::hid.compare("xinput") == 0) {
    drivers.emplace_back(xe::hid::xinput::Create(window));
#endif  // XE_PLATFORM_WIN32
  } else {
#if XE_PLATFORM_WIN32
    auto xinput_driver = xe::hid::xinput::Create(window);
    if (xinput_driver) {
      drivers.emplace_back(std::move(xinput_driver));
    }
    auto winkey_driver = xe::hid::winkey::Create(window);
    if (winkey_driver) {
      drivers.emplace_back(std::move(winkey_driver));
    }
#endif  // XE_PLATFORM_WIN32
  }
  for (auto it = drivers.begin(); it != drivers.end();) {
    if (XFAILED((*it)->Setup())) {
      it = drivers.erase(it);
    } else {
      ++it;
    }
  }
  if (drivers.empty()) {
    // Fallback to nop if none created.
    drivers.emplace_back(xe::hid::nop::Create(window));
  }
  return drivers;
}

int xenia_main(const std::vector<std::wstring>& args) {
  Profiler::Initialize();
  Profiler::ThreadEnter("main");

  // Figure out where content should go.
  std::wstring content_root = xe::to_wstring(cvars::content_root);
  std::wstring config_folder;

  if (content_root.empty()) {
    auto base_path = xe::filesystem::GetExecutableFolder();
    base_path = xe::to_absolute_path(base_path);

    auto portable_path = xe::join_paths(base_path, L"portable.txt");
    if (xe::filesystem::PathExists(portable_path)) {
      content_root = xe::join_paths(base_path, L"content");
      config_folder = base_path;
    } else {
      content_root = xe::filesystem::GetUserFolder();
#if defined(XE_PLATFORM_WIN32)
      content_root = xe::join_paths(content_root, L"Xenia");
#elif defined(XE_PLATFORM_LINUX)
      content_root = xe::join_paths(content_root, L"Xenia");
#else
#warning Unhandled platform for content root.
      content_root = xe::join_paths(content_root, L"Xenia");
#endif
      config_folder = content_root;
      content_root = xe::join_paths(content_root, L"content");
    }
  }
  content_root = xe::to_absolute_path(content_root);

  XELOGI("Content root: %S", content_root.c_str());
  config::SetupConfig(config_folder);

  // Create the emulator but don't initialize so we can setup the window.
  auto emulator = std::make_unique<Emulator>(L"", content_root);

  // Main emulator display window.
  auto emulator_window = EmulatorWindow::Create(emulator.get());

  // Setup and initialize all subsystems. If we can't do something
  // (unsupported system, memory issues, etc) this will fail early.
  X_STATUS result =
      emulator->Setup(emulator_window->window(), CreateAudioSystem,
                      CreateGraphicsSystem, CreateInputDrivers);
  if (XFAILED(result)) {
    XELOGE("Failed to setup emulator: %.8X", result);
    return 1;
  }

  if (cvars::mount_scratch) {
    auto scratch_device = std::make_unique<xe::vfs::HostPathDevice>(
        "\\SCRATCH", L"scratch", false);
    if (!scratch_device->Initialize()) {
{'fraction_non_alphanumeric': 0.18242734527932541, 'fraction_numerical': 0.007528986598403855, 'mean_word_length': 4.41721044045677, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '93730', 'n_tokens_mistral': 4673, 'n_tokens_neox': 4505, 'n_words': 848}