Massive refactoring of all code + audio skeleton.
This should make it easier to find files and (in the future) split things up into separate libraries. It also changes around emulator initialization to make it a little more difficult to do things out of order and a little more sensible as to when real init work happens. Also adding a skeleton audio system/driver and reworking CPU register access to be more extensible.
This commit is contained in:
42
src/xenia/kernel/xboxkrnl/async_request.cc
Normal file
42
src/xenia/kernel/xboxkrnl/async_request.cc
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/async_request.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xevent.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
XAsyncRequest::XAsyncRequest(
|
||||
KernelState* kernel_state, XObject* object,
|
||||
CompletionCallback callback, void* callback_context) :
|
||||
kernel_state_(kernel_state), object_(object),
|
||||
callback_(callback), callback_context_(callback_context),
|
||||
apc_routine_(0), apc_context_(0) {
|
||||
object_->Retain();
|
||||
}
|
||||
|
||||
XAsyncRequest::~XAsyncRequest() {
|
||||
for (vector<XEvent*>::iterator it = wait_events_.begin();
|
||||
it != wait_events_.end(); ++it) {
|
||||
(*it)->Release();
|
||||
}
|
||||
object_->Release();
|
||||
}
|
||||
|
||||
void XAsyncRequest::AddWaitEvent(XEvent* ev) {
|
||||
ev->Retain();
|
||||
wait_events_.push_back(ev);
|
||||
}
|
||||
61
src/xenia/kernel/xboxkrnl/async_request.h
Normal file
61
src/xenia/kernel/xboxkrnl/async_request.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_ASYNC_REQUEST_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_ASYNC_REQUEST_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
class KernelState;
|
||||
class XEvent;
|
||||
class XObject;
|
||||
|
||||
|
||||
class XAsyncRequest {
|
||||
public:
|
||||
typedef void (*CompletionCallback)(XAsyncRequest* request, void* context);
|
||||
|
||||
XAsyncRequest(
|
||||
KernelState* kernel_state, XObject* object,
|
||||
CompletionCallback callback, void* callback_context);
|
||||
virtual ~XAsyncRequest();
|
||||
|
||||
KernelState* kernel_state() const { return kernel_state_; }
|
||||
XObject* object() const { return object_; }
|
||||
|
||||
void AddWaitEvent(XEvent* ev);
|
||||
|
||||
// Complete(result)
|
||||
|
||||
protected:
|
||||
KernelState* kernel_state_;
|
||||
XObject* object_;
|
||||
CompletionCallback callback_;
|
||||
void* callback_context_;
|
||||
|
||||
std::vector<XEvent*> wait_events_;
|
||||
uint32_t apc_routine_;
|
||||
uint32_t apc_context_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_ASYNC_REQUEST_H_
|
||||
28
src/xenia/kernel/xboxkrnl/fs/device.cc
Normal file
28
src/xenia/kernel/xboxkrnl/fs/device.cc
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/device.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
Device::Device(const char* path) {
|
||||
path_ = xestrdupa(path);
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
xe_free(path_);
|
||||
}
|
||||
|
||||
const char* Device::path() {
|
||||
return path_;
|
||||
}
|
||||
45
src/xenia/kernel/xboxkrnl/fs/device.h
Normal file
45
src/xenia/kernel/xboxkrnl/fs/device.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
|
||||
class Device {
|
||||
public:
|
||||
Device(const char* path);
|
||||
virtual ~Device();
|
||||
|
||||
const char* path();
|
||||
|
||||
virtual Entry* ResolvePath(const char* path) = 0;
|
||||
|
||||
protected:
|
||||
char* path_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICE_H_
|
||||
98
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_device.cc
Normal file
98
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_device.cc
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/devices/disc_image_device.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/gdfx.h>
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/disc_image_entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
|
||||
DiscImageDevice::DiscImageDevice(const char* path, const xechar_t* local_path) :
|
||||
Device(path) {
|
||||
local_path_ = xestrdup(local_path);
|
||||
mmap_ = NULL;
|
||||
gdfx_ = NULL;
|
||||
}
|
||||
|
||||
DiscImageDevice::~DiscImageDevice() {
|
||||
delete gdfx_;
|
||||
xe_mmap_release(mmap_);
|
||||
xe_free(local_path_);
|
||||
}
|
||||
|
||||
int DiscImageDevice::Init() {
|
||||
mmap_ = xe_mmap_open(kXEFileModeRead, local_path_, 0, 0);
|
||||
if (!mmap_) {
|
||||
XELOGE("Disc image could not be mapped");
|
||||
return 1;
|
||||
}
|
||||
|
||||
gdfx_ = new GDFX(mmap_);
|
||||
GDFX::Error error = gdfx_->Load();
|
||||
if (error != GDFX::kSuccess) {
|
||||
XELOGE("GDFX init failed: %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//gdfx_->Dump();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Entry* DiscImageDevice::ResolvePath(const char* path) {
|
||||
// The filesystem will have stripped our prefix off already, so the path will
|
||||
// be in the form:
|
||||
// some\PATH.foo
|
||||
|
||||
XELOGFS("DiscImageDevice::ResolvePath(%s)", path);
|
||||
|
||||
GDFXEntry* gdfx_entry = gdfx_->root_entry();
|
||||
|
||||
// Walk the path, one separator at a time.
|
||||
// We copy it into the buffer and shift it left over and over.
|
||||
char remaining[XE_MAX_PATH];
|
||||
XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), path));
|
||||
while (remaining[0]) {
|
||||
char* next_slash = xestrchra(remaining, '\\');
|
||||
if (next_slash == remaining) {
|
||||
// Leading slash - shift
|
||||
XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), remaining + 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make the buffer just the name.
|
||||
if (next_slash) {
|
||||
*next_slash = 0;
|
||||
}
|
||||
|
||||
// Look up in the entry.
|
||||
gdfx_entry = gdfx_entry->GetChild(remaining);
|
||||
if (!gdfx_entry) {
|
||||
// Not found.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Shift the buffer down, unless we are at the end.
|
||||
if (!next_slash) {
|
||||
break;
|
||||
}
|
||||
XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), next_slash + 1));
|
||||
}
|
||||
|
||||
Entry::Type type = gdfx_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY ?
|
||||
Entry::kTypeDirectory : Entry::kTypeFile;
|
||||
return new DiscImageEntry(
|
||||
type, this, path, mmap_, gdfx_entry);
|
||||
}
|
||||
50
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_device.h
Normal file
50
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_device.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/device.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
|
||||
class GDFX;
|
||||
|
||||
|
||||
class DiscImageDevice : public Device {
|
||||
public:
|
||||
DiscImageDevice(const char* path, const xechar_t* local_path);
|
||||
virtual ~DiscImageDevice();
|
||||
|
||||
int Init();
|
||||
|
||||
virtual Entry* ResolvePath(const char* path);
|
||||
|
||||
private:
|
||||
xechar_t* local_path_;
|
||||
xe_mmap_ref mmap_;
|
||||
GDFX* gdfx_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
|
||||
89
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_entry.cc
Normal file
89
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_entry.cc
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/devices/disc_image_entry.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/gdfx.h>
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/disc_image_file.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
class DiscImageMemoryMapping : public MemoryMapping {
|
||||
public:
|
||||
DiscImageMemoryMapping(uint8_t* address, size_t length, xe_mmap_ref mmap) :
|
||||
MemoryMapping(address, length) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
|
||||
virtual ~DiscImageMemoryMapping() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
DiscImageEntry::DiscImageEntry(Type type, Device* device, const char* path,
|
||||
xe_mmap_ref mmap, GDFXEntry* gdfx_entry) :
|
||||
gdfx_entry_(gdfx_entry),
|
||||
Entry(type, device, path) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
|
||||
DiscImageEntry::~DiscImageEntry() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageEntry::QueryInfo(XFileInfo* out_info) {
|
||||
XEASSERTNOTNULL(out_info);
|
||||
out_info->creation_time = 0;
|
||||
out_info->last_access_time = 0;
|
||||
out_info->last_write_time = 0;
|
||||
out_info->change_time = 0;
|
||||
out_info->allocation_size = 2048;
|
||||
out_info->file_length = gdfx_entry_->size;
|
||||
out_info->attributes = gdfx_entry_->attributes;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MemoryMapping* DiscImageEntry::CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length) {
|
||||
if (file_mode & kXEFileModeWrite) {
|
||||
// Only allow reads.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t real_offset = gdfx_entry_->offset + offset;
|
||||
size_t real_length = length ?
|
||||
MIN(length, gdfx_entry_->size) : gdfx_entry_->size;
|
||||
return new DiscImageMemoryMapping(
|
||||
xe_mmap_get_addr(mmap_) + real_offset,
|
||||
real_length,
|
||||
mmap_);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageEntry::Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file) {
|
||||
*out_file = new DiscImageFile(kernel_state, desired_access, this);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
58
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_entry.h
Normal file
58
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_entry.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_ENTRY_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_ENTRY_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
class GDFXEntry;
|
||||
|
||||
|
||||
class DiscImageEntry : public Entry {
|
||||
public:
|
||||
DiscImageEntry(Type type, Device* device, const char* path,
|
||||
xe_mmap_ref mmap, GDFXEntry* gdfx_entry);
|
||||
virtual ~DiscImageEntry();
|
||||
|
||||
xe_mmap_ref mmap() const { return mmap_; }
|
||||
GDFXEntry* gdfx_entry() const { return gdfx_entry_; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
|
||||
virtual MemoryMapping* CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length);
|
||||
|
||||
virtual X_STATUS Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file);
|
||||
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
GDFXEntry* gdfx_entry_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_ENTRY_H_
|
||||
48
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_file.cc
Normal file
48
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_file.cc
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/devices/disc_image_file.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/gdfx.h>
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/disc_image_entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
DiscImageFile::DiscImageFile(
|
||||
KernelState* kernel_state, uint32_t desired_access,
|
||||
DiscImageEntry* entry) :
|
||||
entry_(entry),
|
||||
XFile(kernel_state, desired_access) {
|
||||
}
|
||||
|
||||
DiscImageFile::~DiscImageFile() {
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::QueryInfo(XFileInfo* out_info) {
|
||||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
GDFXEntry* gdfx_entry = entry_->gdfx_entry();
|
||||
xe_mmap_ref mmap = entry_->mmap();
|
||||
size_t real_offset = gdfx_entry->offset + byte_offset;
|
||||
size_t real_length = MIN(buffer_length, gdfx_entry->size - byte_offset);
|
||||
xe_copy_memory(
|
||||
buffer, buffer_length,
|
||||
xe_mmap_get_addr(mmap) + real_offset, real_length);
|
||||
*out_bytes_read = real_length;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
51
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_file.h
Normal file
51
src/xenia/kernel/xboxkrnl/fs/devices/disc_image_file.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/objects/xfile.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
class DiscImageEntry;
|
||||
|
||||
|
||||
class DiscImageFile : public XFile {
|
||||
public:
|
||||
DiscImageFile(KernelState* kernel_state, uint32_t desired_access,
|
||||
DiscImageEntry* entry);
|
||||
virtual ~DiscImageFile();
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
|
||||
protected:
|
||||
virtual X_STATUS ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read);
|
||||
|
||||
private:
|
||||
DiscImageEntry* entry_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_
|
||||
65
src/xenia/kernel/xboxkrnl/fs/devices/host_path_device.cc
Normal file
65
src/xenia/kernel/xboxkrnl/fs/devices/host_path_device.cc
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/devices/host_path_device.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/host_path_entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
HostPathDevice::HostPathDevice(const char* path, const xechar_t* local_path) :
|
||||
Device(path) {
|
||||
local_path_ = xestrdup(local_path);
|
||||
}
|
||||
|
||||
HostPathDevice::~HostPathDevice() {
|
||||
xe_free(local_path_);
|
||||
}
|
||||
|
||||
Entry* HostPathDevice::ResolvePath(const char* path) {
|
||||
// The filesystem will have stripped our prefix off already, so the path will
|
||||
// be in the form:
|
||||
// some\PATH.foo
|
||||
|
||||
XELOGFS("HostPathDevice::ResolvePath(%s)", path);
|
||||
|
||||
#if XE_WCHAR
|
||||
xechar_t rel_path[XE_MAX_PATH];
|
||||
XEIGNORE(xestrwiden(rel_path, XECOUNT(rel_path), path));
|
||||
#else
|
||||
const xechar_t* rel_path = path;
|
||||
#endif
|
||||
|
||||
xechar_t full_path[XE_MAX_PATH];
|
||||
xe_path_join(local_path_, rel_path, full_path, XECOUNT(full_path));
|
||||
|
||||
// Swap around path separators.
|
||||
if (XE_PATH_SEPARATOR != '\\') {
|
||||
for (size_t n = 0; n < XECOUNT(full_path); n++) {
|
||||
if (full_path[n] == 0) {
|
||||
break;
|
||||
}
|
||||
if (full_path[n] == '\\') {
|
||||
full_path[n] = XE_PATH_SEPARATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(benvanik): get file info
|
||||
// TODO(benvanik): fail if does not exit
|
||||
// TODO(benvanik): switch based on type
|
||||
|
||||
Entry::Type type = Entry::kTypeFile;
|
||||
HostPathEntry* entry = new HostPathEntry(type, this, path, full_path);
|
||||
return entry;
|
||||
}
|
||||
43
src/xenia/kernel/xboxkrnl/fs/devices/host_path_device.h
Normal file
43
src/xenia/kernel/xboxkrnl/fs/devices/host_path_device.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_DEVICE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_DEVICE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/device.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
|
||||
class HostPathDevice : public Device {
|
||||
public:
|
||||
HostPathDevice(const char* path, const xechar_t* local_path);
|
||||
virtual ~HostPathDevice();
|
||||
|
||||
virtual Entry* ResolvePath(const char* path);
|
||||
|
||||
private:
|
||||
xechar_t* local_path_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_DEVICE_H_
|
||||
108
src/xenia/kernel/xboxkrnl/fs/devices/host_path_entry.cc
Normal file
108
src/xenia/kernel/xboxkrnl/fs/devices/host_path_entry.cc
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/devices/host_path_entry.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/host_path_file.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
class HostPathMemoryMapping : public MemoryMapping {
|
||||
public:
|
||||
HostPathMemoryMapping(uint8_t* address, size_t length, xe_mmap_ref mmap) :
|
||||
MemoryMapping(address, length) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
virtual ~HostPathMemoryMapping() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
HostPathEntry::HostPathEntry(Type type, Device* device, const char* path,
|
||||
const xechar_t* local_path) :
|
||||
Entry(type, device, path) {
|
||||
local_path_ = xestrdup(local_path);
|
||||
}
|
||||
|
||||
HostPathEntry::~HostPathEntry() {
|
||||
xe_free(local_path_);
|
||||
}
|
||||
|
||||
X_STATUS HostPathEntry::QueryInfo(XFileInfo* out_info) {
|
||||
XEASSERTNOTNULL(out_info);
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
if (!GetFileAttributesEx(
|
||||
local_path_, GetFileExInfoStandard, &data)) {
|
||||
return X_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
#define COMBINE_TIME(t) (((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime)
|
||||
out_info->creation_time = COMBINE_TIME(data.ftCreationTime);
|
||||
out_info->last_access_time = COMBINE_TIME(data.ftLastAccessTime);
|
||||
out_info->last_write_time = COMBINE_TIME(data.ftLastWriteTime);
|
||||
out_info->change_time = COMBINE_TIME(data.ftLastWriteTime);
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->file_length = ((uint64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)data.dwFileAttributes;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MemoryMapping* HostPathEntry::CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length) {
|
||||
xe_mmap_ref mmap = xe_mmap_open(file_mode, local_path_, offset, length);
|
||||
if (!mmap) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HostPathMemoryMapping* lfmm = new HostPathMemoryMapping(
|
||||
(uint8_t*)xe_mmap_get_addr(mmap), xe_mmap_get_length(mmap),
|
||||
mmap);
|
||||
xe_mmap_release(mmap);
|
||||
|
||||
return lfmm;
|
||||
}
|
||||
|
||||
X_STATUS HostPathEntry::Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file) {
|
||||
DWORD share_mode = FILE_SHARE_READ;
|
||||
DWORD creation_disposition = OPEN_EXISTING;
|
||||
DWORD flags_and_attributes = async ? FILE_FLAG_OVERLAPPED : 0;
|
||||
HANDLE file = CreateFile(
|
||||
local_path_,
|
||||
desired_access,
|
||||
share_mode,
|
||||
NULL,
|
||||
creation_disposition,
|
||||
flags_and_attributes,
|
||||
NULL);
|
||||
if (!file) {
|
||||
// TODO(benvanik): pick correct response.
|
||||
return X_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
*out_file = new HostPathFile(kernel_state, desired_access, this, file);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
54
src/xenia/kernel/xboxkrnl/fs/devices/host_path_entry.h
Normal file
54
src/xenia/kernel/xboxkrnl/fs/devices/host_path_entry.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_ENTRY_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_ENTRY_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
|
||||
class HostPathEntry : public Entry {
|
||||
public:
|
||||
HostPathEntry(Type type, Device* device, const char* path,
|
||||
const xechar_t* local_path);
|
||||
virtual ~HostPathEntry();
|
||||
|
||||
const xechar_t* local_path() { return local_path_; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
|
||||
virtual MemoryMapping* CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length);
|
||||
|
||||
virtual X_STATUS Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file);
|
||||
|
||||
private:
|
||||
xechar_t* local_path_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_ENTRY_H_
|
||||
51
src/xenia/kernel/xboxkrnl/fs/devices/host_path_file.cc
Normal file
51
src/xenia/kernel/xboxkrnl/fs/devices/host_path_file.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/devices/host_path_file.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/host_path_entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
HostPathFile::HostPathFile(
|
||||
KernelState* kernel_state, uint32_t desired_access,
|
||||
HostPathEntry* entry, HANDLE file_handle) :
|
||||
entry_(entry), file_handle_(file_handle),
|
||||
XFile(kernel_state, desired_access) {
|
||||
}
|
||||
|
||||
HostPathFile::~HostPathFile() {
|
||||
CloseHandle(file_handle_);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::QueryInfo(XFileInfo* out_info) {
|
||||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
OVERLAPPED overlapped;
|
||||
overlapped.Pointer = (PVOID)byte_offset;
|
||||
overlapped.hEvent = NULL;
|
||||
DWORD bytes_read = 0;
|
||||
BOOL read = ReadFile(
|
||||
file_handle_, buffer, (DWORD)buffer_length, &bytes_read, &overlapped);
|
||||
if (read) {
|
||||
*out_bytes_read = bytes_read;
|
||||
return X_STATUS_SUCCESS;
|
||||
} else {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
52
src/xenia/kernel/xboxkrnl/fs/devices/host_path_file.h
Normal file
52
src/xenia/kernel/xboxkrnl/fs/devices/host_path_file.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_FILE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_FILE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/objects/xfile.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
class HostPathEntry;
|
||||
|
||||
|
||||
class HostPathFile : public XFile {
|
||||
public:
|
||||
HostPathFile(KernelState* kernel_state, uint32_t desired_access,
|
||||
HostPathEntry* entry, HANDLE file_handle);
|
||||
virtual ~HostPathFile();
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
|
||||
protected:
|
||||
virtual X_STATUS ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read);
|
||||
|
||||
private:
|
||||
HostPathEntry* entry_;
|
||||
HANDLE file_handle_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_DEVICES_HOST_PATH_FILE_H_
|
||||
17
src/xenia/kernel/xboxkrnl/fs/devices/sources.gypi
Normal file
17
src/xenia/kernel/xboxkrnl/fs/devices/sources.gypi
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'disc_image_device.cc',
|
||||
'disc_image_device.h',
|
||||
'disc_image_entry.cc',
|
||||
'disc_image_entry.h',
|
||||
'disc_image_file.cc',
|
||||
'disc_image_file.h',
|
||||
'host_path_device.cc',
|
||||
'host_path_device.h',
|
||||
'host_path_entry.cc',
|
||||
'host_path_entry.h',
|
||||
'host_path_file.cc',
|
||||
'host_path_file.h',
|
||||
],
|
||||
}
|
||||
37
src/xenia/kernel/xboxkrnl/fs/entry.cc
Normal file
37
src/xenia/kernel/xboxkrnl/fs/entry.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
MemoryMapping::MemoryMapping(uint8_t* address, size_t length) :
|
||||
address_(address), length_(length) {
|
||||
}
|
||||
|
||||
MemoryMapping::~MemoryMapping() {
|
||||
}
|
||||
|
||||
|
||||
Entry::Entry(Type type, Device* device, const char* path) :
|
||||
type_(type),
|
||||
device_(device) {
|
||||
path_ = xestrdupa(path);
|
||||
// TODO(benvanik): last index of \, unless \ at end, then before that
|
||||
name_ = NULL;
|
||||
}
|
||||
|
||||
Entry::~Entry() {
|
||||
xe_free(path_);
|
||||
xe_free(name_);
|
||||
}
|
||||
85
src/xenia/kernel/xboxkrnl/fs/entry.h
Normal file
85
src/xenia/kernel/xboxkrnl/fs/entry.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_ENTRY_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_ENTRY_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
XEDECLARECLASS3(xe, kernel, xboxkrnl, KernelState);
|
||||
XEDECLARECLASS3(xe, kernel, xboxkrnl, XFile);
|
||||
XEDECLARECLASS3(xe, kernel, xboxkrnl, XFileInfo);
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
class Device;
|
||||
|
||||
|
||||
class MemoryMapping {
|
||||
public:
|
||||
MemoryMapping(uint8_t* address, size_t length);
|
||||
virtual ~MemoryMapping();
|
||||
|
||||
uint8_t* address() const { return address_; }
|
||||
size_t length() const { return length_; }
|
||||
|
||||
private:
|
||||
uint8_t* address_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
enum Type {
|
||||
kTypeFile,
|
||||
kTypeDirectory,
|
||||
};
|
||||
|
||||
Entry(Type type, Device* device, const char* path);
|
||||
virtual ~Entry();
|
||||
|
||||
Type type() const { return type_; }
|
||||
Device* device() const { return device_; }
|
||||
const char* path() const { return path_; }
|
||||
const char* name() const { return name_; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0;
|
||||
|
||||
virtual MemoryMapping* CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length) = 0;
|
||||
|
||||
virtual X_STATUS Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file) = 0;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
Device* device_;
|
||||
char* path_;
|
||||
char* name_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_ENTRY_H_
|
||||
113
src/xenia/kernel/xboxkrnl/fs/filesystem.cc
Normal file
113
src/xenia/kernel/xboxkrnl/fs/filesystem.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/fs/filesystem.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/disc_image_device.h>
|
||||
#include <xenia/kernel/xboxkrnl/fs/devices/host_path_device.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
FileSystem::FileSystem() {
|
||||
}
|
||||
|
||||
FileSystem::~FileSystem() {
|
||||
// Delete all devices.
|
||||
// This will explode if anyone is still using data from them.
|
||||
for (std::vector<Device*>::iterator it = devices_.begin();
|
||||
it != devices_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
devices_.clear();
|
||||
symlinks_.clear();
|
||||
}
|
||||
|
||||
int FileSystem::RegisterDevice(const char* path, Device* device) {
|
||||
devices_.push_back(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileSystem::RegisterHostPathDevice(
|
||||
const char* path, const xechar_t* local_path) {
|
||||
Device* device = new HostPathDevice(path, local_path);
|
||||
return RegisterDevice(path, device);
|
||||
}
|
||||
|
||||
int FileSystem::RegisterDiscImageDevice(
|
||||
const char* path, const xechar_t* local_path) {
|
||||
DiscImageDevice* device = new DiscImageDevice(path, local_path);
|
||||
if (device->Init()) {
|
||||
return 1;
|
||||
}
|
||||
return RegisterDevice(path, device);
|
||||
}
|
||||
|
||||
int FileSystem::CreateSymbolicLink(const char* path, const char* target) {
|
||||
symlinks_.insert(std::pair<const char*, const char*>(
|
||||
xestrdupa(path),
|
||||
xestrdupa(target)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileSystem::DeleteSymbolicLink(const char* path) {
|
||||
std::tr1::unordered_map<std::string, std::string>::iterator it =
|
||||
symlinks_.find(std::string(path));
|
||||
if (it != symlinks_.end()) {
|
||||
symlinks_.erase(it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Entry* FileSystem::ResolvePath(const char* path) {
|
||||
// Strip off prefix and pass to device.
|
||||
// e.g., d:\some\PATH.foo -> some\PATH.foo
|
||||
// Support both symlinks and device specifiers, like:
|
||||
// \\Device\Foo\some\PATH.foo, d:\some\PATH.foo, etc.
|
||||
|
||||
// TODO(benvanik): normalize path/etc
|
||||
// e.g., remove ..'s and such
|
||||
|
||||
// Resolve symlinks.
|
||||
// TODO(benvanik): more robust symlink handling - right now we assume simple
|
||||
// drive path -> device mappings with nothing nested.
|
||||
char full_path[XE_MAX_PATH];
|
||||
XEIGNORE(xestrcpya(full_path, XECOUNT(full_path), path));
|
||||
for (std::tr1::unordered_map<std::string, std::string>::iterator it =
|
||||
symlinks_.begin(); it != symlinks_.end(); ++it) {
|
||||
if (xestrcasestra(path, it->first.c_str()) == path) {
|
||||
// Found symlink, fixup.
|
||||
const char* after_path = path + it->first.size();
|
||||
XEIGNORE(xesnprintfa(full_path, XECOUNT(full_path), "%s%s",
|
||||
it->second.c_str(), after_path));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan all devices.
|
||||
for (std::vector<Device*>::iterator it = devices_.begin();
|
||||
it != devices_.end(); ++it) {
|
||||
Device* device = *it;
|
||||
if (xestrcasestra(full_path, device->path()) == full_path) {
|
||||
// Found!
|
||||
// Trim the device prefix off and pass down.
|
||||
char device_path[XE_MAX_PATH];
|
||||
XEIGNORE(xestrcpya(device_path, XECOUNT(device_path),
|
||||
full_path + xestrlena(device->path())));
|
||||
return device->ResolvePath(device_path);
|
||||
}
|
||||
}
|
||||
|
||||
XELOGE("ResolvePath(%s) failed - no root found", path);
|
||||
return NULL;
|
||||
}
|
||||
56
src/xenia/kernel/xboxkrnl/fs/filesystem.h
Normal file
56
src/xenia/kernel/xboxkrnl/fs/filesystem.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_FILESYSTEM_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_FILESYSTEM_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
|
||||
class Device;
|
||||
|
||||
|
||||
class FileSystem {
|
||||
public:
|
||||
FileSystem();
|
||||
~FileSystem();
|
||||
|
||||
int RegisterDevice(const char* path, Device* device);
|
||||
int RegisterHostPathDevice(const char* path, const xechar_t* local_path);
|
||||
int RegisterDiscImageDevice(const char* path, const xechar_t* local_path);
|
||||
|
||||
int CreateSymbolicLink(const char* path, const char* target);
|
||||
int DeleteSymbolicLink(const char* path);
|
||||
|
||||
Entry* ResolvePath(const char* path);
|
||||
|
||||
private:
|
||||
std::vector<Device*> devices_;
|
||||
std::tr1::unordered_map<std::string, std::string> symlinks_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_FILESYSTEM_H_
|
||||
209
src/xenia/kernel/xboxkrnl/fs/gdfx.cc
Normal file
209
src/xenia/kernel/xboxkrnl/fs/gdfx.cc
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
* Major contributions to this file from:
|
||||
* - abgx360
|
||||
*/
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/fs/gdfx.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
#define kXESectorSize 2048
|
||||
|
||||
}
|
||||
|
||||
|
||||
GDFXEntry::GDFXEntry() :
|
||||
attributes(X_FILE_ATTRIBUTE_NONE), offset(0), size(0) {
|
||||
}
|
||||
|
||||
GDFXEntry::~GDFXEntry() {
|
||||
for (std::vector<GDFXEntry*>::iterator it = children.begin();
|
||||
it != children.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
GDFXEntry* GDFXEntry::GetChild(const char* name) {
|
||||
// TODO(benvanik): a faster search
|
||||
for (std::vector<GDFXEntry*>::iterator it = children.begin();
|
||||
it != children.end(); ++it) {
|
||||
GDFXEntry* entry = *it;
|
||||
if (xestrcasecmpa(entry->name.c_str(), name) == 0) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GDFXEntry::Dump(int indent) {
|
||||
printf("%s%s\n", std::string(indent, ' ').c_str(), name.c_str());
|
||||
for (std::vector<GDFXEntry*>::iterator it = children.begin();
|
||||
it != children.end(); ++it) {
|
||||
GDFXEntry* entry = *it;
|
||||
entry->Dump(indent + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GDFX::GDFX(xe_mmap_ref mmap) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
|
||||
root_entry_ = NULL;
|
||||
}
|
||||
|
||||
GDFX::~GDFX() {
|
||||
delete root_entry_;
|
||||
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
|
||||
GDFXEntry* GDFX::root_entry() {
|
||||
return root_entry_;
|
||||
}
|
||||
|
||||
GDFX::Error GDFX::Load() {
|
||||
Error result = kErrorOutOfMemory;
|
||||
|
||||
ParseState state;
|
||||
xe_zero_struct(&state, sizeof(state));
|
||||
|
||||
state.ptr = (uint8_t*)xe_mmap_get_addr(mmap_);
|
||||
state.size = xe_mmap_get_length(mmap_);
|
||||
|
||||
result = Verify(state);
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
result = ReadAllEntries(state, state.ptr + state.root_offset);
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
result = kSuccess;
|
||||
XECLEANUP:
|
||||
return result;
|
||||
}
|
||||
|
||||
void GDFX::Dump() {
|
||||
if (root_entry_) {
|
||||
root_entry_->Dump(0);
|
||||
}
|
||||
}
|
||||
|
||||
GDFX::Error GDFX::Verify(ParseState& state) {
|
||||
// Find sector 32 of the game partition - try at a few points.
|
||||
const static size_t likely_offsets[] = {
|
||||
0x00000000, 0x0000FB20, 0x00020600, 0x0FD90000,
|
||||
};
|
||||
bool magic_found = false;
|
||||
for (size_t n = 0; n < XECOUNT(likely_offsets); n++) {
|
||||
state.game_offset = likely_offsets[n];
|
||||
if (VerifyMagic(state, state.game_offset + (32 * kXESectorSize))) {
|
||||
magic_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!magic_found) {
|
||||
// File doesn't have the magic values - likely not a real GDFX source.
|
||||
return kErrorFileMismatch;
|
||||
}
|
||||
|
||||
// Read sector 32 to get FS state.
|
||||
if (state.size < state.game_offset + (32 * kXESectorSize)) {
|
||||
return kErrorReadError;
|
||||
}
|
||||
uint8_t* fs_ptr = state.ptr + state.game_offset + (32 * kXESectorSize);
|
||||
state.root_sector = XEGETUINT32LE(fs_ptr + 20);
|
||||
state.root_size = XEGETUINT32LE(fs_ptr + 24);
|
||||
state.root_offset = state.game_offset + (state.root_sector * kXESectorSize);
|
||||
if (state.root_size < 13 ||
|
||||
state.root_size > 32 * 1024 * 1024) {
|
||||
return kErrorDamagedFile;
|
||||
}
|
||||
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
bool GDFX::VerifyMagic(ParseState& state, size_t offset) {
|
||||
// Simple check to see if the given offset contains the magic value.
|
||||
return memcmp(state.ptr + offset, "MICROSOFT*XBOX*MEDIA", 20) == 0;
|
||||
}
|
||||
|
||||
GDFX::Error GDFX::ReadAllEntries(ParseState& state,
|
||||
const uint8_t* root_buffer) {
|
||||
root_entry_ = new GDFXEntry();
|
||||
root_entry_->offset = 0;
|
||||
root_entry_->size = 0;
|
||||
root_entry_->name = "";
|
||||
root_entry_->attributes = X_FILE_ATTRIBUTE_DIRECTORY;
|
||||
|
||||
if (!ReadEntry(state, root_buffer, 0, root_entry_)) {
|
||||
return kErrorOutOfMemory;
|
||||
}
|
||||
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer,
|
||||
uint16_t entry_ordinal, GDFXEntry* parent) {
|
||||
const uint8_t* p = buffer + (entry_ordinal * 4);
|
||||
|
||||
uint16_t node_l = XEGETUINT16LE(p + 0);
|
||||
uint16_t node_r = XEGETUINT16LE(p + 2);
|
||||
size_t sector = XEGETUINT32LE(p + 4);
|
||||
size_t length = XEGETUINT32LE(p + 8);
|
||||
uint8_t attributes = XEGETUINT8LE(p + 12);
|
||||
uint8_t name_length = XEGETUINT8LE(p + 13);
|
||||
char* name = (char*)(p + 14);
|
||||
|
||||
if (node_l && !ReadEntry(state, buffer, node_l, parent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GDFXEntry* entry = new GDFXEntry();
|
||||
entry->name = std::string(name, name_length);
|
||||
entry->name.append(1, '\0');
|
||||
entry->attributes = (X_FILE_ATTRIBUTES)attributes;
|
||||
|
||||
// Add to parent.
|
||||
parent->children.push_back(entry);
|
||||
|
||||
if (attributes & X_FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// Folder.
|
||||
entry->offset = 0;
|
||||
entry->size = 0;
|
||||
if (length) {
|
||||
// Not a leaf - read in children.
|
||||
if (state.size < state.game_offset + (sector * kXESectorSize)) {
|
||||
// Out of bounds read.
|
||||
return false;
|
||||
}
|
||||
// Read child list.
|
||||
uint8_t* folder_ptr =
|
||||
state.ptr + state.game_offset + (sector * kXESectorSize);
|
||||
if (!ReadEntry(state, folder_ptr, 0, entry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// File.
|
||||
entry->offset = state.game_offset + (sector * kXESectorSize);
|
||||
entry->size = length;
|
||||
}
|
||||
|
||||
// Read next file in the list.
|
||||
if (node_r && !ReadEntry(state, buffer, node_r, parent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
98
src/xenia/kernel/xboxkrnl/fs/gdfx.h
Normal file
98
src/xenia/kernel/xboxkrnl/fs/gdfx.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_FS_GDFX_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_FS_GDFX_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/kernel/xboxkrnl/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
namespace fs {
|
||||
|
||||
|
||||
class GDFX;
|
||||
|
||||
|
||||
class GDFXEntry {
|
||||
public:
|
||||
GDFXEntry();
|
||||
~GDFXEntry();
|
||||
|
||||
GDFXEntry* GetChild(const char* name);
|
||||
|
||||
void Dump(int indent);
|
||||
|
||||
std::string name;
|
||||
X_FILE_ATTRIBUTES attributes;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
|
||||
std::vector<GDFXEntry*> children;
|
||||
};
|
||||
|
||||
|
||||
class GDFX {
|
||||
public:
|
||||
enum Error {
|
||||
kSuccess = 0,
|
||||
kErrorOutOfMemory = -1,
|
||||
kErrorReadError = -10,
|
||||
kErrorFileMismatch = -30,
|
||||
kErrorDamagedFile = -31,
|
||||
};
|
||||
|
||||
GDFX(xe_mmap_ref mmap);
|
||||
virtual ~GDFX();
|
||||
|
||||
GDFXEntry* root_entry();
|
||||
|
||||
Error Load();
|
||||
void Dump();
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
uint8_t* ptr;
|
||||
|
||||
size_t size; // Size (bytes) of total image
|
||||
|
||||
size_t game_offset; // Offset (bytes) of game partition
|
||||
|
||||
size_t root_sector; // Offset (sector) of root
|
||||
size_t root_offset; // Offset (bytes) of root
|
||||
size_t root_size; // Size (bytes) of root
|
||||
} ParseState;
|
||||
|
||||
Error Verify(ParseState& state);
|
||||
bool VerifyMagic(ParseState& state, size_t offset);
|
||||
Error ReadAllEntries(ParseState& state, const uint8_t* root_buffer);
|
||||
bool ReadEntry(ParseState& state, const uint8_t* buffer,
|
||||
uint16_t entry_ordinal, GDFXEntry* parent);
|
||||
|
||||
xe_mmap_ref mmap_;
|
||||
|
||||
GDFXEntry* root_entry_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_FS_GDFX_H_
|
||||
17
src/xenia/kernel/xboxkrnl/fs/sources.gypi
Normal file
17
src/xenia/kernel/xboxkrnl/fs/sources.gypi
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'device.cc',
|
||||
'device.h',
|
||||
'entry.cc',
|
||||
'entry.h',
|
||||
'filesystem.cc',
|
||||
'filesystem.h',
|
||||
'gdfx.cc',
|
||||
'gdfx.h',
|
||||
],
|
||||
|
||||
'includes': [
|
||||
'devices/sources.gypi',
|
||||
],
|
||||
}
|
||||
76
src/xenia/kernel/xboxkrnl/kernel_state.cc
Normal file
76
src/xenia/kernel/xboxkrnl/kernel_state.cc
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/kernel_state.h>
|
||||
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
KernelState::KernelState(Emulator* emulator) :
|
||||
emulator_(emulator),
|
||||
executable_module_(NULL) {
|
||||
memory_ = xe_memory_retain(emulator->memory());
|
||||
processor_ = emulator->processor();
|
||||
file_system_ = emulator->file_system();
|
||||
|
||||
object_table_ = new ObjectTable();
|
||||
object_mutex_ = xe_mutex_alloc(10000);
|
||||
}
|
||||
|
||||
KernelState::~KernelState() {
|
||||
SetExecutableModule(NULL);
|
||||
|
||||
// Delete all objects.
|
||||
xe_mutex_free(object_mutex_);
|
||||
delete object_table_;
|
||||
|
||||
xe_memory_release(memory_);
|
||||
}
|
||||
|
||||
KernelState* KernelState::shared() {
|
||||
return shared_kernel_state_;
|
||||
}
|
||||
|
||||
XModule* KernelState::GetModule(const char* name) {
|
||||
// TODO(benvanik): implement lookup. Most games seem to look for xam.xex/etc.
|
||||
XEASSERTALWAYS();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XModule* KernelState::GetExecutableModule() {
|
||||
if (!executable_module_) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
executable_module_->Retain();
|
||||
return executable_module_;
|
||||
}
|
||||
|
||||
void KernelState::SetExecutableModule(XModule* module) {
|
||||
if (module == executable_module_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (executable_module_) {
|
||||
executable_module_->Release();
|
||||
}
|
||||
executable_module_ = module;
|
||||
if (executable_module_) {
|
||||
executable_module_->Retain();
|
||||
}
|
||||
}
|
||||
71
src/xenia/kernel/xboxkrnl/kernel_state.h
Normal file
71
src/xenia/kernel/xboxkrnl/kernel_state.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_KERNEL_STATE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_KERNEL_STATE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/kernel/kernel_module.h>
|
||||
#include <xenia/kernel/xboxkrnl/object_table.h>
|
||||
#include <xenia/kernel/xboxkrnl/fs/filesystem.h>
|
||||
|
||||
|
||||
XEDECLARECLASS2(xe, cpu, Processor);
|
||||
XEDECLARECLASS3(xe, kernel, fs, FileSystem);
|
||||
XEDECLARECLASS3(xe, kernel, xboxkrnl, XModule);
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
class KernelState {
|
||||
public:
|
||||
KernelState(Emulator* emulator);
|
||||
~KernelState();
|
||||
|
||||
static KernelState* shared();
|
||||
|
||||
Emulator* emulator() const { return emulator_; }
|
||||
xe_memory_ref memory() const { return memory_; }
|
||||
cpu::Processor* processor() const { return processor_; }
|
||||
fs::FileSystem* file_system() const { return file_system_; }
|
||||
|
||||
ObjectTable* object_table() const { return object_table_; }
|
||||
|
||||
XModule* GetModule(const char* name);
|
||||
XModule* GetExecutableModule();
|
||||
void SetExecutableModule(XModule* module);
|
||||
|
||||
private:
|
||||
Emulator* emulator_;
|
||||
xe_memory_ref memory_;
|
||||
cpu::Processor* processor_;
|
||||
fs::FileSystem* file_system_;
|
||||
|
||||
ObjectTable* object_table_;
|
||||
xe_mutex_t* object_mutex_;
|
||||
|
||||
XModule* executable_module_;
|
||||
|
||||
friend class XObject;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_KERNEL_STATE_H_
|
||||
194
src/xenia/kernel/xboxkrnl/object_table.cc
Normal file
194
src/xenia/kernel/xboxkrnl/object_table.cc
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/object_table.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
ObjectTable::ObjectTable() :
|
||||
table_capacity_(0),
|
||||
table_(NULL),
|
||||
last_free_entry_(0) {
|
||||
table_mutex_ = xe_mutex_alloc(0);
|
||||
XEASSERTNOTNULL(table_mutex_);
|
||||
}
|
||||
|
||||
ObjectTable::~ObjectTable() {
|
||||
xe_mutex_lock(table_mutex_);
|
||||
|
||||
// Release all objects.
|
||||
for (uint32_t n = 0; n < table_capacity_; n++) {
|
||||
ObjectTableEntry& entry = table_[n];
|
||||
if (entry.object) {
|
||||
entry.object->ReleaseHandle();
|
||||
entry.object->Release();
|
||||
}
|
||||
}
|
||||
|
||||
table_capacity_ = 0;
|
||||
last_free_entry_ = 0;
|
||||
xe_free(table_);
|
||||
table_ = NULL;
|
||||
|
||||
xe_mutex_unlock(table_mutex_);
|
||||
|
||||
xe_mutex_free(table_mutex_);
|
||||
table_mutex_ = NULL;
|
||||
}
|
||||
|
||||
X_STATUS ObjectTable::FindFreeSlot(uint32_t* out_slot) {
|
||||
// Find a free slot.
|
||||
uint32_t slot = last_free_entry_;
|
||||
uint32_t scan_count = 0;
|
||||
while (scan_count < table_capacity_) {
|
||||
ObjectTableEntry& entry = table_[slot];
|
||||
if (!entry.object) {
|
||||
*out_slot = slot;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
scan_count++;
|
||||
slot = (slot + 1) % table_capacity_;
|
||||
if (slot == 0) {
|
||||
// Never allow 0 handles.
|
||||
scan_count++;
|
||||
slot++;
|
||||
}
|
||||
}
|
||||
|
||||
// Table out of slots, expand.
|
||||
uint32_t new_table_capacity = MAX(16 * 1024, table_capacity_ * 2);
|
||||
ObjectTableEntry* new_table = (ObjectTableEntry*)xe_recalloc(
|
||||
table_,
|
||||
table_capacity_ * sizeof(ObjectTableEntry),
|
||||
new_table_capacity * sizeof(ObjectTableEntry));
|
||||
if (!new_table) {
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
last_free_entry_ = table_capacity_;
|
||||
table_capacity_ = new_table_capacity;
|
||||
table_ = new_table;
|
||||
|
||||
// Never allow 0 handles.
|
||||
slot = ++last_free_entry_;
|
||||
*out_slot = slot;
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS ObjectTable::AddHandle(XObject* object, X_HANDLE* out_handle) {
|
||||
XEASSERTNOTNULL(out_handle);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
xe_mutex_lock(table_mutex_);
|
||||
|
||||
// Find a free slot.
|
||||
uint32_t slot = 0;
|
||||
result = FindFreeSlot(&slot);
|
||||
|
||||
// Stash.
|
||||
if (XSUCCEEDED(result)) {
|
||||
ObjectTableEntry& entry = table_[slot];
|
||||
entry.object = object;
|
||||
|
||||
// Retain so long as the object is in the table.
|
||||
object->RetainHandle();
|
||||
object->Retain();
|
||||
}
|
||||
|
||||
xe_mutex_unlock(table_mutex_);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
*out_handle = slot << 2;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
X_STATUS ObjectTable::RemoveHandle(X_HANDLE handle) {
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
xe_mutex_lock(table_mutex_);
|
||||
|
||||
// Lower 2 bits are ignored.
|
||||
uint32_t slot = handle >> 2;
|
||||
|
||||
// Verify slot.
|
||||
XObject* object = NULL;
|
||||
if (slot > table_capacity_) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
} else {
|
||||
ObjectTableEntry& entry = table_[slot];
|
||||
if (entry.object) {
|
||||
// Release after we lose the lock.
|
||||
object = entry.object;
|
||||
} else {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
xe_mutex_unlock(table_mutex_);
|
||||
|
||||
if (object) {
|
||||
// Release the object handle now that it is out of the table.
|
||||
object->ReleaseHandle();
|
||||
object->Release();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
X_STATUS ObjectTable::GetObject(X_HANDLE handle, XObject** out_object) {
|
||||
XEASSERTNOTNULL(out_object);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
if (handle == 0xFFFFFFFF) {
|
||||
// CurrentProcess
|
||||
XEASSERTALWAYS();
|
||||
} else if (handle == 0xFFFFFFFE) {
|
||||
// CurrentThread
|
||||
handle = XThread::GetCurrentThreadHandle();
|
||||
}
|
||||
|
||||
xe_mutex_lock(table_mutex_);
|
||||
|
||||
// Lower 2 bits are ignored.
|
||||
uint32_t slot = handle >> 2;
|
||||
|
||||
// Verify slot.
|
||||
XObject* object = NULL;
|
||||
if (slot > table_capacity_) {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
} else {
|
||||
ObjectTableEntry& entry = table_[slot];
|
||||
if (entry.object) {
|
||||
object = entry.object;
|
||||
} else {
|
||||
result = X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Retain the object pointer.
|
||||
if (object) {
|
||||
object->Retain();
|
||||
}
|
||||
|
||||
xe_mutex_unlock(table_mutex_);
|
||||
|
||||
*out_object = object;
|
||||
return result;
|
||||
}
|
||||
55
src/xenia/kernel/xboxkrnl/object_table.h
Normal file
55
src/xenia/kernel/xboxkrnl/object_table.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_OBJECT_TABLE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_OBJECT_TABLE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
class XObject;
|
||||
|
||||
|
||||
class ObjectTable {
|
||||
public:
|
||||
ObjectTable();
|
||||
~ObjectTable();
|
||||
|
||||
X_STATUS AddHandle(XObject* object, X_HANDLE* out_handle);
|
||||
X_STATUS RemoveHandle(X_HANDLE handle);
|
||||
X_STATUS GetObject(X_HANDLE handle, XObject** out_object);
|
||||
|
||||
private:
|
||||
X_STATUS FindFreeSlot(uint32_t* out_slot);
|
||||
|
||||
typedef struct {
|
||||
XObject* object;
|
||||
} ObjectTableEntry;
|
||||
|
||||
xe_mutex_t* table_mutex_;
|
||||
uint32_t table_capacity_;
|
||||
ObjectTableEntry* table_;
|
||||
uint32_t last_free_entry_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_OBJECT_TABLE_H_
|
||||
13
src/xenia/kernel/xboxkrnl/objects/sources.gypi
Normal file
13
src/xenia/kernel/xboxkrnl/objects/sources.gypi
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'xevent.cc',
|
||||
'xevent.h',
|
||||
'xfile.cc',
|
||||
'xfile.h',
|
||||
'xmodule.cc',
|
||||
'xmodule.h',
|
||||
'xthread.cc',
|
||||
'xthread.h',
|
||||
],
|
||||
}
|
||||
99
src/xenia/kernel/xboxkrnl/objects/xevent.cc
Normal file
99
src/xenia/kernel/xboxkrnl/objects/xevent.cc
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/objects/xevent.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
XEvent::XEvent(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeEvent),
|
||||
handle_(NULL) {
|
||||
}
|
||||
|
||||
XEvent::~XEvent() {
|
||||
}
|
||||
|
||||
void XEvent::Initialize(bool manual_reset, bool initial_state) {
|
||||
XEASSERTNULL(handle_);
|
||||
|
||||
handle_ = CreateEvent(NULL, manual_reset, initial_state, NULL);
|
||||
}
|
||||
|
||||
void XEvent::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) {
|
||||
XEASSERTNULL(handle_);
|
||||
|
||||
bool manual_reset;
|
||||
switch (header.type_flags >> 24) {
|
||||
case 0x00: // EventNotificationObject (manual reset)
|
||||
manual_reset = true;
|
||||
break;
|
||||
case 0x01: // EventSynchronizationObject (auto reset)
|
||||
manual_reset = false;
|
||||
break;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
return;
|
||||
}
|
||||
|
||||
bool initial_state = header.signal_state ? true : false;
|
||||
|
||||
handle_ = CreateEvent(NULL, manual_reset, initial_state, NULL);
|
||||
}
|
||||
|
||||
int32_t XEvent::Set(uint32_t priority_increment, bool wait) {
|
||||
return SetEvent(handle_) ? 1 : 0;
|
||||
}
|
||||
|
||||
int32_t XEvent::Reset() {
|
||||
return ResetEvent(handle_) ? 1 : 0;
|
||||
}
|
||||
|
||||
void XEvent::Clear() {
|
||||
ResetEvent(handle_);
|
||||
}
|
||||
|
||||
X_STATUS XEvent::Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout) {
|
||||
DWORD timeout_ms;
|
||||
if (opt_timeout) {
|
||||
int64_t timeout_ticks = (int64_t)(*opt_timeout);
|
||||
if (timeout_ticks > 0) {
|
||||
// Absolute time, based on January 1, 1601.
|
||||
// TODO(benvanik): convert time to relative time.
|
||||
XEASSERTALWAYS();
|
||||
timeout_ms = 0;
|
||||
} else if (timeout_ticks < 0) {
|
||||
// Relative time.
|
||||
timeout_ms = (DWORD)(-timeout_ticks / 10000); // Ticks -> MS
|
||||
} else {
|
||||
timeout_ms = 0;
|
||||
}
|
||||
} else {
|
||||
timeout_ms = INFINITE;
|
||||
}
|
||||
|
||||
DWORD result = WaitForSingleObjectEx(handle_, timeout_ms, alertable);
|
||||
switch (result) {
|
||||
case WAIT_OBJECT_0:
|
||||
return X_STATUS_SUCCESS;
|
||||
case WAIT_IO_COMPLETION:
|
||||
// Or X_STATUS_ALERTED?
|
||||
return X_STATUS_USER_APC;
|
||||
case WAIT_TIMEOUT:
|
||||
return X_STATUS_TIMEOUT;
|
||||
default:
|
||||
case WAIT_FAILED:
|
||||
case WAIT_ABANDONED:
|
||||
return X_STATUS_ABANDONED_WAIT_0;
|
||||
}
|
||||
}
|
||||
48
src/xenia/kernel/xboxkrnl/objects/xevent.h
Normal file
48
src/xenia/kernel/xboxkrnl/objects/xevent.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XEVENT_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XEVENT_H_
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
class XEvent : public XObject {
|
||||
public:
|
||||
XEvent(KernelState* kernel_state);
|
||||
virtual ~XEvent();
|
||||
|
||||
void Initialize(bool manual_reset, bool initial_state);
|
||||
void InitializeNative(void* native_ptr, DISPATCH_HEADER& header);
|
||||
|
||||
int32_t Set(uint32_t priority_increment, bool wait);
|
||||
int32_t Reset();
|
||||
void Clear();
|
||||
|
||||
virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout);
|
||||
|
||||
private:
|
||||
HANDLE handle_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XEVENT_H_
|
||||
62
src/xenia/kernel/xboxkrnl/objects/xfile.cc
Normal file
62
src/xenia/kernel/xboxkrnl/objects/xfile.cc
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/objects/xfile.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/async_request.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xevent.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
XFile::XFile(KernelState* kernel_state, uint32_t desired_access) :
|
||||
desired_access_(desired_access), position_(0),
|
||||
XObject(kernel_state, kTypeFile) {
|
||||
async_event_ = new XEvent(kernel_state);
|
||||
async_event_->Initialize(false, false);
|
||||
}
|
||||
|
||||
XFile::~XFile() {
|
||||
// TODO(benvanik): signal that the file is closing?
|
||||
async_event_->Set(0, false);
|
||||
async_event_->Delete();
|
||||
}
|
||||
|
||||
X_STATUS XFile::Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout) {
|
||||
// Wait until some async operation completes.
|
||||
return async_event_->Wait(
|
||||
wait_reason, processor_mode, alertable, opt_timeout);
|
||||
}
|
||||
|
||||
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
if (byte_offset == -1) {
|
||||
// Read from current position.
|
||||
byte_offset = position_;
|
||||
}
|
||||
X_STATUS result = ReadSync(buffer, buffer_length, byte_offset, out_bytes_read);
|
||||
if (XSUCCEEDED(result)) {
|
||||
position_ += *out_bytes_read;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
XAsyncRequest* request) {
|
||||
// Also tack on our event so that any waiters wake.
|
||||
request->AddWaitEvent(async_event_);
|
||||
position_ = byte_offset;
|
||||
//return entry_->ReadAsync(buffer, buffer_length, byte_offset, request);
|
||||
X_STATUS result = X_STATUS_NOT_IMPLEMENTED;
|
||||
return result;
|
||||
}
|
||||
87
src/xenia/kernel/xboxkrnl/objects/xfile.h
Normal file
87
src/xenia/kernel/xboxkrnl/objects/xfile.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XFILE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XFILE_H_
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
class XAsyncRequest;
|
||||
class XEvent;
|
||||
|
||||
class XFileInfo {
|
||||
public:
|
||||
// FILE_NETWORK_OPEN_INFORMATION
|
||||
uint64_t creation_time;
|
||||
uint64_t last_access_time;
|
||||
uint64_t last_write_time;
|
||||
uint64_t change_time;
|
||||
uint64_t allocation_size;
|
||||
uint64_t file_length;
|
||||
X_FILE_ATTRIBUTES attributes;
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
XESETUINT64BE(base + p, creation_time);
|
||||
XESETUINT64BE(base + p + 8, last_access_time);
|
||||
XESETUINT64BE(base + p + 16, last_write_time);
|
||||
XESETUINT64BE(base + p + 24, change_time);
|
||||
XESETUINT64BE(base + p + 32, allocation_size);
|
||||
XESETUINT64BE(base + p + 40, file_length);
|
||||
XESETUINT32BE(base + p + 48, attributes);
|
||||
XESETUINT32BE(base + p + 52, 0); // pad
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class XFile : public XObject {
|
||||
public:
|
||||
virtual ~XFile();
|
||||
|
||||
size_t position() const { return position_; }
|
||||
void set_position(size_t value) { position_ = value; }
|
||||
|
||||
virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout);
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0;
|
||||
|
||||
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read);
|
||||
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
XAsyncRequest* request);
|
||||
|
||||
protected:
|
||||
XFile(KernelState* kernel_state, uint32_t desired_access);
|
||||
virtual X_STATUS ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) = 0;
|
||||
|
||||
private:
|
||||
uint32_t desired_access_;
|
||||
XEvent* async_event_;
|
||||
|
||||
// TODO(benvanik): create flags, open state, etc.
|
||||
|
||||
size_t position_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XFILE_H_
|
||||
330
src/xenia/kernel/xboxkrnl/objects/xmodule.cc
Normal file
330
src/xenia/kernel/xboxkrnl/objects/xmodule.cc
Normal file
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/objects/xmodule.h>
|
||||
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace {
|
||||
}
|
||||
|
||||
|
||||
XModule::XModule(KernelState* kernel_state, const char* path) :
|
||||
XObject(kernel_state, kTypeModule),
|
||||
xex_(NULL) {
|
||||
XEIGNORE(xestrcpya(path_, XECOUNT(path_), path));
|
||||
const char* slash = xestrrchra(path, '/');
|
||||
if (!slash) {
|
||||
slash = xestrrchra(path, '\\');
|
||||
}
|
||||
if (slash) {
|
||||
XEIGNORE(xestrcpya(name_, XECOUNT(name_), slash + 1));
|
||||
}
|
||||
}
|
||||
|
||||
XModule::~XModule() {
|
||||
xe_xex2_release(xex_);
|
||||
}
|
||||
|
||||
const char* XModule::path() {
|
||||
return path_;
|
||||
}
|
||||
|
||||
const char* XModule::name() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
xe_xex2_ref XModule::xex() {
|
||||
return xe_xex2_retain(xex_);
|
||||
}
|
||||
|
||||
const xe_xex2_header_t* XModule::xex_header() {
|
||||
return xe_xex2_get_header(xex_);
|
||||
}
|
||||
|
||||
X_STATUS XModule::LoadFromFile(const char* path) {
|
||||
// Resolve the file to open.
|
||||
// TODO(benvanik): make this code shared?
|
||||
fs::Entry* fs_entry = kernel_state()->file_system()->ResolvePath(path);
|
||||
if (!fs_entry) {
|
||||
XELOGE("File not found: %s", path);
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
if (fs_entry->type() != fs::Entry::kTypeFile) {
|
||||
XELOGE("Invalid file type: %s", path);
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
// Map into memory.
|
||||
fs::MemoryMapping* mmap = fs_entry->CreateMemoryMapping(kXEFileModeRead, 0, 0);
|
||||
if (!mmap) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Load the module.
|
||||
X_STATUS return_code = LoadFromMemory(mmap->address(), mmap->length());
|
||||
|
||||
// Unmap memory and cleanup.
|
||||
delete mmap;
|
||||
delete fs_entry;
|
||||
|
||||
return return_code;
|
||||
}
|
||||
|
||||
X_STATUS XModule::LoadFromMemory(const void* addr, const size_t length) {
|
||||
// Load the XEX into memory and decrypt.
|
||||
xe_xex2_options_t xex_options;
|
||||
xe_zero_struct(&xex_options, sizeof(xex_options));
|
||||
xex_ = xe_xex2_load(kernel_state()->memory(), addr, length, xex_options);
|
||||
XEEXPECTNOTNULL(xex_);
|
||||
|
||||
// Prepare the module for execution.
|
||||
XEEXPECTZERO(kernel_state()->processor()->LoadXexModule(name_, path_, xex_));
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
|
||||
XECLEANUP:
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
X_STATUS XModule::GetSection(const char* name,
|
||||
uint32_t* out_data, uint32_t* out_size) {
|
||||
const PESection* section = xe_xex2_get_pe_section(xex_, name);
|
||||
if (!section) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
*out_data = section->address;
|
||||
*out_size = section->size;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void* XModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
||||
// TODO(benvanik): check export tables.
|
||||
XELOGE("GetProcAddressByOrdinal not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X_STATUS XModule::Launch(uint32_t flags) {
|
||||
const xe_xex2_header_t* header = xex_header();
|
||||
|
||||
XELOGI("Launching module...");
|
||||
|
||||
// Set as the main module, while running.
|
||||
kernel_state()->SetExecutableModule(this);
|
||||
|
||||
Dump();
|
||||
|
||||
// Create a thread to run in.
|
||||
XThread* thread = new XThread(
|
||||
kernel_state(),
|
||||
header->exe_stack_size,
|
||||
0,
|
||||
header->exe_entry_point, NULL,
|
||||
0);
|
||||
|
||||
X_STATUS result = thread->Create();
|
||||
if (XFAILED(result)) {
|
||||
XELOGE("Could not create launch thread: %.8X", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Wait until thread completes.
|
||||
thread->Wait(0, 0, 0, NULL);
|
||||
|
||||
kernel_state()->SetExecutableModule(NULL);
|
||||
thread->Release();
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void XModule::Dump() {
|
||||
ExportResolver* export_resolver =
|
||||
kernel_state_->emulator()->export_resolver();
|
||||
const xe_xex2_header_t* header = xe_xex2_get_header(xex_);
|
||||
|
||||
// XEX info.
|
||||
printf("Module %s:\n\n", path_);
|
||||
printf(" Module Flags: %.8X\n", header->module_flags);
|
||||
printf(" System Flags: %.8X\n", header->system_flags);
|
||||
printf("\n");
|
||||
printf(" Address: %.8X\n", header->exe_address);
|
||||
printf(" Entry Point: %.8X\n", header->exe_entry_point);
|
||||
printf(" Stack Size: %.8X\n", header->exe_stack_size);
|
||||
printf(" Heap Size: %.8X\n", header->exe_heap_size);
|
||||
printf("\n");
|
||||
printf(" Execution Info:\n");
|
||||
printf(" Media ID: %.8X\n", header->execution_info.media_id);
|
||||
printf(" Version: %d.%d.%d.%d\n",
|
||||
header->execution_info.version.major,
|
||||
header->execution_info.version.minor,
|
||||
header->execution_info.version.build,
|
||||
header->execution_info.version.qfe);
|
||||
printf(" Base Version: %d.%d.%d.%d\n",
|
||||
header->execution_info.base_version.major,
|
||||
header->execution_info.base_version.minor,
|
||||
header->execution_info.base_version.build,
|
||||
header->execution_info.base_version.qfe);
|
||||
printf(" Title ID: %.8X\n", header->execution_info.title_id);
|
||||
printf(" Platform: %.8X\n", header->execution_info.platform);
|
||||
printf(" Exec Table: %.8X\n", header->execution_info.executable_table);
|
||||
printf(" Disc Number: %d\n", header->execution_info.disc_number);
|
||||
printf(" Disc Count: %d\n", header->execution_info.disc_count);
|
||||
printf(" Savegame ID: %.8X\n", header->execution_info.savegame_id);
|
||||
printf("\n");
|
||||
printf(" Loader Info:\n");
|
||||
printf(" Image Flags: %.8X\n", header->loader_info.image_flags);
|
||||
printf(" Game Regions: %.8X\n", header->loader_info.game_regions);
|
||||
printf(" Media Flags: %.8X\n", header->loader_info.media_flags);
|
||||
printf("\n");
|
||||
printf(" TLS Info:\n");
|
||||
printf(" Slot Count: %d\n", header->tls_info.slot_count);
|
||||
printf(" Data Size: %db\n", header->tls_info.data_size);
|
||||
printf(" Address: %.8X, %db\n", header->tls_info.raw_data_address,
|
||||
header->tls_info.raw_data_size);
|
||||
printf("\n");
|
||||
printf(" Headers:\n");
|
||||
for (size_t n = 0; n < header->header_count; n++) {
|
||||
const xe_xex2_opt_header_t* opt_header = &header->headers[n];
|
||||
printf(" %.8X (%.8X, %4db) %.8X = %11d\n",
|
||||
opt_header->key, opt_header->offset, opt_header->length,
|
||||
opt_header->value, opt_header->value);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Resources.
|
||||
printf("Resources:\n");
|
||||
printf(" %.8X, %db\n", header->resource_info.address,
|
||||
header->resource_info.size);
|
||||
printf(" TODO\n");
|
||||
printf("\n");
|
||||
|
||||
// Section info.
|
||||
printf("Sections:\n");
|
||||
for (size_t n = 0, i = 0; n < header->section_count; n++) {
|
||||
const xe_xex2_section_t* section = &header->sections[n];
|
||||
const char* type = "UNKNOWN";
|
||||
switch (section->info.type) {
|
||||
case XEX_SECTION_CODE:
|
||||
type = "CODE ";
|
||||
break;
|
||||
case XEX_SECTION_DATA:
|
||||
type = "RWDATA ";
|
||||
break;
|
||||
case XEX_SECTION_READONLY_DATA:
|
||||
type = "RODATA ";
|
||||
break;
|
||||
}
|
||||
const size_t start_address =
|
||||
header->exe_address + (i * xe_xex2_section_length);
|
||||
const size_t end_address =
|
||||
start_address + (section->info.page_count * xe_xex2_section_length);
|
||||
printf(" %3d %s %3d pages %.8X - %.8X (%d bytes)\n",
|
||||
(int)n, type, section->info.page_count, (int)start_address,
|
||||
(int)end_address, section->info.page_count * xe_xex2_section_length);
|
||||
i += section->info.page_count;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Static libraries.
|
||||
printf("Static Libraries:\n");
|
||||
for (size_t n = 0; n < header->static_library_count; n++) {
|
||||
const xe_xex2_static_library_t *library = &header->static_libraries[n];
|
||||
printf(" %-8s : %d.%d.%d.%d\n",
|
||||
library->name, library->major,
|
||||
library->minor, library->build, library->qfe);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Imports.
|
||||
printf("Imports:\n");
|
||||
for (size_t n = 0; n < header->import_library_count; n++) {
|
||||
const xe_xex2_import_library_t* library = &header->import_libraries[n];
|
||||
|
||||
xe_xex2_import_info_t* import_infos;
|
||||
size_t import_info_count;
|
||||
if (!xe_xex2_get_import_infos(xex_, library,
|
||||
&import_infos, &import_info_count)) {
|
||||
printf(" %s - %d imports\n", library->name, (int)import_info_count);
|
||||
printf(" Version: %d.%d.%d.%d\n",
|
||||
library->version.major, library->version.minor,
|
||||
library->version.build, library->version.qfe);
|
||||
printf(" Min Version: %d.%d.%d.%d\n",
|
||||
library->min_version.major, library->min_version.minor,
|
||||
library->min_version.build, library->min_version.qfe);
|
||||
printf("\n");
|
||||
|
||||
// Counts.
|
||||
int known_count = 0;
|
||||
int unknown_count = 0;
|
||||
int impl_count = 0;
|
||||
int unimpl_count = 0;
|
||||
for (size_t m = 0; m < import_info_count; m++) {
|
||||
const xe_xex2_import_info_t* info = &import_infos[m];
|
||||
KernelExport* kernel_export =
|
||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||
if (kernel_export) {
|
||||
known_count++;
|
||||
if (kernel_export->is_implemented) {
|
||||
impl_count++;
|
||||
}
|
||||
} else {
|
||||
unknown_count++;
|
||||
unimpl_count++;
|
||||
}
|
||||
}
|
||||
printf(" Total: %4u\n", import_info_count);
|
||||
printf(" Known: %3d%% (%d known, %d unknown)\n",
|
||||
(int)(known_count / (float)import_info_count * 100.0f),
|
||||
known_count, unknown_count);
|
||||
printf(" Implemented: %3d%% (%d implemented, %d unimplemented)\n",
|
||||
(int)(impl_count / (float)import_info_count * 100.0f),
|
||||
impl_count, unimpl_count);
|
||||
printf("\n");
|
||||
|
||||
// Listing.
|
||||
for (size_t m = 0; m < import_info_count; m++) {
|
||||
const xe_xex2_import_info_t* info = &import_infos[m];
|
||||
KernelExport* kernel_export = export_resolver->GetExportByOrdinal(
|
||||
library->name, info->ordinal);
|
||||
const char *name = "UNKNOWN";
|
||||
bool implemented = false;
|
||||
if (kernel_export) {
|
||||
name = kernel_export->name;
|
||||
implemented = kernel_export->is_implemented;
|
||||
}
|
||||
if (info->thunk_address) {
|
||||
printf(" F %.8X %.8X %.3X (%3d) %s %s\n",
|
||||
info->value_address, info->thunk_address, info->ordinal,
|
||||
info->ordinal, implemented ? " " : "!!", name);
|
||||
} else {
|
||||
printf(" V %.8X %.3X (%3d) %s %s\n",
|
||||
info->value_address, info->ordinal, info->ordinal,
|
||||
implemented ? " " : "!!", name);
|
||||
}
|
||||
}
|
||||
|
||||
xe_free(import_infos);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Exports.
|
||||
printf("Exports:\n");
|
||||
printf(" TODO\n");
|
||||
printf("\n");
|
||||
}
|
||||
62
src/xenia/kernel/xboxkrnl/objects/xmodule.h
Normal file
62
src/xenia/kernel/xboxkrnl/objects/xmodule.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XMODULE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XMODULE_H_
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/kernel/xex2.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
class XModule : public XObject {
|
||||
public:
|
||||
XModule(KernelState* kernel_state, const char* path);
|
||||
virtual ~XModule();
|
||||
|
||||
const char* path();
|
||||
const char* name();
|
||||
xe_xex2_ref xex();
|
||||
const xe_xex2_header_t* xex_header();
|
||||
|
||||
X_STATUS LoadFromFile(const char* path);
|
||||
X_STATUS LoadFromMemory(const void* addr, const size_t length);
|
||||
|
||||
X_STATUS GetSection(const char* name, uint32_t* out_data, uint32_t* out_size);
|
||||
void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||
|
||||
X_STATUS Launch(uint32_t flags);
|
||||
|
||||
void Dump();
|
||||
|
||||
private:
|
||||
int LoadPE();
|
||||
|
||||
char name_[256];
|
||||
char path_[XE_MAX_PATH];
|
||||
|
||||
xe_xex2_ref xex_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XMODULE_H_
|
||||
376
src/xenia/kernel/xboxkrnl/objects/xthread.cc
Normal file
376
src/xenia/kernel/xboxkrnl/objects/xthread.cc
Normal file
@@ -0,0 +1,376 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/objects/xthread.h>
|
||||
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_threading.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xevent.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace {
|
||||
static uint32_t next_xthread_id = 0;
|
||||
static uint32_t current_thread_tls = xeKeTlsAlloc();
|
||||
static xe_mutex_t* critical_region_ = xe_mutex_alloc(10000);
|
||||
static XThread* shared_kernel_thread_ = 0;
|
||||
}
|
||||
|
||||
|
||||
XThread::XThread(KernelState* kernel_state,
|
||||
uint32_t stack_size,
|
||||
uint32_t xapi_thread_startup,
|
||||
uint32_t start_address, uint32_t start_context,
|
||||
uint32_t creation_flags) :
|
||||
XObject(kernel_state, kTypeThread),
|
||||
thread_id_(++next_xthread_id),
|
||||
thread_handle_(0),
|
||||
thread_state_address_(0),
|
||||
thread_state_(0),
|
||||
event_(NULL),
|
||||
irql_(0) {
|
||||
creation_params_.stack_size = stack_size;
|
||||
creation_params_.xapi_thread_startup = xapi_thread_startup;
|
||||
creation_params_.start_address = start_address;
|
||||
creation_params_.start_context = start_context;
|
||||
creation_params_.creation_flags = creation_flags;
|
||||
|
||||
// Adjust stack size - min of 16k.
|
||||
if (creation_params_.stack_size < 16 * 1024 * 1024) {
|
||||
creation_params_.stack_size = 16 * 1024 * 1024;
|
||||
}
|
||||
|
||||
event_ = new XEvent(kernel_state);
|
||||
event_->Initialize(true, false);
|
||||
}
|
||||
|
||||
XThread::~XThread() {
|
||||
event_->Release();
|
||||
|
||||
PlatformDestroy();
|
||||
|
||||
if (thread_state_) {
|
||||
kernel_state()->processor()->DeallocThread(thread_state_);
|
||||
}
|
||||
if (tls_address_) {
|
||||
xe_memory_heap_free(kernel_state()->memory(), tls_address_, 0);
|
||||
}
|
||||
if (thread_state_address_) {
|
||||
xe_memory_heap_free(kernel_state()->memory(), thread_state_address_, 0);
|
||||
}
|
||||
|
||||
if (thread_handle_) {
|
||||
// TODO(benvanik): platform kill
|
||||
XELOGE("Thread disposed without exiting");
|
||||
}
|
||||
}
|
||||
|
||||
XThread* XThread::GetCurrentThread() {
|
||||
XThread* thread = (XThread*)xeKeTlsGetValue(current_thread_tls);
|
||||
if (!thread) {
|
||||
// Assume this is some shared interrupt thread/etc.
|
||||
XThread::EnterCriticalRegion();
|
||||
thread = shared_kernel_thread_;
|
||||
if (!thread) {
|
||||
thread = new XThread(
|
||||
KernelState::shared(), 32 * 1024, 0, 0, 0, 0);
|
||||
shared_kernel_thread_ = thread;
|
||||
xeKeTlsSetValue(current_thread_tls, (uint64_t)thread);
|
||||
}
|
||||
XThread::LeaveCriticalRegion();
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
uint32_t XThread::GetCurrentThreadHandle() {
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
return thread->handle();
|
||||
}
|
||||
|
||||
uint32_t XThread::GetCurrentThreadId(const uint8_t* thread_state_block) {
|
||||
return XEGETUINT32BE(thread_state_block + 0x14C);
|
||||
}
|
||||
|
||||
uint32_t XThread::thread_state() {
|
||||
return thread_state_address_;
|
||||
}
|
||||
|
||||
uint32_t XThread::thread_id() {
|
||||
return thread_id_;
|
||||
}
|
||||
|
||||
uint32_t XThread::last_error() {
|
||||
uint8_t *p = xe_memory_addr(memory(), thread_state_address_);
|
||||
return XEGETUINT32BE(p + 0x160);
|
||||
}
|
||||
|
||||
void XThread::set_last_error(uint32_t error_code) {
|
||||
uint8_t *p = xe_memory_addr(memory(), thread_state_address_);
|
||||
XESETUINT32BE(p + 0x160, error_code);
|
||||
}
|
||||
|
||||
X_STATUS XThread::Create() {
|
||||
// Allocate thread state block from heap.
|
||||
// This is set as r13 for user code and some special inlined Win32 calls
|
||||
// (like GetLastError/etc) will poke it directly.
|
||||
// We try to use it as our primary store of data just to keep things all
|
||||
// consistent.
|
||||
// 0x000: pointer to tls data
|
||||
// 0x100: pointer to self?
|
||||
// 0x14C: thread id
|
||||
// 0x150: if >0 then error states don't get set
|
||||
// 0x160: last error
|
||||
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
||||
// structure.
|
||||
thread_state_address_ = xe_memory_heap_alloc(
|
||||
memory(), 0, 2048, XE_MEMORY_FLAG_ZERO);
|
||||
if (!thread_state_address_) {
|
||||
XELOGW("Unable to allocate thread state block");
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Set native info.
|
||||
SetNativePointer(thread_state_address_);
|
||||
|
||||
XModule* module = kernel_state()->GetExecutableModule();
|
||||
|
||||
// Allocate TLS block.
|
||||
const xe_xex2_header_t* header = module->xex_header();
|
||||
uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size;
|
||||
tls_address_ = xe_memory_heap_alloc(
|
||||
memory(), 0, tls_size, XE_MEMORY_FLAG_ZERO);
|
||||
if (!tls_address_) {
|
||||
XELOGW("Unable to allocate thread local storage block");
|
||||
module->Release();
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Copy in default TLS info.
|
||||
// TODO(benvanik): is this correct?
|
||||
xe_memory_copy(memory(),
|
||||
tls_address_, header->tls_info.raw_data_address, tls_size);
|
||||
|
||||
// Setup the thread state block (last error/etc).
|
||||
uint8_t *p = xe_memory_addr(memory(), thread_state_address_);
|
||||
XESETUINT32BE(p + 0x000, tls_address_);
|
||||
XESETUINT32BE(p + 0x100, thread_state_address_);
|
||||
XESETUINT32BE(p + 0x14C, thread_id_);
|
||||
XESETUINT32BE(p + 0x150, 0); // ?
|
||||
XESETUINT32BE(p + 0x160, 0); // last error
|
||||
|
||||
// Allocate processor thread state.
|
||||
// This is thread safe.
|
||||
thread_state_ = kernel_state()->processor()->AllocThread(
|
||||
creation_params_.stack_size, thread_state_address_, thread_id_);
|
||||
if (!thread_state_) {
|
||||
XELOGW("Unable to allocate processor thread state");
|
||||
module->Release();
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
X_STATUS return_code = PlatformCreate();
|
||||
if (XFAILED(return_code)) {
|
||||
XELOGW("Unable to create platform thread (%.8X)", return_code);
|
||||
module->Release();
|
||||
return return_code;
|
||||
}
|
||||
|
||||
module->Release();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS XThread::Exit(int exit_code) {
|
||||
// TODO(benvanik): set exit code in thread state block
|
||||
|
||||
// TODO(benvanik); dispatch events? waiters? etc?
|
||||
event_->Set(0, false);
|
||||
|
||||
// NOTE: unless PlatformExit fails, expect it to never return!
|
||||
X_STATUS return_code = PlatformExit(exit_code);
|
||||
if (XFAILED(return_code)) {
|
||||
return return_code;
|
||||
}
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if XE_PLATFORM(WIN32)
|
||||
|
||||
static uint32_t __stdcall XThreadStartCallbackWin32(void* param) {
|
||||
XThread* thread = reinterpret_cast<XThread*>(param);
|
||||
xeKeTlsSetValue(current_thread_tls, (uint64_t)thread);
|
||||
thread->Execute();
|
||||
xeKeTlsSetValue(current_thread_tls, NULL);
|
||||
thread->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
X_STATUS XThread::PlatformCreate() {
|
||||
thread_handle_ = CreateThread(
|
||||
NULL,
|
||||
creation_params_.stack_size,
|
||||
(LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32,
|
||||
this,
|
||||
creation_params_.creation_flags,
|
||||
NULL);
|
||||
if (!thread_handle_) {
|
||||
uint32_t last_error = GetLastError();
|
||||
// TODO(benvanik): translate?
|
||||
XELOGE("CreateThread failed with %d", last_error);
|
||||
return last_error;
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void XThread::PlatformDestroy() {
|
||||
CloseHandle(reinterpret_cast<HANDLE>(thread_handle_));
|
||||
thread_handle_ = NULL;
|
||||
}
|
||||
|
||||
X_STATUS XThread::PlatformExit(int exit_code) {
|
||||
// NOTE: does not return.
|
||||
ExitThread(exit_code);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void* XThreadStartCallbackPthreads(void* param) {
|
||||
XThread* thread = reinterpret_cast<XThread*>(param);
|
||||
xeKeTlsSetValue(current_thread_tls, (uint64_t)thread);
|
||||
thread->Execute();
|
||||
xeKeTlsSetValue(current_thread_tls, NULL);
|
||||
thread->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
X_STATUS XThread::PlatformCreate() {
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, creation_params_.stack_size);
|
||||
|
||||
int result_code;
|
||||
if (creation_params_.creation_flags & X_CREATE_SUSPENDED) {
|
||||
#if XE_PLATFORM(OSX)
|
||||
result_code = pthread_create_suspended_np(
|
||||
reinterpret_cast<pthread_t*>(&thread_handle_),
|
||||
&attr,
|
||||
&XThreadStartCallbackPthreads,
|
||||
this);
|
||||
#else
|
||||
// TODO(benvanik): pthread_create_suspended_np on linux
|
||||
XEASSERTALWAYS();
|
||||
#endif // OSX
|
||||
} else {
|
||||
result_code = pthread_create(
|
||||
reinterpret_cast<pthread_t*>(&thread_handle_),
|
||||
&attr,
|
||||
&XThreadStartCallbackPthreads,
|
||||
this);
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
switch (result_code) {
|
||||
case 0:
|
||||
// Succeeded!
|
||||
return X_STATUS_SUCCESS;
|
||||
default:
|
||||
case EAGAIN:
|
||||
return X_STATUS_NO_MEMORY;
|
||||
case EINVAL:
|
||||
case EPERM:
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
void XThread::PlatformDestroy() {
|
||||
// No-op?
|
||||
}
|
||||
|
||||
X_STATUS XThread::PlatformExit(int exit_code) {
|
||||
// NOTE: does not return.
|
||||
pthread_exit((void*)exit_code);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
void XThread::Execute() {
|
||||
// If a XapiThreadStartup value is present, we use that as a trampoline.
|
||||
// Otherwise, we are a raw thread.
|
||||
if (creation_params_.xapi_thread_startup) {
|
||||
kernel_state()->processor()->Execute(
|
||||
thread_state_,
|
||||
creation_params_.xapi_thread_startup,
|
||||
creation_params_.start_address, creation_params_.start_context);
|
||||
} else {
|
||||
// Run user code.
|
||||
int exit_code = (int)kernel_state()->processor()->Execute(
|
||||
thread_state_,
|
||||
creation_params_.start_address, creation_params_.start_context);
|
||||
// If we got here it means the execute completed without an exit being called.
|
||||
// Treat the return code as an implicit exit code.
|
||||
Exit(exit_code);
|
||||
}
|
||||
}
|
||||
|
||||
X_STATUS XThread::Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout) {
|
||||
return event_->Wait(wait_reason, processor_mode, alertable, opt_timeout);
|
||||
}
|
||||
|
||||
void XThread::EnterCriticalRegion() {
|
||||
// Global critical region. This isn't right, but is easy.
|
||||
xe_mutex_lock(critical_region_);
|
||||
}
|
||||
|
||||
void XThread::LeaveCriticalRegion() {
|
||||
xe_mutex_unlock(critical_region_);
|
||||
}
|
||||
|
||||
uint32_t XThread::RaiseIrql(uint32_t new_irql) {
|
||||
return xe_atomic_exchange_32(new_irql, &irql_);
|
||||
}
|
||||
|
||||
void XThread::LowerIrql(uint32_t new_irql) {
|
||||
irql_ = new_irql;
|
||||
}
|
||||
|
||||
X_STATUS XThread::Delay(
|
||||
uint32_t processor_mode, uint32_t alertable, uint64_t interval) {
|
||||
int64_t timeout_ticks = interval;
|
||||
DWORD timeout_ms;
|
||||
if (timeout_ticks > 0) {
|
||||
// Absolute time, based on January 1, 1601.
|
||||
// TODO(benvanik): convert time to relative time.
|
||||
XEASSERTALWAYS();
|
||||
timeout_ms = 0;
|
||||
} else if (timeout_ticks < 0) {
|
||||
// Relative time.
|
||||
timeout_ms = (DWORD)(-timeout_ticks / 10000); // Ticks -> MS
|
||||
} else {
|
||||
timeout_ms = 0;
|
||||
}
|
||||
DWORD result = SleepEx(timeout_ms, alertable ? TRUE : FALSE);
|
||||
switch (result) {
|
||||
case 0:
|
||||
return X_STATUS_SUCCESS;
|
||||
case WAIT_IO_COMPLETION:
|
||||
return X_STATUS_USER_APC;
|
||||
default:
|
||||
return X_STATUS_ALERTED;
|
||||
}
|
||||
}
|
||||
97
src/xenia/kernel/xboxkrnl/objects/xthread.h
Normal file
97
src/xenia/kernel/xboxkrnl/objects/xthread.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
class ThreadState;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
class XEvent;
|
||||
|
||||
|
||||
class XThread : public XObject {
|
||||
public:
|
||||
XThread(KernelState* kernel_state,
|
||||
uint32_t stack_size,
|
||||
uint32_t xapi_thread_startup,
|
||||
uint32_t start_address, uint32_t start_context,
|
||||
uint32_t creation_flags);
|
||||
virtual ~XThread();
|
||||
|
||||
static XThread* GetCurrentThread();
|
||||
static uint32_t GetCurrentThreadHandle();
|
||||
static uint32_t GetCurrentThreadId(const uint8_t* thread_state_block);
|
||||
|
||||
uint32_t thread_state();
|
||||
uint32_t thread_id();
|
||||
uint32_t last_error();
|
||||
void set_last_error(uint32_t error_code);
|
||||
|
||||
X_STATUS Create();
|
||||
X_STATUS Exit(int exit_code);
|
||||
|
||||
void Execute();
|
||||
|
||||
virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout);
|
||||
|
||||
static void EnterCriticalRegion();
|
||||
static void LeaveCriticalRegion();
|
||||
uint32_t RaiseIrql(uint32_t new_irql);
|
||||
void LowerIrql(uint32_t new_irql);
|
||||
|
||||
X_STATUS Delay(
|
||||
uint32_t processor_mode, uint32_t alertable, uint64_t interval);
|
||||
|
||||
private:
|
||||
X_STATUS PlatformCreate();
|
||||
void PlatformDestroy();
|
||||
X_STATUS PlatformExit(int exit_code);
|
||||
|
||||
struct {
|
||||
uint32_t stack_size;
|
||||
uint32_t xapi_thread_startup;
|
||||
uint32_t start_address;
|
||||
uint32_t start_context;
|
||||
uint32_t creation_flags;
|
||||
} creation_params_;
|
||||
|
||||
uint32_t thread_id_;
|
||||
void* thread_handle_;
|
||||
uint32_t tls_address_;
|
||||
uint32_t thread_state_address_;
|
||||
cpu::ThreadState* thread_state_;
|
||||
|
||||
uint32_t irql_;
|
||||
|
||||
XEvent* event_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||
45
src/xenia/kernel/xboxkrnl/sources.gypi
Normal file
45
src/xenia/kernel/xboxkrnl/sources.gypi
Normal file
@@ -0,0 +1,45 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'async_request.cc',
|
||||
'async_request.h',
|
||||
'kernel_state.cc',
|
||||
'kernel_state.h',
|
||||
'object_table.cc',
|
||||
'object_table.h',
|
||||
'xboxkrnl_debug.cc',
|
||||
'xboxkrnl_debug.h',
|
||||
'xboxkrnl_hal.cc',
|
||||
'xboxkrnl_hal.h',
|
||||
'xboxkrnl_io.cc',
|
||||
'xboxkrnl_io.h',
|
||||
'xboxkrnl_memory.cc',
|
||||
'xboxkrnl_memory.h',
|
||||
'xboxkrnl_misc.cc',
|
||||
'xboxkrnl_misc.h',
|
||||
'xboxkrnl_module.cc',
|
||||
'xboxkrnl_module.h',
|
||||
'xboxkrnl_modules.cc',
|
||||
'xboxkrnl_modules.h',
|
||||
'xboxkrnl_nt.cc',
|
||||
'xboxkrnl_nt.h',
|
||||
'xboxkrnl_ob.cc',
|
||||
'xboxkrnl_ob.h',
|
||||
'xboxkrnl_ordinals.h',
|
||||
'xboxkrnl_private.h',
|
||||
'xboxkrnl_rtl.cc',
|
||||
'xboxkrnl_rtl.h',
|
||||
'xboxkrnl_table.inc',
|
||||
'xboxkrnl_threading.cc',
|
||||
'xboxkrnl_threading.h',
|
||||
'xboxkrnl_video.cc',
|
||||
'xboxkrnl_video.h',
|
||||
'xobject.cc',
|
||||
'xobject.h',
|
||||
],
|
||||
|
||||
'includes': [
|
||||
'fs/sources.gypi',
|
||||
'objects/sources.gypi',
|
||||
],
|
||||
}
|
||||
242
src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc
Normal file
242
src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_debug.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
// TODO: clean me up!
|
||||
SHIM_CALL DbgPrint_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
|
||||
uint32_t format_ptr = SHIM_GET_ARG_32(0);
|
||||
if (format_ptr == 0) {
|
||||
SHIM_SET_RETURN(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *format = (const char *)SHIM_MEM_ADDR(format_ptr);
|
||||
|
||||
int arg_index = 0;
|
||||
|
||||
char buffer[512]; // TODO: ensure it never writes past the end of the buffer...
|
||||
char *b = buffer;
|
||||
for (; *format != '\0'; ++format) {
|
||||
const char *start = format;
|
||||
|
||||
if (*format != '%') {
|
||||
*b++ = *format;
|
||||
continue;
|
||||
}
|
||||
|
||||
++format;
|
||||
if (*format == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*format == '%') {
|
||||
*b++ = *format;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *end;
|
||||
end = format;
|
||||
|
||||
// skip flags
|
||||
while (*end == '-' ||
|
||||
*end == '+' ||
|
||||
*end == ' ' ||
|
||||
*end == '#' ||
|
||||
*end == '0') {
|
||||
++end;
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
int arg_extras = 0;
|
||||
|
||||
// skip width
|
||||
if (*end == '*') {
|
||||
++end;
|
||||
arg_extras++;
|
||||
}
|
||||
else {
|
||||
while (*end >= '0' && *end <= '9') {
|
||||
++end;
|
||||
}
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
// skip precision
|
||||
if (*end == '.') {
|
||||
++end;
|
||||
|
||||
if (*end == '*') {
|
||||
++end;
|
||||
++arg_extras;
|
||||
}
|
||||
else {
|
||||
while (*end >= '0' && *end <= '9') {
|
||||
++end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
// get length
|
||||
int arg_size = 4;
|
||||
|
||||
if (*end == 'h') {
|
||||
++end;
|
||||
arg_size = 4;
|
||||
if (*end == 'h') {
|
||||
++end;
|
||||
}
|
||||
}
|
||||
else if (*end == 'l') {
|
||||
++end;
|
||||
arg_size = 4;
|
||||
if (*end == 'l') {
|
||||
++end;
|
||||
arg_size = 8;
|
||||
}
|
||||
}
|
||||
else if (*end == 'j') {
|
||||
arg_size = 8;
|
||||
++end;
|
||||
}
|
||||
else if (*end == 'z') {
|
||||
arg_size = 4;
|
||||
++end;
|
||||
}
|
||||
else if (*end == 't') {
|
||||
arg_size = 8;
|
||||
++end;
|
||||
}
|
||||
else if (*end == 'L') {
|
||||
arg_size = 8;
|
||||
++end;
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*end == 'd' ||
|
||||
*end == 'i' ||
|
||||
*end == 'u' ||
|
||||
*end == 'o' ||
|
||||
*end == 'x' ||
|
||||
*end == 'X' ||
|
||||
*end == 'f' ||
|
||||
*end == 'F' ||
|
||||
*end == 'e' ||
|
||||
*end == 'E' ||
|
||||
*end == 'g' ||
|
||||
*end == 'G' ||
|
||||
*end == 'a' ||
|
||||
*end == 'A' ||
|
||||
*end == 'c') {
|
||||
char local[512];
|
||||
local[0] = '\0';
|
||||
strncat(local, start, end + 1 - start);
|
||||
|
||||
XEASSERT(arg_size == 8 || arg_size == 4);
|
||||
if (arg_size == 8) {
|
||||
if (arg_extras == 0) {
|
||||
uint64_t value = arg_index < 7
|
||||
? SHIM_GET_ARG_64(1 + arg_index)
|
||||
: SHIM_MEM_32(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
|
||||
int result = sprintf(b, local, value);
|
||||
b += result;
|
||||
arg_index++;
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
}
|
||||
}
|
||||
else if (arg_size == 4) {
|
||||
if (arg_extras == 0) {
|
||||
uint64_t value = arg_index < 7
|
||||
? SHIM_GET_ARG_64(1 + arg_index)
|
||||
: SHIM_MEM_32(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
|
||||
int result = sprintf(b, local, (uint32_t)value);
|
||||
b += result;
|
||||
arg_index++;
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*end == 's' ||
|
||||
*end == 'p' ||
|
||||
*end == 'n') {
|
||||
char local[512];
|
||||
local[0] = '\0';
|
||||
strncat(local, start, end + 1 - start);
|
||||
|
||||
XEASSERT(arg_size == 4);
|
||||
if (arg_extras == 0) {
|
||||
uint32_t value = arg_index < 7
|
||||
? SHIM_GET_ARG_32(1 + arg_index)
|
||||
: (uint32_t)SHIM_MEM_64(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
|
||||
const char *pointer = (const char *)SHIM_MEM_ADDR(value);
|
||||
int result = sprintf(b, local, pointer);
|
||||
b += result;
|
||||
arg_index++;
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
format = end;
|
||||
}
|
||||
*b++ = '\0';
|
||||
|
||||
XELOGD("(DbgPrint) %s", buffer);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterDebugExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", DbgPrint, state);
|
||||
}
|
||||
29
src/xenia/kernel/xboxkrnl/xboxkrnl_debug.h
Normal file
29
src/xenia/kernel/xboxkrnl/xboxkrnl_debug.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_DEBUG_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_DEBUG_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_DEBUG_H_
|
||||
64
src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc
Normal file
64
src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_hal.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
void xeHalReturnToFirmware(uint32_t routine) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// void
|
||||
// IN FIRMWARE_REENTRY Routine
|
||||
|
||||
// Routine must be 1 'HalRebootRoutine'
|
||||
XEASSERT(routine == 1);
|
||||
|
||||
// TODO(benvank): diediedie much more gracefully
|
||||
// Not sure how to blast back up the stack in LLVM without exceptions, though.
|
||||
XELOGE("Game requested shutdown via HalReturnToFirmware");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL HalReturnToFirmware_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t routine = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"HalReturnToFirmware(%d)",
|
||||
routine);
|
||||
|
||||
xeHalReturnToFirmware(routine);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterHalExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", HalReturnToFirmware, state);
|
||||
}
|
||||
32
src/xenia/kernel/xboxkrnl/xboxkrnl_hal.h
Normal file
32
src/xenia/kernel/xboxkrnl/xboxkrnl_hal.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_HAL_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_HAL_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
void xeHalReturnToFirmware(uint32_t routine);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_HAL_H_
|
||||
406
src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc
Normal file
406
src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc
Normal file
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_io.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/async_request.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xevent.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xfile.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
using namespace xe::kernel::xboxkrnl::fs;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
SHIM_CALL NtCreateFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t desired_access = SHIM_GET_ARG_32(1);
|
||||
uint32_t object_attributes_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t allocation_size_ptr = SHIM_GET_ARG_32(4);
|
||||
uint32_t file_attributes = SHIM_GET_ARG_32(5);
|
||||
uint32_t share_access = SHIM_GET_ARG_32(6);
|
||||
uint32_t creation_disposition = SHIM_GET_ARG_32(7);
|
||||
|
||||
X_OBJECT_ATTRIBUTES attrs(SHIM_MEM_BASE, object_attributes_ptr);
|
||||
|
||||
XELOGD(
|
||||
"NtCreateFile(%.8X, %.8X, %.8X(%s), %.8X, %.8X, %.8X, %d, %d)",
|
||||
handle_ptr,
|
||||
desired_access,
|
||||
object_attributes_ptr,
|
||||
attrs.object_name.buffer,
|
||||
io_status_block_ptr,
|
||||
allocation_size_ptr,
|
||||
file_attributes,
|
||||
share_access,
|
||||
creation_disposition);
|
||||
|
||||
uint64_t allocation_size = 0; // is this correct???
|
||||
if (allocation_size_ptr != 0) {
|
||||
allocation_size = SHIM_MEM_64(allocation_size_ptr);
|
||||
}
|
||||
|
||||
X_STATUS result = X_STATUS_NO_SUCH_FILE;
|
||||
uint32_t info = X_FILE_DOES_NOT_EXIST;
|
||||
uint32_t handle;
|
||||
|
||||
// Resolve the file using the virtual file system.
|
||||
FileSystem* fs = state->file_system();
|
||||
Entry* entry = fs->ResolvePath(attrs.object_name.buffer);
|
||||
XFile* file = NULL;
|
||||
if (entry && entry->type() == Entry::kTypeFile) {
|
||||
// Open the file.
|
||||
result = entry->Open(
|
||||
state,
|
||||
desired_access,
|
||||
false, // TODO(benvanik): pick async mode, if needed.
|
||||
&file);
|
||||
} else {
|
||||
result = X_STATUS_NO_SUCH_FILE;
|
||||
info = X_FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
// Handle ref is incremented, so return that.
|
||||
handle = file->handle();
|
||||
file->Release();
|
||||
result = X_STATUS_SUCCESS;
|
||||
info = X_FILE_OPENED;
|
||||
}
|
||||
|
||||
if (io_status_block_ptr) {
|
||||
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
|
||||
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
|
||||
}
|
||||
if (XSUCCEEDED(result)) {
|
||||
if (handle_ptr) {
|
||||
SHIM_SET_MEM_32(handle_ptr, handle);
|
||||
}
|
||||
}
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtOpenFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
|
||||
}
|
||||
|
||||
class xeNtReadFileState {
|
||||
public:
|
||||
uint32_t x;
|
||||
};
|
||||
void xeNtReadFileCompleted(XAsyncRequest* request, xeNtReadFileState* state) {
|
||||
// TODO(benvanik): set io_status_block_ptr
|
||||
delete request;
|
||||
delete state;
|
||||
}
|
||||
|
||||
SHIM_CALL NtReadFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t file_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t event_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t apc_routine_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t apc_context = SHIM_GET_ARG_32(3);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(4);
|
||||
uint32_t buffer = SHIM_GET_ARG_32(5);
|
||||
uint32_t buffer_length = SHIM_GET_ARG_32(6);
|
||||
uint32_t byte_offset_ptr = SHIM_GET_ARG_32(7);
|
||||
size_t byte_offset = byte_offset_ptr ? SHIM_MEM_64(byte_offset_ptr) : 0;
|
||||
|
||||
XELOGD(
|
||||
"NtReadFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %d)",
|
||||
file_handle,
|
||||
event_handle,
|
||||
apc_routine_ptr,
|
||||
apc_context,
|
||||
io_status_block_ptr,
|
||||
buffer,
|
||||
buffer_length,
|
||||
byte_offset_ptr);
|
||||
|
||||
// Async not supported yet.
|
||||
XEASSERTNULL(apc_routine_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab event to signal.
|
||||
XEvent* ev = NULL;
|
||||
bool signal_event = false;
|
||||
if (event_handle) {
|
||||
result = state->object_table()->GetObject(
|
||||
event_handle, (XObject**)&ev);
|
||||
}
|
||||
|
||||
// Grab file.
|
||||
XFile* file = NULL;
|
||||
if (XSUCCEEDED(result)) {
|
||||
result = state->object_table()->GetObject(
|
||||
file_handle, (XObject**)&file);
|
||||
}
|
||||
|
||||
// Execute read.
|
||||
if (XSUCCEEDED(result)) {
|
||||
// Reset event before we begin.
|
||||
if (ev) {
|
||||
ev->Reset();
|
||||
}
|
||||
|
||||
// TODO(benvanik): async path.
|
||||
if (true) {
|
||||
// Synchronous request.
|
||||
if (!byte_offset_ptr ||
|
||||
byte_offset == 0xFFFFFFFFfffffffe) {
|
||||
// FILE_USE_FILE_POINTER_POSITION
|
||||
byte_offset = -1;
|
||||
}
|
||||
|
||||
// Read now.
|
||||
size_t bytes_read = 0;
|
||||
result = file->Read(
|
||||
SHIM_MEM_ADDR(buffer), buffer_length, byte_offset,
|
||||
&bytes_read);
|
||||
if (XSUCCEEDED(result)) {
|
||||
info = (int32_t)bytes_read;
|
||||
}
|
||||
|
||||
// Mark that we should signal the event now. We do this after
|
||||
// we have written the info out.
|
||||
signal_event = true;
|
||||
} else {
|
||||
// X_STATUS_PENDING if not returning immediately.
|
||||
// XFile is waitable and signalled after each async req completes.
|
||||
// reset the input event (->Reset())
|
||||
/*xeNtReadFileState* call_state = new xeNtReadFileState();
|
||||
XAsyncRequest* request = new XAsyncRequest(
|
||||
state, file,
|
||||
(XAsyncRequest::CompletionCallback)xeNtReadFileCompleted,
|
||||
call_state);*/
|
||||
//result = file->Read(buffer, buffer_length, byte_offset, request);
|
||||
result = X_STATUS_PENDING;
|
||||
info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (io_status_block_ptr) {
|
||||
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
|
||||
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
|
||||
}
|
||||
|
||||
if (file) {
|
||||
file->Release();
|
||||
}
|
||||
if (ev) {
|
||||
if (signal_event) {
|
||||
ev->Set(0, false);
|
||||
}
|
||||
ev->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtSetInformationFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t file_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t file_info_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t length = SHIM_GET_ARG_32(3);
|
||||
uint32_t file_info_class = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"NtSetInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
file_handle,
|
||||
io_status_block_ptr,
|
||||
file_info_ptr,
|
||||
length,
|
||||
file_info_class);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab file.
|
||||
XFile* file = NULL;
|
||||
result = state->object_table()->GetObject(
|
||||
file_handle, (XObject**)&file);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
result = X_STATUS_SUCCESS;
|
||||
switch (file_info_class) {
|
||||
case XFilePositionInformation:
|
||||
// struct FILE_POSITION_INFORMATION {
|
||||
// LARGE_INTEGER CurrentByteOffset;
|
||||
// };
|
||||
XEASSERT(length == 8);
|
||||
info = 8;
|
||||
file->set_position(SHIM_MEM_64(file_info_ptr));
|
||||
break;
|
||||
default:
|
||||
// Unsupported, for now.
|
||||
XEASSERTALWAYS();
|
||||
info = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (XFAILED(result)) {
|
||||
info = 0;
|
||||
}
|
||||
if (io_status_block_ptr) {
|
||||
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
|
||||
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
|
||||
}
|
||||
|
||||
if (file) {
|
||||
file->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtQueryInformationFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t file_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t file_info_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t length = SHIM_GET_ARG_32(3);
|
||||
uint32_t file_info_class = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"NtQueryInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
file_handle,
|
||||
io_status_block_ptr,
|
||||
file_info_ptr,
|
||||
length,
|
||||
file_info_class);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
uint32_t info = 0;
|
||||
|
||||
// Grab file.
|
||||
XFile* file = NULL;
|
||||
result = state->object_table()->GetObject(
|
||||
file_handle, (XObject**)&file);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
result = X_STATUS_SUCCESS;
|
||||
switch (file_info_class) {
|
||||
case XFilePositionInformation:
|
||||
// struct FILE_POSITION_INFORMATION {
|
||||
// LARGE_INTEGER CurrentByteOffset;
|
||||
// };
|
||||
XEASSERT(length == 8);
|
||||
info = 8;
|
||||
SHIM_SET_MEM_64(file_info_ptr, file->position());
|
||||
break;
|
||||
case XFileNetworkOpenInformation:
|
||||
// struct FILE_NETWORK_OPEN_INFORMATION {
|
||||
// LARGE_INTEGER CreationTime;
|
||||
// LARGE_INTEGER LastAccessTime;
|
||||
// LARGE_INTEGER LastWriteTime;
|
||||
// LARGE_INTEGER ChangeTime;
|
||||
// LARGE_INTEGER AllocationSize;
|
||||
// LARGE_INTEGER EndOfFile;
|
||||
// ULONG FileAttributes;
|
||||
// ULONG Unknown;
|
||||
// };
|
||||
XEASSERT(length == 56);
|
||||
XFileInfo file_info;
|
||||
result = file->QueryInfo(&file_info);
|
||||
if (XSUCCEEDED(result)) {
|
||||
info = 56;
|
||||
file_info.Write(SHIM_MEM_BASE, file_info_ptr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unsupported, for now.
|
||||
XEASSERTALWAYS();
|
||||
info = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (XFAILED(result)) {
|
||||
info = 0;
|
||||
}
|
||||
if (io_status_block_ptr) {
|
||||
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
|
||||
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
|
||||
}
|
||||
|
||||
if (file) {
|
||||
file->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtQueryFullAttributesFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t object_attributes_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t file_info_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
X_OBJECT_ATTRIBUTES attrs(SHIM_MEM_BASE, object_attributes_ptr);
|
||||
|
||||
XELOGD(
|
||||
"NtQueryFullAttributesFile(%.8X(%s), %.8X)",
|
||||
object_attributes_ptr,
|
||||
attrs.object_name.buffer,
|
||||
file_info_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_NO_SUCH_FILE;
|
||||
|
||||
// Resolve the file using the virtual file system.
|
||||
FileSystem* fs = state->file_system();
|
||||
Entry* entry = fs->ResolvePath(attrs.object_name.buffer);
|
||||
if (entry && entry->type() == Entry::kTypeFile) {
|
||||
// Found.
|
||||
XFileInfo file_info;
|
||||
result = entry->QueryInfo(&file_info);
|
||||
if (XSUCCEEDED(result)) {
|
||||
file_info.Write(SHIM_MEM_BASE, file_info_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtQueryVolumeInformationFile_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterIoExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtOpenFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtReadFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryInformationFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetInformationFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryFullAttributesFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryVolumeInformationFile, state);
|
||||
}
|
||||
29
src/xenia/kernel/xboxkrnl/xboxkrnl_io.h
Normal file
29
src/xenia/kernel/xboxkrnl/xboxkrnl_io.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_IO_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_IO_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_IO_H_
|
||||
385
src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc
Normal file
385
src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc
Normal file
@@ -0,0 +1,385 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_memory.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
X_STATUS xeNtAllocateVirtualMemory(
|
||||
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
|
||||
uint32_t allocation_type, uint32_t protect_bits,
|
||||
uint32_t unknown) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// NTSTATUS
|
||||
// _Inout_ PVOID *BaseAddress,
|
||||
// _Inout_ PSIZE_T RegionSize,
|
||||
// _In_ ULONG AllocationType,
|
||||
// _In_ ULONG Protect
|
||||
// ? handle?
|
||||
|
||||
// I've only seen zero.
|
||||
XEASSERT(unknown == 0);
|
||||
|
||||
// This allocates memory from the kernel heap, which is initialized on startup
|
||||
// and shared by both the kernel implementation and user code.
|
||||
// The xe_memory_ref object is used to actually get the memory, and although
|
||||
// it's simple today we could extend it to do better things in the future.
|
||||
|
||||
// Must request a size.
|
||||
if (!*region_size_ptr) {
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
// Check allocation type.
|
||||
if (!(allocation_type & (X_MEM_COMMIT | X_MEM_RESET | X_MEM_RESERVE))) {
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
// If MEM_RESET is set only MEM_RESET can be set.
|
||||
if (allocation_type & X_MEM_RESET && (allocation_type & ~X_MEM_RESET)) {
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
// Don't allow games to set execute bits.
|
||||
if (protect_bits & (X_PAGE_EXECUTE | X_PAGE_EXECUTE_READ |
|
||||
X_PAGE_EXECUTE_READWRITE | X_PAGE_EXECUTE_WRITECOPY)) {
|
||||
return X_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
// Adjust size.
|
||||
uint32_t adjusted_size = *region_size_ptr;
|
||||
// TODO(benvanik): adjust based on page size flags/etc?
|
||||
|
||||
// TODO(benvanik): support different allocation types.
|
||||
// Right now we treat everything as a commit and ignore allocations that have
|
||||
// already happened.
|
||||
if (*base_addr_ptr) {
|
||||
// Having a pointer already means that this is likely a follow-on COMMIT.
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Allocate.
|
||||
uint32_t flags = 0;
|
||||
uint32_t addr = xe_memory_heap_alloc(
|
||||
state->memory(), *base_addr_ptr, adjusted_size, flags);
|
||||
if (!addr) {
|
||||
// Failed - assume no memory available.
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Stash back.
|
||||
// Maybe set X_STATUS_ALREADY_COMMITTED if MEM_COMMIT?
|
||||
*base_addr_ptr = addr;
|
||||
*region_size_ptr = adjusted_size;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL NtAllocateVirtualMemory_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
|
||||
uint32_t allocation_type = SHIM_GET_ARG_32(2); // X_MEM_* bitmask
|
||||
uint32_t protect_bits = SHIM_GET_ARG_32(3); // X_PAGE_* bitmask
|
||||
uint32_t unknown = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"NtAllocateVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X, %.8X)",
|
||||
base_addr_ptr, base_addr_value,
|
||||
region_size_ptr, region_size_value,
|
||||
allocation_type, protect_bits, unknown);
|
||||
|
||||
X_STATUS result = xeNtAllocateVirtualMemory(
|
||||
&base_addr_value, ®ion_size_value,
|
||||
allocation_type, protect_bits, unknown);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
SHIM_SET_MEM_32(base_addr_ptr, base_addr_value);
|
||||
SHIM_SET_MEM_32(region_size_ptr, region_size_value);
|
||||
}
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
X_STATUS xeNtFreeVirtualMemory(
|
||||
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
|
||||
uint32_t free_type, uint32_t unknown) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// NTSTATUS
|
||||
// _Inout_ PVOID *BaseAddress,
|
||||
// _Inout_ PSIZE_T RegionSize,
|
||||
// _In_ ULONG FreeType
|
||||
// ? handle?
|
||||
|
||||
// I've only seen zero.
|
||||
XEASSERT(unknown == 0);
|
||||
|
||||
if (!*base_addr_ptr) {
|
||||
return X_STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
// TODO(benvanik): ignore decommits for now.
|
||||
if (free_type == X_MEM_DECOMMIT) {
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Free.
|
||||
uint32_t flags = 0;
|
||||
uint32_t freed_size = xe_memory_heap_free(state->memory(), *base_addr_ptr,
|
||||
flags);
|
||||
if (!freed_size) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Stash back.
|
||||
*region_size_ptr = freed_size;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL NtFreeVirtualMemory_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
|
||||
// X_MEM_DECOMMIT | X_MEM_RELEASE
|
||||
uint32_t free_type = SHIM_GET_ARG_32(2);
|
||||
uint32_t unknown = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD(
|
||||
"NtFreeVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X)",
|
||||
base_addr_ptr, base_addr_value,
|
||||
region_size_ptr, region_size_value,
|
||||
free_type, unknown);
|
||||
|
||||
X_STATUS result = xeNtFreeVirtualMemory(
|
||||
&base_addr_value, ®ion_size_value,
|
||||
free_type, unknown);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
SHIM_SET_MEM_32(base_addr_ptr, base_addr_value);
|
||||
SHIM_SET_MEM_32(region_size_ptr, region_size_value);
|
||||
}
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeMmAllocatePhysicalMemoryEx(
|
||||
uint32_t type, uint32_t region_size, uint32_t protect_bits,
|
||||
uint32_t min_addr_range, uint32_t max_addr_range, uint32_t alignment) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
|
||||
// by D3D/etc.
|
||||
|
||||
// Check protection bits.
|
||||
if (!(protect_bits & (X_PAGE_READONLY | X_PAGE_READWRITE))) {
|
||||
XELOGE("MmAllocatePhysicalMemoryEx: bad protection bits");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Either may be OR'ed into protect_bits:
|
||||
// X_PAGE_NOCACHE
|
||||
// X_PAGE_WRITECOMBINE
|
||||
// We could use this to detect what's likely GPU-synchronized memory
|
||||
// and let the GPU know we're messing with it (or even allocate from
|
||||
// the GPU). At least the D3D command buffer is X_PAGE_WRITECOMBINE.
|
||||
|
||||
// Calculate page size.
|
||||
// Default = 4KB
|
||||
// X_MEM_LARGE_PAGES = 64KB
|
||||
// X_MEM_16MB_PAGES = 16MB
|
||||
uint32_t page_size = 4 * 1024;
|
||||
if (protect_bits & X_MEM_LARGE_PAGES) {
|
||||
page_size = 64 * 1024;
|
||||
} else if (protect_bits & X_MEM_16MB_PAGES) {
|
||||
page_size = 16 * 1024 * 1024;
|
||||
}
|
||||
|
||||
// Round up the region size and alignment to the next page.
|
||||
uint32_t adjusted_size = XEROUNDUP(region_size, page_size);
|
||||
uint32_t adjusted_alignment = XEROUNDUP(alignment, page_size);
|
||||
|
||||
// Callers can pick an address to allocate with min_addr_range/max_addr_range
|
||||
// and the memory must be allocated there. I haven't seen a game do this,
|
||||
// and instead they all do min=0 / max=-1 to indicate the system should pick.
|
||||
// If we have to suport arbitrary placement things will get nasty.
|
||||
XEASSERT(min_addr_range == 0);
|
||||
XEASSERT(max_addr_range == 0xFFFFFFFF);
|
||||
|
||||
// Allocate.
|
||||
uint32_t flags = XE_MEMORY_FLAG_PHYSICAL;
|
||||
uint32_t base_address = xe_memory_heap_alloc(
|
||||
state->memory(), 0, adjusted_size, flags, adjusted_alignment);
|
||||
if (!base_address) {
|
||||
// Failed - assume no memory available.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Move the address into the right range.
|
||||
//if (protect_bits & X_MEM_LARGE_PAGES) {
|
||||
// base_address += 0xA0000000;
|
||||
//} else if (protect_bits & X_MEM_16MB_PAGES) {
|
||||
// base_address += 0xC0000000;
|
||||
//} else {
|
||||
// base_address += 0xE0000000;
|
||||
//}
|
||||
base_address += 0xA0000000;
|
||||
|
||||
return base_address;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL MmAllocatePhysicalMemoryEx_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t type = SHIM_GET_ARG_32(0);
|
||||
uint32_t region_size = SHIM_GET_ARG_32(1);
|
||||
uint32_t protect_bits = SHIM_GET_ARG_32(2);
|
||||
uint32_t min_addr_range = SHIM_GET_ARG_32(3);
|
||||
uint32_t max_addr_range = SHIM_GET_ARG_32(4);
|
||||
uint32_t alignment = SHIM_GET_ARG_32(5);
|
||||
|
||||
XELOGD(
|
||||
"MmAllocatePhysicalMemoryEx(%d, %.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
type, region_size, protect_bits,
|
||||
min_addr_range, max_addr_range, alignment);
|
||||
|
||||
uint32_t base_address = xeMmAllocatePhysicalMemoryEx(
|
||||
type, region_size, protect_bits,
|
||||
min_addr_range, max_addr_range, alignment);
|
||||
|
||||
SHIM_SET_RETURN(base_address);
|
||||
}
|
||||
|
||||
|
||||
void xeMmFreePhysicalMemory(uint32_t type, uint32_t base_address) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// base_address = result of MmAllocatePhysicalMemory.
|
||||
|
||||
// Strip off physical bits before passing down.
|
||||
base_address &= ~0xE0000000;
|
||||
|
||||
// TODO(benvanik): free memory.
|
||||
XELOGE("xeMmFreePhysicalMemory NOT IMPLEMENTED");
|
||||
//uint32_t size = ?;
|
||||
//xe_memory_heap_free(
|
||||
// state->memory(), base_address, size);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL MmFreePhysicalMemory_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t type = SHIM_GET_ARG_32(0);
|
||||
uint32_t base_address = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"MmFreePhysicalAddress(%d, %.8X)",
|
||||
type, base_address);
|
||||
|
||||
xeMmFreePhysicalMemory(type, base_address);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeMmQueryAddressProtect(uint32_t base_address) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
uint32_t access = xe_memory_query_protect(
|
||||
state->memory(), base_address);
|
||||
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL MmQueryAddressProtect_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"MmQueryAddressProtect(%.8X)",
|
||||
base_address);
|
||||
|
||||
uint32_t result = xeMmQueryAddressProtect(base_address);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx
|
||||
uint32_t xeMmGetPhysicalAddress(uint32_t base_address) {
|
||||
// PHYSICAL_ADDRESS MmGetPhysicalAddress(
|
||||
// _In_ PVOID BaseAddress
|
||||
// );
|
||||
// base_address = result of MmAllocatePhysicalMemory.
|
||||
|
||||
// We are always using virtual addresses, right now, since we don't need
|
||||
// physical ones. We could munge up the address here to another mapped view
|
||||
// of memory.
|
||||
|
||||
/*if (protect_bits & X_MEM_LARGE_PAGES) {
|
||||
base_address |= 0xA0000000;
|
||||
} else if (protect_bits & X_MEM_16MB_PAGES) {
|
||||
base_address |= 0xC0000000;
|
||||
} else {
|
||||
base_address |= 0xE0000000;
|
||||
}*/
|
||||
|
||||
return base_address;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL MmGetPhysicalAddress_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t base_address = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"MmGetPhysicalAddress(%.8X)",
|
||||
base_address);
|
||||
|
||||
uint32_t result = xeMmGetPhysicalAddress(base_address);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterMemoryExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtAllocateVirtualMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtFreeVirtualMemory, state);
|
||||
//SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemoryEx, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmFreePhysicalMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmQueryAddressProtect, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", MmGetPhysicalAddress, state);
|
||||
}
|
||||
45
src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h
Normal file
45
src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_MEMORY_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_MEMORY_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
X_STATUS xeNtAllocateVirtualMemory(
|
||||
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
|
||||
uint32_t allocation_type, uint32_t protect_bits,
|
||||
uint32_t unknown);
|
||||
X_STATUS xeNtFreeVirtualMemory(
|
||||
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
|
||||
uint32_t free_type, uint32_t unknown);
|
||||
|
||||
uint32_t xeMmAllocatePhysicalMemoryEx(
|
||||
uint32_t type, uint32_t region_size, uint32_t protect_bits,
|
||||
uint32_t min_addr_range, uint32_t max_addr_range, uint32_t alignment);
|
||||
void xeMmFreePhysicalMemory(uint32_t type, uint32_t base_address);
|
||||
uint32_t xeMmQueryAddressProtect(uint32_t base_address);
|
||||
uint32_t xeMmGetPhysicalAddress(uint32_t base_address);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_MEMORY_H_
|
||||
59
src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc
Normal file
59
src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_misc.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
void xeKeBugCheckEx(uint32_t code, uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4) {
|
||||
XELOGD("*** STOP: 0x%.8X (0x%.8X, 0x%.8X, 0x%.8X, 0x%.8X)", code, param1, param2, param3, param4);
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
SHIM_CALL KeBugCheck_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t code = SHIM_GET_ARG_32(0);
|
||||
xeKeBugCheckEx(code, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
SHIM_CALL KeBugCheckEx_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t code = SHIM_GET_ARG_32(0);
|
||||
uint32_t param1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t param2 = SHIM_GET_ARG_32(2);
|
||||
uint32_t param3 = SHIM_GET_ARG_32(3);
|
||||
uint32_t param4 = SHIM_GET_ARG_32(4);
|
||||
xeKeBugCheckEx(code, param1, param2, param3, param4);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterMiscExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeBugCheck, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeBugCheckEx, state);
|
||||
}
|
||||
29
src/xenia/kernel/xboxkrnl/xboxkrnl_misc.h
Normal file
29
src/xenia/kernel/xboxkrnl/xboxkrnl_misc.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_MISC_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_MISC_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_MISC_H_
|
||||
188
src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc
Normal file
188
src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_module.h>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
DEFINE_bool(abort_before_entry, false,
|
||||
"Abort execution right before launching the module.");
|
||||
|
||||
|
||||
KernelState* xe::kernel::xboxkrnl::shared_kernel_state_ = NULL;
|
||||
|
||||
|
||||
XboxkrnlModule::XboxkrnlModule(Emulator* emulator) :
|
||||
KernelModule(emulator) {
|
||||
// Build the export table used for resolution.
|
||||
#include <xenia/kernel/util/export_table_pre.inc>
|
||||
static KernelExport xboxkrnl_export_table[] = {
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_table.inc>
|
||||
};
|
||||
#include <xenia/kernel/util/export_table_post.inc>
|
||||
export_resolver_->RegisterTable(
|
||||
"xboxkrnl.exe", xboxkrnl_export_table, XECOUNT(xboxkrnl_export_table));
|
||||
|
||||
// Setup the kernel state instance.
|
||||
// This is where all kernel objects are kept while running.
|
||||
kernel_state_ = new KernelState(emulator);
|
||||
|
||||
// Setup the shared global state object.
|
||||
XEASSERTNULL(shared_kernel_state_);
|
||||
shared_kernel_state_ = kernel_state_;
|
||||
|
||||
// Register all exported functions.
|
||||
RegisterDebugExports(export_resolver_, kernel_state_);
|
||||
RegisterHalExports(export_resolver_, kernel_state_);
|
||||
RegisterIoExports(export_resolver_, kernel_state_);
|
||||
RegisterMemoryExports(export_resolver_, kernel_state_);
|
||||
RegisterMiscExports(export_resolver_, kernel_state_);
|
||||
RegisterModuleExports(export_resolver_, kernel_state_);
|
||||
RegisterNtExports(export_resolver_, kernel_state_);
|
||||
RegisterObExports(export_resolver_, kernel_state_);
|
||||
RegisterRtlExports(export_resolver_, kernel_state_);
|
||||
RegisterThreadingExports(export_resolver_, kernel_state_);
|
||||
RegisterVideoExports(export_resolver_, kernel_state_);
|
||||
|
||||
uint8_t* mem = xe_memory_addr(memory_);
|
||||
|
||||
// KeDebugMonitorData (?*)
|
||||
// Set to a valid value when a remote debugger is attached.
|
||||
// Offset 0x18 is a 4b pointer to a handler function that seems to take two
|
||||
// arguments. If we wanted to see what would happen we could fake that.
|
||||
uint32_t pKeDebugMonitorData = xe_memory_heap_alloc(memory_, 0, 256, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeDebugMonitorData,
|
||||
pKeDebugMonitorData);
|
||||
XESETUINT32BE(mem + pKeDebugMonitorData, 0);
|
||||
|
||||
// KeCertMonitorData (?*)
|
||||
// Always set to zero, ignored.
|
||||
uint32_t pKeCertMonitorData = xe_memory_heap_alloc(memory_, 0, 4, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeCertMonitorData,
|
||||
pKeCertMonitorData);
|
||||
XESETUINT32BE(mem + pKeCertMonitorData, 0);
|
||||
|
||||
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
|
||||
// flags cpu# ? ? ? ? ? ?
|
||||
// 0x00000000, 0x06, 0x00, 0x00, 0x00, 0x00000000, 0x0000, 0x0000
|
||||
// Games seem to check if bit 26 (0x20) is set, which at least for xbox1
|
||||
// was whether an HDD was present. Not sure what the other flags are.
|
||||
uint32_t pXboxHardwareInfo = xe_memory_heap_alloc(memory_, 0, 16, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::XboxHardwareInfo,
|
||||
pXboxHardwareInfo);
|
||||
XESETUINT32BE(mem + pXboxHardwareInfo + 0, 0x00000000); // flags
|
||||
XESETUINT8BE (mem + pXboxHardwareInfo + 4, 0x06); // cpu count
|
||||
// Remaining 11b are zeroes?
|
||||
|
||||
// XexExecutableModuleHandle (?**)
|
||||
// Games try to dereference this to get a pointer to some module struct.
|
||||
// So far it seems like it's just in loader code, and only used to look up
|
||||
// the XexHeaderBase for use by RtlImageXexHeaderField.
|
||||
// We fake it so that the address passed to that looks legit.
|
||||
// 0x80100FFC <- pointer to structure
|
||||
// 0x80101000 <- our module structure
|
||||
// 0x80101058 <- pointer to xex header
|
||||
// 0x80101100 <- xex header base
|
||||
uint32_t ppXexExecutableModuleHandle =
|
||||
xe_memory_heap_alloc(memory_, 0, 4, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::XexExecutableModuleHandle,
|
||||
ppXexExecutableModuleHandle);
|
||||
uint32_t pXexExecutableModuleHandle =
|
||||
xe_memory_heap_alloc(memory_, 0, 256, 0);
|
||||
XESETUINT32BE(mem + ppXexExecutableModuleHandle, pXexExecutableModuleHandle);
|
||||
XESETUINT32BE(mem + pXexExecutableModuleHandle + 0x58, 0x80101100);
|
||||
|
||||
// ExLoadedCommandLine (char*)
|
||||
// The name of the xex. Not sure this is ever really used on real devices.
|
||||
// Perhaps it's how swap disc/etc data is sent?
|
||||
// Always set to "default.xex" (with quotes) for now.
|
||||
uint32_t pExLoadedCommandLine = xe_memory_heap_alloc(memory_, 0, 1024, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::ExLoadedCommandLine,
|
||||
pExLoadedCommandLine);
|
||||
char command_line[] = "\"default.xex\"";
|
||||
xe_copy_memory(mem + pExLoadedCommandLine, 1024,
|
||||
command_line, XECOUNT(command_line) + 1);
|
||||
|
||||
// XboxKrnlVersion (8b)
|
||||
// Kernel version, looks like 2b.2b.2b.2b.
|
||||
// I've only seen games check >=, so we just fake something here.
|
||||
uint32_t pXboxKrnlVersion = xe_memory_heap_alloc(memory_, 0, 8, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::XboxKrnlVersion,
|
||||
pXboxKrnlVersion);
|
||||
XESETUINT16BE(mem + pXboxKrnlVersion + 0, 2);
|
||||
XESETUINT16BE(mem + pXboxKrnlVersion + 2, 0xFFFF);
|
||||
XESETUINT16BE(mem + pXboxKrnlVersion + 4, 0xFFFF);
|
||||
XESETUINT16BE(mem + pXboxKrnlVersion + 6, 0xFFFF);
|
||||
|
||||
// KeTimeStampBundle (ad)
|
||||
uint32_t pKeTimeStampBundle = xe_memory_heap_alloc(memory_, 0, 24, 0);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeTimeStampBundle,
|
||||
pKeTimeStampBundle);
|
||||
XESETUINT64BE(mem + pKeTimeStampBundle + 0, 0);
|
||||
XESETUINT64BE(mem + pKeTimeStampBundle + 8, 0);
|
||||
XESETUINT32BE(mem + pKeTimeStampBundle + 12, 0);
|
||||
}
|
||||
|
||||
XboxkrnlModule::~XboxkrnlModule() {
|
||||
delete kernel_state_;
|
||||
|
||||
// Clear the shared kernel state.
|
||||
shared_kernel_state_ = NULL;
|
||||
}
|
||||
|
||||
int XboxkrnlModule::LaunchModule(const char* path) {
|
||||
// Create and register the module. We keep it local to this function and
|
||||
// dispose it on exit.
|
||||
XModule* module = new XModule(kernel_state_, path);
|
||||
|
||||
// Load the module into memory from the filesystem.
|
||||
X_STATUS result_code = module->LoadFromFile(path);
|
||||
if (XFAILED(result_code)) {
|
||||
XELOGE("Failed to load module %s: %.8X", path, result_code);
|
||||
module->Release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (FLAGS_abort_before_entry) {
|
||||
XELOGI("--abort_before_entry causing an early exit");
|
||||
module->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Launch the module.
|
||||
// NOTE: this won't return until the module exits.
|
||||
result_code = module->Launch(0);
|
||||
if (XFAILED(result_code)) {
|
||||
XELOGE("Failed to launch module %s: %.8X", path, result_code);
|
||||
module->Release();
|
||||
return 2;
|
||||
}
|
||||
|
||||
module->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
54
src/xenia/kernel/xboxkrnl/xboxkrnl_module.h
Normal file
54
src/xenia/kernel/xboxkrnl/xboxkrnl_module.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_MODULE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_MODULE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/kernel/kernel_module.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h>
|
||||
|
||||
// All of the exported functions:
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_debug.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_hal.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_memory.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_module.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_rtl.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_threading.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_video.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
class KernelState;
|
||||
|
||||
|
||||
class XboxkrnlModule : public KernelModule {
|
||||
public:
|
||||
XboxkrnlModule(Emulator* emulator);
|
||||
virtual ~XboxkrnlModule();
|
||||
|
||||
int LaunchModule(const char* path);
|
||||
|
||||
private:
|
||||
KernelState* kernel_state_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_MODULE_H_
|
||||
232
src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc
Normal file
232
src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc
Normal file
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_modules.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xex2.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
X_STATUS xeExGetXConfigSetting(
|
||||
uint16_t category, uint16_t setting, void* buffer, uint16_t buffer_size,
|
||||
uint16_t* required_size) {
|
||||
uint16_t setting_size = 0;
|
||||
uint32_t value = 0;
|
||||
|
||||
// TODO(benvanik): have real structs here that just get copied from.
|
||||
// http://free60.org/XConfig
|
||||
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/ExConfig.h
|
||||
switch (category) {
|
||||
case 0x0003:
|
||||
// XCONFIG_USER_CATEGORY
|
||||
switch (setting) {
|
||||
case 0x0001: // XCONFIG_USER_TIME_ZONE_BIAS
|
||||
case 0x0002: // XCONFIG_USER_TIME_ZONE_STD_NAME
|
||||
case 0x0003: // XCONFIG_USER_TIME_ZONE_DLT_NAME
|
||||
case 0x0004: // XCONFIG_USER_TIME_ZONE_STD_DATE
|
||||
case 0x0005: // XCONFIG_USER_TIME_ZONE_DLT_DATE
|
||||
case 0x0006: // XCONFIG_USER_TIME_ZONE_STD_BIAS
|
||||
case 0x0007: // XCONFIG_USER_TIME_ZONE_DLT_BIAS
|
||||
setting_size = 4;
|
||||
// TODO(benvanik): get this value.
|
||||
value = 0;
|
||||
break;
|
||||
case 0x0009: // XCONFIG_USER_LANGUAGE
|
||||
setting_size = 4;
|
||||
value = 0x00000001; // English
|
||||
break;
|
||||
case 0x000A: // XCONFIG_USER_VIDEO_FLAGS
|
||||
setting_size = 4;
|
||||
value = 0x00040000;
|
||||
break;
|
||||
case 0x000C: // XCONFIG_USER_RETAIL_FLAGS
|
||||
setting_size = 4;
|
||||
// TODO(benvanik): get this value.
|
||||
value = 0;
|
||||
break;
|
||||
case 0x000E: // XCONFIG_USER_COUNTRY
|
||||
setting_size = 4;
|
||||
// TODO(benvanik): get this value.
|
||||
value = 0;
|
||||
break;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
return X_STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
return X_STATUS_INVALID_PARAMETER_1;
|
||||
}
|
||||
|
||||
if (buffer_size < setting_size) {
|
||||
return X_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
if (!buffer && buffer_size) {
|
||||
return X_STATUS_INVALID_PARAMETER_3;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
XESETUINT32BE(buffer, value);
|
||||
}
|
||||
if (required_size) {
|
||||
*required_size = setting_size;
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL ExGetXConfigSetting_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint16_t category = SHIM_GET_ARG_16(0);
|
||||
uint16_t setting = SHIM_GET_ARG_16(1);
|
||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
|
||||
uint16_t buffer_size = SHIM_GET_ARG_16(3);
|
||||
uint32_t required_size_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"ExGetXConfigSetting(%.4X, %.4X, %.8X, %.4X, %.8X)",
|
||||
category, setting, buffer_ptr, buffer_size, required_size_ptr);
|
||||
|
||||
void* buffer = buffer_ptr ? SHIM_MEM_ADDR(buffer_ptr) : NULL;
|
||||
uint16_t required_size = 0;
|
||||
X_STATUS result = xeExGetXConfigSetting(
|
||||
category, setting, buffer, buffer_size, &required_size);
|
||||
|
||||
if (required_size_ptr) {
|
||||
SHIM_SET_MEM_16(required_size_ptr, required_size);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int xeXexCheckExecutablePriviledge(uint32_t privilege) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// BOOL
|
||||
// DWORD Privilege
|
||||
|
||||
// Privilege is bit position in xe_xex2_system_flags enum - so:
|
||||
// Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS
|
||||
uint32_t mask = 1 << privilege;
|
||||
|
||||
XModule* module = state->GetExecutableModule();
|
||||
if (!module) {
|
||||
return 0;
|
||||
}
|
||||
xe_xex2_ref xex = module->xex();
|
||||
|
||||
const xe_xex2_header_t* header = xe_xex2_get_header(xex);
|
||||
uint32_t result = (header->system_flags & mask) > 0;
|
||||
|
||||
xe_xex2_release(xex);
|
||||
module->Release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL XexCheckExecutablePrivilege_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t privilege = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"XexCheckExecutablePrivilege(%.8X)",
|
||||
privilege);
|
||||
|
||||
int result = xeXexCheckExecutablePriviledge(privilege);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int xeXexGetModuleHandle(const char* module_name,
|
||||
X_HANDLE* module_handle_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// BOOL
|
||||
// LPCSZ ModuleName
|
||||
// LPHMODULE ModuleHandle
|
||||
|
||||
XModule* module = state->GetModule(module_name);
|
||||
if (!module) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: we don't retain the handle for return.
|
||||
*module_handle_ptr = module->handle();
|
||||
|
||||
module->Release();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL XexGetModuleHandle_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
|
||||
const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
|
||||
uint32_t module_handle_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"XexGetModuleHandle(%s, %.8X)",
|
||||
module_name, module_handle_ptr);
|
||||
|
||||
X_HANDLE module_handle = 0;
|
||||
int result = xeXexGetModuleHandle(module_name, &module_handle);
|
||||
if (result) {
|
||||
SHIM_SET_MEM_32(module_handle_ptr, module_handle);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// SHIM_CALL XexGetModuleSection_shim(
|
||||
// xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
// }
|
||||
|
||||
|
||||
// SHIM_CALL XexGetProcedureAddress_shim(
|
||||
// xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
// }
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterModuleExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleHandle, state);
|
||||
// SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleSection, state);
|
||||
// SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);
|
||||
}
|
||||
38
src/xenia/kernel/xboxkrnl/xboxkrnl_modules.h
Normal file
38
src/xenia/kernel/xboxkrnl/xboxkrnl_modules.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_MODULES_IMPL_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_MODULES_IMPL_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
X_STATUS xeExGetXConfigSetting(
|
||||
uint16_t category, uint16_t setting, void* buffer, uint16_t buffer_size,
|
||||
uint16_t* required_size);
|
||||
|
||||
int xeXexCheckExecutablePriviledge(uint32_t privilege);
|
||||
|
||||
int xeXexGetModuleHandle(const char* module_name,
|
||||
X_HANDLE* module_handle_ptr);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_MODULES_IMPL_H_
|
||||
52
src/xenia/kernel/xboxkrnl/xboxkrnl_nt.cc
Normal file
52
src/xenia/kernel/xboxkrnl/xboxkrnl_nt.cc
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_nt.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
SHIM_CALL NtClose_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t handle = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"NtClose(%.8X)",
|
||||
handle);
|
||||
|
||||
X_STATUS result = X_STATUS_INVALID_HANDLE;
|
||||
|
||||
result = state->object_table()->RemoveHandle(handle);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterNtExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtClose, state);
|
||||
}
|
||||
29
src/xenia/kernel/xboxkrnl/xboxkrnl_nt.h
Normal file
29
src/xenia/kernel/xboxkrnl/xboxkrnl_nt.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_NT_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_NT_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_NT_H_
|
||||
101
src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc
Normal file
101
src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_ob.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/xobject.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
SHIM_CALL ObReferenceObjectByHandle_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t out_object_ptr = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD(
|
||||
"ObReferenceObjectByHandle(%.8X, %.8X, %.8X)",
|
||||
handle,
|
||||
object_type_ptr,
|
||||
out_object_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_INVALID_HANDLE;
|
||||
|
||||
XObject* object = NULL;
|
||||
result = state->object_table()->GetObject(handle, &object);
|
||||
if (XSUCCEEDED(result)) {
|
||||
// TODO(benvanik): verify type with object_type_ptr
|
||||
|
||||
// TODO(benvanik): get native value, if supported.
|
||||
uint32_t native_ptr = 0xDEADF00D;
|
||||
switch (object_type_ptr) {
|
||||
case 0xD01BBEEF: // ExThreadObjectType
|
||||
{
|
||||
XThread* thread = (XThread*)object;
|
||||
native_ptr = thread->thread_state();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_object_ptr) {
|
||||
SHIM_SET_MEM_32(out_object_ptr, native_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL ObDereferenceObject_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t native_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"ObDereferenceObject(%.8X)",
|
||||
native_ptr);
|
||||
|
||||
// Check if a dummy value from ObReferenceObjectByHandle.
|
||||
if (native_ptr == 0xDEADF00D) {
|
||||
SHIM_SET_RETURN(0);
|
||||
return;
|
||||
}
|
||||
|
||||
void* object_ptr = SHIM_MEM_ADDR(native_ptr);
|
||||
XObject* object = XObject::GetObject(state, object_ptr);
|
||||
if (object) {
|
||||
object->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterObExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ObReferenceObjectByHandle, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ObDereferenceObject, state);
|
||||
}
|
||||
29
src/xenia/kernel/xboxkrnl/xboxkrnl_ob.h
Normal file
29
src/xenia/kernel/xboxkrnl/xboxkrnl_ob.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_OB_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_OB_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_OB_H_
|
||||
29
src/xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h
Normal file
29
src/xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_ORDINALS_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_ORDINALS_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/export_resolver.h>
|
||||
|
||||
|
||||
// Build an ordinal enum to make it easy to lookup ordinals.
|
||||
#include <xenia/kernel/util/ordinal_table_pre.inc>
|
||||
namespace ordinals {
|
||||
enum {
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_table.inc>
|
||||
};
|
||||
} // namespace ordinals
|
||||
#include <xenia/kernel/util/ordinal_table_post.inc>
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_ORDINALS_H_
|
||||
51
src/xenia/kernel/xboxkrnl/xboxkrnl_private.h
Normal file
51
src/xenia/kernel/xboxkrnl/xboxkrnl_private.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_PRIVATE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_PRIVATE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_ordinals.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
class KernelState;
|
||||
|
||||
|
||||
// This is a global object initialized with the XboxkrnlModule.
|
||||
// It references the current kernel state object that all kernel methods should
|
||||
// be using to stash their variables.
|
||||
extern KernelState* shared_kernel_state_;
|
||||
|
||||
// Registration functions, one per file.
|
||||
void RegisterDebugExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterHalExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterIoExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterMemoryExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterMiscExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterModuleExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterNtExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterObExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterRtlExports(ExportResolver* export_resolver, KernelState* state);
|
||||
void RegisterThreadingExports(ExportResolver* export_resolver,
|
||||
KernelState* state);
|
||||
void RegisterVideoExports(ExportResolver* export_resolver, KernelState* state);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_PRIVATE_H_
|
||||
898
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc
Normal file
898
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc
Normal file
@@ -0,0 +1,898 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_rtl.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xex2.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561778
|
||||
uint32_t xeRtlCompareMemory(uint32_t source1_ptr, uint32_t source2_ptr,
|
||||
uint32_t length) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// SIZE_T
|
||||
// _In_ const VOID *Source1,
|
||||
// _In_ const VOID *Source2,
|
||||
// _In_ SIZE_T Length
|
||||
|
||||
uint8_t* p1 = IMPL_MEM_ADDR(source1_ptr);
|
||||
uint8_t* p2 = IMPL_MEM_ADDR(source2_ptr);
|
||||
|
||||
// Note that the return value is the number of bytes that match, so it's best
|
||||
// we just do this ourselves vs. using memcmp.
|
||||
// On Windows we could use the builtin function.
|
||||
|
||||
uint32_t c = 0;
|
||||
for (uint32_t n = 0; n < length; n++, p1++, p2++) {
|
||||
if (*p1 == *p2) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlCompareMemory_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t source1 = SHIM_GET_ARG_32(0);
|
||||
uint32_t source2 = SHIM_GET_ARG_32(1);
|
||||
uint32_t length = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD(
|
||||
"RtlCompareMemory(%.8X, %.8X, %d)",
|
||||
source1, source2, length);
|
||||
|
||||
uint32_t result = xeRtlCompareMemory(source1, source2, length);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff552123
|
||||
uint32_t xeRtlCompareMemoryUlong(uint32_t source_ptr, uint32_t length,
|
||||
uint32_t pattern) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// SIZE_T
|
||||
// _In_ PVOID Source,
|
||||
// _In_ SIZE_T Length,
|
||||
// _In_ ULONG Pattern
|
||||
|
||||
if ((source_ptr % 4) || (length % 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* p = IMPL_MEM_ADDR(source_ptr);
|
||||
|
||||
// Swap pattern.
|
||||
// TODO(benvanik): ensure byte order of pattern is correct.
|
||||
// Since we are doing byte-by-byte comparison we may not want to swap.
|
||||
// GET_ARG swaps, so this is a swap back. Ugly.
|
||||
const uint32_t pb32 = XESWAP32BE(pattern);
|
||||
const uint8_t* pb = (uint8_t*)&pb32;
|
||||
|
||||
uint32_t c = 0;
|
||||
for (uint32_t n = 0; n < length; n++, p++) {
|
||||
if (*p == pb[n % 4]) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlCompareMemoryUlong_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t source = SHIM_GET_ARG_32(0);
|
||||
uint32_t length = SHIM_GET_ARG_32(1);
|
||||
uint32_t pattern = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD(
|
||||
"RtlCompareMemoryUlong(%.8X, %d, %.8X)",
|
||||
source, length, pattern);
|
||||
|
||||
uint32_t result = xeRtlCompareMemoryUlong(source, length, pattern);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff552263
|
||||
void xeRtlFillMemoryUlong(uint32_t destination_ptr, uint32_t length,
|
||||
uint32_t pattern) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Out_ PVOID Destination,
|
||||
// _In_ SIZE_T Length,
|
||||
// _In_ ULONG Pattern
|
||||
|
||||
// NOTE: length must be % 4, so we can work on uint32s.
|
||||
uint32_t* p = (uint32_t*)IMPL_MEM_ADDR(destination_ptr);
|
||||
|
||||
// TODO(benvanik): ensure byte order is correct - we're writing back the
|
||||
// swapped arg value.
|
||||
|
||||
uint32_t count = length >> 2;
|
||||
uint32_t native_pattern = XESWAP32BE(pattern);
|
||||
|
||||
// TODO: unroll loop?
|
||||
|
||||
for (uint32_t n = 0; n < count; n++, p++) {
|
||||
*p = native_pattern;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlFillMemoryUlong_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t destination = SHIM_GET_ARG_32(0);
|
||||
uint32_t length = SHIM_GET_ARG_32(1);
|
||||
uint32_t pattern = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD(
|
||||
"RtlFillMemoryUlong(%.8X, %d, %.8X)",
|
||||
destination, length, pattern);
|
||||
|
||||
xeRtlFillMemoryUlong(destination, length, pattern);
|
||||
}
|
||||
|
||||
|
||||
// typedef struct _STRING {
|
||||
// USHORT Length;
|
||||
// USHORT MaximumLength;
|
||||
// PCHAR Buffer;
|
||||
// } ANSI_STRING, *PANSI_STRING;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561918
|
||||
void xeRtlInitAnsiString(uint32_t destination_ptr, uint32_t source_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Out_ PANSI_STRING DestinationString,
|
||||
// _In_opt_ PCSZ SourceString
|
||||
|
||||
const char* source = source_ptr ? (char*)IMPL_MEM_ADDR(source_ptr) : NULL;
|
||||
|
||||
if (source) {
|
||||
uint16_t length = (uint16_t)xestrlena(source);
|
||||
IMPL_SET_MEM_16(destination_ptr + 0, length);
|
||||
IMPL_SET_MEM_16(destination_ptr + 2, length + 1);
|
||||
IMPL_SET_MEM_32(destination_ptr + 4, source_ptr);
|
||||
} else {
|
||||
IMPL_SET_MEM_16(destination_ptr + 0, 0);
|
||||
IMPL_SET_MEM_16(destination_ptr + 2, 0);
|
||||
IMPL_SET_MEM_32(destination_ptr + 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlInitAnsiString_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t source_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
const char* source = source_ptr ? (char*)SHIM_MEM_ADDR(source_ptr) : NULL;
|
||||
XELOGD("RtlInitAnsiString(%.8X, %.8X = %s)",
|
||||
destination_ptr, source_ptr, source ? source : "<null>");
|
||||
|
||||
xeRtlInitAnsiString(destination_ptr, source_ptr);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561899
|
||||
void xeRtlFreeAnsiString(uint32_t string_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Inout_ PANSI_STRING AnsiString
|
||||
|
||||
//uint32_t buffer = SHIM_MEM_32(string_ptr + 4);
|
||||
// TODO(benvanik): free the buffer
|
||||
XELOGE("RtlFreeAnsiString leaking buffer");
|
||||
|
||||
IMPL_SET_MEM_16(string_ptr + 0, 0);
|
||||
IMPL_SET_MEM_16(string_ptr + 2, 0);
|
||||
IMPL_SET_MEM_32(string_ptr + 4, 0);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlFreeAnsiString_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t string_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("RtlFreeAnsiString(%.8X)", string_ptr);
|
||||
|
||||
xeRtlFreeAnsiString(string_ptr);
|
||||
}
|
||||
|
||||
|
||||
// typedef struct _UNICODE_STRING {
|
||||
// USHORT Length;
|
||||
// USHORT MaximumLength;
|
||||
// PWSTR Buffer;
|
||||
// } UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561934
|
||||
void xeRtlInitUnicodeString(uint32_t destination_ptr, uint32_t source_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Out_ PUNICODE_STRING DestinationString,
|
||||
// _In_opt_ PCWSTR SourceString
|
||||
|
||||
const wchar_t* source =
|
||||
source_ptr ? (const wchar_t*)IMPL_MEM_ADDR(source_ptr) : NULL;
|
||||
|
||||
if (source) {
|
||||
uint16_t length = (uint16_t)xestrlenw(source);
|
||||
IMPL_SET_MEM_16(destination_ptr + 0, length * 2);
|
||||
IMPL_SET_MEM_16(destination_ptr + 2, (length + 1) * 2);
|
||||
IMPL_SET_MEM_32(destination_ptr + 4, source_ptr);
|
||||
} else {
|
||||
IMPL_SET_MEM_16(destination_ptr + 0, 0);
|
||||
IMPL_SET_MEM_16(destination_ptr + 2, 0);
|
||||
IMPL_SET_MEM_32(destination_ptr + 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlInitUnicodeString_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t source_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
const wchar_t* source =
|
||||
source_ptr ? (const wchar_t*)SHIM_MEM_ADDR(source_ptr) : NULL;
|
||||
XELOGD("RtlInitUnicodeString(%.8X, %.8X = %ls)",
|
||||
destination_ptr, source_ptr, source ? source : L"<null>");
|
||||
|
||||
xeRtlInitUnicodeString(destination_ptr, source_ptr);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff561903
|
||||
void xeRtlFreeUnicodeString(uint32_t string_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Inout_ PUNICODE_STRING UnicodeString
|
||||
|
||||
//uint32_t buffer = IMPL_MEM_32(string_ptr + 4);
|
||||
// TODO(benvanik): free the buffer
|
||||
XELOGE("RtlFreeUnicodeString leaking buffer");
|
||||
|
||||
IMPL_SET_MEM_16(string_ptr + 0, 0);
|
||||
IMPL_SET_MEM_16(string_ptr + 2, 0);
|
||||
IMPL_SET_MEM_32(string_ptr + 4, 0);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlFreeUnicodeString_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t string_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("RtlFreeUnicodeString(%.8X)", string_ptr);
|
||||
|
||||
xeRtlFreeUnicodeString(string_ptr);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ff562969
|
||||
X_STATUS xeRtlUnicodeStringToAnsiString(
|
||||
uint32_t destination_ptr, uint32_t source_ptr, uint32_t alloc_dest) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// NTSTATUS
|
||||
// _Inout_ PANSI_STRING DestinationString,
|
||||
// _In_ PCUNICODE_STRING SourceString,
|
||||
// _In_ BOOLEAN AllocateDestinationString
|
||||
|
||||
XELOGE("RtlUnicodeStringToAnsiString not yet implemented");
|
||||
XEASSERTALWAYS();
|
||||
|
||||
if (alloc_dest) {
|
||||
// Allocate a new buffer to place the string into.
|
||||
//IMPL_SET_MEM_32(destination_ptr + 4, buffer_ptr);
|
||||
} else {
|
||||
// Reuse the buffer in the target.
|
||||
//uint32_t buffer_size = IMPL_MEM_16(destination_ptr + 2);
|
||||
}
|
||||
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlUnicodeStringToAnsiString_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t source_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t alloc_dest = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("RtlUnicodeStringToAnsiString(%.8X, %.8X, %d)",
|
||||
destination_ptr, source_ptr, alloc_dest);
|
||||
|
||||
X_STATUS result = xeRtlUnicodeStringToAnsiString(
|
||||
destination_ptr, source_ptr, alloc_dest);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// TODO: clean me up!
|
||||
SHIM_CALL _vsnprintf_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
|
||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t count = SHIM_GET_ARG_32(1);
|
||||
uint32_t format_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t arg_ptr = SHIM_GET_ARG_32(3);
|
||||
|
||||
if (format_ptr == 0) {
|
||||
SHIM_SET_RETURN(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
char *buffer = (char *)SHIM_MEM_ADDR(buffer_ptr); // TODO: ensure it never writes past the end of the buffer (count)...
|
||||
const char *format = (const char *)SHIM_MEM_ADDR(format_ptr);
|
||||
|
||||
int arg_index = 0;
|
||||
|
||||
char *b = buffer;
|
||||
for (; *format != '\0'; ++format) {
|
||||
const char *start = format;
|
||||
|
||||
if (*format != '%') {
|
||||
*b++ = *format;
|
||||
continue;
|
||||
}
|
||||
|
||||
++format;
|
||||
if (*format == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*format == '%') {
|
||||
*b++ = *format;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *end;
|
||||
end = format;
|
||||
|
||||
// skip flags
|
||||
while (*end == '-' ||
|
||||
*end == '+' ||
|
||||
*end == ' ' ||
|
||||
*end == '#' ||
|
||||
*end == '0') {
|
||||
++end;
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
int arg_extras = 0;
|
||||
|
||||
// skip width
|
||||
if (*end == '*') {
|
||||
++end;
|
||||
arg_extras++;
|
||||
}
|
||||
else {
|
||||
while (*end >= '0' && *end <= '9') {
|
||||
++end;
|
||||
}
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
// skip precision
|
||||
if (*end == '.') {
|
||||
++end;
|
||||
|
||||
if (*end == '*') {
|
||||
++end;
|
||||
++arg_extras;
|
||||
}
|
||||
else {
|
||||
while (*end >= '0' && *end <= '9') {
|
||||
++end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
// get length
|
||||
int arg_size = 4;
|
||||
|
||||
if (*end == 'h') {
|
||||
++end;
|
||||
arg_size = 4;
|
||||
if (*end == 'h') {
|
||||
++end;
|
||||
}
|
||||
}
|
||||
else if (*end == 'l') {
|
||||
++end;
|
||||
arg_size = 4;
|
||||
if (*end == 'l') {
|
||||
++end;
|
||||
arg_size = 8;
|
||||
}
|
||||
}
|
||||
else if (*end == 'j') {
|
||||
arg_size = 8;
|
||||
++end;
|
||||
}
|
||||
else if (*end == 'z') {
|
||||
arg_size = 4;
|
||||
++end;
|
||||
}
|
||||
else if (*end == 't') {
|
||||
arg_size = 8;
|
||||
++end;
|
||||
}
|
||||
else if (*end == 'L') {
|
||||
arg_size = 8;
|
||||
++end;
|
||||
}
|
||||
|
||||
if (*end == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*end == 'd' ||
|
||||
*end == 'i' ||
|
||||
*end == 'u' ||
|
||||
*end == 'o' ||
|
||||
*end == 'x' ||
|
||||
*end == 'X' ||
|
||||
*end == 'f' ||
|
||||
*end == 'F' ||
|
||||
*end == 'e' ||
|
||||
*end == 'E' ||
|
||||
*end == 'g' ||
|
||||
*end == 'G' ||
|
||||
*end == 'a' ||
|
||||
*end == 'A' ||
|
||||
*end == 'c') {
|
||||
char local[512];
|
||||
local[0] = '\0';
|
||||
strncat(local, start, end + 1 - start);
|
||||
|
||||
XEASSERT(arg_size == 8 || arg_size == 4);
|
||||
if (arg_size == 8) {
|
||||
if (arg_extras == 0) {
|
||||
uint64_t value = SHIM_MEM_64(arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
|
||||
int result = sprintf(b, local, value);
|
||||
b += result;
|
||||
arg_index++;
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
}
|
||||
}
|
||||
else if (arg_size == 4) {
|
||||
if (arg_extras == 0) {
|
||||
uint32_t value = (uint32_t)SHIM_MEM_64(arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
|
||||
int result = sprintf(b, local, value);
|
||||
b += result;
|
||||
arg_index++;
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*end == 's' ||
|
||||
*end == 'p' ||
|
||||
*end == 'n') {
|
||||
char local[512];
|
||||
local[0] = '\0';
|
||||
strncat(local, start, end + 1 - start);
|
||||
|
||||
XEASSERT(arg_size == 4);
|
||||
if (arg_extras == 0) {
|
||||
uint32_t value = (uint32_t)SHIM_MEM_64(arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
|
||||
const char *pointer = (const char *)SHIM_MEM_ADDR(value);
|
||||
int result = sprintf(b, local, pointer);
|
||||
b += result;
|
||||
arg_index++;
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
XEASSERT(false);
|
||||
break;
|
||||
}
|
||||
format = end;
|
||||
}
|
||||
*b++ = '\0';
|
||||
SHIM_SET_RETURN((uint32_t)(b - buffer));
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeRtlNtStatusToDosError(X_STATUS status) {
|
||||
if (!status || (status & 0x20000000)) {
|
||||
// Success.
|
||||
return status;
|
||||
} else if ((status & 0xF0000000) == 0xD0000000) {
|
||||
// High bit doesn't matter.
|
||||
status &= ~0x10000000;
|
||||
}
|
||||
|
||||
// TODO(benvanik): implement lookup table.
|
||||
XELOGE("RtlNtStatusToDosError lookup NOT IMPLEMENTED");
|
||||
|
||||
return 317; // ERROR_MR_MID_NOT_FOUND
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlNtStatusToDosError_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t status = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"RtlNtStatusToDosError(%.4X)",
|
||||
status);
|
||||
|
||||
uint32_t result = xeRtlNtStatusToDosError(status);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeRtlImageXexHeaderField(uint32_t xex_header_base_ptr,
|
||||
uint32_t image_field) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// PVOID
|
||||
// PVOID XexHeaderBase
|
||||
// DWORD ImageField
|
||||
|
||||
// NOTE: this is totally faked!
|
||||
// We set the XexExecutableModuleHandle pointer to a block that has at offset
|
||||
// 0x58 a pointer to our XexHeaderBase. If the value passed doesn't match
|
||||
// then die.
|
||||
// The only ImageField I've seen in the wild is
|
||||
// 0x20401 (XEX_HEADER_DEFAULT_HEAP_SIZE), so that's all we'll support.
|
||||
|
||||
XModule* module = NULL;
|
||||
|
||||
// TODO(benvanik): use xex_header_base to dereference this.
|
||||
// Right now we are only concerned with games making this call on their main
|
||||
// module, so this hack is fine.
|
||||
module = state->GetExecutableModule();
|
||||
|
||||
const xe_xex2_header_t* xex_header = module->xex_header();
|
||||
for (size_t n = 0; n < xex_header->header_count; n++) {
|
||||
if (xex_header->headers[n].key == image_field) {
|
||||
module->Release();
|
||||
return xex_header->headers[n].value;
|
||||
}
|
||||
}
|
||||
|
||||
module->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlImageXexHeaderField_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t xex_header_base = SHIM_GET_ARG_32(0);
|
||||
uint32_t image_field = SHIM_GET_ARG_32(1);
|
||||
|
||||
// NOTE: this is totally faked!
|
||||
// We set the XexExecutableModuleHandle pointer to a block that has at offset
|
||||
// 0x58 a pointer to our XexHeaderBase. If the value passed doesn't match
|
||||
// then die.
|
||||
// The only ImageField I've seen in the wild is
|
||||
// 0x20401 (XEX_HEADER_DEFAULT_HEAP_SIZE), so that's all we'll support.
|
||||
|
||||
XELOGD(
|
||||
"RtlImageXexHeaderField(%.8X, %.8X)",
|
||||
xex_header_base, image_field);
|
||||
|
||||
uint32_t result = xeRtlImageXexHeaderField(xex_header_base, image_field);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// Unfortunately the Windows RTL_CRITICAL_SECTION object is bigger than the one
|
||||
// on the 360 (32b vs. 28b). This means that we can't do in-place splatting of
|
||||
// the critical sections. Also, the 360 never calls RtlDeleteCriticalSection
|
||||
// so we can't clean up the native handles.
|
||||
//
|
||||
// Because of this, we reimplement it poorly. Hooray.
|
||||
// We have 28b to work with so we need to be careful. We map our struct directly
|
||||
// into guest memory, as it should be opaque and so long as our size is right
|
||||
// the user code will never know.
|
||||
//
|
||||
// Ref: http://msdn.microsoft.com/en-us/magazine/cc164040.aspx
|
||||
// Ref: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/critical.c?view=markup
|
||||
|
||||
|
||||
// This structure tries to match the one on the 360 as best I can figure out.
|
||||
// Unfortunately some games have the critical sections pre-initialized in
|
||||
// their embedded data and InitializeCriticalSection will never be called.
|
||||
namespace {
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint8_t unknown00;
|
||||
uint8_t spin_count_div_256; // * 256
|
||||
uint8_t __padding[6];
|
||||
//uint32_t unknown04; // maybe the handle to the event?
|
||||
uint32_t unknown08; // head of queue, pointing to this offset
|
||||
uint32_t unknown0C; // tail of queue?
|
||||
int32_t lock_count; // -1 -> 0 on first lock 0x10
|
||||
uint32_t recursion_count; // 0 -> 1 on first lock 0x14
|
||||
uint32_t owning_thread_id; // 0 unless locked 0x18
|
||||
} X_RTL_CRITICAL_SECTION;
|
||||
#pragma pack(pop)
|
||||
}
|
||||
|
||||
XEASSERTSTRUCTSIZE(X_RTL_CRITICAL_SECTION, 28);
|
||||
|
||||
void xeRtlInitializeCriticalSection(uint32_t cs_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Out_ LPCRITICAL_SECTION lpCriticalSection
|
||||
|
||||
X_RTL_CRITICAL_SECTION* cs = (X_RTL_CRITICAL_SECTION*)IMPL_MEM_ADDR(cs_ptr);
|
||||
cs->unknown00 = 1;
|
||||
cs->spin_count_div_256 = 0;
|
||||
cs->lock_count = -1;
|
||||
cs->recursion_count = 0;
|
||||
cs->owning_thread_id = 0;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlInitializeCriticalSection_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("RtlInitializeCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
xeRtlInitializeCriticalSection(cs_ptr);
|
||||
}
|
||||
|
||||
|
||||
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(
|
||||
uint32_t cs_ptr, uint32_t spin_count) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// NTSTATUS
|
||||
// _Out_ LPCRITICAL_SECTION lpCriticalSection,
|
||||
// _In_ DWORD dwSpinCount
|
||||
|
||||
// Spin count is rouned up to 256 intervals then packed in.
|
||||
//uint32_t spin_count_div_256 = (uint32_t)floor(spin_count / 256.0f + 0.5f);
|
||||
uint32_t spin_count_div_256 = (spin_count + 255) >> 8;
|
||||
if (spin_count_div_256 > 255) {
|
||||
spin_count_div_256 = 255;
|
||||
}
|
||||
|
||||
X_RTL_CRITICAL_SECTION* cs = (X_RTL_CRITICAL_SECTION*)IMPL_MEM_ADDR(cs_ptr);
|
||||
cs->unknown00 = 1;
|
||||
cs->spin_count_div_256 = spin_count_div_256;
|
||||
cs->lock_count = -1;
|
||||
cs->recursion_count = 0;
|
||||
cs->owning_thread_id = 0;
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlInitializeCriticalSectionAndSpinCount_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t spin_count = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD("RtlInitializeCriticalSectionAndSpinCount(%.8X, %d)",
|
||||
cs_ptr, spin_count);
|
||||
|
||||
X_STATUS result = xeRtlInitializeCriticalSectionAndSpinCount(
|
||||
cs_ptr, spin_count);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// TODO(benvanik): remove the need for passing in thread_id.
|
||||
void xeRtlEnterCriticalSection(uint32_t cs_ptr, uint32_t thread_id) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||
|
||||
X_RTL_CRITICAL_SECTION* cs = (X_RTL_CRITICAL_SECTION*)IMPL_MEM_ADDR(cs_ptr);
|
||||
|
||||
uint32_t spin_wait_remaining = cs->spin_count_div_256 * 256;
|
||||
spin:
|
||||
if (xe_atomic_inc_32(&cs->lock_count)) {
|
||||
// If this thread already owns the CS increment the recursion count.
|
||||
if (cs->owning_thread_id == thread_id) {
|
||||
cs->recursion_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Thread was locked - spin wait.
|
||||
if (spin_wait_remaining) {
|
||||
spin_wait_remaining--;
|
||||
goto spin;
|
||||
}
|
||||
|
||||
// All out of spin waits, create a full waiter.
|
||||
// TODO(benvanik): contention - do a real wait!
|
||||
//XELOGE("RtlEnterCriticalSection tried to really lock!");
|
||||
spin_wait_remaining = 1; // HACK: spin forever
|
||||
Sleep(1);
|
||||
goto spin;
|
||||
}
|
||||
|
||||
// Now own the lock.
|
||||
cs->owning_thread_id = thread_id;
|
||||
cs->recursion_count = 1;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlEnterCriticalSection_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
const uint8_t* thread_state_block = ppc_state->membase + ppc_state->r[13];
|
||||
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
|
||||
|
||||
xeRtlEnterCriticalSection(cs_ptr, thread_id);
|
||||
}
|
||||
|
||||
|
||||
// TODO(benvanik): remove the need for passing in thread_id.
|
||||
uint32_t xeRtlTryEnterCriticalSection(uint32_t cs_ptr, uint32_t thread_id) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// DWORD
|
||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||
|
||||
X_RTL_CRITICAL_SECTION* cs = (X_RTL_CRITICAL_SECTION*)IMPL_MEM_ADDR(cs_ptr);
|
||||
|
||||
if (xe_atomic_cas_32(-1, 0, &cs->lock_count)) {
|
||||
// Able to steal the lock right away.
|
||||
cs->owning_thread_id = thread_id;
|
||||
cs->recursion_count = 1;
|
||||
return 1;
|
||||
} else if (cs->owning_thread_id == thread_id) {
|
||||
xe_atomic_inc_32(&cs->lock_count);
|
||||
++cs->recursion_count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlTryEnterCriticalSection_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
const uint8_t* thread_state_block = ppc_state->membase + ppc_state->r[13];
|
||||
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
|
||||
|
||||
uint32_t result = xeRtlTryEnterCriticalSection(cs_ptr, thread_id);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
void xeRtlLeaveCriticalSection(uint32_t cs_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// VOID
|
||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||
|
||||
X_RTL_CRITICAL_SECTION* cs = (X_RTL_CRITICAL_SECTION*)IMPL_MEM_ADDR(cs_ptr);
|
||||
|
||||
// Drop recursion count - if we are still not zero'ed return.
|
||||
uint32_t recursion_count = --cs->recursion_count;
|
||||
if (recursion_count) {
|
||||
xe_atomic_dec_32(&cs->lock_count);
|
||||
return;
|
||||
}
|
||||
|
||||
// Unlock!
|
||||
cs->owning_thread_id = 0;
|
||||
if (xe_atomic_dec_32(&cs->lock_count) != -1) {
|
||||
// There were waiters - wake one of them.
|
||||
// TODO(benvanik): wake a waiter.
|
||||
XELOGE("RtlLeaveCriticalSection would have woken a waiter");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL RtlLeaveCriticalSection_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("RtlLeaveCriticalSection(%.8X)", cs_ptr);
|
||||
|
||||
xeRtlLeaveCriticalSection(cs_ptr);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterRtlExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlCompareMemory, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlCompareMemoryUlong, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlFillMemoryUlong, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitAnsiString, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlFreeAnsiString, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitUnicodeString, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlFreeUnicodeString, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeStringToAnsiString, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", _vsnprintf, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlNtStatusToDosError, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlImageXexHeaderField, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSection, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSectionAndSpinCount, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlEnterCriticalSection, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTryEnterCriticalSection, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", RtlLeaveCriticalSection, state);
|
||||
}
|
||||
57
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.h
Normal file
57
src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_RTL_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_RTL_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
uint32_t xeRtlCompareMemory(uint32_t source1_ptr, uint32_t source2_ptr,
|
||||
uint32_t length);
|
||||
uint32_t xeRtlCompareMemoryUlong(uint32_t source_ptr, uint32_t length,
|
||||
uint32_t pattern);
|
||||
void xeRtlFillMemoryUlong(uint32_t destination_ptr, uint32_t length,
|
||||
uint32_t pattern);
|
||||
|
||||
void xeRtlInitAnsiString(uint32_t destination_ptr, uint32_t source_ptr);
|
||||
void xeRtlFreeAnsiString(uint32_t string_ptr);
|
||||
|
||||
void xeRtlInitUnicodeString(uint32_t destination_ptr, uint32_t source_ptr);
|
||||
void xeRtlFreeUnicodeString(uint32_t string_ptr);
|
||||
X_STATUS xeRtlUnicodeStringToAnsiString(
|
||||
uint32_t destination_ptr, uint32_t source_ptr, uint32_t alloc_dest);
|
||||
|
||||
uint32_t xeRtlNtStatusToDosError(X_STATUS status);
|
||||
|
||||
uint32_t xeRtlImageXexHeaderField(uint32_t xex_header_base_ptr,
|
||||
uint32_t image_field);
|
||||
|
||||
void xeRtlInitializeCriticalSection(uint32_t cs_ptr);
|
||||
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(
|
||||
uint32_t cs_ptr, uint32_t spin_count);
|
||||
void xeRtlEnterCriticalSection(uint32_t cs_ptr, uint32_t thread_id);
|
||||
uint32_t xeRtlTryEnterCriticalSection(uint32_t cs_ptr, uint32_t thread_id);
|
||||
void xeRtlLeaveCriticalSection(uint32_t cs_ptr);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_RTL_H_
|
||||
872
src/xenia/kernel/xboxkrnl/xboxkrnl_table.inc
Normal file
872
src/xenia/kernel/xboxkrnl/xboxkrnl_table.inc
Normal file
@@ -0,0 +1,872 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
// This is a partial file designed to be included by other files when
|
||||
// constructing various tables.
|
||||
|
||||
|
||||
XE_EXPORT(xboxkrnl, 0x00000001, DbgBreakPoint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000002, DbgBreakPointWithStatus, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000003, DbgPrint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000004, DbgPrompt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000005, DumpGetRawDumpInfo, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000006, DumpWriteDump, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000007, ExAcquireReadWriteLockExclusive, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000008, ExAcquireReadWriteLockShared, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000009, ExAllocatePool, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000A, ExAllocatePoolWithTag, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000B, ExAllocatePoolTypeWithTag, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000C, ExConsoleGameRegion, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000D, ExCreateThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000E, ExEventObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000000F, ExFreePool, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000010, ExGetXConfigSetting, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000011, ExInitializeReadWriteLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000012, ExMutantObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000013, ExQueryPoolBlockSize, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000014, ExRegisterThreadNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000015, ExRegisterTitleTerminateNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000016, ExReleaseReadWriteLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000017, ExSemaphoreObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000018, ExSetXConfigSetting, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000019, ExTerminateThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001A, ExTerminateTitleProcess, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001B, ExThreadObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001C, ExTimerObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001D, MmDoubleMapMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001E, MmUnmapMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000001F, XeKeysGetConsoleCertificate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000020, FscGetCacheElementCount, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000021, FscSetCacheElementCount, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000022, HalGetCurrentAVPack, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000023, HalGpioControl, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000024, HalOpenCloseODDTray, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000025, HalReadWritePCISpace, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000026, HalRegisterPowerDownNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000027, HalRegisterSMCNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000028, HalReturnToFirmware, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000029, HalSendSMCMessage, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002A, HalSetAudioEnable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002B, InterlockedFlushSList, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002C, InterlockedPopEntrySList, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002D, InterlockedPushEntrySList, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002E, IoAcquireDeviceObjectLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000002F, IoAllocateIrp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000030, IoBuildAsynchronousFsdRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000031, IoBuildDeviceIoControlRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000032, IoBuildSynchronousFsdRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000033, IoCallDriver, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000034, IoCheckShareAccess, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000035, IoCompleteRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000036, IoCompletionObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000037, IoCreateDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000038, IoCreateFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000039, IoDeleteDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003A, IoDeviceObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003B, IoDismountVolume, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003C, IoDismountVolumeByFileHandle, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003D, IoDismountVolumeByName, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003E, IoFileObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000003F, IoFreeIrp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000040, IoInitializeIrp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000041, IoInvalidDeviceRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000042, ExSetBetaFeaturesEnabled, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000043, IoQueueThreadIrp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000044, IoReleaseDeviceObjectLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000045, IoRemoveShareAccess, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000046, IoSetIoCompletion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000047, IoSetShareAccess, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000048, IoStartNextPacket, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000049, IoStartNextPacketByKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004A, IoStartPacket, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004B, IoSynchronousDeviceIoControlRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004C, IoSynchronousFsdRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004D, KeAcquireSpinLockAtRaisedIrql, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004E, KeAlertResumeThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000004F, KeAlertThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000050, KeBlowFuses, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000051, KeBoostPriorityThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000052, KeBugCheck, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000053, KeBugCheckEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000054, KeCancelTimer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000055, KeConnectInterrupt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000056, KeContextFromKframes, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000057, KeContextToKframes, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000058, KeCreateUserMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000059, KeDebugMonitorData, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005A, KeDelayExecutionThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005B, KeDeleteUserMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005C, KeDisconnectInterrupt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005D, KeEnableFpuExceptions, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005E, KeEnablePPUPerformanceMonitor, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000005F, KeEnterCriticalRegion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000060, KeEnterUserMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000061, KeFlushCacheRange, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000062, KeFlushCurrentEntireTb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000063, KeFlushEntireTb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000064, KeFlushUserModeCurrentTb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000065, KeFlushUserModeTb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000066, KeGetCurrentProcessType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000067, KeGetPMWRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000068, KeGetPRVRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000069, KeGetSocRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006A, KeGetSpecialPurposeRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006B, KeLockL2, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006C, KeUnlockL2, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006D, KeInitializeApc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006E, KeInitializeDeviceQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000006F, KeInitializeDpc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000070, KeInitializeEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000071, KeInitializeInterrupt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000072, KeInitializeMutant, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000073, KeInitializeQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000074, KeInitializeSemaphore, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000075, KeInitializeTimerEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000076, KeInsertByKeyDeviceQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000077, KeInsertDeviceQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000078, KeInsertHeadQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000079, KeInsertQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007A, KeInsertQueueApc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007B, KeInsertQueueDpc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007C, KeIpiGenericCall, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007D, KeLeaveCriticalRegion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007E, KeLeaveUserMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000007F, KePulseEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000080, KeQueryBackgroundProcessors, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000081, KeQueryBasePriorityThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000082, KeQueryInterruptTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000083, KeQueryPerformanceFrequency, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000084, KeQuerySystemTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000085, KeRaiseIrqlToDpcLevel, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000086, KeRegisterDriverNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000087, KeReleaseMutant, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000088, KeReleaseSemaphore, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000089, KeReleaseSpinLockFromRaisedIrql, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008A, KeRemoveByKeyDeviceQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008B, KeRemoveDeviceQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008C, KeRemoveEntryDeviceQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008D, KeRemoveQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008E, KeRemoveQueueDpc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000008F, KeResetEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000090, KeRestoreFloatingPointState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000091, KeRestoreVectorUnitState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000092, KeResumeThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000093, KeRetireDpcList, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000094, KeRundownQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000095, KeSaveFloatingPointState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000096, KeSaveVectorUnitState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000097, KeSetAffinityThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000098, KeSetBackgroundProcessors, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000099, KeSetBasePriorityThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009A, KeSetCurrentProcessType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009B, KeSetCurrentStackPointers, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009C, KeSetDisableBoostThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009D, KeSetEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009E, KeSetEventBoostPriority, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000009F, KeSetPMWRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A0, KeSetPowerMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A1, KeSetPRVRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A2, KeSetPriorityClassThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A3, KeSetPriorityThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A4, KeSetSocRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A5, KeSetSpecialPurposeRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A6, KeSetTimer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A7, KeSetTimerEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A8, KeStallExecutionProcessor, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000A9, KeSuspendThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AA, KeSweepDcacheRange, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AB, KeSweepIcacheRange, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AC, KeTestAlertThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AD, KeTimeStampBundle, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AE, KeTryToAcquireSpinLockAtRaisedIrql, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000AF, KeWaitForMultipleObjects, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B0, KeWaitForSingleObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B1, KfAcquireSpinLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B2, KfRaiseIrql, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B3, KfLowerIrql, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B4, KfReleaseSpinLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B5, KiBugCheckData, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B6, LDICreateDecompression, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B7, LDIDecompress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B8, LDIDestroyDecompression, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000B9, MmAllocatePhysicalMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BA, MmAllocatePhysicalMemoryEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BB, MmCreateKernelStack, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BC, MmDeleteKernelStack, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BD, MmFreePhysicalMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BE, MmGetPhysicalAddress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000BF, MmIsAddressValid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C0, MmLockAndMapSegmentArray, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C1, MmLockUnlockBufferPages, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C2, MmMapIoSpace, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C3, MmPersistPhysicalMemoryAllocation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C4, MmQueryAddressProtect, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C5, MmQueryAllocationSize, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C6, MmQueryStatistics, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C7, MmSetAddressProtect, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C8, MmSplitPhysicalMemoryAllocation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000C9, MmUnlockAndUnmapSegmentArray, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CA, MmUnmapIoSpace, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CB, Nls844UnicodeCaseTable, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CC, NtAllocateVirtualMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CD, NtCancelTimer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CE, NtClearEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000CF, NtClose, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D0, NtCreateDirectoryObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D1, NtCreateEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D2, NtCreateFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D3, NtCreateIoCompletion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D4, NtCreateMutant, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D5, NtCreateSemaphore, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D6, NtCreateSymbolicLinkObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D7, NtCreateTimer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D8, NtDeleteFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000D9, NtDeviceIoControlFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DA, NtDuplicateObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DB, NtFlushBuffersFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DC, NtFreeVirtualMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DD, NtMakeTemporaryObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DE, NtOpenDirectoryObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000DF, NtOpenFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E0, NtOpenSymbolicLinkObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E1, NtProtectVirtualMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E2, NtPulseEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E3, NtQueueApcThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E4, NtQueryDirectoryFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E5, NtQueryDirectoryObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E6, NtQueryEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E7, NtQueryFullAttributesFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E8, NtQueryInformationFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000E9, NtQueryIoCompletion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EA, NtQueryMutant, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EB, NtQuerySemaphore, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EC, NtQuerySymbolicLinkObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000ED, NtQueryTimer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EE, NtQueryVirtualMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000EF, NtQueryVolumeInformationFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F0, NtReadFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F1, NtReadFileScatter, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F2, NtReleaseMutant, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F3, NtReleaseSemaphore, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F4, NtRemoveIoCompletion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F5, NtResumeThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F6, NtSetEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F7, NtSetInformationFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F8, NtSetIoCompletion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000F9, NtSetSystemTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FA, NtSetTimerEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FB, NtSignalAndWaitForSingleObjectEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FC, NtSuspendThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FD, NtWaitForSingleObjectEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FE, NtWaitForMultipleObjectsEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000000FF, NtWriteFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000100, NtWriteFileGather, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000101, NtYieldExecution, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000102, ObCreateObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000103, ObCreateSymbolicLink, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000104, ObDeleteSymbolicLink, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000105, ObDereferenceObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000106, ObDirectoryObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000107, ObGetWaitableObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000108, ObInsertObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000109, ObIsTitleObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010A, ObLookupAnyThreadByThreadId, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010B, ObLookupThreadByThreadId, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010C, ObMakeTemporaryObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010D, ObOpenObjectByName, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010E, ObOpenObjectByPointer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000010F, ObReferenceObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000110, ObReferenceObjectByHandle, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000111, ObReferenceObjectByName, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000112, ObSymbolicLinkObjectType, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000113, ObTranslateSymbolicLink, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000114, RtlAnsiStringToUnicodeString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000115, RtlAppendStringToString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000116, RtlAppendUnicodeStringToString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000117, RtlAppendUnicodeToString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000118, RtlAssert, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000119, RtlCaptureContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011A, RtlCompareMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011B, RtlCompareMemoryUlong, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011C, RtlCompareString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011D, RtlCompareStringN, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011E, RtlCompareUnicodeString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000011F, RtlCompareUnicodeStringN, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000120, RtlCompareUtf8ToUnicode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000121, RtlCopyString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000122, RtlCopyUnicodeString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000123, RtlCreateUnicodeString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000124, RtlDowncaseUnicodeChar, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000125, RtlEnterCriticalSection, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000126, RtlFillMemoryUlong, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000127, RtlFreeAnsiString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000128, RtlFreeUnicodeString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000129, RtlGetCallersAddress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012A, RtlGetStackLimits, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012B, RtlImageXexHeaderField, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012C, RtlInitAnsiString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012D, RtlInitUnicodeString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012E, RtlInitializeCriticalSection, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000012F, RtlInitializeCriticalSectionAndSpinCount, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000130, RtlLeaveCriticalSection, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000131, RtlLookupFunctionEntry, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000132, RtlLowerChar, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000133, RtlMultiByteToUnicodeN, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000134, RtlMultiByteToUnicodeSize, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000135, RtlNtStatusToDosError, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000136, RtlRaiseException, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000137, RtlRaiseStatus, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000138, RtlRip, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000139, _scprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013A, _snprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013B, sprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013C, _scwprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013D, _snwprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013E, _swprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000013F, RtlTimeFieldsToTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000140, RtlTimeToTimeFields, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000141, RtlTryEnterCriticalSection, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000142, RtlUnicodeStringToAnsiString, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000143, RtlUnicodeToMultiByteN, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000144, RtlUnicodeToMultiByteSize, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000145, RtlUnicodeToUtf8, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000146, RtlUnicodeToUtf8Size, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000147, RtlUnwind, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000148, RtlUnwind2, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000149, RtlUpcaseUnicodeChar, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014A, RtlUpperChar, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014B, RtlVirtualUnwind, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014C, _vscprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014D, _vsnprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014E, vsprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000014F, _vscwprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000150, _vsnwprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000151, _vswprintf, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000152, KeTlsAlloc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000153, KeTlsFree, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000154, KeTlsGetValue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000155, KeTlsSetValue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000156, XboxHardwareInfo, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000157, XboxKrnlBaseVersion, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000158, XboxKrnlVersion, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000159, XeCryptAesKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015A, XeCryptAesEcb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015B, XeCryptAesCbc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015C, XeCryptBnDwLeDhEqualBase, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015D, XeCryptBnDwLeDhInvalBase, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015E, XeCryptBnDwLeDhModExp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000015F, XeCryptBnDw_Copy, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000160, XeCryptBnDw_SwapLeBe, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000161, XeCryptBnDw_Zero, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000162, XeCryptBnDwLePkcs1Format, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000163, XeCryptBnDwLePkcs1Verify, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000164, XeCryptBnQwBeSigCreate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000165, XeCryptBnQwBeSigFormat, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000166, XeCryptBnQwBeSigVerify, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000167, XeCryptBnQwNeModExp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000168, XeCryptBnQwNeModExpRoot, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000169, XeCryptBnQwNeModInv, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016A, XeCryptBnQwNeModMul, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016B, XeCryptBnQwNeRsaKeyGen, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016C, XeCryptBnQwNeRsaPrvCrypt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016D, XeCryptBnQwNeRsaPubCrypt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016E, XeCryptBnQw_Copy, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000016F, XeCryptBnQw_SwapDwQw, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000170, XeCryptBnQw_SwapDwQwLeBe, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000171, XeCryptBnQw_SwapLeBe, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000172, XeCryptBnQw_Zero, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000173, XeCryptChainAndSumMac, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000174, XeCryptDesParity, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000175, XeCryptDesKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000176, XeCryptDesEcb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000177, XeCryptDesCbc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000178, XeCryptDes3Key, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000179, XeCryptDes3Ecb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017A, XeCryptDes3Cbc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017B, XeCryptHmacMd5Init, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017C, XeCryptHmacMd5Update, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017D, XeCryptHmacMd5Final, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017E, XeCryptHmacMd5, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000017F, XeCryptHmacShaInit, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000180, XeCryptHmacShaUpdate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000181, XeCryptHmacShaFinal, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000182, XeCryptHmacSha, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000183, XeCryptHmacShaVerify, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000184, XeCryptMd5Init, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000185, XeCryptMd5Update, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000186, XeCryptMd5Final, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000187, XeCryptMd5, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000188, XeCryptParveEcb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000189, XeCryptParveCbcMac, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018A, XeCryptRandom, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018B, XeCryptRc4Key, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018C, XeCryptRc4Ecb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018D, XeCryptRc4, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018E, XeCryptRotSumSha, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000018F, XeCryptShaInit, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000190, XeCryptShaUpdate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000191, XeCryptShaFinal, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000192, XeCryptSha, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000193, XexExecutableModuleHandle, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000194, XexCheckExecutablePrivilege, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000195, XexGetModuleHandle, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000196, XexGetModuleSection, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000197, XexGetProcedureAddress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000198, XexLoadExecutable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000199, XexLoadImage, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019A, XexLoadImageFromMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019B, XexLoadImageHeaders, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019C, XexPcToFileHeader, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019D, KiApcNormalRoutineNop_, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019E, XexRegisterPatchDescriptor, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000019F, XexSendDeferredNotifications, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A0, XexStartExecutable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A1, XexUnloadImage, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A2, XexUnloadImageAndExitThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A3, XexUnloadTitleModules, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A4, XexVerifyImageHeaders, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A5, __C_specific_handler, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A6, DbgLoadImageSymbols, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A7, DbgUnLoadImageSymbols, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A8, RtlImageDirectoryEntryToData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001A9, RtlImageNtHeader, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AA, ExDebugMonitorService, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AB, MmDbgReadCheck, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AC, MmDbgReleaseAddress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AD, MmDbgWriteCheck, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AE, ExLoadedCommandLine, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001AF, ExLoadedImageName, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B0, VdBlockUntilGUIIdle, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B1, VdCallGraphicsNotificationRoutines, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B2, VdDisplayFatalError, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B3, VdEnableClosedCaption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B4, VdEnableDisableClockGating, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B5, VdEnableDisablePowerSavingMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B6, VdEnableRingBufferRPtrWriteBack, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B7, VdGenerateGPUCSCCoefficients, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B8, VdGetClosedCaptionReadyStatus, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001B9, VdGetCurrentDisplayGamma, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BA, VdGetCurrentDisplayInformation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BB, VdGetDisplayModeOverride, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BC, VdGetGraphicsAsicID, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BD, VdGetSystemCommandBuffer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BE, VdGlobalDevice, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001BF, VdGlobalXamDevice, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C0, VdGpuClockInMHz, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C1, VdHSIOCalibrationLock, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C2, VdInitializeEngines, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C3, VdInitializeRingBuffer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C4, VdInitializeScaler, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C5, VdInitializeScalerCommandBuffer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C6, VdIsHSIOTrainingSucceeded, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C7, VdPersistDisplay, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C8, VdQuerySystemCommandBuffer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001C9, VdQueryVideoFlags, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CA, VdQueryVideoMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CB, VdReadDVERegisterUlong, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CC, VdReadWriteHSIOCalibrationFlag, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CD, VdRegisterGraphicsNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CE, VdRegisterXamGraphicsNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001CF, VdSendClosedCaptionData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D0, VdSetCGMSOption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D1, VdSetColorProfileAdjustment, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D2, VdSetCscMatricesOverride, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D3, VdSetDisplayMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D4, VdSetDisplayModeOverride, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D5, VdSetGraphicsInterruptCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D6, VdSetHDCPOption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D7, VdSetMacrovisionOption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D8, VdSetSystemCommandBuffer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001D9, VdSetSystemCommandBufferGpuIdentifierAddress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DA, VdSetWSSData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DB, VdSetWSSOption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DC, VdShutdownEngines, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DD, VdTurnDisplayOff, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DE, VdTurnDisplayOn, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001DF, KiApcNormalRoutineNop, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E0, VdWriteDVERegisterUlong, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E1, XVoicedHeadsetPresent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E2, XVoicedSubmitPacket, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E3, XVoicedClose, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E4, XVoicedActivate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E5, XInputdGetCapabilities, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E6, XInputdReadState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E7, XInputdWriteState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E8, XInputdNotify, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001E9, XInputdRawState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EA, HidGetCapabilities, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EB, HidReadKeys, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EC, XInputdGetDeviceStats, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001ED, XInputdResetDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EE, XInputdSetRingOfLight, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001EF, XInputdSetRFPowerMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F0, XInputdSetRadioFrequency, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F1, HidGetLastInputTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F2, XAudioRenderDriverInitialize, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F3, XAudioRegisterRenderDriverClient, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F4, XAudioUnregisterRenderDriverClient, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F5, XAudioSubmitRenderDriverFrame, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F6, XAudioRenderDriverLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F7, XAudioGetVoiceCategoryVolumeChangeMask, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F8, XAudioGetVoiceCategoryVolume, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001F9, XAudioSetVoiceCategoryVolume, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FA, XAudioBeginDigitalBypassMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FB, XAudioEndDigitalBypassMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FC, XAudioSubmitDigitalPacket, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FD, XAudioQueryDriverPerformance, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FE, XAudioGetRenderDriverThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000001FF, XAudioGetSpeakerConfig, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000200, XAudioSetSpeakerConfig, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000201, NicSetUnicastAddress, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000202, NicAttach, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000203, NicDetach, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000204, NicXmit, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000205, NicUpdateMcastMembership, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000206, NicFlushXmitQueue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000207, NicShutdown, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000208, NicGetLinkState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000209, NicGetStats, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020A, NicGetOpt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020B, NicSetOpt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020C, DrvSetSysReqCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020D, DrvSetUserBindingCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020E, DrvSetContentStorageCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000020F, DrvSetAutobind, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000210, DrvGetContentStorageNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000211, MtpdBeginTransaction, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000212, MtpdCancelTransaction, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000213, MtpdEndTransaction, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000214, MtpdGetCurrentDevices, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000215, MtpdReadData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000216, MtpdReadEvent, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000217, MtpdResetDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000218, MtpdSendData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000219, MtpdVerifyProximity, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021A, XUsbcamSetCaptureMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021B, XUsbcamGetConfig, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021C, XUsbcamSetConfig, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021D, XUsbcamGetState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021E, XUsbcamReadFrame, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000021F, XUsbcamSnapshot, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000220, XUsbcamSetView, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000221, XUsbcamGetView, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000222, XUsbcamCreate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000223, XUsbcamDestroy, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000224, XMACreateContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000225, XMAInitializeContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000226, XMAReleaseContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000227, XMAEnableContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000228, XMADisableContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000229, XMAGetOutputBufferWriteOffset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022A, XMASetOutputBufferReadOffset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022B, XMAGetOutputBufferReadOffset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022C, XMASetOutputBufferValid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022D, XMAIsOutputBufferValid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022E, XMASetInputBuffer0Valid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000022F, XMAIsInputBuffer0Valid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000230, XMASetInputBuffer1Valid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000231, XMAIsInputBuffer1Valid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000232, XMASetInputBuffer0, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000233, XMASetInputBuffer1, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000234, XMAGetPacketMetadata, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000235, XMABlockWhileInUse, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000236, XMASetLoopData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000237, XMASetInputBufferReadOffset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000238, XMAGetInputBufferReadOffset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000239, ExIsBetaFeatureEnabled, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023A, XeKeysGetFactoryChallenge, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023B, XeKeysSetFactoryResponse, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023C, XeKeysInitializeFuses, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023D, XeKeysSaveBootLoader, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023E, XeKeysSaveKeyVault, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000023F, XeKeysGetStatus, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000240, XeKeysGeneratePrivateKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000241, XeKeysGetKeyProperties, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000242, XeKeysSetKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000243, XeKeysGenerateRandomKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000244, XeKeysGetKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000245, XeKeysGetDigest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000246, XeKeysGetConsoleID, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000247, XeKeysGetConsoleType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000248, XeKeysQwNeRsaPrvCrypt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000249, XeKeysHmacSha, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024A, XInputdPassThroughRFCommand, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024B, XeKeysAesCbc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024C, XeKeysDes2Cbc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024D, XeKeysDesCbc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024E, XeKeysObscureKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000024F, XeKeysHmacShaUsingKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000250, XeKeysSaveBootLoaderEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000251, XeKeysAesCbcUsingKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000252, XeKeysDes2CbcUsingKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000253, XeKeysDesCbcUsingKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000254, XeKeysObfuscate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000255, XeKeysUnObfuscate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000256, XeKeysConsolePrivateKeySign, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000257, XeKeysConsoleSignatureVerification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000258, XeKeysVerifyRSASignature, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000259, StfsCreateDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025A, StfsControlDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025B, VdSwap, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025C, HalFsbInterruptCount, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025D, XeKeysSaveSystemUpdate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025E, XeKeysLockSystemUpdate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000025F, XeKeysExecute, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000260, XeKeysGetVersions, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000261, XInputdPowerDownDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000262, AniBlockOnAnimation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000263, AniTerminateAnimation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000264, XUsbcamReset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000265, AniSetLogo, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000266, KeCertMonitorData, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000267, HalIsExecutingPowerDownDpc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000268, VdInitializeEDRAM, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000269, VdRetrainEDRAM, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026A, VdRetrainEDRAMWorker, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026B, VdHSIOTrainCount, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026C, HalGetPowerUpCause, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026D, VdHSIOTrainingStatus, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026E, RgcBindInfo, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000026F, VdReadEEDIDBlock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000270, VdEnumerateVideoModes, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000271, VdEnableHDCP, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000272, VdRegisterHDCPNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000273, HidReadMouseChanges, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000274, DumpSetCollectionFacility, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000275, XexTransformImageKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000276, XAudioOverrideSpeakerConfig, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000277, XInputdReadTextKeystroke, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000278, DrvXenonButtonPressed, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000279, DrvBindToUser, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027A, XexGetModuleImportVersions, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027B, RtlComputeCrc32, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027C, XeKeysSetRevocationList, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027D, HalRegisterPowerDownCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027E, VdGetDisplayDiscoveryData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000027F, XInputdSendStayAliveRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000280, XVoicedSendVPort, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000281, XVoicedGetBatteryStatus, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000282, XInputdFFGetDeviceInfo, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000283, XInputdFFSetEffect, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000284, XInputdFFUpdateEffect, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000285, XInputdFFEffectOperation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000286, XInputdFFDeviceControl, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000287, XInputdFFSetDeviceGain, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000288, XInputdFFCancelIo, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000289, XInputdFFSetRumble, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028A, NtAllocateEncryptedMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028B, NtFreeEncryptedMemory, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028C, XeKeysExSaveKeyVault, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028D, XeKeysExSetKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028E, XeKeysExGetKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000028F, DrvSetDeviceConfigChangeCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000290, DrvDeviceConfigChange, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000291, HalRegisterHdDvdRomNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000292, XeKeysSecurityInitialize, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000293, XeKeysSecurityLoadSettings, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000294, XeKeysSecuritySaveSettings, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000295, XeKeysSecuritySetDetected, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000296, XeKeysSecurityGetDetected, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000297, XeKeysSecuritySetActivated, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000298, XeKeysSecurityGetActivated, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000299, XeKeysDvdAuthAP25InstallTable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029A, XeKeysDvdAuthAP25GetTableVersion, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029B, XeKeysGetProtectedFlag, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029C, XeKeysSetProtectedFlag, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029D, KeEnablePFMInterrupt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029E, KeDisablePFMInterrupt, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000029F, KeSetProfilerISR, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A0, VdStartDisplayDiscovery, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A1, VdSetHDCPRevocationList, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A2, XeKeysGetUpdateSequence, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A3, XeKeysDvdAuthExActivate, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A4, KeGetImagePageTableEntry, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A5, HalRegisterBackgroundModeTransitionCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A6, AniStartBootAnimation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A7, HalClampUnclampOutputDACs, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A8, HalPowerDownToBackgroundMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002A9, HalNotifyAddRemoveBackgroundTask, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AA, HalCallBackgroundModeNotificationRoutines, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AB, HalFsbResetCount, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AC, HalGetMemoryInformation, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AD, XInputdGetLastTextInputTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AE, VdEnableWMAProOverHDMI, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002AF, XeKeysRevokeSaveSettings, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B0, XInputdSetTextMessengerIndicator, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B1, MicDeviceRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B2, XeKeysGetMediaID, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B3, XeKeysLoadKeyVault, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B4, KeGetVidInfo, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B5, HalNotifyBackgroundModeTransitionComplete, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B6, IoAcquireCancelSpinLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B7, IoReleaseCancelSpinLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B8, NtCancelIoFile, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002B9, NtCancelIoFileEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BA, HalFinalizePowerLossRecovery, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BB, HalSetPowerLossRecovery, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BC, ExReadModifyWriteXConfigSettingUlong, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BD, HalRegisterXamPowerDownCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BE, ExCancelAlarm, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002BF, ExInitializeAlarm, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C0, ExSetAlarm, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C1, XexActivationGetNonce, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C2, XexActivationSetLicense, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C3, IptvSetBoundaryKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C4, IptvSetSessionKey, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C5, IptvVerifyOmac1Signature, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C6, IptvGetAesCtrTransform, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C7, SataCdRomRecordReset, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C8, XInputdSetTextDeviceKeyLocks, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002C9, XInputdGetTextDeviceKeyLocks, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CA, XexActivationVerifyOwnership, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CB, XexDisableVerboseDbgPrint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CC, SvodCreateDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CD, RtlCaptureStackBackTrace, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CE, XeKeysRevokeUpdateDynamic, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002CF, XexImportTraceEnable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D0, ExRegisterXConfigNotification, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D1, XeKeysSecuritySetStat, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D2, VdQueryRealVideoMode, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D3, XexSetExecutablePrivilege, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D4, XAudioSuspendRenderDriverClients, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D5, IptvGetSessionKeyHash, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D6, VdSetCGMSState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D7, VdSetSCMSState, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D8, KeFlushMultipleTb, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002D9, VdGetOption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DA, VdSetOption, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DB, UsbdBootEnumerationDoneEvent, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DC, StfsDeviceErrorEvent, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DD, ExTryToAcquireReadWriteLockExclusive, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DE, ExTryToAcquireReadWriteLockShared, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002DF, XexSetLastKdcTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E0, XInputdControl, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E1, RmcDeviceRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E2, LDIResetDecompression, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E3, NicRegisterDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E4, UsbdAddDeviceComplete, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E5, UsbdCancelAsyncTransfer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E6, UsbdGetDeviceSpeed, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E7, UsbdGetDeviceTopology, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E8, UsbdGetEndpointDescriptor, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002E9, UsbdIsDeviceAuthenticated, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EA, UsbdOpenDefaultEndpoint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EB, UsbdOpenEndpoint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EC, UsbdQueueAsyncTransfer, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002ED, UsbdQueueCloseDefaultEndpoint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EE, UsbdQueueCloseEndpoint, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002EF, UsbdRemoveDeviceComplete, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F0, KeRemoveQueueApc, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F1, UsbdDriverLoadRequiredEvent, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F2, UsbdGetRequiredDrivers, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F3, UsbdRegisterDriverObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F4, UsbdUnregisterDriverObject, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F5, UsbdCallAndBlockOnDpcRoutine, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F6, UsbdResetDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F7, UsbdGetDeviceDescriptor, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F8, NomnilGetExtension, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002F9, NomnilStartCloseDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FA, WifiBeginAuthentication, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FB, WifiCheckCounterMeasures, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FC, WifiChooseAuthenCipherSetFromBSSID, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FD, WifiCompleteAuthentication, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FE, WifiGetAssociationIE, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x000002FF, WifiOnMICError, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000300, WifiPrepareAuthenticationContext, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000301, WifiRecvEAPOLPacket, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000302, WifiDeduceNetworkType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000303, NicUnregisterDevice, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000304, DumpXitThread, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000305, XInputdSetWifiChannel, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000306, NomnilSetLed, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000307, WifiCalculateRegulatoryDomain, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000308, WifiSelectAdHocChannel, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000309, WifiChannelToFrequency, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030A, MmGetPoolPagesType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030B, ExExpansionInstall, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030C, ExExpansionCall, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030D, PsCamDeviceRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030E, McaDeviceRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000030F, DetroitDeviceRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000310, XeCryptSha256Init, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000311, XeCryptSha256Update, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000312, XeCryptSha256Final, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000313, XeCryptSha256, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000314, XeCryptSha384Init, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000315, XeCryptSha384Update, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000316, XInputdGetDevicePid, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000317, HalGetNotedArgonErrors, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000318, XeCryptSha384Final, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000319, HalReadArgonEeprom, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031A, HalWriteArgonEeprom, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031B, XeKeysFcrtLoad, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031C, XeKeysFcrtSave, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031D, XeKeysFcrtSet, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031E, XeCryptSha384, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000031F, XeCryptSha512Init, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000320, XAudioRegisterRenderDriverMECClient, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000321, XAudioUnregisterRenderDriverMECClient, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000322, XAudioCaptureRenderDriverFrame, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000323, XeCryptSha512Update, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000324, XeCryptSha512Final, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000325, XeCryptSha512, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000326, XeCryptBnQwNeCompare, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000327, XVoicedGetDirectionalData, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000328, DrvSetMicArrayStartCallback, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000329, DevAuthGetStatistics, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032A, NullCableRequest, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032B, XeKeysRevokeIsDeviceRevoked, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032C, DumpUpdateDumpSettings, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032D, EtxConsumerDisableEventType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032E, EtxConsumerEnableEventType, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000032F, EtxConsumerProcessLogs, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000330, EtxConsumerRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000331, EtxConsumerUnregister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000332, EtxProducerLog, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000333, EtxProducerLogV, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000334, EtxProducerRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000335, EtxProducerUnregister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000336, EtxConsumerFlushBuffers, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000337, EtxProducerLogXwpp, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000338, EtxProducerLogXwppV, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000339, UsbdEnableDisableRootHubPort, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033A, EtxBufferRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033B, EtxBufferUnregister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033C, DumpRegisterDedicatedDataBlock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033D, XeKeysDvdAuthExSave, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033E, XeKeysDvdAuthExInstall, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000033F, XexShimDisable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000340, XexShimEnable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000341, XexShimEntryDisable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000342, XexShimEntryEnable, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000343, XexShimEntryRegister, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000344, XexShimLock, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000345, XboxKrnlVersion4Digit, ? , Variable, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000346, XeKeysObfuscateEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000347, XeKeysUnObfuscateEx, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000348, XexTitleHash, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000349, XexTitleHashClose, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034A, XexTitleHashContinue, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034B, XexTitleHashOpen, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034C, XAudioGetRenderDriverTic, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034D, XAudioEnableDucker, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034E, XAudioSetDuckerLevel, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000034F, XAudioIsDuckerEnabled, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000350, XAudioGetDuckerLevel, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000351, XAudioGetDuckerThreshold, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000352, XAudioSetDuckerThreshold, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000353, XAudioGetDuckerAttackTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000354, XAudioSetDuckerAttackTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000355, XAudioGetDuckerReleaseTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000356, XAudioSetDuckerReleaseTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000357, XAudioGetDuckerHoldTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000358, XAudioSetDuckerHoldTime, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x00000359, DevAuthShouldAlwaysEnforce, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000035A, XAudioGetUnderrunCount, ? , Function, 0),
|
||||
XE_EXPORT(xboxkrnl, 0x0000035C, XVoicedIsActiveProcess, ? , Function, 0),
|
||||
703
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc
Normal file
703
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc
Normal file
@@ -0,0 +1,703 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_threading.h>
|
||||
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xevent.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
// r13 + 0x100: pointer to thread local state
|
||||
// Thread local state:
|
||||
// 0x058: kernel time
|
||||
// 0x14C: thread id
|
||||
// 0x150: if >0 then error states don't get set
|
||||
// 0x160: last error
|
||||
|
||||
// GetCurrentThreadId:
|
||||
// lwz r11, 0x100(r13)
|
||||
// lwz r3, 0x14C(r11)
|
||||
|
||||
// RtlGetLastError:
|
||||
// lwz r11, 0x150(r13)
|
||||
// if (r11 != 0) {
|
||||
// lwz r11, 0x100(r13)
|
||||
// stw r3, 0x160(r11)
|
||||
// }
|
||||
|
||||
// RtlSetLastError:
|
||||
// lwz r11, 0x150(r13)
|
||||
// if (r11 != 0) {
|
||||
// lwz r11, 0x100(r13)
|
||||
// stw r3, 0x160(r11)
|
||||
// }
|
||||
|
||||
// RtlSetLastNTError:
|
||||
// r3 = RtlNtStatusToDosError(r3)
|
||||
// lwz r11, 0x150(r13)
|
||||
// if (r11 != 0) {
|
||||
// lwz r11, 0x100(r13)
|
||||
// stw r3, 0x160(r11)
|
||||
// }
|
||||
|
||||
|
||||
X_STATUS xeExCreateThread(
|
||||
uint32_t* handle_ptr, uint32_t stack_size, uint32_t* thread_id_ptr,
|
||||
uint32_t xapi_thread_startup,
|
||||
uint32_t start_address, uint32_t start_context, uint32_t creation_flags) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// DWORD
|
||||
// LPHANDLE Handle,
|
||||
// DWORD StackSize,
|
||||
// LPDWORD ThreadId,
|
||||
// LPVOID XapiThreadStartup, ?? often 0
|
||||
// LPVOID StartAddress,
|
||||
// LPVOID StartContext,
|
||||
// DWORD CreationFlags // 0x80?
|
||||
|
||||
XThread* thread = new XThread(
|
||||
state, stack_size, xapi_thread_startup, start_address, start_context,
|
||||
creation_flags);
|
||||
|
||||
X_STATUS result_code = thread->Create();
|
||||
if (XFAILED(result_code)) {
|
||||
// Failed!
|
||||
thread->Release();
|
||||
XELOGE("Thread creation failed: %.8X", result_code);
|
||||
return result_code;
|
||||
}
|
||||
|
||||
if (handle_ptr) {
|
||||
*handle_ptr = thread->handle();
|
||||
}
|
||||
if (thread_id_ptr) {
|
||||
*thread_id_ptr = thread->thread_id();
|
||||
}
|
||||
return result_code;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL ExCreateThread_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t stack_size = SHIM_GET_ARG_32(1);
|
||||
uint32_t thread_id_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t xapi_thread_startup = SHIM_GET_ARG_32(3);
|
||||
uint32_t start_address = SHIM_GET_ARG_32(4);
|
||||
uint32_t start_context = SHIM_GET_ARG_32(5);
|
||||
uint32_t creation_flags = SHIM_GET_ARG_32(6);
|
||||
|
||||
XELOGD(
|
||||
"ExCreateThread(%.8X, %d, %.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
handle_ptr,
|
||||
stack_size,
|
||||
thread_id_ptr,
|
||||
xapi_thread_startup,
|
||||
start_address,
|
||||
start_context,
|
||||
creation_flags);
|
||||
|
||||
uint32_t handle;
|
||||
uint32_t thread_id;
|
||||
X_STATUS result = xeExCreateThread(
|
||||
&handle, stack_size, &thread_id, xapi_thread_startup,
|
||||
start_address, start_context, creation_flags);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
if (handle_ptr) {
|
||||
SHIM_SET_MEM_32(handle_ptr, handle);
|
||||
}
|
||||
if (thread_id_ptr) {
|
||||
SHIM_SET_MEM_32(thread_id_ptr, thread_id);
|
||||
}
|
||||
}
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeKeSetAffinityThread(void* thread_ptr, uint32_t affinity) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
XThread* thread = (XThread*)XObject::GetObject(state, thread_ptr);
|
||||
if (thread) {
|
||||
// TODO(benvanik): implement.
|
||||
}
|
||||
|
||||
return affinity;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeSetAffinityThread_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t thread = SHIM_GET_ARG_32(0);
|
||||
uint32_t affinity = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"KeSetAffinityThread(%.8X, %.8X)",
|
||||
thread,
|
||||
affinity);
|
||||
|
||||
void* thread_ptr = SHIM_MEM_ADDR(thread);
|
||||
uint32_t result = xeKeSetAffinityThread(thread_ptr, affinity);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeKeGetCurrentProcessType() {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
// DWORD
|
||||
|
||||
return X_PROCTYPE_USER;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeGetCurrentProcessType_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"KeGetCurrentProcessType()");
|
||||
|
||||
int result = xeKeGetCurrentProcessType();
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
uint64_t xeKeQueryPerformanceFrequency() {
|
||||
LARGE_INTEGER frequency;
|
||||
if (QueryPerformanceFrequency(&frequency)) {
|
||||
return frequency.QuadPart;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeQueryPerformanceFrequency_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"KeQueryPerformanceFrequency()");
|
||||
|
||||
uint64_t result = xeKeQueryPerformanceFrequency();
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
X_STATUS xeKeDelayExecutionThread(
|
||||
uint32_t processor_mode, uint32_t alertable, uint64_t interval) {
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
return thread->Delay(processor_mode, alertable, interval);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeDelayExecutionThread_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t processor_mode = SHIM_GET_ARG_32(0);
|
||||
uint32_t alertable = SHIM_GET_ARG_32(1);
|
||||
uint32_t interval_ptr = SHIM_GET_ARG_32(2);
|
||||
uint64_t interval = SHIM_MEM_64(interval_ptr);
|
||||
|
||||
XELOGD(
|
||||
"KeDelayExecutionThread(%.8X, %d, %.8X(%.16llX)",
|
||||
processor_mode, alertable, interval_ptr, interval);
|
||||
|
||||
X_STATUS result = xeKeDelayExecutionThread(
|
||||
processor_mode, alertable, interval);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
void xeKeQuerySystemTime(uint64_t* time_ptr) {
|
||||
FILETIME t;
|
||||
GetSystemTimeAsFileTime(&t);
|
||||
*time_ptr = ((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeQuerySystemTime_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t time_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"KeQuerySystemTime(%.8X)",
|
||||
time_ptr);
|
||||
|
||||
uint64_t time;
|
||||
xeKeQuerySystemTime(&time);
|
||||
|
||||
if (time_ptr) {
|
||||
SHIM_SET_MEM_64(time_ptr, time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The TLS system used here is a bit hacky, but seems to work.
|
||||
// Both Win32 and pthreads use unsigned longs as TLS indices, so we can map
|
||||
// right into the system for these calls. We're just round tripping the IDs and
|
||||
// hoping for the best.
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms686801
|
||||
uint32_t xeKeTlsAlloc() {
|
||||
// DWORD
|
||||
|
||||
uint32_t tls_index;
|
||||
|
||||
#if XE_PLATFORM(WIN32)
|
||||
tls_index = TlsAlloc();
|
||||
#else
|
||||
pthread_key_t key;
|
||||
if (pthread_key_create(&key, NULL)) {
|
||||
tls_index = X_TLS_OUT_OF_INDEXES;
|
||||
} else {
|
||||
tls_index = (uint32_t)key;
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
return tls_index;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeTlsAlloc_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"KeTlsAlloc()");
|
||||
|
||||
uint32_t result = xeKeTlsAlloc();
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms686804
|
||||
int KeTlsFree(uint32_t tls_index) {
|
||||
// BOOL
|
||||
// _In_ DWORD dwTlsIndex
|
||||
|
||||
if (tls_index == X_TLS_OUT_OF_INDEXES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int result_code = 0;
|
||||
|
||||
#if XE_PLATFORM(WIN32)
|
||||
result_code = TlsFree(tls_index);
|
||||
#else
|
||||
result_code = pthread_key_delete(tls_index) == 0;
|
||||
#endif // WIN32
|
||||
|
||||
return result_code;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeTlsFree_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t tls_index = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"KeTlsFree(%.8X)",
|
||||
tls_index);
|
||||
|
||||
int result = xeKeTlsAlloc();
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms686812
|
||||
uint64_t xeKeTlsGetValue(uint32_t tls_index) {
|
||||
// LPVOID
|
||||
// _In_ DWORD dwTlsIndex
|
||||
|
||||
uint64_t value = 0;
|
||||
|
||||
#if XE_PLATFORM(WIN32)
|
||||
value = (uint64_t)TlsGetValue(tls_index);
|
||||
#else
|
||||
value = (uint64_t)pthread_getspecific(tls_index);
|
||||
#endif // WIN32
|
||||
|
||||
if (!value) {
|
||||
XELOGW("KeTlsGetValue should SetLastError if result is NULL");
|
||||
// TODO(benvanik): SetLastError
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeTlsGetValue_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t tls_index = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"KeTlsGetValue(%.8X)",
|
||||
tls_index);
|
||||
|
||||
uint64_t result = xeKeTlsGetValue(tls_index);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms686818
|
||||
int xeKeTlsSetValue(uint32_t tls_index, uint64_t tls_value) {
|
||||
// BOOL
|
||||
// _In_ DWORD dwTlsIndex,
|
||||
// _In_opt_ LPVOID lpTlsValue
|
||||
|
||||
int result_code = 0;
|
||||
|
||||
#if XE_PLATFORM(WIN32)
|
||||
result_code = TlsSetValue(tls_index, (LPVOID)tls_value);
|
||||
#else
|
||||
result_code = pthread_setspecific(tls_index, (void*)tls_value) == 0;
|
||||
#endif // WIN32
|
||||
|
||||
return result_code;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeTlsSetValue_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t tls_index = SHIM_GET_ARG_32(0);
|
||||
uint32_t tls_value = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"KeTlsSetValue(%.8X, %.8X)",
|
||||
tls_index, tls_value);
|
||||
|
||||
int result = xeKeTlsSetValue(tls_index, tls_value);
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
X_STATUS xeNtCreateEvent(uint32_t* handle_ptr, void* obj_attributes,
|
||||
uint32_t event_type, uint32_t initial_state) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
XEvent* ev = new XEvent(state);
|
||||
ev->Initialize(!event_type, !!initial_state);
|
||||
|
||||
// obj_attributes may have a name inside of it, if != NULL.
|
||||
if (obj_attributes) {
|
||||
//ev->SetName(...);
|
||||
}
|
||||
|
||||
*handle_ptr = ev->handle();
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL NtCreateEvent_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t event_type = SHIM_GET_ARG_32(2);
|
||||
uint32_t initial_state = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD(
|
||||
"NtCreateEvent(%.8X, %.8X, %d, %d)",
|
||||
handle_ptr, obj_attributes_ptr, event_type, initial_state);
|
||||
|
||||
uint32_t handle;
|
||||
X_STATUS result = xeNtCreateEvent(
|
||||
&handle, SHIM_MEM_ADDR(obj_attributes_ptr),
|
||||
event_type, initial_state);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
if (handle_ptr) {
|
||||
SHIM_SET_MEM_32(handle_ptr, handle);
|
||||
}
|
||||
}
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int32_t xeKeSetEvent(void* event_ptr, uint32_t increment, uint32_t wait) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
XEvent* ev = (XEvent*)XObject::GetObject(state, event_ptr);
|
||||
XEASSERTNOTNULL(ev);
|
||||
if (!ev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ev->Set(increment, !!wait);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeSetEvent_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t event_ref = SHIM_GET_ARG_32(0);
|
||||
uint32_t increment = SHIM_GET_ARG_32(1);
|
||||
uint32_t wait = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD(
|
||||
"KeSetEvent(%.8X, %.8X, %.8X)",
|
||||
event_ref, increment, wait);
|
||||
|
||||
void* event_ptr = SHIM_MEM_ADDR(event_ref);
|
||||
int32_t result = xeKeSetEvent(event_ptr, increment, wait);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL NtSetEvent_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t event_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t previous_state_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"NtSetEvent(%.8X, %.8X)",
|
||||
event_handle, previous_state_ptr);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
XEvent* ev = NULL;
|
||||
result = state->object_table()->GetObject(
|
||||
event_handle, (XObject**)&ev);
|
||||
if (XSUCCEEDED(result)) {
|
||||
int32_t was_signalled = ev->Set(0, false);
|
||||
if (previous_state_ptr) {
|
||||
SHIM_SET_MEM_32(previous_state_ptr, was_signalled);
|
||||
}
|
||||
|
||||
ev->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int32_t xeKeResetEvent(void* event_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
XEvent* ev = (XEvent*)XEvent::GetObject(state, event_ptr);
|
||||
XEASSERTNOTNULL(ev);
|
||||
if (!ev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ev->Reset();
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeResetEvent_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t event_ref = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"KeResetEvent(%.8X)",
|
||||
event_ref);
|
||||
|
||||
void* event_ptr = SHIM_MEM_ADDR(event_ref);
|
||||
int32_t result = xeKeResetEvent(event_ptr);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
X_STATUS xeKeWaitForSingleObject(
|
||||
void* object_ptr, uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
|
||||
XObject* object = XObject::GetObject(state, object_ptr);
|
||||
if (!object) {
|
||||
// The only kind-of failure code.
|
||||
return X_STATUS_ABANDONED_WAIT_0;
|
||||
}
|
||||
|
||||
return object->Wait(wait_reason, processor_mode, alertable, opt_timeout);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeWaitForSingleObject_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t object = SHIM_GET_ARG_32(0);
|
||||
uint32_t wait_reason = SHIM_GET_ARG_32(1);
|
||||
uint32_t processor_mode = SHIM_GET_ARG_32(2);
|
||||
uint32_t alertable = SHIM_GET_ARG_32(3);
|
||||
uint32_t timeout_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"KeWaitForSingleObject(%.8X, %.8X, %.8X, %.1X, %.8X)",
|
||||
object, wait_reason, processor_mode, alertable, timeout_ptr);
|
||||
|
||||
void* object_ptr = SHIM_MEM_ADDR(object);
|
||||
uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0;
|
||||
X_STATUS result = xeKeWaitForSingleObject(
|
||||
object_ptr, wait_reason, processor_mode, alertable,
|
||||
timeout_ptr ? &timeout : NULL);
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL NtWaitForSingleObjectEx_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t object_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t timeout = SHIM_GET_ARG_32(1);
|
||||
uint32_t alertable = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD(
|
||||
"NtWaitForSingleObjectEx(%.8X, %.8X, %.1X)",
|
||||
object_handle, timeout, alertable);
|
||||
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
XObject* object = NULL;
|
||||
result = state->object_table()->GetObject(
|
||||
object_handle, &object);
|
||||
if (XSUCCEEDED(result)) {
|
||||
uint64_t timeout_ns = timeout * 1000000 / 100;
|
||||
timeout_ns = ~timeout_ns; // Relative.
|
||||
result = object->Wait(
|
||||
3, 1, alertable,
|
||||
timeout == 0xFFFFFFFF ? 0 : &timeout_ns);
|
||||
object->Release();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeKfAcquireSpinLock(void* lock_ptr) {
|
||||
// Lock.
|
||||
while (!xe_atomic_cas_32(0, 1, lock_ptr)) {
|
||||
// Spin!
|
||||
// TODO(benvanik): error on deadlock?
|
||||
}
|
||||
|
||||
// Raise IRQL to DISPATCH.
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
return thread->RaiseIrql(2);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KfAcquireSpinLock_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t lock_ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"KfAcquireSpinLock(%.8X)",
|
||||
lock_ptr);
|
||||
|
||||
uint32_t old_irql = xeKfAcquireSpinLock(SHIM_MEM_ADDR(lock_ptr));
|
||||
|
||||
SHIM_SET_RETURN(old_irql);
|
||||
}
|
||||
|
||||
|
||||
void xeKfReleaseSpinLock(void* lock_ptr, uint32_t old_irql) {
|
||||
// Restore IRQL.
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
thread->LowerIrql(old_irql);
|
||||
|
||||
// Unlock.
|
||||
xe_atomic_dec_32(lock_ptr);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KfReleaseSpinLock_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t lock_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t old_irql = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"KfReleaseSpinLock(%.8X, %d)",
|
||||
lock_ptr,
|
||||
old_irql);
|
||||
|
||||
xeKfReleaseSpinLock(SHIM_MEM_ADDR(lock_ptr), old_irql);
|
||||
}
|
||||
|
||||
|
||||
void xeKeEnterCriticalRegion() {
|
||||
XThread::EnterCriticalRegion();
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeEnterCriticalRegion_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"KeEnterCriticalRegion()");
|
||||
xeKeEnterCriticalRegion();
|
||||
}
|
||||
|
||||
|
||||
void xeKeLeaveCriticalRegion() {
|
||||
XThread::LeaveCriticalRegion();
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL KeLeaveCriticalRegion_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"KeLeaveCriticalRegion()");
|
||||
xeKeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterThreadingExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExCreateThread, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetAffinityThread, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeGetCurrentProcessType, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeDelayExecutionThread, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeQuerySystemTime, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsAlloc, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsFree, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsGetValue, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsSetValue, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeResetEvent, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForSingleObject, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtWaitForSingleObjectEx, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KfAcquireSpinLock, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KfReleaseSpinLock, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);
|
||||
}
|
||||
65
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.h
Normal file
65
src/xenia/kernel/xboxkrnl/xboxkrnl_threading.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_THREADING_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_THREADING_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
X_STATUS xeExCreateThread(
|
||||
uint32_t* handle_ptr, uint32_t stack_size, uint32_t* thread_id_ptr,
|
||||
uint32_t xapi_thread_startup,
|
||||
uint32_t start_address, uint32_t start_context, uint32_t creation_flags);
|
||||
|
||||
uint32_t xeKeSetAffinityThread(void* thread_ptr, uint32_t affinity);
|
||||
|
||||
uint32_t xeKeGetCurrentProcessType();
|
||||
|
||||
uint64_t xeKeQueryPerformanceFrequency();
|
||||
void xeKeQuerySystemTime(uint64_t* time_ptr);
|
||||
|
||||
X_STATUS xeKeDelayExecutionThread(
|
||||
uint32_t processor_mode, uint32_t alertable, uint64_t interval);
|
||||
|
||||
uint32_t xeKeTlsAlloc();
|
||||
int KeTlsFree(uint32_t tls_index);
|
||||
uint64_t xeKeTlsGetValue(uint32_t tls_index);
|
||||
int xeKeTlsSetValue(uint32_t tls_index, uint64_t tls_value);
|
||||
|
||||
X_STATUS xeNtCreateEvent(uint32_t* handle_ptr, void* obj_attributes,
|
||||
uint32_t event_type, uint32_t initial_state);
|
||||
int32_t xeKeSetEvent(void* event_ptr, uint32_t increment, uint32_t wait);
|
||||
int32_t xeKeResetEvent(void* event_ptr);
|
||||
|
||||
X_STATUS xeKeWaitForSingleObject(
|
||||
void* object_ptr, uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout);
|
||||
|
||||
uint32_t xeKfAcquireSpinLock(void* lock_ptr);
|
||||
void xeKfReleaseSpinLock(void* lock_ptr, uint32_t old_irql);
|
||||
|
||||
void xeKeEnterCriticalRegion();
|
||||
void xeKeLeaveCriticalRegion();
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_THREADING_H_
|
||||
487
src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc
Normal file
487
src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc
Normal file
@@ -0,0 +1,487 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xboxkrnl_video.h>
|
||||
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/gpu/gpu.h>
|
||||
#include <xenia/kernel/shim_utils.h>
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_rtl.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
// http://www.tweakoz.com/orkid/
|
||||
// http://www.tweakoz.com/orkid/dox/d3/d52/xb360init_8cpp_source.html
|
||||
// https://github.com/Free60Project/xenosfb/
|
||||
// https://github.com/Free60Project/xenosfb/blob/master/src/xe.h
|
||||
// https://github.com/gligli/libxemit
|
||||
// http://web.archive.org/web/20090428095215/http://msdn.microsoft.com/en-us/library/bb313877.aspx
|
||||
// http://web.archive.org/web/20100423054747/http://msdn.microsoft.com/en-us/library/bb313961.aspx
|
||||
// http://web.archive.org/web/20100423054747/http://msdn.microsoft.com/en-us/library/bb313878.aspx
|
||||
// http://web.archive.org/web/20090510235238/http://msdn.microsoft.com/en-us/library/bb313942.aspx
|
||||
// http://svn.dd-wrt.com/browser/src/linux/universal/linux-3.8/drivers/gpu/drm/radeon/radeon_ring.c
|
||||
// http://www.microsoft.com/en-za/download/details.aspx?id=5313 -- "Stripped Down Direct3D: Xbox 360 Command Buffer and Resource Management"
|
||||
|
||||
|
||||
void xeVdGetCurrentDisplayGamma(uint32_t* arg0, float* arg1) {
|
||||
*arg0 = 2;
|
||||
*arg1 = 2.22222233f;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdGetCurrentDisplayGamma_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t arg0_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t arg1_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"VdGetCurrentDisplayGamma(%.8X, %.8X)",
|
||||
arg0_ptr, arg1_ptr);
|
||||
|
||||
uint32_t arg0 = 0;
|
||||
union {
|
||||
float float_value;
|
||||
uint32_t uint_value;
|
||||
} arg1;
|
||||
xeVdGetCurrentDisplayGamma(&arg0, &arg1.float_value);
|
||||
SHIM_SET_MEM_32(arg0_ptr, arg0);
|
||||
SHIM_SET_MEM_32(arg1_ptr, arg1.uint_value);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdGetCurrentDisplayInformation_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t ptr = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"VdGetCurrentDisplayInformation(%.8X)",
|
||||
ptr);
|
||||
|
||||
// Expecting a length 0x58 struct of stuff.
|
||||
SHIM_SET_MEM_32(ptr + 0x10, 1280);
|
||||
SHIM_SET_MEM_32(ptr + 0x14, 720);
|
||||
SHIM_SET_MEM_16(ptr + 0x48, 1280);
|
||||
SHIM_SET_MEM_16(ptr + 0x4A, 720);
|
||||
SHIM_SET_MEM_16(ptr + 0x56, 1280);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xeVdQueryVideoFlags() {
|
||||
// ?
|
||||
return 0x00000007;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdQueryVideoFlags_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"VdQueryVideoFlags()");
|
||||
|
||||
SHIM_SET_RETURN(xeVdQueryVideoFlags());
|
||||
}
|
||||
|
||||
|
||||
void xeVdQueryVideoMode(X_VIDEO_MODE *video_mode, bool swap) {
|
||||
if (video_mode == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: get info from actual display
|
||||
video_mode->display_width = 1280;
|
||||
video_mode->display_height = 720;
|
||||
video_mode->is_interlaced = 0;
|
||||
video_mode->is_widescreen = 1;
|
||||
video_mode->is_hi_def = 1;
|
||||
video_mode->refresh_rate = 60.0f;
|
||||
video_mode->video_standard = 1; // NTSC
|
||||
video_mode->unknown_0x8a = 0x8A;
|
||||
video_mode->unknown_0x01 = 0x01;
|
||||
|
||||
if (swap) {
|
||||
video_mode->display_width = XESWAP32BE(video_mode->display_width);
|
||||
video_mode->display_height = XESWAP32BE(video_mode->display_height);
|
||||
video_mode->is_interlaced = XESWAP32BE(video_mode->is_interlaced);
|
||||
video_mode->is_widescreen = XESWAP32BE(video_mode->is_widescreen);
|
||||
video_mode->is_hi_def = XESWAP32BE(video_mode->is_hi_def);
|
||||
video_mode->refresh_rate = XESWAPF32BE(video_mode->refresh_rate);
|
||||
video_mode->video_standard = XESWAP32BE(video_mode->video_standard);
|
||||
video_mode->unknown_0x8a = XESWAP32BE(video_mode->unknown_0x8a);
|
||||
video_mode->unknown_0x01 = XESWAP32BE(video_mode->unknown_0x01);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdQueryVideoMode_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t video_mode_ptr = SHIM_GET_ARG_32(0);
|
||||
X_VIDEO_MODE *video_mode = (X_VIDEO_MODE*)SHIM_MEM_ADDR(video_mode_ptr);
|
||||
|
||||
XELOGD(
|
||||
"VdQueryVideoMode(%.8X)",
|
||||
video_mode_ptr);
|
||||
|
||||
xeVdQueryVideoMode(video_mode, true);
|
||||
}
|
||||
|
||||
|
||||
void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
|
||||
uint32_t unk2_ptr, uint32_t unk3_ptr) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
GraphicsSystem* gs = state->emulator()->graphics_system();
|
||||
if (!gs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// r3 = 0x4F810000
|
||||
// r4 = function ptr (cleanup callback?)
|
||||
// r5 = 0
|
||||
// r6/r7 = some binary data in .data
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdInitializeEngines_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t unk0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t callback = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(2);
|
||||
uint32_t unk2_ptr = SHIM_GET_ARG_32(3);
|
||||
uint32_t unk3_ptr = SHIM_GET_ARG_32(4);
|
||||
|
||||
XELOGD(
|
||||
"VdInitializeEngines(%.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
unk0, callback, unk1, unk2_ptr, unk3_ptr);
|
||||
|
||||
xeVdInitializeEngines(unk0, callback, unk1, unk2_ptr, unk3_ptr);
|
||||
}
|
||||
|
||||
|
||||
void xeVdSetGraphicsInterruptCallback(uint32_t callback, uint32_t user_data) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
GraphicsSystem* gs = state->emulator()->graphics_system();
|
||||
if (!gs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// callback takes 2 params
|
||||
// r3 = bool 0/1 - 0 is normal interrupt, 1 is some acquire/lock mumble
|
||||
// r4 = user_data (r4 of VdSetGraphicsInterruptCallback)
|
||||
|
||||
gs->SetInterruptCallback(callback, user_data);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdSetGraphicsInterruptCallback_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t callback = SHIM_GET_ARG_32(0);
|
||||
uint32_t user_data = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"VdSetGraphicsInterruptCallback(%.8X, %.8X)",
|
||||
callback, user_data);
|
||||
|
||||
xeVdSetGraphicsInterruptCallback(callback, user_data);
|
||||
}
|
||||
|
||||
|
||||
void xeVdInitializeRingBuffer(uint32_t ptr, uint32_t page_count) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
GraphicsSystem* gs = state->emulator()->graphics_system();
|
||||
if (!gs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// r3 = result of MmGetPhysicalAddress
|
||||
// r4 = number of pages? page size?
|
||||
// 0x8000 -> cntlzw=16 -> 0x1C - 16 = 12
|
||||
// Buffer pointers are from MmAllocatePhysicalMemory with WRITE_COMBINE.
|
||||
// Sizes could be zero? XBLA games seem to do this. Default sizes?
|
||||
// D3D does size / region_count - must be > 1024
|
||||
|
||||
gs->InitializeRingBuffer(ptr, page_count);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdInitializeRingBuffer_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t page_count = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"VdInitializeRingBuffer(%.8X, %.8X)",
|
||||
ptr, page_count);
|
||||
|
||||
xeVdInitializeRingBuffer(ptr, page_count);
|
||||
}
|
||||
|
||||
|
||||
void xeVdEnableRingBufferRPtrWriteBack(uint32_t ptr, uint32_t block_size) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
GraphicsSystem* gs = state->emulator()->graphics_system();
|
||||
if (!gs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// r4 = 6, usually --- <=19
|
||||
gs->EnableReadPointerWriteBack(ptr, block_size);
|
||||
|
||||
ptr += 0x20000000;
|
||||
printf("%.8X", ptr);
|
||||
// 0x0110343c
|
||||
|
||||
// r3 = 0x2B10(d3d?) + 0x3C
|
||||
|
||||
//((p + 0x3C) & 0x1FFFFFFF) + ((((p + 0x3C) >> 20) + 0x200) & 0x1000)
|
||||
//also 0x3C offset into WriteBacks is PrimaryRingBufferReadIndex
|
||||
//(1:17:38 AM) Rick: .text:8201B348 lwz r11, 0x2B10(r31)
|
||||
//(1:17:38 AM) Rick: .text:8201B34C addi r11, r11, 0x3C
|
||||
//(1:17:38 AM) Rick: .text:8201B350 srwi r10, r11, 20 # r10 = r11 >> 20
|
||||
//(1:17:38 AM) Rick: .text:8201B354 clrlwi r11, r11, 3 # r11 = r11 & 0x1FFFFFFF
|
||||
//(1:17:38 AM) Rick: .text:8201B358 addi r10, r10, 0x200
|
||||
//(1:17:39 AM) Rick: .text:8201B35C rlwinm r10, r10, 0,19,19 # r10 = r10 & 0x1000
|
||||
//(1:17:39 AM) Rick: .text:8201B360 add r3, r10, r11
|
||||
//(1:17:39 AM) Rick: .text:8201B364 bl VdEnableRingBufferRPtrWriteBack
|
||||
// TODO(benvanik): something?
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdEnableRingBufferRPtrWriteBack_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t block_size = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"VdEnableRingBufferRPtrWriteBack(%.8X, %.8X)",
|
||||
ptr, block_size);
|
||||
|
||||
xeVdEnableRingBufferRPtrWriteBack(ptr, block_size);
|
||||
}
|
||||
|
||||
|
||||
void xeVdGetSystemCommandBuffer(uint32_t* p0, uint32_t* p1) {
|
||||
*p0 = 0xBEEF0000;
|
||||
*p1 = 0xBEEF0001;
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdGetSystemCommandBuffer_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t p0_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t p1_ptr = SHIM_GET_ARG_32(1);
|
||||
|
||||
XELOGD(
|
||||
"VdGetSystemCommandBuffer(%.8X, %.8X)",
|
||||
p0_ptr,
|
||||
p1_ptr);
|
||||
|
||||
uint32_t p0 = 0;
|
||||
uint32_t p1 = 0;
|
||||
xeVdGetSystemCommandBuffer(&p0, &p1);
|
||||
SHIM_SET_MEM_32(p0_ptr, p0);
|
||||
SHIM_SET_MEM_32(p1_ptr, p1);
|
||||
}
|
||||
|
||||
|
||||
void xeVdSetSystemCommandBufferGpuIdentifierAddress(uint32_t unk) {
|
||||
KernelState* state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(state);
|
||||
GraphicsSystem* gs = state->emulator()->graphics_system();
|
||||
if (!gs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// r3 = 0x2B10(d3d?) + 8
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdSetSystemCommandBufferGpuIdentifierAddress_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t unk = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"VdSetSystemCommandBufferGpuIdentifierAddress(%.8X)",
|
||||
unk);
|
||||
|
||||
xeVdSetSystemCommandBufferGpuIdentifierAddress(unk);
|
||||
}
|
||||
|
||||
|
||||
// VdVerifyMEInitCommand
|
||||
// r3
|
||||
// r4 = 19
|
||||
// no op?
|
||||
|
||||
|
||||
// VdCallGraphicsNotificationRoutines
|
||||
// r3 = 1
|
||||
// r4 = ?
|
||||
// callbacks get 0, r3, r4
|
||||
|
||||
|
||||
SHIM_CALL VdIsHSIOTrainingSucceeded_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"VdIsHSIOTrainingSucceeded()");
|
||||
|
||||
// Not really sure what this should be - code does weird stuff here:
|
||||
// (cntlzw r11, r3 / extrwi r11, r11, 1, 26)
|
||||
SHIM_SET_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdPersistDisplay_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
XELOGD(
|
||||
"VdPersistDisplay(?)");
|
||||
|
||||
// ?
|
||||
SHIM_SET_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdRetrainEDRAMWorker_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t unk0 = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD(
|
||||
"VdRetrainEDRAMWorker(%.8X)",
|
||||
unk0);
|
||||
|
||||
SHIM_SET_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdRetrainEDRAM_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t unk0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk2 = SHIM_GET_ARG_32(2);
|
||||
uint32_t unk3 = SHIM_GET_ARG_32(3);
|
||||
uint32_t unk4 = SHIM_GET_ARG_32(4);
|
||||
uint32_t unk5 = SHIM_GET_ARG_32(5);
|
||||
|
||||
XELOGD(
|
||||
"VdRetrainEDRAM(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
unk0, unk1, unk2, unk3, unk4, unk5);
|
||||
|
||||
SHIM_SET_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
SHIM_CALL VdSwap_shim(
|
||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||
uint32_t unk0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t unk1 = SHIM_GET_ARG_32(1);
|
||||
uint32_t unk2 = SHIM_GET_ARG_32(2);
|
||||
uint32_t unk3 = SHIM_GET_ARG_32(3);
|
||||
uint32_t unk4 = SHIM_GET_ARG_32(4);
|
||||
uint32_t unk5 = SHIM_GET_ARG_32(5);
|
||||
uint32_t unk6 = SHIM_GET_ARG_32(6);
|
||||
uint32_t unk7 = SHIM_GET_ARG_32(7);
|
||||
|
||||
XELOGD(
|
||||
"VdSwap(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
|
||||
unk0,
|
||||
unk1,
|
||||
unk2,
|
||||
unk3,
|
||||
unk4,
|
||||
unk5,
|
||||
unk6,
|
||||
unk7);
|
||||
|
||||
KernelState* kernel_state = shared_kernel_state_;
|
||||
XEASSERTNOTNULL(kernel_state);
|
||||
GraphicsSystem* gs = kernel_state->emulator()->graphics_system();
|
||||
if (!gs) {
|
||||
return;
|
||||
}
|
||||
|
||||
gs->set_swap_pending(true);
|
||||
|
||||
SHIM_SET_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
void xe::kernel::xboxkrnl::RegisterVideoExports(
|
||||
ExportResolver* export_resolver, KernelState* state) {
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdGetCurrentDisplayGamma, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdGetCurrentDisplayInformation, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdQueryVideoFlags, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdQueryVideoMode, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdInitializeEngines, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdSetGraphicsInterruptCallback, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdInitializeRingBuffer, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdEnableRingBufferRPtrWriteBack, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdGetSystemCommandBuffer, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe",
|
||||
VdSetSystemCommandBufferGpuIdentifierAddress, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdIsHSIOTrainingSucceeded, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdPersistDisplay, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdRetrainEDRAMWorker, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdRetrainEDRAM, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdSwap, state);
|
||||
|
||||
xe_memory_ref memory = state->memory();
|
||||
uint8_t* mem = xe_memory_addr(memory);
|
||||
|
||||
// VdGlobalDevice (4b)
|
||||
// Pointer to a global D3D device. Games only seem to set this, so we don't
|
||||
// have to do anything. We may want to read it back later, though.
|
||||
uint32_t pVdGlobalDevice = xe_memory_heap_alloc(memory, 0, 4, 0);
|
||||
export_resolver->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::VdGlobalDevice,
|
||||
pVdGlobalDevice);
|
||||
XESETUINT32BE(mem + pVdGlobalDevice, 0);
|
||||
|
||||
// VdGlobalXamDevice (4b)
|
||||
// Pointer to the XAM D3D device, which we don't have.
|
||||
uint32_t pVdGlobalXamDevice = xe_memory_heap_alloc(memory, 0, 4, 0);
|
||||
export_resolver->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::VdGlobalXamDevice,
|
||||
pVdGlobalXamDevice);
|
||||
XESETUINT32BE(mem + pVdGlobalXamDevice, 0);
|
||||
|
||||
// VdGpuClockInMHz (4b)
|
||||
// GPU clock. Xenos is 500MHz. Hope nothing is relying on this timing...
|
||||
uint32_t pVdGpuClockInMHz = xe_memory_heap_alloc(memory, 0, 4, 0);
|
||||
export_resolver->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::VdGpuClockInMHz,
|
||||
pVdGpuClockInMHz);
|
||||
XESETUINT32BE(mem + pVdGpuClockInMHz, 500);
|
||||
|
||||
// VdHSIOCalibrationLock (28b)
|
||||
// CriticalSection.
|
||||
uint32_t pVdHSIOCalibrationLock = xe_memory_heap_alloc(memory, 0, 28, 0);
|
||||
export_resolver->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::VdHSIOCalibrationLock,
|
||||
pVdHSIOCalibrationLock);
|
||||
xeRtlInitializeCriticalSectionAndSpinCount(pVdHSIOCalibrationLock, 10000);
|
||||
}
|
||||
57
src/xenia/kernel/xboxkrnl/xboxkrnl_video.h
Normal file
57
src/xenia/kernel/xboxkrnl/xboxkrnl_video.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_VIDEO_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_VIDEO_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
// http://ffplay360.googlecode.com/svn/trunk/Common/XTLOnPC.h
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint32_t display_width;
|
||||
uint32_t display_height;
|
||||
uint32_t is_interlaced;
|
||||
uint32_t is_widescreen;
|
||||
uint32_t is_hi_def;
|
||||
float refresh_rate;
|
||||
uint32_t video_standard;
|
||||
uint32_t unknown_0x8a;
|
||||
uint32_t unknown_0x01;
|
||||
uint32_t reserved[3];
|
||||
}
|
||||
X_VIDEO_MODE;
|
||||
#pragma pack(pop)
|
||||
XEASSERTSTRUCTSIZE(X_VIDEO_MODE, 48);
|
||||
|
||||
void xeVdGetCurrentDisplayGamma(uint32_t* arg0, float* arg1);
|
||||
uint32_t xeVdQueryVideoFlags();
|
||||
void xeVdQueryVideoMode(X_VIDEO_MODE *video_mode, bool swap);
|
||||
|
||||
void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
|
||||
uint32_t unk2_ptr, uint32_t unk3_ptr);
|
||||
void xeVdSetGraphicsInterruptCallback(uint32_t callback, uint32_t user_data);
|
||||
void xeVdEnableRingBufferRPtrWriteBack(uint32_t ptr, uint32_t block_size);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_VIDEO_H_
|
||||
178
src/xenia/kernel/xboxkrnl/xobject.cc
Normal file
178
src/xenia/kernel/xboxkrnl/xobject.cc
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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/xboxkrnl/xobject.h>
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||
#include <xenia/kernel/xboxkrnl/objects/xevent.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::xboxkrnl;
|
||||
|
||||
|
||||
XObject::XObject(KernelState* kernel_state, Type type) :
|
||||
kernel_state_(kernel_state),
|
||||
handle_ref_count_(0),
|
||||
pointer_ref_count_(1),
|
||||
type_(type), handle_(X_INVALID_HANDLE_VALUE) {
|
||||
kernel_state->object_table()->AddHandle(this, &handle_);
|
||||
}
|
||||
|
||||
XObject::~XObject() {
|
||||
XEASSERTZERO(handle_ref_count_);
|
||||
XEASSERTZERO(pointer_ref_count_);
|
||||
}
|
||||
|
||||
xe_memory_ref XObject::memory() {
|
||||
return kernel_state_->memory();
|
||||
}
|
||||
|
||||
XObject::Type XObject::type() {
|
||||
return type_;
|
||||
}
|
||||
|
||||
X_HANDLE XObject::handle() const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
void XObject::RetainHandle() {
|
||||
xe_atomic_inc_32(&handle_ref_count_);
|
||||
}
|
||||
|
||||
bool XObject::ReleaseHandle() {
|
||||
if (!xe_atomic_dec_32(&handle_ref_count_)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void XObject::Retain() {
|
||||
xe_atomic_inc_32(&pointer_ref_count_);
|
||||
}
|
||||
|
||||
void XObject::Release() {
|
||||
if (!xe_atomic_dec_32(&pointer_ref_count_)) {
|
||||
XEASSERT(pointer_ref_count_ >= handle_ref_count_);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
X_STATUS XObject::Delete() {
|
||||
return shared_kernel_state_->object_table()->RemoveHandle(handle_);
|
||||
}
|
||||
|
||||
X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout) {
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void XObject::LockType() {
|
||||
xe_mutex_lock(shared_kernel_state_->object_mutex_);
|
||||
}
|
||||
|
||||
void XObject::UnlockType() {
|
||||
xe_mutex_unlock(shared_kernel_state_->object_mutex_);
|
||||
}
|
||||
|
||||
void XObject::SetNativePointer(uint32_t native_ptr) {
|
||||
XObject::LockType();
|
||||
|
||||
DISPATCH_HEADER* header_be =
|
||||
(DISPATCH_HEADER*)xe_memory_addr(kernel_state_->memory(), native_ptr);
|
||||
DISPATCH_HEADER header;
|
||||
header.type_flags = XESWAP32(header_be->type_flags);
|
||||
header.signal_state = XESWAP32(header_be->signal_state);
|
||||
header.wait_list_flink = XESWAP32(header_be->wait_list_flink);
|
||||
header.wait_list_blink = XESWAP32(header_be->wait_list_blink);
|
||||
|
||||
XEASSERT(!(header.wait_list_blink & 0x1));
|
||||
|
||||
// Stash pointer in struct.
|
||||
uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
|
||||
object_ptr |= 0x1;
|
||||
header_be->wait_list_flink = XESWAP32((uint32_t)(object_ptr >> 32));
|
||||
header_be->wait_list_blink = XESWAP32((uint32_t)(object_ptr & 0xFFFFFFFF));
|
||||
|
||||
XObject::UnlockType();
|
||||
}
|
||||
|
||||
XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr) {
|
||||
// Unfortunately the XDK seems to inline some KeInitialize calls, meaning
|
||||
// we never see it and just randomly start getting passed events/timers/etc.
|
||||
// Luckily it seems like all other calls (Set/Reset/Wait/etc) are used and
|
||||
// we don't have to worry about PPC code poking the struct. Because of that,
|
||||
// we init on first use, store our pointer in the struct, and dereference it
|
||||
// each time.
|
||||
// We identify this by checking the low bit of wait_list_blink - if it's 1,
|
||||
// we have already put our pointer in there.
|
||||
|
||||
XObject::LockType();
|
||||
|
||||
DISPATCH_HEADER* header_be = (DISPATCH_HEADER*)native_ptr;
|
||||
DISPATCH_HEADER header;
|
||||
header.type_flags = XESWAP32(header_be->type_flags);
|
||||
header.signal_state = XESWAP32(header_be->signal_state);
|
||||
header.wait_list_flink = XESWAP32(header_be->wait_list_flink);
|
||||
header.wait_list_blink = XESWAP32(header_be->wait_list_blink);
|
||||
|
||||
if (header.wait_list_blink & 0x1) {
|
||||
// Already initialized.
|
||||
uint64_t object_ptr =
|
||||
((uint64_t)header.wait_list_flink << 32) |
|
||||
((header.wait_list_blink) & ~0x1);
|
||||
XObject* object = reinterpret_cast<XObject*>(object_ptr);
|
||||
// TODO(benvanik): assert nothing has been changed in the struct.
|
||||
XObject::UnlockType();
|
||||
return object;
|
||||
} else {
|
||||
// First use, create new.
|
||||
// http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
|
||||
XObject* object = NULL;
|
||||
switch (header.type_flags & 0xFF) {
|
||||
case 0: // EventNotificationObject
|
||||
case 1: // EventSynchronizationObject
|
||||
{
|
||||
XEvent* ev = new XEvent(kernel_state);
|
||||
ev->InitializeNative(native_ptr, header);
|
||||
object = ev;
|
||||
}
|
||||
break;
|
||||
case 2: // MutantObject
|
||||
case 3: // ProcessObject
|
||||
case 4: // QueueObject
|
||||
case 5: // SemaphoreObject
|
||||
case 6: // ThreadObject
|
||||
case 7: // GateObject
|
||||
case 8: // TimerNotificationObject
|
||||
case 9: // TimerSynchronizationObject
|
||||
case 18: // ApcObject
|
||||
case 19: // DpcObject
|
||||
case 20: // DeviceQueueObject
|
||||
case 21: // EventPairObject
|
||||
case 22: // InterruptObject
|
||||
case 23: // ProfileObject
|
||||
case 24: // ThreadedDpcObject
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
XObject::UnlockType();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Stash pointer in struct.
|
||||
uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
|
||||
object_ptr |= 0x1;
|
||||
header_be->wait_list_flink = XESWAP32((uint32_t)(object_ptr >> 32));
|
||||
header_be->wait_list_blink = XESWAP32((uint32_t)(object_ptr & 0xFFFFFFFF));
|
||||
|
||||
XObject::UnlockType();
|
||||
return object;
|
||||
}
|
||||
}
|
||||
86
src/xenia/kernel/xboxkrnl/xobject.h
Normal file
86
src/xenia/kernel/xboxkrnl/xobject.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||
|
||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
|
||||
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
|
||||
typedef struct {
|
||||
uint32_t type_flags;
|
||||
uint32_t signal_state;
|
||||
uint32_t wait_list_flink;
|
||||
uint32_t wait_list_blink;
|
||||
} DISPATCH_HEADER;
|
||||
|
||||
|
||||
class XObject {
|
||||
public:
|
||||
enum Type {
|
||||
kTypeModule = 0x00000001,
|
||||
kTypeThread = 0x00000002,
|
||||
kTypeEvent = 0x00000003,
|
||||
kTypeFile = 0x00000004,
|
||||
};
|
||||
|
||||
XObject(KernelState* kernel_state, Type type);
|
||||
virtual ~XObject();
|
||||
|
||||
Emulator* emulator() const { return kernel_state_->emulator_; }
|
||||
KernelState* kernel_state() const { return kernel_state_; }
|
||||
|
||||
Type type();
|
||||
X_HANDLE handle() const;
|
||||
|
||||
void RetainHandle();
|
||||
bool ReleaseHandle();
|
||||
void Retain();
|
||||
void Release();
|
||||
X_STATUS Delete();
|
||||
|
||||
// Reference()
|
||||
// Dereference()
|
||||
|
||||
virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout);
|
||||
|
||||
static void LockType();
|
||||
static void UnlockType();
|
||||
static XObject* GetObject(KernelState* kernel_state, void* native_ptr);
|
||||
|
||||
protected:
|
||||
xe_memory_ref memory(); // unretained
|
||||
void SetNativePointer(uint32_t native_ptr);
|
||||
|
||||
KernelState* kernel_state_;
|
||||
|
||||
private:
|
||||
volatile int32_t handle_ref_count_;
|
||||
volatile int32_t pointer_ref_count_;
|
||||
|
||||
Type type_;
|
||||
X_HANDLE handle_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||
Reference in New Issue
Block a user