Fixing printfs and fixing exports. link.exe is too good.

This commit is contained in:
Ben Vanik 2015-06-01 21:40:53 -07:00
parent a91a754b24
commit 5c34b0a73e
13 changed files with 88 additions and 81 deletions

View File

@ -411,7 +411,7 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, const Reg64& reg) {
uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) { uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
auto symbol_info = reinterpret_cast<FunctionInfo*>(symbol_info_ptr); auto symbol_info = reinterpret_cast<FunctionInfo*>(symbol_info_ptr);
XELOGW("undefined extern call to %.8llX %s", symbol_info->address(), XELOGW("undefined extern call to %.8X %s", symbol_info->address(),
symbol_info->name().c_str()); symbol_info->name().c_str());
return 0; return 0;
} }

View File

@ -447,7 +447,7 @@ xe::cpu::Export* RegisterExport(void (*fn)(Ps&...), std::string name,
using xe::cpu::ExportTag; using xe::cpu::ExportTag;
#define DECLARE_EXPORT(module_name, name, tags) \ #define DECLARE_EXPORT(module_name, name, tags) \
auto EXPORT_##module_name##_##name = \ const auto EXPORT_##module_name##_##name = \
RegisterExport_##module_name(xe::kernel::shim::RegisterExport< \ RegisterExport_##module_name(xe::kernel::shim::RegisterExport< \
xe::kernel::shim::KernelModuleId::module_name, ordinals::##name>( \ xe::kernel::shim::KernelModuleId::module_name, ordinals::##name>( \
&name, std::string(#name), tags)); &name, std::string(#name), tags));

View File

@ -29,6 +29,8 @@ XamModule::XamModule(Emulator* emulator, KernelState* kernel_state)
xam::RegisterNotifyExports(export_resolver_, kernel_state_); xam::RegisterNotifyExports(export_resolver_, kernel_state_);
xam::RegisterUIExports(export_resolver_, kernel_state_); xam::RegisterUIExports(export_resolver_, kernel_state_);
xam::RegisterUserExports(export_resolver_, kernel_state_); xam::RegisterUserExports(export_resolver_, kernel_state_);
xam::RegisterVideoExports(export_resolver_, kernel_state_);
xam::RegisterVoiceExports(export_resolver_, kernel_state_);
} }
std::vector<xe::cpu::Export*> xam_exports; std::vector<xe::cpu::Export*> xam_exports;

View File

@ -38,6 +38,10 @@ void RegisterUIExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterUserExports(xe::cpu::ExportResolver* export_resolver, void RegisterUserExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state);
void RegisterVoiceExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state);
} // namespace xam } // namespace xam
} // namespace kernel } // namespace kernel

View File

@ -29,3 +29,6 @@ DECLARE_XAM_EXPORT(XGetVideoCapabilities, ExportTag::kVideo | ExportTag::kStub);
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe
void xe::kernel::xam::RegisterVideoExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}

View File

@ -40,3 +40,6 @@ DECLARE_XAM_EXPORT(XamVoiceHeadsetPresent, ExportTag::kStub);
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe
void xe::kernel::xam::RegisterVoiceExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}

View File

@ -104,3 +104,6 @@ DECLARE_XBOXKRNL_EXPORT(KeBugCheck, ExportTag::kImportant);
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe
void xe::kernel::xboxkrnl::RegisterDebugExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}

View File

@ -837,3 +837,6 @@ DECLARE_XBOXKRNL_EXPORT(RtlNtStatusToDosError,
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe
void xe::kernel::xboxkrnl::RegisterErrorExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}

View File

@ -32,3 +32,6 @@ DECLARE_XBOXKRNL_EXPORT(HalReturnToFirmware, ExportTag::kImportant);
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe
void xe::kernel::xboxkrnl::RegisterHalExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}

View File

