From 7c24e9a9b02b04dcaf9507acb94091ea70a2c02d Mon Sep 17 00:00:00 2001 From: Xavi Del Campo Date: Fri, 31 Jan 2020 10:32:23 +0100 Subject: Imported pristine psxsdk-20190410 from official repo --- tools/psfex.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tools/psfex.c (limited to 'tools/psfex.c') diff --git a/tools/psfex.c b/tools/psfex.c new file mode 100644 index 0000000..3de4bc8 --- /dev/null +++ b/tools/psfex.c @@ -0,0 +1,113 @@ +/* + * psfex - Extracts an EXE from a PSF file + * + * Programmed by Giuseppe Gatta - released in the public domain + * It can be used for any platform which the PSF format supports, not only PS1. + */ + +#include +#include +#include + +// 0-2: PSF +// 3: Version byte (0x01 for PlayStation) +// 4: Size of reserved area (LE unsigned 32-bit) +// 8: Compressed program length (LE unsigned 32-bit) +// 12: Compressed program CRC32 (LE unsigned 32-bit) +// xxx: Reserved area +// xxx: Compressed program + +int main(int argc, char *argv[]) +{ + FILE *f; + unsigned char *fm; + unsigned int res_size; + unsigned int cprg_size; + unsigned int cprg_crc32; + unsigned char *om; + unsigned long dest_len; + int sz; + + if(argc < 3) + { + printf("psfex - Extracts an executable from a PSF file\n"); + printf("psfex [.psf] [output]\n"); + return -1; + } + + f = fopen(argv[1], "rb"); + + if (f == NULL) + { + printf("Could not open file.\n"); + return -1; + } + +/* + * Get PSF size and load it in memory + */ + + fseek(f, 0, SEEK_END); + sz = ftell(f); + fseek(f, 0, SEEK_SET); + + fm = malloc(sz); + fread(fm, sizeof(char), sz, f); + + fclose(f); + +/* + * Get header information +*/ + if(fm[0] == 'P' && fm[1] == 'S' && fm[2] == 'F') + { + printf("PSF file.\n"); + } + else + { + printf("Not a PSF file. Aborting.\n"); + return -1; + } + + res_size = fm[4] | (fm[5] << 8) | (fm[6]<<16) | (fm[7]<<24); + cprg_size = fm[8] | (fm[9] << 8) | (fm[10]<<16)|(fm[11]<<24); + cprg_crc32 = fm[12] | (fm[13]<<8)|(fm[14]<<16)|(fm[15]<<24); + + printf("Reserved area size: %d bytes\n", res_size); + printf("Compressed program size: %d bytes\n", cprg_size); + printf("Compressed program CRC32: 0x%08x\n", cprg_crc32); + +/* + * Decompress the program + * The PSF format is inherently flawed and so we have to allocate 2 megabytes + * of memory (size of PS1 RAM) and then get the real destination size at the end + */ + om = malloc(0x200000); + dest_len = 0x200000; + uncompress(om, &dest_len, &fm[16 + res_size], cprg_size); + + printf("Real destination length: %ld\n", dest_len); + +/* + * Now let's write the decompressed program to the output file + */ + f = fopen(argv[2], "wb"); + + if(f == NULL) + { + printf("Could not open %s for writing. Aborting.\n", argv[2]); + return -1; + } + + fwrite(om, sizeof(char), dest_len, f); + fclose(f); + +/* + * Free memory, at the exit it is done anyway but this helps adaptions + */ + + free(om); + free(fm); + + return 0; +} -- cgit v1.2.3