Skip to content

Commit

Permalink
Initial files related to microphone support
Browse files Browse the repository at this point in the history
  • Loading branch information
Gliniak committed Aug 10, 2022
1 parent e344725 commit b5e95f5
Show file tree
Hide file tree
Showing 24 changed files with 624 additions and 11 deletions.
2 changes: 2 additions & 0 deletions premake5.lua
Expand Up @@ -291,6 +291,7 @@ workspace("xenia")
include("src/xenia/gpu/vulkan")
include("src/xenia/hid/controller")
include("src/xenia/hid/controller/nop")
include("src/xenia/hid/microphone")
include("src/xenia/kernel")
include("src/xenia/ui")
include("src/xenia/ui/vulkan")
Expand All @@ -300,6 +301,7 @@ workspace("xenia")
include("src/xenia/apu/sdl")
include("src/xenia/helper/sdl")
include("src/xenia/hid/controller/sdl")
include("src/xenia/hid/microphone/sdl")
end

if os.istarget("windows") then
Expand Down
2 changes: 2 additions & 0 deletions src/xenia/app/premake5.lua
Expand Up @@ -16,6 +16,7 @@ project("xenia-app")
"xenia-gpu-vulkan",
"xenia-hid-controller",
"xenia-hid-controller-nop",
"xenia-hid-microphone",
"xenia-kernel",
"xenia-ui",
"xenia-ui-vulkan",
Expand Down Expand Up @@ -94,6 +95,7 @@ project("xenia-app")
"xenia-debug-ui",
"xenia-helper-sdl",
"xenia-hid-controller-sdl",
"xenia-hid-microphone-sdl",
})

filter("platforms:Linux")
Expand Down
29 changes: 27 additions & 2 deletions src/xenia/app/xenia_main.cc
Expand Up @@ -54,6 +54,7 @@
#include "xenia/hid/controller/nop/nop_hid.h"
#if !XE_PLATFORM_ANDROID
#include "xenia/hid/controller/sdl/sdl_hid.h"
#include "xenia/hid/microphone/sdl/sdl_hid.h"
#endif // !XE_PLATFORM_ANDROID
#if XE_PLATFORM_WIN32
#include "xenia/hid/controller/winkey/winkey_hid.h"
Expand Down Expand Up @@ -214,6 +215,8 @@ class EmulatorApp final : public xe::ui::WindowedApp {
static std::unique_ptr<gpu::GraphicsSystem> CreateGraphicsSystem();
static std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
ui::Window* window);
static std::vector<std::unique_ptr<hid::MicrophoneDriver>>
CreateMicrophoneDrivers();

