clang-format on most of kernel/

This commit is contained in:
Ben Vanik 2014-08-17 13:13:03 -07:00
parent 854bcdb60a
commit 1c4dcd5e0e
76 changed files with 2075 additions and 3169 deletions

View File

@ -22,8 +22,8 @@
#include <xenia/kernel/fs/filesystem.h>
#include <xenia/ui/window.h>
namespace xe {
using namespace xe;
using namespace xe::apu;
using namespace xe::cpu;
using namespace xe::gpu;
@ -218,3 +218,5 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
return xboxkrnl_->LaunchModule(module_path.c_str());
}
} // namespace xe

View File

@ -11,24 +11,22 @@
#include <xenia/kernel/kernel_state.h>
namespace xe {
namespace kernel {
XApp::XApp(KernelState* kernel_state, uint32_t app_id)
: kernel_state_(kernel_state), app_id_(app_id),
: kernel_state_(kernel_state),
app_id_(app_id),
membase_(kernel_state->memory()->membase()) {}
void XAppManager::RegisterApp(std::unique_ptr<XApp> app) {
assert_zero(app_lookup_.count(app->app_id()));
app_lookup_.insert({ app->app_id(), app.get() });
app_lookup_.insert({app->app_id(), app.get()});
apps_.push_back(std::move(app));
}
X_RESULT XAppManager::DispatchMessageSync(uint32_t app_id, uint32_t message, uint32_t arg1, uint32_t arg2) {
X_RESULT XAppManager::DispatchMessageSync(uint32_t app_id, uint32_t message,
uint32_t arg1, uint32_t arg2) {
const auto& it = app_lookup_.find(app_id);
if (it == app_lookup_.end()) {
return X_ERROR_NOT_FOUND;
@ -36,8 +34,9 @@ X_RESULT XAppManager::DispatchMessageSync(uint32_t app_id, uint32_t message, uin
return it->second->DispatchMessageSync(message, arg1, arg2);
}
X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message, uint32_t buffer_ptr, size_t buffer_length) {
X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message,
uint32_t buffer_ptr,
size_t buffer_length) {
const auto& it = app_lookup_.find(app_id);
if (it == app_lookup_.end()) {
return X_ERROR_NOT_FOUND;
@ -45,6 +44,5 @@ X_RESULT XAppManager::DispatchMessageAsync(uint32_t app_id, uint32_t message, ui
return it->second->DispatchMessageAsync(message, buffer_ptr, buffer_length);
}
} // namespace kernel
} // namespace xe

View File

@ -15,25 +15,23 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class KernelState;
class XApp {
public:
public:
uint32_t app_id() const { return app_id_; }
virtual X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1, uint32_t arg2) = 0;
virtual X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr, size_t buffer_length) = 0;
virtual X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1,
uint32_t arg2) = 0;
virtual X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
size_t buffer_length) = 0;
protected:
protected:
XApp(KernelState* kernel_state, uint32_t app_id);
KernelState* kernel_state_;
@ -41,22 +39,21 @@ protected:
uint8_t* membase_;
};
class XAppManager {
public:
public:
void RegisterApp(std::unique_ptr<XApp> app);
X_RESULT DispatchMessageSync(uint32_t app_id, uint32_t message, uint32_t arg1, uint32_t arg2);
X_RESULT DispatchMessageAsync(uint32_t app_id, uint32_t message, uint32_t buffer_ptr, size_t buffer_length);
X_RESULT DispatchMessageSync(uint32_t app_id, uint32_t message, uint32_t arg1,
uint32_t arg2);
X_RESULT DispatchMessageAsync(uint32_t app_id, uint32_t message,
uint32_t buffer_ptr, size_t buffer_length);
private:
private:
std::vector<std::unique_ptr<XApp>> apps_;
std::unordered_map<uint32_t, XApp*> app_lookup_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_APP_H_

View File

@ -11,17 +11,14 @@
#include <xenia/kernel/apps/xmp_app.h>
namespace xe {
namespace kernel {
namespace apps {
void RegisterApps(KernelState* kernel_state, XAppManager* manager) {
manager->RegisterApp(std::make_unique<XXMPApp>(kernel_state));
}
} // namespace apps
} // namespace kernel
} // namespace xe

View File

@ -16,18 +16,14 @@
#include <xenia/kernel/app.h>
#include <xenia/kernel/kernel_state.h>
namespace xe {
namespace kernel {
namespace apps {
void RegisterApps(KernelState* kernel_state, XAppManager* manager);
} // namespace apps
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_APPS_APPS_H_

View File

@ -9,12 +9,10 @@
#include <xenia/kernel/apps/xmp_app.h>
namespace xe {
namespace kernel {
namespace apps {
X_RESULT XXMPApp::XMPGetStatus(uint32_t unk, uint32_t status_ptr) {
// Some stupid games will hammer this on a thread - induce a delay
// here to keep from starving real threads.
@ -28,7 +26,8 @@ X_RESULT XXMPApp::XMPGetStatus(uint32_t unk, uint32_t status_ptr) {
return X_ERROR_SUCCESS;
}
X_RESULT XXMPApp::XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr, uint32_t disabled_ptr) {
X_RESULT XXMPApp::XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr,
uint32_t disabled_ptr) {
// Some stupid games will hammer this on a thread - induce a delay
// here to keep from starving real threads.
Sleep(1);
@ -42,7 +41,8 @@ X_RESULT XXMPApp::XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr, uint32_t disabl
return X_ERROR_SUCCESS;
}
X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t arg1, uint32_t arg2) {
X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t arg1,
uint32_t arg2) {
// http://freestyledash.googlecode.com/svn-history/r1/trunk/Freestyle/Scenes/Media/Music/ScnMusic.cpp
switch (message) {
case 0x00070009: {
@ -75,33 +75,33 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t arg1, uint32_t
return X_ERROR_NOT_FOUND;
}
X_RESULT XXMPApp::DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr, size_t buffer_length) {
X_RESULT XXMPApp::DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
size_t buffer_length) {
switch (message) {
case 0x00070009: {
uint32_t unk =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); // 0x00000002
uint32_t status_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
assert_true(buffer_length == 8);
return XMPGetStatus(unk, status_ptr);
}
case 0x0007001B: {
uint32_t unk =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); // 0x00000002
uint32_t unk_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
uint32_t disabled_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 8); // out ptr to 4b - expect 1 (to skip)
assert_true(buffer_length == 0xC);
return XMPGetStatusEx(unk, unk_ptr, disabled_ptr);
}
case 0x00070009: {
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr +
0); // 0x00000002
uint32_t status_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
assert_true(buffer_length == 8);
return XMPGetStatus(unk, status_ptr);
}
case 0x0007001B: {
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr +
0); // 0x00000002
uint32_t unk_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0
uint32_t disabled_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 8); // out ptr to 4b - expect 1 (to skip)
assert_true(buffer_length == 0xC);
return XMPGetStatusEx(unk, unk_ptr, disabled_ptr);
}
}
XELOGE("Unimplemented XMsg message app=%.8X, msg=%.8X, buffer=%.8X, len=%d",
app_id(), message, buffer_ptr, buffer_length);
return X_ERROR_NOT_FOUND;
}
} // namespace apps
} // namespace kernel
} // namespace xe

View File

@ -16,27 +16,26 @@
#include <xenia/kernel/app.h>
#include <xenia/kernel/kernel_state.h>
namespace xe {
namespace kernel {
namespace apps {
class XXMPApp : public XApp {
public:
public:
XXMPApp(KernelState* kernel_state) : XApp(kernel_state, 0xFA) {}
X_RESULT XMPGetStatus(uint32_t unk, uint32_t status_ptr);
X_RESULT XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr, uint32_t disabled_ptr);
X_RESULT XMPGetStatusEx(uint32_t unk, uint32_t unk_ptr,
uint32_t disabled_ptr);
X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1, uint32_t arg2) override;
X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr, size_t buffer_length) override;
X_RESULT DispatchMessageSync(uint32_t message, uint32_t arg1,
uint32_t arg2) override;
X_RESULT DispatchMessageAsync(uint32_t message, uint32_t buffer_ptr,
size_t buffer_length) override;
};
} // namespace apps
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_APPS_XMP_APP_H_

View File

