Module
Version |
World |
Privilege
|
1.69-3.60 |
Non-secure |
Kernel
|
Libraries
Known NIDs
Version |
Name |
World |
Visibility |
NID
|
1.69 |
SceErrorForDriver |
Non-secure |
Kernel |
0xBA576248
|
1.69-3.60 |
SceError |
Non-secure |
User |
0x5CD2CAD1
|
Types
typedef struct SceErrorDefaultFormat {
int data1;
int data2;
} SceErrorDefaultFormat;
typedef struct SceErrorStrings {
char s[0x10];
} SceErrorStrings;
typedef struct SceErrorHistoryPostInfo { // size is 0x180
char error_message[0x100];
char data_0x100[0x40]; // unknown
int error_code_hex;
int data_0x174;
SceUInt version; // from SceKernelFwInfo
int data_0x17C;
char titleid[0xC];
int data_0x15C; // from SceKernelFwInfo->unk_24
char data_0x160[0x20];
} SceErrorHistoryPostInfo;
typedef struct SceErrorHistoryInfo {
int data_0x00;
int data_0x04;
SceInt64 time;
SceErrorStrings error_code;
char data_0x20[0x10];
SceErrorHistoryPostInfo post;
} SceErrorHistoryInfo;
typedef struct SceErrorSequenceInfo { // size is 0x20
int data[8];
} SceErrorSequenceInfo;
SceErrorForDriver
SceError
_sceErrorHistoryUpdateSequenceInfo
Version |
NID
|
1.69-3.60 |
0x6FBE4BDC
|
int _sceErrorHistoryUpdateSequenceInfo(const SceErrorSequenceInfo *info, int a2);
_sceErrorHistoryPostError
Version |
NID
|
1.69-3.60 |
0x70F9D872
|
//src_user is of size 0x180
int _sceErrorHistoryPostError(void* src_user);
_sceErrorGetExternalString
Version |
NID
|
1.69-3.60 |
0x85747003
|
//dest is of size 0x10
int _sceErrorGetExternalString(void* dest_user, int unk);
_sceErrorHistorySetDefaultFormat
Version |
NID
|
1.69-3.60 |
0xB94DAA2F
|
//src_user is of size 0x08
int _sceErrorHistorySetDefaultFormat(void* src_user);
_sceErrorHistoryClearError
Version |
NID
|
1.69-3.60 |
0xC88F479E
|
//argument can be only 0, or SCE_ERROR_ERRNO_EINVAL error will be returned
int _sceErrorHistoryClearError(int zero);
_sceErrorHistoryGetError
Version |
NID
|
1.69-3.60 |
0xF16DF981
|
//dest_user is of size 0x1B0
int _sceErrorHistoryGetError (int unk0, void* dest_user);
Error table translation
In various places PSVita may display errors translated into their string representation. The code below also does this, provided you feed it with a copy of os0:kd/error_table.bin
.
#include <stdlib.h>
#include <stdio.h>
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
int read_error_table(const char *path, void *buf) {
unsigned int v6; // r1@6
unsigned int v7; // r1@10
FILE *f = fopen(path, "rb");
if ( f ) {
if ( fread(buf, 1, 8, f) == 8 ) {
v6 = *((short *)buf + 2);
if ( v6 <= 0x20 )
{
if ( fread(*((int *)buf + 2), 1, 8 * v6, f) == 8 * v6
&& fread((char *)buf + 12, 1, 4, f) == 4 ) {
v7 = *((short *)buf + 7);
if ( v7 <= 0x36B0 ) {
if ( fread(*((int *)buf + 4), 1, 4 * v7, f) == 4 * v7 ) {
fclose(f);
return 0;
}
}
else
fprintf(stderr, "[SceError] error_table_num = %d\n", v7);
}
}
else
fprintf(stderr, "[SceError] facility_group_num = %d\n", v6);
}
fclose(f);
}
*(int *)buf = 0;
*((int *)buf + 1) = 0;
*((int *)buf + 2) = 0;
*((int *)buf + 3) = 0;
*((int *)buf + 4) = 0;
*((int *)buf + 5) = 0;
return 0;
}
#define _WORD short
#define _DWORD int
#define _BYTE char
int error_code_to_string(int error_table, char *output, unsigned int error_code) {
signed int v4; // r7@2
int v5; // r4@2
int v6; // r2@4
int v7; // r5@4
int v8; // t1@6
int v9; // t1@9
int v10; // t1@10
int v11; // r5@11
int v12; // r12@11
int v13; // r6@11
int v14; // r5@12
int v15; // t1@12
int v16; // r5@13
int v17; // t1@13
signed int v18; // lr@17
unsigned int v19; // r3@17
int v20; // r4@17
int v21; // r6@18
int v22; // r5@18
signed int v23; // r6@19
signed int v24; // r5@23
signed int v25; // r5@25
signed int v26; // r7@28
int v27; // r5@28
signed int v28; // r7@30
signed int v29; // r7@32
signed int v30; // r5@35
int v31; // r6@37
int v32; // r3@38
int v33; // r4@39
int v34; // r5@40
signed int v35; // r2@41
signed int v36; // r6@41
int v37; // r7@42
if (!output)
return 0;
v4 = *(_WORD *)(error_table + 14);
v5 = *(_DWORD *)(error_table + 16);
if (!*(_WORD *)(error_table + 14))
goto LABEL_46;
if (*(_DWORD *)v5 == error_code) {
v6 = 0;
goto LABEL_17;
}
v6 = 0;
v7 = ((_BYTE)v4 - 1) & 3;
if (!(((_BYTE)v4 - 1) & 3))
goto LABEL_11;
v6 = 1;
if (v4 <= 1) {
LABEL_46:
snprintf(output, 16, "E-%08x", error_code);
return 0;
}
v8 = *(_DWORD *)(v5 + 4);
v5 += 4;
if (v8 != error_code) {
if (v7 == 1
|| (v7 == 2 || (v9 = *(_DWORD *)(v5 + 4), v5 += 4, v6 = 2, v9 != error_code))
&& (v10 = *(_DWORD *)(v5 + 4), v5 += 4, ++v6, v10 != error_code)) {
LABEL_11:
while (1) {
++v6;
v11 = v5;
v12 = v5 + 12;
v13 = v6;
v5 += 16;
if (v6 >= v4)
goto LABEL_46;
v15 = *(_DWORD *)(v11 + 4);
v14 = v11 + 4;
if (v15 != error_code) {
v17 = *(_DWORD *)(v14 + 4);
v16 = v14 + 4;
++v6;
if (v17 != error_code) {
v6 = v13 + 2;
if (*(_DWORD *)(v16 + 4) != error_code) {
v6 = v13 + 3;
if (*(_DWORD *)(v12 + 4) != error_code)
continue;
}
}
}
break;
}
}
}
if (*(_WORD *)(error_table + 6) < v6) {
snprintf(output, 16, "*-%08x", error_code);
return 0;
}
LABEL_17:
v18 = *(_WORD *)(error_table + 4);
v19 = (error_code >> 16) & 0xFFF;
v20 = *(_DWORD *)(error_table + 8);
if (*(_WORD *)(error_table + 4)) {
v21 = 0;
v22 = ((_BYTE)v18 - 1) & 3;
if (!(((_BYTE)v18 - 1) & 3)) {
LABEL_35:
while (1) {
v30 = *(_WORD *)v20;
if ((signed int)v19 >= v30 && (signed int)v19 < *(_WORD *)(v20 + 2) + v30)
goto LABEL_48;
v31 = v21 + 1;
if (v31 >= v18)
goto LABEL_38;
v20 += 8;
v26 = *(_WORD *)v20;
v27 = v20;
if ((signed int)v19 >= v26 && (signed int)v19 < v26 + *(_WORD *)(v20 + 2))
goto LABEL_48;
v28 = *(_WORD *)(v20 + 8);
v20 += 8;
if ((signed int)v19 >= v28 && (signed int)v19 < v28 + *(_WORD *)(v27 + 10))
goto LABEL_48;
v29 = *(_WORD *)(v27 + 16);
v20 = v27 + 16;
if ((signed int)v19 >= v29 && (signed int)v19 < v29 + *(_WORD *)(v27 + 18))
goto LABEL_48;
v21 = v31 + 3;
v20 = v27 + 24;
}
}
v23 = *(_WORD *)v20;
if ((signed int)v19 >= v23 && (signed int)v19 < *(_WORD *)(v20 + 2) + v23) {
LABEL_48:
v32 = v20 + 4;
goto LABEL_39;
}
v21 = 1;
if (v18 > 1) {
v20 += 8;
if (v22 == 1)
goto LABEL_35;
if (v22 != 2) {
v24 = *(_WORD *)v20;
if ((signed int)v19 >= v24 && (signed int)v19 < *(_WORD *)(v20 + 2) + v24) {
v32 = v20 + 4;
goto LABEL_39;
}
v21 = 2;
v20 += 8;
}
v25 = *(_WORD *)v20;
if ((signed int)v19 < v25 || (signed int)v19 >= *(_WORD *)(v20 + 2) + v25) {
++v21;
v20 += 8;
goto LABEL_35;
}
goto LABEL_48;
}
}
LABEL_38:
v32 = error_table;
LABEL_39:
v33 = v6 + *(_WORD *)(error_table + 12);
if (v33) {
v35 = v6 + *(_WORD *)(error_table + 12);
v36 = 0;
do {
v37 = v35 % 10;
v35 /= 10;
v36 += v37;
} while (v35);
v34 = v36 % 10;
}
else
v34 = 0;
snprintf(output, 16, "%s-%d-%1d", v32, v33, v34);
return 0;
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: ./error error_table.bin 0xC0DE");
return 1;
}
int *error_table = calloc(1, 1024 * 1024);
error_table[2] = calloc(1, 1024 * 1024);
error_table[4] = calloc(1, 1024 * 1024);
read_error_table(argv[1], error_table);
char *str = calloc(1, 500);
error_code_to_string(error_table, str, strtoul(argv[2], NULL, 0));
printf("%s\n", str);
free(str);
free(error_table[2]);
free(error_table[4]);
free(error_table);
return 0;
}