@ -30,6 +30,9 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// Register all exported functions. // Register all exported functions.
xboxkrnl::RegisterAudioExports(export_resolver_, kernel_state_); xboxkrnl::RegisterAudioExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterAudioXmaExports(export_resolver_, kernel_state_); xboxkrnl::RegisterAudioXmaExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterDebugExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterErrorExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterHalExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterIoExports(export_resolver_, kernel_state_); xboxkrnl::RegisterIoExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterMemoryExports(export_resolver_, kernel_state_); xboxkrnl::RegisterMemoryExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterMiscExports(export_resolver_, kernel_state_); xboxkrnl::RegisterMiscExports(export_resolver_, kernel_state_);
@ -38,6 +41,7 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
xboxkrnl::RegisterRtlExports(export_resolver_, kernel_state_); xboxkrnl::RegisterRtlExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterStringExports(export_resolver_, kernel_state_); xboxkrnl::RegisterStringExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterThreadingExports(export_resolver_, kernel_state_); xboxkrnl::RegisterThreadingExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterUsbcamExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterVideoExports(export_resolver_, kernel_state_); xboxkrnl::RegisterVideoExports(export_resolver_, kernel_state_);
// KeDebugMonitorData (?*) // KeDebugMonitorData (?*)

View File

@ -25,6 +25,12 @@ void RegisterAudioExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterAudioXmaExports(xe::cpu::ExportResolver* export_resolver, void RegisterAudioXmaExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterDebugExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state);
void RegisterErrorExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state);
void RegisterHalExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state);
void RegisterIoExports(xe::cpu::ExportResolver* export_resolver, void RegisterIoExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterMemoryExports(xe::cpu::ExportResolver* export_resolver, void RegisterMemoryExports(xe::cpu::ExportResolver* export_resolver,
@ -41,6 +47,8 @@ void RegisterStringExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver, void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
void RegisterUsbcamExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state);
void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver, void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state); KernelState* kernel_state);
} // namespace xboxkrnl } // namespace xboxkrnl

View File

