Files
Xenia-Canary/src/xenia/kernel/xmodule.cc

134 lines
3.7 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/kernel/xmodule.h"
#include "xenia/base/byte_stream.h"
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
namespace xe {
namespace kernel {
XModule::XModule(KernelState* kernel_state, ModuleType module_type)
: XObject(kernel_state, kType),
module_type_(module_type),
processor_module_(nullptr),
hmodule_ptr_(0) {
// Loader data (HMODULE)
hmodule_ptr_ = memory()->SystemHeapAlloc(sizeof(X_LDR_DATA_TABLE_ENTRY));
// Hijack the checksum field to store our kernel object handle.
auto ldr_data =
memory()->TranslateVirtual<X_LDR_DATA_TABLE_ENTRY*>(hmodule_ptr_);
ldr_data->checksum = handle();
}
XModule::~XModule() {
kernel_state_->UnregisterModule(this);
// Destroy the loader data.
memory()->SystemHeapFree(hmodule_ptr_);
}
bool XModule::Matches(const std::string& name) const {
if (strcasecmp(xe::find_name_from_path(path_).c_str(), name.c_str()) == 0) {
return true;
}
if (strcasecmp(name_.c_str(), name.c_str()) == 0) {
return true;
}
if (strcasecmp(path_.c_str(), name.c_str()) == 0) {
return true;
}
return false;
}
void XModule::OnLoad() { kernel_state_->RegisterModule(this); }
void XModule::OnUnload() { kernel_state_->UnregisterModule(this); }
X_STATUS XModule::GetSection(const char* name, uint32_t* out_section_data,
uint32_t* out_section_size) {
return X_STATUS_UNSUCCESSFUL;
}
object_ref<XModule> XModule::GetFromHModule(KernelState* kernel_state,
void* hmodule) {
// Grab the object from our stashed kernel handle
return kernel_state->object_table()->LookupObject<XModule>(
GetHandleFromHModule(hmodule));
}
uint32_t XModule::GetHandleFromHModule(void* hmodule) {
auto ldr_data = reinterpret_cast<X_LDR_DATA_TABLE_ENTRY*>(hmodule);
return ldr_data->checksum;
}
std::string XModule::NameFromPath(std::string path) {
std::string name;
auto last_slash = path.find_last_of('/');
if (last_slash == path.npos) {
last_slash = path.find_last_of('\\');
}
if (last_slash == path.npos) {
name = path;
} else {
name = path.substr(last_slash + 1);
}
auto dot = name.find_last_of('.');
if (dot != name.npos) {
name = name.substr(0, dot);
}
return name;
}
bool XModule::Save(ByteStream* stream) {
XELOGD("XModule %.8X (%s)", handle(), path_.c_str());
stream->Write('XMOD');
stream->Write(path_);
stream->Write(hmodule_ptr_);
if (!SaveObject(stream)) {
return false;
}
return true;
}
object_ref<XModule> XModule::Restore(KernelState* kernel_state,
ByteStream* stream) {
if (stream->Read<uint32_t>() != 'XMOD') {
return nullptr;
}
auto path = stream->Read<std::string>();
auto hmodule_ptr = stream->Read<uint32_t>();
// Can only save user modules at the moment, so just redirect.
// TODO: Find a way to call RestoreObject here before UserModule::Restore.
auto module = UserModule::Restore(kernel_state, stream, path);
if (!module) {
return nullptr;
}
XELOGD("XModule %.8X (%s)", module->handle(), module->path_.c_str());
module->hmodule_ptr_ = hmodule_ptr;
return module;
}
} // namespace kernel
} // namespace xe