Skip to content

Instantly share code, notes, and snippets.

@Kethen
Last active November 15, 2023 10:01
Show Gist options
  • Save Kethen/a95a0a825cf9d14e7cd8d30c0ad3e2fc to your computer and use it in GitHub Desktop.
Save Kethen/a95a0a825cf9d14e7cd8d30c0ad3e2fc to your computer and use it in GitHub Desktop.
sony psp param.sfo dumper
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#define CONV_LE(addr, dest) { \
dest = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24; \
}
#define CONV_LE16(addr, dest) { \
dest = addr[0] | addr[1] << 8; \
}
int main(int argc, char **argv){
if(argc != 2){
printf("this program takes exactly one argument, path to param.sfo\n");
exit(1);
}
int fd = open(argv[1], O_RDONLY);
if(fd <= 0){
printf("cannot open %s for reading\n", argv[1]);
}
lseek(fd, 0x08, SEEK_SET);
unsigned char buf[4];
if(read(fd, &buf, 4) != 4){
close(fd);
printf("failed reading key table start from sfo\n");
return -1;
}
uint32_t key_table_start = 0;
CONV_LE(buf, key_table_start);
printf("key_table_start is %ld\n", key_table_start);
if(read(fd, &buf, 4) != 4){
close(fd);
printf("failed reading data table start from sfo\n");
return -1;
}
uint32_t data_table_start = 0;
CONV_LE(buf, data_table_start);
printf("data_table_start is %ld\n", data_table_start);
if(read(fd, &buf, 4) != 4){
close(fd);
printf("failed reading tables entries from sfo\n");
return -1;
}
uint32_t tables_entries = 0;
CONV_LE(buf, tables_entries);
printf("tables_entries is %ld\n", tables_entries);
int i;
for(i = 0;i < tables_entries;i++){
lseek(fd, 0x14 + i * 0x10, SEEK_SET);
if(read(fd, &buf, 2) != 2){
close(fd);
printf("failed reading key offset from sfo\n");
return -1;
}
uint32_t key_offset = 0;
CONV_LE16(buf, key_offset);
if(read(fd, &buf, 2) != 2){
close(fd);
printf("failed reading data format from sfo\n");
return -1;
}
uint32_t data_format = 0;
CONV_LE16(buf, data_format);
if(read(fd, &buf, 4) != 4){
close(fd);
printf("failed reading data len from sfo\n");
return -1;
}
uint32_t data_len = 0;
CONV_LE(buf, data_len);
lseek(fd, 4, SEEK_CUR);
if(read(fd, &buf, 4) != 4){
close(fd);
printf("failed reading data offset from sfo\n");
return -1;
}
uint32_t data_offset = 0;
CONV_LE(buf, data_offset);
lseek(fd, key_offset + key_table_start, SEEK_SET);
char keybuf[50];
int j;
for(j = 0;j < 50;j++){
if(read(fd, &keybuf[j], 1) != 1){
close(fd);
printf("failed reading key from sfo\n");
}
if(keybuf[j] == 0){
break;
}
}
printf("key is %s\n", keybuf);
lseek(fd, data_offset + data_table_start, SEEK_SET);
char databuf[data_len];
for(j = 0;j < data_len; j++){
if(read(fd, &databuf[j], 1) != 1){
close(fd);
printf("failed reading data from sfo\n");
}
}
if(data_format == 0x0204){
printf("utf8 data: %s\n", databuf);
}else{
printf("hex data: ");
int j;
for(j = 0;j < data_len; j++){
if(j != 0 && j % 16 == 0){
printf("| ");
}
printf("0x%02x ", (uint8_t)databuf[j]);
}
printf("\n");
}
}
close(fd);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment