mirror of
https://github.com/izzy2lost/xenia-edge.git
synced 2026-07-06 00:20:26 -07:00
Merge remote-tracking branch 'upstream/canary_experimental' into edge
This commit is contained in:
@@ -490,6 +490,73 @@ void EmulatorWindow::EmulatorWindowListener::OnMouseDoubleClick(
|
||||
emulator_window_.OnMouseDoubleClick(e);
|
||||
}
|
||||
|
||||
void EmulatorWindow::XMPConfigDialog::OnDraw(ImGuiIO& io) {
|
||||
// Center window horizontally, position in lower portion of screen
|
||||
float window_width = 400.0f;
|
||||
float window_height = 150.0f;
|
||||
float x = (io.DisplaySize.x - window_width) * 0.5f;
|
||||
float y = io.DisplaySize.y * 0.85f - window_height * 0.5f;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(x, y), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(window_width, window_height),
|
||||
ImGuiCond_FirstUseEver);
|
||||
|
||||
bool dialog_open = true;
|
||||
if (!ImGui::Begin("Audio Player Menu", &dialog_open,
|
||||
ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
Close();
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
auto audio_player = emulator_window_.emulator_->audio_media_player();
|
||||
using xmp_state = kernel::xam::apps::XmpApp::State;
|
||||
if (audio_player) {
|
||||
ImGui::Text("Audio player status:");
|
||||
ImGui::SameLine();
|
||||
switch (audio_player->GetState()) {
|
||||
case xmp_state::kIdle:
|
||||
ImGui::Text("Idle");
|
||||
break;
|
||||
case xmp_state::kPaused:
|
||||
ImGui::Text("Paused");
|
||||
break;
|
||||
case xmp_state::kPlaying:
|
||||
ImGui::Text("Playing");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (audio_player->IsPlaying()) {
|
||||
if (ImGui::Button("Pause")) {
|
||||
audio_player->Pause();
|
||||
}
|
||||
} else if (audio_player->IsPaused()) {
|
||||
if (ImGui::Button("Resume")) {
|
||||
audio_player->Continue();
|
||||
}
|
||||
}
|
||||
|
||||
volume_ =
|
||||
emulator_window_.emulator_->audio_media_player()->GetVolume()->load();
|
||||
|
||||
if (ImGui::SliderFloat("Audio player volume", &volume_, 0.0f, 1.0f)) {
|
||||
audio_player->SetVolume(volume_);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dialog_open) {
|
||||
ImGui::End();
|
||||
emulator_window_.ToggleXMPConfigDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool EmulatorWindow::Initialize() {
|
||||
window_->AddListener(&window_listener_);
|
||||
window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput);
|
||||
@@ -1050,6 +1117,9 @@ void EmulatorWindow::OnMouseDown(const ui::MouseEvent& e) {
|
||||
context_menu->AddAction("Profiles Menu",
|
||||
[this]() { ToggleProfilesConfigDialog(); });
|
||||
|
||||
context_menu->AddAction("XMP Audio Player",
|
||||
[this]() { ToggleXMPConfigDialog(); });
|
||||
|
||||
// Show menu at mouse position
|
||||
QPoint global_pos = QCursor::pos();
|
||||
context_menu->ShowAt(global_pos);
|
||||
@@ -1544,6 +1614,15 @@ void EmulatorWindow::OpenConfigDialog(const std::string& category) {
|
||||
config_dialog_qt_->activateWindow();
|
||||
}
|
||||
|
||||
void EmulatorWindow::ToggleXMPConfigDialog() {
|
||||
if (!xmp_config_dialog_) {
|
||||
xmp_config_dialog_ = std::unique_ptr<XMPConfigDialog>(
|
||||
new XMPConfigDialog(imgui_drawer_.get(), *this));
|
||||
} else {
|
||||
xmp_config_dialog_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatorWindow::ToggleControllerVibration() {
|
||||
auto input_sys = emulator()->input_system();
|
||||
if (input_sys) {
|
||||
|
||||
@@ -113,6 +113,7 @@ class EmulatorWindow {
|
||||
const xe::ui::RawImage& image);
|
||||
|
||||
void ToggleProfilesConfigDialog();
|
||||
void ToggleXMPConfigDialog();
|
||||
void SetHotkeysState(bool enabled) { disable_hotkeys_ = !enabled; }
|
||||
void FileOpen();
|
||||
const std::vector<RecentTitleEntry>& GetRecentlyLaunchedTitles() const {
|
||||
@@ -180,6 +181,26 @@ class EmulatorWindow {
|
||||
};
|
||||
|
||||
public:
|
||||
class XMPConfigDialog final : public ui::ImGuiDialog {
|
||||
public:
|
||||
XMPConfigDialog(ui::ImGuiDrawer* imgui_drawer,
|
||||
EmulatorWindow& emulator_window)
|
||||
: ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) {
|
||||
if (emulator_window_.emulator_->audio_media_player()) {
|
||||
volume_ = emulator_window_.emulator_->audio_media_player()
|
||||
->GetVolume()
|
||||
->load();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void OnDraw(ImGuiIO& io) override;
|
||||
|
||||
private:
|
||||
EmulatorWindow& emulator_window_;
|
||||
float volume_ = 0.0f;
|
||||
};
|
||||
|
||||
explicit EmulatorWindow(Emulator* emulator,
|
||||
ui::WindowedAppContext& app_context, uint32_t width,
|
||||
uint32_t height, bool is_game_process = false);
|
||||
@@ -283,6 +304,8 @@ class EmulatorWindow {
|
||||
// messages back to guest.
|
||||
std::unique_ptr<ProfileConfigDialog> profile_config_dialog_;
|
||||
|
||||
std::unique_ptr<XMPConfigDialog> xmp_config_dialog_;
|
||||
|
||||
std::vector<RecentTitleEntry> recently_launched_titles_;
|
||||
|
||||
// Menu items that need to be enabled/disabled based on child process state
|
||||
|
||||
@@ -448,7 +448,7 @@ void AudioMediaPlayer::RemovePlaylist(uint32_t handle) {
|
||||
}
|
||||
|
||||
X_STATUS AudioMediaPlayer::SetVolume(float volume) {
|
||||
volume_ = std::min(volume, 1.0f);
|
||||
volume_.store(std::min(volume, 1.0f));
|
||||
|
||||
std::unique_lock<xe_mutex> guard(driver_mutex_);
|
||||
if (!driver_) {
|
||||
|
||||
@@ -51,7 +51,7 @@ class AudioMediaPlayer {
|
||||
bool IsLastSongInPlaylist() const;
|
||||
|
||||
X_STATUS SetVolume(float volume);
|
||||
float GetVolume() const { return volume_; }
|
||||
const std::atomic<float>* GetVolume() const { return &volume_; }
|
||||
|
||||
void SetPlaybackMode(XmpApp::PlaybackMode playback_mode) {
|
||||
playback_mode_ = playback_mode;
|
||||
@@ -106,7 +106,7 @@ class AudioMediaPlayer {
|
||||
XmpApp::PlaybackMode playback_mode_ = XmpApp::PlaybackMode::kInOrder;
|
||||
XmpApp::RepeatMode repeat_mode_ = XmpApp::RepeatMode::kPlaylist;
|
||||
XmpApp::PlaybackFlags playback_flags_ = XmpApp::PlaybackFlags::kDefault;
|
||||
float volume_ = 1.0f;
|
||||
std::atomic<float> volume_ = 0.0f;
|
||||
uint32_t dash_init_state = 0;
|
||||
|
||||
std::unordered_map<uint32_t, std::unique_ptr<XmpApp::Playlist>> playlists_;
|
||||
|
||||
@@ -175,6 +175,10 @@ struct ValueOp : Op<ValueOp<T, KEY_TYPE, REG_TYPE, CONST_TYPE>, KEY_TYPE> {
|
||||
virtual bool ConstantFitsIn32Reg() const { return true; }
|
||||
const REG_TYPE& reg() const {
|
||||
assert_true(!is_constant);
|
||||
if (is_constant) {
|
||||
XELOGE("{} - Invalid handling of constant! Report this to developers!",
|
||||
__FUNCTION__);
|
||||
}
|
||||
return reg_;
|
||||
}
|
||||
operator const REG_TYPE&() const { return reg(); }
|
||||
|
||||
@@ -1885,7 +1885,12 @@ struct VECTOR_ROTATE_LEFT_V128
|
||||
} break;
|
||||
case INT32_TYPE: {
|
||||
if (e.IsFeatureEnabled(kX64EmitAVX512Ortho)) {
|
||||
e.vprolvd(i.dest, i.src1, i.src2);
|
||||
if (i.src2.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm0, i.src2.constant());
|
||||
e.vprolvd(i.dest, i.src1, e.xmm0);
|
||||
} else {
|
||||
e.vprolvd(i.dest, i.src1, i.src2);
|
||||
}
|
||||
} else if (e.IsFeatureEnabled(kX64EmitAVX2)) {
|
||||
Xmm temp = i.dest;
|
||||
if (i.dest == i.src1 || i.dest == i.src2) {
|
||||
|
||||
@@ -262,7 +262,7 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
|
||||
|
||||
xe::store_and_swap<float>(
|
||||
memory_->TranslateVirtual(args->volume_ptr),
|
||||
kernel_state_->emulator()->audio_media_player()->GetVolume());
|
||||
kernel_state_->emulator()->audio_media_player()->GetVolume()->load());
|
||||
return X_E_SUCCESS;
|
||||
}
|
||||
case 0x0007000C: {
|
||||
@@ -401,7 +401,7 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
|
||||
XMP_CREATE_USER_PLAYLIST_ENUMERATOR* args =
|
||||
reinterpret_cast<XMP_CREATE_USER_PLAYLIST_ENUMERATOR*>(buffer);
|
||||
|
||||
XELOGD("XMPSetPlaybackController({:08X}, {:08X}, {:08X})",
|
||||
XELOGD("XMPCreateUserPlaylistEnumerator({:08X}, {:08X}, {:08X})",
|
||||
uint32_t(args->xmp_client), uint32_t(args->flags),
|
||||
uint32_t(args->unk_ptr));
|
||||
return X_E_SUCCESS;
|
||||
|
||||
@@ -86,7 +86,7 @@ static_assert_size(XMP_GET_VOLUME, 0x8);
|
||||
|
||||
struct XMP_SET_VOLUME {
|
||||
xe::be<uint32_t> xmp_client;
|
||||
xe::be<uint32_t> value;
|
||||
xe::be<float> value;
|
||||
};
|
||||
static_assert_size(XMP_SET_VOLUME, 0x8);
|
||||
|
||||
|
||||
@@ -672,7 +672,8 @@ dword_result_t NetDll_socket_entry(dword_t caller, dword_t af, dword_t type,
|
||||
socket->Release();
|
||||
|
||||
XThread::SetLastError(socket->GetLastWSAError());
|
||||
XELOGI("NetDll_socket: failed with error");
|
||||
XELOGE("NetDll_socket: failed with error {:08X}",
|
||||
socket->GetLastWSAError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -765,7 +766,8 @@ dword_result_t NetDll_ioctlsocket_entry(dword_t caller, dword_t socket_handle,
|
||||
X_STATUS status = socket->IOControl(cmd, arg_ptr);
|
||||
if (XFAILED(status)) {
|
||||
XThread::SetLastError(socket->GetLastWSAError());
|
||||
XELOGI("NetDll_ioctlsocket: failed");
|
||||
XELOGE("NetDll_ioctlsocket: failed with error {:08X}",
|
||||
socket->GetLastWSAError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1072,7 +1074,6 @@ dword_result_t NetDll_sendto_entry(dword_t caller, dword_t socket_handle,
|
||||
|
||||
N_XSOCKADDR_IN native_to(to_ptr);
|
||||
int ret = socket->SendTo(buf_ptr, buf_len, flags, &native_to, to_len);
|
||||
XELOGD("NetDll_sendto: returned {}", ret);
|
||||
return ret;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(NetDll_sendto, kNetworking, kImplemented);
|
||||
|
||||
@@ -157,7 +157,7 @@ X_STATUS XSocket::SetOption(uint32_t level, uint32_t optname, void* optval_ptr,
|
||||
}
|
||||
|
||||
int ret = setsockopt(native_handle_, native_level, native_optname,
|
||||
(char*)optval_ptr, optlen);
|
||||
static_cast<char*>(optval_ptr), optlen);
|
||||
if (ret < 0) {
|
||||
XELOGE("XSocket::SetOption: setsockopt failed, errno={}", errno);
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
@@ -218,7 +218,7 @@ X_STATUS XSocket::Bind(N_XSOCKADDR_IN* name, int name_len) {
|
||||
// privileges. Remap to port + 10000 to avoid privilege issues.
|
||||
// Note: sin_port is xe::be<uint16_t> which automatically handles endianness,
|
||||
// so we use it directly without ntohs/htons.
|
||||
uint16_t original_port = uint16_t(name->sin_port);
|
||||
const uint16_t original_port = uint16_t(name->sin_port);
|
||||
if (original_port < 1024) {
|
||||
uint16_t new_port = original_port + 10000;
|
||||
name->sin_port = new_port;
|
||||
|
||||
Reference in New Issue
Block a user