Files
PS2Recomp/ps2xRuntime/src/lib/Kernel/Syscalls/Deci2.cpp
T
Ranieri 790aaf4cda feat: invert codegen hight to low convertion (#131)
* feat: invert codegen hight to low convertion
feat: added copy and GetEntryAddress
feat: handle truncated DMAC

* feat: always use address on analyzer now

* feat: correct pick syscalls ID

* feat: added deci2Call

* feat: added wip dbcmain IOP

* feat: added InitTLB
feat: added err logs on thread for debug sus crash

* fix: fix SetupHeap for strange cases

* feat: fix incorrect SetupHeap test(it use a wrong idea on how heap allocate memory)

* feat: added memalign and memalign_r
feat: added GetOsdConfigParam2 and  SetOsdConfigParam2 but idk if was a good idea

* feat: added more memory stuff

* feat: back to library functions
2026-06-13 16:39:39 -03:00

236 lines
7.1 KiB
C++

#include "System.h"
#include "Common.h"
#include "ps2_runtime.h"
namespace
{
struct Deci2Session
{
uint16_t protocol = 0;
uint32_t opt = 0;
uint32_t handler = 0;
uint32_t userArea = 0;
bool locked = false;
};
std::mutex g_deci2Mutex;
std::unordered_map<int32_t, Deci2Session> g_deci2Sessions;
int32_t g_nextDeci2Socket = 1;
std::atomic<uint32_t> g_deci2LogCount{0};
static bool readDeci2U32(uint8_t *rdram, uint32_t guestAddr, uint32_t &value)
{
value = 0;
const uint8_t *ptr = getConstMemPtr(rdram, guestAddr);
if (!ptr)
{
return false;
}
std::memcpy(&value, ptr, sizeof(value));
return true;
}
static void readDeci2Args(uint8_t *rdram, uint32_t argsAddr, uint32_t args[4])
{
for (uint32_t argIndex = 0; argIndex < 4; argIndex++)
{
uint32_t value = 0;
readDeci2U32(rdram, argsAddr + (argIndex * sizeof(uint32_t)), value);
args[argIndex] = value;
}
}
static std::string sanitizeDeci2Text(std::string text)
{
for (char &ch : text)
{
const unsigned char value = static_cast<unsigned char>(ch);
if (ch == '\r')
{
ch = '\n';
continue;
}
if (ch != '\n' && ch != '\t' && !std::isprint(value))
{
ch = '.';
}
}
return text;
}
static void logDeci2Text(const char *prefix, const std::string &text)
{
constexpr uint32_t kMaxDeci2TextLogs = 256u;
const uint32_t logIndex = g_deci2LogCount.fetch_add(1u, std::memory_order_relaxed);
if (logIndex >= kMaxDeci2TextLogs)
{
return;
}
const std::string safeText = sanitizeDeci2Text(text);
std::cerr << prefix << safeText;
if (safeText.empty() || safeText.back() != '\n')
{
std::cerr << std::endl;
}
}
static int32_t allocateDeci2Socket(uint16_t protocol, uint32_t opt, uint32_t handler, uint32_t userArea)
{
std::lock_guard<std::mutex> lock(g_deci2Mutex);
if (g_nextDeci2Socket <= 0)
{
g_nextDeci2Socket = 1;
}
const int32_t socket = g_nextDeci2Socket;
Deci2Session session;
session.protocol = protocol;
session.opt = opt;
session.handler = handler;
session.userArea = userArea;
session.locked = false;
g_deci2Sessions[socket] = session;
return socket;
}
static bool updateDeci2LockState(int32_t socket, bool locked)
{
std::lock_guard<std::mutex> lock(g_deci2Mutex);
auto sessionIt = g_deci2Sessions.find(socket);
if (sessionIt == g_deci2Sessions.end())
{
return false;
}
sessionIt->second.locked = locked;
return true;
}
static bool closeDeci2Socket(int32_t socket)
{
std::lock_guard<std::mutex> lock(g_deci2Mutex);
return g_deci2Sessions.erase(socket) != 0;
}
}
namespace ps2_syscalls
{
void Deci2Call(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
#if defined(_DEBUG) || defined(RUNTIME_DECI2CALL)
const int32_t code = static_cast<int32_t>(getRegU32(ctx, 4));
const uint32_t argsAddr = getRegU32(ctx, 5);
uint32_t args[4] = {};
readDeci2Args(rdram, argsAddr, args);
switch (code)
{
case 1: // sceDeci2Open(protocol, opt, handler)
{
const uint16_t protocol = static_cast<uint16_t>(args[0] & 0xFFFFu);
const uint32_t opt = args[1];
const uint32_t handler = args[2];
const uint32_t userArea = args[3];
const int32_t socket = allocateDeci2Socket(protocol, opt, handler, userArea);
setReturnS32(ctx, socket);
return;
}
case 2: // sceDeci2Close(socket)
{
const int32_t socket = static_cast<int32_t>(args[0]);
setReturnS32(ctx, closeDeci2Socket(socket) ? KE_OK : KE_ERROR);
return;
}
// WE dont need to do thouses
case 3: // sceDeci2ReqSend(socket, dest)
case 4: // sceDeci2Poll(socket)
case -7: // sceDeci2ExReqSend(socket, dest)
{
setReturnS32(ctx, KE_OK);
return;
}
case -5: // sceDeci2ExRecv(socket, buf, len)
{
// No host debugger channel is attached, so report "no bytes available".
setReturnS32(ctx, 0);
return;
}
case -6: // sceDeci2ExSend(socket, buf, len)
{
const uint32_t bufferAddr = args[1];
const uint32_t length = args[2] & 0xFFFFu;
if (bufferAddr != 0u && length != 0u)
{
const uint32_t clampedLength = std::min<uint32_t>(length, 512u);
std::string text;
text.reserve(clampedLength);
for (uint32_t byteIndex = 0; byteIndex < clampedLength; byteIndex++)
{
text.push_back(static_cast<char>(rdram[(bufferAddr + byteIndex) & PS2_RAM_MASK]));
}
logDeci2Text("[Deci2Call:send] ", text);
}
// Treat send as successful and return the amount accepted.
setReturnS32(ctx, static_cast<int32_t>(length));
return;
}
case -8: // sceDeci2ExLock(socket)
{
const int32_t socket = static_cast<int32_t>(args[0]);
setReturnS32(ctx, updateDeci2LockState(socket, true) ? KE_OK : KE_ERROR);
return;
}
case -9: // sceDeci2ExUnLock(socket)
{
const int32_t socket = static_cast<int32_t>(args[0]);
setReturnS32(ctx, updateDeci2LockState(socket, false) ? KE_OK : KE_ERROR);
return;
}
case 16: // kputs(char *s)
{
constexpr size_t kMaxDeci2KputsBytes = 4096u;
const uint32_t textAddr = args[0];
const std::string text = readGuestCStringBounded(rdram, textAddr, kMaxDeci2KputsBytes);
logDeci2Text("[Deci2Call:kputs] ", text);
setReturnS32(ctx, static_cast<int32_t>(text.size()));
return;
}
default:
{
static std::atomic<uint32_t> s_unknownDeci2Logs{0u};
constexpr uint32_t kMaxUnknownDeci2Logs = 64u;
const uint32_t logIndex = s_unknownDeci2Logs.fetch_add(1u, std::memory_order_relaxed);
if (logIndex < kMaxUnknownDeci2Logs)
{
std::cerr << "[Deci2Call:unknown]"
<< " code=" << code
<< " args=0x" << std::hex << argsAddr
<< " a0=0x" << args[0]
<< " a1=0x" << args[1]
<< " a2=0x" << args[2]
<< " a3=0x" << args[3]
<< " pc=0x" << ctx->pc
<< std::dec << std::endl;
}
setReturnS32(ctx, KE_OK);
return;
}
}
#endif
}
}