@ -12,17 +12,18 @@
#include <xenia/kernel/xobject.h>
#include <xenia/kernel/objects/xevent.h>
namespace xe {
namespace kernel {
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) {
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();
}

View File

@ -14,10 +14,8 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
@ -25,14 +23,12 @@ class KernelState;
class XEvent;
class XObject;
class XAsyncRequest {
public:
public:
typedef void (*CompletionCallback)(XAsyncRequest* request, void* context);
XAsyncRequest(
KernelState* kernel_state, XObject* object,
CompletionCallback callback, void* callback_context);
XAsyncRequest(KernelState* kernel_state, XObject* object,
CompletionCallback callback, void* callback_context);
virtual ~XAsyncRequest();
KernelState* kernel_state() const { return kernel_state_; }
@ -42,20 +38,18 @@ public:
// Complete(result)
protected:
KernelState* kernel_state_;
XObject* object_;
CompletionCallback callback_;
void* callback_context_;
protected:
KernelState* kernel_state_;
XObject* object_;
CompletionCallback callback_;
void* callback_context_;
std::vector<XEvent*> wait_events_;
uint32_t apc_routine_;
uint32_t apc_context_;
std::vector<XEvent*> wait_events_;
uint32_t apc_routine_;
uint32_t apc_context_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_ASYNC_REQUEST_H_

View File

@ -12,27 +12,19 @@
#include <xenia/kernel/kernel_state.h>
#include <xenia/kernel/native_list.h>
namespace xe {
namespace kernel {
Dispatcher::Dispatcher(KernelState* kernel_state) :
kernel_state_(kernel_state) {
Dispatcher::Dispatcher(KernelState* kernel_state)
: kernel_state_(kernel_state) {
dpc_list_ = new NativeList(kernel_state->memory());
}
Dispatcher::~Dispatcher() {
delete dpc_list_;
}
Dispatcher::~Dispatcher() { delete dpc_list_; }
void Dispatcher::Lock() {
lock_.lock();
}
void Dispatcher::Lock() { lock_.lock(); }
void Dispatcher::Unlock() {
lock_.unlock();
}
void Dispatcher::Unlock() { lock_.unlock(); }
} // namespace kernel
} // namespace xe

View File

@ -17,16 +17,14 @@
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class KernelState;
class NativeList;
class Dispatcher {
public:
public:
Dispatcher(KernelState* kernel_state);
virtual ~Dispatcher();
@ -37,18 +35,15 @@ public:
NativeList* dpc_list() const { return dpc_list_; }
private:
private:
private:
KernelState* kernel_state_;
private:
KernelState* kernel_state_;
std::mutex lock_;
NativeList* dpc_list_;
std::mutex lock_;
NativeList* dpc_list_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_DISPATCHER_H_

View File

@ -22,26 +22,24 @@
#include <xenia/kernel/objects/xthread.h>
#include <xenia/kernel/objects/xuser_module.h>
namespace xe {
namespace kernel {
// 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.
KernelState* shared_kernel_state_ = nullptr;
KernelState::KernelState(Emulator* emulator)
: emulator_(emulator),
memory_(emulator->memory()),
executable_module_(NULL) {
processor_ = emulator->processor();
file_system_ = emulator->file_system();
KernelState::KernelState(Emulator* emulator) :
emulator_(emulator), memory_(emulator->memory()),
executable_module_(NULL) {
processor_ = emulator->processor();
file_system_ = emulator->file_system();
dispatcher_ = new Dispatcher(this);
dispatcher_ = new Dispatcher(this);
app_manager_ = std::make_unique<XAppManager>();
app_manager_ = std::make_unique<XAppManager>();
user_profile_ = std::make_unique<UserProfile>();
object_table_ = new ObjectTable();
@ -67,9 +65,7 @@ KernelState::~KernelState() {
shared_kernel_state_ = NULL;
}
KernelState* KernelState::shared() {
return shared_kernel_state_;
}
KernelState* KernelState::shared() { return shared_kernel_state_; }
void KernelState::RegisterModule(XModule* module) {}
@ -170,7 +166,8 @@ void KernelState::BroadcastNotification(XNotificationID id, uint32_t data) {
}
}
void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, uint32_t length) {
void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result,
uint32_t length) {
auto ptr = memory()->membase() + overlapped_ptr;
XOverlappedSetResult(ptr, result);
XOverlappedSetLength(ptr, length);
@ -179,7 +176,7 @@ void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, u
if (event_handle) {
XEvent* ev = nullptr;
if (XSUCCEEDED(object_table()->GetObject(
event_handle, reinterpret_cast<XObject**>(&ev)))) {
event_handle, reinterpret_cast<XObject**>(&ev)))) {
ev->Set(0, false);
ev->Release();
}
@ -189,17 +186,19 @@ void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, u
X_HANDLE thread_handle = XOverlappedGetContext(ptr);
XThread* thread = nullptr;
if (XSUCCEEDED(object_table()->GetObject(
thread_handle, reinterpret_cast<XObject**>(&thread)))) {
// TODO(benvanik): queue APC on the thread that requested the overlapped operation.
thread_handle, reinterpret_cast<XObject**>(&thread)))) {
// TODO(benvanik): queue APC on the thread that requested the overlapped
// operation.
thread->Release();
}
}
}
void KernelState::CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result, uint32_t length) {
void KernelState::CompleteOverlappedImmediate(uint32_t overlapped_ptr,
X_RESULT result,
uint32_t length) {
auto ptr = memory()->membase() + overlapped_ptr;
XOverlappedSetContext(ptr,
XThread::GetCurrentThreadHandle());
XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle());
CompleteOverlapped(overlapped_ptr, result, length);
}

View File

@ -9,15 +9,11 @@
#include <xenia/kernel/native_list.h>
namespace xe {
namespace kernel {
NativeList::NativeList(Memory* memory) :
memory_(memory),
head_(kInvalidPointer) {
}
NativeList::NativeList(Memory* memory)
: memory_(memory), head_(kInvalidPointer) {}
void NativeList::Insert(uint32_t ptr) {
uint8_t* mem = memory_->membase();
@ -67,9 +63,7 @@ uint32_t NativeList::Shift() {
return ptr;
}
bool NativeList::HasPending() {
return head_ != kInvalidPointer;
}
bool NativeList::HasPending() { return head_ != kInvalidPointer; }
} // namespace kernel
} // namespace xe

View File

@ -15,11 +15,9 @@
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
// List is designed for storing pointers to objects in the guest heap.
// All values in the list should be assumed to be in big endian.
@ -31,7 +29,7 @@ namespace kernel {
// }
class NativeList {
public:
public:
NativeList(Memory* memory);
void Insert(uint32_t list_entry_ptr);
@ -40,17 +38,15 @@ public:
uint32_t Shift();
bool HasPending();
private:
private:
const uint32_t kInvalidPointer = 0xE0FE0FFF;
private:
private:
Memory* memory_;
uint32_t head_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_NATIVE_LIST_H_

View File

@ -14,16 +14,11 @@
#include <xenia/kernel/xobject.h>
#include <xenia/kernel/objects/xthread.h>
namespace xe {
namespace kernel {
ObjectTable::ObjectTable() :
table_capacity_(0),
table_(NULL),
last_free_entry_(0) {
}
ObjectTable::ObjectTable()
: table_capacity_(0), table_(NULL), last_free_entry_(0) {}
ObjectTable::~ObjectTable() {
std::lock_guard<std::mutex> lock(table_mutex_);
@ -85,7 +80,7 @@ X_STATUS ObjectTable::AddHandle(XObject* object, X_HANDLE* out_handle) {
assert_not_null(out_handle);
X_STATUS result = X_STATUS_SUCCESS;
uint32_t slot = 0;
{
std::lock_guard<std::mutex> lock(table_mutex_);
@ -182,7 +177,6 @@ X_STATUS ObjectTable::GetObject(X_HANDLE handle, XObject** out_object) {
if (object) {
object->Retain();
}
}
*out_object = object;
@ -192,7 +186,7 @@ X_STATUS ObjectTable::GetObject(X_HANDLE handle, XObject** out_object) {
X_HANDLE ObjectTable::TranslateHandle(X_HANDLE handle) {
if (handle == 0xFFFFFFFF) {
// CurrentProcess
//assert_always();
// assert_always();
return 0;
} else if (handle == 0xFFFFFFFE) {
// CurrentThread

View File

@ -17,16 +17,13 @@
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XObject;
class ObjectTable {
public:
public:
ObjectTable();
~ObjectTable();
@ -34,23 +31,19 @@ public:
X_STATUS RemoveHandle(X_HANDLE handle);
X_STATUS GetObject(X_HANDLE handle, XObject** out_object);
private:
private:
X_HANDLE TranslateHandle(X_HANDLE handle);
X_STATUS FindFreeSlot(uint32_t* out_slot);
typedef struct {
XObject* object;
} ObjectTableEntry;
typedef struct { XObject* object; } ObjectTableEntry;
std::mutex table_mutex_;
uint32_t table_capacity_;
std::mutex table_mutex_;
uint32_t table_capacity_;
ObjectTableEntry* table_;
uint32_t last_free_entry_;
uint32_t last_free_entry_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_OBJECT_TABLE_H_

View File

@ -9,17 +9,15 @@
#include <xenia/kernel/objects/xenumerator.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XEnumerator::XEnumerator(KernelState* kernel_state)
: XObject(kernel_state, kTypeEnumerator) {}
XEnumerator::~XEnumerator() {}
XEnumerator::XEnumerator(KernelState* kernel_state) :
XObject(kernel_state, kTypeEnumerator) {
}
void XEnumerator::Initialize() {}
XEnumerator::~XEnumerator() {
}
void XEnumerator::Initialize() {
}
} // namespace kernel
} // namespace xe

View File

@ -11,27 +11,22 @@
#define XENIA_KERNEL_XBOXKRNL_XENUMERATOR_H_
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XEnumerator : public XObject {
public:
public:
XEnumerator(KernelState* kernel_state);
virtual ~XEnumerator();
void Initialize();
private:
private:
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XENUMERATOR_H_

View File

@ -9,15 +9,11 @@
#include <xenia/kernel/objects/xevent.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XEvent::XEvent(KernelState* kernel_state) :
XObject(kernel_state, kTypeEvent),
handle_(NULL) {
}
XEvent::XEvent(KernelState* kernel_state)
: XObject(kernel_state, kTypeEvent), handle_(NULL) {}
XEvent::~XEvent() {
if (handle_) {
@ -36,15 +32,15 @@ void XEvent::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) {
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:
assert_always();
return;
case 0x00: // EventNotificationObject (manual reset)
manual_reset = true;
break;
case 0x01: // EventSynchronizationObject (auto reset)
manual_reset = false;
break;
default:
assert_always();
return;
}
bool initial_state = header.signal_state ? true : false;
@ -60,10 +56,9 @@ int32_t XEvent::Pulse(uint32_t priority_increment, bool wait) {
return PulseEvent(handle_) ? 1 : 0;
}
int32_t XEvent::Reset() {
return ResetEvent(handle_) ? 1 : 0;
}
int32_t XEvent::Reset() { return ResetEvent(handle_) ? 1 : 0; }
void XEvent::Clear() {
ResetEvent(handle_);
}
void XEvent::Clear() { ResetEvent(handle_); }
} // namespace kernel
} // namespace xe

View File

@ -11,16 +11,13 @@
#define XENIA_KERNEL_XBOXKRNL_XEVENT_H_
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XEvent : public XObject {
public:
public:
XEvent(KernelState* kernel_state);
virtual ~XEvent();
@ -34,13 +31,11 @@ public:
virtual void* GetWaitHandle() { return handle_; }
private:
private:
HANDLE handle_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XEVENT_H_

View File

@ -12,14 +12,11 @@
#include <xenia/kernel/async_request.h>
#include <xenia/kernel/objects/xevent.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XFile::XFile(KernelState* kernel_state, fs::Mode mode) :
mode_(mode), position_(0),
XObject(kernel_state, kTypeFile) {
XFile::XFile(KernelState* kernel_state, fs::Mode mode)
: mode_(mode), position_(0), XObject(kernel_state, kTypeFile) {
async_event_ = new XEvent(kernel_state);
async_event_->Initialize(false, false);
}
@ -30,9 +27,7 @@ XFile::~XFile() {
async_event_->Delete();
}
void* XFile::GetWaitHandle() {
return async_event_->GetWaitHandle();
}
void* XFile::GetWaitHandle() { return async_event_->GetWaitHandle(); }
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read) {
@ -40,7 +35,8 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
// Read from current position.
byte_offset = position_;
}
X_STATUS result = ReadSync(buffer, buffer_length, byte_offset, out_bytes_read);
X_STATUS result =
ReadSync(buffer, buffer_length, byte_offset, out_bytes_read);
if (XSUCCEEDED(result)) {
position_ += *out_bytes_read;
}
@ -52,7 +48,10 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
// 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);
// return entry_->ReadAsync(buffer, buffer_length, byte_offset, request);
X_STATUS result = X_STATUS_NOT_IMPLEMENTED;
return result;
}
} // namespace kernel
} // namespace xe

View File

@ -14,7 +14,6 @@
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
@ -22,14 +21,14 @@ class XAsyncRequest;
class XEvent;
class XFileInfo {
public:
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;
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) {
@ -40,24 +39,24 @@ public:
poly::store_and_swap<uint64_t>(base + p + 32, allocation_size);
poly::store_and_swap<uint64_t>(base + p + 40, file_length);
poly::store_and_swap<uint32_t>(base + p + 48, attributes);
poly::store_and_swap<uint32_t>(base + p + 52, 0); // pad
poly::store_and_swap<uint32_t>(base + p + 52, 0); // pad
}
};
class XDirectoryInfo {
public:
public:
// FILE_DIRECTORY_INFORMATION
uint32_t next_entry_offset;
uint32_t file_index;
uint64_t creation_time;
uint64_t last_access_time;
uint64_t last_write_time;
uint64_t change_time;
uint64_t end_of_file;
uint64_t allocation_size;
uint32_t next_entry_offset;
uint32_t file_index;
uint64_t creation_time;
uint64_t last_access_time;
uint64_t last_write_time;
uint64_t change_time;
uint64_t end_of_file;
uint64_t allocation_size;
X_FILE_ATTRIBUTES attributes;
uint32_t file_name_length;
char file_name[1];
uint32_t file_name_length;
char file_name[1];
void Write(uint8_t* base, uint32_t p) {
uint8_t* dst = base + p;
@ -75,7 +74,8 @@ public:
poly::store_and_swap<uint64_t>(dst + 48, info->allocation_size);
poly::store_and_swap<uint32_t>(dst + 56, info->attributes);
poly::store_and_swap<uint32_t>(dst + 60, info->file_name_length);
xe_copy_memory(dst + 64, info->file_name_length, info->file_name, info->file_name_length);
xe_copy_memory(dst + 64, info->file_name_length, info->file_name,
info->file_name_length);
dst += info->next_entry_offset;
src += info->next_entry_offset;
} while (info->next_entry_offset != 0);
@ -85,13 +85,13 @@ static_assert_size(XDirectoryInfo, 72);
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540287(v=vs.85).aspx
class XVolumeInfo {
public:
public:
// FILE_FS_VOLUME_INFORMATION
uint64_t creation_time;
uint32_t serial_number;
uint32_t label_length;
uint32_t supports_objects;
char label[1];
uint64_t creation_time;
uint32_t serial_number;
uint32_t label_length;
uint32_t supports_objects;
char label[1];
void Write(uint8_t* base, uint32_t p) {
uint8_t* dst = base + p;
@ -99,32 +99,35 @@ public:
poly::store_and_swap<uint32_t>(dst + 8, this->serial_number);
poly::store_and_swap<uint32_t>(dst + 12, this->label_length);
poly::store_and_swap<uint32_t>(dst + 16, this->supports_objects);
xe_copy_memory(dst + 20, this->label_length, this->label, this->label_length);
xe_copy_memory(dst + 20, this->label_length, this->label,
this->label_length);
}
};
static_assert_size(XVolumeInfo, 24);
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx
class XFileSystemAttributeInfo {
public:
public:
// FILE_FS_ATTRIBUTE_INFORMATION
uint32_t attributes;
int32_t maximum_component_name_length;
uint32_t fs_name_length;
char fs_name[1];
uint32_t attributes;
int32_t maximum_component_name_length;
uint32_t fs_name_length;
char fs_name[1];
void Write(uint8_t* base, uint32_t p) {
uint8_t* dst = base + p;
poly::store_and_swap<uint32_t>(dst + 0, this->attributes);
poly::store_and_swap<uint32_t>(dst + 4, this->maximum_component_name_length);
poly::store_and_swap<uint32_t>(dst + 4,
this->maximum_component_name_length);
poly::store_and_swap<uint32_t>(dst + 8, this->fs_name_length);
xe_copy_memory(dst + 12, this->fs_name_length, this->fs_name, this->fs_name_length);
xe_copy_memory(dst + 12, this->fs_name_length, this->fs_name,
this->fs_name_length);
}
};
static_assert_size(XFileSystemAttributeInfo, 16);
class XFile : public XObject {
public:
public:
virtual ~XFile();
virtual const std::string& path() const = 0;
@ -148,24 +151,21 @@ public:
virtual void* GetWaitHandle();
protected:
protected:
XFile(KernelState* kernel_state, fs::Mode mode);
virtual X_STATUS ReadSync(
void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read) = 0;
virtual X_STATUS ReadSync(void* buffer, size_t buffer_length,
size_t byte_offset, size_t* out_bytes_read) = 0;
private:
fs::Mode mode_;
XEvent* async_event_;
private:
fs::Mode mode_;
XEvent* async_event_;
// TODO(benvanik): create flags, open state, etc.
size_t position_;
size_t position_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XFILE_H_

View File

@ -13,14 +13,11 @@
#include <xenia/cpu/cpu.h>
#include <xenia/kernel/objects/xthread.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::cpu;
using namespace xe::kernel;
XKernelModule::XKernelModule(KernelState* kernel_state, const char* path) :
XModule(kernel_state, path) {
XKernelModule::XKernelModule(KernelState* kernel_state, const char* path)
: XModule(kernel_state, path) {
emulator_ = kernel_state->emulator();
memory_ = emulator_->memory();
export_resolver_ = kernel_state->emulator()->export_resolver();
@ -28,11 +25,13 @@ XKernelModule::XKernelModule(KernelState* kernel_state, const char* path) :
OnLoad();
}
XKernelModule::~XKernelModule() {
}
XKernelModule::~XKernelModule() {}
void* XKernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
// TODO(benvanik): check export tables.
XELOGE("GetProcAddressByOrdinal not implemented");
return NULL;
}
} // namespace kernel
} // namespace xe

View File

@ -14,29 +14,26 @@
XEDECLARECLASS1(xe, Emulator);
XEDECLARECLASS1(xe, ExportResolver);
XEDECLARECLASS2(xe, kernel, KernelState);
namespace xe {
namespace kernel {
class KernelState;
class XKernelModule : public XModule {
public:
public:
XKernelModule(KernelState* kernel_state, const char* path);
virtual ~XKernelModule();
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
protected:
Emulator* emulator_;
Memory* memory_;
ExportResolver* export_resolver_;
protected:
Emulator* emulator_;
Memory* memory_;
ExportResolver* export_resolver_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XKERNEL_MODULE_H_

View File

@ -11,14 +11,11 @@
#include <xdb/protocol.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::cpu;
using namespace xe::kernel;
XModule::XModule(KernelState* kernel_state, const std::string& path) :
XObject(kernel_state, kTypeModule), path_(path) {
XModule::XModule(KernelState* kernel_state, const std::string& path)
: XObject(kernel_state, kTypeModule), path_(path) {
auto last_slash = path.find_last_of('/');
if (last_slash == path.npos) {
last_slash = path.find_last_of('\\');
@ -54,8 +51,10 @@ void XModule::OnLoad() {
kernel_state_->RegisterModule(this);
}
X_STATUS XModule::GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size) {
X_STATUS XModule::GetSection(const char* name, uint32_t* out_section_data,
uint32_t* out_section_size) {
return X_STATUS_UNSUCCESSFUL;
}
} // namespace kernel
} // namespace xe

View File

@ -13,16 +13,13 @@
#include <string>
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XModule : public XObject {
public:
public:
XModule(KernelState* kernel_state, const std::string& path);
virtual ~XModule();
@ -30,20 +27,17 @@ public:
const std::string& name() const { return name_; }
virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0;
virtual X_STATUS GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size);
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
uint32_t* out_section_size);
protected:
protected:
void OnLoad();
std::string name_;
std::string path_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XMODULE_H_

View File

@ -9,15 +9,11 @@
#include <xenia/kernel/objects/xmutant.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XMutant::XMutant(KernelState* kernel_state) :
XObject(kernel_state, kTypeMutant),
handle_(NULL) {
}
XMutant::XMutant(KernelState* kernel_state)
: XObject(kernel_state, kTypeMutant), handle_(NULL) {}
XMutant::~XMutant() {
if (handle_) {
@ -38,8 +34,8 @@ void XMutant::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) {
assert_always();
}
X_STATUS XMutant::ReleaseMutant(
uint32_t priority_increment, bool abandon, bool wait) {
X_STATUS XMutant::ReleaseMutant(uint32_t priority_increment, bool abandon,
bool wait) {
// TODO(benvanik): abandoning.
assert_false(abandon);
BOOL result = ReleaseMutex(handle_);
@ -49,3 +45,6 @@ X_STATUS XMutant::ReleaseMutant(
return X_STATUS_MUTANT_NOT_OWNED;
}
}
} // namespace kernel
} // namespace xe

View File

@ -11,16 +11,13 @@
#define XENIA_KERNEL_XBOXKRNL_XMUTANT_H_
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XMutant : public XObject {
public:
public:
XMutant(KernelState* kernel_state);
virtual ~XMutant();
@ -31,13 +28,11 @@ public:
virtual void* GetWaitHandle() { return handle_; }
private:
private:
HANDLE handle_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XMUTANT_H_

View File

@ -9,15 +9,14 @@
#include <xenia/kernel/objects/xnotify_listener.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XNotifyListener::XNotifyListener(KernelState* kernel_state) :
XObject(kernel_state, kTypeNotifyListener),
wait_handle_(NULL), mask_(0), notification_count_(0) {
}
XNotifyListener::XNotifyListener(KernelState* kernel_state)
: XObject(kernel_state, kTypeNotifyListener),
wait_handle_(NULL),
mask_(0),
notification_count_(0) {}
XNotifyListener::~XNotifyListener() {
kernel_state_->UnregisterNotifyListener(this);
@ -48,13 +47,13 @@ void XNotifyListener::EnqueueNotification(XNotificationID id, uint32_t data) {
} else {
// New.
notification_count_++;
notifications_.insert({ id, data });
notifications_.insert({id, data});
}
SetEvent(wait_handle_);
}
bool XNotifyListener::DequeueNotification(
XNotificationID* out_id, uint32_t* out_data) {
bool XNotifyListener::DequeueNotification(XNotificationID* out_id,
uint32_t* out_data) {
std::lock_guard<std::mutex> lock(lock_);
bool dequeued = false;
if (notification_count_) {
@ -71,8 +70,8 @@ bool XNotifyListener::DequeueNotification(
return dequeued;
}
bool XNotifyListener::DequeueNotification(
XNotificationID id, uint32_t* out_data) {
bool XNotifyListener::DequeueNotification(XNotificationID id,
uint32_t* out_data) {
std::lock_guard<std::mutex> lock(lock_);
bool dequeued = false;
if (notification_count_) {
@ -89,3 +88,6 @@ bool XNotifyListener::DequeueNotification(
}
return dequeued;
}
} // namespace kernel
} // namespace xe

View File

@ -7,25 +7,19 @@
******************************************************************************
*/
// This should probably be in XAM, but I don't want to build an extensible
// object system. Meh.
#ifndef XENIA_KERNEL_XBOXKRNL_XNOTIFY_LISTENER_H_
#define XENIA_KERNEL_XBOXKRNL_XNOTIFY_LISTENER_H_
#include <mutex>
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XNotifyListener : public XObject {
public:
public:
XNotifyListener(KernelState* kernel_state);
virtual ~XNotifyListener();
@ -37,7 +31,7 @@ public:
virtual void* GetWaitHandle() { return wait_handle_; }
private:
private:
HANDLE wait_handle_;
std::mutex lock_;
std::unordered_map<XNotificationID, uint32_t> notifications_;
@ -45,9 +39,7 @@ private:
uint64_t mask_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XNOTIFY_LISTENER_H_

View File

@ -9,15 +9,11 @@
#include <xenia/kernel/objects/xsemaphore.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XSemaphore::XSemaphore(KernelState* kernel_state) :
XObject(kernel_state, kTypeSemaphore),
handle_(NULL) {
}
XSemaphore::XSemaphore(KernelState* kernel_state)
: XObject(kernel_state, kTypeSemaphore), handle_(NULL) {}
XSemaphore::~XSemaphore() {
if (handle_) {
@ -43,3 +39,6 @@ int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {
::ReleaseSemaphore(handle_, release_count, &previous_count);
return previous_count;
}
} // namespace kernel
} // namespace xe

View File

@ -11,16 +11,13 @@
#define XENIA_KERNEL_XBOXKRNL_XSEMAPHORE_H_
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XSemaphore : public XObject {
public:
public:
XSemaphore(KernelState* kernel_state);
virtual ~XSemaphore();
@ -31,13 +28,11 @@ public:
virtual void* GetWaitHandle() { return handle_; }
private:
private:
HANDLE handle_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XSEMAPHORE_H_

View File

@ -16,41 +16,34 @@
#include <xenia/kernel/objects/xevent.h>
#include <xenia/kernel/objects/xuser_module.h>
namespace xe {
namespace kernel {
using namespace alloy;
using namespace xe;
using namespace xe::cpu;
using namespace xe::kernel;
uint32_t next_xthread_id = 0;
thread_local XThread* current_thread_tls;
std::mutex critical_region_;
XThread* shared_kernel_thread_ = 0;
namespace {
static uint32_t next_xthread_id = 0;
static thread_local XThread* current_thread_tls;
static std::mutex critical_region_;
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;
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;
// top 8 bits = processor ID (or 0 for default)
// bit 0 = 1 to create suspended
creation_params_.creation_flags = creation_flags;
creation_params_.creation_flags = creation_flags;
// Adjust stack size - min of 16k.
if (creation_params_.stack_size < 16 * 1024) {
@ -108,8 +101,7 @@ XThread* XThread::GetCurrentThread() {
XThread::EnterCriticalRegion();
thread = shared_kernel_thread_;
if (!thread) {
thread = new XThread(
KernelState::shared(), 32 * 1024, 0, 0, 0, 0);
thread = new XThread(KernelState::shared(), 32 * 1024, 0, 0, 0, 0);
shared_kernel_thread_ = thread;
current_thread_tls = thread;
}
@ -127,21 +119,17 @@ uint32_t XThread::GetCurrentThreadId(const uint8_t* thread_state_block) {
return poly::load_and_swap<uint32_t>(thread_state_block + 0x14C);
}
uint32_t XThread::thread_state() {
return thread_state_address_;
}
uint32_t XThread::thread_state() { return thread_state_address_; }
uint32_t XThread::thread_id() {
return thread_id_;
}
uint32_t XThread::thread_id() { return thread_id_; }
uint32_t XThread::last_error() {
uint8_t *p = memory()->Translate(thread_state_address_);
uint8_t* p = memory()->Translate(thread_state_address_);
return poly::load_and_swap<uint32_t>(p + 0x160);
}
void XThread::set_last_error(uint32_t error_code) {
uint8_t *p = memory()->Translate(thread_state_address_);
uint8_t* p = memory()->Translate(thread_state_address_);
poly::store_and_swap<uint32_t>(p + 0x160, error_code);
}
@ -163,8 +151,8 @@ X_STATUS XThread::Create() {
// 0x160: last error
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
// structure.
thread_state_address_ = (uint32_t)memory()->HeapAlloc(
0, 2048, MEMORY_FLAG_ZERO);
thread_state_address_ =
(uint32_t)memory()->HeapAlloc(0, 2048, alloy::MEMORY_FLAG_ZERO);
if (!thread_state_address_) {
XELOGW("Unable to allocate thread state block");
return X_STATUS_NO_MEMORY;
@ -178,14 +166,14 @@ X_STATUS XThread::Create() {
// Allocate thread scratch.
// This is used by interrupts/APCs/etc so we can round-trip pointers through.
scratch_size_ = 4 * 16;
scratch_address_ = (uint32_t)memory()->HeapAlloc(
0, scratch_size_, MEMORY_FLAG_ZERO);
scratch_address_ =
(uint32_t)memory()->HeapAlloc(0, scratch_size_, alloy::MEMORY_FLAG_ZERO);
// 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_ = (uint32_t)memory()->HeapAlloc(
0, tls_size, MEMORY_FLAG_ZERO);
tls_address_ =
(uint32_t)memory()->HeapAlloc(0, tls_size, alloy::MEMORY_FLAG_ZERO);
if (!tls_address_) {
XELOGW("Unable to allocate thread local storage block");
module->Release();
@ -194,22 +182,21 @@ X_STATUS XThread::Create() {
// Copy in default TLS info.
// TODO(benvanik): is this correct?
memory()->Copy(
tls_address_, header->tls_info.raw_data_address, tls_size);
memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size);
// Setup the thread state block (last error/etc).
uint8_t *p = memory()->Translate(thread_state_address_);
uint8_t* p = memory()->Translate(thread_state_address_);
poly::store_and_swap<uint32_t>(p + 0x000, tls_address_);
poly::store_and_swap<uint32_t>(p + 0x100, thread_state_address_);
poly::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
poly::store_and_swap<uint32_t>(p + 0x150, 0); // ?
poly::store_and_swap<uint32_t>(p + 0x160, 0); // last error
poly::store_and_swap<uint32_t>(p + 0x150, 0); // ?
poly::store_and_swap<uint32_t>(p + 0x160, 0); // last error
// Allocate processor thread state.
// This is thread safe.
thread_state_ = new XenonThreadState(
kernel_state()->processor()->runtime(),
thread_id_, creation_params_.stack_size, thread_state_address_);
thread_state_ =
new XenonThreadState(kernel_state()->processor()->runtime(), thread_id_,
creation_params_.stack_size, thread_state_address_);
X_STATUS return_code = PlatformCreate();
if (XFAILED(return_code)) {
@ -268,13 +255,10 @@ static uint32_t __stdcall XThreadStartCallbackWin32(void* param) {
X_STATUS XThread::PlatformCreate() {
bool suspended = creation_params_.creation_flags & 0x1;
thread_handle_ = CreateThread(
NULL,
creation_params_.stack_size,
(LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32,
this,
suspended ? CREATE_SUSPENDED : 0,
NULL);
thread_handle_ =
CreateThread(NULL, creation_params_.stack_size,
(LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32, this,
suspended ? CREATE_SUSPENDED : 0, NULL);
if (!thread_handle_) {
uint32_t last_error = GetLastError();
// TODO(benvanik): translate?
@ -319,20 +303,15 @@ X_STATUS XThread::PlatformCreate() {
if (creation_params_.creation_flags & 0x1) {
#if XE_PLATFORM_OSX
result_code = pthread_create_suspended_np(
reinterpret_cast<pthread_t*>(&thread_handle_),
&attr,
&XThreadStartCallbackPthreads,
this);
reinterpret_cast<pthread_t*>(&thread_handle_), &attr,
&XThreadStartCallbackPthreads, this);
#else
// TODO(benvanik): pthread_create_suspended_np on linux
assert_always();
#endif // OSX
} else {
result_code = pthread_create(
reinterpret_cast<pthread_t*>(&thread_handle_),
&attr,
&XThreadStartCallbackPthreads,
this);
result_code = pthread_create(reinterpret_cast<pthread_t*>(&thread_handle_),
&attr, &XThreadStartCallbackPthreads, this);
}
pthread_attr_destroy(&attr);
@ -389,28 +368,21 @@ void XThread::EnterCriticalRegion() {
critical_region_.lock();
}
void XThread::LeaveCriticalRegion() {
critical_region_.unlock();
}
void XThread::LeaveCriticalRegion() { critical_region_.unlock(); }
uint32_t XThread::RaiseIrql(uint32_t new_irql) {
return irql_.exchange(new_irql);
}
void XThread::LowerIrql(uint32_t new_irql) {
irql_ = new_irql;
}
void XThread::LowerIrql(uint32_t new_irql) { irql_ = new_irql; }
void XThread::LockApc() {
apc_lock_.lock();
}
void XThread::LockApc() { apc_lock_.lock(); }
void XThread::UnlockApc() {
bool needs_apc = apc_list_->HasPending();
apc_lock_.unlock();
if (needs_apc) {
QueueUserAPC(reinterpret_cast<PAPCFUNC>(DeliverAPCs),
thread_handle_,
QueueUserAPC(reinterpret_cast<PAPCFUNC>(DeliverAPCs), thread_handle_,
reinterpret_cast<ULONG_PTR>(this));
}
}
@ -447,16 +419,15 @@ void XThread::DeliverAPCs(void* data) {
poly::store_and_swap<uint32_t>(scratch_ptr + 4, normal_context);
poly::store_and_swap<uint32_t>(scratch_ptr + 8, system_arg1);
poly::store_and_swap<uint32_t>(scratch_ptr + 12, system_arg2);
// kernel_routine(apc_address, &normal_routine, &normal_context, &system_arg1, &system_arg2)
// kernel_routine(apc_address, &normal_routine, &normal_context,
// &system_arg1, &system_arg2)
uint64_t kernel_args[] = {
apc_address,
thread->scratch_address_ + 0,
thread->scratch_address_ + 4,
thread->scratch_address_ + 8,
thread->scratch_address_ + 12,
apc_address, thread->scratch_address_ + 0,
thread->scratch_address_ + 4, thread->scratch_address_ + 8,
thread->scratch_address_ + 12,
};
processor->ExecuteInterrupt(
0, kernel_routine, kernel_args, poly::countof(kernel_args));
processor->ExecuteInterrupt(0, kernel_routine, kernel_args,
poly::countof(kernel_args));
normal_routine = poly::load_and_swap<uint32_t>(scratch_ptr + 0);
normal_context = poly::load_and_swap<uint32_t>(scratch_ptr + 4);
system_arg1 = poly::load_and_swap<uint32_t>(scratch_ptr + 8);
@ -467,9 +438,9 @@ void XThread::DeliverAPCs(void* data) {
if (normal_routine) {
thread->UnlockApc();
// normal_routine(normal_context, system_arg1, system_arg2)
uint64_t normal_args[] = { normal_context, system_arg1, system_arg2 };
processor->ExecuteInterrupt(
0, normal_routine, normal_args, poly::countof(normal_args));
uint64_t normal_args[] = {normal_context, system_arg1, system_arg2};
processor->ExecuteInterrupt(0, normal_routine, normal_args,
poly::countof(normal_args));
thread->LockApc();
}
}
@ -493,17 +464,15 @@ void XThread::RundownAPCs() {
// Call the rundown routine.
if (rundown_routine) {
// rundown_routine(apc)
uint64_t args[] = { apc_address };
kernel_state()->processor()->ExecuteInterrupt(
0, rundown_routine, args, poly::countof(args));
uint64_t args[] = {apc_address};
kernel_state()->processor()->ExecuteInterrupt(0, rundown_routine, args,
poly::countof(args));
}
}
UnlockApc();
}
int32_t XThread::QueryPriority() {
return GetThreadPriority(thread_handle_);
}
int32_t XThread::QueryPriority() { return GetThreadPriority(thread_handle_); }
void XThread::SetPriority(int32_t increment) {
SetThreadPriority(thread_handle_, increment);
@ -538,8 +507,8 @@ X_STATUS XThread::Suspend(uint32_t* out_suspend_count) {
}
}
X_STATUS XThread::Delay(
uint32_t processor_mode, uint32_t alertable, uint64_t interval) {
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) {
@ -549,21 +518,22 @@ X_STATUS XThread::Delay(
timeout_ms = 0;
} else if (timeout_ticks < 0) {
// Relative time.
timeout_ms = (DWORD)(-timeout_ticks / 10000); // Ticks -> MS
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;
case 0:
return X_STATUS_SUCCESS;
case WAIT_IO_COMPLETION:
return X_STATUS_USER_APC;
default:
return X_STATUS_ALERTED;
}
}
void* XThread::GetWaitHandle() {
return event_->GetWaitHandle();
}
void* XThread::GetWaitHandle() { return event_->GetWaitHandle(); }
} // namespace kernel
} // namespace xe

View File

@ -15,26 +15,21 @@
#include <string>
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
XEDECLARECLASS2(xe, cpu, XenonThreadState);
namespace xe {
namespace kernel {
class NativeList;
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);
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();
@ -68,12 +63,12 @@ public:
X_STATUS Resume(uint32_t* out_suspend_count);
X_STATUS Suspend(uint32_t* out_suspend_count);
X_STATUS Delay(
uint32_t processor_mode, uint32_t alertable, uint64_t interval);
X_STATUS Delay(uint32_t processor_mode, uint32_t alertable,
uint64_t interval);
virtual void* GetWaitHandle();
private:
private:
X_STATUS PlatformCreate();
void PlatformDestroy();
X_STATUS PlatformExit(int exit_code);
@ -82,33 +77,31 @@ private:
void RundownAPCs();
struct {
uint32_t stack_size;
uint32_t xapi_thread_startup;
uint32_t start_address;
uint32_t start_context;
uint32_t creation_flags;
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 scratch_address_;
uint32_t scratch_size_;
uint32_t tls_address_;
uint32_t thread_state_address_;
uint32_t thread_id_;
void* thread_handle_;
uint32_t scratch_address_;
uint32_t scratch_size_;
uint32_t tls_address_;
uint32_t thread_state_address_;
cpu::XenonThreadState* thread_state_;
std::string name_;
std::string name_;
std::atomic<uint32_t> irql_;
std::mutex apc_lock_;
NativeList* apc_list_;
NativeList* apc_list_;
XEvent* event_;
XEvent* event_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XTHREAD_H_

View File

@ -11,15 +11,11 @@
#include <xenia/cpu/processor.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::kernel;
XTimer::XTimer(KernelState* kernel_state) :
XObject(kernel_state, kTypeTimer),
handle_(NULL) {
}
XTimer::XTimer(KernelState* kernel_state)
: XObject(kernel_state, kTypeTimer), handle_(NULL) {}
XTimer::~XTimer() {
if (handle_) {
@ -32,33 +28,32 @@ void XTimer::Initialize(uint32_t timer_type) {
bool manual_reset = false;
switch (timer_type) {
case 0: // NotificationTimer
manual_reset = true;
break;
case 1: // SynchronizationTimer
manual_reset = false;
break;
default:
assert_always();
break;
case 0: // NotificationTimer
manual_reset = true;
break;
case 1: // SynchronizationTimer
manual_reset = false;
break;
default:
assert_always();
break;
}
handle_ = CreateWaitableTimer(NULL, manual_reset, NULL);
}
X_STATUS XTimer::SetTimer(
int64_t due_time, uint32_t period_ms,
uint32_t routine, uint32_t routine_arg, bool resume) {
X_STATUS XTimer::SetTimer(int64_t due_time, uint32_t period_ms,
uint32_t routine, uint32_t routine_arg, bool resume) {
// Stash routine for callback.
current_routine_ = routine;
current_routine_arg_ = routine_arg;
LARGE_INTEGER due_time_li;
due_time_li.QuadPart = due_time;
BOOL result = SetWaitableTimer(
handle_, &due_time_li, period_ms,
routine ? (PTIMERAPCROUTINE)CompletionRoutine : NULL, this,
resume ? TRUE : FALSE);
BOOL result =
SetWaitableTimer(handle_, &due_time_li, period_ms,
routine ? (PTIMERAPCROUTINE)CompletionRoutine : NULL,
this, resume ? TRUE : FALSE);
// Caller is checking for STATUS_TIMER_RESUME_IGNORED.
// This occurs if result == TRUE but error is set.
@ -69,8 +64,8 @@ X_STATUS XTimer::SetTimer(
return result ? X_STATUS_SUCCESS : X_STATUS_UNSUCCESSFUL;
}
void XTimer::CompletionRoutine(
XTimer* timer, DWORD timer_low, DWORD timer_high) {
void XTimer::CompletionRoutine(XTimer* timer, DWORD timer_low,
DWORD timer_high) {
assert_true(timer->current_routine_);
// Queue APC to call back routine with (arg, low, high).
@ -81,6 +76,9 @@ void XTimer::CompletionRoutine(
}
X_STATUS XTimer::Cancel() {
return CancelWaitableTimer(handle_) == 0 ?
X_STATUS_SUCCESS : X_STATUS_UNSUCCESSFUL;
return CancelWaitableTimer(handle_) == 0 ? X_STATUS_SUCCESS
: X_STATUS_UNSUCCESSFUL;
}
} // namespace kernel
} // namespace xe

View File

@ -11,41 +11,36 @@
#define XENIA_KERNEL_XBOXKRNL_XTIMER_H_
#include <xenia/kernel/xobject.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XTimer : public XObject {
public:
public:
XTimer(KernelState* kernel_state);
virtual ~XTimer();
void Initialize(uint32_t timer_type);
// completion routine, arg to completion routine
X_STATUS SetTimer(int64_t due_time, uint32_t period_ms,
uint32_t routine, uint32_t routine_arg, bool resume);
X_STATUS SetTimer(int64_t due_time, uint32_t period_ms, uint32_t routine,
uint32_t routine_arg, bool resume);
X_STATUS Cancel();
virtual void* GetWaitHandle() { return handle_; }
private:
private:
HANDLE handle_;
uint32_t current_routine_;
uint32_t current_routine_arg_;
static void CompletionRoutine(
XTimer* timer, DWORD timer_low, DWORD timer_high);
static void CompletionRoutine(XTimer* timer, DWORD timer_low,
DWORD timer_high);
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_TIMER_H_

View File

@ -14,24 +14,17 @@
#include <xenia/kernel/objects/xfile.h>
#include <xenia/kernel/objects/xthread.h>
namespace xe {
namespace kernel {
using namespace xe;
using namespace xe::cpu;
using namespace xe::kernel;
XUserModule::XUserModule(KernelState* kernel_state, const char* path)
: XModule(kernel_state, path), xex_(NULL) {}
XUserModule::XUserModule(KernelState* kernel_state, const char* path) :
XModule(kernel_state, path),
xex_(NULL) {
}
XUserModule::~XUserModule() { xe_xex2_release(xex_); }
XUserModule::~XUserModule() {
xe_xex2_release(xex_);
}
xe_xex2_ref XUserModule::xex() {
return xe_xex2_retain(xex_);
}
xe_xex2_ref XUserModule::xex() { return xe_xex2_retain(xex_); }
const xe_xex2_header_t* XUserModule::xex_header() {
return xe_xex2_get_header(xex_);
@ -134,9 +127,8 @@ void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) {
return NULL;
}
X_STATUS XUserModule::GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size) {
X_STATUS XUserModule::GetSection(const char* name, uint32_t* out_section_data,
uint32_t* out_section_size) {
auto header = xe_xex2_get_header(xex_);
for (size_t n = 0; n < header->resource_info_count; n++) {
auto& res = header->resource_infos[n];
@ -158,12 +150,8 @@ X_STATUS XUserModule::Launch(uint32_t flags) {
Dump();
// Create a thread to run in.
XThread* thread = new XThread(
kernel_state(),
header->exe_stack_size,
0,
header->exe_entry_point, NULL,
0);
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)) {
@ -196,11 +184,10 @@ void XUserModule::Dump() {
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(
" 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,
@ -222,14 +209,14 @@ void XUserModule::Dump() {
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);
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(" %.8X (%.8X, %4db) %.8X = %11d\n", opt_header->key,
opt_header->offset, opt_header->length, opt_header->value,
opt_header->value);
}
printf("\n");
@ -237,8 +224,8 @@ void XUserModule::Dump() {
printf("Resources:\n");
for (size_t n = 0; n < header->resource_info_count; n++) {
auto& res = header->resource_infos[n];
printf(" %-8s %.8X-%.8X, %db\n",
res.name, res.address, res.address + res.size, res.size);
printf(" %-8s %.8X-%.8X, %db\n", res.name, res.address,
res.address + res.size, res.size);
}
printf("\n");
@ -248,23 +235,23 @@ void XUserModule::Dump() {
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;
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);
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");
@ -272,9 +259,8 @@ void XUserModule::Dump() {
// 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,
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");
@ -286,15 +272,15 @@ void XUserModule::Dump() {
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)) {
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(" 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.
@ -323,30 +309,28 @@ void XUserModule::Dump() {
(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);
(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";
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 (kernel_export && kernel_export->type == KernelExport::Variable) {
printf(" V %.8X %.3X (%3d) %s %s\n",
info->value_address, info->ordinal, info->ordinal,
implemented ? " " : "!!", name);
printf(" V %.8X %.3X (%3d) %s %s\n", info->value_address,
info->ordinal, info->ordinal, implemented ? " " : "!!", name);
} else 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);
printf(" F %.8X %.8X %.3X (%3d) %s %s\n", info->value_address,
info->thunk_address, info->ordinal, info->ordinal,
implemented ? " " : "!!", name);
}
}
}
@ -359,3 +343,6 @@ void XUserModule::Dump() {
printf(" TODO\n");
printf("\n");
}
} // namespace kernel
} // namespace xe

View File

@ -13,16 +13,14 @@
#include <xenia/kernel/objects/xmodule.h>
#include <xenia/export_resolver.h>
#include <xenia/xbox.h>
#include <xenia/kernel/util/xex2.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class XUserModule : public XModule {
public:
public:
XUserModule(KernelState* kernel_state, const char* path);
virtual ~XUserModule();
@ -33,23 +31,20 @@ public:
X_STATUS LoadFromMemory(const void* addr, const size_t length);
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
virtual X_STATUS GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size);
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
uint32_t* out_section_size);
X_STATUS Launch(uint32_t flags);
void Dump();
private:
private:
int LoadPE();
xe_xex2_ref xex_;
xe_xex2_ref xex_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XUSER_MODULE_H_

View File

@ -9,11 +9,9 @@
#include <xenia/kernel/user_profile.h>
namespace xe {
namespace kernel {
UserProfile::UserProfile() {
xuid_ = 0xBABEBABEBABEBABE;
name_ = "User";
@ -78,13 +76,11 @@ UserProfile::UserProfile() {
AddSetting(std::make_unique<BinarySetting>(0x63E83FFD, zeros));
}
void UserProfile::AddSetting(std::unique_ptr<Setting> setting) {
settings_.insert({ setting->setting_id, setting.get() });
settings_.insert({setting->setting_id, setting.get()});
setting_list_.push_back(std::move(setting));
}
UserProfile::Setting* UserProfile::GetSetting(uint32_t setting_id) {
const auto& it = settings_.find(setting_id);
if (it == settings_.end()) {
@ -93,6 +89,5 @@ UserProfile::Setting* UserProfile::GetSetting(uint32_t setting_id) {
return it->second;
}
} // namespace kernel
} // namespace xe

View File

@ -20,13 +20,11 @@
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
class UserProfile {
public:
public:
struct Setting {
enum class Type {
UNKNOWN = 0,
@ -54,14 +52,15 @@ public:
Setting(uint32_t setting_id, Type type, size_t size)
: setting_id(setting_id), type(type), size(size) {}
virtual size_t extra_size() const { return 0; }
virtual size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) {
poly::store_and_swap<uint8_t>(user_data + kTypeOffset, static_cast<uint8_t>(type));
virtual size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) {
poly::store_and_swap<uint8_t>(user_data + kTypeOffset,
static_cast<uint8_t>(type));
return buffer_offset;
}
bool is_title_specific() const {
return (setting_id & 0x3F00) == 0x3F00;
}
protected:
bool is_title_specific() const { return (setting_id & 0x3F00) == 0x3F00; }
protected:
const size_t kTypeOffset = 0;
const size_t kValueOffset = 8;
const size_t kPointerOffset = 12;
@ -70,7 +69,8 @@ public:
Int32Setting(uint32_t setting_id, int32_t value)
: Setting(setting_id, Type::INT32, 4), value(value) {}
int32_t value;
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
poly::store_and_swap<int32_t>(user_data + kValueOffset, value);
return buffer_offset;
@ -80,7 +80,8 @@ public:
Int64Setting(uint32_t setting_id, int64_t value)
: Setting(setting_id, Type::INT64, 8), value(value) {}
int64_t value;
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
poly::store_and_swap<int64_t>(user_data + kValueOffset, value);
return buffer_offset;
@ -90,7 +91,8 @@ public:
DoubleSetting(uint32_t setting_id, double value)
: Setting(setting_id, Type::DOUBLE, 8), value(value) {}
double value;
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
poly::store_and_swap<double>(user_data + kValueOffset, value);
return buffer_offset;
@ -103,7 +105,8 @@ public:
size_t extra_size() const override {
return value.empty() ? 0 : 2 * (static_cast<int32_t>(value.size()) + 1);
}
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
int32_t length;
if (value.empty()) {
@ -124,7 +127,8 @@ public:
FloatSetting(uint32_t setting_id, float value)
: Setting(setting_id, Type::FLOAT, 4), value(value) {}
float value;
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
poly::store_and_swap<float>(user_data + kValueOffset, value);
return buffer_offset;
@ -137,7 +141,8 @@ public:
size_t extra_size() const override {
return static_cast<int32_t>(value.size());
}
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
int32_t length;
if (value.empty()) {
@ -158,7 +163,8 @@ public:
DateTimeSetting(uint32_t setting_id, int64_t value)
: Setting(setting_id, Type::DATETIME, 8), value(value) {}
int64_t value;
size_t Append(uint8_t* user_data, uint8_t* buffer, size_t buffer_offset) override {
size_t Append(uint8_t* user_data, uint8_t* buffer,
size_t buffer_offset) override {
buffer_offset = Setting::Append(user_data, buffer, buffer_offset);
poly::store_and_swap<int64_t>(user_data + kValueOffset, value);
return buffer_offset;
@ -174,16 +180,14 @@ public:
void AddSetting(std::unique_ptr<Setting> setting);
Setting* GetSetting(uint32_t setting_id);
private:
private:
uint64_t xuid_;
std::string name_;
std::vector<std::unique_ptr<Setting>> setting_list_;
std::unordered_map<uint32_t, Setting*> settings_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_USER_PROFILE_H_

File diff suppressed because it is too large Load Diff

View File

@ -13,51 +13,47 @@
#include <xenia/core.h>
#include <xenia/kernel/util/xex2_info.h>
typedef struct {
int reserved;
} xe_xex2_options_t;
typedef struct { int reserved; } xe_xex2_options_t;
struct xe_xex2;
typedef struct xe_xex2* xe_xex2_ref;
typedef struct {
uint32_t ordinal;
uint32_t value_address; // address to place value
uint32_t thunk_address; // NULL or address of thunk
uint32_t value_address; // address to place value
uint32_t thunk_address; // NULL or address of thunk
} xe_xex2_import_info_t;
enum xe_pe_section_flags_e {
kXEPESectionContainsCode = 0x00000020,
kXEPESectionContainsDataInit = 0x00000040,
kXEPESectionContainsDataUninit = 0x00000080,
kXEPESectionMemoryExecute = 0x20000000,
kXEPESectionMemoryRead = 0x40000000,
kXEPESectionMemoryWrite = 0x80000000,
kXEPESectionContainsCode = 0x00000020,
kXEPESectionContainsDataInit = 0x00000040,
kXEPESectionContainsDataUninit = 0x00000080,
kXEPESectionMemoryExecute = 0x20000000,
kXEPESectionMemoryRead = 0x40000000,
kXEPESectionMemoryWrite = 0x80000000,
};
class PESection {
public:
char name[9]; // 8 + 1 for \0
uint32_t raw_address;
uint32_t raw_size;
uint32_t address;
uint32_t size;
uint32_t flags; // kXEPESection*
public:
char name[9]; // 8 + 1 for \0
uint32_t raw_address;
uint32_t raw_size;
uint32_t address;
uint32_t size;
uint32_t flags; // kXEPESection*
};
xe_xex2_ref xe_xex2_load(xe::Memory* memory,
const void* addr, const size_t length,
xe_xex2_options_t options);
xe_xex2_ref xe_xex2_load(xe::Memory* memory, const void* addr,
const size_t length, xe_xex2_options_t options);
xe_xex2_ref xe_xex2_retain(xe_xex2_ref xex);
void xe_xex2_release(xe_xex2_ref xex);
const xe_xex2_header_t *xe_xex2_get_header(xe_xex2_ref xex);
const xe_xex2_header_t* xe_xex2_get_header(xe_xex2_ref xex);
const PESection* xe_xex2_get_pe_section(xe_xex2_ref xex, const char* name);
int xe_xex2_get_import_infos(xe_xex2_ref xex,
const xe_xex2_import_library_t *library,
xe_xex2_import_info_t **out_import_infos,
size_t *out_import_info_count);
const xe_xex2_import_library_t* library,
xe_xex2_import_info_t** out_import_infos,
size_t* out_import_info_count);
#endif // XENIA_KERNEL_UTIL_XEX2_H_

View File

@ -12,7 +12,6 @@
#include <xenia/common.h>
typedef enum {
XEX_HEADER_RESOURCE_INFO = 0x000002FF,
XEX_HEADER_FILE_FORMAT_INFO = 0x000003FF,
@ -456,5 +455,4 @@ typedef struct {
xe_xex2_section_t* sections;
} xe_xex2_header_t;
#endif // XENIA_KERNEL_XEX2_INFO_H_

View File

@ -14,20 +14,15 @@
#include <xenia/kernel/xam_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XamContentGetLicenseMask_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamContentGetLicenseMask_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t mask_ptr = SHIM_GET_ARG_32(0);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(1);
XELOGD(
"XamContentGetLicenseMask(%.8X, %.8X)",
mask_ptr,
overlapped_ptr);
XELOGD("XamContentGetLicenseMask(%.8X, %.8X)", mask_ptr, overlapped_ptr);
// Arcade games seem to call this and check the result mask for random bits.
// If we fail, the games seem to use a hardcoded mask, which is likely trial.
@ -42,10 +37,9 @@ SHIM_CALL XamContentGetLicenseMask_shim(
}
}
// http://gameservice.googlecode.com/svn-history/r14/trunk/ContentManager.cpp
SHIM_CALL XamContentCreateEnumerator_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t arg1 = SHIM_GET_ARG_32(1);
uint32_t arg2 = SHIM_GET_ARG_32(2);
@ -54,18 +48,16 @@ SHIM_CALL XamContentCreateEnumerator_shim(
uint32_t arg5 = SHIM_GET_ARG_32(5);
uint32_t handle_ptr = SHIM_GET_ARG_32(6);
XELOGD(
"XamContentCreateEnumerator(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
arg0, arg1, arg2, arg3, arg4, arg5, handle_ptr);
XELOGD("XamContentCreateEnumerator(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
arg0, arg1, arg2, arg3, arg4, arg5, handle_ptr);
SHIM_SET_MEM_32(handle_ptr, X_INVALID_HANDLE_VALUE);
SHIM_SET_RETURN_32(X_ERROR_NO_MORE_FILES);
}
SHIM_CALL XamShowDeviceSelectorUI_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamShowDeviceSelectorUI_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t arg1 = SHIM_GET_ARG_32(1);
uint32_t arg2 = SHIM_GET_ARG_32(2);
@ -73,19 +65,16 @@ SHIM_CALL XamShowDeviceSelectorUI_shim(
uint32_t arg4 = SHIM_GET_ARG_32(4);
uint32_t arg5 = SHIM_GET_ARG_32(5);
XELOGD(
"XamShowDeviceSelectorUI(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
arg0, arg1, arg2, arg3, arg4, arg5);
XELOGD("XamShowDeviceSelectorUI(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", arg0,
arg1, arg2, arg3, arg4, arg5);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterContentExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterContentExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamContentGetLicenseMask, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreateEnumerator, state);
SHIM_SET_MAPPING("xam.xex", XamShowDeviceSelectorUI, state);

View File

@ -16,13 +16,10 @@
#include <xenia/kernel/util/shim_utils.h>
#include <xenia/kernel/util/xex2.h>
namespace xe {
namespace kernel {
SHIM_CALL XamGetSystemVersion_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamGetSystemVersion_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("XamGetSystemVersion()");
// eh, just picking one. If we go too low we may break new games, but
// this value seems to be used for conditionally loading symbols and if
@ -32,9 +29,7 @@ SHIM_CALL XamGetSystemVersion_shim(
SHIM_SET_RETURN_64(0);
}
SHIM_CALL XGetAVPack_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XGetAVPack_shim(PPCContext* ppc_state, KernelState* state) {
// DWORD
// Not sure what the values are for this, but 6 is VGA.
// Other likely values are 3/4/8 for HDMI or something.
@ -43,17 +38,13 @@ SHIM_CALL XGetAVPack_shim(
SHIM_SET_RETURN_64(6);
}
SHIM_CALL XGetGameRegion_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XGetGameRegion_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("XGetGameRegion()");
SHIM_SET_RETURN_64(XEX_REGION_ALL);
}
SHIM_CALL XGetLanguage_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XGetLanguage_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("XGetLanguage()");
uint32_t desired_language = X_LANGUAGE_ENGLISH;
@ -71,36 +62,28 @@ SHIM_CALL XGetLanguage_shim(
SHIM_SET_RETURN_64(desired_language);
}
SHIM_CALL XamLoaderGetLaunchDataSize_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamLoaderGetLaunchDataSize_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t size_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XamLoaderGetLaunchDataSize(%.8X)",
size_ptr);
XELOGD("XamLoaderGetLaunchDataSize(%.8X)", size_ptr);
SHIM_SET_MEM_32(size_ptr, 0);
SHIM_SET_RETURN_64(0);
}
SHIM_CALL XamLoaderGetLaunchData_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamLoaderGetLaunchData_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t buffer_ptr = SHIM_GET_ARG_32(0);
uint32_t buffer_size = SHIM_GET_ARG_32(1);
XELOGD(
"XamLoaderGetLaunchData(%.8X, %d)",
buffer_ptr, buffer_size);
XELOGD("XamLoaderGetLaunchData(%.8X, %d)", buffer_ptr, buffer_size);
SHIM_SET_RETURN_64(0);
}
SHIM_CALL XamEnumerate_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamEnumerate_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t zero = SHIM_GET_ARG_32(1);
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
@ -108,14 +91,11 @@ SHIM_CALL XamEnumerate_shim(
uint32_t item_count_ptr = SHIM_GET_ARG_32(4);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(5);
XELOGD(
"XamEnumerate(%.8X, %d, %d, %.8X, %d, %.8X, %.8X)",
handle, zero, buffer_ptr, buffer_length, item_count_ptr,
overlapped_ptr);
XELOGD("XamEnumerate(%.8X, %d, %d, %.8X, %d, %.8X, %.8X)", handle, zero,
buffer_ptr, buffer_length, item_count_ptr, overlapped_ptr);
XEnumerator* e = nullptr;
if (XFAILED(state->object_table()->GetObject(
handle, (XObject**)&e))) {
if (XFAILED(state->object_table()->GetObject(handle, (XObject**)&e))) {
SHIM_SET_RETURN_64(X_ERROR_INVALID_HANDLE);
return;
}
@ -135,13 +115,11 @@ SHIM_CALL XamEnumerate_shim(
SHIM_SET_RETURN_64(0);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterInfoExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterInfoExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamGetSystemVersion, state);
SHIM_SET_MAPPING("xam.xex", XGetAVPack, state);
SHIM_SET_MAPPING("xam.xex", XGetGameRegion, state);

View File

@ -16,53 +16,40 @@
#include <xenia/kernel/xam_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
using xe::hid::InputSystem;
SHIM_CALL XamResetInactivity_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamResetInactivity_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk = SHIM_GET_ARG_32(0);
XELOGD(
"XamResetInactivity(%d)",
unk);
XELOGD("XamResetInactivity(%d)", unk);
// Result ignored.
SHIM_SET_RETURN_64(0);
}
SHIM_CALL XamEnableInactivityProcessing_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamEnableInactivityProcessing_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t zero = SHIM_GET_ARG_32(0);
uint32_t unk = SHIM_GET_ARG_32(2);
XELOGD(
"XamEnableInactivityProcessing(%d, %d)",
zero,
unk);
XELOGD("XamEnableInactivityProcessing(%d, %d)", zero, unk);
// Expects 0.
SHIM_SET_RETURN_64(0);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetcapabilities(v=vs.85).aspx
SHIM_CALL XamInputGetCapabilities_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamInputGetCapabilities_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t flags = SHIM_GET_ARG_32(1);
uint32_t caps_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamInputGetCapabilities(%d, %.8X, %.8X)",
user_index,
flags,
caps_ptr);
XELOGD("XamInputGetCapabilities(%d, %.8X, %.8X)", user_index, flags,
caps_ptr);
if (!caps_ptr) {
SHIM_SET_RETURN_32(X_ERROR_BAD_ARGUMENTS);
@ -79,19 +66,13 @@ SHIM_CALL XamInputGetCapabilities_shim(
SHIM_SET_RETURN_32(result);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetstate(v=vs.85).aspx
SHIM_CALL XamInputGetState_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamInputGetState_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t one = SHIM_GET_ARG_32(1);
uint32_t state_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamInputGetState(%d, %.8X, %.8X)",
user_index,
one,
state_ptr);
XELOGD("XamInputGetState(%d, %.8X, %.8X)", user_index, one, state_ptr);
// Games call this with a NULL state ptr, probably as a query.
@ -107,19 +88,13 @@ SHIM_CALL XamInputGetState_shim(
SHIM_SET_RETURN_32(result);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputsetstate(v=vs.85).aspx
SHIM_CALL XamInputSetState_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamInputSetState_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t unk = SHIM_GET_ARG_32(1);
uint32_t vibration_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamInputSetState(%d, %.8X, %.8X)",
user_index,
unk,
vibration_ptr);
XELOGD("XamInputSetState(%d, %.8X, %.8X)", user_index, unk, vibration_ptr);
if (!vibration_ptr) {
SHIM_SET_RETURN_32(X_ERROR_BAD_ARGUMENTS);
@ -133,10 +108,8 @@ SHIM_CALL XamInputSetState_shim(
SHIM_SET_RETURN_32(result);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke(v=vs.85).aspx
SHIM_CALL XamInputGetKeystroke_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamInputGetKeystroke_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t flags = SHIM_GET_ARG_32(1);
uint32_t keystroke_ptr = SHIM_GET_ARG_32(2);
@ -145,11 +118,8 @@ SHIM_CALL XamInputGetKeystroke_shim(
// user index = index or XUSER_INDEX_ANY
// flags = XINPUT_FLAG_GAMEPAD (| _ANYUSER | _ANYDEVICE)
XELOGD(
"XamInputGetKeystroke(%d, %.8X, %.8X)",
user_index,
flags,
keystroke_ptr);
XELOGD("XamInputGetKeystroke(%d, %.8X, %.8X)", user_index, flags,
keystroke_ptr);
if (!keystroke_ptr) {
SHIM_SET_RETURN_32(X_ERROR_BAD_ARGUMENTS);
@ -166,21 +136,17 @@ SHIM_CALL XamInputGetKeystroke_shim(
SHIM_SET_RETURN_32(result);
}
// Same as non-ex, just takes a pointer to user index.
SHIM_CALL XamInputGetKeystrokeEx_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamInputGetKeystrokeEx_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index_ptr = SHIM_GET_ARG_32(0);
uint32_t flags = SHIM_GET_ARG_32(1);
uint32_t keystroke_ptr = SHIM_GET_ARG_32(2);
uint32_t user_index = SHIM_MEM_32(user_index_ptr);
XELOGD(
"XamInputGetKeystroke(%.8X(%.d), %.8X, %.8X)",
user_index_ptr, user_index,
flags,
keystroke_ptr);
XELOGD("XamInputGetKeystroke(%.8X(%.d), %.8X, %.8X)", user_index_ptr,
user_index, flags, keystroke_ptr);
if (!keystroke_ptr) {
SHIM_SET_RETURN_32(X_ERROR_BAD_ARGUMENTS);
@ -198,18 +164,13 @@ SHIM_CALL XamInputGetKeystrokeEx_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XamUserGetDeviceContext_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserGetDeviceContext_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t unk = SHIM_GET_ARG_32(1);
uint32_t out_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamUserGetDeviceContext(%d, %d, %.8X)",
user_index,
unk,
out_ptr);
XELOGD("XamUserGetDeviceContext(%d, %d, %.8X)", user_index, unk, out_ptr);
// Games check the result - usually with some masking.
// If this function fails they assume zero, so let's fail AND
@ -222,13 +183,11 @@ SHIM_CALL XamUserGetDeviceContext_shim(
}
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterInputExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterInputExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamResetInactivity, state);
SHIM_SET_MAPPING("xam.xex", XamEnableInactivityProcessing, state);
SHIM_SET_MAPPING("xam.xex", XamInputGetCapabilities, state);

View File

@ -14,21 +14,19 @@
#include <xenia/kernel/kernel_state.h>
#include <xenia/kernel/xam_private.h>
namespace xe {
namespace kernel {
XamModule::XamModule(Emulator* emulator, KernelState* kernel_state) :
XKernelModule(kernel_state, "xe:\\xam.xex") {
// Build the export table used for resolution.
#include <xenia/kernel/util/export_table_pre.inc>
XamModule::XamModule(Emulator* emulator, KernelState* kernel_state)
: XKernelModule(kernel_state, "xe:\\xam.xex") {
// Build the export table used for resolution.
#include <xenia/kernel/util/export_table_pre.inc>
static KernelExport xam_export_table[] = {
#include <xenia/kernel/xam_table.inc>
#include <xenia/kernel/xam_table.inc>
};
#include <xenia/kernel/util/export_table_post.inc>
export_resolver_->RegisterTable(
"xam.xex", xam_export_table, poly::countof(xam_export_table));
#include <xenia/kernel/util/export_table_post.inc>
export_resolver_->RegisterTable("xam.xex", xam_export_table,
poly::countof(xam_export_table));
// Register all exported functions.
xam::RegisterContentExports(export_resolver_, kernel_state);
@ -43,8 +41,7 @@ XamModule::XamModule(Emulator* emulator, KernelState* kernel_state) :
xam::RegisterVoiceExports(export_resolver_, kernel_state);
}
XamModule::~XamModule() {
}
XamModule::~XamModule() {}
} // namespace kernel
} // namespace xe

View File

@ -12,7 +12,6 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/export_resolver.h>
#include <xenia/kernel/xam_ordinals.h>
#include <xenia/kernel/objects/xkernel_module.h>
@ -20,18 +19,15 @@
namespace xe {
namespace kernel {
class XamModule : public XKernelModule {
public:
public:
XamModule(Emulator* emulator, KernelState* kernel_state);
virtual ~XamModule();
private:
private:
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XAM_H_

View File

@ -15,68 +15,56 @@
#include <xenia/kernel/objects/xevent.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XMsgInProcessCall_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XMsgInProcessCall_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t app = SHIM_GET_ARG_32(0);
uint32_t message = SHIM_GET_ARG_32(1);
uint32_t arg1 = SHIM_GET_ARG_32(2);
uint32_t arg2 = SHIM_GET_ARG_32(3);
XELOGD(
"XMsgInProcessCall(%.8X, %.8X, %.8X, %.8X)",
app, message, arg1, arg2);
XELOGD("XMsgInProcessCall(%.8X, %.8X, %.8X, %.8X)", app, message, arg1, arg2);
auto result = state->app_manager()->DispatchMessageSync(
app, message, arg1, arg2);
auto result =
state->app_manager()->DispatchMessageSync(app, message, arg1, arg2);
if (result == X_ERROR_NOT_FOUND) {
XELOGE("XMsgInProcessCall: app %.8X undefined", app);
}
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XMsgStartIORequest_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XMsgStartIORequest_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t app = SHIM_GET_ARG_32(0);
uint32_t message = SHIM_GET_ARG_32(1);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(2);
uint32_t buffer = SHIM_GET_ARG_32(3);
uint32_t buffer_length = SHIM_GET_ARG_32(4);
XELOGD(
"XMsgStartIORequest(%.8X, %.8X, %.8X, %.8X, %d)",
app, message, overlapped_ptr, buffer, buffer_length);
XELOGD("XMsgStartIORequest(%.8X, %.8X, %.8X, %.8X, %d)", app, message,
overlapped_ptr, buffer, buffer_length);
assert_zero(overlapped_ptr);
auto result = state->app_manager()->DispatchMessageAsync(
app, message, buffer, buffer_length);
auto result = state->app_manager()->DispatchMessageAsync(app, message, buffer,
buffer_length);
if (result == X_ERROR_NOT_FOUND) {
XELOGE("XMsgStartIORequest: app %.8X undefined", app);
}
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XMsgCancelIORequest_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XMsgCancelIORequest_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t overlapped_ptr = SHIM_GET_ARG_32(0);
uint32_t wait = SHIM_GET_ARG_32(1);
XELOGD(
"XMsgCancelIORequest(%.8X, %d)",
overlapped_ptr, wait);
XELOGD("XMsgCancelIORequest(%.8X, %d)", overlapped_ptr, wait);
X_HANDLE event_handle = XOverlappedGetEvent(SHIM_MEM_ADDR(overlapped_ptr));
if (event_handle && wait) {
XEvent* ev = nullptr;
if (XSUCCEEDED(state->object_table()->GetObject(
event_handle, reinterpret_cast<XObject**>(&ev)))) {
event_handle, reinterpret_cast<XObject**>(&ev)))) {
ev->Wait(0, 0, true, nullptr);
ev->Release();
}
@ -85,13 +73,11 @@ SHIM_CALL XMsgCancelIORequest_shim(
SHIM_SET_RETURN_32(0);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterMsgExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterMsgExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XMsgInProcessCall, state);
SHIM_SET_MAPPING("xam.xex", XMsgStartIORequest, state);
SHIM_SET_MAPPING("xam.xex", XMsgCancelIORequest, state);

View File

@ -16,48 +16,33 @@
#include <xenia/kernel/xam_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL NetDll_XNetStartup_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_XNetStartup_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t params_ptr = SHIM_GET_ARG_32(1);
XELOGD(
"NetDll_XNetStartup(%d, %.8X)",
arg0,
params_ptr);
XELOGD("NetDll_XNetStartup(%d, %.8X)", arg0, params_ptr);
SHIM_SET_RETURN_64(0);
}
SHIM_CALL NetDll_XNetCleanup_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_XNetCleanup_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t params_ptr = SHIM_GET_ARG_32(1);
XELOGD(
"NetDll_XNetCleanup(%d, %.8X)",
arg0,
params_ptr);
XELOGD("NetDll_XNetCleanup(%d, %.8X)", arg0, params_ptr);
SHIM_SET_RETURN_64(0);
}
SHIM_CALL NetDll_XNetRandom_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_XNetRandom_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t buffer_ptr = SHIM_GET_ARG_32(1);
uint32_t length = SHIM_GET_ARG_32(2);
XELOGD(
"NetDll_XNetRandom(%d, %.8X, %d)",
arg0,
buffer_ptr,
length);
XELOGD("NetDll_XNetRandom(%d, %.8X, %d)", arg0, buffer_ptr, length);
// For now, constant values.
// This makes replicating things easier.
@ -66,17 +51,12 @@ SHIM_CALL NetDll_XNetRandom_shim(
SHIM_SET_RETURN_64(0);
}
SHIM_CALL NetDll_WSAStartup_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_WSAStartup_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t version = SHIM_GET_ARG_16(1);
uint32_t data_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"NetDll_WSAStartup(%d, %.4X, %.8X)",
arg0,
version,
data_ptr);
XELOGD("NetDll_WSAStartup(%d, %.4X, %.8X)", arg0, version, data_ptr);
if (data_ptr) {
SHIM_SET_MEM_16(data_ptr + 0x000, version);
@ -94,109 +74,76 @@ SHIM_CALL NetDll_WSAStartup_shim(
SHIM_SET_RETURN_64(0);
}
SHIM_CALL NetDll_WSAGetLastError_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_WSAGetLastError_shim(PPCContext* ppc_state,
KernelState* state) {
XELOGD("NetDll_WSAGetLastError()");
SHIM_SET_RETURN_32(10093L); // WSANOTINITIALISED
}
SHIM_CALL NetDll_XNetGetTitleXnAddr_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_XNetGetTitleXnAddr_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t arg1 = SHIM_GET_ARG_32(1);
XELOGD(
"NetDll_XNetGetTitleXnAddr(%d, %.8X)",
arg0,
arg1);
XELOGD("NetDll_XNetGetTitleXnAddr(%d, %.8X)", arg0, arg1);
SHIM_SET_RETURN_32(0x00000001);
}
SHIM_CALL NetDll_XNetGetEthernetLinkStatus_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_XNetGetEthernetLinkStatus_shim(PPCContext* ppc_state,
KernelState* state) {
// Games seem to call this before *Startup. If we return 0, they don't even
// try.
uint32_t arg0 = SHIM_GET_ARG_32(0);
XELOGD(
"NetDll_XNetGetEthernetLinkStatus(%d)",
arg0);
XELOGD("NetDll_XNetGetEthernetLinkStatus(%d)", arg0);
SHIM_SET_RETURN_32(0);
}
SHIM_CALL NetDll_inet_addr_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_inet_addr_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t cp_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"NetDll_inet_addr(%.8X)",
cp_ptr);
SHIM_SET_RETURN_32(0xFFFFFFFF); // X_INADDR_NONE
XELOGD("NetDll_inet_addr(%.8X)", cp_ptr);
SHIM_SET_RETURN_32(0xFFFFFFFF); // X_INADDR_NONE
}
SHIM_CALL NetDll_socket_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_socket_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t af = SHIM_GET_ARG_32(1);
uint32_t type = SHIM_GET_ARG_32(2);
uint32_t protocol = SHIM_GET_ARG_32(3);
XELOGD(
"NetDll_socket(%d, %d, %d, %d)",
arg0,
af,
type,
protocol);
XELOGD("NetDll_socket(%d, %d, %d, %d)", arg0, af, type, protocol);
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
}
SHIM_CALL NetDll_setsockopt_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_setsockopt_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
uint32_t level = SHIM_GET_ARG_32(2);
uint32_t optname = SHIM_GET_ARG_32(3);
uint32_t optval_ptr = SHIM_GET_ARG_32(4);
uint32_t optlen = SHIM_GET_ARG_32(5);
XELOGD(
"NetDll_setsockopt(%d, %.8X, %d, %d, %.8X, %d)",
arg0,
socket_ptr,
level,
optname,
optval_ptr,
optlen);
XELOGD("NetDll_setsockopt(%d, %.8X, %d, %d, %.8X, %d)", arg0, socket_ptr,
level, optname, optval_ptr, optlen);
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
}
SHIM_CALL NetDll_connect_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_connect_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t socket_ptr = SHIM_GET_ARG_32(0);
uint32_t sockaddr_ptr = SHIM_GET_ARG_32(1);
uint32_t namelen = SHIM_GET_ARG_32(2);
XELOGD(
"NetDll_connect(%.8X, %.8X, %d)",
socket_ptr,
sockaddr_ptr,
namelen);
XELOGD("NetDll_connect(%.8X, %.8X, %d)", socket_ptr, sockaddr_ptr, namelen);
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
}
SHIM_CALL NetDll_recv_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_recv_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
uint32_t len = SHIM_GET_ARG_32(3);
uint32_t flags = SHIM_GET_ARG_32(4);
XELOGD(
"NetDll_recv(%d, %.8X, %.8X, %d, %d)",
arg0,
socket_ptr,
buf_ptr,
len,
flags);
XELOGD("NetDll_recv(%d, %.8X, %.8X, %d, %d)", arg0, socket_ptr, buf_ptr, len,
flags);
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
}
SHIM_CALL NetDll_recvfrom_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_recvfrom_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
@ -204,42 +151,27 @@ SHIM_CALL NetDll_recvfrom_shim(
uint32_t flags = SHIM_GET_ARG_32(4);
uint32_t from_ptr = SHIM_GET_ARG_32(5);
uint32_t fromlen_ptr = SHIM_GET_ARG_32(6);
XELOGD(
"NetDll_recvfrom(%d, %.8X, %.8X, %d, %d, %.8X, %.8X)",
arg0,
socket_ptr,
buf_ptr,
len,
flags,
from_ptr,
fromlen_ptr);
XELOGD("NetDll_recvfrom(%d, %.8X, %.8X, %d, %d, %.8X, %.8X)", arg0,
socket_ptr, buf_ptr, len, flags, from_ptr, fromlen_ptr);
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
}
SHIM_CALL NetDll_send_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NetDll_send_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
uint32_t len = SHIM_GET_ARG_32(3);
uint32_t flags = SHIM_GET_ARG_32(4);
XELOGD(
"NetDll_send(%d,%.8X, %.8X, %d, %d)",
arg0,
socket_ptr,
buf_ptr,
len,
flags);
XELOGD("NetDll_send(%d,%.8X, %.8X, %d, %d)", arg0, socket_ptr, buf_ptr, len,
flags);
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterNetExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterNetExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", NetDll_XNetStartup, state);
SHIM_SET_MAPPING("xam.xex", NetDll_XNetCleanup, state);
SHIM_SET_MAPPING("xam.xex", NetDll_XNetRandom, state);

View File

@ -15,20 +15,15 @@
#include <xenia/kernel/objects/xnotify_listener.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XamNotifyCreateListener_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamNotifyCreateListener_shim(PPCContext* ppc_state,
KernelState* state) {
uint64_t mask = SHIM_GET_ARG_64(0);
uint32_t one = SHIM_GET_ARG_32(1);
XELOGD(
"XamNotifyCreateListener(%.8llX, %d)",
mask,
one);
XELOGD("XamNotifyCreateListener(%.8llX, %d)", mask, one);
// r4=1 may indicate user process?
@ -42,21 +37,15 @@ SHIM_CALL XamNotifyCreateListener_shim(
SHIM_SET_RETURN_64(handle);
}
// http://ffplay360.googlecode.com/svn/Test/Common/AtgSignIn.cpp
SHIM_CALL XNotifyGetNext_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XNotifyGetNext_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t match_id = SHIM_GET_ARG_32(1);
uint32_t id_ptr = SHIM_GET_ARG_32(2);
uint32_t param_ptr = SHIM_GET_ARG_32(3);
XELOGD(
"XNotifyGetNext(%.8X, %.8X, %.8X, %.8X)",
handle,
match_id,
id_ptr,
param_ptr);
XELOGD("XNotifyGetNext(%.8X, %.8X, %.8X, %.8X)", handle, match_id, id_ptr,
param_ptr);
if (!handle) {
SHIM_SET_RETURN_64(0);
@ -65,8 +54,7 @@ SHIM_CALL XNotifyGetNext_shim(
// Grab listener.
XNotifyListener* listener = NULL;
if (XFAILED(state->object_table()->GetObject(
handle, (XObject**)&listener))) {
if (XFAILED(state->object_table()->GetObject(handle, (XObject**)&listener))) {
SHIM_SET_RETURN_64(0);
return;
}
@ -95,25 +83,19 @@ SHIM_CALL XNotifyGetNext_shim(
SHIM_SET_RETURN_64(dequeued ? 1 : 0);
}
SHIM_CALL XNotifyPositionUI_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XNotifyPositionUI_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t position = SHIM_GET_ARG_32(0);
XELOGD(
"XNotifyPositionUI(%.8X)",
position);
XELOGD("XNotifyPositionUI(%.8X)", position);
// Ignored.
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterNotifyExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterNotifyExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamNotifyCreateListener, state);
SHIM_SET_MAPPING("xam.xex", XNotifyGetNext, state);
SHIM_SET_MAPPING("xam.xex", XNotifyPositionUI, state);

View File

@ -12,18 +12,15 @@
#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/xam_table.inc>
#include <xenia/kernel/xam_table.inc>
};
} // namespace ordinals
#include <xenia/kernel/util/ordinal_table_post.inc>
#endif // XENIA_KERNEL_XAM_ORDINALS_H_

View File

@ -12,10 +12,8 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/xam_ordinals.h>
namespace xe {
namespace kernel {
@ -23,7 +21,8 @@ class KernelState;
namespace xam {
// Registration functions, one per file.
void RegisterContentExports(ExportResolver* export_resolver, KernelState* state);
void RegisterContentExports(ExportResolver* export_resolver,
KernelState* state);
void RegisterInfoExports(ExportResolver* export_resolver, KernelState* state);
void RegisterInputExports(ExportResolver* export_resolver, KernelState* state);
void RegisterMsgExports(ExportResolver* export_resolver, KernelState* state);
@ -38,5 +37,4 @@ void RegisterVoiceExports(ExportResolver* export_resolver, KernelState* state);
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XAM_PRIVATE_H_

View File

@ -14,13 +14,11 @@
#include <xenia/kernel/xam_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
// http://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/?jdfwkey=sb0vm
SHIM_CALL XamShowMessageBoxUI_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamShowMessageBoxUI_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t title_ptr = SHIM_GET_ARG_32(1);
uint32_t text_ptr = SHIM_GET_ARG_32(2);
@ -61,12 +59,10 @@ SHIM_CALL XamShowMessageBoxUI_shim(
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterUIExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterUIExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamShowMessageBoxUI, state);
}

View File

@ -16,22 +16,15 @@
#include <xenia/kernel/objects/xthread.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XamUserGetXUID_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserGetXUID_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t unk = SHIM_GET_ARG_32(1);
uint32_t xuid_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamUserGetXUID(%d, %.8X, %.8X)",
user_index,
unk,
xuid_ptr);
XELOGD("XamUserGetXUID(%d, %.8X, %.8X)", user_index, unk, xuid_ptr);
if (user_index == 0) {
const auto& user_profile = state->user_profile();
@ -44,14 +37,11 @@ SHIM_CALL XamUserGetXUID_shim(
}
}
SHIM_CALL XamUserGetSigninState_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserGetSigninState_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
XELOGD(
"XamUserGetSigninState(%d)",
user_index);
XELOGD("XamUserGetSigninState(%d)", user_index);
// Lie and say we are signed in, but local-only.
// This should keep games from asking us to sign in and also keep them
@ -64,24 +54,20 @@ SHIM_CALL XamUserGetSigninState_shim(
}
}
SHIM_CALL XamUserGetSigninInfo_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserGetSigninInfo_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t flags = SHIM_GET_ARG_32(1);
uint32_t info_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamUserGetSigninInfo(%d, %.8X, %.8X)",
user_index, flags, info_ptr);
XELOGD("XamUserGetSigninInfo(%d, %.8X, %.8X)", user_index, flags, info_ptr);
if (user_index == 0) {
const auto& user_profile = state->user_profile();
SHIM_SET_MEM_64(info_ptr + 0, user_profile->xuid());
SHIM_SET_MEM_32(info_ptr + 8, 0); // maybe zero?
SHIM_SET_MEM_32(info_ptr + 8, 0); // maybe zero?
SHIM_SET_MEM_32(info_ptr + 12, user_profile->signin_state());
SHIM_SET_MEM_32(info_ptr + 16, 0); // ?
SHIM_SET_MEM_32(info_ptr + 20, 0); // ?
SHIM_SET_MEM_32(info_ptr + 16, 0); // ?
SHIM_SET_MEM_32(info_ptr + 20, 0); // ?
char* buffer = (char*)SHIM_MEM_ADDR(info_ptr + 24);
strcpy(buffer, user_profile->name().data());
SHIM_SET_RETURN_32(0);
@ -90,16 +76,12 @@ SHIM_CALL XamUserGetSigninInfo_shim(
}
}
SHIM_CALL XamUserGetName_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserGetName_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t buffer_ptr = SHIM_GET_ARG_32(1);
uint32_t buffer_len = SHIM_GET_ARG_32(2);
XELOGD(
"XamUserGetName(%d, %.8X, %d)",
user_index, buffer_ptr, buffer_len);
XELOGD("XamUserGetName(%d, %.8X, %d)", user_index, buffer_ptr, buffer_len);
if (user_index == 0) {
const auto& user_profile = state->user_profile();
@ -111,10 +93,9 @@ SHIM_CALL XamUserGetName_shim(
}
}
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/xboxtools.cpp
SHIM_CALL XamUserReadProfileSettings_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserReadProfileSettings_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t title_id = SHIM_GET_ARG_32(0);
uint32_t user_index = SHIM_GET_ARG_32(1);
uint32_t unk_0 = SHIM_GET_ARG_32(2);
@ -130,7 +111,8 @@ SHIM_CALL XamUserReadProfileSettings_shim(
uint32_t buffer_size = SHIM_MEM_32(buffer_size_ptr);
XELOGD(
"XamUserReadProfileSettings(%.8X, %d, %d, %d, %d, %.8X, %.8X(%d), %.8X, %.8X)",
"XamUserReadProfileSettings(%.8X, %d, %d, %d, %d, %.8X, %.8X(%d), %.8X, "
"%.8X)",
title_id, user_index, unk_0, unk_1, setting_count, setting_ids_ptr,
buffer_size_ptr, buffer_size, buffer_ptr, overlapped_ptr);
@ -171,14 +153,16 @@ SHIM_CALL XamUserReadProfileSettings_shim(
uint32_t setting_id = SHIM_MEM_32(setting_ids_ptr + n * 4);
auto setting = user_profile->GetSetting(setting_id);
if (setting) {
auto extra_size = static_cast<uint32_t>(setting->extra_size());;
auto extra_size = static_cast<uint32_t>(setting->extra_size());
;
size_needed += extra_size;
}
}
SHIM_SET_MEM_32(buffer_size_ptr, size_needed);
if (buffer_size < size_needed) {
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_INSUFFICIENT_BUFFER);
state->CompleteOverlappedImmediate(overlapped_ptr,
X_ERROR_INSUFFICIENT_BUFFER);
}
SHIM_SET_RETURN_32(X_ERROR_INSUFFICIENT_BUFFER);
return;
@ -201,8 +185,7 @@ SHIM_CALL XamUserReadProfileSettings_shim(
SHIM_SET_MEM_32(user_data_ptr + 16, setting_id);
if (setting) {
buffer_offset = setting->Append(SHIM_MEM_ADDR(user_data_ptr + 24),
SHIM_MEM_ADDR(buffer_ptr),
buffer_offset);
SHIM_MEM_ADDR(buffer_ptr), buffer_offset);
} else {
memset(SHIM_MEM_ADDR(user_data_ptr + 24), 0, 16);
}
@ -217,18 +200,18 @@ SHIM_CALL XamUserReadProfileSettings_shim(
}
}
SHIM_CALL XamUserWriteProfileSettings_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserWriteProfileSettings_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t unknown = SHIM_GET_ARG_32(1);
uint32_t setting_count = SHIM_GET_ARG_32(2);
uint32_t settings_ptr = SHIM_GET_ARG_32(3);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(4);
XELOGD(
"XamUserWriteProfileSettings(%.8X, %d, %d, %d, %d, %.8X, %.8X(%d), %.8X, %.8X)",
user_index, unknown, setting_count, settings_ptr, overlapped_ptr);
"XamUserWriteProfileSettings(%.8X, %d, %d, %d, %d, %.8X, %.8X(%d), %.8X, "
"%.8X)",
user_index, unknown, setting_count, settings_ptr, overlapped_ptr);
if (!setting_count || !settings_ptr) {
SHIM_SET_RETURN_32(X_ERROR_INVALID_PARAMETER);
@ -251,22 +234,19 @@ SHIM_CALL XamUserWriteProfileSettings_shim(
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
}
else {
} else {
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
}
SHIM_CALL XamUserCheckPrivilege_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserCheckPrivilege_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t mask = SHIM_GET_ARG_32(1);
uint32_t out_value_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamUserCheckPrivilege(%d, %.8X, %.8X)",
user_index, mask, out_value_ptr);
XELOGD("XamUserCheckPrivilege(%d, %.8X, %.8X)", user_index, mask,
out_value_ptr);
// If we deny everything, games should hopefully not try to do stuff.
SHIM_SET_MEM_32(out_value_ptr, 0);
@ -274,15 +254,11 @@ SHIM_CALL XamUserCheckPrivilege_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XamShowSigninUI_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamShowSigninUI_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk_0 = SHIM_GET_ARG_32(0);
uint32_t unk_mask = SHIM_GET_ARG_32(1);
XELOGD(
"XamShowSigninUI(%d, %.8X)",
unk_0, unk_mask);
XELOGD("XamShowSigninUI(%d, %.8X)", unk_0, unk_mask);
// Mask values vary. Probably matching user types? Local/remote?
// Games seem to sit and loop until we trigger this notification.
@ -291,9 +267,8 @@ SHIM_CALL XamShowSigninUI_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XamUserCreateAchievementEnumerator_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamUserCreateAchievementEnumerator_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t title_id = SHIM_GET_ARG_32(0);
uint32_t user_index = SHIM_GET_ARG_32(1);
uint32_t xuid = SHIM_GET_ARG_32(2);
@ -304,7 +279,8 @@ SHIM_CALL XamUserCreateAchievementEnumerator_shim(
uint32_t handle_ptr = SHIM_GET_ARG_32(7);
XELOGD(
"XamUserCreateAchievementEnumerator(%.8X, %d, %.8X, %.8X, %d, %d, %.8X, %.8X)",
"XamUserCreateAchievementEnumerator(%.8X, %d, %.8X, %.8X, %d, %d, %.8X, "
"%.8X)",
title_id, user_index, xuid, flags, offset, count, buffer, handle_ptr);
XEnumerator* e = new XEnumerator(state);
@ -315,9 +291,7 @@ SHIM_CALL XamUserCreateAchievementEnumerator_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XamWriteGamerTile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamWriteGamerTile_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t arg0 = SHIM_GET_ARG_32(0);
uint32_t arg1 = SHIM_GET_ARG_32(1);
uint32_t arg2 = SHIM_GET_ARG_32(2);
@ -325,26 +299,22 @@ SHIM_CALL XamWriteGamerTile_shim(
uint32_t arg4 = SHIM_GET_ARG_32(4);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(5);
XELOGD(
"XamWriteGamerTile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
arg0, arg1, arg2, arg3, arg4, overlapped_ptr);
XELOGD("XamWriteGamerTile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", arg0, arg1,
arg2, arg3, arg4, overlapped_ptr);
if (overlapped_ptr) {
state->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
}
else {
} else {
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterUserExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterUserExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamUserGetXUID, state);
SHIM_SET_MAPPING("xam.xex", XamUserGetSigninState, state);
SHIM_SET_MAPPING("xam.xex", XamUserGetSigninInfo, state);

View File

@ -14,11 +14,9 @@
#include <xenia/kernel/xam_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
// TODO(benvanik): actually check to see if these are the same.
void xeVdQueryVideoMode(X_VIDEO_MODE* video_mode);
SHIM_CALL XGetVideoMode_shim(PPCContext* ppc_state, KernelState* state) {
@ -27,12 +25,10 @@ SHIM_CALL XGetVideoMode_shim(PPCContext* ppc_state, KernelState* state) {
xeVdQueryVideoMode(video_mode);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterVideoExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterVideoExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XGetVideoMode, state);
}

View File

@ -15,20 +15,15 @@
#include <xenia/kernel/xam_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XamVoiceCreate_shim(
PPCContext* ppc_state, KernelState* state) {
uint32_t unk1 = SHIM_GET_ARG_32(0); // 0
uint32_t unk2 = SHIM_GET_ARG_32(1); // 0xF
SHIM_CALL XamVoiceCreate_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk1 = SHIM_GET_ARG_32(0); // 0
uint32_t unk2 = SHIM_GET_ARG_32(1); // 0xF
uint32_t out_voice_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XamVoiceCreate(%.8X, %.8X, %.8X)",
unk1, unk2, out_voice_ptr);
XELOGD("XamVoiceCreate(%.8X, %.8X, %.8X)", unk1, unk2, out_voice_ptr);
// Null out the ptr.
SHIM_SET_MEM_32(out_voice_ptr, 0);
@ -36,37 +31,28 @@ SHIM_CALL XamVoiceCreate_shim(
SHIM_SET_RETURN_32(X_ERROR_ACCESS_DENIED);
}
SHIM_CALL XamVoiceClose_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamVoiceClose_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t voice_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XamVoiceClose(%.8X)",
voice_ptr);
XELOGD("XamVoiceClose(%.8X)", voice_ptr);
SHIM_SET_RETURN_32(0);
}
SHIM_CALL XamVoiceHeadsetPresent_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XamVoiceHeadsetPresent_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t voice_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XamVoiceHeadsetPresent(%.8X)",
voice_ptr);
XELOGD("XamVoiceHeadsetPresent(%.8X)", voice_ptr);
SHIM_SET_RETURN_32(0);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xam::RegisterVoiceExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xam::RegisterVoiceExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xam.xex", XamVoiceCreate, state);
SHIM_SET_MAPPING("xam.xex", XamVoiceClose, state);
SHIM_SET_MAPPING("xam.xex", XamVoiceHeadsetPresent, state);

View File

@ -16,18 +16,13 @@
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XMACreateContext_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XMACreateContext_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XMACreateContext(%.8X)",
context_ptr);
XELOGD("XMACreateContext(%.8X)", context_ptr);
// TODO(benvanik): allocate and return -- see if size required or just dummy?
// Games will call MmGetPhysicalAddress on the result.
@ -36,41 +31,32 @@ SHIM_CALL XMACreateContext_shim(
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
}
SHIM_CALL XMAReleaseContext_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XMAReleaseContext_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XMAReleaseContext(%.8X)",
context_ptr);
XELOGD("XMAReleaseContext(%.8X)", context_ptr);
// TODO(benvanik): free
}
SHIM_CALL XAudioGetSpeakerConfig_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioGetSpeakerConfig_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t config_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XAudioGetSpeakerConfig(%.8X)",
config_ptr);
XELOGD("XAudioGetSpeakerConfig(%.8X)", config_ptr);
SHIM_SET_MEM_32(config_ptr, 0x00010001);
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XAudioGetVoiceCategoryVolumeChangeMask_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioGetVoiceCategoryVolumeChangeMask_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t driver_ptr = SHIM_GET_ARG_32(0);
uint32_t out_ptr = SHIM_GET_ARG_32(1);
XELOGD(
"XAudioGetVoiceCategoryVolumeChangeMask(%.8X, %.8X)",
driver_ptr, out_ptr);
XELOGD("XAudioGetVoiceCategoryVolumeChangeMask(%.8X, %.8X)", driver_ptr,
out_ptr);
assert_true((driver_ptr & 0xFFFF0000) == 0x41550000);
@ -83,15 +69,12 @@ SHIM_CALL XAudioGetVoiceCategoryVolumeChangeMask_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XAudioGetVoiceCategoryVolume_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioGetVoiceCategoryVolume_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t unk = SHIM_GET_ARG_32(0);
uint32_t out_ptr = SHIM_GET_ARG_32(1);
XELOGD(
"XAudioGetVoiceCategoryVolume(%.8X, %.8X)",
unk, out_ptr);
XELOGD("XAudioGetVoiceCategoryVolume(%.8X, %.8X)", unk, out_ptr);
// Expects a floating point single. Volume %?
SHIM_SET_MEM_F32(out_ptr, 1.0f);
@ -99,30 +82,24 @@ SHIM_CALL XAudioGetVoiceCategoryVolume_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XAudioEnableDucker_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioEnableDucker_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk = SHIM_GET_ARG_32(0);
XELOGD(
"XAudioEnableDucker(%.8X)",
unk);
XELOGD("XAudioEnableDucker(%.8X)", unk);
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XAudioRegisterRenderDriverClient_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioRegisterRenderDriverClient_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t callback_ptr = SHIM_GET_ARG_32(0);
uint32_t driver_ptr = SHIM_GET_ARG_32(1);
uint32_t callback = SHIM_MEM_32(callback_ptr + 0);
uint32_t callback_arg = SHIM_MEM_32(callback_ptr + 4);
XELOGD(
"XAudioRegisterRenderDriverClient(%.8X(%.8X, %.8X), %.8X)",
callback_ptr, callback, callback_arg, driver_ptr);
XELOGD("XAudioRegisterRenderDriverClient(%.8X(%.8X, %.8X), %.8X)",
callback_ptr, callback, callback_arg, driver_ptr);
auto audio_system = state->emulator()->audio_system();
@ -134,18 +111,16 @@ SHIM_CALL XAudioRegisterRenderDriverClient_shim(
}
assert_true(!(index & ~0x0000FFFF));
SHIM_SET_MEM_32(driver_ptr, 0x41550000 | (static_cast<uint32_t>(index) & 0x0000FFFF));
SHIM_SET_MEM_32(driver_ptr,
0x41550000 | (static_cast<uint32_t>(index) & 0x0000FFFF));
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XAudioUnregisterRenderDriverClient_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioUnregisterRenderDriverClient_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t driver_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"XAudioUnregisterRenderDriverClient(%.8X)",
driver_ptr);
XELOGD("XAudioUnregisterRenderDriverClient(%.8X)", driver_ptr);
assert_true((driver_ptr & 0xFFFF0000) == 0x41550000);
@ -154,15 +129,12 @@ SHIM_CALL XAudioUnregisterRenderDriverClient_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XAudioSubmitRenderDriverFrame_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XAudioSubmitRenderDriverFrame_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t driver_ptr = SHIM_GET_ARG_32(0);
uint32_t samples_ptr = SHIM_GET_ARG_32(1);
XELOGD(
"XAudioSubmitRenderDriverFrame(%.8X, %.8X)",
driver_ptr, samples_ptr);
XELOGD("XAudioSubmitRenderDriverFrame(%.8X, %.8X)", driver_ptr, samples_ptr);
assert_true((driver_ptr & 0xFFFF0000) == 0x41550000);
@ -172,13 +144,11 @@ SHIM_CALL XAudioSubmitRenderDriverFrame_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterAudioExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xboxkrnl::RegisterAudioExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", XMACreateContext, state);
// SHIM_SET_MAPPING("xboxkrnl.exe", XMAInitializeContext, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XMAReleaseContext, state);
@ -202,7 +172,8 @@ void xe::kernel::xboxkrnl::RegisterAudioExports(
// SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetInputBufferReadOffset, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetSpeakerConfig, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetVoiceCategoryVolumeChangeMask, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetVoiceCategoryVolumeChangeMask,
state);
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetVoiceCategoryVolume, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XAudioEnableDucker, state);

View File

@ -15,29 +15,26 @@
#include <xenia/kernel/objects/xthread.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
// TODO: clean me up!
SHIM_CALL DbgPrint_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL DbgPrint_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t format_ptr = SHIM_GET_ARG_32(0);
if (format_ptr == 0) {
SHIM_SET_RETURN_64(-1);
return;
}
const char *format = (const char *)SHIM_MEM_ADDR(format_ptr);
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;
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;
const char* start = format;
if (*format != '%') {
*b++ = *format;
@ -54,14 +51,11 @@ SHIM_CALL DbgPrint_shim(
continue;
}
const char *end;
const char* end;
end = format;
// skip flags
while (*end == '-' ||
*end == '+' ||
*end == ' ' ||
*end == '#' ||
while (*end == '-' || *end == '+' || *end == ' ' || *end == '#' ||
*end == '0') {
++end;
}
@ -76,8 +70,7 @@ SHIM_CALL DbgPrint_shim(
if (*end == '*') {
++end;
arg_extras++;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -94,8 +87,7 @@ SHIM_CALL DbgPrint_shim(
if (*end == '*') {
++end;
++arg_extras;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -115,28 +107,23 @@ SHIM_CALL DbgPrint_shim(
if (*end == 'h') {
++end;
}
}
else if (*end == 'l') {
} else if (*end == 'l') {
++end;
arg_size = 4;
if (*end == 'l') {
++end;
arg_size = 8;
}
}
else if (*end == 'j') {
} else if (*end == 'j') {
arg_size = 8;
++end;
}
else if (*end == 'z') {
} else if (*end == 'z') {
arg_size = 4;
++end;
}
else if (*end == 't') {
} else if (*end == 't') {
arg_size = 8;
++end;
}
else if (*end == 'L') {
} else if (*end == 'L') {
arg_size = 8;
++end;
}
@ -145,21 +132,10 @@ SHIM_CALL DbgPrint_shim(
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') {
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);
@ -167,47 +143,42 @@ SHIM_CALL DbgPrint_shim(
assert_true(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));
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 {
} else {
assert_true(false);
}
}
else if (arg_size == 4) {
} 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));
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 {
} else {
assert_true(false);
}
}
}
else if (*end == 'n')
{
} else if (*end == 'n') {
assert_true(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));
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
? SHIM_GET_ARG_32(1 + arg_index)
: (uint32_t)SHIM_MEM_64(SHIM_GPR_32(1) + 16 +
((1 + arg_index) * 8));
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else if (*end == 's' ||
*end == 'p') {
} else if (*end == 's' || *end == 'p') {
char local[512];
local[0] = '\0';
strncat(local, start, end + 1 - start);
@ -215,18 +186,17 @@ SHIM_CALL DbgPrint_shim(
assert_true(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 void *pointer = (const void *)SHIM_MEM_ADDR(value);
? SHIM_GET_ARG_32(1 + arg_index)
: (uint32_t)SHIM_MEM_64(SHIM_GPR_32(1) + 16 +
((1 + arg_index) * 8));
const void* pointer = (const void*)SHIM_MEM_ADDR(value);
int result = sprintf(b, local, pointer);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else {
} else {
assert_true(false);
break;
}
@ -238,16 +208,12 @@ SHIM_CALL DbgPrint_shim(
XELOGD("(DbgPrint) %s", buffer);
}
SHIM_CALL DbgBreakPoint_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL DbgBreakPoint_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("DbgBreakPoint()");
DebugBreak();
}
SHIM_CALL RtlRaiseException_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlRaiseException_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t record_ptr = SHIM_GET_ARG_32(0);
uint32_t code = SHIM_MEM_32(record_ptr + 0);
@ -255,9 +221,7 @@ SHIM_CALL RtlRaiseException_shim(
// ...
uint32_t param_count = SHIM_MEM_32(record_ptr + 16);
XELOGD(
"RtlRaiseException(%.8X(%.8X))",
record_ptr, code);
XELOGD("RtlRaiseException(%.8X(%.8X))", record_ptr, code);
if (code == 0x406D1388) {
// SetThreadName. FFS.
@ -294,22 +258,21 @@ SHIM_CALL RtlRaiseException_shim(
DebugBreak();
}
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);
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);
fflush(stdout);
DebugBreak();
assert_always();
}
SHIM_CALL KeBugCheck_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL KeBugCheck_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t code = SHIM_GET_ARG_32(0);
xeKeBugCheckEx(code, 0, 0, 0, 0);
}
SHIM_CALL KeBugCheckEx_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL KeBugCheckEx_shim(PPCContext* 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);
@ -318,13 +281,11 @@ SHIM_CALL KeBugCheckEx_shim(
xeKeBugCheckEx(code, param1, param2, param3, param4);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterDebugExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xboxkrnl::RegisterDebugExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", DbgPrint, state);
SHIM_SET_MAPPING("xboxkrnl.exe", DbgBreakPoint, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlRaiseException, state);

View File

@ -14,18 +14,13 @@
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL HalReturnToFirmware_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL HalReturnToFirmware_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t routine = SHIM_GET_ARG_32(0);
XELOGD(
"HalReturnToFirmware(%d)",
routine);
XELOGD("HalReturnToFirmware(%d)", routine);
// void
// IN FIRMWARE_REENTRY Routine
@ -39,12 +34,10 @@ SHIM_CALL HalReturnToFirmware_shim(
exit(0);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterHalExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xboxkrnl::RegisterHalExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", HalReturnToFirmware, state);
}

View File

@ -18,15 +18,12 @@
#include <xenia/kernel/util/shim_utils.h>
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
using namespace xe::kernel::fs;
SHIM_CALL NtCreateFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtCreateFile_shim(PPCContext* 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);
@ -40,19 +37,13 @@ SHIM_CALL NtCreateFile_shim(
char* object_name = attrs.object_name.Duplicate();
XELOGD(
"NtCreateFile(%.8X, %.8X, %.8X(%s), %.8X, %.8X, %.8X, %d, %d)",
handle_ptr,
desired_access,
object_attributes_ptr,
!object_name ? "(null)" : object_name,
io_status_block_ptr,
allocation_size_ptr,
file_attributes,
share_access,
creation_disposition);
XELOGD("NtCreateFile(%.8X, %.8X, %.8X(%s), %.8X, %.8X, %.8X, %d, %d)",
handle_ptr, desired_access, object_attributes_ptr,
!object_name ? "(null)" : object_name, io_status_block_ptr,
allocation_size_ptr, file_attributes, share_access,
creation_disposition);
uint64_t allocation_size = 0; // is this correct???
uint64_t allocation_size = 0; // is this correct???
if (allocation_size_ptr != 0) {
allocation_size = SHIM_MEM_64(allocation_size_ptr);
}
@ -65,18 +56,17 @@ SHIM_CALL NtCreateFile_shim(
Entry* entry;
XFile* root_file = NULL;
if (attrs.root_directory != 0xFFFFFFFD && // ObDosDevices
if (attrs.root_directory != 0xFFFFFFFD && // ObDosDevices
attrs.root_directory != 0) {
result = state->object_table()->GetObject(
attrs.root_directory, (XObject**)&root_file);
result = state->object_table()->GetObject(attrs.root_directory,
(XObject**)&root_file);
assert_true(XSUCCEEDED(result));
assert_true(root_file->type() == XObject::Type::kTypeFile);
auto root_path = root_file->absolute_path();
auto target_path = root_path + object_name;
entry = fs->ResolvePath(target_path);
}
else {
} else {
// Resolve the file using the virtual file system.
entry = fs->ResolvePath(object_name);
}
@ -87,11 +77,9 @@ SHIM_CALL NtCreateFile_shim(
XFile* file = NULL;
if (entry && entry->type() == Entry::Type::FILE) {
// Open the file.
result = entry->Open(
state,
mode,
false, // TODO(benvanik): pick async mode, if needed.
&file);
result = entry->Open(state, mode,
false, // TODO(benvanik): pick async mode, if needed.
&file);
} else {
result = X_STATUS_NO_SUCH_FILE;
info = X_FILE_DOES_NOT_EXIST;
@ -101,13 +89,13 @@ SHIM_CALL NtCreateFile_shim(
// Handle ref is incremented, so return that.
handle = file->handle();
file->Release();
result = X_STATUS_SUCCESS;
info = X_FILE_OPENED;
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
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) {
@ -119,8 +107,7 @@ SHIM_CALL NtCreateFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtOpenFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtOpenFile_shim(PPCContext* 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);
@ -131,23 +118,19 @@ SHIM_CALL NtOpenFile_shim(
char* object_name = attrs.object_name.Duplicate();
XELOGD(
"NtOpenFile(%.8X, %.8X, %.8X(%s), %.8X, %d)",
handle_ptr,
desired_access,
object_attributes_ptr,
!object_name ? "(null)" : object_name,
io_status_block_ptr,
open_options);
XELOGD("NtOpenFile(%.8X, %.8X, %.8X(%s), %.8X, %d)", handle_ptr,
desired_access, object_attributes_ptr,
!object_name ? "(null)" : object_name, io_status_block_ptr,
open_options);
X_STATUS result = X_STATUS_NO_SUCH_FILE;
uint32_t info = X_FILE_DOES_NOT_EXIST;
uint32_t handle;
XFile* root_file = NULL;
if (attrs.root_directory != 0xFFFFFFFD) { // ObDosDevices
result = state->object_table()->GetObject(
attrs.root_directory, (XObject**)&root_file);
if (attrs.root_directory != 0xFFFFFFFD) { // ObDosDevices
result = state->object_table()->GetObject(attrs.root_directory,
(XObject**)&root_file);
assert_true(XSUCCEEDED(result));
assert_true(root_file->type() == XObject::Type::kTypeFile);
assert_always();
@ -162,13 +145,10 @@ SHIM_CALL NtOpenFile_shim(
XFile* file = NULL;
if (entry && entry->type() == Entry::Type::FILE) {
// Open the file.
result = entry->Open(
state,
mode,
false, // TODO(benvanik): pick async mode, if needed.
&file);
}
else {
result = entry->Open(state, mode,
false, // TODO(benvanik): pick async mode, if needed.
&file);
} else {
result = X_STATUS_NO_SUCH_FILE;
info = X_FILE_DOES_NOT_EXIST;
}
@ -182,8 +162,8 @@ SHIM_CALL NtOpenFile_shim(
}
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
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) {
@ -196,7 +176,7 @@ SHIM_CALL NtOpenFile_shim(
}
class xeNtReadFileState {
public:
public:
uint32_t x;
};
void xeNtReadFileCompleted(XAsyncRequest* request, xeNtReadFileState* state) {
@ -205,8 +185,7 @@ void xeNtReadFileCompleted(XAsyncRequest* request, xeNtReadFileState* state) {
delete state;
}
SHIM_CALL NtReadFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtReadFile_shim(PPCContext* 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);
@ -217,17 +196,10 @@ SHIM_CALL NtReadFile_shim(
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, %.8X(%d))",
file_handle,
event_handle,
apc_routine_ptr,
apc_context,
io_status_block_ptr,
buffer,
buffer_length,
byte_offset_ptr,
byte_offset);
XELOGD("NtReadFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %.8X(%d))",
file_handle, event_handle, apc_routine_ptr, apc_context,
io_status_block_ptr, buffer, buffer_length, byte_offset_ptr,
byte_offset);
// Async not supported yet.
assert_zero(apc_routine_ptr);
@ -239,15 +211,13 @@ SHIM_CALL NtReadFile_shim(
XEvent* ev = NULL;
bool signal_event = false;
if (event_handle) {
result = state->object_table()->GetObject(
event_handle, (XObject**)&ev);
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);
result = state->object_table()->GetObject(file_handle, (XObject**)&file);
}
// Execute read.
@ -260,17 +230,15 @@ SHIM_CALL NtReadFile_shim(
// TODO(benvanik): async path.
if (true) {
// Synchronous request.
if (!byte_offset_ptr ||
byte_offset == 0xFFFFFFFFfffffffe) {
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);
result = file->Read(SHIM_MEM_ADDR(buffer), buffer_length, byte_offset,
&bytes_read);
if (XSUCCEEDED(result)) {
info = (int32_t)bytes_read;
}
@ -287,15 +255,15 @@ SHIM_CALL NtReadFile_shim(
state, file,
(XAsyncRequest::CompletionCallback)xeNtReadFileCompleted,
call_state);*/
//result = file->Read(buffer, buffer_length, byte_offset, request);
// 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
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
}
if (file) {
@ -311,46 +279,39 @@ SHIM_CALL NtReadFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtSetInformationFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtSetInformationFile_shim(PPCContext* 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);
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);
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;
// };
assert_true(length == 8);
info = 8;
file->set_position(SHIM_MEM_64(file_info_ptr));
break;
default:
// Unsupported, for now.
assert_always();
info = 0;
break;
case XFilePositionInformation:
// struct FILE_POSITION_INFORMATION {
// LARGE_INTEGER CurrentByteOffset;
// };
assert_true(length == 8);
info = 8;
file->set_position(SHIM_MEM_64(file_info_ptr));
break;
default:
// Unsupported, for now.
assert_always();
info = 0;
break;
}
}
@ -358,8 +319,8 @@ SHIM_CALL NtSetInformationFile_shim(
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
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
}
if (file) {
@ -369,91 +330,85 @@ SHIM_CALL NtSetInformationFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtQueryInformationFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtQueryInformationFile_shim(PPCContext* 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);
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);
result = state->object_table()->GetObject(file_handle, (XObject**)&file);
if (XSUCCEEDED(result)) {
result = X_STATUS_SUCCESS;
switch (file_info_class) {
case XFileInternalInformation:
// Internal unique file pointer. Not sure why anyone would want this.
assert_true(length == 8);
info = 8;
// TODO(benvanik): use pointer to fs:: entry?
SHIM_SET_MEM_64(file_info_ptr, hash_combine(0, file->absolute_path()));
break;
case XFilePositionInformation:
// struct FILE_POSITION_INFORMATION {
// LARGE_INTEGER CurrentByteOffset;
// };
assert_true(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;
// };
assert_true(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;
case XFileXctdCompressionInformation:
// Read timeout.
if (length == 4) {
uint32_t magic;
size_t bytes_read;
result = file->Read(&magic, sizeof(magic), 0, &bytes_read);
case XFileInternalInformation:
// Internal unique file pointer. Not sure why anyone would want this.
assert_true(length == 8);
info = 8;
// TODO(benvanik): use pointer to fs:: entry?
SHIM_SET_MEM_64(file_info_ptr, hash_combine(0, file->absolute_path()));
break;
case XFilePositionInformation:
// struct FILE_POSITION_INFORMATION {
// LARGE_INTEGER CurrentByteOffset;
// };
assert_true(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;
// };
assert_true(length == 56);
XFileInfo file_info;
result = file->QueryInfo(&file_info);
if (XSUCCEEDED(result)) {
if (bytes_read == sizeof(magic)) {
info = 4;
SHIM_SET_MEM_32(file_info_ptr, magic == poly::byte_swap(0x0FF512ED));
}
else {
result = X_STATUS_UNSUCCESSFUL;
}
info = 56;
file_info.Write(SHIM_MEM_BASE, file_info_ptr);
}
} else {
result = X_STATUS_INFO_LENGTH_MISMATCH;
}
break;
default:
// Unsupported, for now.
assert_always();
info = 0;
break;
break;
case XFileXctdCompressionInformation:
// Read timeout.
if (length == 4) {
uint32_t magic;
size_t bytes_read;
result = file->Read(&magic, sizeof(magic), 0, &bytes_read);
if (XSUCCEEDED(result)) {
if (bytes_read == sizeof(magic)) {
info = 4;
SHIM_SET_MEM_32(file_info_ptr,
magic == poly::byte_swap(0x0FF512ED));
} else {
result = X_STATUS_UNSUCCESSFUL;
}
}
} else {
result = X_STATUS_INFO_LENGTH_MISMATCH;
}
break;
default:
// Unsupported, for now.
assert_always();
info = 0;
break;
}
}
@ -461,8 +416,8 @@ SHIM_CALL NtQueryInformationFile_shim(
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
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
}
if (file) {
@ -472,8 +427,8 @@ SHIM_CALL NtQueryInformationFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtQueryFullAttributesFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtQueryFullAttributesFile_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t object_attributes_ptr = SHIM_GET_ARG_32(0);
uint32_t file_info_ptr = SHIM_GET_ARG_32(1);
@ -481,18 +436,15 @@ SHIM_CALL NtQueryFullAttributesFile_shim(
char* object_name = attrs.object_name.Duplicate();
XELOGD(
"NtQueryFullAttributesFile(%.8X(%s), %.8X)",
object_attributes_ptr,
!object_name ? "(null)" : object_name,
file_info_ptr);
XELOGD("NtQueryFullAttributesFile(%.8X(%s), %.8X)", object_attributes_ptr,
!object_name ? "(null)" : object_name, file_info_ptr);
X_STATUS result = X_STATUS_NO_SUCH_FILE;
XFile* root_file = NULL;
if (attrs.root_directory != 0xFFFFFFFD) { // ObDosDevices
result = state->object_table()->GetObject(
attrs.root_directory, (XObject**)&root_file);
if (attrs.root_directory != 0xFFFFFFFD) { // ObDosDevices
result = state->object_table()->GetObject(attrs.root_directory,
(XObject**)&root_file);
assert_true(XSUCCEEDED(result));
assert_true(root_file->type() == XObject::Type::kTypeFile);
assert_always();
@ -514,59 +466,52 @@ SHIM_CALL NtQueryFullAttributesFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtQueryVolumeInformationFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtQueryVolumeInformationFile_shim(PPCContext* 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 fs_info_ptr = SHIM_GET_ARG_32(2);
uint32_t length = SHIM_GET_ARG_32(3);
uint32_t fs_info_class = SHIM_GET_ARG_32(4);
XELOGD(
"NtQueryVolumeInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
file_handle,
io_status_block_ptr,
fs_info_ptr,
length,
fs_info_class);
XELOGD("NtQueryVolumeInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
file_handle, io_status_block_ptr, fs_info_ptr, length, fs_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);
result = state->object_table()->GetObject(file_handle, (XObject**)&file);
if (XSUCCEEDED(result)) {
result = X_STATUS_SUCCESS;
switch (fs_info_class) {
case 1: { // FileFsVolumeInformation
auto volume_info = (XVolumeInfo*)xe_calloc(length);
result = file->QueryVolume(volume_info, length);
if (XSUCCEEDED(result)) {
volume_info->Write(SHIM_MEM_BASE, fs_info_ptr);
info = length;
case 1: { // FileFsVolumeInformation
auto volume_info = (XVolumeInfo*)xe_calloc(length);
result = file->QueryVolume(volume_info, length);
if (XSUCCEEDED(result)) {
volume_info->Write(SHIM_MEM_BASE, fs_info_ptr);
info = length;
}
xe_free(volume_info);
break;
}
xe_free(volume_info);
break;
}
case 5: { // FileFsAttributeInformation
auto fs_attribute_info = (XFileSystemAttributeInfo*)xe_calloc(length);
result = file->QueryFileSystemAttributes(fs_attribute_info, length);
if (XSUCCEEDED(result)) {
fs_attribute_info->Write(SHIM_MEM_BASE, fs_info_ptr);
info = length;
case 5: { // FileFsAttributeInformation
auto fs_attribute_info = (XFileSystemAttributeInfo*)xe_calloc(length);
result = file->QueryFileSystemAttributes(fs_attribute_info, length);
if (XSUCCEEDED(result)) {
fs_attribute_info->Write(SHIM_MEM_BASE, fs_info_ptr);
info = length;
}
xe_free(fs_attribute_info);
break;
}
xe_free(fs_attribute_info);
break;
}
default:
// Unsupported, for now.
assert_always();
info = 0;
break;
default:
// Unsupported, for now.
assert_always();
info = 0;
break;
}
}
@ -574,8 +519,8 @@ SHIM_CALL NtQueryVolumeInformationFile_shim(
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
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
}
if (file) {
@ -585,8 +530,7 @@ SHIM_CALL NtQueryVolumeInformationFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtQueryDirectoryFile_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtQueryDirectoryFile_shim(PPCContext* 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 = SHIM_GET_ARG_32(2);
@ -605,16 +549,10 @@ SHIM_CALL NtQueryDirectoryFile_shim(
}
XELOGD(
"NtQueryDirectoryFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %.8X(%s), %d)",
file_handle,
event_handle,
apc_routine,
apc_context,
io_status_block_ptr,
file_info_ptr,
length,
file_name_ptr,
!file_name ? "(null)" : file_name,
"NtQueryDirectoryFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %.8X(%s), "
"%d)",
file_handle, event_handle, apc_routine, apc_context, io_status_block_ptr,
file_info_ptr, length, file_name_ptr, !file_name ? "(null)" : file_name,
restart_scan);
if (length < 72) {
@ -627,11 +565,11 @@ SHIM_CALL NtQueryDirectoryFile_shim(
uint32_t info = 0;
XFile* file = NULL;
result = state->object_table()->GetObject(
file_handle, (XObject**)&file);
result = state->object_table()->GetObject(file_handle, (XObject**)&file);
if (XSUCCEEDED(result)) {
XDirectoryInfo* dir_info = (XDirectoryInfo*)xe_calloc(length);
result = file->QueryDirectory(dir_info, length, file_name, restart_scan != 0);
result =
file->QueryDirectory(dir_info, length, file_name, restart_scan != 0);
if (XSUCCEEDED(result)) {
dir_info->Write(SHIM_MEM_BASE, file_info_ptr);
info = length;
@ -643,8 +581,8 @@ SHIM_CALL NtQueryDirectoryFile_shim(
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
SHIM_SET_MEM_32(io_status_block_ptr, result); // Status
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
}
if (file) {
@ -655,27 +593,23 @@ SHIM_CALL NtQueryDirectoryFile_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL FscSetCacheElementCount_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL FscSetCacheElementCount_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t unk_0 = SHIM_GET_ARG_32(0);
uint32_t unk_1 = SHIM_GET_ARG_32(1);
// unk_0 = 0
// unk_1 looks like a count? in what units? 256 is a common value
XELOGD(
"FscSetCacheElementCount(%.8X, %.8X)",
unk_0, unk_1);
XELOGD("FscSetCacheElementCount(%.8X, %.8X)", unk_0, unk_1);
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterIoExports(
ExportResolver* export_resolver, KernelState* state) {
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);

View File

@ -15,26 +15,22 @@
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL NtAllocateVirtualMemory_shim(PPCContext* 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);
SHIM_CALL NtAllocateVirtualMemory_shim(
PPCContext* 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);
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);
// NTSTATUS
// _Inout_ PVOID *BaseAddress,
@ -68,7 +64,7 @@ SHIM_CALL NtAllocateVirtualMemory_shim(
}
// 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)) {
X_PAGE_EXECUTE_READWRITE | X_PAGE_EXECUTE_WRITECOPY)) {
SHIM_SET_RETURN_32(X_STATUS_ACCESS_DENIED);
return;
}
@ -83,7 +79,7 @@ SHIM_CALL NtAllocateVirtualMemory_shim(
if (base_addr_value) {
// Having a pointer already means that this is likely a follow-on COMMIT.
assert_true(!(allocation_type & X_MEM_RESERVE) &&
(allocation_type & X_MEM_COMMIT));
(allocation_type & X_MEM_COMMIT));
SHIM_SET_MEM_32(base_addr_ptr, base_addr_value);
SHIM_SET_MEM_32(region_size_ptr, adjusted_size);
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
@ -92,8 +88,8 @@ SHIM_CALL NtAllocateVirtualMemory_shim(
// Allocate.
uint32_t flags = (allocation_type & X_MEM_NOZERO);
uint32_t addr = (uint32_t)state->memory()->HeapAlloc(
base_addr_value, adjusted_size, flags);
uint32_t addr = (uint32_t)state->memory()->HeapAlloc(base_addr_value,
adjusted_size, flags);
if (!addr) {
// Failed - assume no memory available.
SHIM_SET_RETURN_32(X_STATUS_NO_MEMORY);
@ -107,22 +103,18 @@ SHIM_CALL NtAllocateVirtualMemory_shim(
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
}
SHIM_CALL NtFreeVirtualMemory_shim(
PPCContext* 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);
SHIM_CALL NtFreeVirtualMemory_shim(PPCContext* 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);
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);
XELOGD("NtFreeVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X)",
base_addr_ptr, base_addr_value, region_size_ptr, region_size_value,
free_type, unknown);
// NTSTATUS
// _Inout_ PVOID *BaseAddress,
@ -146,8 +138,7 @@ SHIM_CALL NtFreeVirtualMemory_shim(
// Free.
uint32_t flags = 0;
uint32_t freed_size = state->memory()->HeapFree(
base_addr_value, flags);
uint32_t freed_size = state->memory()->HeapFree(base_addr_value, flags);
if (!freed_size) {
SHIM_SET_RETURN_32(X_STATUS_UNSUCCESSFUL);
return;
@ -158,15 +149,14 @@ SHIM_CALL NtFreeVirtualMemory_shim(
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
}
SHIM_CALL NtQueryVirtualMemory_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtQueryVirtualMemory_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t base_address = SHIM_GET_ARG_32(0);
uint32_t memory_basic_information_ptr = SHIM_GET_ARG_32(1);
X_MEMORY_BASIC_INFORMATION *memory_basic_information = (X_MEMORY_BASIC_INFORMATION*)SHIM_MEM_ADDR(memory_basic_information_ptr);
X_MEMORY_BASIC_INFORMATION* memory_basic_information =
(X_MEMORY_BASIC_INFORMATION*)SHIM_MEM_ADDR(memory_basic_information_ptr);
XELOGD(
"NtQueryVirtualMemory(%.8X, %.8X)",
base_address, memory_basic_information_ptr);
XELOGD("NtQueryVirtualMemory(%.8X, %.8X)", base_address,
memory_basic_information_ptr);
MEMORY_BASIC_INFORMATION mem_info;
size_t result = state->memory()->QueryInformation(base_address, &mem_info);
@ -208,9 +198,8 @@ SHIM_CALL NtQueryVirtualMemory_shim(
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
}
SHIM_CALL MmAllocatePhysicalMemoryEx_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL MmAllocatePhysicalMemoryEx_shim(PPCContext* 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);
@ -218,10 +207,8 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(
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);
XELOGD("MmAllocatePhysicalMemoryEx(%d, %.8X, %.8X, %.8X, %.8X, %.8X)", type,
region_size, protect_bits, min_addr_range, max_addr_range, alignment);
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
// by D3D/etc.
@ -273,7 +260,7 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(
}
// Move the address into the right range.
//if (protect_bits & X_MEM_LARGE_PAGES) {
// if (protect_bits & X_MEM_LARGE_PAGES) {
// base_address += 0xA0000000;
//} else if (protect_bits & X_MEM_16MB_PAGES) {
// base_address += 0xC0000000;
@ -285,16 +272,12 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(
SHIM_SET_RETURN_32(base_address);
}
SHIM_CALL MmFreePhysicalMemory_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL MmFreePhysicalMemory_shim(PPCContext* 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);
XELOGD("MmFreePhysicalAddress(%d, %.8X)", type, base_address);
// base_address = result of MmAllocatePhysicalMemory.
// Strip off physical bits before passing down.
@ -302,47 +285,37 @@ SHIM_CALL MmFreePhysicalMemory_shim(
// TODO(benvanik): free memory.
XELOGE("xeMmFreePhysicalMemory NOT IMPLEMENTED");
//uint32_t size = ?;
//xe_memory_heap_free(
// uint32_t size = ?;
// xe_memory_heap_free(
// state->memory(), base_address, size);
}
SHIM_CALL MmQueryAddressProtect_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL MmQueryAddressProtect_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t base_address = SHIM_GET_ARG_32(0);
XELOGD(
"MmQueryAddressProtect(%.8X)",
base_address);
XELOGD("MmQueryAddressProtect(%.8X)", base_address);
uint32_t access = state->memory()->QueryProtect(base_address);
SHIM_SET_RETURN_32(access);
}
SHIM_CALL MmQueryAllocationSize_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL MmQueryAllocationSize_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t base_address = SHIM_GET_ARG_32(0);
XELOGD(
"MmQueryAllocationSize(%.8X)",
base_address);
XELOGD("MmQueryAllocationSize(%.8X)", base_address);
size_t size = state->memory()->QuerySize(base_address);
SHIM_SET_RETURN_32(static_cast<uint32_t>(size));
}
SHIM_CALL MmQueryStatistics_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL MmQueryStatistics_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t stats_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"MmQueryStatistics(%.8X)",
stats_ptr);
XELOGD("MmQueryStatistics(%.8X)", stats_ptr);
uint32_t size = SHIM_MEM_32(stats_ptr + 0);
if (size != 104) {
@ -361,45 +334,45 @@ SHIM_CALL MmQueryStatistics_shim(
// memory, this should satisfy it. If it's actually verifying things
// this won't work :/
// https://code.google.com/p/vdash/source/browse/trunk/vdash/include/kernel.h
SHIM_SET_MEM_32(stats_ptr + 4 * 1, 0x00020000); // TotalPhysicalPages
SHIM_SET_MEM_32(stats_ptr + 4 * 2, 0x00000300); // KernelPages
SHIM_SET_MEM_32(stats_ptr + 4 * 3, 0x00020000); // TitleAvailablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 4, 0x2FFF0000); // TitleTotalVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 5, 0x00160000); // TitleReservedVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 6, 0x00001000); // TitlePhysicalPages
SHIM_SET_MEM_32(stats_ptr + 4 * 7, 0x00000010); // TitlePoolPages
SHIM_SET_MEM_32(stats_ptr + 4 * 8, 0x00000100); // TitleStackPages
SHIM_SET_MEM_32(stats_ptr + 4 * 9, 0x00000100); // TitleImagePages
SHIM_SET_MEM_32(stats_ptr + 4 * 10, 0x00000100); // TitleHeapPages
SHIM_SET_MEM_32(stats_ptr + 4 * 11, 0x00000100); // TitleVirtualPages
SHIM_SET_MEM_32(stats_ptr + 4 * 12, 0x00000100); // TitlePageTablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 13, 0x00000100); // TitleCachePages
SHIM_SET_MEM_32(stats_ptr + 4 * 14, 0x00000000); // SystemAvailablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 15, 0x00000000); // SystemTotalVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 16, 0x00000000); // SystemReservedVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 17, 0x00000000); // SystemPhysicalPages
SHIM_SET_MEM_32(stats_ptr + 4 * 18, 0x00000000); // SystemPoolPages
SHIM_SET_MEM_32(stats_ptr + 4 * 19, 0x00000000); // SystemStackPages
SHIM_SET_MEM_32(stats_ptr + 4 * 20, 0x00000000); // SystemImagePages
SHIM_SET_MEM_32(stats_ptr + 4 * 21, 0x00000000); // SystemHeapPages
SHIM_SET_MEM_32(stats_ptr + 4 * 22, 0x00000000); // SystemVirtualPages
SHIM_SET_MEM_32(stats_ptr + 4 * 23, 0x00000000); // SystemPageTablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 24, 0x00000000); // SystemCachePages
SHIM_SET_MEM_32(stats_ptr + 4 * 25, 0x0001FFFF); // HighestPhysicalPage
SHIM_SET_MEM_32(stats_ptr + 4 * 1, 0x00020000); // TotalPhysicalPages
SHIM_SET_MEM_32(stats_ptr + 4 * 2, 0x00000300); // KernelPages
SHIM_SET_MEM_32(stats_ptr + 4 * 3, 0x00020000); // TitleAvailablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 4,
0x2FFF0000); // TitleTotalVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 5,
0x00160000); // TitleReservedVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 6, 0x00001000); // TitlePhysicalPages
SHIM_SET_MEM_32(stats_ptr + 4 * 7, 0x00000010); // TitlePoolPages
SHIM_SET_MEM_32(stats_ptr + 4 * 8, 0x00000100); // TitleStackPages
SHIM_SET_MEM_32(stats_ptr + 4 * 9, 0x00000100); // TitleImagePages
SHIM_SET_MEM_32(stats_ptr + 4 * 10, 0x00000100); // TitleHeapPages
SHIM_SET_MEM_32(stats_ptr + 4 * 11, 0x00000100); // TitleVirtualPages
SHIM_SET_MEM_32(stats_ptr + 4 * 12, 0x00000100); // TitlePageTablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 13, 0x00000100); // TitleCachePages
SHIM_SET_MEM_32(stats_ptr + 4 * 14, 0x00000000); // SystemAvailablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 15,
0x00000000); // SystemTotalVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 16,
0x00000000); // SystemReservedVirtualMemoryBytes
SHIM_SET_MEM_32(stats_ptr + 4 * 17, 0x00000000); // SystemPhysicalPages
SHIM_SET_MEM_32(stats_ptr + 4 * 18, 0x00000000); // SystemPoolPages
SHIM_SET_MEM_32(stats_ptr + 4 * 19, 0x00000000); // SystemStackPages
SHIM_SET_MEM_32(stats_ptr + 4 * 20, 0x00000000); // SystemImagePages
SHIM_SET_MEM_32(stats_ptr + 4 * 21, 0x00000000); // SystemHeapPages
SHIM_SET_MEM_32(stats_ptr + 4 * 22, 0x00000000); // SystemVirtualPages
SHIM_SET_MEM_32(stats_ptr + 4 * 23, 0x00000000); // SystemPageTablePages
SHIM_SET_MEM_32(stats_ptr + 4 * 24, 0x00000000); // SystemCachePages
SHIM_SET_MEM_32(stats_ptr + 4 * 25, 0x0001FFFF); // HighestPhysicalPage
SHIM_SET_RETURN_32(result);
}
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx
SHIM_CALL MmGetPhysicalAddress_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL MmGetPhysicalAddress_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t base_address = SHIM_GET_ARG_32(0);
XELOGD(
"MmGetPhysicalAddress(%.8X)",
base_address);
XELOGD("MmGetPhysicalAddress(%.8X)", base_address);
// PHYSICAL_ADDRESS MmGetPhysicalAddress(
// _In_ PVOID BaseAddress
// );
@ -420,16 +393,13 @@ SHIM_CALL MmGetPhysicalAddress_shim(
SHIM_SET_RETURN_32(base_address);
}
SHIM_CALL ExAllocatePoolTypeWithTag_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL ExAllocatePoolTypeWithTag_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t size = SHIM_GET_ARG_32(0);
uint32_t tag = SHIM_GET_ARG_32(1);
uint32_t zero = SHIM_GET_ARG_32(2);
XELOGD(
"ExAllocatePoolTypeWithTag(%d, %.8X, %d)",
size, tag, zero);
XELOGD("ExAllocatePoolTypeWithTag(%d, %.8X, %d)", size, tag, zero);
uint32_t alignment = 8;
uint32_t adjusted_size = size;
@ -445,48 +415,36 @@ SHIM_CALL ExAllocatePoolTypeWithTag_shim(
SHIM_SET_RETURN_32(addr);
}
SHIM_CALL ExFreePool_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL ExFreePool_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t base_address = SHIM_GET_ARG_32(0);
XELOGD(
"ExFreePool(%.8X)",
base_address);
XELOGD("ExFreePool(%.8X)", base_address);
state->memory()->HeapFree(base_address, 0);
}
SHIM_CALL KeLockL2_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL KeLockL2_shim(PPCContext* ppc_state, KernelState* state) {
// Ignored for now. This is just a perf optimization, I think.
// It may be useful as a hint for CPU-GPU transfer.
XELOGD(
"KeLockL2(?)");
XELOGD("KeLockL2(?)");
SHIM_SET_RETURN_32(0);
}
SHIM_CALL KeUnlockL2_shim(
PPCContext* ppc_state, KernelState* state) {
XELOGD(
"KeUnlockL2(?)");
SHIM_CALL KeUnlockL2_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("KeUnlockL2(?)");
}
} // 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", NtQueryVirtualMemory, state);
//SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemory, 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);

View File

@ -15,24 +15,20 @@
#include <xenia/kernel/objects/xthread.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL KeEnableFpuExceptions_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL KeEnableFpuExceptions_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t enabled = SHIM_GET_ARG_32(0);
XELOGD("KeEnableFpuExceptions(%d)", enabled);
// TODO(benvanik): can we do anything about exceptions?
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterMiscExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xboxkrnl::RegisterMiscExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnableFpuExceptions, state);
}

View File

@ -17,23 +17,20 @@
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/objects/xuser_module.h>
DEFINE_bool(abort_before_entry, false,
"Abort execution right before launching the module.");
"Abort execution right before launching the module.");
namespace xe {
namespace kernel {
XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) :
XKernelModule(kernel_state, "xe:\\xboxkrnl.exe") {
// Build the export table used for resolution.
#include <xenia/kernel/util/export_table_pre.inc>
XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
: XKernelModule(kernel_state, "xe:\\xboxkrnl.exe") {
// Build the export table used for resolution.
#include <xenia/kernel/util/export_table_pre.inc>
static KernelExport xboxkrnl_export_table[] = {
#include <xenia/kernel/xboxkrnl_table.inc>
#include <xenia/kernel/xboxkrnl_table.inc>
};
#include <xenia/kernel/util/export_table_post.inc>
#include <xenia/kernel/util/export_table_post.inc>
export_resolver_->RegisterTable("xboxkrnl.exe", xboxkrnl_export_table,
poly::countof(xboxkrnl_export_table));
@ -60,16 +57,14 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) :
// arguments. If we wanted to see what would happen we could fake that.
uint32_t pKeDebugMonitorData = (uint32_t)memory_->HeapAlloc(0, 256, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::KeDebugMonitorData,
pKeDebugMonitorData);
"xboxkrnl.exe", ordinals::KeDebugMonitorData, pKeDebugMonitorData);
poly::store_and_swap<uint32_t>(mem + pKeDebugMonitorData, 0);
// KeCertMonitorData (?*)
// Always set to zero, ignored.
uint32_t pKeCertMonitorData = (uint32_t)memory_->HeapAlloc(0, 4, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::KeCertMonitorData,
pKeCertMonitorData);
"xboxkrnl.exe", ordinals::KeCertMonitorData, pKeCertMonitorData);
poly::store_and_swap<uint32_t>(mem + pKeCertMonitorData, 0);
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
@ -79,10 +74,11 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) :
// was whether an HDD was present. Not sure what the other flags are.
uint32_t pXboxHardwareInfo = (uint32_t)memory_->HeapAlloc(0, 16, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::XboxHardwareInfo,
pXboxHardwareInfo);
poly::store_and_swap<uint32_t>(mem + pXboxHardwareInfo + 0, 0x00000000); // flags
poly::store_and_swap<uint8_t> (mem + pXboxHardwareInfo + 4, 0x06); // cpu count
"xboxkrnl.exe", ordinals::XboxHardwareInfo, pXboxHardwareInfo);
poly::store_and_swap<uint32_t>(mem + pXboxHardwareInfo + 0,
0x00000000); // flags
poly::store_and_swap<uint8_t>(mem + pXboxHardwareInfo + 4,
0x06); // cpu count
// Remaining 11b are zeroes?
// XexExecutableModuleHandle (?**)
@ -95,13 +91,14 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) :
// 0x80101058 <- pointer to xex header
// 0x80101100 <- xex header base
uint32_t ppXexExecutableModuleHandle = (uint32_t)memory_->HeapAlloc(0, 4, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::XexExecutableModuleHandle,
ppXexExecutableModuleHandle);
uint32_t pXexExecutableModuleHandle =
(uint32_t)memory_->HeapAlloc(0, 256, 0);
poly::store_and_swap<uint32_t>(mem + ppXexExecutableModuleHandle, pXexExecutableModuleHandle);
poly::store_and_swap<uint32_t>(mem + pXexExecutableModuleHandle + 0x58, 0x80101100);
export_resolver_->SetVariableMapping("xboxkrnl.exe",
ordinals::XexExecutableModuleHandle,
ppXexExecutableModuleHandle);
uint32_t pXexExecutableModuleHandle = (uint32_t)memory_->HeapAlloc(0, 256, 0);
poly::store_and_swap<uint32_t>(mem + ppXexExecutableModuleHandle,
pXexExecutableModuleHandle);
poly::store_and_swap<uint32_t>(mem + pXexExecutableModuleHandle + 0x58,
0x80101100);
// ExLoadedCommandLine (char*)
// The name of the xex. Not sure this is ever really used on real devices.
@ -109,19 +106,17 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) :
// Always set to "default.xex" (with quotes) for now.
uint32_t pExLoadedCommandLine = (uint32_t)memory_->HeapAlloc(0, 1024, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::ExLoadedCommandLine,
pExLoadedCommandLine);
"xboxkrnl.exe", ordinals::ExLoadedCommandLine, pExLoadedCommandLine);
char command_line[] = "\"default.xex\"";
xe_copy_memory(mem + pExLoadedCommandLine, 1024,
command_line, poly::countof(command_line) + 1);
xe_copy_memory(mem + pExLoadedCommandLine, 1024, command_line,
poly::countof(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 = (uint32_t)memory_->HeapAlloc(0, 8, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::XboxKrnlVersion,
pXboxKrnlVersion);
"xboxkrnl.exe", ordinals::XboxKrnlVersion, pXboxKrnlVersion);
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 0, 2);
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 2, 0xFFFF);
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 4, 0xFFFF);
@ -130,15 +125,13 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) :
// KeTimeStampBundle (ad)
uint32_t pKeTimeStampBundle = (uint32_t)memory_->HeapAlloc(0, 24, 0);
export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::KeTimeStampBundle,
pKeTimeStampBundle);
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 0, 0);
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 8, 0);
"xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle);
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 0, 0);
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 8, 0);
poly::store_and_swap<uint32_t>(mem + pKeTimeStampBundle + 12, 0);
}
XboxkrnlModule::~XboxkrnlModule() {
}
XboxkrnlModule::~XboxkrnlModule() {}
int XboxkrnlModule::LaunchModule(const char* path) {
// Create and register the module. We keep it local to this function and

View File

@ -12,7 +12,6 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/export_resolver.h>
#include <xenia/kernel/xboxkrnl_ordinals.h>
#include <xenia/kernel/objects/xkernel_module.h>
@ -20,26 +19,22 @@
// All of the exported functions:
#include <xenia/kernel/xboxkrnl_rtl.h>
namespace xe {
namespace kernel {
class KernelState;
class XboxkrnlModule : public XKernelModule {
public:
public:
XboxkrnlModule(Emulator* emulator, KernelState* kernel_state);
virtual ~XboxkrnlModule();
int LaunchModule(const char* path);
private:
private:
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_MODULE_H_

View File

@ -16,14 +16,12 @@
#include <xenia/kernel/util/shim_utils.h>
#include <xenia/kernel/util/xex2.h>
namespace xe {
namespace kernel {
X_STATUS xeExGetXConfigSetting(
uint16_t category, uint16_t setting, void* buffer, uint16_t buffer_size,
uint16_t* required_size) {
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;
@ -31,58 +29,58 @@ X_STATUS xeExGetXConfigSetting(
// http://free60.org/XConfig
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/Generic/ExConfig.h
switch (category) {
case 0x0002:
// XCONFIG_SECURED_CATEGORY
switch (setting) {
case 0x0002: // XCONFIG_SECURED_AV_REGION
setting_size = 4;
value = 0x00001000; // USA/Canada
case 0x0002:
// XCONFIG_SECURED_CATEGORY
switch (setting) {
case 0x0002: // XCONFIG_SECURED_AV_REGION
setting_size = 4;
value = 0x00001000; // USA/Canada
break;
default:
assert_unhandled_case(setting);
return X_STATUS_INVALID_PARAMETER_2;
}
break;
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:
assert_unhandled_case(setting);
return X_STATUS_INVALID_PARAMETER_2;
}
break;
default:
assert_unhandled_case(setting);
return X_STATUS_INVALID_PARAMETER_2;
}
break;
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:
assert_unhandled_case(setting);
return X_STATUS_INVALID_PARAMETER_2;
}
break;
default:
assert_unhandled_case(category);
return X_STATUS_INVALID_PARAMETER_1;
assert_unhandled_case(category);
return X_STATUS_INVALID_PARAMETER_1;
}
if (buffer_size < setting_size) {
@ -102,23 +100,20 @@ X_STATUS xeExGetXConfigSetting(
return X_STATUS_SUCCESS;
}
SHIM_CALL ExGetXConfigSetting_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL ExGetXConfigSetting_shim(PPCContext* 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);
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);
X_STATUS result = xeExGetXConfigSetting(category, setting, buffer,
buffer_size, &required_size);
if (required_size_ptr) {
SHIM_SET_MEM_16(required_size_ptr, required_size);
@ -127,14 +122,11 @@ SHIM_CALL ExGetXConfigSetting_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XexCheckExecutablePrivilege_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t privilege = SHIM_GET_ARG_32(0);
XELOGD(
"XexCheckExecutablePrivilege(%.8X)",
privilege);
XELOGD("XexCheckExecutablePrivilege(%.8X)", privilege);
// BOOL
// DWORD Privilege
@ -159,16 +151,12 @@ SHIM_CALL XexCheckExecutablePrivilege_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XexGetModuleHandle_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XexGetModuleHandle_shim(PPCContext* 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);
XELOGD("XexGetModuleHandle(%s, %.8X)", module_name, module_handle_ptr);
XModule* module = state->GetModule(module_name);
if (!module) {
@ -184,18 +172,15 @@ SHIM_CALL XexGetModuleHandle_shim(
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XexGetModuleSection_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t name_ptr = SHIM_GET_ARG_32(1);
const char* name = (const char*)SHIM_MEM_ADDR(name_ptr);
uint32_t data_ptr = SHIM_GET_ARG_32(2);
uint32_t size_ptr = SHIM_GET_ARG_32(3);
XELOGD(
"XexGetModuleSection(%.8X, %s, %.8X, %.8X)",
handle, name, data_ptr, size_ptr);
XELOGD("XexGetModuleSection(%.8X, %s, %.8X, %.8X)", handle, name, data_ptr,
size_ptr);
XModule* module = NULL;
X_STATUS result =
@ -215,18 +200,15 @@ SHIM_CALL XexGetModuleSection_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XexLoadImage_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XexLoadImage_shim(PPCContext* 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_flags = SHIM_GET_ARG_32(1);
uint32_t min_version = SHIM_GET_ARG_32(2);
uint32_t handle_ptr = SHIM_GET_ARG_32(3);
XELOGD(
"XexLoadImage(%s, %.8X, %.8X, %.8X)",
module_name, module_flags, min_version, handle_ptr);
XELOGD("XexLoadImage(%s, %.8X, %.8X, %.8X)", module_name, module_flags,
min_version, handle_ptr);
X_STATUS result = X_STATUS_NO_SUCH_FILE;
@ -244,14 +226,10 @@ SHIM_CALL XexLoadImage_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XexUnloadImage_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XexUnloadImage_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t handle = SHIM_GET_ARG_32(0);
XELOGD(
"XexUnloadImage(%.8X)",
handle);
XELOGD("XexUnloadImage(%.8X)", handle);
X_STATUS result = X_STATUS_INVALID_HANDLE;
@ -260,16 +238,14 @@ SHIM_CALL XexUnloadImage_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL XexGetProcedureAddress_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t module_handle = SHIM_GET_ARG_32(0);
uint32_t ordinal = SHIM_GET_ARG_32(1);
uint32_t out_function_ptr = SHIM_GET_ARG_32(2);
XELOGD(
"XexGetProcedureAddress(%.8X, %.8X, %.8X)",
module_handle, ordinal, out_function_ptr);
XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
out_function_ptr);
X_STATUS result = X_STATUS_INVALID_HANDLE;
@ -278,8 +254,8 @@ SHIM_CALL XexGetProcedureAddress_shim(
if (!module_handle) {
module = state->GetExecutableModule();
} else {
result = state->object_table()->GetObject(
module_handle, (XObject**)&module);
result =
state->object_table()->GetObject(module_handle, (XObject**)&module);
}
if (XSUCCEEDED(result)) {
@ -294,9 +270,8 @@ SHIM_CALL XexGetProcedureAddress_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL ExRegisterTitleTerminateNotification_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL ExRegisterTitleTerminateNotification_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t registration_ptr = SHIM_GET_ARG_32(0);
uint32_t create = SHIM_GET_ARG_32(1);
@ -305,9 +280,8 @@ SHIM_CALL ExRegisterTitleTerminateNotification_shim(
// list entry flink
// list entry blink
XELOGD(
"ExRegisterTitleTerminateNotification(%.8X(%.8X), %.1X)",
registration_ptr, routine, create);
XELOGD("ExRegisterTitleTerminateNotification(%.8X(%.8X), %.1X)",
registration_ptr, routine, create);
if (create) {
// Adding.
@ -318,11 +292,9 @@ SHIM_CALL ExRegisterTitleTerminateNotification_shim(
}
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterModuleExports(
ExportResolver* export_resolver, KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state);

View File

@ -16,22 +16,17 @@
#include <xenia/kernel/objects/xthread.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL ObReferenceObjectByHandle_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* 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);
XELOGD("ObReferenceObjectByHandle(%.8X, %.8X, %.8X)", handle, object_type_ptr,
out_object_ptr);
X_STATUS result = X_STATUS_INVALID_HANDLE;
@ -43,12 +38,11 @@ SHIM_CALL ObReferenceObjectByHandle_shim(
// TODO(benvanik): get native value, if supported.
uint32_t native_ptr = 0xDEADF00D;
switch (object_type_ptr) {
case 0xD01BBEEF: // ExThreadObjectType
case 0xD01BBEEF: // ExThreadObjectType
{
XThread* thread = (XThread*)object;
native_ptr = thread->thread_state();
}
break;
} break;
}
if (out_object_ptr) {
@ -59,14 +53,10 @@ SHIM_CALL ObReferenceObjectByHandle_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL ObDereferenceObject_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t native_ptr = SHIM_GET_ARG_32(0);
XELOGD(
"ObDereferenceObject(%.8X)",
native_ptr);
XELOGD("ObDereferenceObject(%.8X)", native_ptr);
// Check if a dummy value from ObReferenceObjectByHandle.
if (native_ptr == 0xDEADF00D) {
@ -83,16 +73,13 @@ SHIM_CALL ObDereferenceObject_shim(
SHIM_SET_RETURN_32(0);
}
SHIM_CALL NtDuplicateObject_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtDuplicateObject_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t new_handle_ptr = SHIM_GET_ARG_32(1);
uint32_t options = SHIM_GET_ARG_32(2);
XELOGD(
"NtDuplicateObject(%.8X, %.8X, %.8X)",
handle, new_handle_ptr, options);
XELOGD("NtDuplicateObject(%.8X, %.8X, %.8X)", handle, new_handle_ptr,
options);
// NOTE: new_handle_ptr can be zero to just close a handle.
// NOTE: this function seems to be used to get the current thread handle
@ -123,14 +110,10 @@ SHIM_CALL NtDuplicateObject_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL NtClose_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL NtClose_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t handle = SHIM_GET_ARG_32(0);
XELOGD(
"NtClose(%.8X)",
handle);
XELOGD("NtClose(%.8X)", handle);
X_STATUS result = X_STATUS_INVALID_HANDLE;
@ -139,13 +122,11 @@ SHIM_CALL NtClose_shim(
SHIM_SET_RETURN_32(result);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterObExports(
ExportResolver* export_resolver, KernelState* state) {
void xe::kernel::xboxkrnl::RegisterObExports(ExportResolver* export_resolver,
KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", ObReferenceObjectByHandle, state);
SHIM_SET_MAPPING("xboxkrnl.exe", ObDereferenceObject, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtDuplicateObject, state);

View File

@ -12,18 +12,15 @@
#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_table.inc>
#include <xenia/kernel/xboxkrnl_table.inc>
};
} // namespace ordinals
#include <xenia/kernel/util/ordinal_table_post.inc>
#endif // XENIA_KERNEL_XBOXKRNL_ORDINALS_H_

View File

@ -12,10 +12,8 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/xboxkrnl_ordinals.h>
namespace xe {
namespace kernel {
@ -42,5 +40,4 @@ void RegisterVideoExports(ExportResolver* export_resolver, KernelState* state);
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_PRIVATE_H_

View File

@ -17,21 +17,16 @@
#include <xenia/kernel/util/shim_utils.h>
#include <xenia/kernel/util/xex2.h>
namespace xe {
namespace kernel {
// http://msdn.microsoft.com/en-us/library/ff561778
SHIM_CALL RtlCompareMemory_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlCompareMemory_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t source1_ptr = SHIM_GET_ARG_32(0);
uint32_t source2_ptr = SHIM_GET_ARG_32(1);
uint32_t length = SHIM_GET_ARG_32(2);
XELOGD(
"RtlCompareMemory(%.8X, %.8X, %d)",
source1_ptr, source2_ptr, length);
XELOGD("RtlCompareMemory(%.8X, %.8X, %d)", source1_ptr, source2_ptr, length);
// SIZE_T
// _In_ const VOID *Source1,
@ -55,17 +50,14 @@ SHIM_CALL RtlCompareMemory_shim(
SHIM_SET_RETURN_64(c);
}
// http://msdn.microsoft.com/en-us/library/ff552123
SHIM_CALL RtlCompareMemoryUlong_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlCompareMemoryUlong_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t source_ptr = 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_ptr, length, pattern);
XELOGD("RtlCompareMemoryUlong(%.8X, %d, %.8X)", source_ptr, length, pattern);
// SIZE_T
// _In_ PVOID Source,
@ -96,17 +88,14 @@ SHIM_CALL RtlCompareMemoryUlong_shim(
SHIM_SET_RETURN_64(c);
}
// http://msdn.microsoft.com/en-us/library/ff552263
SHIM_CALL RtlFillMemoryUlong_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlFillMemoryUlong_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t destination_ptr = 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_ptr, length, pattern);
XELOGD("RtlFillMemoryUlong(%.8X, %d, %.8X)", destination_ptr, length,
pattern);
// VOID
// _Out_ PVOID Destination,
@ -129,23 +118,20 @@ SHIM_CALL RtlFillMemoryUlong_shim(
}
}
// typedef struct _STRING {
// USHORT Length;
// USHORT MaximumLength;
// PCHAR Buffer;
// } ANSI_STRING, *PANSI_STRING;
// http://msdn.microsoft.com/en-us/library/ff561918
SHIM_CALL RtlInitAnsiString_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlInitAnsiString_shim(PPCContext* 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>");
XELOGD("RtlInitAnsiString(%.8X, %.8X = %s)", destination_ptr, source_ptr,
source ? source : "<null>");
// VOID
// _Out_ PANSI_STRING DestinationString,
@ -163,10 +149,8 @@ SHIM_CALL RtlInitAnsiString_shim(
SHIM_SET_MEM_32(destination_ptr + 4, source_ptr);
}
// http://msdn.microsoft.com/en-us/library/ff561899
SHIM_CALL RtlFreeAnsiString_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlFreeAnsiString_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t string_ptr = SHIM_GET_ARG_32(0);
XELOGD("RtlFreeAnsiString(%.8X)", string_ptr);
@ -186,17 +170,14 @@ SHIM_CALL RtlFreeAnsiString_shim(
SHIM_SET_MEM_32(string_ptr + 4, 0);
}
// typedef struct _UNICODE_STRING {
// USHORT Length;
// USHORT MaximumLength;
// PWSTR Buffer;
// } UNICODE_STRING, *PUNICODE_STRING;
// http://msdn.microsoft.com/en-us/library/ff561934
SHIM_CALL RtlInitUnicodeString_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlInitUnicodeString_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
uint32_t source_ptr = SHIM_GET_ARG_32(1);
@ -223,10 +204,8 @@ SHIM_CALL RtlInitUnicodeString_shim(
}
}
// http://msdn.microsoft.com/en-us/library/ff561903
SHIM_CALL RtlFreeUnicodeString_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlFreeUnicodeString_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t string_ptr = SHIM_GET_ARG_32(0);
XELOGD("RtlFreeUnicodeString(%.8X)", string_ptr);
@ -246,16 +225,15 @@ SHIM_CALL RtlFreeUnicodeString_shim(
SHIM_SET_MEM_32(string_ptr + 4, 0);
}
// http://msdn.microsoft.com/en-us/library/ff562969
SHIM_CALL RtlUnicodeStringToAnsiString_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlUnicodeStringToAnsiString_shim(PPCContext* 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);
XELOGD("RtlUnicodeStringToAnsiString(%.8X, %.8X, %d)", destination_ptr,
source_ptr, alloc_dest);
// NTSTATUS
// _Inout_ PANSI_STRING DestinationString,
@ -294,9 +272,8 @@ SHIM_CALL RtlUnicodeStringToAnsiString_shim(
SHIM_SET_RETURN_32(result);
}
SHIM_CALL RtlMultiByteToUnicodeN_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlMultiByteToUnicodeN_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
uint32_t destination_len = SHIM_GET_ARG_32(1);
uint32_t written_ptr = SHIM_GET_ARG_32(2);
@ -310,22 +287,19 @@ SHIM_CALL RtlMultiByteToUnicodeN_shim(
auto source = (uint8_t*)SHIM_MEM_ADDR(source_ptr);
auto destination = (uint16_t*)SHIM_MEM_ADDR(destination_ptr);
for (uint32_t i = 0; i < copy_len; i++)
{
for (uint32_t i = 0; i < copy_len; i++) {
*destination++ = poly::byte_swap(*source++);
}
if (written_ptr != 0)
{
if (written_ptr != 0) {
SHIM_SET_MEM_32(written_ptr, copy_len << 1);
}
SHIM_SET_RETURN_32(0);
}
SHIM_CALL RtlUnicodeToMultiByteN_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlUnicodeToMultiByteN_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
uint32_t destination_len = SHIM_GET_ARG_32(1);
uint32_t written_ptr = SHIM_GET_ARG_32(2);
@ -339,28 +313,23 @@ SHIM_CALL RtlUnicodeToMultiByteN_shim(
auto source = (uint16_t*)SHIM_MEM_ADDR(source_ptr);
auto destination = (uint8_t*)SHIM_MEM_ADDR(destination_ptr);
for (uint32_t i = 0; i < copy_len; i++)
{
for (uint32_t i = 0; i < copy_len; i++) {
uint16_t c = poly::byte_swap(*source++);
*destination++ = c < 256 ? (uint8_t)c : '?';
}
if (written_ptr != 0)
{
if (written_ptr != 0) {
SHIM_SET_MEM_32(written_ptr, copy_len);
}
SHIM_SET_RETURN_32(0);
}
SHIM_CALL RtlNtStatusToDosError_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlNtStatusToDosError_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t status = SHIM_GET_ARG_32(0);
XELOGD(
"RtlNtStatusToDosError(%.4X)",
status);
XELOGD("RtlNtStatusToDosError(%.4X)", status);
if (!status || (status & 0x20000000)) {
// Success.
@ -374,16 +343,15 @@ SHIM_CALL RtlNtStatusToDosError_shim(
// TODO(benvanik): implement lookup table.
XELOGE("RtlNtStatusToDosError lookup NOT SHIMEMENTED");
uint32_t result = 317; // ERROR_MR_MID_NOT_FOUND
uint32_t result = 317; // ERROR_MR_MID_NOT_FOUND
SHIM_SET_RETURN_32(result);
}
SHIM_CALL RtlImageXexHeaderField_shim(
PPCContext* ppc_state, KernelState* state) {
uint32_t xex_header_base = SHIM_GET_ARG_32(0);
uint32_t image_field = SHIM_GET_ARG_32(1);
SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* 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
@ -392,9 +360,7 @@ SHIM_CALL RtlImageXexHeaderField_shim(
// 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);
XELOGD("RtlImageXexHeaderField(%.8X, %.8X)", xex_header_base, image_field);
// PVOID
// PVOID XexHeaderBase
@ -428,7 +394,6 @@ SHIM_CALL RtlImageXexHeaderField_shim(
SHIM_SET_RETURN_64(0);
}
// 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
@ -440,23 +405,23 @@ SHIM_CALL RtlImageXexHeaderField_shim(
// 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
// 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.
#pragma pack(push, 1)
struct X_RTL_CRITICAL_SECTION {
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
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
};
#pragma pack(pop)
static_assert_size(X_RTL_CRITICAL_SECTION, 28);
@ -465,16 +430,15 @@ void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
// VOID
// _Out_ LPCRITICAL_SECTION lpCriticalSection
cs->unknown00 = 1;
cs->spin_count_div_256 = 0;
cs->lock_count = -1;
cs->recursion_count = 0;
cs->owning_thread_id = 0;
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(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlInitializeCriticalSection_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
XELOGD("RtlInitializeCriticalSection(%.8X)", cs_ptr);
@ -483,45 +447,41 @@ SHIM_CALL RtlInitializeCriticalSection_shim(
xeRtlInitializeCriticalSection(cs);
}
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(
X_RTL_CRITICAL_SECTION* cs, uint32_t spin_count) {
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
uint32_t spin_count) {
// 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 = (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;
}
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;
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(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlInitializeCriticalSectionAndSpinCount_shim(PPCContext* 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);
XELOGD("RtlInitializeCriticalSectionAndSpinCount(%.8X, %d)", cs_ptr,
spin_count);
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
X_STATUS result = xeRtlInitializeCriticalSectionAndSpinCount(
cs, spin_count);
X_STATUS result = xeRtlInitializeCriticalSectionAndSpinCount(cs, spin_count);
SHIM_SET_RETURN_32(result);
}
// TODO(benvanik): remove the need for passing in thread_id.
void xeRtlEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs, uint32_t thread_id) {
// VOID
@ -545,19 +505,19 @@ 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
// 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;
cs->owning_thread_id = thread_id;
cs->recursion_count = 1;
}
SHIM_CALL RtlEnterCriticalSection_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlEnterCriticalSection_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
// XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr);
@ -569,16 +529,16 @@ SHIM_CALL RtlEnterCriticalSection_shim(
xeRtlEnterCriticalSection(cs, thread_id);
}
// TODO(benvanik): remove the need for passing in thread_id.
uint32_t xeRtlTryEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs, uint32_t thread_id) {
uint32_t xeRtlTryEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs,
uint32_t thread_id) {
// DWORD
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
if (poly::atomic_cas(-1, 0, &cs->lock_count)) {
// Able to steal the lock right away.
cs->owning_thread_id = thread_id;
cs->recursion_count = 1;
cs->owning_thread_id = thread_id;
cs->recursion_count = 1;
return 1;
} else if (cs->owning_thread_id == thread_id) {
poly::atomic_inc(&cs->lock_count);
@ -589,9 +549,8 @@ uint32_t xeRtlTryEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs, uint32_t threa
return 0;
}
SHIM_CALL RtlTryEnterCriticalSection_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlTryEnterCriticalSection_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
// XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr);
@ -604,7 +563,6 @@ SHIM_CALL RtlTryEnterCriticalSection_shim(
SHIM_SET_RETURN_64(result);
}
void xeRtlLeaveCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
// VOID
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
@ -617,7 +575,7 @@ void xeRtlLeaveCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
}
// Unlock!
cs->owning_thread_id = 0;
cs->owning_thread_id = 0;
if (poly::atomic_dec(&cs->lock_count) != -1) {
// There were waiters - wake one of them.
// TODO(benvanik): wake a waiter.
@ -625,9 +583,8 @@ void xeRtlLeaveCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
}
}
SHIM_CALL RtlLeaveCriticalSection_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlLeaveCriticalSection_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
// XELOGD("RtlLeaveCriticalSection(%.8X)", cs_ptr);
@ -636,9 +593,7 @@ SHIM_CALL RtlLeaveCriticalSection_shim(
xeRtlLeaveCriticalSection(cs);
}
SHIM_CALL RtlTimeToTimeFields_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlTimeToTimeFields_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t time_ptr = SHIM_GET_ARG_32(0);
uint32_t time_fields_ptr = SHIM_GET_ARG_32(1);
@ -661,22 +616,20 @@ SHIM_CALL RtlTimeToTimeFields_shim(
SHIM_SET_MEM_16(time_fields_ptr + 12, st.wMilliseconds);
}
SHIM_CALL RtlTimeFieldsToTime_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL RtlTimeFieldsToTime_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t time_fields_ptr = SHIM_GET_ARG_32(0);
uint32_t time_ptr = SHIM_GET_ARG_32(1);
XELOGD("RtlTimeFieldsToTime(%.8X, %.8X)", time_fields_ptr, time_ptr);
SYSTEMTIME st;
st.wYear = SHIM_MEM_16(time_fields_ptr + 0);
st.wMonth = SHIM_MEM_16(time_fields_ptr + 2);
st.wDay = SHIM_MEM_16(time_fields_ptr + 4);
st.wHour = SHIM_MEM_16(time_fields_ptr + 6);
st.wMinute = SHIM_MEM_16(time_fields_ptr + 8);
st.wSecond = SHIM_MEM_16(time_fields_ptr + 10);
st.wMilliseconds = SHIM_MEM_16(time_fields_ptr + 12);
st.wYear = SHIM_MEM_16(time_fields_ptr + 0);
st.wMonth = SHIM_MEM_16(time_fields_ptr + 2);
st.wDay = SHIM_MEM_16(time_fields_ptr + 4);
st.wHour = SHIM_MEM_16(time_fields_ptr + 6);
st.wMinute = SHIM_MEM_16(time_fields_ptr + 8);
st.wSecond = SHIM_MEM_16(time_fields_ptr + 10);
st.wMilliseconds = SHIM_MEM_16(time_fields_ptr + 12);
FILETIME ft;
if (!SystemTimeToFileTime(&st, &ft)) {
@ -690,13 +643,11 @@ SHIM_CALL RtlTimeFieldsToTime_shim(
SHIM_SET_RETURN_64(1);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterRtlExports(
ExportResolver* export_resolver, KernelState* state) {
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);
@ -717,7 +668,8 @@ void xe::kernel::xboxkrnl::RegisterRtlExports(
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", RtlInitializeCriticalSectionAndSpinCount,
state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlEnterCriticalSection, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTryEnterCriticalSection, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlLeaveCriticalSection, state);

View File

@ -17,15 +17,11 @@
#include <xenia/kernel/util/shim_utils.h>
#include <xenia/kernel/util/xex2.h>
namespace xe {
namespace kernel {
// TODO: clean me up!
SHIM_CALL vsprintf_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL vsprintf_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t buffer_ptr = SHIM_GET_ARG_32(0);
uint32_t format_ptr = SHIM_GET_ARG_32(1);
uint32_t arg_ptr = SHIM_GET_ARG_32(2);
@ -63,10 +59,7 @@ SHIM_CALL vsprintf_shim(
end = format;
// skip flags
while (*end == '-' ||
*end == '+' ||
*end == ' ' ||
*end == '#' ||
while (*end == '-' || *end == '+' || *end == ' ' || *end == '#' ||
*end == '0') {
++end;
}
@ -81,8 +74,7 @@ SHIM_CALL vsprintf_shim(
if (*end == '*') {
++end;
arg_extras++;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -99,8 +91,7 @@ SHIM_CALL vsprintf_shim(
if (*end == '*') {
++end;
++arg_extras;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -120,28 +111,23 @@ SHIM_CALL vsprintf_shim(
if (*end == 'h') {
++end;
}
}
else if (*end == 'l') {
} else if (*end == 'l') {
++end;
arg_size = 4;
if (*end == 'l') {
++end;
arg_size = 8;
}
}
else if (*end == 'j') {
} else if (*end == 'j') {
arg_size = 8;
++end;
}
else if (*end == 'z') {
} else if (*end == 'z') {
arg_size = 4;
++end;
}
else if (*end == 't') {
} else if (*end == 't') {
arg_size = 8;
++end;
}
else if (*end == 'L') {
} else if (*end == 'L') {
arg_size = 8;
++end;
}
@ -150,21 +136,10 @@ SHIM_CALL vsprintf_shim(
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') {
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);
@ -172,58 +147,52 @@ SHIM_CALL vsprintf_shim(
assert_true(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...
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 {
} else {
assert_true(false);
}
}
else if (arg_size == 4) {
} 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...
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 {
} else {
assert_true(false);
}
}
}
else if (*end == 'n')
{
} else if (*end == 'n') {
assert_true(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...
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else if (*end == 's' ||
*end == 'p') {
} else if (*end == 's' || *end == 'p') {
char local[512];
local[0] = '\0';
strncat(local, start, end + 1 - start);
assert_true(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...
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
const void* pointer = (const void*)SHIM_MEM_ADDR(value);
int result = sprintf(b, local, pointer);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else {
} else {
assert_true(false);
break;
}
@ -233,11 +202,8 @@ SHIM_CALL vsprintf_shim(
SHIM_SET_RETURN_32((uint32_t)(b - buffer));
}
// TODO: clean me up!
SHIM_CALL _vsnprintf_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL _vsnprintf_shim(PPCContext* 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);
@ -248,7 +214,9 @@ SHIM_CALL _vsnprintf_shim(
return;
}
char* buffer = (char*)SHIM_MEM_ADDR(buffer_ptr); // TODO: ensure it never writes past the end of the buffer (count)...
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;
@ -276,10 +244,7 @@ SHIM_CALL _vsnprintf_shim(
end = format;
// skip flags
while (*end == '-' ||
*end == '+' ||
*end == ' ' ||
*end == '#' ||
while (*end == '-' || *end == '+' || *end == ' ' || *end == '#' ||
*end == '0') {
++end;
}
@ -294,8 +259,7 @@ SHIM_CALL _vsnprintf_shim(
if (*end == '*') {
++end;
arg_extras++;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -312,8 +276,7 @@ SHIM_CALL _vsnprintf_shim(
if (*end == '*') {
++end;
++arg_extras;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -333,28 +296,23 @@ SHIM_CALL _vsnprintf_shim(
if (*end == 'h') {
++end;
}
}
else if (*end == 'l') {
} else if (*end == 'l') {
++end;
arg_size = 4;
if (*end == 'l') {
++end;
arg_size = 8;
}
}
else if (*end == 'j') {
} else if (*end == 'j') {
arg_size = 8;
++end;
}
else if (*end == 'z') {
} else if (*end == 'z') {
arg_size = 4;
++end;
}
else if (*end == 't') {
} else if (*end == 't') {
arg_size = 8;
++end;
}
else if (*end == 'L') {
} else if (*end == 'L') {
arg_size = 8;
++end;
}
@ -363,21 +321,10 @@ SHIM_CALL _vsnprintf_shim(
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') {
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);
@ -385,58 +332,52 @@ SHIM_CALL _vsnprintf_shim(
assert_true(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...
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 {
} else {
assert_true(false);
}
}
else if (arg_size == 4) {
} 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...
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 {
} else {
assert_true(false);
}
}
}
else if (*end == 'n')
{
} else if (*end == 'n') {
assert_true(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...
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else if (*end == 's' ||
*end == 'p') {
} else if (*end == 's' || *end == 'p') {
char local[512];
local[0] = '\0';
strncat(local, start, end + 1 - start);
assert_true(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...
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
const void* pointer = (const void*)SHIM_MEM_ADDR(value);
int result = sprintf(b, local, pointer);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else {
} else {
assert_true(false);
break;
}
@ -446,11 +387,8 @@ SHIM_CALL _vsnprintf_shim(
SHIM_SET_RETURN_32((uint32_t)(b - buffer));
}
// TODO: clean me up!
SHIM_CALL _vswprintf_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL _vswprintf_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t buffer_ptr = SHIM_GET_ARG_32(0);
uint32_t format_ptr = SHIM_GET_ARG_32(1);
uint32_t arg_ptr = SHIM_GET_ARG_32(2);
@ -460,14 +398,17 @@ SHIM_CALL _vswprintf_shim(
return;
}
wchar_t*buffer = (wchar_t*)SHIM_MEM_ADDR(buffer_ptr); // TODO: ensure it never writes past the end of the buffer (count)...
wchar_t* buffer =
(wchar_t*)SHIM_MEM_ADDR(buffer_ptr); // TODO: ensure it never writes past
// the end of the buffer (count)...
const wchar_t* format = (const wchar_t*)SHIM_MEM_ADDR(format_ptr);
// this will work since a null is the same regardless of endianness
size_t format_length = wcslen(format);
// swap the format buffer
wchar_t* swapped_format = (wchar_t*)xe_malloc((format_length + 1) * sizeof(wchar_t));
wchar_t* swapped_format =
(wchar_t*)xe_malloc((format_length + 1) * sizeof(wchar_t));
for (size_t i = 0; i < format_length; ++i) {
swapped_format[i] = poly::byte_swap(format[i]);
}
@ -480,7 +421,7 @@ SHIM_CALL _vswprintf_shim(
wchar_t* b = buffer;
for (; *format != '\0'; ++format) {
const wchar_t *start = format;
const wchar_t* start = format;
if (*format != '%') {
*b++ = *format;
@ -501,10 +442,7 @@ SHIM_CALL _vswprintf_shim(
end = format;
// skip flags
while (*end == '-' ||
*end == '+' ||
*end == ' ' ||
*end == '#' ||
while (*end == '-' || *end == '+' || *end == ' ' || *end == '#' ||
*end == '0') {
++end;
}
@ -519,8 +457,7 @@ SHIM_CALL _vswprintf_shim(
if (*end == '*') {
++end;
arg_extras++;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -537,8 +474,7 @@ SHIM_CALL _vswprintf_shim(
if (*end == '*') {
++end;
++arg_extras;
}
else {
} else {
while (*end >= '0' && *end <= '9') {
++end;
}
@ -558,28 +494,23 @@ SHIM_CALL _vswprintf_shim(
if (*end == 'h') {
++end;
}
}
else if (*end == 'l') {
} else if (*end == 'l') {
++end;
arg_size = 4;
if (*end == 'l') {
++end;
arg_size = 8;
}
}
else if (*end == 'j') {
} else if (*end == 'j') {
arg_size = 8;
++end;
}
else if (*end == 'z') {
} else if (*end == 'z') {
arg_size = 4;
++end;
}
else if (*end == 't') {
} else if (*end == 't') {
arg_size = 8;
++end;
}
else if (*end == 'L') {
} else if (*end == 'L') {
arg_size = 8;
++end;
}
@ -588,21 +519,10 @@ SHIM_CALL _vswprintf_shim(
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') {
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') {
wchar_t local[512];
local[0] = '\0';
wcsncat(local, start, end + 1 - start);
@ -610,67 +530,64 @@ SHIM_CALL _vswprintf_shim(
assert_true(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...
uint64_t value = SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
int result = wsprintf(b, local, value);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else if (arg_size == 4) {
} 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...
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
int result = wsprintf(b, local, value);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
}
else if (*end == 'n')
{
} else if (*end == 'n') {
assert_true(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...
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(wchar_t)));
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(wchar_t)));
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else if (*end == 'p') {
} else if (*end == 'p') {
wchar_t local[512];
local[0] = '\0';
wcsncat(local, start, end + 1 - start);
assert_true(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...
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
const void* pointer = (void*)SHIM_MEM_ADDR(value);
int result = wsprintf(b, local, pointer);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else if (*end == 's') {
} else if (*end == 's') {
wchar_t local[512];
local[0] = '\0';
wcsncat(local, start, end + 1 - start);
assert_true(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...
uint32_t value = (uint32_t)SHIM_MEM_64(
arg_ptr + (arg_index * 8)); // TODO: check if this is correct...
const wchar_t* data = (const wchar_t*)SHIM_MEM_ADDR(value);
size_t data_length = wcslen(data);
wchar_t* swapped_data = (wchar_t*)xe_malloc((data_length + 1) * sizeof(wchar_t));
wchar_t* swapped_data =
(wchar_t*)xe_malloc((data_length + 1) * sizeof(wchar_t));
for (size_t i = 0; i < data_length; ++i) {
swapped_data[i] = poly::byte_swap(data[i]);
}
@ -679,12 +596,10 @@ SHIM_CALL _vswprintf_shim(
xe_free(swapped_data);
b += result;
arg_index++;
}
else {
} else {
assert_true(false);
}
}
else {
} else {
assert_true(false);
break;
}
@ -695,19 +610,16 @@ SHIM_CALL _vswprintf_shim(
xe_free(swapped_format);
// swap the result buffer
for (wchar_t* swap = buffer; swap != b; ++swap)
{
for (wchar_t* swap = buffer; swap != b; ++swap) {
*swap = poly::byte_swap(*swap);
}
SHIM_SET_RETURN_32((uint32_t)((b - buffer) / sizeof(wchar_t)));
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterStringExports(
ExportResolver* export_resolver, KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", vsprintf, state);

File diff suppressed because it is too large Load Diff

View File

@ -14,27 +14,21 @@
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
SHIM_CALL XUsbcamCreate_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL XUsbcamCreate_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk1 = SHIM_GET_ARG_32(0);
uint32_t unk2 = SHIM_GET_ARG_32(1);
XELOGD(
"XUsbcamCreate(%.8X, %.8X)",
unk1, unk2);
XELOGD("XUsbcamCreate(%.8X, %.8X)", unk1, unk2);
SHIM_SET_RETURN_32(-1);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterUsbcamExports(
ExportResolver* export_resolver, KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", XUsbcamCreate, state);

View File

@ -19,13 +19,11 @@
#include <xenia/kernel/xboxkrnl_rtl.h>
#include <xenia/kernel/util/shim_utils.h>
namespace xe {
namespace kernel {
using xe::gpu::GraphicsSystem;
// http://www.tweakoz.com/orkid/
// http://www.tweakoz.com/orkid/dox/d3/d52/xb360init_8cpp_source.html
// https://github.com/Free60Project/xenosfb/
@ -36,30 +34,25 @@ using xe::gpu::GraphicsSystem;
// 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"
// http://www.microsoft.com/en-za/download/details.aspx?id=5313 -- "Stripped
// Down Direct3D: Xbox 360 Command Buffer and Resource Management"
SHIM_CALL VdGetCurrentDisplayGamma_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdGetCurrentDisplayGamma_shim(PPCContext* 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);
XELOGD("VdGetCurrentDisplayGamma(%.8X, %.8X)", arg0_ptr, arg1_ptr);
SHIM_SET_MEM_32(arg0_ptr, 2);
SHIM_SET_MEM_F32(arg1_ptr, 2.22222233f);
}
SHIM_CALL VdGetCurrentDisplayInformation_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdGetCurrentDisplayInformation_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t ptr = SHIM_GET_ARG_32(0);
XELOGD(
"VdGetCurrentDisplayInformation(%.8X)",
ptr);
XELOGD("VdGetCurrentDisplayInformation(%.8X)", ptr);
// Expecting a length 0x58 struct of stuff.
SHIM_SET_MEM_32(ptr + 0, (1280 << 16) | 720);
@ -67,7 +60,7 @@ SHIM_CALL VdGetCurrentDisplayInformation_shim(
SHIM_SET_MEM_32(ptr + 8, 0);
SHIM_SET_MEM_32(ptr + 12, 0);
SHIM_SET_MEM_32(ptr + 16, 1280); // backbuffer width?
SHIM_SET_MEM_32(ptr + 20, 720); // backbuffer height?
SHIM_SET_MEM_32(ptr + 20, 720); // backbuffer height?
SHIM_SET_MEM_32(ptr + 24, 1280);
SHIM_SET_MEM_32(ptr + 28, 720);
SHIM_SET_MEM_32(ptr + 32, 1);
@ -78,104 +71,87 @@ SHIM_CALL VdGetCurrentDisplayInformation_shim(
SHIM_SET_MEM_32(ptr + 52, 0);
SHIM_SET_MEM_32(ptr + 56, 0);
SHIM_SET_MEM_32(ptr + 60, 0);
SHIM_SET_MEM_32(ptr + 64, 0x014000B4); // ?
SHIM_SET_MEM_32(ptr + 68, 0x014000B4); // ?
SHIM_SET_MEM_32(ptr + 64, 0x014000B4); // ?
SHIM_SET_MEM_32(ptr + 68, 0x014000B4); // ?
SHIM_SET_MEM_32(ptr + 72, (1280 << 16) | 720); // actual display size?
SHIM_SET_MEM_32(ptr + 76, 0x42700000);
SHIM_SET_MEM_32(ptr + 80, 0);
SHIM_SET_MEM_32(ptr + 84, 1280); // display width
}
SHIM_CALL VdQueryVideoFlags_shim(
PPCContext* ppc_state, KernelState* state) {
XELOGD(
"VdQueryVideoFlags()");
SHIM_CALL VdQueryVideoFlags_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("VdQueryVideoFlags()");
SHIM_SET_RETURN_64(0x00000006);
}
void xeVdQueryVideoMode(X_VIDEO_MODE* video_mode) {
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;
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;
// TODO(benvanik): auto swap structure.
video_mode->display_width = poly::byte_swap(video_mode->display_width);
video_mode->display_height = poly::byte_swap(video_mode->display_height);
video_mode->is_interlaced = poly::byte_swap(video_mode->is_interlaced);
video_mode->is_widescreen = poly::byte_swap(video_mode->is_widescreen);
video_mode->is_hi_def = poly::byte_swap(video_mode->is_hi_def);
video_mode->refresh_rate = poly::byte_swap(video_mode->refresh_rate);
video_mode->video_standard = poly::byte_swap(video_mode->video_standard);
video_mode->unknown_0x8a = poly::byte_swap(video_mode->unknown_0x8a);
video_mode->unknown_0x01 = poly::byte_swap(video_mode->unknown_0x01);
video_mode->display_width = poly::byte_swap(video_mode->display_width);
video_mode->display_height = poly::byte_swap(video_mode->display_height);
video_mode->is_interlaced = poly::byte_swap(video_mode->is_interlaced);
video_mode->is_widescreen = poly::byte_swap(video_mode->is_widescreen);
video_mode->is_hi_def = poly::byte_swap(video_mode->is_hi_def);
video_mode->refresh_rate = poly::byte_swap(video_mode->refresh_rate);
video_mode->video_standard = poly::byte_swap(video_mode->video_standard);
video_mode->unknown_0x8a = poly::byte_swap(video_mode->unknown_0x8a);
video_mode->unknown_0x01 = poly::byte_swap(video_mode->unknown_0x01);
}
SHIM_CALL VdQueryVideoMode_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdQueryVideoMode_shim(PPCContext* 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);
X_VIDEO_MODE* video_mode = (X_VIDEO_MODE*)SHIM_MEM_ADDR(video_mode_ptr);
XELOGD(
"VdQueryVideoMode(%.8X)",
video_mode_ptr);
XELOGD("VdQueryVideoMode(%.8X)", video_mode_ptr);
xeVdQueryVideoMode(video_mode);
}
SHIM_CALL VdInitializeEngines_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdInitializeEngines_shim(PPCContext* 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);
XELOGD("VdInitializeEngines(%.8X, %.8X, %.8X, %.8X, %.8X)", unk0, callback,
unk1, unk2_ptr, unk3_ptr);
// r3 = 0x4F810000
// r4 = function ptr (cleanup callback?)
// r5 = 0
// r6/r7 = some binary data in .data
}
SHIM_CALL VdShutdownEngines_shim(
PPCContext* ppc_state, KernelState* state) {
XELOGD(
"VdShutdownEngines()");
SHIM_CALL VdShutdownEngines_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("VdShutdownEngines()");
// Ignored for now.
// Games seem to call an Initialize/Shutdown pair to query info, then
// re-initialize.
}
SHIM_CALL VdSetGraphicsInterruptCallback_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdSetGraphicsInterruptCallback_shim(PPCContext* 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);
XELOGD("VdSetGraphicsInterruptCallback(%.8X, %.8X)", callback, user_data);
GraphicsSystem* gs = state->emulator()->graphics_system();
if (!gs) {
@ -189,16 +165,13 @@ SHIM_CALL VdSetGraphicsInterruptCallback_shim(
gs->SetInterruptCallback(callback, user_data);
}
SHIM_CALL VdInitializeRingBuffer_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdInitializeRingBuffer_shim(PPCContext* 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);
XELOGD("VdInitializeRingBuffer(%.8X, %.8X)", ptr, page_count);
GraphicsSystem* gs = state->emulator()->graphics_system();
if (!gs) {
return;
@ -214,15 +187,12 @@ SHIM_CALL VdInitializeRingBuffer_shim(
gs->InitializeRingBuffer(ptr, page_count);
}
SHIM_CALL VdEnableRingBufferRPtrWriteBack_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdEnableRingBufferRPtrWriteBack_shim(PPCContext* 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);
XELOGD("VdEnableRingBufferRPtrWriteBack(%.8X, %.8X)", ptr, block_size);
GraphicsSystem* gs = state->emulator()->graphics_system();
if (!gs) {
@ -233,99 +203,83 @@ SHIM_CALL VdEnableRingBufferRPtrWriteBack_shim(
gs->EnableReadPointerWriteBack(ptr, block_size);
ptr += 0x20000000;
//printf("%.8X", ptr);
// printf("%.8X", ptr);
// 0x0110343c
// r3 = 0x2B10(d3d?) + 0x3C
//((p + 0x3C) & 0x1FFFFFFF) + ((((p + 0x3C) >> 20) + 0x200) & 0x1000)
//also 0x3C offset into WriteBacks is PrimaryRingBufferReadIndex
// 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: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: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
//(1:17:39 AM) Rick: .text:8201B364 bl
//VdEnableRingBufferRPtrWriteBack
// TODO(benvanik): something?
}
SHIM_CALL VdGetSystemCommandBuffer_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdGetSystemCommandBuffer_shim(PPCContext* 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);
XELOGD("VdGetSystemCommandBuffer(%.8X, %.8X)", p0_ptr, p1_ptr);
SHIM_SET_MEM_32(p0_ptr, 0xBEEF0000);
SHIM_SET_MEM_32(p1_ptr, 0xBEEF0001);
}
SHIM_CALL VdSetSystemCommandBufferGpuIdentifierAddress_shim(
PPCContext* ppc_state, KernelState* state) {
uint32_t unk = SHIM_GET_ARG_32(0);
XELOGD(
"VdSetSystemCommandBufferGpuIdentifierAddress(%.8X)",
unk);
XELOGD("VdSetSystemCommandBufferGpuIdentifierAddress(%.8X)", unk);
// r3 = 0x2B10(d3d?) + 8
}
// VdVerifyMEInitCommand
// r3
// r4 = 19
// no op?
// VdCallGraphicsNotificationRoutines
// r3 = 1
// r4 = ?
// callbacks get 0, r3, r4
SHIM_CALL VdIsHSIOTrainingSucceeded_shim(
PPCContext* ppc_state, KernelState* state) {
XELOGD(
"VdIsHSIOTrainingSucceeded()");
SHIM_CALL VdIsHSIOTrainingSucceeded_shim(PPCContext* 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_64(1);
}
SHIM_CALL VdPersistDisplay_shim(
PPCContext* ppc_state, KernelState* state) {
XELOGD(
"VdPersistDisplay(?)");
SHIM_CALL VdPersistDisplay_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("VdPersistDisplay(?)");
// ?
SHIM_SET_RETURN_64(1);
}
SHIM_CALL VdRetrainEDRAMWorker_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdRetrainEDRAMWorker_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk0 = SHIM_GET_ARG_32(0);
XELOGD(
"VdRetrainEDRAMWorker(%.8X)",
unk0);
XELOGD("VdRetrainEDRAMWorker(%.8X)", unk0);
SHIM_SET_RETURN_64(0);
}
SHIM_CALL VdRetrainEDRAM_shim(
PPCContext* ppc_state, KernelState* state) {
SHIM_CALL VdRetrainEDRAM_shim(PPCContext* 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);
@ -333,35 +287,24 @@ SHIM_CALL VdRetrainEDRAM_shim(
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);
XELOGD("VdRetrainEDRAM(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", unk0, unk1, unk2,
unk3, unk4, unk5);
SHIM_SET_RETURN_64(0);
}
SHIM_CALL VdSwap_shim(
PPCContext* ppc_state, KernelState* state) {
uint32_t unk0 = SHIM_GET_ARG_32(0); // ptr into primary ringbuffer
SHIM_CALL VdSwap_shim(PPCContext* ppc_state, KernelState* state) {
uint32_t unk0 = SHIM_GET_ARG_32(0); // ptr into primary ringbuffer
uint32_t unk1 = SHIM_GET_ARG_32(1);
uint32_t unk2 = SHIM_GET_ARG_32(2);
uint32_t unk3 = SHIM_GET_ARG_32(3); // ptr to 0xBEEF0000
uint32_t unk4 = SHIM_GET_ARG_32(4); // 0xBEEF0001
uint32_t unk3 = SHIM_GET_ARG_32(3); // ptr to 0xBEEF0000
uint32_t unk4 = SHIM_GET_ARG_32(4); // 0xBEEF0001
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);
XELOGD("VdSwap(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", unk0, unk1,
unk2, unk3, unk4, unk5, unk6, unk7);
// The caller seems to reserve 64 words (256b) in the primary ringbuffer
// for this method to do what it needs. We just zero them out and send a
@ -370,20 +313,17 @@ SHIM_CALL VdSwap_shim(
// use this method.
xe_zero_struct(SHIM_MEM_ADDR(unk0), 64 * 4);
auto dwords = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(unk0));
dwords[0] = poly::byte_swap((0x03 << 30) |
((1 - 1) << 16) |
dwords[0] = poly::byte_swap((0x03 << 30) | ((1 - 1) << 16) |
(xe::gpu::xenos::PM4_XE_SWAP << 8));
SHIM_SET_RETURN_64(0);
}
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterVideoExports(
ExportResolver* export_resolver, KernelState* state) {
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);
@ -394,8 +334,8 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(
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", VdSetSystemCommandBufferGpuIdentifierAddress,
state);
SHIM_SET_MAPPING("xboxkrnl.exe", VdIsHSIOTrainingSucceeded, state);
SHIM_SET_MAPPING("xboxkrnl.exe", VdPersistDisplay, state);
SHIM_SET_MAPPING("xboxkrnl.exe", VdRetrainEDRAMWorker, state);

View File

@ -14,16 +14,15 @@
#include <xenia/kernel/objects/xmutant.h>
#include <xenia/kernel/objects/xsemaphore.h>
namespace xe {
namespace kernel {
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) {
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_);
}
@ -32,21 +31,13 @@ XObject::~XObject() {
assert_zero(pointer_ref_count_);
}
Memory* XObject::memory() const {
return kernel_state_->memory();
}
Memory* XObject::memory() const { return kernel_state_->memory(); }
XObject::Type XObject::type() {
return type_;
}
XObject::Type XObject::type() { return type_; }
X_HANDLE XObject::handle() const {
return handle_;
}
X_HANDLE XObject::handle() const { return handle_; }
void XObject::RetainHandle() {
++handle_ref_count_;
}
void XObject::RetainHandle() { ++handle_ref_count_; }
bool XObject::ReleaseHandle() {
if (--handle_ref_count_ == 0) {
@ -55,9 +46,7 @@ bool XObject::ReleaseHandle() {
return false;
}
void XObject::Retain() {
++pointer_ref_count_;
}
void XObject::Retain() { ++pointer_ref_count_; }
void XObject::Release() {
if (--pointer_ref_count_ == 0) {
@ -78,7 +67,7 @@ uint32_t XObject::TimeoutTicksToMs(int64_t timeout_ticks) {
return 0;
} else if (timeout_ticks < 0) {
// Relative time.
return (uint32_t)(-timeout_ticks / 10000); // Ticks -> MS
return (uint32_t)(-timeout_ticks / 10000); // Ticks -> MS
} else {
return 0;
}
@ -92,57 +81,50 @@ X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
return X_STATUS_SUCCESS;
}
DWORD timeout_ms = opt_timeout ?
TimeoutTicksToMs(*opt_timeout) : INFINITE;
DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;
DWORD result = WaitForSingleObjectEx(wait_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;
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;
}
}
X_STATUS XObject::SignalAndWait(
XObject* signal_object, XObject* wait_object,
uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable,
uint64_t* opt_timeout) {
DWORD timeout_ms = opt_timeout ?
TimeoutTicksToMs(*opt_timeout) : INFINITE;
X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout) {
DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;
DWORD result = SignalObjectAndWait(
signal_object->GetWaitHandle(),
wait_object->GetWaitHandle(),
timeout_ms,
alertable ? TRUE : FALSE);
DWORD result = SignalObjectAndWait(signal_object->GetWaitHandle(),
wait_object->GetWaitHandle(), timeout_ms,
alertable ? TRUE : FALSE);
return result;
}
X_STATUS XObject::WaitMultiple(
uint32_t count, XObject** objects,
uint32_t wait_type, uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout) {
X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
uint32_t wait_type, uint32_t wait_reason,
uint32_t processor_mode, uint32_t alertable,
uint64_t* opt_timeout) {
void** wait_handles = (void**)alloca(sizeof(void*) * count);
for (uint32_t n = 0; n < count; n++) {
wait_handles[n] = objects[n]->GetWaitHandle();
assert_not_null(wait_handles[n]);
}
DWORD timeout_ms = opt_timeout ?
TimeoutTicksToMs(*opt_timeout) : INFINITE;
DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;
DWORD result = WaitForMultipleObjectsEx(
count, wait_handles,
wait_type ? FALSE : TRUE, timeout_ms, alertable);
count, wait_handles, wait_type ? FALSE : TRUE, timeout_ms, alertable);
return result;
}
@ -164,7 +146,8 @@ void XObject::SetNativePointer(uint32_t native_ptr) {
uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
object_ptr |= 0x1;
header_be->wait_list_flink = poly::byte_swap((uint32_t)(object_ptr >> 32));
header_be->wait_list_blink = poly::byte_swap((uint32_t)(object_ptr & 0xFFFFFFFF));
header_be->wait_list_blink =
poly::byte_swap((uint32_t)(object_ptr & 0xFFFFFFFF));
}
XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
@ -193,9 +176,8 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
if (header.wait_list_blink & 0x1) {
// Already initialized.
uint64_t object_ptr =
((uint64_t)header.wait_list_flink << 32) |
((header.wait_list_blink) & ~0x1);
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.
return object;
@ -204,51 +186,49 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
// http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
XObject* object = NULL;
switch (as_type) {
case 0: // EventNotificationObject
case 1: // EventSynchronizationObject
case 0: // EventNotificationObject
case 1: // EventSynchronizationObject
{
XEvent* ev = new XEvent(kernel_state);
ev->InitializeNative(native_ptr, header);
object = ev;
}
break;
case 2: // MutantObject
} break;
case 2: // MutantObject
{
XMutant* mutant = new XMutant(kernel_state);
mutant->InitializeNative(native_ptr, header);
object = mutant;
}
break;
case 5: // SemaphoreObject
} break;
case 5: // SemaphoreObject
{
XSemaphore* sem = new XSemaphore(kernel_state);
sem->InitializeNative(native_ptr, header);
object = sem;
}
break;
case 3: // ProcessObject
case 4: // QueueObject
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:
assert_always();
return NULL;
} break;
case 3: // ProcessObject
case 4: // QueueObject
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:
assert_always();
return NULL;
}
// Stash pointer in struct.
uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
object_ptr |= 0x1;
header_be->wait_list_flink = poly::byte_swap((uint32_t)(object_ptr >> 32));
header_be->wait_list_blink = poly::byte_swap((uint32_t)(object_ptr & 0xFFFFFFFF));
header_be->wait_list_blink =
poly::byte_swap((uint32_t)(object_ptr & 0xFFFFFFFF));
return object;
}

View File

@ -16,11 +16,9 @@
#include <xenia/xbox.h>
namespace xe {
namespace kernel {
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
typedef struct {
uint32_t type_flags;
@ -29,9 +27,8 @@ typedef struct {
uint32_t wait_list_blink;
} DISPATCH_HEADER;
class XObject {
public:
public:
enum Type {
kTypeModule,
kTypeThread,
@ -62,42 +59,38 @@ public:
// Reference()
// Dereference()
X_STATUS Wait(
uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable,
uint64_t* opt_timeout);
static X_STATUS SignalAndWait(
XObject* signal_object, XObject* wait_object,
uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable,
uint64_t* opt_timeout);
static X_STATUS WaitMultiple(
uint32_t count, XObject** objects,
uint32_t wait_type, uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout);
X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout);
static X_STATUS SignalAndWait(XObject* signal_object, XObject* wait_object,
uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout);
static X_STATUS WaitMultiple(uint32_t count, XObject** objects,
uint32_t wait_type, uint32_t wait_reason,
uint32_t processor_mode, uint32_t alertable,
uint64_t* opt_timeout);
static XObject* GetObject(KernelState* kernel_state, void* native_ptr,
int32_t as_type = -1);
virtual void* GetWaitHandle() { return 0; }
protected:
protected:
Memory* memory() const;
void SetNativePointer(uint32_t native_ptr);
static uint32_t TimeoutTicksToMs(int64_t timeout_ticks);
KernelState* kernel_state_;
KernelState* kernel_state_;
private:
private:
std::atomic<int32_t> handle_ref_count_;
std::atomic<int32_t> pointer_ref_count_;
Type type_;
X_HANDLE handle_;
Type type_;
X_HANDLE handle_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XBOXKRNL_XOBJECT_H_