commit
91dfb6a8a0
|
@ -294,6 +294,11 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) {
|
|||
return;
|
||||
}
|
||||
|
||||
// No available data.
|
||||
if (!data->input_buffer_0_valid && !data->input_buffer_1_valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert_zero(data->unk_dword_9);
|
||||
|
||||
// XAudio Loops
|
||||
|
|
|
@ -189,6 +189,7 @@ Function* Processor::ResolveFunction(uint32_t address) {
|
|||
// Grab symbol declaration.
|
||||
auto function = LookupFunction(address);
|
||||
if (!function) {
|
||||
entry->status = Entry::STATUS_FAILED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -317,10 +318,21 @@ uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
|||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
PPCContext* context = thread_state->context();
|
||||
assert_true(arg_count <= 5);
|
||||
for (size_t i = 0; i < arg_count; ++i) {
|
||||
for (size_t i = 0; i < std::min(arg_count, 8ull); ++i) {
|
||||
context->r[3 + i] = args[i];
|
||||
}
|
||||
|
||||
if (arg_count > 7) {
|
||||
// Rest of the arguments go on the stack.
|
||||
// FIXME: This assumes arguments are 32 bits!
|
||||
auto stack_arg_base =
|
||||
memory()->TranslateVirtual((uint32_t)context->r[1] + 0x54 - (64 + 112));
|
||||
for (size_t i = 0; i < arg_count - 8; i++) {
|
||||
xe::store_and_swap<uint32_t>(stack_arg_base + (i * 8),
|
||||
(uint32_t)args[i + 8]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Execute(thread_state, address)) {
|
||||
return 0xDEADBABE;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ bool RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
|||
|
||||
low_address_ = base_address;
|
||||
high_address_ = base_address + file_length;
|
||||
|
||||
// Notify backend about executable code.
|
||||
processor_->backend()->CommitExecutableRange(low_address_, high_address_);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
|
||||
#include "third_party/xxhash/xxhash.h"
|
||||
|
||||
DEFINE_bool(draw_all_framebuffers, false,
|
||||
"Copy all render targets to screen on swap");
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace gl4 {
|
||||
|
@ -641,6 +644,53 @@ void CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
|
|||
swap_state_.back_buffer_texture, dest_rect,
|
||||
GL_LINEAR);
|
||||
|
||||
if (FLAGS_draw_all_framebuffers) {
|
||||
int32_t offsetx = (1280 - (1280 / 5));
|
||||
int32_t offsety = 0;
|
||||
int32_t doffsetx = 0;
|
||||
for (int i = 0; i < cached_framebuffers_.size(); i++) {
|
||||
bool has_colortargets = false;
|
||||
|
||||
// Copy color targets to top right corner
|
||||
for (int j = 0; j < 4; j++) {
|
||||
GLuint tex = cached_framebuffers_[i].color_targets[j];
|
||||
if (!tex) {
|
||||
continue;
|
||||
}
|
||||
has_colortargets = true;
|
||||
|
||||
dest_rect = {offsetx, offsety, 1280 / 5, 720 / 5};
|
||||
reinterpret_cast<ui::gl::GLContext*>(context_.get())
|
||||
->blitter()
|
||||
->CopyColorTexture2D(tex, src_rect, swap_state_.back_buffer_texture,
|
||||
dest_rect, GL_LINEAR);
|
||||
|
||||
offsety += 720 / 5;
|
||||
}
|
||||
|
||||
if (has_colortargets) {
|
||||
offsetx -= 1280 / 5;
|
||||
}
|
||||
|
||||
offsety = 0;
|
||||
|
||||
GLuint tex = cached_framebuffers_[i].depth_target;
|
||||
if (!tex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy depth targets to bottom left corner of screen
|
||||
dest_rect = {doffsetx, (int32_t)swap_state_.height - (720 / 5), 1280 / 5,
|
||||
720 / 5};
|
||||
reinterpret_cast<ui::gl::GLContext*>(context_.get())
|
||||
->blitter()
|
||||
->CopyColorTexture2D(tex, src_rect, swap_state_.back_buffer_texture,
|
||||
dest_rect, GL_LINEAR);
|
||||
|
||||
doffsetx += 1280 / 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to finish to be sure the other context sees the right data.
|
||||
// TODO(benvanik): prevent this? fences?
|
||||
glFinish();
|
||||
|
|
|
@ -142,12 +142,12 @@ X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
|
|||
}
|
||||
|
||||
X_STATUS UserModule::Unload() {
|
||||
if (!xex_module()->loaded()) {
|
||||
if (module_format_ == kModuleFormatXex && !xex_module()->loaded()) {
|
||||
// Quick abort.
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (xex_module()->Unload()) {
|
||||
if (module_format_ == kModuleFormatXex && xex_module()->Unload()) {
|
||||
OnUnload();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -505,7 +505,14 @@ void UserModule::Dump() {
|
|||
sb.AppendFormat(" XEX_HEADER_GAME_RATINGS (TODO):\n");
|
||||
} break;
|
||||
case XEX_HEADER_LAN_KEY: {
|
||||
sb.AppendFormat(" XEX_HEADER_LAN_KEY (TODO):\n");
|
||||
sb.AppendFormat(" XEX_HEADER_LAN_KEY:");
|
||||
auto opt_lan_key =
|
||||
reinterpret_cast<const xex2_opt_lan_key*>(opt_header_ptr);
|
||||
|
||||
for (int l = 0; l < 16; l++) {
|
||||
sb.AppendFormat(" %.2X", opt_lan_key->key[l]);
|
||||
}
|
||||
sb.Append("\n");
|
||||
} break;
|
||||
case XEX_HEADER_XBOX360_LOGO: {
|
||||
sb.AppendFormat(" XEX_HEADER_XBOX360_LOGO (TODO):\n");
|
||||
|
|
|
@ -297,6 +297,7 @@ class Result {
|
|||
} // namespace shim
|
||||
|
||||
using int_t = const shim::ParamBase<int32_t>&;
|
||||
using word_t = const shim::ParamBase<uint16_t>&;
|
||||
using dword_t = const shim::ParamBase<uint32_t>&;
|
||||
using qword_t = const shim::ParamBase<uint64_t>&;
|
||||
using float_t = const shim::ParamBase<float>&;
|
||||
|
@ -322,6 +323,9 @@ namespace shim {
|
|||
inline void AppendParam(StringBuffer* string_buffer, int_t param) {
|
||||
string_buffer->AppendFormat("%d", int32_t(param));
|
||||
}
|
||||
inline void AppendParam(StringBuffer* string_buffer, word_t param) {
|
||||
string_buffer->AppendFormat("%.4X", uint16_t(param));
|
||||
}
|
||||
inline void AppendParam(StringBuffer* string_buffer, dword_t param) {
|
||||
string_buffer->AppendFormat("%.8X", uint32_t(param));
|
||||
}
|
||||
|
|
|
@ -468,6 +468,10 @@ union xex2_version {
|
|||
};
|
||||
};
|
||||
|
||||
struct xex2_opt_lan_key {
|
||||
uint8_t key[0x10];
|
||||
};
|
||||
|
||||
struct xex2_opt_bound_path {
|
||||
xe::be<uint32_t> size;
|
||||
char path[1];
|
||||
|
|
|
@ -333,6 +333,13 @@ SHIM_CALL XamContentCreateEx_shim(PPCContext* ppc_context,
|
|||
cache_size, content_size, overlapped_ptr);
|
||||
}
|
||||
|
||||
dword_result_t XamContentOpenFile(dword_t r3, lpstring_t r4, lpstring_t r5,
|
||||
dword_t r6, dword_t r7, dword_t r8,
|
||||
dword_t r9) {
|
||||
return X_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
DECLARE_XAM_EXPORT(XamContentOpenFile, ExportTag::kStub);
|
||||
|
||||
SHIM_CALL XamContentFlush_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t root_name_ptr = SHIM_GET_ARG_32(0);
|
||||
|
|
|
@ -117,6 +117,13 @@ SHIM_CALL NtAllocateVirtualMemory_shim(PPCContext* ppc_context,
|
|||
}
|
||||
uint32_t adjusted_size = xe::round_up(region_size_value, page_size);
|
||||
|
||||
// Some games (BF1943) do this, but then if we return an error code it'll
|
||||
// allocate with a smaller page size.
|
||||
if (base_addr_value % page_size != 0) {
|
||||
SHIM_SET_RETURN_32(X_STATUS_MAPPED_ALIGNMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate.
|
||||
uint32_t allocation_type = 0;
|
||||
if (alloc_type & X_MEM_RESERVE) {
|
||||
|
@ -480,6 +487,7 @@ SHIM_CALL MmGetPhysicalAddress_shim(PPCContext* ppc_context,
|
|||
// _In_ PVOID BaseAddress
|
||||
// );
|
||||
// base_address = result of MmAllocatePhysicalMemory.
|
||||
assert_true(base_address >= 0xA0000000);
|
||||
|
||||
uint32_t physical_address = base_address & 0x1FFFFFFF;
|
||||
if (base_address >= 0xE0000000) {
|
||||
|
@ -514,7 +522,7 @@ SHIM_CALL ExAllocatePoolTypeWithTag_shim(PPCContext* ppc_context,
|
|||
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, %.4s, %d)", size, &tag, zero);
|
||||
|
||||
uint32_t alignment = 8;
|
||||
uint32_t adjusted_size = size;
|
||||
|
|
|
@ -494,33 +494,25 @@ dword_result_t KeResetEvent(pointer_t<X_KEVENT> event_ptr) {
|
|||
DECLARE_XBOXKRNL_EXPORT(KeResetEvent,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t event_type = SHIM_GET_ARG_32(2);
|
||||
uint32_t initial_state = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("NtCreateEvent(%.8X, %.8X, %d, %d)", handle_ptr, obj_attributes_ptr,
|
||||
event_type, initial_state);
|
||||
|
||||
dword_result_t NtCreateEvent(lpdword_t handle_ptr,
|
||||
pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes_ptr,
|
||||
dword_t event_type, dword_t initial_state) {
|
||||
// Check for an existing timer with the same name.
|
||||
auto existing_object =
|
||||
LookupNamedObject<XEvent>(kernel_state, obj_attributes_ptr);
|
||||
LookupNamedObject<XEvent>(kernel_state(), obj_attributes_ptr);
|
||||
if (existing_object) {
|
||||
if (existing_object->type() == XObject::kTypeEvent) {
|
||||
if (handle_ptr) {
|
||||
existing_object->RetainHandle();
|
||||
SHIM_SET_MEM_32(handle_ptr, existing_object->handle());
|
||||
*handle_ptr = existing_object->handle();
|
||||
}
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
return X_STATUS_SUCCESS;
|
||||
} else {
|
||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
|
||||
return X_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
XEvent* ev = new XEvent(kernel_state);
|
||||
XEvent* ev = new XEvent(kernel_state());
|
||||
ev->Initialize(!event_type, !!initial_state);
|
||||
|
||||
// obj_attributes may have a name inside of it, if != NULL.
|
||||
|
@ -529,10 +521,12 @@ SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context,
|
|||
}
|
||||
|
||||
if (handle_ptr) {
|
||||
SHIM_SET_MEM_32(handle_ptr, ev->handle());
|
||||
*handle_ptr = ev->handle();
|
||||
}
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtCreateEvent,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
dword_result_t NtSetEvent(dword_t handle, lpdword_t previous_state_ptr) {
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
@ -1421,8 +1415,6 @@ void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
|
|||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsGetValue, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsSetValue, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateEvent, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateSemaphore, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseSemaphore, state);
|
||||
|
||||
|
|
|
@ -107,6 +107,16 @@ uint32_t XThread::GetCurrentThreadId() {
|
|||
return thread->guest_object<X_KTHREAD>()->thread_id;
|
||||
}
|
||||
|
||||
uint32_t XThread::GetLastError() {
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
return thread->last_error();
|
||||
}
|
||||
|
||||
void XThread::SetLastError(uint32_t error_code) {
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
thread->set_last_error(error_code);
|
||||
}
|
||||
|
||||
uint32_t XThread::last_error() { return guest_object<X_KTHREAD>()->last_error; }
|
||||
|
||||
void XThread::set_last_error(uint32_t error_code) {
|
||||
|
|
|
@ -122,6 +122,9 @@ class XThread : public XObject {
|
|||
static uint32_t GetCurrentThreadHandle();
|
||||
static uint32_t GetCurrentThreadId();
|
||||
|
||||
static uint32_t GetLastError();
|
||||
static void SetLastError(uint32_t error_code);
|
||||
|
||||
const CreationParams* creation_params() const { return &creation_params_; }
|
||||
uint32_t tls_ptr() const { return tls_address_; }
|
||||
uint32_t pcr_ptr() const { return pcr_address_; }
|
||||
|
|
|
@ -66,6 +66,7 @@ typedef uint32_t X_STATUS;
|
|||
#define X_STATUS_INVALID_PARAMETER_2 ((X_STATUS)0xC00000F0L)
|
||||
#define X_STATUS_INVALID_PARAMETER_3 ((X_STATUS)0xC00000F1L)
|
||||
#define X_STATUS_DLL_NOT_FOUND ((X_STATUS)0xC0000135L)
|
||||
#define X_STATUS_MAPPED_ALIGNMENT ((X_STATUS)0xC0000220L)
|
||||
#define X_STATUS_NOT_FOUND ((X_STATUS)0xC0000225L)
|
||||
#define X_STATUS_DRIVER_ORDINAL_NOT_FOUND ((X_STATUS)0xC0000262L)
|
||||
#define X_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((X_STATUS)0xC0000263L)
|
||||
|
|
Loading…
Reference in New Issue