Implement XamLoaderLaunchTitle and other loader functions.

This commit is contained in:
Dr. Chat 2015-07-05 15:44:46 -05:00
parent d6686fc345
commit 39d6e9a20f
4 changed files with 113 additions and 39 deletions

View File

@ -274,10 +274,29 @@ X_STATUS Emulator::LaunchStfsContainer(std::wstring path) {
X_STATUS Emulator::CompleteLaunch(const std::wstring& path, X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
const std::string& module_path) { const std::string& module_path) {
// Allow xam to request module loads.
auto xam_module = kernel_state_->GetModule("xam.xex");
auto xam = kernel::object_ref<kernel::XamModule>(
reinterpret_cast<kernel::XamModule*>(xam_module.release()));
auto xboxkrnl_module = kernel_state_->GetModule("xboxkrnl.exe"); auto xboxkrnl_module = kernel_state_->GetModule("xboxkrnl.exe");
auto xboxkrnl = kernel::object_ref<kernel::XboxkrnlModule>( auto xboxkrnl = kernel::object_ref<kernel::XboxkrnlModule>(
reinterpret_cast<kernel::XboxkrnlModule*>(xboxkrnl_module.release())); reinterpret_cast<kernel::XboxkrnlModule*>(xboxkrnl_module.release()));
int result = xboxkrnl->LaunchModule(module_path.c_str());
int result = 0;
auto next_module = module_path;
while (next_module != "") {
XELOGI("Launching module %s", next_module.c_str());
result = xboxkrnl->LaunchModule(next_module.c_str());
// Check xam and see if they want us to load another module.
auto& loader_data = xam->loader_data();
next_module = loader_data.launch_path;
// And blank out the launch path to avoid an infinite loop.
loader_data.launch_path = "";
}
if (result == 0) { if (result == 0) {
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} else { } else {

View File

@ -11,8 +11,10 @@
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xenumerator.h" #include "xenia/kernel/objects/xenumerator.h"
#include "xenia/kernel/objects/xuser_module.h" #include "xenia/kernel/objects/xuser_module.h"
#include "xenia/kernel/objects/xthread.h"
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h" #include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xam_module.h"
#include "xenia/kernel/xam_private.h" #include "xenia/kernel/xam_private.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
@ -90,53 +92,93 @@ SHIM_CALL XamGetExecutionId_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(X_STATUS_SUCCESS); SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
} }
SHIM_CALL XamLoaderSetLaunchData_shim(PPCContext* ppc_context, dword_result_t XamLoaderSetLaunchData(lpvoid_t data, dword_t size) {
KernelState* kernel_state) { auto xam_module = kernel_state()->GetModule("xam.xex");
uint32_t data_ptr = SHIM_GET_ARG_32(0); auto xam = kernel::object_ref<kernel::XamModule>(
uint32_t data_size = SHIM_GET_ARG_32(1); reinterpret_cast<kernel::XamModule*>(xam_module.release()));
XELOGD("XamLoaderSetLaunchData(%.8X, %d)", data_ptr, data_size); auto& loader_data = xam->loader_data();
if (loader_data.launch_data_ptr) {
kernel_memory()->SystemHeapFree(loader_data.launch_data_ptr);
}
// Unknown return value. loader_data.launch_data_ptr = kernel_memory()->SystemHeapAlloc(size);
SHIM_SET_RETURN_32(0); loader_data.launch_data_size = size;
std::memcpy(kernel_memory()->TranslateVirtual(loader_data.launch_data_ptr),
data, size);
// FIXME: Unknown return value.
return 0;
} }
DECLARE_XAM_EXPORT(XamLoaderSetLaunchData, ExportTag::kSketchy);
SHIM_CALL XamLoaderGetLaunchDataSize_shim(PPCContext* ppc_context, dword_result_t XamLoaderGetLaunchDataSize(lpdword_t size_ptr) {
KernelState* kernel_state) { auto xam_module = kernel_state()->GetModule("xam.xex");
uint32_t size_ptr = SHIM_GET_ARG_32(0); auto xam = kernel::object_ref<kernel::XamModule>(
reinterpret_cast<kernel::XamModule*>(xam_module.release()));
XELOGD("XamLoaderGetLaunchDataSize(%.8X)", size_ptr); *size_ptr = xam->loader_data().launch_data_size;
SHIM_SET_MEM_32(size_ptr, 0); // FIXME: What do we return?
return 1;
SHIM_SET_RETURN_32(1);
} }
DECLARE_XAM_EXPORT(XamLoaderGetLaunchDataSize, ExportTag::kSketchy);
SHIM_CALL XamLoaderGetLaunchData_shim(PPCContext* ppc_context, dword_result_t XamLoaderGetLaunchData(lpvoid_t buffer_ptr, dword_t buffer_size) {
KernelState* kernel_state) { auto xam_module = kernel_state()->GetModule("xam.xex");
uint32_t buffer_ptr = SHIM_GET_ARG_32(0); auto xam = kernel::object_ref<kernel::XamModule>(
uint32_t buffer_size = SHIM_GET_ARG_32(1); reinterpret_cast<kernel::XamModule*>(xam_module.release()));
XELOGD("XamLoaderGetLaunchData(%.8X, %d)", buffer_ptr, buffer_size); auto& loader_data = xam->loader_data();
if (loader_data.launch_data_ptr) {
uint8_t* loader_buffer_ptr =
kernel_memory()->TranslateVirtual(loader_data.launch_data_ptr);
SHIM_SET_RETURN_32(0); uint32_t copy_size =
std::min(loader_data.launch_data_size, (uint32_t)buffer_size);
std::memcpy(buffer_ptr, loader_buffer_ptr, copy_size);
}
// FIXME: Unknown return value.
return 0;
} }
DECLARE_XAM_EXPORT(XamLoaderGetLaunchData, ExportTag::kSketchy);
SHIM_CALL XamLoaderLaunchTitle_shim(PPCContext* ppc_context, void XamLoaderLaunchTitle(lpstring_t raw_name, dword_t flags) {
KernelState* kernel_state) { auto xam_module = kernel_state()->GetModule("xam.xex");
uint32_t name_ptr = SHIM_GET_ARG_32(0); auto xam = kernel::object_ref<kernel::XamModule>(
const char* name = (const char*)SHIM_MEM_ADDR(name_ptr); reinterpret_cast<kernel::XamModule*>(xam_module.release()));
uint32_t flags = SHIM_GET_ARG_32(1);
XELOGD("XamLoaderLaunchTitle(%.8X(%s), %.8X)", name_ptr, name, flags); auto& loader_data = xam->loader_data();
assert_always(); loader_data.launch_flags = flags;
// Translate the launch path to a full path.
if (raw_name) {
std::string name = xe::find_name_from_path(std::string(raw_name));
std::string path(raw_name);
if (name == std::string(raw_name)) {
path = xe::join_paths(
xe::find_base_path(kernel_state()->GetExecutableModule()->path()),
name);
}
loader_data.launch_path = path;
} else {
assert_always("Game requested exit to dashboard via XamLoaderLaunchTitle");
}
// This function does not return.
XThread::GetCurrentThread()->Exit(0);
} }
DECLARE_XAM_EXPORT(XamLoaderLaunchTitle, ExportTag::kSketchy);
SHIM_CALL XamLoaderTerminateTitle_shim(PPCContext* ppc_context, void XamLoaderTerminateTitle() {
KernelState* kernel_state) { // This function does not return.
XELOGD("XamLoaderTerminateTitle()"); XThread::GetCurrentThread()->Exit(0);
assert_always();
} }
DECLARE_XAM_EXPORT(XamLoaderTerminateTitle, ExportTag::kSketchy);
SHIM_CALL XamAlloc_shim(PPCContext* ppc_context, KernelState* kernel_state) { SHIM_CALL XamAlloc_shim(PPCContext* ppc_context, KernelState* kernel_state) {
uint32_t unk = SHIM_GET_ARG_32(0); uint32_t unk = SHIM_GET_ARG_32(0);
@ -223,12 +265,6 @@ void xe::kernel::xam::RegisterInfoExports(
SHIM_SET_MAPPING("xam.xex", XamGetExecutionId, state); SHIM_SET_MAPPING("xam.xex", XamGetExecutionId, state);
SHIM_SET_MAPPING("xam.xex", XamLoaderSetLaunchData, state);
SHIM_SET_MAPPING("xam.xex", XamLoaderGetLaunchDataSize, state);
SHIM_SET_MAPPING("xam.xex", XamLoaderGetLaunchData, state);
SHIM_SET_MAPPING("xam.xex", XamLoaderLaunchTitle, state);
SHIM_SET_MAPPING("xam.xex", XamLoaderTerminateTitle, state);
SHIM_SET_MAPPING("xam.xex", XamAlloc, state); SHIM_SET_MAPPING("xam.xex", XamAlloc, state);
SHIM_SET_MAPPING("xam.xex", XamFree, state); SHIM_SET_MAPPING("xam.xex", XamFree, state);

View File

@ -17,7 +17,8 @@ namespace xe {
namespace kernel { namespace kernel {
XamModule::XamModule(Emulator* emulator, KernelState* kernel_state) XamModule::XamModule(Emulator* emulator, KernelState* kernel_state)
: XKernelModule(kernel_state, "xe:\\xam.xex") { : XKernelModule(kernel_state, "xe:\\xam.xex")
, loader_data_() {
RegisterExportTable(export_resolver_); RegisterExportTable(export_resolver_);
// Register all exported functions. // Register all exported functions.

View File

@ -24,7 +24,25 @@ class XamModule : public XKernelModule {
static void RegisterExportTable(xe::cpu::ExportResolver* export_resolver); static void RegisterExportTable(xe::cpu::ExportResolver* export_resolver);
struct LoaderData {
LoaderData() {
launch_data_ptr = 0;
launch_data_size = 0;
launch_flags = 0;
launch_path = "";
}
uint32_t launch_data_ptr;
uint32_t launch_data_size;
uint32_t launch_flags;
std::string launch_path; // Full path to next xex
};
const LoaderData& loader_data() const { return loader_data_; }
LoaderData& loader_data() { return loader_data_; }
private: private:
LoaderData loader_data_;
}; };
} // namespace kernel } // namespace kernel