From 41b412fa76f2fc4d913af0b74a68208616f205ce Mon Sep 17 00:00:00 2001 From: The-Little-Wolf <116989599+The-Little-Wolf@users.noreply.github.com> Date: Thu, 21 Aug 2025 16:16:32 -0700 Subject: [PATCH] [Xam/XMP App] - Clean up & improvements - Clean up xmp app - XMPGetTitlePlaylistBufferSize now returns proper errors - Implement XMPGetDashInItState - Add missing xnotifications --- src/xenia/apu/audio_media_player.h | 2 + src/xenia/kernel/xam/apps/xmp_app.cc | 285 ++++++++++++--------------- src/xenia/kernel/xam/apps/xmp_app.h | 145 ++++++++++++++ src/xenia/xbox.h | 4 + 4 files changed, 277 insertions(+), 159 deletions(-) diff --git a/src/xenia/apu/audio_media_player.h b/src/xenia/apu/audio_media_player.h index ab5201ad5..4343a8b9d 100644 --- a/src/xenia/apu/audio_media_player.h +++ b/src/xenia/apu/audio_media_player.h @@ -77,6 +77,7 @@ class AudioMediaPlayer { } XmpApp::PlaybackClient GetPlaybackClient() const { return playback_client_; } + uint32_t GetDashInItState() const { return dash_init_state; } bool IsTitleInPlaybackControl() const { return playback_client_ == XmpApp::PlaybackClient::kTitle || @@ -106,6 +107,7 @@ class AudioMediaPlayer { XmpApp::RepeatMode repeat_mode_ = XmpApp::RepeatMode::kPlaylist; XmpApp::PlaybackFlags playback_flags_ = XmpApp::PlaybackFlags::kDefault; float volume_ = 1.0f; + uint32_t dash_init_state = 0; std::unordered_map> playlists_; XmpApp::Playlist* active_playlist_; diff --git a/src/xenia/kernel/xam/apps/xmp_app.cc b/src/xenia/kernel/xam/apps/xmp_app.cc index 6d483ba2a..95176156e 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.cc +++ b/src/xenia/kernel/xam/apps/xmp_app.cc @@ -148,20 +148,46 @@ X_HRESULT XmpApp::XMPPrevious() { return X_E_SUCCESS; } +X_HRESULT XmpApp::XMPGetTitlePlaylistBufferSize(uint32_t xmp_client, + uint32_t song_count, + uint32_t size_ptr) { + /* Note: + - Query of size for XamAlloc - the result of the alloc is passed to + 0x0007000D. + - xmp_client can range from 0 - 6 but will fail on 1 and set size to zero + if its anything other than 0 or 2. + */ + XELOGD( + "XMPGetTitlePlaylistBufferSize(XMP client: 0x{:08X}, Song count: " + "0x{:08X}, Size ptr: 0x{:08X})", + xmp_client, song_count, size_ptr); + + if (xmp_client == 1 || !size_ptr || !song_count) { + return X_E_INVALIDARG; + } + uint32_t size = 0; + if (xmp_client == 0 || xmp_client == 2) { + size = song_count * 0x3E8 + 0x88; + } + // We don't use the storage, so just fudge the number. + xe::store_and_swap(memory_->TranslateVirtual(size_ptr), size); + return X_E_SUCCESS; +} + X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, uint32_t buffer_length) { // NOTE: buffer_length may be zero or valid. auto buffer = memory_->TranslateVirtual(buffer_ptr); switch (message) { case 0x00070002: { - assert_true(!buffer_length || buffer_length == 12); - uint32_t xmp_client = xe::load_and_swap(buffer + 0); - uint32_t storage_ptr = xe::load_and_swap(buffer + 4); - uint32_t song_handle = xe::load_and_swap(buffer + 8); // 0? - uint32_t playlist_handle = - xe::load_and_swap(memory_->TranslateVirtual(storage_ptr)); - assert_true(xmp_client == 0x00000002); - return XMPPlayTitlePlaylist(playlist_handle, song_handle); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_PLAY_TITLE_PLAYLIST)); + XMP_PLAY_TITLE_PLAYLIST* args = + reinterpret_cast(buffer); + uint32_t playlist_handle = xe::load_and_swap( + memory_->TranslateVirtual(args->storage_ptr)); + assert_true(args->xmp_client == 0x00000002); + return XMPPlayTitlePlaylist(playlist_handle, args->song_handle); } case 0x00070003: { assert_true(!buffer_length || buffer_length == 4); @@ -170,11 +196,10 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, return XMPContinue(); } case 0x00070004: { - assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = xe::load_and_swap(buffer + 0); - uint32_t unk = xe::load_and_swap(buffer + 4); - assert_true(xmp_client == 0x00000002); - return XMPStop(unk); + assert_true(!buffer_length || buffer_length == sizeof(XMP_STOP)); + XMP_STOP* args = reinterpret_cast(buffer); + assert_true(args->xmp_client == 0x00000002); + return XMPStop(args->unk); } case 0x00070005: { assert_true(!buffer_length || buffer_length == 4); @@ -195,20 +220,21 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, return XMPPrevious(); } case 0x00070008: { - assert_true(!buffer_length || buffer_length == 16); - struct { - xe::be xmp_client; - xe::be playback_mode; - xe::be repeat_mode; - xe::be flags; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 16); + /* Notes: + - xmp_client == 2 uses kXNotificationXmpPlaybackBehaviorChanged while + the others, excluding 6 (returns X_E_ACCESS_DENIED), use + kXNotificationXmpPlaybackBehaviorChangedEx + */ + assert_true(!buffer_length || + buffer_length == sizeof(XMP_SET_PLAYBACK_BEHAVIOR)); + XMP_SET_PLAYBACK_BEHAVIOR* args = + reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002 || args->xmp_client == 0x00000000); - XELOGD("XMPSetPlaybackBehavior({:08X}, {:08X}, {:08X})", - uint32_t(args->playback_mode), uint32_t(args->repeat_mode), - uint32_t(args->flags)); + XELOGD("XMPSetPlaybackBehavior({:08X}, {:08X}, {:08X}, {:08X})", + uint32_t(args->xmp_client), uint32_t(args->playback_mode), + uint32_t(args->repeat_mode), uint32_t(args->flags)); kernel_state_->emulator()->audio_media_player()->SetPlaybackMode( static_cast(uint32_t(args->playback_mode))); @@ -222,20 +248,14 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, return X_E_SUCCESS; } case 0x00070009: { - assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = xe::load_and_swap(buffer + 0); - uint32_t state_ptr = - xe::load_and_swap(buffer + 4); // out ptr to 4b - expect 0 - assert_true(xmp_client == 0x00000002); - return XMPGetStatus(state_ptr); + assert_true(!buffer_length || buffer_length == sizeof(XMP_GET_STATUS)); + XMP_GET_STATUS* args = reinterpret_cast(buffer); + assert_true(args->xmp_client == 0x00000002); + return XMPGetStatus(args->state_ptr); } case 0x0007000B: { - assert_true(!buffer_length || buffer_length == 8); - struct { - xe::be xmp_client; - xe::be volume_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 8); + assert_true(!buffer_length || buffer_length == sizeof(XMP_GET_VOLUME)); + XMP_GET_VOLUME* args = reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002); XELOGD("XMPGetVolume({:08X})", uint32_t(args->volume_ptr)); @@ -246,12 +266,8 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, return X_E_SUCCESS; } case 0x0007000C: { - assert_true(!buffer_length || buffer_length == 8); - struct { - xe::be xmp_client; - xe::be value; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 8); + assert_true(!buffer_length || buffer_length == sizeof(XMP_SET_VOLUME)); + XMP_SET_VOLUME* args = reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002); XELOGD("XMPSetVolume({:d}, {:g})", args->xmp_client.get(), @@ -261,19 +277,10 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, return X_E_SUCCESS; } case 0x0007000D: { - assert_true(!buffer_length || buffer_length == 36); - struct { - xe::be xmp_client; - xe::be storage_ptr; - xe::be storage_size; - xe::be songs_ptr; - xe::be song_count; - xe::be playlist_name_ptr; - xe::be flags; - xe::be song_handles_ptr; - xe::be playlist_handle_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 36); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_CREATE_TITLE_PLAYLIST)); + XMP_CREATE_TITLE_PLAYLIST* args = + reinterpret_cast(buffer); xe::store_and_swap( memory_->TranslateVirtual(args->playlist_handle_ptr), @@ -294,13 +301,10 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, args->storage_ptr); } case 0x0007000E: { - assert_true(!buffer_length || buffer_length == 12); - struct { - xe::be xmp_client; - xe::be unk_ptr; // 0 - xe::be info_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 12); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_GET_CURRENT_SONG)); + XMP_GET_CURRENT_SONG* args = + reinterpret_cast(buffer); auto info = memory_->TranslateVirtual(args->info_ptr); assert_true(args->xmp_client == 0x00000002); @@ -330,12 +334,10 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, return X_E_SUCCESS; } case 0x00070013: { - assert_true(!buffer_length || buffer_length == 8); - struct { - xe::be xmp_client; - xe::be storage_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 8); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_DELETE_TITLE_PLAYLIST)); + XMP_DELETE_TITLE_PLAYLIST* args = + reinterpret_cast(buffer); uint32_t playlist_handle = xe::load_and_swap( memory_->TranslateVirtual(args->storage_ptr)); @@ -345,19 +347,17 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, } case 0x0007001A: { // XMPSetPlaybackController - assert_true(!buffer_length || buffer_length == 12); - struct { - xe::be xmp_client; - xe::be controller; - xe::be playback_client; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 12); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_SET_PLAYBACK_CONTROLLER)); + XMP_SET_PLAYBACK_CONTROLLER* args = + reinterpret_cast(buffer); assert_true( (args->xmp_client == 0x00000002 && args->controller == 0x00000000) || (args->xmp_client == 0x00000000 && args->controller == 0x00000001)); - XELOGD("XMPSetPlaybackController({:08X}, {:08X})", - uint32_t(args->controller), uint32_t(args->playback_client)); + XELOGD("XMPSetPlaybackController({:08X}, {:08X}, {:08X})", + uint32_t(args->xmp_client), uint32_t(args->controller), + uint32_t(args->playback_client)); kernel_state_->emulator()->audio_media_player()->SetPlaybackClient( PlaybackClient(uint32_t(args->playback_client))); @@ -371,13 +371,10 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, } case 0x0007001B: { // XMPGetPlaybackController - assert_true(!buffer_length || buffer_length == 12); - struct { - xe::be xmp_client; - xe::be controller_ptr; - xe::be locked_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 12); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_GET_PLAYBACK_CONTROLLER)); + XMP_GET_PLAYBACK_CONTROLLER* args = + reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002); XELOGD("XMPGetPlaybackController({:08X}, {:08X}, {:08X})", @@ -401,23 +398,26 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, // Return buffer size is set to be items * 0x338 bytes. // Games used in: // 54540809, 494707D4 + XMP_CREATE_USER_PLAYLIST_ENUMERATOR* args = + reinterpret_cast(buffer); + + XELOGD("XMPSetPlaybackController({:08X}, {:08X}, {:08X})", + uint32_t(args->xmp_client), uint32_t(args->flags), + uint32_t(args->unk_ptr)); return X_E_SUCCESS; } case 0x00070029: { // XMPGetPlaybackBehavior - assert_true(!buffer_length || buffer_length == 16); - struct { - xe::be xmp_client; - xe::be playback_mode_ptr; - xe::be repeat_mode_ptr; - xe::be playback_flags_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 16); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_GET_PLAYBACK_BEHAVIOR)); + XMP_GET_PLAYBACK_BEHAVIOR* args = + reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002 || args->xmp_client == 0x00000000); - XELOGD("XMPGetPlaybackBehavior({:08X}, {:08X}, {:08X})", - uint32_t(args->playback_mode_ptr), uint32_t(args->repeat_mode_ptr), + XELOGD("XMPGetPlaybackBehavior({:08X}, {:08X}, {:08X}, {:08X})", + uint32_t(args->xmp_client), uint32_t(args->playback_mode_ptr), + uint32_t(args->repeat_mode_ptr), uint32_t(args->playback_flags_ptr)); if (args->playback_mode_ptr) { xe::store_and_swap( @@ -446,76 +446,49 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, // XMPGetMediaSources // Called on the NXE and Kinect dashboard after clicking on the picture, // video, and music library - assert_true(!buffer_length || buffer_length == 20); - struct { - xe::be xmp_client; - xe::be unk1; - xe::be unk2; - xe::be unk3; - xe::be unk4; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 20); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_GET_MEDIA_SOURCES)); + XMP_GET_MEDIA_SOURCES* args = + reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002 || args->xmp_client == 0x00000000); XELOGD( "XMPGetMediaSources({:08X}, {:08X}, {:08X}, {:08X}, {:08X}), " "unimplemented", - args->xmp_client.get(), args->unk1.get(), args->unk2.get(), - args->unk3.get(), args->unk4.get()); + args->xmp_client.get(), args->unk1.get(), args->unk1_ptr.get(), + args->unk2.get(), args->unk2_ptr.get()); return X_E_INVALIDARG; } case 0x0007002E: { - assert_true(!buffer_length || buffer_length == 12); - // Query of size for XamAlloc - the result of the alloc is passed to - // 0x0007000D. - struct { - xe::be xmp_client; - xe::be song_count; - xe::be size_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 12); - - assert_true(args->xmp_client == 0x00000002 || - args->xmp_client == 0x00000000); - // We don't use the storage, so just fudge the number. - xe::store_and_swap(memory_->TranslateVirtual(args->size_ptr), - args->song_count * 0x3E8 + 0x88); - return X_E_SUCCESS; + assert_true(!buffer_length || + buffer_length == sizeof(XMP_GET_TITLE_PLAYLIST_BUFFER_SIZE)); + XMP_GET_TITLE_PLAYLIST_BUFFER_SIZE* args = + reinterpret_cast(buffer); + return XMPGetTitlePlaylistBufferSize(args->xmp_client, args->song_count, + args->size_ptr); } case 0x0007002F: { // XMPDashInIt // Called on the start up of all dashboard versions before kinect - assert_true(!buffer_length || buffer_length == 24); - struct { - xe::be xmp_client; - xe::be unk1; - xe::be unk2; - xe::be unk3; - xe::be unk4; - xe::be storage_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 24); + assert_true(!buffer_length || buffer_length == sizeof(XMP_DASH_INIT)); + XMP_DASH_INIT* args = reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002 || args->xmp_client == 0x00000000); XELOGD( "XMPDashInIt({:08X}, {:08X}, {:08X}, {:08X}, {:08X}, {:08X}), " "unimplemented", - args->xmp_client.get(), args->unk1.get(), args->unk2.get(), - args->unk3.get(), args->unk4.get(), args->storage_ptr.get()); + args->xmp_client.get(), args->buffer_ptr.get(), + args->buffer_length.get(), args->unk1.get(), args->unk2.get(), + args->storage_ptr.get()); return X_E_INVALIDARG; } case 0x0007003D: { // XMPCaptureOutput - assert_true(!buffer_length || buffer_length == 16); - struct { - xe::be xmp_client; - xe::be callback; - xe::be context; - xe::be title_render; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 16); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_CAPTURE_OUTPUT)); + XMP_CAPTURE_OUTPUT* args = reinterpret_cast(buffer); XELOGD("XMPCaptureOutput({:08X}, {:08X}, {:08X}, {:08X})", args->xmp_client.get(), args->callback.get(), args->context.get(), @@ -529,16 +502,13 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, // Called on the start up of all dashboard versions before kinect // When it returns X_E_INVALIDARG you can access the music player up to // version 5787 - assert_true(!buffer_length || buffer_length == 16); - struct { - xe::be xmp_client; - xe::be unk1; - xe::be storage_ptr; - xe::be unk2; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 16); + assert_true(!buffer_length || + buffer_length == sizeof(XMP_SET_MEDIA_SOURCE_WORKSPACE)); + XMP_SET_MEDIA_SOURCE_WORKSPACE* args = + reinterpret_cast(buffer); assert_true(args->xmp_client == 0x00000002 || + args->xmp_client == 0x00000001 || args->xmp_client == 0x00000000); XELOGD( "XMPSetMediaSourceWorkspace({:08X}, {:08X}, {:08X}, {:08X}), " @@ -550,17 +520,14 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, case 0x00070053: { // Called on the blades dashboard Version 4532-5787 after clicking on the // picture or video library. It only receives buffer - // *unk1_ptr = to some unknown value - struct { - xe::be xmp_client; - xe::be unk1_ptr; - }* args = memory_->TranslateVirtual(buffer_ptr); - static_assert_size(decltype(*args), 8); + XMP_GET_DASH_INIT_STATE* args = + reinterpret_cast(buffer); + XELOGD("XMPGetDashInItState({:08X}, {:08X})", args->xmp_client.get(), + args->dash_init_state_ptr.get()); - assert_true(args->xmp_client == 0x00000002 || - args->xmp_client == 0x00000000); - XELOGD("XMPUnk70053({:08X}, {:08X}), unimplemented", - args->xmp_client.get(), args->unk1_ptr.get()); + xe::store_and_swap( + memory_->TranslateVirtual(args->dash_init_state_ptr), + kernel_state_->emulator()->audio_media_player()->GetDashInItState()); return X_E_SUCCESS; } } diff --git a/src/xenia/kernel/xam/apps/xmp_app.h b/src/xenia/kernel/xam/apps/xmp_app.h index ddea2251d..b0324fd81 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.h +++ b/src/xenia/kernel/xam/apps/xmp_app.h @@ -51,6 +51,148 @@ struct XMP_SONGINFO { }; static_assert_size(XMP_SONGINFO, 988); +struct XMP_PLAY_TITLE_PLAYLIST { + xe::be xmp_client; + xe::be storage_ptr; + xe::be song_handle; +}; +static_assert_size(XMP_PLAY_TITLE_PLAYLIST, 0xC); + +struct XMP_STOP { + xe::be xmp_client; + xe::be unk; +}; +static_assert_size(XMP_STOP, 0x8); + +struct XMP_SET_PLAYBACK_BEHAVIOR { + xe::be xmp_client; + xe::be playback_mode; + xe::be repeat_mode; + xe::be flags; +}; +static_assert_size(XMP_SET_PLAYBACK_BEHAVIOR, 0x10); + +struct XMP_GET_STATUS { + xe::be xmp_client; + xe::be state_ptr; +}; +static_assert_size(XMP_GET_STATUS, 0x8); + +struct XMP_GET_VOLUME { + xe::be xmp_client; + xe::be volume_ptr; +}; +static_assert_size(XMP_GET_VOLUME, 0x8); + +struct XMP_SET_VOLUME { + xe::be xmp_client; + xe::be value; +}; +static_assert_size(XMP_SET_VOLUME, 0x8); + +struct XMP_CREATE_TITLE_PLAYLIST { + xe::be xmp_client; + xe::be storage_ptr; + xe::be storage_size; + xe::be songs_ptr; + xe::be song_count; + xe::be playlist_name_ptr; + xe::be flags; + xe::be song_handles_ptr; + xe::be playlist_handle_ptr; +}; +static_assert_size(XMP_CREATE_TITLE_PLAYLIST, 0x24); + +struct XMP_GET_CURRENT_SONG { + xe::be xmp_client; + xe::be unk_ptr; + xe::be info_ptr; +}; +static_assert_size(XMP_GET_CURRENT_SONG, 0xC); + +struct XMP_DELETE_TITLE_PLAYLIST { + xe::be xmp_client; + xe::be storage_ptr; +}; +static_assert_size(XMP_DELETE_TITLE_PLAYLIST, 0x8); + +struct XMP_SET_PLAYBACK_CONTROLLER { + xe::be xmp_client; + xe::be controller; + xe::be playback_client; +}; +static_assert_size(XMP_SET_PLAYBACK_CONTROLLER, 0xC); + +struct XMP_GET_PLAYBACK_CONTROLLER { + xe::be xmp_client; + xe::be controller_ptr; + xe::be locked_ptr; +}; +static_assert_size(XMP_GET_PLAYBACK_CONTROLLER, 0xC); + +struct XMP_CREATE_USER_PLAYLIST_ENUMERATOR { + xe::be xmp_client; + xe::be flags; + xe::be unk_ptr; +}; +static_assert_size(XMP_CREATE_USER_PLAYLIST_ENUMERATOR, 0xC); + +struct XMP_GET_PLAYBACK_BEHAVIOR { + xe::be xmp_client; + xe::be playback_mode_ptr; + xe::be repeat_mode_ptr; + xe::be playback_flags_ptr; +}; +static_assert_size(XMP_GET_PLAYBACK_BEHAVIOR, 0x10); + +struct XMP_GET_MEDIA_SOURCES { + xe::be xmp_client; + xe::be unk1; + xe::be unk1_ptr; + xe::be unk2; + xe::be unk2_ptr; +}; +static_assert_size(XMP_GET_MEDIA_SOURCES, 0x14); + +struct XMP_GET_TITLE_PLAYLIST_BUFFER_SIZE { + xe::be xmp_client; + xe::be song_count; + xe::be size_ptr; +}; +static_assert_size(XMP_GET_TITLE_PLAYLIST_BUFFER_SIZE, 0xC); + +struct XMP_DASH_INIT { + xe::be xmp_client; + xe::be buffer_ptr; // used by XamEnumerate + xe::be buffer_length; // used by XamEnumerate + xe::be unk1; + xe::be unk2; + xe::be storage_ptr; +}; +static_assert_size(XMP_DASH_INIT, 0x18); + +struct XMP_CAPTURE_OUTPUT { + xe::be xmp_client; + xe::be callback; + xe::be context; + xe::be title_render; +}; +static_assert_size(XMP_CAPTURE_OUTPUT, 0x10); + +struct XMP_SET_MEDIA_SOURCE_WORKSPACE { + xe::be xmp_client; + xe::be unk1; + xe::be storage_ptr; + xe::be unk2; +}; +static_assert_size(XMP_SET_MEDIA_SOURCE_WORKSPACE, 0x10); + +struct XMP_GET_DASH_INIT_STATE { + xe::be xmp_client; + xe::be dash_init_state_ptr; +}; +static_assert_size(XMP_GET_DASH_INIT_STATE, 0x8); + class XmpApp : public App { public: enum class State : uint32_t { @@ -115,6 +257,9 @@ class XmpApp : public App { X_HRESULT XMPPause(); X_HRESULT XMPNext(); X_HRESULT XMPPrevious(); + X_HRESULT XMPGetTitlePlaylistBufferSize(uint32_t xmp_client, + uint32_t song_count, + uint32_t storage_ptr); X_HRESULT DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, uint32_t buffer_length) override; diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 087f43356..3b6b6f76c 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -122,10 +122,12 @@ typedef uint32_t X_HRESULT; #define X_E_NOT_IMPLEMENTED static_cast(0x80004001L) #define X_E_FAIL static_cast(0x80004005L) #define X_E_NO_MORE_FILES X_HRESULT_FROM_WIN32(X_ERROR_NO_MORE_FILES) +#define X_E_NOT_SUPPORTED X_HRESULT_FROM_WIN32(X_ERROR_NOT_SUPPORTED) #define X_E_INVALIDARG X_HRESULT_FROM_WIN32(X_ERROR_INVALID_PARAMETER) #define X_E_DEVICE_NOT_CONNECTED X_HRESULT_FROM_WIN32(X_ERROR_DEVICE_NOT_CONNECTED) #define X_E_NOTFOUND X_HRESULT_FROM_WIN32(X_ERROR_NOT_FOUND) #define X_E_NO_SUCH_USER X_HRESULT_FROM_WIN32(X_ERROR_NO_SUCH_USER) +#define X_E_FUNCTION_FAILED X_HRESULT_FROM_WIN32(X_ERROR_FUNCTION_FAILED) // Sockets/networking. #define X_INVALID_SOCKET (uint32_t)(~0) @@ -257,6 +259,8 @@ enum : XNotificationID { kXNotificationXmpTitlePlayListContentChanged = 0x8A000005, kXNotificationXmpLocalMediaContentChanged = 0x8A000006, kXNotificationXmpDashNowPlayingQueueModeChanged = 0x8A000007, + kXNotificationXmpDashInItChanged = 0x8A000009, + kXNotificationXmpPlaybackBehaviorChangedEx = 0x8A00000A, // XNotification Party kXNotificationPartyMembersChanged = 0x0E040002,