void EmulatorThread();
void ShutdownEmulatorThreadFromUIThread();
Expand Down Expand Up @@ -357,7 +360,7 @@ std::vector<std::unique_ptr<hid::InputDriver>> EmulatorApp::CreateInputDrivers(
factory.Add("xinput", xe::hid::xinput::Create);
#endif // XE_PLATFORM_WIN32
#if !XE_PLATFORM_ANDROID
factory.Add("sdl", xe::hid::sdl::Create);
factory.Add("sdl", xe::hid::sdl::controller::Create);
#endif // !XE_PLATFORM_ANDROID
#if XE_PLATFORM_WIN32
// WinKey input driver should always be the last input driver added!
Expand All @@ -378,6 +381,27 @@ std::vector<std::unique_ptr<hid::InputDriver>> EmulatorApp::CreateInputDrivers(
return drivers;
}

std::vector<std::unique_ptr<hid::MicrophoneDriver>>
EmulatorApp::CreateMicrophoneDrivers() {
std::vector<std::unique_ptr<hid::MicrophoneDriver>> drivers;
Factory<hid::MicrophoneDriver> factory;
#if !XE_PLATFORM_ANDROID
factory.Add("sdl", xe::hid::microphone::sdl::Create);
#endif // !XE_PLATFORM_ANDROID
for (auto& driver :
factory.CreateAll("sdl")) {
if (XSUCCEEDED(driver->Setup())) {
drivers.emplace_back(std::move(driver));
}
}
if (drivers.empty()) {
// Fallback to nop if none created.
//drivers.emplace_back(
// xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput));
}
return drivers;
}

bool EmulatorApp::OnInitialize() {
Profiler::Initialize();
Profiler::ThreadEnter("Main");
Expand Down Expand Up @@ -486,7 +510,8 @@ void EmulatorApp::EmulatorThread() {
// (unsupported system, memory issues, etc) this will fail early.
X_STATUS result = emulator_->Setup(
emulator_window_->window(), emulator_window_->imgui_drawer(), true,
CreateAudioSystem, CreateGraphicsSystem, CreateInputDrivers);
CreateAudioSystem, CreateGraphicsSystem, CreateInputDrivers,
CreateMicrophoneDrivers);
if (XFAILED(result)) {
XELOGE("Failed to setup emulator: {:08X}", result);
app_context().RequestDeferredQuit();
Expand Down
31 changes: 29 additions & 2 deletions src/xenia/emulator.cc
Expand Up @@ -33,6 +33,8 @@
#include "xenia/gpu/graphics_system.h"
#include "xenia/hid/controller/input_driver.h"
#include "xenia/hid/controller/input_system.h"
#include "xenia/hid/microphone/microphone_driver.h"
#include "xenia/hid/microphone/microphone_system.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/gameinfo_utils.h"
Expand Down Expand Up @@ -96,6 +98,7 @@ Emulator::Emulator(const std::filesystem::path& command_line,
audio_system_(),
graphics_system_(),
input_system_(),
microphone_system_(),
export_resolver_(),
file_system_(),
kernel_state_(),
Expand All @@ -119,6 +122,7 @@ Emulator::~Emulator() {
input_system_.reset();
graphics_system_.reset();
audio_system_.reset();
microphone_system_.reset();

kernel_state_.reset();
file_system_.reset();
Expand All @@ -138,7 +142,9 @@ X_STATUS Emulator::Setup(
std::function<std::unique_ptr<gpu::GraphicsSystem>()>
graphics_system_factory,
std::function<std::vector<std::unique_ptr<hid::InputDriver>>(ui::Window*)>
input_driver_factory) {
input_driver_factory,
std::function<std::vector<std::unique_ptr<hid::MicrophoneDriver>>()>
microphone_driver_factory) {
X_STATUS result = X_STATUS_UNSUCCESSFUL;

display_window_ = display_window;
Expand Down Expand Up @@ -203,7 +209,7 @@ X_STATUS Emulator::Setup(
return X_STATUS_NOT_IMPLEMENTED;
}

// Initialize the HID.
// Initialize the HID controller.
input_system_ = std::make_unique<xe::hid::InputSystem>(display_window_);
if (!input_system_) {
return X_STATUS_NOT_IMPLEMENTED;
Expand All @@ -223,6 +229,27 @@ X_STATUS Emulator::Setup(
return result;
}

// Initialize the HID microphone
microphone_system_ = std::make_unique<xe::hid::MicrophoneSystem>();

if (!microphone_system_) {
return X_STATUS_NOT_IMPLEMENTED;
}
if (microphone_driver_factory) {
auto input_drivers = microphone_driver_factory();
for (size_t i = 0; i < input_drivers.size(); ++i) {
auto& input_driver = input_drivers[i];
input_driver->set_is_active_callback(
[]() -> bool { return !xe::kernel::xam::xeXamIsUIActive(); });
microphone_system_->AddDriver(std::move(input_driver));
}
}

result = microphone_system_->Setup();
if (result) {
return result;
}

// Bring up the virtual filesystem used by the kernel.
file_system_ = std::make_unique<xe::vfs::VirtualFileSystem>();

Expand Down
12 changes: 11 additions & 1 deletion src/xenia/emulator.h
Expand Up @@ -39,6 +39,8 @@ class GraphicsSystem;
namespace hid {
class InputDriver;
class InputSystem;
class MicrophoneDriver;
class MicrophoneSystem;
} // namespace hid
namespace ui {
class ImGuiDrawer;
Expand Down Expand Up @@ -142,6 +144,11 @@ class Emulator {
// Human-interface Device (HID) adapters for controllers.
hid::InputSystem* input_system() const { return input_system_.get(); }

// Human-interface Device (HID) adapters for microphones
hid::MicrophoneSystem* microphone_system() const {
return microphone_system_.get();
}

// Kernel function export table used to resolve exports when JITing code.
cpu::ExportResolver* export_resolver() const {
return export_resolver_.get();
Expand All @@ -167,7 +174,9 @@ class Emulator {
std::function<std::unique_ptr<gpu::GraphicsSystem>()>
graphics_system_factory,
std::function<std::vector<std::unique_ptr<hid::InputDriver>>(ui::Window*)>
input_driver_factory);
input_driver_factory,
std::function<std::vector<std::unique_ptr<hid::MicrophoneDriver>>()>
microphone_driver_factory);

// Terminates the currently running title.
X_STATUS TerminateTitle();
Expand Down Expand Up @@ -235,6 +244,7 @@ class Emulator {
std::unique_ptr<apu::AudioSystem> audio_system_;
std::unique_ptr<gpu::GraphicsSystem> graphics_system_;
std::unique_ptr<hid::InputSystem> input_system_;
std::unique_ptr<hid::MicrophoneSystem> microphone_system_;

std::unique_ptr<cpu::ExportResolver> export_resolver_;
std::unique_ptr<vfs::VirtualFileSystem> file_system_;
Expand Down
2 changes: 1 addition & 1 deletion src/xenia/gpu/trace_dump.cc
Expand Up @@ -97,7 +97,7 @@ bool TraceDump::Setup() {
emulator_ = std::make_unique<Emulator>("", "", "", "");
X_STATUS result = emulator_->Setup(
nullptr, nullptr, false, nullptr,
[this]() { return CreateGraphicsSystem(); }, nullptr);
[this]() { return CreateGraphicsSystem(); }, nullptr, nullptr);
if (XFAILED(result)) {
XELOGE("Failed to setup emulator: {:08X}", result);
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/xenia/gpu/trace_viewer.cc
Expand Up @@ -132,7 +132,7 @@ bool TraceViewer::Setup() {
emulator_ = std::make_unique<Emulator>("", "", "", "");
X_STATUS result = emulator_->Setup(
window_.get(), nullptr, false, nullptr,
[this]() { return CreateGraphicsSystem(); }, nullptr);
[this]() { return CreateGraphicsSystem(); }, nullptr, nullptr);
if (XFAILED(result)) {
XELOGE("Failed to setup emulator: {:08X}", result);
return false;
Expand Down
4 changes: 2 additions & 2 deletions src/xenia/hid/controller/hid_demo.cc
Expand Up @@ -127,7 +127,7 @@ std::vector<std::unique_ptr<hid::InputDriver>> HidDemoApp::CreateInputDrivers(
drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput));
#if !XE_PLATFORM_ANDROID
} else if (cvars::hid.compare("sdl") == 0) {
auto driver = xe::hid::sdl::Create(window, kZOrderHidInput);
auto driver = xe::hid::sdl::controller::Create(window, kZOrderHidInput);
if (XSUCCEEDED(driver->Setup())) {
drivers.emplace_back(std::move(driver));
}
Expand All @@ -146,7 +146,7 @@ std::vector<std::unique_ptr<hid::InputDriver>> HidDemoApp::CreateInputDrivers(
#endif // XE_PLATFORM_WIN32
} else {
#if !XE_PLATFORM_ANDROID
auto sdl_driver = xe::hid::sdl::Create(window, kZOrderHidInput);
auto sdl_driver = xe::hid::sdl::controller::Create(window, kZOrderHidInput);
if (sdl_driver && XSUCCEEDED(sdl_driver->Setup())) {
drivers.emplace_back(std::move(sdl_driver));
}
Expand Down
2 changes: 2 additions & 0 deletions src/xenia/hid/controller/sdl/sdl_hid.cc
Expand Up @@ -14,12 +14,14 @@
namespace xe {
namespace hid {
namespace sdl {
namespace controller {

std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order) {
return std::make_unique<SDLInputDriver>(window, window_z_order);
}

} // namespace controller
} // namespace sdl
} // namespace hid
} // namespace xe
3 changes: 2 additions & 1 deletion src/xenia/hid/controller/sdl/sdl_hid.h
Expand Up @@ -17,10 +17,11 @@
namespace xe {
namespace hid {
namespace sdl {
namespace controller {

std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order);

} // namespace controller
} // namespace sdl
} // namespace hid
} // namespace xe
Expand Down
59 changes: 59 additions & 0 deletions src/xenia/hid/microphone/microphone.h
@@ -0,0 +1,59 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/

#pragma once

#include "xenia/base/assert.h"
#include "xenia/base/byte_order.h"

namespace xe {
namespace hid {

/* States of microphone
0 - Not connected
1 - Connected, not initialized for user_index 0
2 - Connected, not initialized for user_index 1
3 - Connected, not initialized for user_index 2
4 - Connected, not initialized for user_index 3
5 - Ready (for user_index 0?)
*/

typedef struct {
xe::be<uint16_t> request_type;
xe::be<uint16_t> user_index;
xe::be<uint32_t> state; // 8

xe::be<uint64_t> unk1; // 16
xe::be<uint64_t> unk2; // 24
} XMICINFO;

typedef struct {
xe::be<uint32_t> features;
xe::be<uint16_t> format_tag;
xe::be<uint16_t> channels;
xe::be<uint32_t> sample_rates;
xe::be<uint16_t> bits_per_sample;
xe::be<uint16_t> frame_length; // 0xE
xe::be<uint8_t> mic_color; // 0x10
xe::be<uint16_t> vendor_id;
xe::be<uint16_t> product_id;
xe::be<uint16_t> revision;
xe::be<uint32_t> device_id;

} XMICCAPABILITIES;
static_assert_size(XMICCAPABILITIES, 0x1C);

typedef struct {
XMICINFO info;
XMICCAPABILITIES capabilities;

} X_MIC_DEVICE;

} // namespace hid
} // namespace xe
48 changes: 48 additions & 0 deletions src/xenia/hid/microphone/microphone_driver.h
@@ -0,0 +1,48 @@
/**
******************************************************************************
* 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_HID_MICROPHONE_DRIVER_H_
#define XENIA_HID_MICROPHONE_DRIVER_H_

#include "xenia/xbox.h"

namespace xe {
namespace hid {

class MicrophoneSystem;

class MicrophoneDriver {
public:
virtual ~MicrophoneDriver() = default;

virtual X_STATUS Setup() = 0;

virtual X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
void* out_caps) = 0;
virtual X_RESULT GetState(uint32_t user_index, uint32_t* out_state) = 0;
virtual X_RESULT GetData(uint32_t user_index, void* out_ptr) = 0;

void set_is_active_callback(std::function<bool()> is_active_callback) {
is_active_callback_ = is_active_callback;
}

protected:
explicit MicrophoneDriver() {}

bool is_active() const {
return !is_active_callback_ || is_active_callback_();
}

private:
std::function<bool()> is_active_callback_ = nullptr;
};
}
} // namespace xe

#endif // XENIA_HID_MICROPHONE_DRIVER_H_

0 comments on commit b5e95f5

Please sign in to comment.