Digging into XMP stuff. Wish these were just normal functions.

This commit is contained in:
Ben Vanik 2015-01-10 21:36:46 -08:00
parent cf31969510
commit f5e12eba76
4 changed files with 228 additions and 79 deletions

View File

@ -26,12 +26,13 @@ void XAppManager::RegisterApp(std::unique_ptr<XApp> app) {
} }
X_RESULT XAppManager::DispatchMessageSync(uint32_t app_id, uint32_t message, X_RESULT XAppManager::DispatchMessageSync(uint32_t app_id, uint32_t message,
uint32_t arg1, uint32_t arg2) { uint32_t buffer_ptr,
uint32_t buffer_length) {
const auto& it = app_lookup_.find(app_id); const auto& it = app_lookup_.find(app_id);
if (it == app_lookup_.end()) { if (it == app_lookup_.end()) {
return X_ERROR_NOT_FOUND; return X_ERROR_NOT_FOUND;
} }
return it->second->DispatchMessageSync(message, arg1, arg2); return it->second->DispatchMessageSync(message, buffer_ptr, buffer_length);
} }
X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message, X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message,
@ -41,7 +42,7 @@ X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message,
if (it == app_lookup_.end()) { if (it == app_lookup_.end()) {
return X_ERROR_NOT_FOUND; return X_ERROR_NOT_FOUND;
} }
return it->second->DispatchMessageAsync(message, buffer_ptr, buffer_length); return it->second->DispatchMessageSync(message, buffer_ptr, buffer_length);
} }
} // namespace kernel } // namespace kernel

View File

