Starting to properly attribute virtual vs. physical memory accesses.

This commit is contained in:
Ben Vanik
2015-03-29 11:11:35 -07:00
parent ab90e0932b
commit ec84a688e9
42 changed files with 346 additions and 372 deletions

View File

@@ -22,6 +22,7 @@ XXGIApp::XXGIApp(KernelState* kernel_state) : XApp(kernel_state, 0xFB) {}
X_RESULT XXGIApp::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 0x000B0006: {
assert_true(!buffer_length || buffer_length == 24);
@@ -30,35 +31,26 @@ X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
// qword 0
// dword r4 context enum
// dword r5 value
uint32_t user_index =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t context_id =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
uint32_t context_value =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t context_id = poly::load_and_swap<uint32_t>(buffer + 16);
uint32_t context_value = poly::load_and_swap<uint32_t>(buffer + 20);
XELOGD("XUserSetContextEx(%.8X, %.8X, %.8X)", user_index, context_id,
context_value);
return X_ERROR_SUCCESS;
}
case 0x000B0007: {
uint32_t user_index =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t property_id =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
uint32_t value_size =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
uint32_t value_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 24);
uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t property_id = poly::load_and_swap<uint32_t>(buffer + 16);
uint32_t value_size = poly::load_and_swap<uint32_t>(buffer + 20);
uint32_t value_ptr = poly::load_and_swap<uint32_t>(buffer + 24);
XELOGD("XUserSetPropertyEx(%.8X, %.8X, %d, %.8X)", user_index,
property_id, value_size, value_ptr);
return X_ERROR_SUCCESS;
}
case 0x000B0008: {
assert_true(!buffer_length || buffer_length == 8);
uint32_t achievement_count =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t achievements_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t achievement_count = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t achievements_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
XELOGD("XUserWriteAchievements(%.8X, %.8X)", achievement_count,
achievements_ptr);
return X_ERROR_SUCCESS;
@@ -76,16 +68,14 @@ X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
case 0x000B0041: {
assert_true(!buffer_length || buffer_length == 32);
// 00000000 2789fecc 00000000 00000000 200491e0 00000000 200491f0 20049340
uint32_t user_index =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t context_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
uint32_t context_id =
poly::load_and_swap<uint32_t>(membase_ + context_ptr + 0);
uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t context_ptr = poly::load_and_swap<uint32_t>(buffer + 16);
auto context = memory_->TranslateVirtual(context_ptr);
uint32_t context_id = poly::load_and_swap<uint32_t>(context + 0);
XELOGD("XUserGetContext(%.8X, %.8X(%.8X))", user_index, context_ptr,
context_id);
uint32_t value = 0;
poly::store_and_swap<uint32_t>(membase_ + context_ptr + 4, value);
poly::store_and_swap<uint32_t>(context + 4, value);
return X_ERROR_SUCCESS;
}
case 0x000B0071: {

View File

@@ -24,12 +24,13 @@ X_RESULT XXLiveBaseApp::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 0x00058004: {
// Called on startup, seems to just return a bool in the buffer.
assert_true(!buffer_length || buffer_length == 4);
XELOGD("XLiveBaseGetLogonId(%.8X)", buffer_ptr);
poly::store_and_swap<uint32_t>(membase_ + buffer_ptr + 0, 1); // ?
poly::store_and_swap<uint32_t>(buffer + 0, 1); // ?
return X_ERROR_SUCCESS;
}
case 0x00058020: {

View File

@@ -34,7 +34,7 @@ X_RESULT XXMPApp::XMPGetStatus(uint32_t state_ptr) {
Sleep(1);
XELOGD("XMPGetStatus(%.8X)", state_ptr);
poly::store_and_swap<uint32_t>(membase_ + state_ptr,
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(state_ptr),
static_cast<uint32_t>(state_));
return X_ERROR_SUCCESS;
}
@@ -54,30 +54,32 @@ X_RESULT XXMPApp::XMPCreateTitlePlaylist(
for (uint32_t i = 0; i < song_count; ++i) {
auto song = std::make_unique<Song>();
song->handle = ++next_song_handle_;
uint8_t* song_base = membase_ + songs_ptr + (i * 36);
song->file_path = poly::load_and_swap<std::wstring>(
membase_ + poly::load_and_swap<uint32_t>(song_base + 0));
song->name = poly::load_and_swap<std::wstring>(
membase_ + poly::load_and_swap<uint32_t>(song_base + 4));
song->artist = poly::load_and_swap<std::wstring>(
membase_ + poly::load_and_swap<uint32_t>(song_base + 8));
song->album = poly::load_and_swap<std::wstring>(
membase_ + poly::load_and_swap<uint32_t>(song_base + 12));
song->album_artist = poly::load_and_swap<std::wstring>(
membase_ + poly::load_and_swap<uint32_t>(song_base + 16));
song->genre = poly::load_and_swap<std::wstring>(
membase_ + poly::load_and_swap<uint32_t>(song_base + 20));
uint8_t* song_base = memory_->TranslateVirtual(songs_ptr + (i * 36));
song->file_path =
poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 0)));
song->name = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 4)));
song->artist = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 8)));
song->album = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 12)));
song->album_artist =
poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 16)));
song->genre = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 20)));
song->track_number = poly::load_and_swap<uint32_t>(song_base + 24);
song->duration_ms = poly::load_and_swap<uint32_t>(song_base + 28);
song->format = static_cast<Song::Format>(
poly::load_and_swap<uint32_t>(song_base + 32));
if (out_song_handles) {
poly::store_and_swap<uint32_t>(membase_ + out_song_handles + (i * 4),
song->handle);
poly::store_and_swap<uint32_t>(
memory_->TranslateVirtual(out_song_handles + (i * 4)), song->handle);
}
playlist->songs.emplace_back(std::move(song));
}
poly::store_and_swap<uint32_t>(membase_ + out_playlist_handle,
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(out_playlist_handle),
playlist->handle);
std::lock_guard<std::mutex> lock(mutex_);
@@ -195,64 +197,53 @@ void XXMPApp::OnStateChanged() {
X_RESULT XXMPApp::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 =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t playlist_handle =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t song_handle =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8); // 0?
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t playlist_handle = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t song_handle = poly::load_and_swap<uint32_t>(buffer + 8); // 0?
assert_true(xmp_client == 0x00000002);
return XMPPlayTitlePlaylist(playlist_handle, song_handle);
}
case 0x00070003: {
assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
assert_true(xmp_client == 0x00000002);
return XMPContinue();
}
case 0x00070004: {
assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t unk = poly::load_and_swap<uint32_t>(buffer + 4);
assert_true(xmp_client == 0x00000002);
return XMPStop(unk);
}
case 0x00070005: {
assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
assert_true(xmp_client == 0x00000002);
return XMPPause();
}
case 0x00070006: {
assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
assert_true(xmp_client == 0x00000002);
return XMPNext();
}
case 0x00070007: {
assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
assert_true(xmp_client == 0x00000002);
return XMPPrevious();
}
case 0x00070008: {
assert_true(!buffer_length || buffer_length == 16);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t playback_mode =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t repeat_mode =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t flags =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t playback_mode = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t repeat_mode = poly::load_and_swap<uint32_t>(buffer + 8);
uint32_t flags = poly::load_and_swap<uint32_t>(buffer + 12);
assert_true(xmp_client == 0x00000002);
XELOGD("XMPSetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode,
repeat_mode, flags);
@@ -264,29 +255,27 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
}
case 0x00070009: {
assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t state_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
buffer + 4); // out ptr to 4b - expect 0
assert_true(xmp_client == 0x00000002);
return XMPGetStatus(state_ptr);
}
case 0x0007000B: {
assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t float_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - floating point
buffer + 4); // out ptr to 4b - floating point
assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetVolume(%.8X)", float_ptr);
poly::store_and_swap<float>(membase_ + float_ptr, volume_);
poly::store_and_swap<float>(memory_->TranslateVirtual(float_ptr),
volume_);
return X_ERROR_SUCCESS;
}
case 0x0007000C: {
assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
float float_value = poly::load_and_swap<float>(membase_ + buffer_ptr + 4);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
float float_value = poly::load_and_swap<float>(buffer + 4);
assert_true(xmp_client == 0x00000002);
XELOGD("XMPSetVolume(%g)", float_value);
volume_ = float_value;
@@ -294,27 +283,19 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
}
case 0x0007000D: {
assert_true(!buffer_length || buffer_length == 36);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t dummy_alloc_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t dummy_alloc_size =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t songs_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
uint32_t song_count =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
uint32_t playlist_name_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
uint32_t flags =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 24);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t dummy_alloc_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t dummy_alloc_size = poly::load_and_swap<uint32_t>(buffer + 8);
uint32_t songs_ptr = poly::load_and_swap<uint32_t>(buffer + 12);
uint32_t song_count = poly::load_and_swap<uint32_t>(buffer + 16);
uint32_t playlist_name_ptr = poly::load_and_swap<uint32_t>(buffer + 20);
uint32_t flags = poly::load_and_swap<uint32_t>(buffer + 24);
uint32_t song_handles_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 28); // 0?
uint32_t playlist_handle_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 32);
poly::load_and_swap<uint32_t>(buffer + 28); // 0?
uint32_t playlist_handle_ptr = poly::load_and_swap<uint32_t>(buffer + 32);
assert_true(xmp_client == 0x00000002);
auto playlist_name =
poly::load_and_swap<std::wstring>(membase_ + playlist_name_ptr);
auto playlist_name = poly::load_and_swap<std::wstring>(
memory_->TranslateVirtual(playlist_name_ptr));
// dummy_alloc_ptr is the result of a XamAlloc of dummy_alloc_size.
assert_true(dummy_alloc_size == song_count * 128);
return XMPCreateTitlePlaylist(songs_ptr, song_count, playlist_name_ptr,
@@ -323,12 +304,10 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
}
case 0x0007000E: {
assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t unk_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); // 0
uint32_t info_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t unk_ptr = poly::load_and_swap<uint32_t>(buffer + 4); // 0
uint32_t info_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
auto info = memory_->TranslateVirtual(info_ptr);
assert_true(xmp_client == 0x00000002);
assert_zero(unk_ptr);
XELOGE("XMPGetInfo?(%.8X, %.8X)", unk_ptr, info_ptr);
@@ -336,41 +315,31 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
return X_ERROR_NOT_FOUND;
}
auto& song = active_playlist_->songs[active_song_index_];
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 0, song->handle);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 0,
song->name);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 40,
song->artist);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 80,
song->album);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 120,
poly::store_and_swap<uint32_t>(info + 0, song->handle);
poly::store_and_swap<std::wstring>(info + 4 + 572 + 0, song->name);
poly::store_and_swap<std::wstring>(info + 4 + 572 + 40, song->artist);
poly::store_and_swap<std::wstring>(info + 4 + 572 + 80, song->album);
poly::store_and_swap<std::wstring>(info + 4 + 572 + 120,
song->album_artist);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 160,
song->genre);
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 200,
song->track_number);
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 204,
song->duration_ms);
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 208,
poly::store_and_swap<std::wstring>(info + 4 + 572 + 160, song->genre);
poly::store_and_swap<uint32_t>(info + 4 + 572 + 200, song->track_number);
poly::store_and_swap<uint32_t>(info + 4 + 572 + 204, song->duration_ms);
poly::store_and_swap<uint32_t>(info + 4 + 572 + 208,
static_cast<uint32_t>(song->format));
return X_ERROR_SUCCESS;
}
case 0x00070013: {
assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t playlist_handle =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t playlist_handle = poly::load_and_swap<uint32_t>(buffer + 4);
assert_true(xmp_client == 0x00000002);
return XMPDeleteTitlePlaylist(playlist_handle);
}
case 0x0007001A: {
assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t unk1 = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t enabled =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t unk1 = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t enabled = poly::load_and_swap<uint32_t>(buffer + 8);
assert_true(xmp_client == 0x00000002);
assert_zero(unk1);
XELOGD("XMPSetEnabled(%.8X, %.8X)", unk1, enabled);
@@ -383,53 +352,49 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
}
case 0x0007001B: {
assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t unk_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
buffer + 4); // out ptr to 4b - expect 0
uint32_t disabled_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 8); // out ptr to 4b - expect 1 (to skip)
buffer + 8); // out ptr to 4b - expect 1 (to skip)
assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetEnabled(%.8X, %.8X)", unk_ptr, disabled_ptr);
poly::store_and_swap<uint32_t>(membase_ + unk_ptr, 0);
poly::store_and_swap<uint32_t>(membase_ + disabled_ptr, disabled_);
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(unk_ptr), 0);
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(disabled_ptr),
disabled_);
// Atrain spawns a thread 82437FD0 to call this in a tight loop forever.
poly::threading::Sleep(std::chrono::milliseconds(10));
return X_ERROR_SUCCESS;
}
case 0x00070029: {
assert_true(!buffer_length || buffer_length == 16);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t playback_mode_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t repeat_mode_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t unk3_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t playback_mode_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t repeat_mode_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
uint32_t unk3_ptr = poly::load_and_swap<uint32_t>(buffer + 12);
assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode_ptr,
repeat_mode_ptr, unk3_ptr);
poly::store_and_swap<uint32_t>(membase_ + playback_mode_ptr,
static_cast<uint32_t>(playback_mode_));
poly::store_and_swap<uint32_t>(membase_ + repeat_mode_ptr,
poly::store_and_swap<uint32_t>(
memory_->TranslateVirtual(playback_mode_ptr),
static_cast<uint32_t>(playback_mode_));
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(repeat_mode_ptr),
static_cast<uint32_t>(repeat_mode_));
poly::store_and_swap<uint32_t>(membase_ + unk3_ptr, unknown_flags_);
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(unk3_ptr),
unknown_flags_);
return X_ERROR_SUCCESS;
}
case 0x0007002E: {
assert_true(!buffer_length || buffer_length == 12);
// Query of size for XamAlloc - the result of the alloc is passed to
// 0x0007000D.
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t song_count =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t size_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
uint32_t song_count = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t size_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
assert_true(xmp_client == 0x00000002);
// We don't use the storage, so just fudge the number.
poly::store_and_swap<uint32_t>(membase_ + size_ptr, song_count * 128);
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(size_ptr),
song_count * 128);
return X_ERROR_SUCCESS;
}
case 0x0007003D: {