mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 16:30:30 +02:00
cleanup
This commit is contained in:
1 parent
7ff48f97c3
commit
fa0eaebfb5
1 file changed
+152
-163
+152
-163
@@ -743,172 +743,161 @@ static int sysclib_memcmp(u32 dst, u32 src, u32 size) {
|
||||
|
||||
static int sysclib_sprintf(u32 dst, u32 fmt) {
|
||||
ERROR_LOG(SCEKERNEL, "Untested sysclib_sprintf(dst=%08x, fmt=%08x)", dst, fmt);
|
||||
if (Memory::IsValidAddress(dst) && Memory::IsValidAddress(fmt)) {
|
||||
|
||||
|
||||
u32 psp_stack_pointer = currentMIPS->r[MIPS_REG_SP];
|
||||
ERROR_LOG(SCEKERNEL, "Fmt: %s", Memory::GetCharPointerUnchecked(fmt));
|
||||
ERROR_LOG(SCEKERNEL, "PSP arg reg dump: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||
currentMIPS->r[MIPS_REG_A0],
|
||||
currentMIPS->r[MIPS_REG_A1],
|
||||
currentMIPS->r[MIPS_REG_A2],
|
||||
currentMIPS->r[MIPS_REG_A3],
|
||||
currentMIPS->r[MIPS_REG_T0],
|
||||
currentMIPS->r[MIPS_REG_T1],
|
||||
currentMIPS->r[MIPS_REG_T2],
|
||||
currentMIPS->r[MIPS_REG_T3]
|
||||
);
|
||||
for(int i = 0;i < 24; i+=8){
|
||||
u32 base = psp_stack_pointer + i * 4;
|
||||
ERROR_LOG(SCEKERNEL, "PSP stack dump: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||
Memory::Read_U32(base),
|
||||
Memory::Read_U32(base + 1 * 4),
|
||||
Memory::Read_U32(base + 2 * 4),
|
||||
Memory::Read_U32(base + 3 * 4),
|
||||
Memory::Read_U32(base + 4 * 4),
|
||||
Memory::Read_U32(base + 5 * 4),
|
||||
Memory::Read_U32(base + 6 * 4),
|
||||
Memory::Read_U32(base + 7 * 4)
|
||||
);
|
||||
}
|
||||
int state = 0;
|
||||
std::string result = "";
|
||||
std::string cur_fmt = "";
|
||||
int bytes_to_read = 0;
|
||||
int arg_idx = 0;
|
||||
int fmt_len = 0;
|
||||
|
||||
for(const char *c = Memory::GetCharPointerUnchecked(fmt); *c != '\0'; c++){
|
||||
// in case we have a bad fmt string, try not to crash the whole emulator
|
||||
fmt_len++;
|
||||
if(fmt_len == 1024){
|
||||
ERROR_LOG(SCEKERNEL, "sprintf, fmt is longer than 1024");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(state == 0){
|
||||
if(*c == '%'){
|
||||
cur_fmt = "%";
|
||||
state = 1;
|
||||
bytes_to_read = 0;
|
||||
}else{
|
||||
result.append(1, *c);
|
||||
}
|
||||
}else{
|
||||
cur_fmt.append(1, *c);
|
||||
|
||||
// going by https://cplusplus.com/reference/cstdio/printf/#compatibility
|
||||
// no idea what the kernel module really supports as of writing this
|
||||
|
||||
if(*c == '%'){
|
||||
result.append(cur_fmt);
|
||||
state = 0;
|
||||
}else if(*c == 'd' ||
|
||||
*c == 'i' ||
|
||||
*c == 'u' ||
|
||||
*c == 'o' ||
|
||||
*c == 'x' ||
|
||||
*c == 'X' ||
|
||||
*c == 'f' ||
|
||||
*c == 'e' ||
|
||||
*c == 'E' ||
|
||||
*c == 'g' ||
|
||||
*c == 'G' ||
|
||||
*c == 'c' ||
|
||||
*c == 'p' ||
|
||||
*c == 'n' ||
|
||||
*c == 's'
|
||||
){
|
||||
// we have a format ending
|
||||
if(*c == 's'){
|
||||
// consume 4 bytes from arguments
|
||||
u32 val = 0;
|
||||
if(arg_idx <= 1){
|
||||
val = currentMIPS->r[MIPS_REG_A2 + arg_idx];
|
||||
}else if(arg_idx <= 5){
|
||||
val = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2];
|
||||
}else{
|
||||
// XXX assuming right to left arg pushing
|
||||
int stack_idx = arg_idx - 6;
|
||||
u32 stack_cur = psp_stack_pointer + stack_idx * 4;
|
||||
|
||||
if(!Memory::IsValidAddress(stack_cur)){
|
||||
ERROR_LOG(SCEKERNEL, "sprintf, bad stack pointer %08x", stack_cur);
|
||||
return 0;
|
||||
}
|
||||
val = Memory::Read_U32(stack_cur);
|
||||
}
|
||||
arg_idx++;
|
||||
|
||||
if(!Memory::IsValidAddress(val)){
|
||||
ERROR_LOG(SCEKERNEL, "sprintf, bad string reference %08x", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *str = Memory::GetCharPointerUnchecked(val);
|
||||
// limit the string length and hope that we don't crash on a bad string reference
|
||||
char buf[1024] = {0};
|
||||
strncpy(buf, str, sizeof(buf));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
result.append(buf);
|
||||
}else{
|
||||
u64 val = 0;
|
||||
if(bytes_to_read == 0){
|
||||
bytes_to_read = 4;
|
||||
}
|
||||
int read_cnt = 0;
|
||||
while(bytes_to_read != 0){
|
||||
u64 val_from_arg = 0;
|
||||
if(arg_idx <= 1){
|
||||
val_from_arg = currentMIPS->r[MIPS_REG_A2 + arg_idx];
|
||||
}else if(arg_idx <= 5){
|
||||
val_from_arg = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2];
|
||||
}else{
|
||||
// XXX assuming right to left arg pushing
|
||||
int stack_idx = arg_idx - 6;
|
||||
u32 stack_cur = psp_stack_pointer + stack_idx * 4;
|
||||
|
||||
if(!Memory::IsValidAddress(stack_cur)){
|
||||
ERROR_LOG(SCEKERNEL, "sprintf, bad stack pointer %08x", stack_cur);
|
||||
return 0;
|
||||
}
|
||||
val_from_arg = Memory::Read_U32(stack_cur);
|
||||
}
|
||||
arg_idx++;
|
||||
|
||||
val = val | (val_from_arg << (read_cnt * 32));
|
||||
|
||||
bytes_to_read = bytes_to_read - 4;
|
||||
read_cnt++;
|
||||
}
|
||||
/*
|
||||
// windows compiler don't like this
|
||||
int space_needed = snprintf(nullptr, 0, cur_fmt.c_str(), val);
|
||||
char buf[space_needed + 1];
|
||||
sprintf(buf, cur_fmt.c_str(), val);
|
||||
*/
|
||||
char buf[1024] = {0};
|
||||
snprintf(buf, sizeof(buf), cur_fmt.c_str(), val);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
result.append(buf);
|
||||
}
|
||||
state = 0;
|
||||
}else if(*c == 'h'){
|
||||
// allegrex calling convention is 4 bytes aligned
|
||||
bytes_to_read = 4;
|
||||
}else if(*c == 'l'){
|
||||
bytes_to_read = bytes_to_read + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if a small buffer was allocated by the program, we will likely crash
|
||||
strcpy((char *)Memory::GetPointerUnchecked(dst), result.c_str());
|
||||
return result.length();
|
||||
} else {
|
||||
if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(fmt)) {
|
||||
// What to do? Crash, probably.
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fmt: %s", Memory::GetCharPointerUnchecked(fmt));
|
||||
DEBUG_LOG(SCEKERNEL, "sysclib_sprintf a0-a4, t0-t4: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||
currentMIPS->r[MIPS_REG_A0],
|
||||
currentMIPS->r[MIPS_REG_A1],
|
||||
currentMIPS->r[MIPS_REG_A2],
|
||||
currentMIPS->r[MIPS_REG_A3],
|
||||
currentMIPS->r[MIPS_REG_T0],
|
||||
currentMIPS->r[MIPS_REG_T1],
|
||||
currentMIPS->r[MIPS_REG_T2],
|
||||
currentMIPS->r[MIPS_REG_T3]
|
||||
);
|
||||
|
||||
bool processing_specifier = false;
|
||||
std::string specifier = "";
|
||||
int bytes_to_read = 0;
|
||||
int arg_idx = 0;
|
||||
int fmt_len = 0;
|
||||
std::string result = "";
|
||||
for (const char *c = Memory::GetCharPointerUnchecked(fmt); *c != '\0'; c++) {
|
||||
// in case we have a bad fmt string, try not to crash the whole emulator
|
||||
fmt_len++;
|
||||
if (fmt_len == 1024) {
|
||||
ERROR_LOG(SCEKERNEL, "sysclib_sprintf fmt is longer than 1024");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!processing_specifier) {
|
||||
if (*c == '%') {
|
||||
specifier = "%";
|
||||
processing_specifier = true;
|
||||
bytes_to_read = 0;
|
||||
} else {
|
||||
result.append(1, *c);
|
||||
}
|
||||
} else {
|
||||
specifier.append(1, *c);
|
||||
|
||||
// going by https://cplusplus.com/reference/cstdio/printf/#compatibility
|
||||
// no idea what the kernel module really supports as of writing this
|
||||
switch (*c) {
|
||||
case '%':
|
||||
{
|
||||
result.append(specifier);
|
||||
processing_specifier = false;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
// consume 4 bytes from arguments
|
||||
u32 val = 0;
|
||||
if (arg_idx <= 1) {
|
||||
val = currentMIPS->r[MIPS_REG_A2 + arg_idx];
|
||||
} else if(arg_idx <= 5) {
|
||||
val = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2];
|
||||
} else {
|
||||
int stack_idx = arg_idx - 6;
|
||||
u32 stack_cur = currentMIPS->r[MIPS_REG_SP] + stack_idx * 4;
|
||||
|
||||
if (!Memory::IsValidAddress(stack_cur)) {
|
||||
ERROR_LOG(SCEKERNEL, "sysclib_sprintf bad stack pointer %08x", stack_cur);
|
||||
return 0;
|
||||
}
|
||||
val = Memory::Read_U32(stack_cur);
|
||||
DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fetching %08x from sp + %u", val, stack_idx * 4);
|
||||
}
|
||||
arg_idx++;
|
||||
|
||||
if (!Memory::IsValidAddress(val)) {
|
||||
ERROR_LOG(SCEKERNEL, "sysclib_sprintf bad string reference %08x", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *str = Memory::GetCharPointerUnchecked(val);
|
||||
// limit the string length and hope that we don't crash on a bad string reference
|
||||
char buf[1024] = {0};
|
||||
strncpy(buf, str, sizeof(buf));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
result.append(buf);
|
||||
processing_specifier = false;
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'c':
|
||||
case 'p':
|
||||
case 'n':
|
||||
{
|
||||
u64 val = 0;
|
||||
if (bytes_to_read == 0) {
|
||||
bytes_to_read = 4;
|
||||
}
|
||||
int read_cnt = 0;
|
||||
while (bytes_to_read != 0) {
|
||||
u32 val_from_arg = 0;
|
||||
if (arg_idx <= 1) {
|
||||
val_from_arg = currentMIPS->r[MIPS_REG_A2 + arg_idx];
|
||||
} else if (arg_idx <= 5) {
|
||||
val_from_arg = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2];
|
||||
} else {
|
||||
int stack_idx = arg_idx - 6;
|
||||
u32 stack_cur = currentMIPS->r[MIPS_REG_SP] + stack_idx * 4;
|
||||
|
||||
if (!Memory::IsValidAddress(stack_cur)) {
|
||||
ERROR_LOG(SCEKERNEL, "sysclib_sprintf bad stack pointer %08x", stack_cur);
|
||||
return 0;
|
||||
}
|
||||
val_from_arg = Memory::Read_U32(stack_cur);
|
||||
DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fetching %08x from sp + %u", val_from_arg, stack_idx * 4);
|
||||
}
|
||||
arg_idx++;
|
||||
|
||||
val = val | ((u64)val_from_arg << (read_cnt * 32));
|
||||
|
||||
bytes_to_read = bytes_to_read - 4;
|
||||
read_cnt++;
|
||||
}
|
||||
char buf[1024] = {0};
|
||||
snprintf(buf, sizeof(buf), specifier.c_str(), val);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
result.append(buf);
|
||||
processing_specifier = false;
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
{
|
||||
// allegrex calling convention is 4 bytes aligned
|
||||
bytes_to_read = 4;
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
{
|
||||
bytes_to_read = bytes_to_read + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if a small buffer was allocated by the program, we will likely crash
|
||||
strcpy((char *)Memory::GetPointerUnchecked(dst), result.c_str());
|
||||
return result.length();
|
||||
}
|
||||
|
||||
static u32 sysclib_memset(u32 destAddr, int data, int size) {
|
||||
|
||||
Reference in new issue
Block a user