From a38a27aa9c2b3898e2f2058a38242865d2809de3 Mon Sep 17 00:00:00 2001 From: arcum42 Date: Sat, 2 Jan 2010 13:27:15 +0000 Subject: [PATCH] Mucked around with Elfheaders a bit. Cranked up the number of chars in DisR3000A (Because I own a few games with symbols over 64 chars). A few other things. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2407 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVD.cpp | 58 +-- pcsx2/CDVD/CDVDaccess.cpp | 2 +- pcsx2/CDVD/IsoFileFormats.cpp | 22 +- pcsx2/Config.h | 4 +- pcsx2/DebugTools/DisR5900.cpp | 4 +- pcsx2/Elfheader.cpp | 630 ++++++++++++++------------------- pcsx2/Elfheader.h | 140 +++++++- pcsx2/Patch.cpp | 1 - pcsx2/System/SysCoreThread.cpp | 5 +- pcsx2/VU0.cpp | 8 + 10 files changed, 475 insertions(+), 399 deletions(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 7958d78634..97585a9e08 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -305,30 +305,50 @@ s32 cdvdWriteConfig(const u8* config) static MutexLockRecursive Mutex_NewDiskCB; -static void reloadElfInfo(const char* str) +static __forceinline void _reloadElfInfo(wxString str) { // Now's a good time to reload the ELF info... - if (ElfCRC == 0) - { - ScopedLock locker( Mutex_NewDiskCB ); - - ElfCRC = loadElfCRC( str ); - ElfApplyPatches(); - GetMTGS().SendGameCRC( ElfCRC ); - } + ScopedLock locker( Mutex_NewDiskCB ); + + ElfCRC = loadElfCRC(str); + + ElfApplyPatches(); + GetMTGS().SendGameCRC(ElfCRC); } -void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { - wxString fname; - char exeName[12]; +static __forceinline void reloadElfInfo(u32 discType, wxString str) +{ + if (ElfCRC == 0) + { + switch (discType) + { + case 2: // Is a PS2 disc. + _reloadElfInfo(str); + break; + case 1: // Is a PS1 disc. + if (ENABLE_LOADING_PS1_GAMES) _reloadElfInfo(str); + break; + default: // Isn't a disc we recognise. + break; + } + } +} + +void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) +{ s32 numbers, letters; u32 key_0_3; u8 key_4, key_14; - // get main elf name - bool IsPs2 = (GetPS2ElfName(fname) == 2); + wxString fname; + char exeName[12]; + + // Get the main elf name. + u32 discType = GetPS2ElfName(fname); + const wxCharBuffer crap( fname.To8BitData() ); const char* str = crap.data(); + sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]); DevCon.Warning("exeName = %s", &str[8]); @@ -390,7 +410,7 @@ void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { Console.WriteLn( "CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X", cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15] ); - if (IsPs2) reloadElfInfo(str); + reloadElfInfo(discType, fname); } s32 cdvdGetToc(void* toc) @@ -512,12 +532,10 @@ void SaveStateBase::cdvdFreeze() static void cdvdDetectDisk() { - cdvd.Type = DoCDVDdetectDiskType(); - wxString str; - bool IsPs2 = (GetPS2ElfName(str) == 2); - - if (IsPs2) reloadElfInfo( str.ToUTF8() ); + cdvd.Type = DoCDVDdetectDiskType(); + + reloadElfInfo(GetPS2ElfName(str), str); } void cdvdNewDiskCB() diff --git a/pcsx2/CDVD/CDVDaccess.cpp b/pcsx2/CDVD/CDVDaccess.cpp index 100e463e9e..a354a80809 100644 --- a/pcsx2/CDVD/CDVDaccess.cpp +++ b/pcsx2/CDVD/CDVDaccess.cpp @@ -204,7 +204,7 @@ static int FindDiskType(int mType) switch (iCDType) { case CDVD_TYPE_PS2CD: - iCDType=CDVD_TYPE_PS2CDDA; + iCDType=CDVD_TYPE_PS2CDDA; break; case CDVD_TYPE_PSCD: iCDType=CDVD_TYPE_PSCDDA; diff --git a/pcsx2/CDVD/IsoFileFormats.cpp b/pcsx2/CDVD/IsoFileFormats.cpp index 0003d482f9..5b101a0f95 100644 --- a/pcsx2/CDVD/IsoFileFormats.cpp +++ b/pcsx2/CDVD/IsoFileFormats.cpp @@ -180,14 +180,20 @@ isoFile *isoOpen(const char *filename) _seekfile(iso->handle, 0, SEEK_END); iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / (iso->blocksize)); } - - Console.WriteLn("isoOpen: %s ok", iso->filename); - Console.WriteLn("offset = %d", iso->offset); - Console.WriteLn("blockofs = %d", iso->blockofs); - Console.WriteLn("blocksize = %u", iso->blocksize); - Console.WriteLn("blocks = %u", iso->blocks); - Console.WriteLn("type = %u", iso->type); - + + switch(iso->type) + { + case ISOTYPE_CD: Console.Write("isoOpen(CD): "); break; + case ISOTYPE_DVD: Console.Write("isoOpen(DVD): "); break; + case ISOTYPE_AUDIO: Console.Write("isoOpen(Audio CD): "); break; + case ISOTYPE_DVDDL: Console.Write("isoOpen(DVDDL): "); break; + case ISOTYPE_ILLEGAL: + default: Console.Write("isoOpen(illegal media): "); break; + } + Console.WriteLn("%s ok.", iso->filename); + Console.WriteLn("The iso has %u blocks (size %u).", iso->blocks, iso->blocksize); + Console.WriteLn("The isos offset is %d, and the block offset is %d.", iso->offset, iso->blockofs); + return iso; } diff --git a/pcsx2/Config.h b/pcsx2/Config.h index ec1c60b3f0..9a1aad8c75 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -619,11 +619,11 @@ TraceLogFilters& SetTraceConfig(); #define EE_CONST_PROP // rec2 - enables constant propagation (faster) -// Uncomment this if working on getting PS1 emulation working. +// Change to 1 if working on getting PS1 emulation working. // This disables the exception normally caused by trying to load PS1 // games. Note: currently PS1 games will error out even without this // commented, so this is for development purposes only. -//#define ENABLE_LOADING_PS1_GAMES +#define ENABLE_LOADING_PS1_GAMES 0 // Change to 1 to enable SIF wakeup hack: #define IOP_ENABLE_SIF_HACK 0 diff --git a/pcsx2/DebugTools/DisR5900.cpp b/pcsx2/DebugTools/DisR5900.cpp index 7be7c0d094..223ed73fb6 100644 --- a/pcsx2/DebugTools/DisR5900.cpp +++ b/pcsx2/DebugTools/DisR5900.cpp @@ -164,7 +164,7 @@ typedef void (*TdisR5900F)DisFInterface; struct sSymbol { u32 addr; - char name[64]; + char name[256]; }; static sSymbol *dSyms = NULL; @@ -186,7 +186,7 @@ void disR5900AddSym(u32 addr, const char *name) { if (dSyms == NULL) return; dSyms[nSyms].addr = addr; - strncpy(dSyms[nSyms].name, name, 64); + strncpy(dSyms[nSyms].name, name, 256); nSyms++; } diff --git a/pcsx2/Elfheader.cpp b/pcsx2/Elfheader.cpp index 51eea99389..6554362ccb 100644 --- a/pcsx2/Elfheader.cpp +++ b/pcsx2/Elfheader.cpp @@ -17,113 +17,13 @@ #include "Common.h" #include "GS.h" // for sending game crc to mtgs - -#include "CDVD/IsoFS/IsoFSCDVD.h" -#include "CDVD/IsoFS/IsoFS.h" +#include "Elfheader.h" using namespace std; extern void InitPatch(const wxString& crc); u32 ElfCRC; -struct ELF_HEADER { - u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) - u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE - u16 e_machine; //Processor: 8=MIPS R3000 - u32 e_version; //Version: 1=current - u32 e_entry; //Entry point address - u32 e_phoff; //Start of program headers (offset from file start) - u32 e_shoff; //Start of section headers (offset from file start) - u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips - u16 e_ehsize; //ELF header size (0x34 = 52 bytes) - u16 e_phentsize; //Program headers entry size - u16 e_phnum; //Number of program headers - u16 e_shentsize; //Section headers entry size - u16 e_shnum; //Number of section headers - u16 e_shstrndx; //Section header stringtable index -}; - -struct ELF_PHR { - u32 p_type; //see notes1 - u32 p_offset; //Offset from file start to program segment. - u32 p_vaddr; //Virtual address of the segment - u32 p_paddr; //Physical address of the segment - u32 p_filesz; //Number of bytes in the file image of the segment - u32 p_memsz; //Number of bytes in the memory image of the segment - u32 p_flags; //Flags for segment - u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment -}; - -/* -notes1 ------- -0=Inactive -1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 -2=Dynamic linking -3=Interpreter. The array element must specify a path name -4=Note. The array element must specify the location and size of aux. info -5=reserved -6=The array element must specify location and size of the program header table. -*/ - -struct ELF_SHR { - u32 sh_name; //No. to the index of the Section header stringtable index - u32 sh_type; //See notes2 - u32 sh_flags; //see notes3 - u32 sh_addr; //Section start address - u32 sh_offset; //Offset from start of file to section - u32 sh_size; //Size of section - u32 sh_link; //Section header table index link - u32 sh_info; //Info - u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. - u32 sh_entsize; //Fixed size entries. -}; - -/* -notes 2 -------- -Type: -0=Inactive -1=PROGBITS -2=SYMTAB symbol table -3=STRTAB string table -4=RELA relocation entries -5=HASH hash table -6=DYNAMIC dynamic linking information -7=NOTE -8=NOBITS -9=REL relocation entries -10=SHLIB -0x70000000=LOPROC processor specifc -0x7fffffff=HIPROC -0x80000000=LOUSER lower bound -0xffffffff=HIUSER upper bound - -notes 3 -------- -Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) -1=Write section contains data the is be writeable during execution. -2=Alloc section occupies memory during execution -4=Exec section contains executable instructions -0xf0000000=Mask bits processor-specific -*/ - -struct Elf32_Sym { - u32 st_name; - u32 st_value; - u32 st_size; - u8 st_info; - u8 st_other; - u16 st_shndx; -}; - -#define ELF32_ST_TYPE(i) ((i)&0xf) - -struct Elf32_Rel { - u32 r_offset; - u32 r_info; -}; - #if 0 // fixme: ELF command line option system. // It parses a command line and pastes it into PS2 memory, and then points the a0 register at it. @@ -238,280 +138,301 @@ static uint parseCommandLine( const wxString& filename ) #endif //--------------- -struct ElfObject +// All of ElfObjects functions. +ElfObject::ElfObject(const wxString& srcfile, IsoFile isofile) + : filename( srcfile ) + + , data( wxULongLong(isofile.getLength()).GetLo(), L"ELF headers" ) + , header( *(ELF_HEADER*)data.GetPtr() ) + , proghead( NULL ) + , secthead( NULL ) { - wxString filename; - SafeArray data; - ELF_HEADER& header; - ELF_PHR* proghead; - ELF_SHR* secthead; + isCdvd = true; + checkElfSize(data.GetSizeInBytes()); + readIso(isofile); + initElfHeaders(); +} + +ElfObject::ElfObject( const wxString& srcfile, uint hdrsize ) + : filename( srcfile ) + , data( wxULongLong(hdrsize).GetLo(), L"ELF headers" ) + , header( *(ELF_HEADER*)data.GetPtr() ) + , proghead( NULL ) + , secthead( NULL ) +{ + isCdvd = false; + checkElfSize(data.GetSizeInBytes()); + readFile(); + initElfHeaders(); +} + +void ElfObject::initElfHeaders() +{ + Console.WriteLn( L"Initializing Elf: %d bytes", data.GetSizeInBytes()); + + if ( header.e_phnum > 0 ) + proghead = (ELF_PHR*)&data[header.e_phoff]; - // Destructor! - // C++ does all the cleanup automagically for us. - virtual ~ElfObject() throw() { } + if ( header.e_shnum > 0 ) + secthead = (ELF_SHR*)&data[header.e_shoff]; - ElfObject( const wxString& srcfile, uint hdrsize ) - : filename( srcfile ) - , data( hdrsize, L"ELF headers" ) - , header( *(ELF_HEADER*)data.GetPtr() ) - , proghead( NULL ) - , secthead( NULL ) - { - readFile(); + if ( ( header.e_shnum > 0 ) && ( header.e_shentsize != sizeof(ELF_SHR) ) ) + Console.Error( "(ELF) Size of section headers is not standard" ); - if( header.e_phnum > 0 ) - proghead = (ELF_PHR*)&data[header.e_phoff]; + if ( ( header.e_phnum > 0 ) && ( header.e_phentsize != sizeof(ELF_PHR) ) ) + Console.Error( "(ELF) Size of program headers is not standard" ); - if( header.e_shnum > 0 ) - secthead = (ELF_SHR*)&data[header.e_shoff]; + const char* elftype = NULL; + switch( header.e_type ) + { + default: + ELF_LOG( "type: unknown = %x", header.e_type ); + break; - if ( ( header.e_shnum > 0 ) && ( header.e_shentsize != sizeof(ELF_SHR) ) ) - Console.Error( "(ELF) Size of section headers is not standard" ); + case 0x0: elftype = "no file type"; break; + case 0x1: elftype = "relocatable"; break; + case 0x2: elftype = "executable"; break; + } + + if (elftype != NULL) ELF_LOG( "type: %s", elftype ); - if ( ( header.e_phnum > 0 ) && ( header.e_phentsize != sizeof(ELF_PHR) ) ) - Console.Error( "(ELF) Size of program headers is not standard" ); + const char* machine = NULL; + + switch(header.e_machine) + { + case 1: machine = "AT&T WE 32100"; break; + case 2: machine = "SPARC"; break; + case 3: machine = "Intel 80386"; break; + case 4: machine = "Motorola 68000"; break; + case 5: machine = "Motorola 88000"; break; + case 7: machine = "Intel 80860"; break; + case 8: machine = "mips_rs3000"; break; - const char* elftype = NULL; - switch( header.e_type ) - { - default: - ELF_LOG( "type: unknown = %x", header.e_type ); + default: + ELF_LOG( "machine: unknown = %x", header.e_machine ); break; + } - case 0x0: elftype = "no file type"; break; - case 0x1: elftype = "relocatable"; break; - case 0x2: elftype = "executable"; break; - } - if( elftype != NULL ) ELF_LOG( "type: %s", elftype ); + if (machine != NULL) ELF_LOG( "machine: %s", machine ); - const char* machine = NULL; - switch ( header.e_machine ) - { - case 1: machine = "AT&T WE 32100"; break; - case 2: machine = "SPARC"; break; - case 3: machine = "Intel 80386"; break; - case 4: machine = "Motorola 68000"; break; - case 5: machine = "Motorola 88000"; break; - case 7: machine = "Intel 80860"; break; - case 8: machine = "mips_rs3000"; break; + ELF_LOG("version: %d",header.e_version); + ELF_LOG("entry: %08x",header.e_entry); + ELF_LOG("flags: %08x",header.e_flags); + ELF_LOG("eh size: %08x",header.e_ehsize); + ELF_LOG("ph off: %08x",header.e_phoff); + ELF_LOG("ph entsiz: %08x",header.e_phentsize); + ELF_LOG("ph num: %08x",header.e_phnum); + ELF_LOG("sh off: %08x",header.e_shoff); + ELF_LOG("sh entsiz: %08x",header.e_shentsize); + ELF_LOG("sh num: %08x",header.e_shnum); + ELF_LOG("sh strndx: %08x",header.e_shstrndx); - default: - ELF_LOG( "machine: unknown = %x", header.e_machine ); - break; - } + ELF_LOG("\n"); +} + +bool ElfObject::hasProgramHeaders() { return (proghead != NULL); } +bool ElfObject::hasSectionHeaders() { return (secthead != NULL); } +bool ElfObject::hasHeaders() { return (hasProgramHeaders() && hasSectionHeaders()); } + +void ElfObject::readIso(IsoFile file) +{ + int rsize = file.read(data.GetPtr(), data.GetSizeInBytes()); + if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream( filename ); +} + +void ElfObject::readFile() +{ + int rsize = 0; + FILE *f; + + f = fopen( filename.ToUTF8(), "rb" ); + if (f == NULL) Exception::FileNotFound( filename ); + + fseek(f, 0, SEEK_SET); + rsize = fread(data.GetPtr(), 1, data.GetSizeInBytes(), f); + fclose( f ); - if( machine != NULL ) - ELF_LOG( "machine: %s", machine ); + if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream( filename ); +} - ELF_LOG("version: %d",header.e_version); - ELF_LOG("entry: %08x",header.e_entry); - ELF_LOG("flags: %08x",header.e_flags); - ELF_LOG("eh size: %08x",header.e_ehsize); - ELF_LOG("ph off: %08x",header.e_phoff); - ELF_LOG("ph entsiz: %08x",header.e_phentsize); - ELF_LOG("ph num: %08x",header.e_phnum); - ELF_LOG("sh off: %08x",header.e_shoff); - ELF_LOG("sh entsiz: %08x",header.e_shentsize); - ELF_LOG("sh num: %08x",header.e_shnum); - ELF_LOG("sh strndx: %08x",header.e_shstrndx); +void ElfObject::checkElfSize(s64 elfsize) +{ + if (elfsize > 0xfffffff) + throw Exception::BadStream( filename, wxLt("Illegal ELF file size, over 2GB!") ); - ELF_LOG("\n"); - } + if (elfsize == -1) + throw Exception::BadStream( filename, wxLt("Elf file does not exist! ") ); - void readFile() - { - int rsize = 0; - const wxCharBuffer work( filename.ToUTF8() ); - if ((strnicmp( work, "cdrom:", strlen("cdrom:" )) == 0) || - (strnicmp( work, "cdrom0:", strlen("cdromN:")) == 0) || - (strnicmp( work, "cdrom1:", strlen("cdromN:")) == 0)) - { - IsoFSCDVD isofs; - IsoFile file( isofs, fromUTF8(work) ); + if (elfsize == 0) + throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") ); +} + +u32 ElfObject::getCRC() const +{ + u32 CRC = 0; - //int size = file.getLength(); - rsize = file.read(data.GetPtr(), data.GetSizeInBytes()); - } - else - { - FILE *f; + const u32* srcdata = (u32*)data.GetPtr(); + for(u32 i=data.GetSizeInBytes()/4; i; --i, ++srcdata) + CRC ^= *srcdata; - f = fopen( work.data(), "rb" ); - if( f == NULL ) Exception::FileNotFound( filename ); + return CRC; +} - fseek( f, 0, SEEK_SET ); - rsize = fread( data.GetPtr(), 1, data.GetSizeInBytes(), f ); - fclose( f ); - } +void ElfObject::loadProgramHeaders() +{ + if (proghead == NULL) return; - if( rsize < data.GetSizeInBytes() ) throw Exception::EndOfStream( filename ); - } + for( int i = 0 ; i < header.e_phnum ; i++ ) + { + ELF_LOG( "Elf32 Program Header" ); + ELF_LOG( "type: " ); - u32 GetCRC() const - { - u32 CRC = 0; - - const u32* srcdata = (u32*)data.GetPtr(); - for(u32 i=data.GetSizeInBytes()/4; i; --i, ++srcdata) - CRC ^= *srcdata; - - return CRC; - } - - - void loadProgramHeaders() - { - if ( proghead == NULL ) - return; - - for( int i = 0 ; i < header.e_phnum ; i++ ) - { - ELF_LOG( "Elf32 Program Header" ); - ELF_LOG( "type: " ); - - switch ( proghead[ i ].p_type ) { - default: - ELF_LOG( "unknown %x", (int)proghead[ i ].p_type ); + switch(proghead[ i ].p_type) + { + default: + ELF_LOG( "unknown %x", (int)proghead[ i ].p_type ); break; - case 0x1: - { - ELF_LOG("load"); - const uint elfsize = data.GetLength(); + case 0x1: + { + ELF_LOG("load"); + const uint elfsize = data.GetLength(); - if (proghead[ i ].p_offset < elfsize) { - int size; + if (proghead[ i ].p_offset < elfsize) + { + int size; - if ((proghead[ i ].p_filesz + proghead[ i ].p_offset) > elfsize) - size = elfsize - proghead[ i ].p_offset; - else - size = proghead[ i ].p_filesz; + if ((proghead[ i ].p_filesz + proghead[ i ].p_offset) > elfsize) + size = elfsize - proghead[ i ].p_offset; + else + size = proghead[ i ].p_filesz; - if( proghead[ i ].p_vaddr != proghead[ i ].p_paddr ) - Console.Warning( "ElfProgram different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x", - proghead[ i ].p_paddr, proghead[ i ].p_vaddr); + if (proghead[ i ].p_vaddr != proghead[ i ].p_paddr) + Console.Warning( "ElfProgram different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x", + proghead[ i ].p_paddr, proghead[ i ].p_vaddr); - // used to be paddr - memcpy_fast( - &PS2MEM_BASE[proghead[ i ].p_vaddr & 0x1ffffff], - data.GetPtr(proghead[ i ].p_offset), size - ); + // used to be paddr + memcpy_fast( + &PS2MEM_BASE[proghead[ i ].p_vaddr & 0x1ffffff], + data.GetPtr(proghead[ i ].p_offset), size + ); - ELF_LOG("\t*LOADED*"); - } - } - break; - } + ELF_LOG("\t*LOADED*"); + } + } + break; + } - ELF_LOG("\n"); - ELF_LOG("offset: %08x",proghead[i].p_offset); - ELF_LOG("vaddr: %08x",proghead[i].p_vaddr); - ELF_LOG("paddr: %08x",proghead[i].p_paddr); - ELF_LOG("file size: %08x",proghead[i].p_filesz); - ELF_LOG("mem size: %08x",proghead[i].p_memsz); - ELF_LOG("flags: %08x",proghead[i].p_flags); - ELF_LOG("palign: %08x",proghead[i].p_align); - ELF_LOG("\n"); - } - } + ELF_LOG("\n"); + ELF_LOG("offset: %08x",proghead[i].p_offset); + ELF_LOG("vaddr: %08x",proghead[i].p_vaddr); + ELF_LOG("paddr: %08x",proghead[i].p_paddr); + ELF_LOG("file size: %08x",proghead[i].p_filesz); + ELF_LOG("mem size: %08x",proghead[i].p_memsz); + ELF_LOG("flags: %08x",proghead[i].p_flags); + ELF_LOG("palign: %08x",proghead[i].p_align); + ELF_LOG("\n"); + } +} - void loadSectionHeaders() - { - if( secthead == NULL || header.e_shoff > (u32)data.GetLength() ) - return; +void ElfObject::loadSectionHeaders() +{ + if (secthead == NULL || header.e_shoff > (u32)data.GetLength()) return; - const u8* sections_names = data.GetPtr( secthead[ (header.e_shstrndx == 0xffff ? 0 : header.e_shstrndx) ].sh_offset ); + const u8* sections_names = data.GetPtr( secthead[ (header.e_shstrndx == 0xffff ? 0 : header.e_shstrndx) ].sh_offset ); - int i_st = -1; - int i_dt = -1; + int i_st = -1, i_dt = -1; - for( int i = 0 ; i < header.e_shnum ; i++ ) - { - ELF_LOG( "ELF32 Section Header [%x] %s", i, §ions_names[ secthead[ i ].sh_name ] ); + for( int i = 0 ; i < header.e_shnum ; i++ ) + { + ELF_LOG( "ELF32 Section Header [%x] %s", i, §ions_names[ secthead[ i ].sh_name ] ); - // used by parseCommandLine - //if ( secthead[i].sh_flags & 0x2 ) - // args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff ); + // used by parseCommandLine + //if ( secthead[i].sh_flags & 0x2 ) + // args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff ); - ELF_LOG("\n"); + ELF_LOG("\n"); - const char* sectype = NULL; - switch ( secthead[ i ].sh_type ) - { - case 0x0: sectype = "null"; break; - case 0x1: sectype = "progbits"; break; - case 0x2: sectype = "symtab"; break; - case 0x3: sectype = "strtab"; break; - case 0x4: sectype = "rela"; break; - case 0x8: sectype = "no bits"; break; - case 0x9: sectype = "rel"; break; + const char* sectype = NULL; + switch(secthead[ i ].sh_type) + { + case 0x0: sectype = "null"; break; + case 0x1: sectype = "progbits"; break; + case 0x2: sectype = "symtab"; break; + case 0x3: sectype = "strtab"; break; + case 0x4: sectype = "rela"; break; + case 0x8: sectype = "no bits"; break; + case 0x9: sectype = "rel"; break; - default: - ELF_LOG("type: unknown %08x",secthead[i].sh_type); - break; - } + default: + ELF_LOG("type: unknown %08x",secthead[i].sh_type); + break; + } - ELF_LOG("type: %s", sectype); - ELF_LOG("flags: %08x", secthead[i].sh_flags); - ELF_LOG("addr: %08x", secthead[i].sh_addr); - ELF_LOG("offset: %08x", secthead[i].sh_offset); - ELF_LOG("size: %08x", secthead[i].sh_size); - ELF_LOG("link: %08x", secthead[i].sh_link); - ELF_LOG("info: %08x", secthead[i].sh_info); - ELF_LOG("addralign: %08x", secthead[i].sh_addralign); - ELF_LOG("entsize: %08x", secthead[i].sh_entsize); - // dump symbol table + ELF_LOG("type: %s", sectype); + ELF_LOG("flags: %08x", secthead[i].sh_flags); + ELF_LOG("addr: %08x", secthead[i].sh_addr); + ELF_LOG("offset: %08x", secthead[i].sh_offset); + ELF_LOG("size: %08x", secthead[i].sh_size); + ELF_LOG("link: %08x", secthead[i].sh_link); + ELF_LOG("info: %08x", secthead[i].sh_info); + ELF_LOG("addralign: %08x", secthead[i].sh_addralign); + ELF_LOG("entsize: %08x", secthead[i].sh_entsize); + // dump symbol table - if( secthead[ i ].sh_type == 0x02 ) - { - i_st = i; - i_dt = secthead[i].sh_link; - } - } + if (secthead[ i ].sh_type == 0x02) + { + i_st = i; + i_dt = secthead[i].sh_link; + } + } - if( ( i_st >= 0 ) && ( i_dt >= 0 ) ) - { - const char * SymNames; - Elf32_Sym * eS; + if ((i_st >= 0) && (i_dt >= 0)) + { + const char * SymNames; + Elf32_Sym * eS; - SymNames = (char*)data.GetPtr( secthead[ i_dt ].sh_offset ); - eS = (Elf32_Sym*)data.GetPtr( secthead[ i_st ].sh_offset ); - Console.WriteLn("found %d symbols", secthead[ i_st ].sh_size / sizeof( Elf32_Sym )); + SymNames = (char*)data.GetPtr(secthead[i_dt].sh_offset); + eS = (Elf32_Sym*)data.GetPtr(secthead[i_st].sh_offset); + Console.WriteLn("found %d symbols", secthead[i_st].sh_size / sizeof(Elf32_Sym)); - for( uint i = 1; i < ( secthead[ i_st ].sh_size / sizeof( Elf32_Sym ) ); i++ ) { - if ( ( eS[ i ].st_value != 0 ) && ( ELF32_ST_TYPE( eS[ i ].st_info ) == 2 ) ) { - R5900::disR5900AddSym( eS[i].st_value, &SymNames[ eS[ i ].st_name ] ); - } - } - } - } -}; + for(uint i = 1; i < (secthead[i_st].sh_size / sizeof(Elf32_Sym)); i++) { + if ((eS[i].st_value != 0) && (ELF32_ST_TYPE(eS[i].st_info) == 2)) + { + R5900::disR5900AddSym(eS[i].st_value, &SymNames[eS[i].st_name]); + } + } + } +} + +void ElfObject::loadHeaders() +{ + loadProgramHeaders(); + loadSectionHeaders(); +} void ElfApplyPatches() { wxString filename( wxsFormat( L"%8.8x", ElfCRC ) ); // if patches found the following status msg will be overwritten - Console.SetTitle( wxsFormat( _("Game running [CRC=%s]"), filename.c_str() ) ); + Console.SetTitle(L"Game running [CRC=" + filename +L"]"); - if( !EmuConfig.EnablePatches ) return; - - InitPatch(filename); + if (EmuConfig.EnablePatches) InitPatch(filename); } // Fetches the CRC of the game bound to the CDVD plugin. -u32 loadElfCRC( const char* filename ) +u32 loadElfCRC( const wxString filename ) { + // Note: calling loadElfFile here causes bad things to happen. u32 crcval = 0; - Console.WriteLn("loadElfCRC: %s", filename); - - IsoFSCDVD isofs; - const int filesize = IsoDirectory(isofs).GetFileSize( fromUTF8(filename) ); - - DevCon.WriteLn( "loadElfFile: %d bytes", filesize ); - crcval = ElfObject( fromUTF8(filename), filesize ).GetCRC(); - Console.WriteLn( "loadElfFile: %s; CRC = %8.8X", filename, crcval ); + IsoFSCDVD isofs; + IsoFile file(isofs, filename); + + crcval = ElfObject(filename, file).getCRC(); + + Console.WriteLn(wxsFormat(L"loadElfCRC(" + filename + L") = %8.8X", crcval)); return crcval; } @@ -525,54 +446,39 @@ u32 loadElfCRC( const char* filename ) // If the specified filename is empty then no action is taken (PS2 will continue booting // normally as if it has no CD. // -// Throws exception on error: +// Throws exceptions on errors. Not called if not skipping the bios. // void loadElfFile(const wxString& filename) { - if( filename.IsEmpty() ) return; + ElfObject *elfptr; + + if (filename.IsEmpty()) return; - s64 elfsize; Console.WriteLn( L"loadElfFile: " + filename ); - const wxCharBuffer fnptr( filename.ToUTF8() ); - bool useCdvdSource = false; - -#ifndef ENABLE_LOADING_PS1_GAMES - if( filename.StartsWith( L"cdrom:" ) ) + if (filename.StartsWith(L"cdrom:") && !ENABLE_LOADING_PS1_GAMES) throw Exception::RuntimeError( wxLt("This is not a Ps2 disc. (And we don't currently emulate PS1 games)") ); -#endif - if( !filename.StartsWith( L"cdrom:" ) && !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) ) + if (filename.StartsWith(L"cdrom:") || filename.StartsWith(L"cdrom0:") || filename.StartsWith(L"cdrom1:")) { - DevCon.WriteLn("Loading from a file (or non-cd image)"); - elfsize = Path::GetFileSize( filename ); + // It's a game disc. + DevCon.WriteLn(L"Loading from a CD rom or CD image."); + + IsoFSCDVD isofs; + IsoFile file(isofs, filename); + + elfptr = new ElfObject(filename, file); } else { - DevCon.WriteLn("Loading from a CD rom or CD image"); - useCdvdSource = true; - - Console.WriteLn(L"loadElfCRC: " + filename); - IsoFSCDVD isofs; - elfsize = IsoDirectory( isofs ).GetFileSize( fromUTF8(fnptr) ); + // It's an elf file. + DevCon.WriteLn("Loading from a file (or non-cd image)"); + elfptr = new ElfObject(filename, Path::GetFileSize(filename)); } - if( elfsize > 0xfffffff ) - throw Exception::BadStream( filename, wxLt("Illegal ELF file size, over 2GB!") ); - - if( elfsize == -1 ) - throw Exception::BadStream( filename, wxLt("Elf file does not exist! ") ); - - if( elfsize == 0 ) - throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") ); - - Console.WriteLn( L"loadElfFile: %d bytes", wxULongLong(elfsize).GetLo() ); - - ElfObject elfobj( filename, wxULongLong(elfsize).GetLo() ); - - if( elfobj.proghead == NULL ) + if (!elfptr->hasProgramHeaders()) { - throw Exception::BadStream( filename, useCdvdSource ? + throw Exception::BadStream( filename, elfptr->isCdvd ? wxLt("Invalid ELF file header. The CD-Rom may be damaged, or the ISO image corrupted.") : wxLt("Invalid ELF file.") ); @@ -581,10 +487,9 @@ void loadElfFile(const wxString& filename) //2002-09-19 (Florin) //args_ptr = 0xFFFFFFFF; //big value, searching for minimum [used by parseCommandLine] - elfobj.loadProgramHeaders(); - elfobj.loadSectionHeaders(); + elfptr->loadHeaders(); - cpuRegs.pc = elfobj.header.e_entry; //set pc to proper place + cpuRegs.pc = elfptr->header.e_entry; //set pc to proper place ELF_LOG( "PC set to: %8.8lx", cpuRegs.pc ); cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; @@ -595,11 +500,11 @@ void loadElfFile(const wxString& filename) { if( memcmp( "rom0:OSDSYS", (char*)PSM( i ), 11 ) == 0 ) { - strcpy( (char*)PSM( i ), fnptr ); - DevCon.WriteLn( "loadElfFile: addr %x \"%s\" -> \"%s\"", i, "rom0:OSDSYS", fnptr.data() ); + strcpy( (char*)PSM( i ), filename.ToUTF8() ); + DevCon.WriteLn( wxsFormat(L"loadElfFile: addr %x \"rom0:OSDSYS\" -> \"" + filename + L"\"", i)); } } - ElfCRC = elfobj.GetCRC(); + ElfCRC = elfptr->getCRC(); Console.WriteLn( L"loadElfFile: %s; CRC = %8.8X", filename.c_str(), ElfCRC ); ElfApplyPatches(); GetMTGS().SendGameCRC( ElfCRC ); @@ -613,6 +518,8 @@ void loadElfFile(const wxString& filename) // 2 - PS2 CD int GetPS2ElfName( wxString& name ) { + int retype = 0; + try { IsoFSCDVD isofs; IsoFile file( isofs, L"SYSTEM.CNF;1"); @@ -620,7 +527,6 @@ int GetPS2ElfName( wxString& name ) int size = file.getLength(); if( size == 0 ) return 0; - int retype = 0; while( !file.eof() ) { @@ -696,6 +602,6 @@ int GetPS2ElfName( wxString& name ) } fclose(fp); #endif - - return 2; + + return retype; } diff --git a/pcsx2/Elfheader.h b/pcsx2/Elfheader.h index fa6340e85c..598391533b 100644 --- a/pcsx2/Elfheader.h +++ b/pcsx2/Elfheader.h @@ -16,13 +16,151 @@ #ifndef __ELF_H__ #define __ELF_H__ +#include "CDVD/IsoFS/IsoFSCDVD.h" +#include "CDVD/IsoFS/IsoFS.h" + +#if 0 //2002-09-20 (Florin) extern char args[256]; //to be filled by GUI extern unsigned int args_ptr; +#endif + +struct ELF_HEADER { + u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) + u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE + u16 e_machine; //Processor: 8=MIPS R3000 + u32 e_version; //Version: 1=current + u32 e_entry; //Entry point address + u32 e_phoff; //Start of program headers (offset from file start) + u32 e_shoff; //Start of section headers (offset from file start) + u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips + u16 e_ehsize; //ELF header size (0x34 = 52 bytes) + u16 e_phentsize; //Program headers entry size + u16 e_phnum; //Number of program headers + u16 e_shentsize; //Section headers entry size + u16 e_shnum; //Number of section headers + u16 e_shstrndx; //Section header stringtable index +}; + +struct ELF_PHR { + u32 p_type; //see notes1 + u32 p_offset; //Offset from file start to program segment. + u32 p_vaddr; //Virtual address of the segment + u32 p_paddr; //Physical address of the segment + u32 p_filesz; //Number of bytes in the file image of the segment + u32 p_memsz; //Number of bytes in the memory image of the segment + u32 p_flags; //Flags for segment + u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment +}; + +/* +notes1 +------ +0=Inactive +1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 +2=Dynamic linking +3=Interpreter. The array element must specify a path name +4=Note. The array element must specify the location and size of aux. info +5=reserved +6=The array element must specify location and size of the program header table. +*/ + +struct ELF_SHR { + u32 sh_name; //No. to the index of the Section header stringtable index + u32 sh_type; //See notes2 + u32 sh_flags; //see notes3 + u32 sh_addr; //Section start address + u32 sh_offset; //Offset from start of file to section + u32 sh_size; //Size of section + u32 sh_link; //Section header table index link + u32 sh_info; //Info + u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. + u32 sh_entsize; //Fixed size entries. +}; + +/* +notes 2 +------- +Type: +0=Inactive +1=PROGBITS +2=SYMTAB symbol table +3=STRTAB string table +4=RELA relocation entries +5=HASH hash table +6=DYNAMIC dynamic linking information +7=NOTE +8=NOBITS +9=REL relocation entries +10=SHLIB +0x70000000=LOPROC processor specifc +0x7fffffff=HIPROC +0x80000000=LOUSER lower bound +0xffffffff=HIUSER upper bound + +notes 3 +------- +Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) +1=Write section contains data the is be writeable during execution. +2=Alloc section occupies memory during execution +4=Exec section contains executable instructions +0xf0000000=Mask bits processor-specific +*/ + +struct Elf32_Sym { + u32 st_name; + u32 st_value; + u32 st_size; + u8 st_info; + u8 st_other; + u16 st_shndx; +}; + +#define ELF32_ST_TYPE(i) ((i)&0xf) + +struct Elf32_Rel { + u32 r_offset; + u32 r_info; +}; + +class ElfObject +{ + private: + SafeArray data; + ELF_PHR* proghead; + ELF_SHR* secthead; + wxString filename; + + void initElfHeaders(); + void readIso(IsoFile file); + void readFile(); + void checkElfSize(s64 elfsize); + + public: + bool isCdvd; + ELF_HEADER& header; + + // Destructor! + // C++ does all the cleanup automagically for us. + virtual ~ElfObject() throw() { } + + ElfObject(const wxString& srcfile, IsoFile isofile); + ElfObject( const wxString& srcfile, uint hdrsize ); + + void loadProgramHeaders(); + void loadSectionHeaders(); + void loadHeaders(); + + bool hasProgramHeaders(); + bool hasSectionHeaders(); + bool hasHeaders(); + + u32 getCRC() const; +}; //------------------- extern void loadElfFile(const wxString& filename); -extern u32 loadElfCRC(const char *filename); +extern u32 loadElfCRC(const wxString filename); extern void ElfApplyPatches(); extern int GetPS2ElfName( wxString& dest ); diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index e11d108879..524b37ffc1 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -420,7 +420,6 @@ void inifile_command( const wxString& cmd ) // Then sends the command to be parsed. void inifile_process(wxTextFile &f1 ) { - Console.WriteLn("inifile_process"); for (uint i = 0; i < f1.GetLineCount(); i++) { inifile_trim(f1[i]); diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 25b79eb130..2ed285b417 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -292,7 +292,8 @@ void SysCoreThread::CpuInitializeMess() throw Exception::RuntimeError( wxLt("Fast Boot failed: CDVD image is not a PS1 or PS2 game.") ); case 1: - throw Exception::RuntimeError( wxLt("Fast Boot failed: PCSX2 does not support emulation of PS1 games.") ); + if (!ENABLE_LOADING_PS1_GAMES) + throw Exception::RuntimeError( wxLt("Fast Boot failed: PCSX2 does not support emulation of PS1 games.") ); case 2: // PS2 game. Valid! @@ -310,7 +311,7 @@ void SysCoreThread::CpuInitializeMess() // injects the cpuRegs.pc with the address of the execution start point. // // This hack is necessary for non-CD ELF files, and is optional for game CDs as a - // fast bott up option. (though not recommended for games because of rare ill side + // fast boot up option. (though not recommended for games because of rare ill side // effects). SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR ); diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index 08d00efec2..4ca436cacc 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -336,8 +336,15 @@ void VXITOP() { VU0.code = cpuRegs.code; _vuXITOP(&VU0); } // fixme: Shouldn't anything calling this function be calling vu0WaitMicro instead? // Meaning that this function stalls, but doesn't increment the cpuRegs.cycle like // you would think it should. + +// Well, we can always test that out... +//#define USE_WAIT_MICRO + void vu0Finish() { +#ifdef USE_WAIT_MICRO + _vu0WaitMicro(); +#else if( (VU0.VI[REG_VPU_STAT].UL & 0x1) ) { int i = 0; @@ -352,4 +359,5 @@ void vu0Finish() //Console.Warning("vu0Finish > stall aborted by force."); } } +#endif }