Files
Xenia-Canary/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc
Ben Vanik fdb6a5cfa3 Initial Alloy implementation.
This is a regression in functionality and performance, but a much better
foundation for the future of the project (I think). It can run basic
apps under an SSA interpreter but doesn't support some of the features
required to do real 360 apps yet.
2013-12-06 22:57:16 -08:00

255 lines
5.2 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/kernel/xboxkrnl/xboxkrnl_debug.h>
#include <xenia/kernel/shim_utils.h>
#include <xenia/kernel/xboxkrnl/kernel_state.h>
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
#include <xenia/kernel/xboxkrnl/objects/xthread.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xboxkrnl;
namespace xe {
namespace kernel {
namespace xboxkrnl {
// TODO: clean me up!
SHIM_CALL DbgPrint_shim(
PPCContext* ppc_state, KernelState* state) {
uint32_t format_ptr = SHIM_GET_ARG_32(0);
if (format_ptr == 0) {
SHIM_SET_RETURN(-1);
return;
}
const char *format = (const char *)SHIM_MEM_ADDR(format_ptr);
int arg_index = 0;
char buffer[512]; // TODO: ensure it never writes past the end of the buffer...
char *b = buffer;
for (; *format != '\0'; ++format) {
const char *start = format;
if (*format != '%') {
*b++ = *format;
continue;
}
++format;
if (*format == '\0') {
break;
}
if (*format == '%') {
*b++ = *format;
continue;
}
const char *end;
end = format;
// skip flags
while (*end == '-' ||
*end == '+' ||
*end == ' ' ||
*end == '#' ||
*end == '0') {
++end;
}
if (*end == '\0') {
break;
}
int arg_extras = 0;
// skip width
if (*end == '*') {
++end;
arg_extras++;
}
else {
while (*end >= '0' && *end <= '9') {
++end;
}
}
if (*end == '\0') {
break;
}
// skip precision
if (*end == '.') {
++end;
if (*end == '*') {
++end;
++arg_extras;
}
else {
while (*end >= '0' && *end <= '9') {
++end;
}
}
}
if (*end == '\0') {
break;
}
// get length
int arg_size = 4;
if (*end == 'h') {
++end;
arg_size = 4;
if (*end == 'h') {
++end;
}
}
else if (*end == 'l') {
++end;
arg_size = 4;
if (*end == 'l') {
++end;
arg_size = 8;
}
}
else if (*end == 'j') {
arg_size = 8;
++end;
}
else if (*end == 'z') {
arg_size = 4;
++end;
}
else if (*end == 't') {
arg_size = 8;
++end;
}
else if (*end == 'L') {
arg_size = 8;
++end;
}
if (*end == '\0') {
break;
}
if (*end == 'd' ||
*end == 'i' ||
*end == 'u' ||
*end == 'o' ||
*end == 'x' ||
*end == 'X' ||
*end == 'f' ||
*end == 'F' ||
*end == 'e' ||
*end == 'E' ||
*end == 'g' ||
*end == 'G' ||
*end == 'a' ||
*end == 'A' ||
*end == 'c') {
char local[512];
local[0] = '\0';
strncat(local, start, end + 1 - start);
XEASSERT(arg_size == 8 || arg_size == 4);
if (arg_size == 8) {
if (arg_extras == 0) {
uint64_t value = arg_index < 7
? SHIM_GET_ARG_64(1 + arg_index)
: SHIM_MEM_32(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
int result = sprintf(b, local, value);
b += result;
arg_index++;
}
else {
XEASSERT(false);
}
}
else if (arg_size == 4) {
if (arg_extras == 0) {
uint64_t value = arg_index < 7
? SHIM_GET_ARG_64(1 + arg_index)
: SHIM_MEM_32(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
int result = sprintf(b, local, (uint32_t)value);
b += result;
arg_index++;
}
else {
XEASSERT(false);
}
}
}
else if (*end == 's' ||
*end == 'p' ||
*end == 'n') {
char local[512];
local[0] = '\0';
strncat(local, start, end + 1 - start);
XEASSERT(arg_size == 4);
if (arg_extras == 0) {
uint32_t value = arg_index < 7
? SHIM_GET_ARG_32(1 + arg_index)
: (uint32_t)SHIM_MEM_64(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
const char *pointer = (const char *)SHIM_MEM_ADDR(value);
int result = sprintf(b, local, pointer);
b += result;
arg_index++;
}
else {
XEASSERT(false);
}
}
else {
XEASSERT(false);
break;
}
format = end;
}
*b++ = '\0';
XELOGD("(DbgPrint) %s", buffer);
}
void xeDbgBreakPoint() {
DebugBreak();
}
SHIM_CALL DbgBreakPoint_shim(
PPCContext* ppc_state, KernelState* state) {
XELOGD("DbgBreakPoint()");
}
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe
void xe::kernel::xboxkrnl::RegisterDebugExports(
ExportResolver* export_resolver, KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", DbgPrint, state);
SHIM_SET_MAPPING("xboxkrnl.exe", DbgBreakPoint, state);
}