@ -58,7 +58,7 @@ enum ArgumentSize {
}; };
class FormatData { class FormatData {
public: public:
virtual uint16_t get() = 0; virtual uint16_t get() = 0;
virtual uint16_t peek(int32_t offset) = 0; virtual uint16_t peek(int32_t offset) = 0;
virtual void skip(int32_t count) = 0; virtual void skip(int32_t count) = 0;
@ -66,19 +66,21 @@ public:
}; };
class ArgList { class ArgList {
public: public:
virtual uint32_t get32() = 0; virtual uint32_t get32() = 0;
virtual uint64_t get64() = 0; virtual uint64_t get64() = 0;
}; };
/* Making the assumption that the Xbox 360's implementation of the printf-functions /* Making the assumption that the Xbox 360's implementation of the
*printf-functions
* matches what is described on MSDN's documentation for the Windows CRT: * matches what is described on MSDN's documentation for the Windows CRT:
* *
* "Format Specification Syntax: printf and wprintf Functions" * "Format Specification Syntax: printf and wprintf Functions"
* https://msdn.microsoft.com/en-us/library/56e442dc.aspx * https://msdn.microsoft.com/en-us/library/56e442dc.aspx
*/ */
std::string format_double(double value, int32_t precision, uint16_t c, uint32_t flags) { std::string format_double(double value, int32_t precision, uint16_t c,
uint32_t flags) {
if (precision < 0) { if (precision < 0) {
precision = 6; precision = 6;
} else if (precision == 0 && c == 'g') { } else if (precision == 0 && c == 'g') {
@ -110,7 +112,8 @@ std::string format_double(double value, int32_t precision, uint16_t c, uint32_t
return temp.str(); return temp.str();
} }
int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, const bool wide) { int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args,
const bool wide) {
int32_t count = 0; int32_t count = 0;
char work[512]; char work[512];
@ -143,12 +146,12 @@ int32_t format_core(PPCContext* ppc_context, FormatData& data, ArgList& args, co
prefix.buffer[0] = '\0'; prefix.buffer[0] = '\0';
prefix.length = 0; prefix.length = 0;
for (uint16_t c = data.get(); ; c = data.get()) { for (uint16_t c = data.get();; c = data.get()) {
if (state == FS_Unknown) { if (state == FS_Unknown) {
if (!c) { // the end if (!c) { // the end
return count; return count;
} else if (c != '%') { } else if (c != '%') {
output: output:
data.put(c); data.put(c);
++count; ++count;
continue; continue;
@ -164,7 +167,7 @@ output:
return -1; return -1;
} }
restart: restart:
switch (state) { switch (state) {
case FS_Start: { case FS_Start: {
if (c == '%') { if (c == '%') {
@ -295,8 +298,7 @@ restart:
data.skip(2); data.skip(2);
state = FS_Type; state = FS_Type;
continue; continue;
} } else {
else {
state = FS_Type; state = FS_Type;
continue; continue;
} }
@ -344,7 +346,7 @@ restart:
digits = "0123456789"; digits = "0123456789";
radix = 10; radix = 10;
integer: integer:
assert_not_null(digits); assert_not_null(digits);
assert_not_zero(radix); assert_not_zero(radix);
@ -390,7 +392,8 @@ restart:
*--start = digits[digit]; *--start = digits[digit];
} }
if ((flags & FF_ForceLeadingZero) && (start == end || *start != '0')) { if ((flags & FF_ForceLeadingZero) &&
(start == end || *start != '0')) {
*--start = '0'; *--start = '0';
} }
@ -440,7 +443,7 @@ restart:
// floating-point without exponent // floating-point without exponent
case 'f': { case 'f': {
floatingpoint: floatingpoint:
flags |= FF_IsSigned; flags |= FF_IsSigned;
int64_t dummy = args.get64(); int64_t dummy = args.get64();
@ -547,9 +550,7 @@ restart:
assert_always(); assert_always();
} }
default: { default: { assert_always(); }
assert_always();
}
} }
} }
} }
@ -589,7 +590,8 @@ restart:
} }
} }
if ((flags & FF_AddLeadingZeros) && !(flags & (FF_LeftJustify)) && padding > 0) { if ((flags & FF_AddLeadingZeros) && !(flags & (FF_LeftJustify)) &&
padding > 0) {
count += padding; count += padding;
while (padding-- > 0) { while (padding-- > 0) {
if (!data.put('0')) { if (!data.put('0')) {
@ -643,16 +645,10 @@ restart:
} }
class StackArgList : public ArgList { class StackArgList : public ArgList {
public: public:
StackArgList(PPCContext* ppc_context) StackArgList(PPCContext* ppc_context) : ppc_context(ppc_context), index_(2) {}
: ppc_context(ppc_context)
, index_(2)
{
}
uint32_t get32() { uint32_t get32() { return (uint32_t)get64(); }
return (uint32_t)get64();
}
uint64_t get64() { uint64_t get64() {
auto value = SHIM_GET_ARG_64(2 + index_); auto value = SHIM_GET_ARG_64(2 + index_);
@ -660,23 +656,17 @@ public:
return value; return value;
} }
private: private:
PPCContext* ppc_context; PPCContext* ppc_context;
int32_t index_; int32_t index_;
}; };
class ArrayArgList : public ArgList { class ArrayArgList : public ArgList {
public: public:
ArrayArgList(PPCContext* ppc_context, uint32_t arg_ptr) ArrayArgList(PPCContext* ppc_context, uint32_t arg_ptr)
: ppc_context(ppc_context) : ppc_context(ppc_context), arg_ptr_(arg_ptr), index_(0) {}
, arg_ptr_(arg_ptr)
, index_(0)
{
}
uint32_t get32() { uint32_t get32() { return (uint32_t)get64(); }
return (uint32_t)get64();
}
uint64_t get64() { uint64_t get64() {
auto value = SHIM_MEM_64(arg_ptr_ + (8 * index_)); auto value = SHIM_MEM_64(arg_ptr_ + (8 * index_));
@ -684,18 +674,15 @@ public:
return value; return value;
} }
private: private:
PPCContext* ppc_context; PPCContext* ppc_context;
uint32_t arg_ptr_; uint32_t arg_ptr_;
int32_t index_; int32_t index_;
}; };
class StringFormatData : public FormatData { class StringFormatData : public FormatData {
public: public:
StringFormatData(const uint8_t* input) StringFormatData(const uint8_t* input) : input_(input) {}
: input_(input)
{
}
uint16_t get() { uint16_t get() {
uint16_t result = *input_; uint16_t result = *input_;
@ -705,9 +692,7 @@ public:
return result; return result;
} }
uint16_t peek(int32_t offset) { uint16_t peek(int32_t offset) { return input_[offset]; }
return input_[offset];
}
void skip(int32_t count) { void skip(int32_t count) {
while (count-- > 0) { while (count-- > 0) {
@ -725,21 +710,16 @@ public:
return true; return true;
} }
const std::string& str() const { std::string str() const { return output_.str(); }
return output_.str();
}
private: private:
const uint8_t* input_; const uint8_t* input_;
std::ostringstream output_; std::ostringstream output_;
}; };
class WideStringFormatData : public FormatData { class WideStringFormatData : public FormatData {
public: public:
WideStringFormatData(const uint16_t* input) WideStringFormatData(const uint16_t* input) : input_(input) {}
: input_(input)
{
}
uint16_t get() { uint16_t get() {
uint16_t result = *input_; uint16_t result = *input_;
@ -749,9 +729,7 @@ public:
return xe::byte_swap(result); return xe::byte_swap(result);
} }
uint16_t peek(int32_t offset) { uint16_t peek(int32_t offset) { return input_[offset]; }
return input_[offset];
}
void skip(int32_t count) { void skip(int32_t count) {
while (count-- > 0) { while (count-- > 0) {
@ -766,21 +744,16 @@ public:
return true; return true;
} }
const std::wstring& wstr() const { std::wstring wstr() const { return output_.str(); }
return output_.str();
}
private: private:
const uint16_t* input_; const uint16_t* input_;
std::wostringstream output_; std::wostringstream output_;
}; };
class WideCountFormatData : public FormatData { class WideCountFormatData : public FormatData {
public: public:
WideCountFormatData(const uint16_t* input) WideCountFormatData(const uint16_t* input) : input_(input), count_(0) {}
: input_(input), count_(0)
{
}
uint16_t get() { uint16_t get() {
uint16_t result = *input_; uint16_t result = *input_;
@ -790,9 +763,7 @@ public:
return xe::byte_swap(result); return xe::byte_swap(result);
} }
uint16_t peek(int32_t offset) { uint16_t peek(int32_t offset) { return input_[offset]; }
return input_[offset];
}
void skip(int32_t count) { void skip(int32_t count) {
while (count-- > 0) { while (count-- > 0) {
@ -807,11 +778,9 @@ public:
return true; return true;
} }
const int32_t count() const { const int32_t count() const { return count_; }
return count_;
}
private: private:
const uint16_t* input_; const uint16_t* input_;
int32_t count_; int32_t count_;
}; };
@ -880,9 +849,10 @@ SHIM_CALL _vsnprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) {
uint32_t format_ptr = SHIM_GET_ARG_32(2); uint32_t format_ptr = SHIM_GET_ARG_32(2);
uint32_t arg_ptr = SHIM_GET_ARG_32(3); uint32_t arg_ptr = SHIM_GET_ARG_32(3);
XELOGD("_vsnprintf(%08X, %i, %08X, %08X)", buffer_ptr, buffer_count, format_ptr, arg_ptr); XELOGD("_vsnprintf(%08X, %i, %08X, %08X)", buffer_ptr, buffer_count,
format_ptr, arg_ptr);
if (buffer_ptr == 0 || buffer_count<= 0 || format_ptr == 0) { if (buffer_ptr == 0 || buffer_count <= 0 || format_ptr == 0) {
SHIM_SET_RETURN_32(-1); SHIM_SET_RETURN_32(-1);
return; return;
} }
@ -896,16 +866,17 @@ SHIM_CALL _vsnprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) {
int32_t count = format_core(ppc_context, data, args, false); int32_t count = format_core(ppc_context, data, args, false);
if (count < 0) { if (count < 0) {
if (buffer_count > 0) { if (buffer_count > 0) {
buffer[0] = '\0'; // write a null, just to be safe buffer[0] = '\0'; // write a null, just to be safe
} }
} if (count <= buffer_count) { }
if (count <= buffer_count) {
std::memcpy(buffer, data.str().c_str(), count); std::memcpy(buffer, data.str().c_str(), count);
if (count < buffer_count) { if (count < buffer_count) {
buffer[count] = '\0'; buffer[count] = '\0';
} }
} else { } else {
std::memcpy(buffer, data.str().c_str(), buffer_count); std::memcpy(buffer, data.str().c_str(), buffer_count);
count = -1; // for return value count = -1; // for return value
} }
SHIM_SET_RETURN_32(count); SHIM_SET_RETURN_32(count);
} }

View File

@ -32,3 +32,6 @@ DECLARE_XBOXKRNL_EXPORT(XUsbcamGetState, ExportTag::kStub);
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe
void xe::kernel::xboxkrnl::RegisterUsbcamExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}