Skip to content

Commit

Permalink
Merge pull request #5486 from sepalani/hle-print
Browse files Browse the repository at this point in the history
HLE: More printf logs added
  • Loading branch information
shuffle2 committed Jun 6, 2017
2 parents 497afbf + ac51c80 commit 065c3d7
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 47 deletions.
1 change: 1 addition & 0 deletions Source/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ set(SRCS
HLE/HLE.cpp
HLE/HLE_Misc.cpp
HLE/HLE_OS.cpp
HLE/HLE_VarArgs.cpp
HW/AudioInterface.cpp
HW/CPU.cpp
HW/DSP.cpp
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
<ClCompile Include="HLE\HLE.cpp" />
<ClCompile Include="HLE\HLE_Misc.cpp" />
<ClCompile Include="HLE\HLE_OS.cpp" />
<ClCompile Include="HLE\HLE_VarArgs.cpp" />
<ClCompile Include="HotkeyManager.cpp" />
<ClCompile Include="HW\AudioInterface.cpp" />
<ClCompile Include="HW\CPU.cpp" />
Expand Down Expand Up @@ -343,6 +344,7 @@
<ClInclude Include="HLE\HLE.h" />
<ClInclude Include="HLE\HLE_Misc.h" />
<ClInclude Include="HLE\HLE_OS.h" />
<ClInclude Include="HLE\HLE_VarArgs.h" />
<ClInclude Include="Host.h" />
<ClInclude Include="HotkeyManager.h" />
<ClInclude Include="HW\AudioInterface.h" />
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/Core/Core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@
<ClCompile Include="HLE\HLE_OS.cpp">
<Filter>HLE</Filter>
</ClCompile>
<ClCompile Include="HLE\HLE_VarArgs.cpp" />
<Filter>HLE</Filter>
</ClCompile>
<ClCompile Include="PowerPC\BreakPoints.cpp">
<Filter>PowerPC</Filter>
</ClCompile>
Expand Down Expand Up @@ -955,6 +958,9 @@
<ClInclude Include="HLE\HLE_OS.h">
<Filter>HLE</Filter>
</ClInclude>
<ClInclude Include="HLE\HLE_VarArgs.h">
<Filter>HLE</Filter>
</ClInclude>
<ClInclude Include="PowerPC\CachedInterpreter\CachedInterpreter.h">
<Filter>PowerPC\Cached Interpreter</Filter>
</ClInclude>
Expand Down
6 changes: 5 additions & 1 deletion Source/Core/Core/HLE/HLE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,12 @@ static const SPatch OSPatches[] = {
{"OSReport", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"vprintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"vprintf", HLE_OS::HLE_GeneralDebugVPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"printf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"vdprintf", HLE_OS::HLE_LogVDPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"dprintf", HLE_OS::HLE_LogDPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"vfprintf", HLE_OS::HLE_LogVFPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"fprintf", HLE_OS::HLE_LogFPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"nlPrintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
{"puts", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG}, // gcc-optimized printf?
{"___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG}, // used for early init things (normally)
Expand Down
152 changes: 106 additions & 46 deletions Source/Core/Core/HLE/HLE_OS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <memory>
#include <string>

#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
#include "Core/HLE/HLE_OS.h"
#include "Core/HLE/HLE_VarArgs.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h"

namespace HLE_OS
{
std::string GetStringVA(u32 strReg = 3);
enum class ParameterType : bool
{
ParameterList = false,
VariableArgumentList = true
};

std::string GetStringVA(u32 str_reg = 3,
ParameterType parameter_type = ParameterType::ParameterList);

void HLE_OSPanic()
{
Expand All @@ -27,8 +36,8 @@ void HLE_OSPanic()
NPC = LR;
}

// Generalized func for just printing string pointed to by r3.
void HLE_GeneralDebugPrint()
// Generalized function for printing formatted string.
void HLE_GeneralDebugPrint(ParameterType parameter_type)
{
std::string report_message;

Expand All @@ -38,25 +47,25 @@ void HLE_GeneralDebugPrint()
if (PowerPC::HostIsRAMAddress(GPR(4)))
{
// ___blank(void* this, const char* fmt, ...);
report_message = GetStringVA(4);
report_message = GetStringVA(4, parameter_type);
}
else
{
// ___blank(void* this, int log_type, const char* fmt, ...);
report_message = GetStringVA(5);
report_message = GetStringVA(5, parameter_type);
}
}
else
{
if (PowerPC::HostIsRAMAddress(GPR(3)))
{
// ___blank(const char* fmt, ...);
report_message = GetStringVA();
report_message = GetStringVA(3, parameter_type);
}
else
{
// ___blank(int log_type, const char* fmt, ...);
report_message = GetStringVA(4);
report_message = GetStringVA(4, parameter_type);
}
}

Expand All @@ -65,6 +74,18 @@ void HLE_GeneralDebugPrint()
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
}

// Generalized function for printing formatted string using parameter list.
void HLE_GeneralDebugPrint()
{
HLE_GeneralDebugPrint(ParameterType::ParameterList);
}

// Generalized function for printing formatted string using va_list.
void HLE_GeneralDebugVPrint()
{
HLE_GeneralDebugPrint(ParameterType::VariableArgumentList);
}

// __write_console(int fd, const void* buffer, const u32* size)
void HLE_write_console()
{
Expand All @@ -89,14 +110,79 @@ void HLE_write_console()
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
}

std::string GetStringVA(u32 strReg)
// Log (v)dprintf message if fd is 1 (stdout) or 2 (stderr)
void HLE_LogDPrint(ParameterType parameter_type)
{
std::string ArgumentBuffer;
u32 ParameterCounter = strReg + 1;
u32 FloatingParameterCounter = 1;
NPC = LR;

if (GPR(3) != 1 && GPR(3) != 2)
return;

std::string report_message = GetStringVA(4, parameter_type);
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
}

// Log dprintf message
// -> int dprintf(int fd, const char* format, ...);
void HLE_LogDPrint()
{
HLE_LogDPrint(ParameterType::ParameterList);
}

// Log vdprintf message
// -> int vdprintf(int fd, const char* format, va_list ap);
void HLE_LogVDPrint()
{
HLE_LogDPrint(ParameterType::VariableArgumentList);
}

// Log (v)fprintf message if FILE is stdout or stderr
void HLE_LogFPrint(ParameterType parameter_type)
{
NPC = LR;

// The structure FILE is implementation defined.
// Both libogc and Dolphin SDK seem to store the fd at the same address.
int fd = -1;
if (PowerPC::HostIsRAMAddress(GPR(3)) && PowerPC::HostIsRAMAddress(GPR(3) + 0xF))
{
// The fd is stored as a short at FILE+0xE.
fd = static_cast<short>(PowerPC::HostRead_U16(GPR(3) + 0xE));
}
if (fd != 1 && fd != 2)
{
// On RVL SDK it seems stored at FILE+0x2.
fd = static_cast<short>(PowerPC::HostRead_U16(GPR(3) + 0x2));
}
if (fd != 1 && fd != 2)
return;

std::string report_message = GetStringVA(4, parameter_type);
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
}

// Log fprintf message
// -> int fprintf(FILE* stream, const char* format, ...);
void HLE_LogFPrint()
{
HLE_LogFPrint(ParameterType::ParameterList);
}

// Log vfprintf message
// -> int vfprintf(FILE* stream, const char* format, va_list ap);
void HLE_LogVFPrint()
{
HLE_LogFPrint(ParameterType::VariableArgumentList);
}

std::string GetStringVA(u32 str_reg, ParameterType parameter_type)
{
std::string ArgumentBuffer;
std::string result;
std::string string = PowerPC::HostGetString(GPR(strReg));
std::string string = PowerPC::HostGetString(GPR(str_reg));
auto ap = parameter_type == ParameterType::VariableArgumentList ?
std::make_unique<HLE::SystemVABI::VAListStruct>(GPR(str_reg + 1)) :
std::make_unique<HLE::SystemVABI::VAList>(GPR(1) + 0x8, str_reg + 1);

for (size_t i = 0; i < string.size(); i++)
{
Expand All @@ -120,38 +206,13 @@ std::string GetStringVA(u32 strReg)

ArgumentBuffer += string[i];

u64 Parameter;
if (ParameterCounter > 10)
{
Parameter = PowerPC::HostRead_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4));
}
else
{
if (string[i - 1] == 'l' &&
string[i - 2] == 'l') // hax, just seen this on sysmenu osreport
{
Parameter = GPR(++ParameterCounter);
Parameter = (Parameter << 32) | GPR(++ParameterCounter);
}
else // normal, 32bit
Parameter = GPR(ParameterCounter);
}
ParameterCounter++;

switch (string[i])
{
case 's':
result += StringFromFormat(ArgumentBuffer.c_str(),
PowerPC::HostGetString((u32)Parameter).c_str());
PowerPC::HostGetString(ap->GetArgT<u32>()).c_str());
break;

case 'd':
case 'i':
{
result += StringFromFormat(ArgumentBuffer.c_str(), Parameter);
break;
}

case 'a':
case 'A':
case 'e':
Expand All @@ -160,25 +221,24 @@ std::string GetStringVA(u32 strReg)
case 'F':
case 'g':
case 'G':
{
result += StringFromFormat(ArgumentBuffer.c_str(), rPS0(FloatingParameterCounter));
FloatingParameterCounter++;
ParameterCounter--;
result += StringFromFormat(ArgumentBuffer.c_str(), ap->GetArgT<double>());
break;
}

case 'p':
// Override, so 64bit Dolphin prints 32bit pointers, since the ppc is 32bit :)
result += StringFromFormat("%x", (u32)Parameter);
result += StringFromFormat("%x", ap->GetArgT<u32>());
break;

case 'n':
PowerPC::HostWrite_U32(static_cast<u32>(result.size()), static_cast<u32>(Parameter));
// %n doesn't output anything, so the result variable is untouched
PowerPC::HostWrite_U32(static_cast<u32>(result.size()), ap->GetArgT<u32>());
break;

default:
result += StringFromFormat(ArgumentBuffer.c_str(), Parameter);
if (string[i - 1] == 'l' && string[i - 2] == 'l')
result += StringFromFormat(ArgumentBuffer.c_str(), ap->GetArgT<u64>());
else
result += StringFromFormat(ArgumentBuffer.c_str(), ap->GetArgT<u32>());
break;
}
}
Expand Down
5 changes: 5 additions & 0 deletions Source/Core/Core/HLE/HLE_OS.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
namespace HLE_OS
{
void HLE_GeneralDebugPrint();
void HLE_GeneralDebugVPrint();
void HLE_write_console();
void HLE_OSPanic();
void HLE_LogDPrint();
void HLE_LogVDPrint();
void HLE_LogFPrint();
void HLE_LogVFPrint();
}
67 changes: 67 additions & 0 deletions Source/Core/Core/HLE/HLE_VarArgs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "Core/HLE/HLE_VarArgs.h"

#include "Common/Logging/Log.h"

HLE::SystemVABI::VAList::~VAList() = default;

u32 HLE::SystemVABI::VAList::GetGPR(u32 gpr) const
{
return GPR(gpr);
}

double HLE::SystemVABI::VAList::GetFPR(u32 fpr) const
{
return rPS0(fpr);
}

HLE::SystemVABI::VAListStruct::VAListStruct(u32 address)
: VAList(0), m_va_list{PowerPC::HostRead_U8(address), PowerPC::HostRead_U8(address + 1),
PowerPC::HostRead_U32(address + 4), PowerPC::HostRead_U32(address + 8)},
m_address(address), m_has_fpr_area(GetCRBit(6) == 1)
{
m_stack = m_va_list.overflow_arg_area;
m_gpr += m_va_list.gpr;
m_fpr += m_va_list.fpr;
}

u32 HLE::SystemVABI::VAListStruct::GetGPRArea() const
{
return m_va_list.reg_save_area;
}

u32 HLE::SystemVABI::VAListStruct::GetFPRArea() const
{
return GetGPRArea() + 4 * 8;
}

u32 HLE::SystemVABI::VAListStruct::GetGPR(u32 gpr) const
{
if (gpr < 3 || gpr > 10)
{
ERROR_LOG(OSHLE, "VAListStruct at %08x doesn't have GPR%d!", m_address, gpr);
return 0;
}
const u32 gpr_address = Common::AlignUp(GetGPRArea() + 4 * (gpr - 3), 4);
return PowerPC::HostRead_U32(gpr_address);
}

double HLE::SystemVABI::VAListStruct::GetFPR(u32 fpr) const
{
double value = 0.0;

if (!m_has_fpr_area || fpr < 1 || fpr > 8)
{
ERROR_LOG(OSHLE, "VAListStruct at %08x doesn't have FPR%d!", m_address, fpr);
}
else
{
const u32 fpr_address = Common::AlignUp(GetFPRArea() + 8 * (fpr - 1), 8);
const u64 integral = PowerPC::HostRead_U64(fpr_address);
std::memcpy(&value, &integral, sizeof(double));
}
return value;
}

0 comments on commit 065c3d7

Please sign in to comment.