SceError

From Vita Development Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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
int _sceErrorHistoryPostError(const SceErrorHistoryPostInfo *info);

_sceErrorGetExternalString

Version NID
1.69-3.60 0x85747003
int _sceErrorGetExternalString(SceErrorStrings *error_strings, int error_code);

_sceErrorHistorySetDefaultFormat

Version NID
1.69-3.60 0xB94DAA2F
int _sceErrorHistorySetDefaultFormat(const SceErrorDefaultFormat *a1);

_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 ch);

_sceErrorHistoryGetError

Version NID
1.69-3.60 0xF16DF981
int _sceErrorHistoryGetError(SceUInt32 error_idx, SceErrorHistoryInfo *info);

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;
}