// Originally written in C++ by Lameguy64 // Ported to plain C by Orion #include #include #include #include "elf.h" #ifdef WIN32 #define strcasecmp _stricmp #endif #define MAX_prg_entry_count 128 #define true (1) #define false (0) 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 [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" ); fclose( fp ); 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 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 >= 0x00000000) && (exe_taddr < 0x00001000)) || ((exe_taddr >= 0x80000000) && (exe_taddr < 0x80001000)) || ((exe_taddr >= 0xa0000000) && (exe_taddr < 0xa0001000)) ) printf("WARNING: program text address overlaps kernel area!\n"); // Throw warning if executable is larger than 2MB if (exe_tsize > 0x1f0000) printf("WARNING: executable is larger than available RAM on a stock console!\n"); // Pad out the size to multiples of 2KB (CD sector size) exe_tsize = ((exe_tsize + 2047) / 2048) * 2048; // Load the binary data binary = (unsigned char*)malloc( exe_tsize ); memset( binary, 0x0, exe_tsize ); for( i=0; i