Implement XamLoaderLaunchTitle and other loader functions.
This commit is contained in:
parent
d6686fc345
commit
39d6e9a20f
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue