diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 2a0f44b7ca..43ee3319ac 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -28,6 +28,8 @@ #include "Elfheader.h" #include "ps2/BiosTools.h" +wxString DiscID; + static cdvdStruct cdvd; static __forceinline void SetResultSize(u8 size) @@ -306,7 +308,7 @@ s32 cdvdWriteConfig(const u8* config) static MutexLockRecursive Mutex_NewDiskCB; // Sets ElfCRC to the CRC of the game bound to the CDVD plugin. -static __forceinline ElfObject *loadElfCRC( const wxString filename ) +static __forceinline ElfObject *loadElf( const wxString filename ) { // Note: calling loadElfFile here causes bad things to happen. IsoFSCDVD isofs; @@ -314,35 +316,51 @@ static __forceinline ElfObject *loadElfCRC( const wxString filename ) ElfObject *elfptr; elfptr = new ElfObject(filename, file); - elfptr->getCRC(); - - Console.WriteLn(wxsFormat(L"loadElfCRC(" + filename + L") = %8.8X", ElfCRC)); return elfptr; } -static __forceinline void _reloadElfInfo(wxString str) +static __forceinline void _reloadElfInfo(wxString elfpath) { ScopedPtr elfptr; // Now's a good time to reload the ELF info... ScopedLock locker( Mutex_NewDiskCB ); - - elfptr = loadElfCRC(str); - elfptr->applyPatches(); + + wxString fname = elfpath.AfterLast('\\'); + if (!fname) + fname = elfpath.AfterLast('/'); + if (!fname) + fname = elfpath.AfterLast(':'); + if (fname.Matches(L"????_???.??*")) + DiscID = fname(0,4) + L"-" + fname(5,3) + fname(9,2); + + Console.WriteLn("Disc ID = %s", DiscID.ToUTF8()); + + elfptr = loadElf(elfpath); + + ElfCRC = elfptr->getCRC(); + Console.WriteLn("ELF (%s) CRC = %8.8X", elfpath.ToUTF8(), ElfCRC); + + ElfEntry = elfptr->header.e_entry; + Console.WriteLn("Entry point = 0x%08x", ElfEntry); + elfptr.Delete(); } -static __forceinline void reloadElfInfo(u32 discType, wxString str) +void cdvdReloadElfInfo() { + wxString elfpath; + u32 discType = GetPS2ElfName(elfpath); + if (ElfCRC == 0) { switch (discType) { case 2: // Is a PS2 disc. - _reloadElfInfo(str); + _reloadElfInfo(elfpath); break; case 1: // Is a PS1 disc. - if (ENABLE_LOADING_PS1_GAMES) _reloadElfInfo(str); + if (ENABLE_LOADING_PS1_GAMES) _reloadElfInfo(elfpath); break; default: // Isn't a disc we recognise. break; @@ -363,23 +381,17 @@ void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) u32 key_0_3; u8 key_4, key_14; - wxString fname, exeName; - - // Get the main elf name. - u32 discType = GetPS2ElfName(fname); - - exeName = fname(8, 11); - DevCon.Warning(L"exeName = " + exeName); + cdvdReloadElfInfo(); // convert the number characters to a real 32 bit number - numbers = StrToS32(exeName(5,3) + exeName(9,2)); + numbers = StrToS32(DiscID(5,5)); // combine the lower 7 bits of each char // to make the 4 letters fit into a single u32 - letters = (s32)((exeName[3]&0x7F)<< 0) | - (s32)((exeName[2]&0x7F)<< 7) | - (s32)((exeName[1]&0x7F)<<14) | - (s32)((exeName[0]&0x7F)<<21); + letters = (s32)((DiscID[3]&0x7F)<< 0) | + (s32)((DiscID[2]&0x7F)<< 7) | + (s32)((DiscID[1]&0x7F)<<14) | + (s32)((DiscID[0]&0x7F)<<21); // calculate magic numbers key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80 @@ -424,8 +436,6 @@ 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] ); - - reloadElfInfo(discType, fname); } s32 cdvdGetToc(void* toc) @@ -551,8 +561,7 @@ static void cdvdDetectDisk() { wxString str; cdvd.Type = DoCDVDdetectDiskType(); - - reloadElfInfo(GetPS2ElfName(str), str); + cdvdReloadElfInfo(); } void cdvdNewDiskCB() diff --git a/pcsx2/CDVD/CDVD.h b/pcsx2/CDVD/CDVD.h index b7c692831c..85940e9879 100644 --- a/pcsx2/CDVD/CDVD.h +++ b/pcsx2/CDVD/CDVD.h @@ -142,3 +142,7 @@ extern void cdvdReadInterrupt(); extern void cdvdNewDiskCB(); extern u8 cdvdRead(u8 key); extern void cdvdWrite(u8 key, u8 rt); + +void cdvdReloadElfInfo(); + +extern wxString DiscID; diff --git a/pcsx2/Elfheader.cpp b/pcsx2/Elfheader.cpp index 4192a9926c..3ef24c72f1 100644 --- a/pcsx2/Elfheader.cpp +++ b/pcsx2/Elfheader.cpp @@ -20,9 +20,9 @@ #include "Elfheader.h" using namespace std; -extern void InitPatch(const wxString& crc); u32 ElfCRC; +u32 ElfEntry; // uncomment this to enable pcsx2hostfs loading when using "load elf" //#define USE_HOSTFS @@ -274,7 +274,7 @@ void ElfObject::checkElfSize(s64 elfsize) throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") ); } -void ElfObject::getCRC() +u32 ElfObject::getCRC() { u32 CRC = 0; @@ -282,7 +282,7 @@ void ElfObject::getCRC() for(u32 i=data.GetSizeInBytes()/4; i; --i, ++srcdata) CRC ^= *srcdata; - ElfCRC = CRC; + return CRC; } void ElfObject::loadProgramHeaders() @@ -418,17 +418,6 @@ void ElfObject::loadHeaders() loadSectionHeaders(); } -void ElfObject::applyPatches() -{ - wxString filename( wxsFormat( L"%8.8x", ElfCRC ) ); - - // if patches found the following status msg will be overwritten - Console.SetTitle(L"Game running [CRC=" + filename +L"]"); - - if (EmuConfig.EnablePatches) InitPatch(filename); - GetMTGS().SendGameCRC(ElfCRC); -} - // Loads the elf binary data from the specified file into PS2 memory, and injects the ELF's // starting execution point into cpuRegs.pc. If the filename is a cdrom URI in the form // of "cdrom0:" or "cdrom1:" then the CDVD is used as the source; otherwise the ELF is loaded @@ -448,7 +437,6 @@ void loadElfFile(const wxString& filename) #endif { ScopedPtr elfptr; - bool iscdvd; #ifdef USE_HOSTFS wxString filename = _filename; @@ -459,53 +447,36 @@ void loadElfFile(const wxString& filename) Console.WriteLn( L"loadElfFile: " + filename ); - 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)") ); - - iscdvd = (filename.StartsWith(L"cdrom:") || filename.StartsWith(L"cdrom0:") || filename.StartsWith(L"cdrom1:")); - if (iscdvd) - { - // 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 - { - // It's an elf file. - DevCon.WriteLn("Loading from a file (or non-cd image)."); #ifdef USE_HOSTFS - parameters = filename; - filename = wxT("pcsx2hostfs_ldr.elf"); + parameters = filename; + filename = wxT("pcsx2hostfs_ldr.elf"); #endif - elfptr = new ElfObject(filename, Path::GetFileSize(filename)); + elfptr = new ElfObject(filename, Path::GetFileSize(filename)); #ifdef USE_HOSTFS - filename = wxT("host:pcsx2hostfs_ldr.elf"); + filename = wxT("host:pcsx2hostfs_ldr.elf"); #endif - } if (!elfptr->hasProgramHeaders()) { - 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.") - ); + throw Exception::BadStream(filename, wxLt("Invalid ELF file.")); } + elfptr->loadHeaders(); + + ElfCRC = elfptr->getCRC(); + Console.WriteLn( L"loadElfFile: %s; CRC = %8.8X", filename.c_str(), ElfCRC ); + ElfEntry = elfptr->header.e_entry; + elfptr.Delete(); + //2002-09-19 (Florin) //args_ptr = 0xFFFFFFFF; //big value, searching for minimum [used by parseCommandLine] - elfptr->loadHeaders(); - - cpuRegs.pc = elfptr->header.e_entry; //set pc to proper place + cpuRegs.pc = ElfEntry; //set pc to proper place ELF_LOG( "PC set to: %8.8lx", cpuRegs.pc ); - cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok //cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); // see #ifdef'd out parseCommendLine for details. + #ifdef USE_HOSTFS //HACK!!!!!!!!!!!!! @@ -524,30 +495,6 @@ void loadElfFile(const wxString& filename) #endif - for( uint i = 0; i < 0x100000; i++ ) - { - if( memcmp( "rom0:OSDSYS", (char*)PSM( i ), 11 ) == 0 ) - { - // All right, this is not likely to be right. It's fine if it is a cd, but - // We really do not want to pass the elf file with full path and drive letter - // into pcsx2 memory, like this. - strcpy((char*)PSM(i), filename.ToUTF8()); - - // We could test and only do it if (iscdvd) is true, or we could do something - // like this if it isn't a cdvd: - // strcpy((char*)PSM(i), wxsFormat(L"rom0:"+Path::GetFilename(filename)).ToUTF8()); - - // Though the question is what device name to pass if we do that... - // Not sure, so I'm leaving it the known incorrect way for now. --arcum42 - - DevCon.WriteLn( wxsFormat(L"loadElfFile: addr %x \"rom0:OSDSYS\" -> \"" + filename + L"\"", i)); - } - } - elfptr->getCRC(); - Console.WriteLn( L"loadElfFile: %s; CRC = %8.8X", filename.c_str(), ElfCRC ); - elfptr->applyPatches(); - elfptr.Delete(); - return; } @@ -608,6 +555,10 @@ int GetPS2ElfName( wxString& name ) return 0; } } + catch (Exception::BadStream&) + { + return 0; // ISO error + } catch( Exception::FileNotFound& ) { return 0; // no SYSTEM.CNF, not a PS1/PS2 disc. diff --git a/pcsx2/Elfheader.h b/pcsx2/Elfheader.h index 930c127c38..3f3a636ace 100644 --- a/pcsx2/Elfheader.h +++ b/pcsx2/Elfheader.h @@ -155,8 +155,7 @@ class ElfObject bool hasSectionHeaders(); bool hasHeaders(); - void getCRC(); - void applyPatches(); + u32 getCRC(); }; //------------------- @@ -165,5 +164,6 @@ extern int GetPS2ElfName( wxString& dest ); extern u32 ElfCRC; +extern u32 ElfEntry; #endif diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index bf2538e557..b5a6160c35 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -20,6 +20,8 @@ #include "R5900OpcodeTables.h" #include "System/SysThreads.h" +#include "ElfHeader.h" + #include using namespace R5900; // for OPCODE and OpcodeImpl @@ -383,39 +385,22 @@ static void intExecute() // done in a more optimized fashion. try { - while( true ) - execI(); - } catch( Exception::ExitCpuExecute& ) { } -} - -static void intExecuteBiosStub() -{ - g_EEFreezeRegs = false; - - // We need to be wary of events that could occur during vsyncs, which means - // making sure to exit this function for ExitCpuExecute. The calling function - // will update UI status, and then re-enter if the bios stub execution criteria - // wasn't met yet. - - try { - while( (cpuRegs.pc != 0x00200008) && (cpuRegs.pc != 0x00100008) ) { - execI(); + if (g_SkipBiosHack) { + do + execI(); + while (cpuRegs.pc != EELOAD_START); + eeloadReplaceOSDSYS(); + } + if (ElfEntry != -1) { + do + execI(); + while (cpuRegs.pc != ElfEntry); + eeGameStarting(); + } else { + while (true) + execI(); } } catch( Exception::ExitCpuExecute& ) { } - - // ... some maual bios injection hack from a century ago, me thinks. Leaving the - // code intact for posterity. --air - - // { - // FILE* f = fopen("eebios.bin", "wb"); - // fwrite(PSM(0x80000000), 0x100000, 1, f); - // fclose(f); - // exit(0); - - // f = fopen("iopbios.bin", "wb"); - // fwrite(PS2MEM_PSX, 0x80000, 1, f); - // fclose(f); - // } } static void intCheckExecutionState() @@ -445,7 +430,6 @@ R5900cpu intCpu = intReset, intStep, intExecute, - intExecuteBiosStub, intCheckExecutionState, intClear, diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index 524b37ffc1..40be1dbfe9 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -465,19 +465,25 @@ void _ApplyPatch(IniPatch *p) switch (p->type) { case BYTE_T: - memWrite8(p->addr, (u8)p->data); + if (memRead8(p->addr) != (u8)p->data) + memWrite8(p->addr, (u8)p->data); break; case SHORT_T: - memWrite16(p->addr, (u16)p->data); + if (memRead16(p->addr) != (u16)p->data) + memWrite16(p->addr, (u16)p->data); break; case WORD_T: - memWrite32(p->addr, (u32)p->data); + if (memRead32(p->addr) != (u32)p->data) + memWrite32(p->addr, (u32)p->data); break; case DOUBLE_T: - memWrite64(p->addr, &p->data); + u64 mem; + memRead64(p->addr, &mem); + if (mem != p->data) + memWrite64(p->addr, &p->data); break; case EXTENDED_T: @@ -493,13 +499,16 @@ void _ApplyPatch(IniPatch *p) switch (p->type) { case BYTE_T: - iopMemWrite8(p->addr, (u8)p->data); + if (iopMemRead8(p->addr) != (u8)p->data) + iopMemWrite8(p->addr, (u8)p->data); break; case SHORT_T: - iopMemWrite16(p->addr, (u16)p->data); + if (iopMemRead16(p->addr) != (u16)p->data) + iopMemWrite16(p->addr, (u16)p->data); break; case WORD_T: - iopMemWrite32(p->addr, (u32)p->data); + if (iopMemRead32(p->addr) != (u32)p->data) + iopMemWrite32(p->addr, (u32)p->data); break; default: break; @@ -525,7 +534,6 @@ void InitPatch(const wxString& crc) { inifile_read(crc); Console.WriteLn("patchnumber: %d", patchnumber); - ApplyPatch(0); } void ResetPatch( void ) diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index 01556ba0dc..5f535731f7 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -60,6 +60,7 @@ void inifile_read( const wxString& name ); void inifile_command( const wxString& cmd ); void inifile_trim( wxString& buffer ); +void InitPatch(const wxString& crc); int AddPatch(int Mode, int Place, int Address, int Size, u64 data); void ApplyPatch( int place = 1); void ResetPatch( void ); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index fa89de024e..81f0619587 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -27,6 +27,10 @@ #include "Hardware.h" +#include "ElfHeader.h" +#include "CDVD/CDVD.h" +#include "Patch.h" + using namespace R5900; // for R5900 disasm tools s32 EEsCycle; // used to sync the IOP to the EE @@ -37,7 +41,8 @@ __aligned16 fpuRegisters fpuRegs; __aligned16 tlbs tlb[48]; R5900cpu *Cpu = NULL; -bool g_ExecBiosHack = false; // set if the BIOS has already been executed +bool g_SkipBiosHack; // set at boot if the skip bios hack is on, reset before the game has started +bool g_GameStarted; // set when we reach the game's entry point or earlier if the entry point cannot be determined static const uint eeWaitCycles = 3072; @@ -75,6 +80,13 @@ void cpuReset() vif1Reset(); rcntInit(); psxReset(); + + g_GameStarted = false; + g_SkipBiosHack = EmuConfig.SkipBiosSplash; + + ElfCRC = 0; + DiscID = L""; + ElfEntry = -1; } __releaseinline void cpuException(u32 code, u32 bd) @@ -555,4 +567,70 @@ __forceinline void CPU_INT( u32 n, s32 ecycle) } cpuSetNextBranchDelta( cpuRegs.eCycle[n] ); -} \ No newline at end of file +} + +void __fastcall eeGameStarting() +{ + if (!g_GameStarted && ElfCRC) { + wxString filename( wxsFormat( L"%8.8x", ElfCRC ) ); + + // if patches found the following status msg will be overwritten + Console.SetTitle(L"Game running [CRC=" + filename +L"]"); + + if (EmuConfig.EnablePatches) InitPatch(filename); + GetMTGS().SendGameCRC(ElfCRC); + + g_GameStarted = true; + } + + ApplyPatch(0); +} + +void __fastcall eeloadReplaceOSDSYS() +{ + g_SkipBiosHack = false; + + const wxString &elf_override = GetCoreThread().GetElfOverride(); + + if (!elf_override.IsEmpty()) { + loadElfFile(elf_override); + return; + } + + cdvdReloadElfInfo(); + + // didn't recognise an ELF + if (ElfEntry == -1) { + eeGameStarting(); + return; + } + + static u32 osdsys = 0, osdsys_p = 0; + // Memory this high is safe before the game's running presumably + // Other options are kernel memory (first megabyte) or the scratchpad + // PS2LOGO is loaded at 16MB, let's use 17MB + const u32 safemem = 0x1100000; + + // The strings are all 64-bit aligned. Why? I don't know, but they are + for (u32 i = EELOAD_START; i < EELOAD_START + EELOAD_SIZE; i += 8) { + if (!strcmp((char*)PSM(i), "rom0:OSDSYS")) { + osdsys = i; + break; + } + } + pxAssert(osdsys); + + for (u32 i = osdsys - 4; i >= EELOAD_START; i -= 4) { + if (memRead32(i) == osdsys) { + osdsys_p = i; + break; + } + } + pxAssert(osdsys_p); + + wxString elfname; + if (GetPS2ElfName(elfname) == 2) { + strcpy((char*)PSM(safemem), elfname.ToUTF8()); + memWrite32(osdsys_p, safemem); + } +} diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 58a1984a16..21e768058a 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -25,7 +25,8 @@ // right now, so we're sticking them here for now until a better solution comes along. extern bool g_EEFreezeRegs; -extern bool g_ExecBiosHack; +extern bool g_SkipBiosHack; +extern bool g_GameStarted; namespace Exception { @@ -255,6 +256,15 @@ void intSetBranch(); // parts of the Recs (namely COP0's branch codes and stuff). void __fastcall intDoBranch(u32 target); +// modules loaded at hardcoded addresses by the kernel +const u32 EEKERNEL_START = 0; +const u32 EENULL_START = 0x81FC0; +const u32 EELOAD_START = 0x82000; +const u32 EELOAD_SIZE = 0x20000; // overestimate for searching + +void __fastcall eeGameStarting(); +void __fastcall eeloadReplaceOSDSYS(); + //////////////////////////////////////////////////////////////////// // R5900 Public Interface / API // @@ -319,20 +329,6 @@ struct R5900cpu // void (*Execute)(); - // This function performs a "hackish" execution of the BIOS stub, which initializes - // EE memory and hardware. It forcefully breaks execution when the stub is finished, - // prior to the PS2 logos being displayed. This allows us to "shortcut" right into - // a game without having to wait through the logos or endure game/bios localization - // checks. - // - // Use of this function must be followed by the proper injection of the elf header's - // code execution entry point into cpuRegs.pc. Failure to modify cpuRegs.pc will - // result in the bios continuing its normal unimpeded splash screen execution. - // - // Exception Throws: [TODO] (possible execution-related throws to be added) - // - void (*ExecuteBiosStub)(); - // Checks for execution suspension or cancellation. In pthreads terms this provides // a "cancellation point." Execution state checks are typically performed at Vsyncs // by the generic VM event handlers in R5900.cpp/Counters.cpp (applies to both recs diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 2126ffcb6c..e56d85d55a 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -273,57 +273,6 @@ void SysCoreThread::CpuInitializeMess() ScopedBool_ClearOnError sbcoe( m_hasValidState ); - wxString elf_file( m_elf_override ); - if( elf_file.IsEmpty() && EmuConfig.SkipBiosSplash && (CDVDsys_GetSourceType() != CDVDsrc_NoDisc)) - { - // Fetch the ELF filename and CD type from the CDVD provider. - wxString ename; - int result = GetPS2ElfName( ename ); - switch( result ) - { - case 0: - throw Exception::RuntimeError( wxLt("Fast Boot failed: CDVD image is not a PS1 or PS2 game.") ); - - case 1: - 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! - elf_file = ename; - break; - - jNO_DEFAULT - } - } - - if( !elf_file.IsEmpty() ) - { - // Skip Bios Hack *or* Manual ELF override: - // Runs the PS2 BIOS stub, and then manually loads the ELF executable data, and - // 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 boot up option. (though not recommended for games because of rare ill side - // effects). - - SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR ); - - Console.WriteLn( Color_StrongGreen, "(PCSX2 Core) Executing Bios Stub..." ); - - do { - // Even the BiosStub invokes vsyncs, so we need to be weary of state - // changes and premature loop exits, and re-enter the stub executer until - // the critera is met. - - StateCheckInThread(); - Cpu->ExecuteBiosStub(); - } while( cpuRegs.pc != 0x00200008 && cpuRegs.pc != 0x00100008 ); - - Console.WriteLn( Color_StrongGreen, "(PCSX2 Core) Execute Bios Stub Complete"); - loadElfFile( elf_file ); - } - sbcoe.Success(); } diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index 6d8ded2b0f..31ee1b0f3b 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -28,6 +28,9 @@ #include "System/SysThreads.h" #include "GS.h" +#include "CDVD/CDVD.h" +#include "ElfHeader.h" + #if !PCSX2_SEH # include #endif @@ -763,19 +766,6 @@ static void recExecute() #endif } -static void recExecuteBiosStub() -{ - g_ExecBiosHack = true; - recExecute(); - g_ExecBiosHack = false; - - // Reset the EErecs here, because the bios generates "slow" blocks that have - // g_ExecBiosHack checks in them. This deletes them so that the recs replace them - // with new faster versions: - recResetEE(); -} - - //////////////////////////////////////////////////// void R5900::Dynarec::OpcodeImpl::recSYSCALL( void ) { @@ -886,36 +876,6 @@ static void recExitExecution() #endif } -// check for end of bios -void CheckForBIOSEnd() -{ - xMOV( eax, &cpuRegs.pc ); - - if( IsDevBuild ) - { - // Using CALL retains stacktrace info, useful for debugging. - - xCMP( eax, 0x00200008 ); - xForwardJE8 CallExitRec; - - xCMP( eax, 0x00100008 ); - xForwardJNE8 SkipExitRec; - - CallExitRec.SetTarget(); - xCALL( recExitExecution ); - - SkipExitRec.SetTarget(); - } - else - { - xCMP( eax, 0x00200008 ); - xJE(recExitExecution); - - xCMP( eax, 0x00100008 ); - xJE(recExitExecution); - } -} - static int *s_pCode; void SetBranchReg( u32 reg ) @@ -1127,8 +1087,6 @@ static void iBranchTest(u32 newpc) { _DynGen_StackFrameCheck(); - if( g_ExecBiosHack ) CheckForBIOSEnd(); - // Check the Event scheduler if our "cycle target" has been reached. // Equiv code to: // cpuRegs.cycle += blockcycles; @@ -1394,6 +1352,16 @@ static void __fastcall recRecompile( const u32 startpc ) pxAssume(s_pCurBlockEx); + if (g_SkipBiosHack && HWADDR(startpc) == EELOAD_START) { + xCALL(eeloadReplaceOSDSYS); + xCMP(ptr32[&cpuRegs.pc], startpc); + xJNE(DispatcherReg); + } + + // this is the only way patches get applied, doesn't depend on a hack + if (HWADDR(startpc) == ElfEntry) + xCALL(eeGameStarting); + branch = 0; // reset recomp state variables @@ -1857,8 +1825,7 @@ R5900cpu recCpu = recResetEE, recStep, recExecute, - recExecuteBiosStub, - + recCheckExecutionState, recClear, };