mirror of https://github.com/PCSX2/pcsx2.git
More robust eeload hooking to monitor and interfere with bios and game loading.
Maybe some other cruft can go now this should be reliable.
This commit is contained in:
parent
242ac26299
commit
c782b6222c
|
@ -512,8 +512,8 @@ static void intExecute()
|
||||||
bool instruction_was_cancelled;
|
bool instruction_was_cancelled;
|
||||||
enum ExecuteState {
|
enum ExecuteState {
|
||||||
RESET,
|
RESET,
|
||||||
REPLACE_OSDSYS_DONE,
|
GAME_LOADING,
|
||||||
GAME_STARTING_DONE
|
GAME_RUNNING
|
||||||
};
|
};
|
||||||
ExecuteState state = RESET;
|
ExecuteState state = RESET;
|
||||||
do {
|
do {
|
||||||
|
@ -523,24 +523,32 @@ static void intExecute()
|
||||||
// resume it after a cancelled instruction.
|
// resume it after a cancelled instruction.
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case RESET:
|
case RESET:
|
||||||
if (g_SkipBiosHack) {
|
do
|
||||||
do
|
execI();
|
||||||
execI();
|
while (cpuRegs.pc != (eeloadMain ? eeloadMain : EELOAD_START));
|
||||||
while (cpuRegs.pc != EELOAD_START);
|
if (cpuRegs.pc == EELOAD_START)
|
||||||
eeloadReplaceOSDSYS();
|
{
|
||||||
}
|
// The EELOAD _start function is the same across all BIOS versions afaik
|
||||||
state = REPLACE_OSDSYS_DONE;
|
u32 mainjump = memRead32(EELOAD_START + 0x9c);
|
||||||
|
if (mainjump >> 26 == 3) // JAL
|
||||||
|
eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU);
|
||||||
|
} else if (cpuRegs.pc == eeloadMain)
|
||||||
|
eeloadHook();
|
||||||
|
if (g_GameLoading)
|
||||||
|
state = GAME_LOADING;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
case REPLACE_OSDSYS_DONE:
|
case GAME_LOADING:
|
||||||
if (ElfEntry != 0xFFFFFFFF) {
|
if (ElfEntry != 0xFFFFFFFF) {
|
||||||
do
|
do
|
||||||
execI();
|
execI();
|
||||||
while (cpuRegs.pc != ElfEntry);
|
while (cpuRegs.pc != ElfEntry);
|
||||||
eeGameStarting();
|
eeGameStarting();
|
||||||
}
|
}
|
||||||
state = GAME_STARTING_DONE;
|
state = GAME_RUNNING;
|
||||||
|
|
||||||
case GAME_STARTING_DONE:
|
case GAME_RUNNING:
|
||||||
while (true)
|
while (true)
|
||||||
execI();
|
execI();
|
||||||
}
|
}
|
||||||
|
|
105
pcsx2/R5900.cpp
105
pcsx2/R5900.cpp
|
@ -49,11 +49,14 @@ R5900cpu *Cpu = NULL;
|
||||||
|
|
||||||
bool g_SkipBiosHack; // set at boot if the skip bios hack is on, reset before the game has started
|
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
|
bool g_GameStarted; // set when we reach the game's entry point or earlier if the entry point cannot be determined
|
||||||
|
bool g_GameLoading; // EELOAD has been called to load the game
|
||||||
|
|
||||||
static const uint eeWaitCycles = 3072;
|
static const uint eeWaitCycles = 3072;
|
||||||
|
|
||||||
bool eeEventTestIsActive = false;
|
bool eeEventTestIsActive = false;
|
||||||
|
|
||||||
|
u32 eeloadMain = 0;
|
||||||
|
|
||||||
extern SysMainMemory& GetVmMemory();
|
extern SysMainMemory& GetVmMemory();
|
||||||
|
|
||||||
void cpuReset()
|
void cpuReset()
|
||||||
|
@ -87,6 +90,7 @@ void cpuReset()
|
||||||
Deci2Reset();
|
Deci2Reset();
|
||||||
|
|
||||||
g_GameStarted = false;
|
g_GameStarted = false;
|
||||||
|
g_GameLoading = false;
|
||||||
g_SkipBiosHack = EmuConfig.UseBOOT2Injection;
|
g_SkipBiosHack = EmuConfig.UseBOOT2Injection;
|
||||||
|
|
||||||
ElfCRC = 0;
|
ElfCRC = 0;
|
||||||
|
@ -103,6 +107,8 @@ void cpuReset()
|
||||||
// run into this while testing minor binary hacked changes to ISO images, which
|
// run into this while testing minor binary hacked changes to ISO images, which
|
||||||
// is why I found out about this) --air
|
// is why I found out about this) --air
|
||||||
LastELF = L"";
|
LastELF = L"";
|
||||||
|
|
||||||
|
eeloadMain = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpuShutdown()
|
void cpuShutdown()
|
||||||
|
@ -517,6 +523,7 @@ void __fastcall eeGameStarting()
|
||||||
{
|
{
|
||||||
//Console.WriteLn( Color_Green, "(R5900) ELF Entry point! [addr=0x%08X]", ElfEntry );
|
//Console.WriteLn( Color_Green, "(R5900) ELF Entry point! [addr=0x%08X]", ElfEntry );
|
||||||
g_GameStarted = true;
|
g_GameStarted = true;
|
||||||
|
g_GameLoading = false;
|
||||||
GetCoreThread().GameStartingInThread();
|
GetCoreThread().GameStartingInThread();
|
||||||
|
|
||||||
// GameStartingInThread may issue a reset of the cpu and/or recompilers. Check for and
|
// GameStartingInThread may issue a reset of the cpu and/or recompilers. Check for and
|
||||||
|
@ -530,10 +537,8 @@ void __fastcall eeGameStarting()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from recompilers; __fastcall define is mandatory.
|
// Called from recompilers; __fastcall define is mandatory.
|
||||||
void __fastcall eeloadReplaceOSDSYS()
|
void __fastcall eeloadHook()
|
||||||
{
|
{
|
||||||
g_SkipBiosHack = false;
|
|
||||||
|
|
||||||
const wxString &elf_override = GetCoreThread().GetElfOverride();
|
const wxString &elf_override = GetCoreThread().GetElfOverride();
|
||||||
|
|
||||||
if (!elf_override.IsEmpty())
|
if (!elf_override.IsEmpty())
|
||||||
|
@ -541,55 +546,63 @@ void __fastcall eeloadReplaceOSDSYS()
|
||||||
else
|
else
|
||||||
cdvdReloadElfInfo();
|
cdvdReloadElfInfo();
|
||||||
|
|
||||||
// didn't recognize an ELF
|
wxString discelf;
|
||||||
if (ElfEntry == 0xFFFFFFFF) {
|
int disctype = GetPS2ElfName(discelf);
|
||||||
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);
|
|
||||||
|
|
||||||
std::string elfname;
|
std::string elfname;
|
||||||
|
if (cpuRegs.GPR.n.a0.SD[0] >= 2) // argc >= 2
|
||||||
|
elfname = (char*)PSM(memRead32(cpuRegs.GPR.n.a1.UD[0] + 4)); // argv[1]
|
||||||
|
|
||||||
if (!elf_override.IsEmpty())
|
if (g_SkipBiosHack && elfname.empty())
|
||||||
{
|
{
|
||||||
elfname += "host:";
|
std::string elftoload;
|
||||||
elfname += elf_override.ToUTF8();
|
if (!elf_override.IsEmpty())
|
||||||
}
|
{
|
||||||
else
|
elftoload = "host:";
|
||||||
{
|
elftoload += elf_override.ToUTF8();
|
||||||
wxString boot2;
|
}
|
||||||
if (GetPS2ElfName(boot2) == 2)
|
else
|
||||||
elfname = boot2.ToUTF8();
|
{
|
||||||
|
if (disctype == 2)
|
||||||
|
elftoload = discelf.ToUTF8();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!elftoload.empty())
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// FIXME: you'd think that changing argc and argv would work but no, need to work out why not
|
||||||
|
// This method would support adding command line arguments to homebrew (and is generally less hacky)
|
||||||
|
// It works if you hook on rom0:PS2LOGO loading, but not on the first call with no arguments
|
||||||
|
cpuRegs.GPR.n.a0.SD[0] = 2; // argc = 2
|
||||||
|
// argv[0] = "EELOAD"
|
||||||
|
strcpy((char*)PSM(cpuRegs.GPR.n.a1.UD[0] + 0x40), "EELOAD");
|
||||||
|
memWrite32(cpuRegs.GPR.n.a1.UD[0] + 0, cpuRegs.GPR.n.a1.UD[0] + 0x40);
|
||||||
|
// argv[1] = elftoload
|
||||||
|
strcpy((char*)PSM(cpuRegs.GPR.n.a1.UD[0] + 0x47), elftoload.c_str());
|
||||||
|
memWrite32(cpuRegs.GPR.n.a1.UD[0] + 4, cpuRegs.GPR.n.a1.UD[0] + 0x47);
|
||||||
|
memWrite32(cpuRegs.GPR.n.a1.UD[0] + 8, 0);
|
||||||
|
g_GameLoading = true;
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
// The strings are all 64-bit aligned. Why? I don't know, but they are
|
||||||
|
for (u32 osdsys_str = EELOAD_START; osdsys_str < EELOAD_START + EELOAD_SIZE; osdsys_str += 8) {
|
||||||
|
if (!strcmp((char*)PSM(osdsys_str), "rom0:OSDSYS")) {
|
||||||
|
for (u32 osdsys_ptr = osdsys_str - 4; osdsys_ptr >= EELOAD_START; osdsys_ptr -= 4) {
|
||||||
|
if (memRead32(osdsys_ptr) == osdsys_str) {
|
||||||
|
strcpy((char*)PSM(cpuRegs.GPR.n.a1.UD[0] + 0x40), elftoload.c_str());
|
||||||
|
memWrite32(osdsys_ptr, cpuRegs.GPR.n.a1.UD[0] + 0x40);
|
||||||
|
g_GameLoading = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elfname.empty())
|
if (!g_GameStarted && disctype == 2 && elfname == discelf)
|
||||||
{
|
g_GameLoading = true;
|
||||||
strcpy((char*)PSM(safemem), elfname.c_str());
|
|
||||||
memWrite32(osdsys_p, safemem);
|
|
||||||
}
|
|
||||||
// else... uh...?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isBranchOrJump(u32 addr)
|
inline bool isBranchOrJump(u32 addr)
|
||||||
|
|
|
@ -26,6 +26,7 @@ class BaseR5900Exception;
|
||||||
|
|
||||||
extern bool g_SkipBiosHack;
|
extern bool g_SkipBiosHack;
|
||||||
extern bool g_GameStarted;
|
extern bool g_GameStarted;
|
||||||
|
extern bool g_GameLoading;
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
|
@ -272,9 +273,10 @@ const u32 EEKERNEL_START = 0;
|
||||||
const u32 EENULL_START = 0x81FC0;
|
const u32 EENULL_START = 0x81FC0;
|
||||||
const u32 EELOAD_START = 0x82000;
|
const u32 EELOAD_START = 0x82000;
|
||||||
const u32 EELOAD_SIZE = 0x20000; // overestimate for searching
|
const u32 EELOAD_SIZE = 0x20000; // overestimate for searching
|
||||||
|
extern u32 eeloadMain;
|
||||||
|
|
||||||
extern void __fastcall eeGameStarting();
|
extern void __fastcall eeGameStarting();
|
||||||
extern void __fastcall eeloadReplaceOSDSYS();
|
extern void __fastcall eeloadHook();
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// R5900cpu
|
// R5900cpu
|
||||||
|
|
|
@ -1607,14 +1607,18 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
|
|
||||||
pxAssert(s_pCurBlockEx);
|
pxAssert(s_pCurBlockEx);
|
||||||
|
|
||||||
if (g_SkipBiosHack && HWADDR(startpc) == EELOAD_START) {
|
if (HWADDR(startpc) == EELOAD_START) {
|
||||||
xFastCall(eeloadReplaceOSDSYS);
|
// The EELOAD _start function is the same across all BIOS versions afaik
|
||||||
xCMP(ptr32[&cpuRegs.pc], startpc);
|
u32 mainjump = memRead32(EELOAD_START + 0x9c);
|
||||||
xJNE(DispatcherReg);
|
if (mainjump >> 26 == 3) // JAL
|
||||||
|
eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eeloadMain && HWADDR(startpc) == HWADDR(eeloadMain))
|
||||||
|
xFastCall(eeloadHook);
|
||||||
|
|
||||||
// this is the only way patches get applied, doesn't depend on a hack
|
// this is the only way patches get applied, doesn't depend on a hack
|
||||||
if (HWADDR(startpc) == ElfEntry) {
|
if (g_GameLoading && HWADDR(startpc) == ElfEntry) {
|
||||||
Console.WriteLn(L"Elf entry point @ 0x%08x about to get recompiled. Load patches first.", startpc);
|
Console.WriteLn(L"Elf entry point @ 0x%08x about to get recompiled. Load patches first.", startpc);
|
||||||
xFastCall(eeGameStarting);
|
xFastCall(eeGameStarting);
|
||||||
// Apply patch as soon as possible. Normally it is done in
|
// Apply patch as soon as possible. Normally it is done in
|
||||||
|
|
Loading…
Reference in New Issue