Digging into XMP stuff. Wish these were just normal functions.
This commit is contained in:
parent
cf31969510
commit
f5e12eba76
|
@ -26,12 +26,13 @@ void XAppManager::RegisterApp(std::unique_ptr<XApp> app) {
|
|||
}
|
||||
|
||||
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);
|
||||
if (it == app_lookup_.end()) {
|
||||
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,
|
||||
|
@ -41,7 +42,7 @@ X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message,
|
|||
if (it == app_lookup_.end()) {
|
||||
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
|
||||
|
|
|
@ -26,10 +26,8 @@ class XApp {
|
|||
public:
|
||||
uint32_t app_id() const { return app_id_; }
|
||||
|
||||
virtual X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1,
|
||||
uint32_t arg2) = 0;
|
||||
virtual X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
|
||||
size_t buffer_length) = 0;
|
||||
virtual X_RESULT DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
|
||||
uint32_t buffer_length) = 0;
|
||||
|
||||
protected:
|
||||
XApp(KernelState* kernel_state, uint32_t app_id);
|
||||
|
@ -43,8 +41,8 @@ class XAppManager {
|
|||
public:
|
||||
void RegisterApp(std::unique_ptr<XApp> app);
|
||||
|
||||
X_RESULT DispatchMessageSync(uint32_t app_id, uint32_t message, uint32_t arg1,
|
||||
uint32_t arg2);
|
||||
X_RESULT DispatchMessageSync(uint32_t app_id, uint32_t message,
|
||||
uint32_t buffer_ptr, uint32_t buffer_length);
|
||||
X_RESULT DispatchMessageAsync(uint32_t app_id, uint32_t message,
|
||||
uint32_t buffer_ptr, size_t buffer_length);
|
||||
|
||||
|
|
|
@ -13,91 +13,219 @@ namespace xe {
|
|||
namespace kernel {
|
||||
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
|
||||
// here to keep from starving real threads.
|
||||
Sleep(1);
|
||||
|
||||
XELOGD("XMPGetStatus(%.8X, %.8X)", unk, status_ptr);
|
||||
|
||||
assert_true(unk == 2);
|
||||
poly::store_and_swap<uint32_t>(membase_ + status_ptr, 0);
|
||||
|
||||
XELOGD("XMPGetStatus(%.8X)", status_ptr);
|
||||
poly::store_and_swap<uint32_t>(membase_ + status_ptr,
|
||||
static_cast<uint32_t>(status_));
|
||||
OnStatusChanged();
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
X_RESULT XXMPApp::XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr,
|
||||
uint32_t disabled_ptr) {
|
||||
// Some stupid games will hammer this on a thread - induce a delay
|
||||
// here to keep from starving real threads.
|
||||
Sleep(10);
|
||||
|
||||
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);
|
||||
|
||||
X_RESULT XXMPApp::XMPContinue() {
|
||||
XELOGD("XMPContinue()");
|
||||
if (status_ == Status::kPaused) {
|
||||
status_ = Status::kPlaying;
|
||||
}
|
||||
OnStatusChanged();
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t arg1,
|
||||
uint32_t arg2) {
|
||||
X_RESULT XXMPApp::XMPStop(uint32_t unk) {
|
||||
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
|
||||
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: {
|
||||
uint32_t unk =
|
||||
poly::load_and_swap<uint32_t>(membase_ + arg1 + 0); // 0x00000002
|
||||
uint32_t status_ptr = poly::load_and_swap<uint32_t>(
|
||||
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
|
||||
assert_true(!buffer_length || buffer_length == 8);
|
||||
uint32_t xmp_client =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t status_ptr = poly::load_and_swap<uint32_t>(
|
||||
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
|
||||
assert_true(buffer_length == 8);
|
||||
return XMPGetStatus(unk, status_ptr);
|
||||
assert_true(xmp_client == 0x00000002);
|
||||
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: {
|
||||
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr +
|
||||
0); // 0x00000002
|
||||
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); // 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)
|
||||
assert_true(buffer_length == 0xC);
|
||||
return XMPGetStatusEx(unk, unk_ptr, disabled_ptr);
|
||||
assert_true(xmp_client == 0x00000002);
|
||||
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);
|
||||
return X_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
|
|
@ -20,16 +20,38 @@ namespace apps {
|
|||
|
||||
class XXMPApp : public XApp {
|
||||
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);
|
||||
X_RESULT XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr,
|
||||
uint32_t disabled_ptr);
|
||||
XXMPApp(KernelState* kernel_state);
|
||||
|
||||
X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1,
|
||||
uint32_t arg2) override;
|
||||
X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
|
||||
size_t buffer_length) override;
|
||||
X_RESULT XMPGetStatus(uint32_t status_ptr);
|
||||
|
||||
X_RESULT XMPContinue();
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue