diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 864993b6e..7986ef79b 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -477,7 +477,7 @@ void EmulatorApp::EmulatorThread() { // 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(), emulator_window_->imgui_drawer(), + emulator_window_->window(), emulator_window_->imgui_drawer(), true, CreateAudioSystem, CreateGraphicsSystem, CreateInputDrivers); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); diff --git a/src/xenia/cpu/backend/null_backend.cc b/src/xenia/cpu/backend/null_backend.cc new file mode 100644 index 000000000..e401b5f41 --- /dev/null +++ b/src/xenia/cpu/backend/null_backend.cc @@ -0,0 +1,36 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/cpu/backend/null_backend.h" + +#include "xenia/cpu/backend/assembler.h" +#include "xenia/cpu/function.h" + +namespace xe { +namespace cpu { +namespace backend { + +void NullBackend::CommitExecutableRange(uint32_t guest_low, + uint32_t guest_high) {} + +std::unique_ptr NullBackend::CreateAssembler() { return nullptr; } + +std::unique_ptr NullBackend::CreateGuestFunction( + Module* module, uint32_t address) { + return nullptr; +} + +uint64_t NullBackend::CalculateNextHostInstruction(ThreadDebugInfo* thread_info, + uint64_t current_pc) { + return current_pc; +} + +} // namespace backend +} // namespace cpu +} // namespace xe diff --git a/src/xenia/cpu/backend/null_backend.h b/src/xenia/cpu/backend/null_backend.h new file mode 100644 index 000000000..957132269 --- /dev/null +++ b/src/xenia/cpu/backend/null_backend.h @@ -0,0 +1,36 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_CPU_BACKEND_NULL_BACKEND_H_ +#define XENIA_CPU_BACKEND_NULL_BACKEND_H_ + +#include "xenia/cpu/backend/backend.h" + +namespace xe { +namespace cpu { +namespace backend { + +class NullBackend : public Backend { + public: + void CommitExecutableRange(uint32_t guest_low, uint32_t guest_high) override; + + std::unique_ptr CreateAssembler() override; + + std::unique_ptr CreateGuestFunction(Module* module, + uint32_t address) override; + + uint64_t CalculateNextHostInstruction(ThreadDebugInfo* thread_info, + uint64_t current_pc) override; +}; + +} // namespace backend +} // namespace cpu +} // namespace xe + +#endif // XENIA_CPU_BACKEND_NULL_BACKEND_H_ diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index f22a4e12b..eb63a1abf 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -134,7 +134,11 @@ bool Processor::Setup(std::unique_ptr backend) { // Stack walker is used when profiling, debugging, and dumping. // Note that creation may fail, in which case we'll have to disable those // features. - stack_walker_ = StackWalker::Create(backend_->code_cache()); + // The code cache may be unavailable in case of a "null" backend. + cpu::backend::CodeCache* code_cache = backend_->code_cache(); + if (code_cache) { + stack_walker_ = StackWalker::Create(code_cache); + } if (!stack_walker_) { // TODO(benvanik): disable features. if (cvars::debug) { diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index da9fb18d4..38a2bb09c 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -27,6 +27,7 @@ #include "xenia/base/platform.h" #include "xenia/base/string.h" #include "xenia/cpu/backend/code_cache.h" +#include "xenia/cpu/backend/null_backend.h" #include "xenia/cpu/cpu_flags.h" #include "xenia/cpu/thread_state.h" #include "xenia/gpu/graphics_system.h" @@ -131,6 +132,7 @@ Emulator::~Emulator() { X_STATUS Emulator::Setup( ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer, + bool require_cpu_backend, std::function(cpu::Processor*)> audio_system_factory, std::function()> @@ -164,20 +166,21 @@ X_STATUS Emulator::Setup( export_resolver_ = std::make_unique(); std::unique_ptr backend; - if (!backend) { #if XE_ARCH_AMD64 - if (cvars::cpu == "x64") { + if (cvars::cpu == "x64") { + backend.reset(new xe::cpu::backend::x64::X64Backend()); + } +#endif // XE_ARCH + if (cvars::cpu == "any") { + if (!backend) { +#if XE_ARCH_AMD64 backend.reset(new xe::cpu::backend::x64::X64Backend()); - } #endif // XE_ARCH - if (cvars::cpu == "any") { - if (!backend) { -#if XE_ARCH_AMD64 - backend.reset(new xe::cpu::backend::x64::X64Backend()); -#endif // XE_ARCH - } } } + if (!backend && !require_cpu_backend) { + backend.reset(new xe::cpu::backend::NullBackend()); + } // Initialize the CPU. processor_ = std::make_unique(memory_.get(), diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index 96d81d00a..a0dbeff25 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -161,6 +161,7 @@ class Emulator { // functions. X_STATUS Setup( ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer, + bool require_cpu_backend, std::function(cpu::Processor*)> audio_system_factory, std::function()> diff --git a/src/xenia/gpu/trace_dump.cc b/src/xenia/gpu/trace_dump.cc index 2932a4110..ec4e85cea 100644 --- a/src/xenia/gpu/trace_dump.cc +++ b/src/xenia/gpu/trace_dump.cc @@ -95,8 +95,8 @@ bool TraceDump::Setup() { // Create the emulator but don't initialize so we can setup the window. emulator_ = std::make_unique("", "", "", ""); X_STATUS result = emulator_->Setup( - nullptr, nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, - nullptr); + nullptr, nullptr, false, nullptr, + [this]() { return CreateGraphicsSystem(); }, nullptr); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); return false; diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 70f68c184..7485dd6b0 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -125,7 +125,7 @@ bool TraceViewer::Setup() { // Create the emulator but don't initialize so we can setup the window. emulator_ = std::make_unique("", "", "", ""); X_STATUS result = emulator_->Setup( - window_.get(), nullptr, nullptr, + window_.get(), nullptr, false, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result);