2008-01-15 20:27:44 +00:00
|
|
|
#include "Iop_Sysclib.h"
|
2016-03-09 15:31:00 +00:00
|
|
|
#include "../Ps2Const.h"
|
2018-05-24 16:59:15 +00:00
|
|
|
#include "../Log.h"
|
|
|
|
|
|
|
|
#define LOG_NAME "iop_sysclib"
|
2008-01-15 20:27:44 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
|
2016-03-17 23:20:02 +00:00
|
|
|
CSysclib::CSysclib(uint8* ram, uint8* spr, CStdio& stdio)
|
2018-04-30 20:01:23 +00:00
|
|
|
: m_ram(ram)
|
|
|
|
, m_spr(spr)
|
|
|
|
, m_stdio(stdio)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-04-12 03:04:32 +00:00
|
|
|
std::string CSysclib::GetId() const
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
return "sysclib";
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2012-04-12 03:04:32 +00:00
|
|
|
std::string CSysclib::GetFunctionName(unsigned int functionId) const
|
2008-11-28 23:46:52 +00:00
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
switch(functionId)
|
|
|
|
{
|
2016-12-24 23:36:02 +00:00
|
|
|
case 4:
|
|
|
|
return "setjmp";
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
return "longjmp";
|
|
|
|
break;
|
2014-11-21 23:52:45 +00:00
|
|
|
case 6:
|
|
|
|
return "toupper";
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
return "tolower";
|
|
|
|
break;
|
2012-09-26 02:21:37 +00:00
|
|
|
case 8:
|
|
|
|
return "look_ctype_table";
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
return "memcmp";
|
|
|
|
break;
|
2011-02-21 05:23:39 +00:00
|
|
|
case 12:
|
|
|
|
return "memcpy";
|
|
|
|
break;
|
2018-05-26 01:53:04 +00:00
|
|
|
case 13:
|
|
|
|
return "memmove";
|
|
|
|
break;
|
2011-02-21 05:23:39 +00:00
|
|
|
case 14:
|
|
|
|
return "memset";
|
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 16:
|
|
|
|
return "bcopy";
|
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
return "bzero";
|
|
|
|
break;
|
|
|
|
case 19:
|
|
|
|
return "sprintf";
|
|
|
|
break;
|
2015-12-19 01:59:06 +00:00
|
|
|
case 20:
|
|
|
|
return "strcat";
|
|
|
|
break;
|
2015-03-03 23:32:03 +00:00
|
|
|
case 21:
|
|
|
|
return "strchr";
|
|
|
|
break;
|
2011-02-21 05:23:39 +00:00
|
|
|
case 22:
|
|
|
|
return "strcmp";
|
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 23:
|
|
|
|
return "strcpy";
|
|
|
|
break;
|
2015-04-19 08:17:46 +00:00
|
|
|
case 24:
|
|
|
|
return "strcspn";
|
|
|
|
break;
|
2018-02-07 00:18:29 +00:00
|
|
|
case 25:
|
|
|
|
return "index";
|
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 27:
|
|
|
|
return "strlen";
|
|
|
|
break;
|
2012-09-26 02:21:37 +00:00
|
|
|
case 29:
|
|
|
|
return "strncmp";
|
|
|
|
break;
|
2015-06-04 03:56:33 +00:00
|
|
|
case 30:
|
|
|
|
return "strncpy";
|
|
|
|
break;
|
2014-07-13 02:23:54 +00:00
|
|
|
case 32:
|
|
|
|
return "strrchr";
|
|
|
|
break;
|
2015-06-04 03:58:08 +00:00
|
|
|
case 34:
|
|
|
|
return "strstr";
|
|
|
|
break;
|
2017-05-25 02:08:12 +00:00
|
|
|
case 35:
|
|
|
|
return "strtok";
|
|
|
|
break;
|
2011-02-21 05:23:39 +00:00
|
|
|
case 36:
|
|
|
|
return "strtol";
|
|
|
|
break;
|
2015-11-21 23:29:22 +00:00
|
|
|
case 40:
|
|
|
|
return "wmemcopy";
|
|
|
|
break;
|
2014-12-12 23:42:19 +00:00
|
|
|
case 41:
|
|
|
|
return "wmemset";
|
|
|
|
break;
|
2016-05-24 22:29:50 +00:00
|
|
|
case 42:
|
|
|
|
return "vsprintf";
|
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
break;
|
|
|
|
}
|
2008-11-28 23:46:52 +00:00
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
void CSysclib::Invoke(CMIPS& context, unsigned int functionId)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
switch(functionId)
|
|
|
|
{
|
2016-12-24 23:36:02 +00:00
|
|
|
case 4:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __setjmp(context);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__longjmp(context);
|
|
|
|
break;
|
2014-11-21 23:52:45 +00:00
|
|
|
case 6:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = toupper(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0);
|
2014-11-21 23:52:45 +00:00
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = tolower(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0);
|
2014-11-21 23:52:45 +00:00
|
|
|
break;
|
2012-09-26 02:21:37 +00:00
|
|
|
case 8:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __look_ctype_table(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0);
|
2012-09-26 02:21:37 +00:00
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__memcmp(
|
2018-04-30 20:01:23 +00:00
|
|
|
reinterpret_cast<void*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
|
|
|
reinterpret_cast<void*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0]),
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0));
|
2012-09-26 02:21:37 +00:00
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 12:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
|
|
|
__memcpy(
|
2018-04-30 20:01:23 +00:00
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A0].nV0],
|
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A1].nV0],
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
2014-06-17 02:26:24 +00:00
|
|
|
case 13:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
|
|
|
__memmove(
|
2018-04-30 20:01:23 +00:00
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A0].nV0],
|
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A1].nV0],
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
2014-06-17 02:26:24 +00:00
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 14:
|
2016-03-17 23:20:02 +00:00
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __memset(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
//bcopy
|
|
|
|
memmove(
|
2018-04-30 20:01:23 +00:00
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A1].nV0],
|
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A0].nV0],
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
//bzero
|
|
|
|
__memset(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
|
|
|
case 19:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__sprintf(context));
|
|
|
|
break;
|
2015-12-19 01:59:06 +00:00
|
|
|
case 20:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __strcat(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2015-12-19 01:59:06 +00:00
|
|
|
break;
|
2015-03-03 23:32:03 +00:00
|
|
|
case 21:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __strchr(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2015-03-03 23:32:03 +00:00
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 22:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strcmp(
|
2018-04-30 20:01:23 +00:00
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0])));
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
|
|
|
case 23:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
|
|
|
__strcpy(
|
2018-04-30 20:01:23 +00:00
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0]));
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
2015-04-19 08:17:46 +00:00
|
|
|
case 24:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __strcspn(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2015-04-19 08:17:46 +00:00
|
|
|
break;
|
2018-02-07 00:18:29 +00:00
|
|
|
case 25:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __index(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2018-02-07 00:18:29 +00:00
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 27:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strlen(
|
2018-04-30 20:01:23 +00:00
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])));
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
|
|
|
case 29:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strncmp(
|
2018-04-30 20:01:23 +00:00
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0]),
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0));
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
|
|
|
case 30:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
|
|
|
__strncpy(
|
2018-04-30 20:01:23 +00:00
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0]),
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
2014-07-13 02:23:54 +00:00
|
|
|
case 32:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __strrchr(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2014-07-13 02:23:54 +00:00
|
|
|
break;
|
2015-06-04 03:58:08 +00:00
|
|
|
case 34:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __strstr(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2015-06-04 03:58:08 +00:00
|
|
|
break;
|
2017-05-25 02:08:12 +00:00
|
|
|
case 35:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = __strtok(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
2017-05-25 02:08:12 +00:00
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
case 36:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strtol(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0));
|
2012-04-12 03:04:32 +00:00
|
|
|
break;
|
2015-11-21 23:29:22 +00:00
|
|
|
case 40:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__wmemcopy(
|
2018-04-30 20:01:23 +00:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0));
|
2015-11-21 23:29:22 +00:00
|
|
|
break;
|
2014-12-12 23:42:19 +00:00
|
|
|
case 41:
|
2014-12-22 06:23:52 +00:00
|
|
|
//wmemset
|
2014-12-12 23:42:19 +00:00
|
|
|
{
|
|
|
|
uint32* dest = reinterpret_cast<uint32*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]);
|
|
|
|
uint32 value = context.m_State.nGPR[CMIPS::A1].nV0;
|
2015-01-07 06:39:20 +00:00
|
|
|
uint32 numBytes = context.m_State.nGPR[CMIPS::A2].nV0;
|
|
|
|
uint32* end = dest + (numBytes / 4);
|
2014-12-22 06:23:52 +00:00
|
|
|
while(dest < end)
|
|
|
|
{
|
2014-12-12 23:42:19 +00:00
|
|
|
*dest++ = value;
|
|
|
|
}
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nV0;
|
|
|
|
}
|
|
|
|
break;
|
2016-05-24 22:29:50 +00:00
|
|
|
case 42:
|
2016-05-29 20:41:31 +00:00
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__vsprintf(
|
2018-04-30 20:01:23 +00:00
|
|
|
context,
|
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV0,
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV0));
|
2016-05-24 22:29:50 +00:00
|
|
|
break;
|
2012-04-12 03:04:32 +00:00
|
|
|
default:
|
2018-05-24 16:59:15 +00:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "(%08X): Unknown function (%d) called.\r\n",
|
2018-05-25 16:26:07 +00:00
|
|
|
context.m_State.nPC, functionId);
|
2012-04-12 03:04:32 +00:00
|
|
|
assert(0);
|
|
|
|
break;
|
|
|
|
}
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2016-03-17 23:20:02 +00:00
|
|
|
uint8* CSysclib::GetPtr(uint32 ptr, uint32 size) const
|
2016-03-09 15:31:00 +00:00
|
|
|
{
|
|
|
|
assert(ptr != 0);
|
2016-03-17 23:20:02 +00:00
|
|
|
if(ptr >= PS2::IOP_SCRATCH_ADDR)
|
|
|
|
{
|
|
|
|
//Some games (Phantasy Star Collection) seem to address areas beyond the SPR's limits
|
|
|
|
ptr &= (PS2::IOP_SCRATCH_SIZE - 1);
|
|
|
|
assert((ptr + size) <= PS2::IOP_SCRATCH_SIZE);
|
|
|
|
return reinterpret_cast<uint8*>(m_spr + ptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//We should rarely get addresses that point to other areas
|
|
|
|
//than RAM, so we assert just to give a warning because it might
|
|
|
|
//mean there's an error somewhere else
|
|
|
|
assert(ptr < PS2::IOP_RAM_SIZE);
|
|
|
|
ptr &= (PS2::IOP_RAM_SIZE - 1);
|
|
|
|
return reinterpret_cast<uint8*>(m_ram + ptr);
|
|
|
|
}
|
2016-03-09 15:31:00 +00:00
|
|
|
}
|
|
|
|
|
2016-12-24 23:36:02 +00:00
|
|
|
int32 CSysclib::__setjmp(CMIPS& context)
|
|
|
|
{
|
|
|
|
uint32 envPtr = context.m_State.nGPR[CMIPS::A0].nV0;
|
|
|
|
auto env = reinterpret_cast<JMP_BUF*>(GetPtr(envPtr, sizeof(JMP_BUF)));
|
|
|
|
env->ra = context.m_State.nGPR[CMIPS::RA].nV0;
|
|
|
|
env->sp = context.m_State.nGPR[CMIPS::SP].nV0;
|
|
|
|
env->fp = context.m_State.nGPR[CMIPS::FP].nV0;
|
|
|
|
env->s0 = context.m_State.nGPR[CMIPS::S0].nV0;
|
|
|
|
env->s1 = context.m_State.nGPR[CMIPS::S1].nV0;
|
|
|
|
env->s2 = context.m_State.nGPR[CMIPS::S2].nV0;
|
|
|
|
env->s3 = context.m_State.nGPR[CMIPS::S3].nV0;
|
|
|
|
env->s4 = context.m_State.nGPR[CMIPS::S4].nV0;
|
|
|
|
env->s5 = context.m_State.nGPR[CMIPS::S5].nV0;
|
|
|
|
env->s6 = context.m_State.nGPR[CMIPS::S6].nV0;
|
|
|
|
env->s7 = context.m_State.nGPR[CMIPS::S7].nV0;
|
|
|
|
env->gp = context.m_State.nGPR[CMIPS::GP].nV0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSysclib::__longjmp(CMIPS& context)
|
|
|
|
{
|
|
|
|
uint32 envPtr = context.m_State.nGPR[CMIPS::A0].nV0;
|
|
|
|
uint32 returnValue = context.m_State.nGPR[CMIPS::A1].nV0;
|
|
|
|
auto env = reinterpret_cast<const JMP_BUF*>(GetPtr(envPtr, sizeof(JMP_BUF)));
|
|
|
|
context.m_State.nPC = env->ra;
|
|
|
|
context.m_State.nGPR[CMIPS::SP].nV0 = env->sp;
|
|
|
|
context.m_State.nGPR[CMIPS::FP].nV0 = env->fp;
|
|
|
|
context.m_State.nGPR[CMIPS::S0].nV0 = env->s0;
|
|
|
|
context.m_State.nGPR[CMIPS::S1].nV0 = env->s1;
|
|
|
|
context.m_State.nGPR[CMIPS::S2].nV0 = env->s2;
|
|
|
|
context.m_State.nGPR[CMIPS::S3].nV0 = env->s3;
|
|
|
|
context.m_State.nGPR[CMIPS::S4].nV0 = env->s4;
|
|
|
|
context.m_State.nGPR[CMIPS::S5].nV0 = env->s5;
|
|
|
|
context.m_State.nGPR[CMIPS::S6].nV0 = env->s6;
|
|
|
|
context.m_State.nGPR[CMIPS::S7].nV0 = env->s7;
|
|
|
|
context.m_State.nGPR[CMIPS::GP].nV0 = env->gp;
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nV0 = static_cast<int32>(returnValue);
|
|
|
|
}
|
|
|
|
|
2012-09-26 02:21:37 +00:00
|
|
|
uint32 CSysclib::__look_ctype_table(uint32 character)
|
|
|
|
{
|
|
|
|
static const uint8 ctype_table[128] =
|
2018-04-30 20:01:23 +00:00
|
|
|
{
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
2012-09-26 02:21:37 +00:00
|
|
|
|
2018-04-30 20:01:23 +00:00
|
|
|
0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
|
|
|
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
|
|
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
|
|
0x04, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
2012-09-26 02:21:37 +00:00
|
|
|
|
2018-04-30 20:01:23 +00:00
|
|
|
0x10, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x01,
|
|
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
|
|
0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10, 0x10,
|
2012-09-26 02:21:37 +00:00
|
|
|
|
2018-04-30 20:01:23 +00:00
|
|
|
0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x02,
|
|
|
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
|
|
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
|
|
|
0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x20};
|
2012-09-26 02:21:37 +00:00
|
|
|
|
|
|
|
assert(character < 128);
|
|
|
|
|
|
|
|
return ctype_table[character & 0x7F];
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSysclib::__memcmp(const void* dst, const void* src, uint32 length)
|
|
|
|
{
|
|
|
|
return static_cast<uint32>(memcmp(dst, src, length));
|
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
void CSysclib::__memcpy(void* dest, const void* src, unsigned int length)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
memcpy(dest, src, length);
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2014-06-17 02:26:24 +00:00
|
|
|
void CSysclib::__memmove(void* dest, const void* src, uint32 length)
|
|
|
|
{
|
|
|
|
memmove(dest, src, length);
|
|
|
|
}
|
|
|
|
|
2016-03-17 23:20:02 +00:00
|
|
|
uint32 CSysclib::__memset(uint32 destPtr, uint32 character, uint32 length)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2016-03-17 23:20:02 +00:00
|
|
|
auto dest = reinterpret_cast<uint8*>(GetPtr(destPtr, length));
|
2012-04-12 03:04:32 +00:00
|
|
|
memset(dest, character, length);
|
2016-03-17 23:20:02 +00:00
|
|
|
return destPtr;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSysclib::__sprintf(CMIPS& context)
|
|
|
|
{
|
2016-05-29 20:41:31 +00:00
|
|
|
CCallArgumentIterator args(context);
|
|
|
|
auto destination = reinterpret_cast<char*>(m_ram + args.GetNext());
|
|
|
|
auto format = reinterpret_cast<const char*>(m_ram + args.GetNext());
|
|
|
|
auto output = m_stdio.PrintFormatted(format, args);
|
2012-04-12 03:04:32 +00:00
|
|
|
strcpy(destination, output.c_str());
|
|
|
|
return static_cast<uint32>(output.length());
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2015-12-19 01:59:06 +00:00
|
|
|
uint32 CSysclib::__strcat(uint32 dstPtr, uint32 srcPtr)
|
|
|
|
{
|
|
|
|
assert(dstPtr != 0);
|
|
|
|
assert(srcPtr != 0);
|
|
|
|
auto dst = reinterpret_cast<char*>(m_ram + dstPtr);
|
|
|
|
auto src = reinterpret_cast<const char*>(m_ram + srcPtr);
|
|
|
|
strcat(dst, src);
|
|
|
|
return dstPtr;
|
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
uint32 CSysclib::__strlen(const char* string)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
return static_cast<uint32>(strlen(string));
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2009-02-20 04:00:18 +00:00
|
|
|
uint32 CSysclib::__strcmp(const char* s1, const char* s2)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
return static_cast<uint32>(strcmp(s1, s2));
|
2009-02-20 04:00:18 +00:00
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
void CSysclib::__strcpy(char* dst, const char* src)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
strcpy(dst, src);
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 02:35:27 +00:00
|
|
|
uint32 CSysclib::__strncmp(const char* s1, const char* s2, uint32 length)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
return static_cast<uint32>(strncmp(s1, s2, length));
|
2009-01-11 02:35:27 +00:00
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
void CSysclib::__strncpy(char* dst, const char* src, unsigned int count)
|
|
|
|
{
|
2012-04-12 03:04:32 +00:00
|
|
|
strncpy(dst, src, count);
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2015-03-03 23:32:03 +00:00
|
|
|
uint32 CSysclib::__strchr(uint32 strPtr, uint32 character)
|
|
|
|
{
|
|
|
|
auto str = reinterpret_cast<const char*>(m_ram + strPtr);
|
|
|
|
auto result = strchr(str, static_cast<int>(character));
|
|
|
|
if(result == nullptr) return 0;
|
|
|
|
size_t ptrDiff = result - str;
|
|
|
|
return strPtr + ptrDiff;
|
|
|
|
}
|
|
|
|
|
2014-07-13 02:23:54 +00:00
|
|
|
uint32 CSysclib::__strrchr(uint32 strPtr, uint32 character)
|
|
|
|
{
|
2015-03-03 23:32:03 +00:00
|
|
|
auto str = reinterpret_cast<const char*>(m_ram + strPtr);
|
|
|
|
auto result = strrchr(str, static_cast<int>(character));
|
2014-07-13 02:23:54 +00:00
|
|
|
if(result == nullptr) return 0;
|
|
|
|
size_t ptrDiff = result - str;
|
|
|
|
return strPtr + ptrDiff;
|
|
|
|
}
|
|
|
|
|
2015-06-04 03:58:08 +00:00
|
|
|
uint32 CSysclib::__strstr(uint32 str1Ptr, uint32 str2Ptr)
|
|
|
|
{
|
|
|
|
auto str1 = reinterpret_cast<const char*>(m_ram + str1Ptr);
|
|
|
|
auto str2 = reinterpret_cast<const char*>(m_ram + str2Ptr);
|
|
|
|
auto result = strstr(str1, str2);
|
|
|
|
if(result == nullptr) return 0;
|
|
|
|
size_t ptrDiff = result - str1;
|
|
|
|
return str1Ptr + ptrDiff;
|
|
|
|
}
|
|
|
|
|
2017-05-25 02:08:12 +00:00
|
|
|
uint32 CSysclib::__strtok(uint32 sPtr, uint32 delimPtr)
|
|
|
|
{
|
|
|
|
auto delim = reinterpret_cast<const char*>(m_ram + delimPtr);
|
|
|
|
|
|
|
|
if(sPtr != 0)
|
|
|
|
{
|
|
|
|
m_strtok_prevSPtr = sPtr;
|
|
|
|
}
|
|
|
|
else if(m_strtok_prevSPtr == 0)
|
|
|
|
{
|
|
|
|
//If sPtr == 0 && prevSPtr == 0
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
auto s = reinterpret_cast<char*>(m_ram + m_strtok_prevSPtr);
|
|
|
|
|
|
|
|
auto str = s + strspn(s, delim);
|
|
|
|
s = str + strcspn(str, delim);
|
|
|
|
if(s == str)
|
|
|
|
{
|
|
|
|
m_strtok_prevSPtr = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(*s)
|
|
|
|
{
|
|
|
|
(*s) = 0;
|
|
|
|
m_strtok_prevSPtr = (reinterpret_cast<uint8*>(s) - m_ram) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_strtok_prevSPtr = 0;
|
|
|
|
}
|
|
|
|
return reinterpret_cast<uint8*>(str) - m_ram;
|
|
|
|
}
|
|
|
|
|
2015-04-19 08:17:46 +00:00
|
|
|
uint32 CSysclib::__strcspn(uint32 str1Ptr, uint32 str2Ptr)
|
|
|
|
{
|
|
|
|
auto str1 = reinterpret_cast<const char*>(m_ram + str1Ptr);
|
|
|
|
auto str2 = reinterpret_cast<const char*>(m_ram + str2Ptr);
|
|
|
|
auto result = strcspn(str1, str2);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-07 00:18:29 +00:00
|
|
|
uint32 CSysclib::__index(uint32 sPtr, uint32 c)
|
|
|
|
{
|
|
|
|
auto s = reinterpret_cast<const char*>(m_ram + sPtr);
|
|
|
|
auto result = strchr(s, c);
|
|
|
|
if(result == nullptr) return 0;
|
|
|
|
return reinterpret_cast<const uint8*>(result) - m_ram;
|
|
|
|
}
|
|
|
|
|
2016-03-09 15:31:00 +00:00
|
|
|
uint32 CSysclib::__strtol(uint32 stringPtr, uint32 endPtrPtr, uint32 radix)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2016-03-17 23:20:02 +00:00
|
|
|
auto string = reinterpret_cast<const char*>(GetPtr(stringPtr, 0));
|
2016-05-16 04:23:30 +00:00
|
|
|
char* end = nullptr;
|
|
|
|
uint32 result = strtol(string, &end, radix);
|
|
|
|
if(endPtrPtr != 0)
|
|
|
|
{
|
|
|
|
auto endPtr = reinterpret_cast<uint32*>(GetPtr(endPtrPtr, 4));
|
|
|
|
(*endPtr) = static_cast<uint32>(end - string);
|
|
|
|
}
|
|
|
|
return result;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
2015-11-21 23:29:22 +00:00
|
|
|
|
|
|
|
uint32 CSysclib::__wmemcopy(uint32 dstPtr, uint32 srcPtr, uint32 size)
|
|
|
|
{
|
|
|
|
assert((size & 0x3) == 0);
|
|
|
|
auto dst = reinterpret_cast<uint8*>(m_ram + dstPtr);
|
|
|
|
auto src = reinterpret_cast<uint8*>(m_ram + srcPtr);
|
|
|
|
memmove(dst, src, size);
|
|
|
|
return dstPtr;
|
|
|
|
}
|
2016-05-29 20:41:31 +00:00
|
|
|
|
|
|
|
uint32 CSysclib::__vsprintf(CMIPS& context, uint32 destinationPtr, uint32 formatPtr, uint32 argsPtr)
|
|
|
|
{
|
|
|
|
CValistArgumentIterator args(context, argsPtr);
|
|
|
|
auto destination = reinterpret_cast<char*>(m_ram + destinationPtr);
|
|
|
|
auto format = reinterpret_cast<const char*>(m_ram + formatPtr);
|
|
|
|
auto output = m_stdio.PrintFormatted(format, args);
|
|
|
|
strcpy(destination, output.c_str());
|
|
|
|
return static_cast<uint32>(output.length());
|
|
|
|
}
|