mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 17:27:19 +02:00
Music: Favorites takes playlist 0 on the music player's channels only
The Favorites order fix gave Favorites to any channel that asked for playlist 0. That is what the music player asks for when Favorites is chosen, but nothing said another channel could not ask for 0 and mean something else. The channels the music player's own queues pick songs for are now remembered as they are seen, and only those are given Favorites for 0; on any other channel the request goes through as it came. The channel numbers are still the game's: none is written down. A channel's binding was logged once per change, except for a channel past the end of the table, which was logged on every call. Those are no longer logged at all. The binding line now says whether the channel is one of the music player's. The hook on the game's candidate check is removed, with its address: it changed nothing and only logged.
This commit is contained in:
1 parent
a95c542a72
commit
aa08050c8b
4 files changed
+17
-55
No files matched your search
@@ -56,8 +56,6 @@ inline constexpr Fingerprint playback_select_next_contract{0x14f8ed0, {0x48,0x89
|
||||
inline constexpr Fingerprint playback_mode_setter_contract{0x443aa0, {0x44,0x8b,0x91,0xa8,0x00,0x00,0x00,0x4c,0x8b,0x99,0xa0,0x00,0x00,0x00,0x44,0x8b,0xca,0x8b,0xc2,0x33,0xd2,0x49,0xf7,0xf2,0x8b,0xc2,0x49,0x8b,0x04,0xc3,0x48,0x85}};
|
||||
// Native channel-to-playlist binding entrypoint, used by the generated UI/script thunk.
|
||||
inline constexpr Fingerprint playback_channel_playlist_bind_contract{0x8ca6a0, {0x48,0x89,0x5c,0x24,0x08,0x57,0x48,0x83,0xec,0x20,0x48,0x8b,0xda,0x48,0x8b,0xf9,0xe8,0x2b,0xad,0xb6,0xff,0x48,0x85,0xc0,0x74,0x0e,0x4c,0x8b,0xc3,0x48,0x8b,0xd7}};
|
||||
// Candidate-admission callback called by the shared selector; arg4 is its actual channel-map key.
|
||||
inline constexpr Fingerprint playback_candidate_admission_contract{0x43c460, {0x48,0x89,0x5c,0x24,0x08,0x48,0x89,0x6c,0x24,0x10,0x56,0x57,0x41,0x54,0x41,0x56,0x41,0x57,0x48,0x83,0xec,0x30,0x44,0x8b,0x81,0xd0,0x00,0x00,0x00,0x4c,0x8b,0xfa}};
|
||||
inline constexpr std::array<Fingerprint, 7> music_ui_contracts{{
|
||||
music_ui_initialize_contract,
|
||||
{construct_playlist, {0x48,0x89,0x5c,0x24,0x08,0x57,0x48,0x83,0xec,0x20,0x48,0x8b,0xda,0x48,0x8b,0xf9,0x48,0x8d,0x15,0x21,0x95,0x32,0x04,0xe8,0x94,0x30,0x5e,0x00,0x33,0xc9,0x48,0x8d}},
|
||||
|
||||
@@ -20,7 +20,6 @@ using namespace dingosdk::game::build::v20260929;
|
||||
using local_music::playback_mode_setter_contract;
|
||||
using local_music::playback_select_next_contract;
|
||||
using local_music::playback_channel_playlist_bind_contract;
|
||||
using local_music::playback_candidate_admission_contract;
|
||||
using music_playback::CursorPlan;
|
||||
|
||||
std::atomic<std::uintptr_t> image_base{};
|
||||
@@ -29,8 +28,10 @@ std::atomic<bool> playback_available{};
|
||||
MusicSelectNext select_next{};
|
||||
MusicChannelPlaylistBind bind_channel_playlist{};
|
||||
std::array<std::atomic<std::uint64_t>, 256> last_logged_channel_bindings{};
|
||||
MusicCandidateAdmission candidate_admission{};
|
||||
std::array<std::atomic<std::uint8_t>, 256> logged_candidate_admission_results{};
|
||||
// The channels the music player's own queues select for (apply_policy learns them: the game
|
||||
// supplies the numbers, they are not written down here). Only those are ever given Favorites
|
||||
// for a playlist ID of zero: on any other channel zero is left to mean what the game means.
|
||||
std::array<std::atomic<bool>, 256> music_channels{};
|
||||
using SetPlaybackMode = void (__fastcall *)(std::uintptr_t manager, std::uint32_t playlist_id,
|
||||
std::uint32_t mode);
|
||||
SetPlaybackMode set_playback_mode{};
|
||||
@@ -248,6 +249,7 @@ void apply_policy(std::uintptr_t queue, std::uintptr_t playlist_asset) noexcept
|
||||
log_policy_event_once(1u << 2, "{\"event\":\"music_playback_policy_skipped\",\"reason\":\"queue_channel_unavailable\"}");
|
||||
return;
|
||||
}
|
||||
music_channels[channel].store(true, std::memory_order_relaxed);
|
||||
|
||||
std::uintptr_t manager{};
|
||||
if (!read_at(base + local_music::asset_manager, manager) || !manager ||
|
||||
@@ -402,8 +404,7 @@ bool initialize_music_playback(std::uintptr_t base, bool shuffle) noexcept {
|
||||
last_binding_by_channel = {};
|
||||
for (auto& binding : last_logged_channel_bindings)
|
||||
binding.store(std::numeric_limits<std::uint64_t>::max(), std::memory_order_relaxed);
|
||||
for (auto& results : logged_candidate_admission_results)
|
||||
results.store(0, std::memory_order_relaxed);
|
||||
for (auto& known : music_channels) known.store(false, std::memory_order_relaxed);
|
||||
logged_policy_events.store(0, std::memory_order_relaxed);
|
||||
playback_available.store(false, std::memory_order_release);
|
||||
return true;
|
||||
@@ -433,7 +434,10 @@ std::uintptr_t __fastcall music_channel_playlist_bind_hook(std::uintptr_t channe
|
||||
read_at(playlist_id_pointer, requested_playlist_id);
|
||||
auto playlist_id = requested_playlist_id;
|
||||
bool favorites_remapped{};
|
||||
if (have_binding && requested_playlist_id == 0) {
|
||||
// Zero is Favorites only where the music player asks: a channel it has selected songs for.
|
||||
const bool music_channel = have_binding && channel < music_channels.size() &&
|
||||
music_channels[channel].load(std::memory_order_relaxed);
|
||||
if (music_channel && requested_playlist_id == 0) {
|
||||
const auto base = image_base.load(std::memory_order_acquire);
|
||||
std::uintptr_t manager{}, ui_manager{};
|
||||
const bool have_favorites = base &&
|
||||
@@ -456,19 +460,15 @@ std::uintptr_t __fastcall music_channel_playlist_bind_hook(std::uintptr_t channe
|
||||
? bind_channel_playlist(channel_pointer, reinterpret_cast<std::uintptr_t>(&playlist_id))
|
||||
: bind_channel_playlist(channel_pointer, playlist_id_pointer);
|
||||
|
||||
if (have_binding) {
|
||||
// Said once for each change of a channel's binding. A channel outside the table cannot be
|
||||
// told from its last binding, so it is not said at all rather than every time.
|
||||
if (have_binding && channel < last_logged_channel_bindings.size()) {
|
||||
const auto signature = (static_cast<std::uint64_t>(channel) << 32) | playlist_id;
|
||||
bool should_log = true;
|
||||
if (channel < last_logged_channel_bindings.size()) {
|
||||
const auto previous = last_logged_channel_bindings[channel].exchange(
|
||||
signature, std::memory_order_relaxed);
|
||||
should_log = previous != signature;
|
||||
}
|
||||
if (should_log) {
|
||||
char message[224]{};
|
||||
if (last_logged_channel_bindings[channel].exchange(signature, std::memory_order_relaxed) != signature) {
|
||||
char message[256]{};
|
||||
std::snprintf(message, sizeof(message),
|
||||
"{\"event\":\"music_channel_playlist_binding\",\"channel\":%u,\"requested_playlist_id\":%u,\"playlist_id\":%u,\"favorites\":%u,\"favorites_remapped\":%s,\"applied\":%s}",
|
||||
channel, requested_playlist_id, playlist_id, favorites_playlist,
|
||||
"{\"event\":\"music_channel_playlist_binding\",\"channel\":%u,\"music_channel\":%s,\"requested_playlist_id\":%u,\"playlist_id\":%u,\"favorites\":%u,\"favorites_remapped\":%s,\"applied\":%s}",
|
||||
channel, music_channel ? "true" : "false", requested_playlist_id, playlist_id, favorites_playlist,
|
||||
favorites_remapped ? "true" : "false", result ? "true" : "false");
|
||||
dingosdk::logging::event(dingosdk::logging::Channel::music, message);
|
||||
}
|
||||
@@ -476,29 +476,6 @@ std::uintptr_t __fastcall music_channel_playlist_bind_hook(std::uintptr_t channe
|
||||
return result;
|
||||
}
|
||||
|
||||
MusicCandidateAdmission& music_candidate_admission_original() noexcept { return candidate_admission; }
|
||||
|
||||
bool __fastcall music_candidate_admission_hook(std::uintptr_t manager,
|
||||
std::uintptr_t candidate_guid, std::uintptr_t context, std::uint32_t channel_key) {
|
||||
if (!candidate_admission) return false;
|
||||
const bool accepted = candidate_admission(manager, candidate_guid, context, channel_key);
|
||||
const auto result_bit = static_cast<std::uint8_t>(accepted ? 2 : 1);
|
||||
bool should_log = true;
|
||||
if (channel_key < logged_candidate_admission_results.size()) {
|
||||
const auto previous = logged_candidate_admission_results[channel_key].fetch_or(
|
||||
result_bit, std::memory_order_relaxed);
|
||||
should_log = (previous & result_bit) == 0;
|
||||
}
|
||||
if (should_log) {
|
||||
char message[128]{};
|
||||
std::snprintf(message, sizeof(message),
|
||||
"{\"event\":\"music_candidate_admission\",\"channel_key\":%u,\"accepted\":%s}",
|
||||
channel_key, accepted ? "true" : "false");
|
||||
dingosdk::logging::event(dingosdk::logging::Channel::music, message);
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
|
||||
bool music_shuffle_enabled() noexcept { return shuffle_enabled.load(std::memory_order_acquire); }
|
||||
|
||||
void set_music_shuffle_enabled(bool enabled) noexcept {
|
||||
|
||||
@@ -6,8 +6,6 @@ namespace dingosdk::profile_runtime {
|
||||
using MusicSelectNext = std::int32_t (__fastcall *)(std::uintptr_t queue, std::uintptr_t playlist_asset);
|
||||
using MusicChannelPlaylistBind = std::uintptr_t (__fastcall *)(std::uintptr_t channel_pointer,
|
||||
std::uintptr_t playlist_id_pointer);
|
||||
using MusicCandidateAdmission = bool (__fastcall *)(std::uintptr_t manager,
|
||||
std::uintptr_t candidate_guid, std::uintptr_t context, std::uint32_t channel_key);
|
||||
|
||||
// Validate the supported native selector/setter contracts and seed the lock-free
|
||||
// preference read used by the audio selection hook.
|
||||
@@ -20,9 +18,6 @@ std::int32_t __fastcall music_select_next_hook(std::uintptr_t queue, std::uintpt
|
||||
MusicChannelPlaylistBind& music_channel_playlist_bind_original() noexcept;
|
||||
std::uintptr_t __fastcall music_channel_playlist_bind_hook(std::uintptr_t channel_pointer,
|
||||
std::uintptr_t playlist_id_pointer);
|
||||
MusicCandidateAdmission& music_candidate_admission_original() noexcept;
|
||||
bool __fastcall music_candidate_admission_hook(std::uintptr_t manager,
|
||||
std::uintptr_t candidate_guid, std::uintptr_t context, std::uint32_t channel_key);
|
||||
|
||||
bool music_shuffle_enabled() noexcept;
|
||||
void set_music_shuffle_enabled(bool enabled) noexcept;
|
||||
|
||||
@@ -553,14 +553,6 @@ bool initialize_local_profile(std::uintptr_t base, bool authored_offline,
|
||||
&music_channel_playlist_bind_hook, music_channel_playlist_bind_original());
|
||||
else dingosdk::logging::event(dingosdk::logging::Channel::music,
|
||||
"{\"event\":\"music_channel_playlist_binding_contract_mismatch\"}");
|
||||
std::array<unsigned char, 32> admission_bytes{};
|
||||
if (read(base + addr::local_music::playback_candidate_admission_contract.rva,
|
||||
admission_bytes) &&
|
||||
admission_bytes == addr::local_music::playback_candidate_admission_contract.bytes)
|
||||
hook(addr::local_music::playback_candidate_admission_contract,
|
||||
&music_candidate_admission_hook, music_candidate_admission_original());
|
||||
else dingosdk::logging::event(dingosdk::logging::Channel::music,
|
||||
"{\"event\":\"music_candidate_admission_contract_mismatch\"}");
|
||||
hook(addr::local_music::playback_select_next_contract,
|
||||
&music_select_next_hook, music_select_next_original());
|
||||
} else dingosdk::logging::event(dingosdk::logging::Channel::music,
|
||||
|
||||
Reference in new issue
Block a user