@ -26,10 +26,8 @@ class XApp {
public: public:
uint32_t app_id() const { return app_id_; } uint32_t app_id() const { return app_id_; }
virtual X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1, virtual X_RESULT DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
uint32_t arg2) = 0; uint32_t buffer_length) = 0;
virtual X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
size_t buffer_length) = 0;
protected: protected:
XApp(KernelState* kernel_state, uint32_t app_id); XApp(KernelState* kernel_state, uint32_t app_id);
@ -43,8 +41,8 @@ class XAppManager {
public: public:
void RegisterApp(std::unique_ptr<XApp> app); void RegisterApp(std::unique_ptr<XApp> app);
X_RESULT DispatchMessageSync(uint32_t app_id, uint32_t message, uint32_t arg1, X_RESULT DispatchMessageSync(uint32_t app_id, uint32_t message,
uint32_t arg2); uint32_t buffer_ptr, uint32_t buffer_length);
X_RESULT DispatchMessageAsync(uint32_t app_id, uint32_t message, X_RESULT DispatchMessageAsync(uint32_t app_id, uint32_t message,
uint32_t buffer_ptr, size_t buffer_length); uint32_t buffer_ptr, size_t buffer_length);

View File

@ -13,91 +13,219 @@ namespace xe {
namespace kernel { namespace kernel {
namespace apps { namespace apps {
X_RESULT XXMPApp::XMPGetStatus(uint32_t unk, uint32_t status_ptr) { XXMPApp::XXMPApp(KernelState* kernel_state)
: XApp(kernel_state, 0xFA),
status_(Status::kStopped),
disabled_(0),
unknown_state1_(0),
unknown_state2_(0),
unknown_flags_(0),
unknown_float_(0.0f) {}
X_RESULT XXMPApp::XMPGetStatus(uint32_t status_ptr) {
// Some stupid games will hammer this on a thread - induce a delay // Some stupid games will hammer this on a thread - induce a delay
// here to keep from starving real threads. // here to keep from starving real threads.
Sleep(1); Sleep(1);
XELOGD("XMPGetStatus(%.8X, %.8X)", unk, status_ptr); XELOGD("XMPGetStatus(%.8X)", status_ptr);
poly::store_and_swap<uint32_t>(membase_ + status_ptr,
assert_true(unk == 2); static_cast<uint32_t>(status_));
poly::store_and_swap<uint32_t>(membase_ + status_ptr, 0); OnStatusChanged();
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
X_RESULT XXMPApp::XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr, X_RESULT XXMPApp::XMPContinue() {
uint32_t disabled_ptr) { XELOGD("XMPContinue()");
// Some stupid games will hammer this on a thread - induce a delay if (status_ == Status::kPaused) {
// here to keep from starving real threads. status_ = Status::kPlaying;
Sleep(10); }
OnStatusChanged();
XELOGD("XMPGetStatusEx(%.8X, %.8X, %.8X)", unk, unk_ptr, disabled_ptr);
assert_true(unk == 2);
poly::store_and_swap<uint32_t>(membase_ + unk_ptr, 0);
poly::store_and_swap<uint32_t>(membase_ + disabled_ptr, 1);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t arg1, X_RESULT XXMPApp::XMPStop(uint32_t unk) {
uint32_t arg2) { assert_zero(unk);
XELOGD("XMPStop(%.8X)", unk);
status_ = Status::kStopped;
OnStatusChanged();
return X_ERROR_SUCCESS;
}
X_RESULT XXMPApp::XMPPause() {
XELOGD("XMPPause()");
if (status_ == Status::kPlaying) {
status_ = Status::kPaused;
}
OnStatusChanged();
return X_ERROR_SUCCESS;
}
X_RESULT XXMPApp::XMPNext() {
XELOGD("XMPNext()");
status_ = Status::kPlaying;
OnStatusChanged();
return X_ERROR_SUCCESS;
}
X_RESULT XXMPApp::XMPPrevious() {
XELOGD("XMPPrevious()");
status_ = Status::kPlaying;
OnStatusChanged();
return X_ERROR_SUCCESS;
}
void XXMPApp::OnStatusChanged() {
kernel_state_->BroadcastNotification(kMsgStatusChanged,
static_cast<uint32_t>(status_));
}
X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
uint32_t buffer_length) {
// NOTE: buffer_length may be zero or valid.
// http://freestyledash.googlecode.com/svn-history/r1/trunk/Freestyle/Scenes/Media/Music/ScnMusic.cpp // http://freestyledash.googlecode.com/svn-history/r1/trunk/Freestyle/Scenes/Media/Music/ScnMusic.cpp
switch (message) { switch (message) {
case 0x00070003: {
assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 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);
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);
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);
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);
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 unk1 = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t unk2 = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t flags =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
assert_true(xmp_client == 0x00000002);
XELOGD("XMPSetState?(%.8X, %.8X, %.8X)", unk1, unk2, flags);
unknown_state1_ = unk1;
unknown_state2_ = unk2;
unknown_flags_ = flags;
kernel_state_->BroadcastNotification(kMsgStateChanged, 0);
return X_ERROR_SUCCESS;
}
case 0x00070009: { case 0x00070009: {
uint32_t unk = assert_true(!buffer_length || buffer_length == 8);
poly::load_and_swap<uint32_t>(membase_ + arg1 + 0); // 0x00000002 uint32_t xmp_client =
uint32_t status_ptr = poly::load_and_swap<uint32_t>( poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
membase_ + arg1 + 4); // out ptr to 4b - expect 0
assert_zero(arg2);
return XMPGetStatus(unk, status_ptr);
}
case 0x0007001A: {
// dcz
// arg1 = ?
// arg2 = 0
break;
}
case 0x0007001B: {
uint32_t unk =
poly::load_and_swap<uint32_t>(membase_ + arg1 + 0); // 0x00000002
uint32_t unk_ptr = poly::load_and_swap<uint32_t>(
membase_ + arg1 + 4); // out ptr to 4b - expect 0
uint32_t disabled_ptr = poly::load_and_swap<uint32_t>(
membase_ + arg1 + 8); // out ptr to 4b - expect 1 (to skip)
assert_zero(arg2);
return XMPGetStatusEx(unk, unk_ptr, disabled_ptr);
}
}
XELOGE("Unimplemented XMsg message app=%.8X, msg=%.8X, arg1=%.8X, arg2=%.8X",
app_id(), message, arg1, arg2);
return X_ERROR_NOT_FOUND;
}
X_RESULT XXMPApp::DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
size_t buffer_length) {
switch (message) {
case 0x00070009: {
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr +
0); // 0x00000002
uint32_t status_ptr = poly::load_and_swap<uint32_t>( uint32_t status_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0 membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
assert_true(buffer_length == 8); assert_true(xmp_client == 0x00000002);
return XMPGetStatus(unk, status_ptr); return XMPGetStatus(status_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 float_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - floating point
assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetFloat?(%.8X)", float_ptr);
poly::store_and_swap<float>(membase_ + float_ptr, unknown_float_);
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);
assert_true(xmp_client == 0x00000002);
XELOGD("XMPSetFloat?(%g)", float_value);
unknown_float_ = float_value;
return X_ERROR_SUCCESS;
}
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 disabled =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
assert_true(xmp_client == 0x00000002);
assert_zero(unk1);
XELOGD("XMPSetDisabled(%.8X, %.8X)", unk1, disabled);
disabled_ = disabled;
kernel_state_->BroadcastNotification(kMsgDisableChanged, disabled_);
return X_ERROR_SUCCESS;
} }
case 0x0007001B: { case 0x0007001B: {
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + assert_true(!buffer_length || buffer_length == 12);
0); // 0x00000002 uint32_t xmp_client =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t unk_ptr = poly::load_and_swap<uint32_t>( uint32_t unk_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0 membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
uint32_t disabled_ptr = poly::load_and_swap<uint32_t>( uint32_t disabled_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 8); // out ptr to 4b - expect 1 (to skip) membase_ + buffer_ptr + 8); // out ptr to 4b - expect 1 (to skip)
assert_true(buffer_length == 0xC); assert_true(xmp_client == 0x00000002);
return XMPGetStatusEx(unk, unk_ptr, disabled_ptr); XELOGD("XMPGetDisabled(%.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_);
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 unk1_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t unk2_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);
assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetState?(%.8X, %.8X, %.8X)", unk1_ptr, unk2_ptr, unk3_ptr);
poly::store_and_swap<uint32_t>(membase_ + unk1_ptr, unknown_state1_);
poly::store_and_swap<uint32_t>(membase_ + unk2_ptr, unknown_state2_);
poly::store_and_swap<uint32_t>(membase_ + unk3_ptr, unknown_flags_);
return X_ERROR_SUCCESS;
}
case 0x0007002E: {
assert_true(!buffer_length || buffer_length == 12);
// 00000002 00000003 20049ce0
uint32_t xmp_client = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 0); // 0x00000002
uint32_t unk1 = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr +
4); // 0x00000003
uint32_t unk_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
assert_true(xmp_client == 0x00000002);
//
break;
} }
} }
XELOGE("Unimplemented XMsg message app=%.8X, msg=%.8X, buffer=%.8X, len=%d", XELOGE("Unimplemented XMsg message app=%.8X, msg=%.8X, arg1=%.8X, arg2=%.8X",
app_id(), message, buffer_ptr, buffer_length); app_id(), message, buffer_ptr, buffer_length);
return X_ERROR_NOT_FOUND; return X_ERROR_NOT_FOUND;
} }

