rpcsx/rpcs3/Emu/Cell/Modules/sys_libc_.cpp

394 lines
8.4 KiB
C++
Raw Normal View History

2015-02-26 21:08:48 +01:00
#include "stdafx.h"
2016-03-21 20:42:14 +01:00
#include "Emu/Cell/PPUModule.h"
2015-02-26 21:08:48 +01:00
2016-05-13 15:55:34 +02:00
extern logs::channel sysPrxForUser;
2015-02-26 21:08:48 +01:00
extern fs::file g_tty;
2016-03-21 20:42:14 +01:00
// TODO
static std::string ps3_fmt(ppu_thread& context, vm::cptr<char> fmt, u32 g_count)
2015-08-02 04:15:49 +02:00
{
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++;
2016-03-21 20:42:14 +01:00
return context.get_next_arg(g_count);
2015-08-02 04:15:49 +02:00
}
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++;
2016-03-21 20:42:14 +01:00
return context.get_next_arg(g_count);
2015-08-02 04:15:49 +02:00
}
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
2016-03-21 20:42:14 +01:00
const s64 value = context.get_next_arg(g_count);
2015-08-02 04:15:49 +02:00
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
result += fmt::format("%lld", value);
2015-08-02 04:15:49 +02:00
continue;
}
case 'x':
case 'X':
{
// hexadecimal
2016-03-21 20:42:14 +01:00
const u64 value = context.get_next_arg(g_count);
2015-08-02 04:15:49 +02:00
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);
2015-08-02 04:15:49 +02:00
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
2016-03-21 20:42:14 +01:00
auto string = vm::cptr<char, u64>::make(context.get_next_arg(g_count));
2015-08-02 04:15:49 +02:00
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
result += string.get_ptr();
continue;
}
case 'u':
{
// unsigned decimal
2016-03-21 20:42:14 +01:00
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;
}
2015-08-02 04:15:49 +02:00
}
fmt::throw_exception("Unknown formatting: '%s'" HERE, start.get_ptr());
2015-08-02 04:15:49 +02:00
}
}
result += c;
}
return result;
}
vm::ptr<void> _sys_memset(vm::ptr<void> dst, s32 value, u32 size)
{
sysPrxForUser.trace("_sys_memset(dst=*0x%x, value=%d, size=0x%x)", dst, value, size);
2015-08-02 04:15:49 +02:00
2016-08-11 01:29:59 +02:00
std::memset(dst.get_ptr(), value, size);
2015-08-02 04:15:49 +02:00
return dst;
}
vm::ptr<void> _sys_memcpy(vm::ptr<void> dst, vm::cptr<void> src, u32 size)
{
sysPrxForUser.trace("_sys_memcpy(dst=*0x%x, src=*0x%x, size=0x%x)", dst, src, size);
2015-08-02 04:15:49 +02:00
2016-08-11 01:29:59 +02:00
std::memcpy(dst.get_ptr(), src.get_ptr(), size);
2015-08-02 04:15:49 +02:00
return dst;
}
s32 _sys_memcmp(vm::cptr<void> buf1, vm::cptr<void> buf2, u32 size)
{
sysPrxForUser.trace("_sys_memcmp(buf1=*0x%x, buf2=*0x%x, size=%d)", buf1, buf2, size);
2015-08-02 04:15:49 +02:00
2016-08-11 01:29:59 +02:00
return std::memcmp(buf1.get_ptr(), buf2.get_ptr(), size);
2015-08-02 04:15:49 +02:00
}
s32 _sys_memchr()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
2016-02-16 19:54:09 +01:00
vm::ptr<void> _sys_memmove(vm::ptr<void> dst, vm::cptr<void> src, u32 size)
2015-08-02 04:15:49 +02:00
{
2016-02-16 19:54:09 +01:00
sysPrxForUser.trace("_sys_memmove(dst=*0x%x, src=*0x%x, size=%d)", dst, src, size);
2016-08-11 01:29:59 +02:00
std::memmove(dst.get_ptr(), src.get_ptr(), size);
2016-02-16 19:54:09 +01:00
return dst;
2015-08-02 04:15:49 +02:00
}
s64 _sys_strlen(vm::cptr<char> str)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strlen(str=%s)", str);
2015-08-02 04:15:49 +02:00
2016-08-11 01:29:59 +02:00
return std::strlen(str.get_ptr());
2015-08-02 04:15:49 +02:00
}
s32 _sys_strcmp(vm::cptr<char> str1, vm::cptr<char> str2)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strcmp(str1=%s, str2=%s)", str1, str2);
2015-08-02 04:15:49 +02:00
2016-08-11 01:29:59 +02:00
return std::strcmp(str1.get_ptr(), str2.get_ptr());
2015-08-02 04:15:49 +02:00
}
s32 _sys_strncmp(vm::cptr<char> str1, vm::cptr<char> str2, s32 max)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strncmp(str1=%s, str2=%s, max=%d)", str1, str2, max);
2015-08-02 04:15:49 +02:00
2016-08-11 01:29:59 +02:00
return std::strncmp(str1.get_ptr(), str2.get_ptr(), max);
2015-08-02 04:15:49 +02:00
}
vm::ptr<char> _sys_strcat(vm::ptr<char> dest, vm::cptr<char> source)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strcat(dest=*0x%x, source=%s)", dest, source);
2015-08-02 04:15:49 +02:00
2016-08-15 02:11:49 +02:00
verify(HERE), std::strcat(dest.get_ptr(), source.get_ptr()) == dest.get_ptr();
2015-08-02 04:15:49 +02:00
return dest;
}
vm::cptr<char> _sys_strchr(vm::cptr<char> str, s32 ch)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strchr(str=%s, ch=0x%x)", str, ch);
2015-08-02 04:15:49 +02:00
return vm::cptr<char>::make(vm::get_addr(strchr(str.get_ptr(), ch)));
}
vm::ptr<char> _sys_strncat(vm::ptr<char> dest, vm::cptr<char> source, u32 len)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strncat(dest=*0x%x, source=%s, len=%d)", dest, source, len);
2015-08-02 04:15:49 +02:00
2016-08-15 02:11:49 +02:00
verify(HERE), std::strncat(dest.get_ptr(), source.get_ptr(), len) == dest.get_ptr();
2015-08-02 04:15:49 +02:00
return dest;
}
vm::ptr<char> _sys_strcpy(vm::ptr<char> dest, vm::cptr<char> source)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strcpy(dest=*0x%x, source=%s)", dest, source);
2015-08-02 04:15:49 +02:00
2016-08-15 02:11:49 +02:00
verify(HERE), std::strcpy(dest.get_ptr(), source.get_ptr()) == dest.get_ptr();
2015-08-02 04:15:49 +02:00
return dest;
}
vm::ptr<char> _sys_strncpy(vm::ptr<char> dest, vm::cptr<char> source, u32 len)
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.trace("_sys_strncpy(dest=*0x%x, source=%s, len=%d)", dest, source, len);
2015-08-02 04:15:49 +02:00
if (!dest || !source)
{
return vm::null;
}
2016-08-15 02:11:49 +02:00
verify(HERE), std::strncpy(dest.get_ptr(), source.get_ptr(), len) == dest.get_ptr();
2015-08-02 04:15:49 +02:00
return dest;
}
s32 _sys_strncasecmp()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_strrchr()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_tolower()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_toupper()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
u32 _sys_malloc(u32 size)
{
sysPrxForUser.warning("_sys_malloc(size=0x%x)", size);
2015-08-02 04:15:49 +02:00
return vm::alloc(size, vm::main);
}
u32 _sys_memalign(u32 align, u32 size)
{
sysPrxForUser.warning("_sys_memalign(align=0x%x, size=0x%x)", align, size);
2015-08-02 04:15:49 +02:00
return vm::alloc(size, vm::main, std::max<u32>(align, 4096));
}
s32 _sys_free(u32 addr)
{
sysPrxForUser.warning("_sys_free(addr=0x%x)", addr);
2015-08-02 04:15:49 +02:00
vm::dealloc(addr, vm::main);
return CELL_OK;
}
s32 _sys_snprintf(ppu_thread& ppu, vm::ptr<char> dst, u32 count, vm::cptr<char> fmt, ppu_va_args_t va_args)
2015-08-02 04:15:49 +02:00
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.warning("_sys_snprintf(dst=*0x%x, count=%d, fmt=%s, ...)", dst, count, fmt);
2015-08-02 04:15:49 +02:00
2016-03-21 20:42:14 +01:00
std::string result = ps3_fmt(ppu, fmt, va_args.count);
2015-08-02 04:15:49 +02:00
if (!count)
{
return 0; // ???
}
else
{
count = (u32)std::min<size_t>(count - 1, result.size());
memcpy(dst.get_ptr(), result.c_str(), count);
dst[count] = 0;
return count;
}
}
s32 _sys_printf(ppu_thread& ppu, vm::cptr<char> fmt, ppu_va_args_t va_args)
2015-08-02 04:15:49 +02:00
{
2016-08-11 01:29:59 +02:00
sysPrxForUser.warning("_sys_printf(fmt=%s, ...)", fmt);
2015-08-02 04:15:49 +02:00
if (g_tty)
{
g_tty.write(ps3_fmt(ppu, fmt, va_args.count));
}
return CELL_OK;
2015-08-02 04:15:49 +02:00
}
s32 _sys_sprintf()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_vprintf()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_vsnprintf()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_vsprintf()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
s32 _sys_qsort()
{
fmt::throw_exception("Unimplemented" HERE);
2015-08-02 04:15:49 +02:00
}
void sysPrxForUser_sys_libc_init()
{
REG_FUNC(sysPrxForUser, _sys_memset);
REG_FUNC(sysPrxForUser, _sys_memcpy);
REG_FUNC(sysPrxForUser, _sys_memcmp);
REG_FUNC(sysPrxForUser, _sys_memchr);
REG_FUNC(sysPrxForUser, _sys_memmove);
REG_FUNC(sysPrxForUser, _sys_strlen);
REG_FUNC(sysPrxForUser, _sys_strcmp);
REG_FUNC(sysPrxForUser, _sys_strncmp);
REG_FUNC(sysPrxForUser, _sys_strcat);
REG_FUNC(sysPrxForUser, _sys_strchr);
REG_FUNC(sysPrxForUser, _sys_strncat);
REG_FUNC(sysPrxForUser, _sys_strcpy);
REG_FUNC(sysPrxForUser, _sys_strncpy);
REG_FUNC(sysPrxForUser, _sys_strncasecmp);
REG_FUNC(sysPrxForUser, _sys_strrchr);
REG_FUNC(sysPrxForUser, _sys_tolower);
REG_FUNC(sysPrxForUser, _sys_toupper);
REG_FUNC(sysPrxForUser, _sys_malloc);
REG_FUNC(sysPrxForUser, _sys_memalign);
REG_FUNC(sysPrxForUser, _sys_free);
REG_FUNC(sysPrxForUser, _sys_snprintf);
REG_FUNC(sysPrxForUser, _sys_printf);
REG_FUNC(sysPrxForUser, _sys_sprintf);
REG_FUNC(sysPrxForUser, _sys_vprintf);
REG_FUNC(sysPrxForUser, _sys_vsnprintf);
REG_FUNC(sysPrxForUser, _sys_vsprintf);
REG_FUNC(sysPrxForUser, _sys_qsort);
}