clang-format on most of kernel/
This commit is contained in:
parent
854bcdb60a
commit
1c4dcd5e0e
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
Loading…
Reference in New Issue