View File

@ -20,16 +20,38 @@ namespace apps {
class XXMPApp : public XApp { class XXMPApp : public XApp {
public: public:
XXMPApp(KernelState* kernel_state) : XApp(kernel_state, 0xFA) {} enum class Status : uint32_t {
kStopped = 0,
kPlaying = 1,
kPaused = 2,
};
X_RESULT XMPGetStatus(uint32_t unk, uint32_t status_ptr); XXMPApp(KernelState* kernel_state);
X_RESULT XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr,
uint32_t disabled_ptr);
X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1, X_RESULT XMPGetStatus(uint32_t status_ptr);
uint32_t arg2) override;
X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr, X_RESULT XMPContinue();
size_t buffer_length) override; X_RESULT XMPStop(uint32_t unk);
X_RESULT XMPPause();
X_RESULT XMPNext();
X_RESULT XMPPrevious();
X_RESULT DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
uint32_t buffer_length) override;
private:
static const uint32_t kMsgStatusChanged = 0xA000001;
static const uint32_t kMsgStateChanged = 0xA000002;
static const uint32_t kMsgDisableChanged = 0xA000003;
void OnStatusChanged();
Status status_;
uint32_t disabled_;
uint32_t unknown_state1_;
uint32_t unknown_state2_;
uint32_t unknown_flags_;
float unknown_float_;
}; };
} // namespace apps } // namespace apps