1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00

_sys_sprintf implemented

_sys_printf, _sys_snprintf fixed
This commit is contained in:
Nekotekina 2017-03-26 00:25:28 +03:00
parent 8590b66b4b
commit e8984d976c
2 changed files with 54 additions and 151 deletions

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "Utilities/cfmt.h"
namespace vm { using namespace ps3; }
@ -7,146 +8,54 @@ extern logs::channel sysPrxForUser;
extern fs::file g_tty;
// TODO
// cfmt implementation (TODO)
struct ps3_fmt_src
{
ppu_thread* ctx;
u32 g_count;
bool test(std::size_t index) const
{
return true;
}
template <typename T>
T get(std::size_t index) const
{
const u32 i = (u32)index + g_count;
return ppu_gpr_cast<T>(i < 8 ? ctx->gpr[3 + i] : +*ctx->get_stack_arg(i));
}
void skip(std::size_t extra)
{
++g_count += (u32)extra;
}
std::size_t fmt_string(std::string& out, std::size_t extra) const
{
const std::size_t start = out.size();
out += vm::ps3::_ptr<const char>(get<u32>(extra));
return out.size() - start;
}
std::size_t type(std::size_t extra) const
{
return 0;
}
};
template <>
f64 ps3_fmt_src::get<f64>(std::size_t index) const
{
const u64 value = get<u64>(index);
return *reinterpret_cast<const f64*>(reinterpret_cast<const u8*>(&value));
}
static std::string ps3_fmt(ppu_thread& context, vm::cptr<char> fmt, u32 g_count)
{
std::string result;
for (char c = *fmt++; c; c = *fmt++)
{
switch (c)
{
case '%':
{
const auto start = fmt - 1;
// read flags
const bool plus_sign = *fmt == '+' ? fmt++, true : false;
const bool minus_sign = *fmt == '-' ? fmt++, true : false;
const bool space_sign = *fmt == ' ' ? fmt++, true : false;
const bool number_sign = *fmt == '#' ? fmt++, true : false;
const bool zero_padding = *fmt == '0' ? fmt++, true : false;
// read width
const u32 width = [&]() -> u32
{
u32 width = 0;
if (*fmt == '*')
{
fmt++;
return context.get_next_arg(g_count);
}
while (*fmt - '0' < 10)
{
width = width * 10 + (*fmt++ - '0');
}
return width;
}();
// read precision
const u32 prec = [&]() -> u32
{
u32 prec = 0;
if (*fmt != '.')
{
return 0;
}
if (*++fmt == '*')
{
fmt++;
return context.get_next_arg(g_count);
}
while (*fmt - '0' < 10)
{
prec = prec * 10 + (*fmt++ - '0');
}
return prec;
}();
switch (char cf = *fmt++)
{
case '%':
{
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
result += '%';
continue;
}
case 'd':
case 'i':
{
// signed decimal
const s64 value = context.get_next_arg(g_count);
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
result += fmt::format("%lld", value);
continue;
}
case 'x':
case 'X':
{
// hexadecimal
const u64 value = context.get_next_arg(g_count);
if (plus_sign || minus_sign || space_sign || prec) break;
if (number_sign && value)
{
result += cf == 'x' ? "0x" : "0X";
}
const std::string& hex = fmt::format(cf == 'x' ? "%llx" : "%llX", value);
if (hex.length() >= width)
{
result += hex;
}
else if (zero_padding)
{
result += std::string(width - hex.length(), '0') + hex;
}
else
{
result += hex + std::string(width - hex.length(), ' ');
}
continue;
}
case 's':
{
// string
auto string = vm::cptr<char, u64>::make(context.get_next_arg(g_count));
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
result += string.get_ptr();
continue;
}
case 'u':
{
// unsigned decimal
const u64 value = context.get_next_arg(g_count);
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
result += fmt::format("%llu", value);
continue;
}
}
fmt::throw_exception("Unknown formatting: '%s'" HERE, start.get_ptr());
}
}
result += c;
}
cfmt_append(result, fmt.get_ptr(), ps3_fmt_src{&context, g_count});
return result;
}
@ -316,7 +225,7 @@ s32 _sys_snprintf(ppu_thread& ppu, vm::ptr<char> dst, u32 count, vm::cptr<char>
{
count = (u32)std::min<size_t>(count - 1, result.size());
memcpy(dst.get_ptr(), result.c_str(), count);
std::memcpy(dst.get_ptr(), result.c_str(), count);
dst[count] = 0;
return count;
}
@ -334,9 +243,15 @@ s32 _sys_printf(ppu_thread& ppu, vm::cptr<char> fmt, ppu_va_args_t va_args)
return CELL_OK;
}
s32 _sys_sprintf()
s32 _sys_sprintf(ppu_thread& ppu, vm::ptr<char> buffer, vm::cptr<char> fmt, ppu_va_args_t va_args)
{
fmt::throw_exception("Unimplemented" HERE);
sysPrxForUser.warning("_sys_sprintf(buffer=*0x%x, fmt=%s, ...)", buffer, fmt);
std::string result = ps3_fmt(ppu, fmt, va_args.count);
std::memcpy(buffer.get_ptr(), result.c_str(), result.size() + 1);
return static_cast<s32>(result.size());
}
s32 _sys_vprintf()

View File

@ -142,18 +142,6 @@ public:
const std::string m_name; // Thread name
u64 get_next_arg(u32& g_count)
{
if (g_count < 8)
{
return gpr[g_count++ + 3];
}
else
{
return *get_stack_arg(++g_count);
}
}
be_t<u64>* get_stack_arg(s32 i, u64 align = alignof(u64));
void exec_task();
void fast_call(u32 addr, u32 rtoc);