aboutsummaryrefslogtreecommitdiff
path: root/tools/util
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-04-06 10:11:07 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-04-06 10:11:07 +0800
commitf3e040230772f978540a71aea43dfde200992922 (patch)
treebd8ca31b72dd01e24980b073854e263589530f56 /tools/util
downloadpsn00bsdk-f3e040230772f978540a71aea43dfde200992922.tar.gz
First commit
Diffstat (limited to 'tools/util')
-rw-r--r--tools/util/elf2x.c300
-rw-r--r--tools/util/makefile19
2 files changed, 319 insertions, 0 deletions
diff --git a/tools/util/elf2x.c b/tools/util/elf2x.c
new file mode 100644
index 0000000..940e4a1
--- /dev/null
+++ b/tools/util/elf2x.c
@@ -0,0 +1,300 @@
+// Originally written in C++ by Lameguy64
+// Ported to plain C by Orion
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_prg_entry_count 128
+#define true (1)
+#define false (0)
+
+#pragma pack(push, 1)
+
+typedef struct {
+
+ unsigned int magic; // 0-3
+ unsigned char word_size; // 4
+ unsigned char endianness; // 5
+ unsigned char elf_version; // 6
+ unsigned char os_abi; // 7
+ unsigned int unused[2]; // 8-15
+
+ unsigned short type; // 16-17
+ unsigned short instr_set; // 18-19
+ unsigned int elf_version2; // 20-23
+
+ unsigned int prg_entry_addr; // 24-27
+ unsigned int prg_head_pos; // 28-31
+ unsigned int sec_head_pos; // 32-35
+ unsigned int flags; // 36-39
+ unsigned short head_size; // 40-41
+ unsigned short prg_entry_size; // 42-23
+ unsigned short prg_entry_count; // 44-45
+ unsigned short sec_entry_size; // 46-47
+ unsigned short sec_entry_count; // 48-49
+ unsigned short sec_names_index; // 50-51
+
+} ELF_HEADER;
+
+typedef struct {
+ unsigned int seg_type;
+ unsigned int p_offset;
+ unsigned int p_vaddr;
+ unsigned int undefined;
+ unsigned int p_filesz;
+ unsigned int p_memsz;
+ unsigned int flags;
+ unsigned int alignment;
+} PRG_HEADER;
+
+#pragma pack(pop)
+
+typedef struct {
+ unsigned int pc0;
+ unsigned int gp0;
+ unsigned int t_addr;
+ unsigned int t_size;
+ unsigned int d_addr;
+ unsigned int d_size;
+ unsigned int b_addr;
+ unsigned int b_size;
+ unsigned int sp_addr;
+ unsigned int sp_size;
+ unsigned int sp;
+ unsigned int fp;
+ unsigned int gp;
+ unsigned int ret;
+ unsigned int base;
+} EXEC;
+
+typedef struct {
+ char header[8];
+ char pad[8];
+ EXEC params;
+ char license[64];
+ char pad2[1908];
+} PSEXE;
+
+int main(int argc, char** argv) {
+
+ char* in_file = NULL;
+ char* out_file = NULL;
+ int quiet = false;
+ int i;
+ FILE* fp;
+ ELF_HEADER head;
+ PRG_HEADER prg_heads[MAX_prg_entry_count];
+ unsigned int exe_taddr = 0xffffffff;
+ unsigned int exe_haddr = 0;
+ unsigned int exe_tsize = 0;
+ unsigned char* binary;
+ PSEXE exe;
+ char *output_name;
+
+ for( i=1; i<argc; i++ ) {
+
+ if( strcasecmp( "-q", argv[i] ) == 0 ) {
+
+ quiet = true;
+
+ } else {
+
+ if( in_file == NULL ) {
+ in_file = argv[i];
+ } else if( out_file == NULL ) {
+ out_file = argv[i];
+ }
+
+ }
+
+ }
+
+ if( !quiet ) {
+ printf( "PSn00bSDK elf2x - ELF to PS-EXE Converter\n" );
+ printf( "2018-2019 Meido-Tek Productions\n\n" );
+ }
+
+ if( argc == 1 ) {
+ printf( "Usage:\n" );
+ printf( " elf2x [-q] <elf_file> [exe_file]\n" );
+ return 0;
+ }
+
+ if( in_file == NULL ) {
+ printf( "No input file specified.\n" );
+ return EXIT_FAILURE;
+ }
+
+
+ fp = fopen( in_file, "rb" );
+
+ if( fp == NULL ) {
+ printf( "Cannot open file %s.\n", in_file );
+ return EXIT_FAILURE;
+ }
+
+ fread( &head, 1, sizeof(head), fp );
+
+
+ // Check header
+ if( head.magic != 0x464c457f ) {
+ printf( "File is not an ELF file.\n" );
+ return EXIT_FAILURE;
+ }
+
+ if( head.type != 2 ) {
+ printf( "Only executable ELF files are supported.\n" );
+ fclose( fp );
+ return EXIT_FAILURE;
+ }
+
+ if( head.instr_set != 8 ) {
+ printf( "ELF file is not a MIPS binary.\n" );
+ fclose( fp );
+ return EXIT_FAILURE;
+ }
+
+ if( head.word_size != 1 ) {
+ printf( "Only 32-bit ELF files are supported.\n" );
+ fclose( fp );
+ return EXIT_FAILURE;
+ }
+
+ if( head.endianness != 1 ) {
+ printf( "Only little endian ELF files are supported.\n" );
+ fclose( fp );
+ return EXIT_FAILURE;
+ }
+
+
+ // Load program headers and determine binary size and load address
+
+ fseek( fp, head.prg_head_pos, SEEK_SET );
+ for( i=0; i<head.prg_entry_count; i++ ) {
+
+ fread( &prg_heads[i], 1, sizeof(PRG_HEADER), fp );
+
+ if( prg_heads[i].flags == 4 ) {
+ continue;
+ }
+
+ if( prg_heads[i].p_vaddr < exe_taddr ) {
+ exe_taddr = prg_heads[i].p_vaddr;
+ }
+
+ if( prg_heads[i].p_vaddr > exe_haddr ) {
+ exe_haddr = prg_heads[i].p_vaddr;
+ }
+
+ }
+
+ exe_tsize = (exe_haddr-exe_taddr);
+ exe_tsize += prg_heads[head.prg_entry_count-1].p_filesz;
+
+ if( !quiet ) {
+
+ printf( "pc:%08x t_addr:%08x t_size:%d\n",
+ head.prg_entry_addr, exe_taddr, exe_tsize );
+
+ }
+
+ // Check if load address is appropriate in main RAM locations
+ if( ( ( exe_taddr>>24 ) == 0x0 ) || ( ( exe_taddr>>24 ) == 0x80 ) ||
+ ( ( exe_taddr>>24 ) == 0xA0 ) ) {
+
+ if( ( exe_taddr&0x00ffffff ) < 65536 ) {
+
+ printf( "Warning: Program text address overlaps kernel area!\n" );
+
+ }
+
+ }
+
+
+ // Pad out the size to multiples of 2KB
+ exe_tsize = 2048*((exe_tsize+2047)/2048);
+
+ // Load the binary data
+ binary = (unsigned char*)malloc( exe_tsize );
+ memset( binary, 0x0, exe_tsize );
+
+ for( i=0; i<head.prg_entry_count; i++ ) {
+
+ if( prg_heads[i].flags == 4 ) {
+ continue;
+ }
+
+ fseek( fp, prg_heads[i].p_offset, SEEK_SET );
+ fread( &binary[(int)(prg_heads[i].p_vaddr-exe_taddr)],
+ 1, prg_heads[i].p_filesz, fp );
+
+ }
+
+ fclose( fp );
+
+
+ if( out_file ) {
+
+ output_name = out_file;
+
+ } else {
+ char *ptr;
+
+ // Generate output filename if no output is specified
+ output_name = in_file;
+
+ ptr = &output_name[strlen(output_name)];
+ while (ptr != output_name)
+ {
+ if (*ptr == '.')
+ break;
+ else
+ ptr--;
+ }
+
+ if (ptr != output_name)
+ {
+ strcpy(ptr, ".exe");
+ }
+ else
+ {
+ strcat(ptr, ".exe");
+ }
+ }
+
+
+ // Prepare PS-EXE header
+ memset( &exe, 0, sizeof(PSEXE) );
+
+ exe.params.sp_addr = 0x801FFFF0;
+ exe.params.t_addr = exe_taddr;
+ exe.params.t_size = exe_tsize;
+ exe.params.pc0 = head.prg_entry_addr;
+
+ strncpy( exe.header, "PS-X EXE", 8 );
+ strcpy( exe.license,
+ "Not Licensed or Endorsed by Sony Computer Entertainment Inc." );
+ strcpy( exe.pad2, "Built using GCC and PSn00bSDK libraries" );
+
+
+ // Write file
+ fp = fopen( output_name, "wb" );
+
+ if( !fp ) {
+ printf( "Cannot write output: %s\n", output_name );
+ free( binary );
+ fclose( fp );
+ }
+
+ fwrite( &exe, 1, sizeof( PSEXE ), fp );
+ fwrite( binary, 1, exe_tsize, fp );
+
+ fclose( fp );
+
+
+ free( binary );
+
+ return 0;
+}
+
diff --git a/tools/util/makefile b/tools/util/makefile
new file mode 100644
index 0000000..c49a581
--- /dev/null
+++ b/tools/util/makefile
@@ -0,0 +1,19 @@
+CFLAGS = -O2 -s
+
+CC = gcc
+
+ifeq "$(OS)" "Windows_NT"
+EXE_SUFFIX = .exe
+else
+EXE_SUFFIX =
+endif
+
+all:
+ $(CC) $(CFLAGS) elf2x.c -o elf2x$(EXE_SUFFIX)
+
+install:
+ mkdir -p ../bin
+ cp elf2x$(EXE_SUFFIX) ../bin/elf2x$(EXE_SUFFIX)
+
+clean:
+ rm -f elf2x$(EXE_SUFFIX)