forked from st4rk/PkgDecrypt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sfo.c
122 lines (110 loc) · 3.34 KB
/
sfo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
* SFO/PSF files reader.
*/
#include "sfo.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char *name;
uint8_t *value;
uint32_t value_len;
uint32_t type;
} _PSF_ITEM;
typedef struct {
uint8_t *buffer;
uint32_t item_count;
_PSF_ITEM *item;
} _PSF;
PSF psfParse( const uint8_t *buffer ) {
uint32_t *ubuf = (uint32_t *) buffer;
if ( *ubuf == 0x46535000 && *( ubuf + 1 ) == 0x101 ) {
char *names = (char *) buffer + *( ubuf + 2 );
uint8_t *values = buffer + *( ubuf + 3 );
uint32_t count = *( ubuf + 4 );
buffer += 20;
_PSF *psf = malloc( sizeof( _PSF ) + sizeof( _PSF_ITEM ) * count );
psf->item = (_PSF_ITEM *) ( (uint8_t *) psf + sizeof( _PSF ) );
for ( uint32_t i = 0; i < count; i++ ) {
psf->item[i].name = names + *( (uint16_t *) buffer );
psf->item[i].type = *( buffer + 3 );
psf->item[i].value_len = *( (uint32_t *) buffer + 1 );
if ( psf->item[i].type == 0x2 ) {
//Strings in psf isn't zero terminated
psf->item[i].value = malloc( psf->item[i].value_len + 1 );
memset( psf->item[i].value, 0, psf->item[i].value_len + 1 );
memcpy( psf->item[i].value, values + *( (uint32_t *) buffer + 3 ), psf->item[i].value_len );
} else {
psf->item[i].value = values + *( (uint32_t *) buffer + 3 );
}
buffer += 16;
//printf("PSF%u: %s, %u, %X, %u\n", i, psf->item[i].name, psf->item[i].type, psf->item[i].value, psf->item[i].value_len);
}
psf->buffer = NULL;
psf->item_count = count;
return psf;
}
return NULL;
}
PSF psfRead( const char *path ) {
FILE *in = fopen( path, "rb" );
if ( in ) {
uint8_t *buf = malloc( 0x10000 );
int length = fread( buf, sizeof( uint8_t ), 0x10000, in );
if ( length ) {
PSF p = psfParse( buf );
if ( p ) {
//Set buffer ptr to free it automatically later
( (_PSF *) p )->buffer = buf;
return p;
} else {
free( buf );
}
} else {
free( buf );
}
}
return NULL;
}
void psfDiscard( PSF psf ) {
_PSF *_psf = (_PSF *) psf;
if ( _psf ) {
for ( int i = 0; i < _psf->item_count; i++ ) {
if ( _psf->item[i].type == 0x2 ) {
free( _psf->item[i].value );
}
}
if ( _psf->buffer )
free( _psf->buffer );
free( _psf );
}
}
static int findItemIndex( _PSF *psf, const char *name ) {
if ( name ) {
for ( int i = 0; i < psf->item_count; i++ ) {
if ( strcmp( psf->item[i].name, name ) == 0 ) {
return i;
}
}
}
return -1;
}
char *psfGetString( PSF psf, const char *name ) {
if ( psf ) {
int index = findItemIndex( (_PSF *) psf, name );
if ( index >= 0 ) {
return (char *) ( ( (_PSF *) psf )->item[index].value );
}
}
return "";
}
int psfGetInt( PSF psf, const char *name ) {
if ( psf ) {
int index = findItemIndex( (_PSF *) psf, name );
if ( index >= 0 ) {
return *( (int *) ( ( (_PSF *) psf )->item[index].value ) );
}
}
return 0;
}