mirror of https://github.com/PCSX2/pcsx2.git
PCSX2: Add ability to pass launch arguments to games with CLI option '--gameargs="-arg1 -arg2 -etc (#2576)
For more information please check the PR (#2576) since it's a bit detailed.
This commit is contained in:
parent
d1dc12f6b0
commit
a3c6ad636b
|
@ -522,15 +522,35 @@ static void intExecute()
|
||||||
case RESET:
|
case RESET:
|
||||||
do
|
do
|
||||||
execI();
|
execI();
|
||||||
while (cpuRegs.pc != (eeloadMain ? eeloadMain : EELOAD_START));
|
while (cpuRegs.pc != (g_eeloadMain ? g_eeloadMain : EELOAD_START));
|
||||||
if (cpuRegs.pc == EELOAD_START)
|
if (cpuRegs.pc == EELOAD_START)
|
||||||
{
|
{
|
||||||
// The EELOAD _start function is the same across all BIOS versions afaik
|
// The EELOAD _start function is the same across all BIOS versions afaik
|
||||||
u32 mainjump = memRead32(EELOAD_START + 0x9c);
|
u32 mainjump = memRead32(EELOAD_START + 0x9c);
|
||||||
if (mainjump >> 26 == 3) // JAL
|
if (mainjump >> 26 == 3) // JAL
|
||||||
eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU);
|
g_eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU);
|
||||||
} else if (cpuRegs.pc == eeloadMain)
|
}
|
||||||
|
else if (cpuRegs.pc == g_eeloadMain)
|
||||||
|
{
|
||||||
eeloadHook();
|
eeloadHook();
|
||||||
|
if (g_SkipBiosHack)
|
||||||
|
{
|
||||||
|
// See comments on this code in iR5900-32.cpp's recRecompile()
|
||||||
|
u32 typeAexecjump = memRead32(EELOAD_START + 0x470);
|
||||||
|
u32 typeBexecjump = memRead32(EELOAD_START + 0x5B0);
|
||||||
|
u32 typeCexecjump = memRead32(EELOAD_START + 0x618);
|
||||||
|
u32 typeDexecjump = memRead32(EELOAD_START + 0x600);
|
||||||
|
if ((typeBexecjump >> 26 == 3) || (typeCexecjump >> 26 == 3) || (typeDexecjump >> 26 == 3)) // JAL to 0x822B8
|
||||||
|
g_eeloadExec = EELOAD_START + 0x2B8;
|
||||||
|
else if (typeAexecjump >> 26 == 3) // JAL to 0x82170
|
||||||
|
g_eeloadExec = EELOAD_START + 0x170;
|
||||||
|
else
|
||||||
|
Console.WriteLn("intExecute: Could not enable launch arguments for fast boot mode; unidentified BIOS version! Please report this to the PCSX2 developers.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cpuRegs.pc == g_eeloadExec)
|
||||||
|
eeloadHook2();
|
||||||
|
|
||||||
if (g_GameLoading)
|
if (g_GameLoading)
|
||||||
state = GAME_LOADING;
|
state = GAME_LOADING;
|
||||||
else
|
else
|
||||||
|
|
204
pcsx2/R5900.cpp
204
pcsx2/R5900.cpp
|
@ -56,7 +56,16 @@ static const uint eeWaitCycles = 3072;
|
||||||
|
|
||||||
bool eeEventTestIsActive = false;
|
bool eeEventTestIsActive = false;
|
||||||
|
|
||||||
u32 eeloadMain = 0;
|
u32 g_eeloadMain = 0, g_eeloadExec = 0, g_osdsys_str = 0;
|
||||||
|
|
||||||
|
/* I don't know how much space for args there is in the memory block used for args in full boot mode,
|
||||||
|
but in fast boot mode, the block we use can fit at least 16 argv pointers (varies with BIOS version).
|
||||||
|
The second EELOAD call during full boot has three built-in arguments ("EELOAD rom0:PS2LOGO <ELF>"),
|
||||||
|
meaning that only the first 13 game arguments supplied by the user can be added on and passed through.
|
||||||
|
In fast boot mode, 15 arguments can fit because the only call to EELOAD is "<ELF> <<args>>". */
|
||||||
|
const int kMaxArgs = 16;
|
||||||
|
uptr g_argPtrs[kMaxArgs];
|
||||||
|
#define DEBUG_LAUNCHARG 0 // show lots of helpful console messages as the launch arguments are passed to the game
|
||||||
|
|
||||||
extern SysMainMemory& GetVmMemory();
|
extern SysMainMemory& GetVmMemory();
|
||||||
|
|
||||||
|
@ -110,7 +119,7 @@ void cpuReset()
|
||||||
// is why I found out about this) --air
|
// is why I found out about this) --air
|
||||||
LastELF = L"";
|
LastELF = L"";
|
||||||
|
|
||||||
eeloadMain = 0;
|
g_eeloadMain = 0, g_eeloadExec = 0, g_osdsys_str = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpuShutdown()
|
void cpuShutdown()
|
||||||
|
@ -540,6 +549,49 @@ void __fastcall eeGameStarting()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count arguments, save their starting locations, and replace the space separators with null terminators so they're separate strings
|
||||||
|
int ParseArgumentString(u32 arg_block)
|
||||||
|
{
|
||||||
|
if (!arg_block)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int argc = 1; // one arg is guaranteed at least
|
||||||
|
g_argPtrs[0] = arg_block; // first arg is right here
|
||||||
|
bool wasSpace = false; // status of last char. scanned
|
||||||
|
int args_len = strlen((char *)PSM(arg_block));
|
||||||
|
for (int i = 0; i < args_len; i++)
|
||||||
|
{
|
||||||
|
char curchar = *(char *)PSM(arg_block + i);
|
||||||
|
if (curchar == '\0')
|
||||||
|
break; // should never reach this
|
||||||
|
|
||||||
|
bool isSpace = (curchar == ' ');
|
||||||
|
if (isSpace)
|
||||||
|
memset(PSM(arg_block + i), 0, 1);
|
||||||
|
else if (wasSpace) // then we're at a new arg
|
||||||
|
{
|
||||||
|
if (argc < kMaxArgs)
|
||||||
|
{
|
||||||
|
g_argPtrs[argc] = arg_block + i;
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLn("ParseArgumentString: Discarded additional arguments beyond the maximum of %d.", kMaxArgs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wasSpace = isSpace;
|
||||||
|
}
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
// Check our args block
|
||||||
|
Console.WriteLn("ParseArgumentString: Saving these strings:");
|
||||||
|
for (int a = 0; a < argc; a++)
|
||||||
|
Console.WriteLn("%p -> '%s'.", g_argPtrs[a], (char *)PSM(g_argPtrs[a]));
|
||||||
|
#endif
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
// Called from recompilers; __fastcall define is mandatory.
|
// Called from recompilers; __fastcall define is mandatory.
|
||||||
void __fastcall eeloadHook()
|
void __fastcall eeloadHook()
|
||||||
{
|
{
|
||||||
|
@ -554,9 +606,71 @@ void __fastcall eeloadHook()
|
||||||
int disctype = GetPS2ElfName(discelf);
|
int disctype = GetPS2ElfName(discelf);
|
||||||
|
|
||||||
std::string elfname;
|
std::string elfname;
|
||||||
if (cpuRegs.GPR.n.a0.SD[0] >= 2) // argc >= 2
|
int argc = cpuRegs.GPR.n.a0.SD[0];
|
||||||
elfname = (char*)PSM(memRead32(cpuRegs.GPR.n.a1.UD[0] + 4)); // argv[1]
|
if (argc) // calls to EELOAD *after* the first one during the startup process will come here
|
||||||
|
{
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
Console.WriteLn("eeloadHook: EELOAD was called with %d arguments according to $a0 and %d according to vargs block:",
|
||||||
|
argc, memRead32(cpuRegs.GPR.n.a1.UD[0] - 4));
|
||||||
|
for (int a = 0; a < argc; a++)
|
||||||
|
Console.WriteLn("argv[%d]: %p -> %p -> '%s'", a, cpuRegs.GPR.n.a1.UL[0] + (a * 4),
|
||||||
|
memRead32(cpuRegs.GPR.n.a1.UD[0] + (a * 4)), (char *)PSM(memRead32(cpuRegs.GPR.n.a1.UD[0] + (a * 4))));
|
||||||
|
#endif
|
||||||
|
if (argc > 1)
|
||||||
|
elfname = (char*)PSM(memRead32(cpuRegs.GPR.n.a1.UD[0] + 4)); // argv[1] in OSDSYS's invocation "EELOAD <game ELF>"
|
||||||
|
|
||||||
|
// This code fires if the user chooses "full boot". First the Sony Computer Entertainment screen appears. This is the result
|
||||||
|
// of an EELOAD call that does not want to accept launch arguments (but we patch it to do so in eeloadHook2() in fast boot
|
||||||
|
// mode). Then EELOAD is called with the argument "rom0:PS2LOGO". At this point, we do not need any additional tricks
|
||||||
|
// because EELOAD is now ready to accept launch arguments. So in full-boot mode, we simply wait for PS2LOGO to be called,
|
||||||
|
// then we add the desired launch arguments. PS2LOGO passes those on to the game itself as it calls EELOAD a third time.
|
||||||
|
if (!g_Conf->CurrentGameArgs.empty() && !strcmp(elfname.c_str(), "rom0:PS2LOGO"))
|
||||||
|
{
|
||||||
|
const char *argString = g_Conf->CurrentGameArgs.c_str();
|
||||||
|
Console.WriteLn("eeloadHook: Supplying launch argument(s) '%s' to module '%s'...", argString, elfname.c_str());
|
||||||
|
|
||||||
|
// Join all arguments by space characters so they can be processed as one string by ParseArgumentString(), then add the
|
||||||
|
// user's launch arguments onto the end
|
||||||
|
u32 arg_ptr = 0;
|
||||||
|
int arg_len = 0;
|
||||||
|
for (int a = 0; a < argc; a++)
|
||||||
|
{
|
||||||
|
arg_ptr = memRead32(cpuRegs.GPR.n.a1.UD[0] + (a * 4));
|
||||||
|
arg_len = strlen((char *)PSM(arg_ptr));
|
||||||
|
memset(PSM(arg_ptr + arg_len), 0x20, 1);
|
||||||
|
}
|
||||||
|
strcpy((char *)PSM(arg_ptr + arg_len + 1), g_Conf->CurrentGameArgs.c_str());
|
||||||
|
u32 first_arg_ptr = memRead32(cpuRegs.GPR.n.a1.UD[0]);
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
Console.WriteLn("eeloadHook: arg block is '%s'.", (char *)PSM(first_arg_ptr));
|
||||||
|
#endif
|
||||||
|
argc = ParseArgumentString(first_arg_ptr);
|
||||||
|
|
||||||
|
// Write pointer to next slot in $a1
|
||||||
|
for (int a = 0; a < argc; a++)
|
||||||
|
memWrite32(cpuRegs.GPR.n.a1.UD[0] + (a * 4), g_argPtrs[a]);
|
||||||
|
cpuRegs.GPR.n.a0.SD[0] = argc;
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
// Check our work
|
||||||
|
Console.WriteLn("eeloadHook: New arguments are:");
|
||||||
|
for (int a = 0; a < argc; a++)
|
||||||
|
Console.WriteLn("argv[%d]: %p -> '%s'", a, memRead32(cpuRegs.GPR.n.a1.UD[0] + (a * 4)),
|
||||||
|
(char *)PSM(memRead32(cpuRegs.GPR.n.a1.UD[0] + (a * 4))));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// else it's presumed that the invocation is "EELOAD <game ELF> <<launch args>>", coming from PS2LOGO, and we needn't do
|
||||||
|
// anything more
|
||||||
|
}
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
// This code fires in full/fast boot mode when EELOAD is called the first/only time. When EELOAD is not given any arguments,
|
||||||
|
// it calls rom0:OSDSYS by default, which displays the Sony Computer Entertainment screen. OSDSYS then calls "EELOAD
|
||||||
|
// rom0:PS2LOGO" and we end up above.
|
||||||
|
else
|
||||||
|
Console.WriteLn("eeloadHook: EELOAD was called with no arguments.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If "fast boot" was chosen, then on EELOAD's first call we won't yet know what the game's ELF is. Find the name and write it
|
||||||
|
// into EELOAD's memory.
|
||||||
if (g_SkipBiosHack && elfname.empty())
|
if (g_SkipBiosHack && elfname.empty())
|
||||||
{
|
{
|
||||||
std::string elftoload;
|
std::string elftoload;
|
||||||
|
@ -571,37 +685,21 @@ void __fastcall eeloadHook()
|
||||||
elftoload = discelf.ToUTF8();
|
elftoload = discelf.ToUTF8();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When fast-booting, we insert the game's ELF name into EELOAD so that the game is called instead of the default call of
|
||||||
|
// "rom0:OSDSYS"; any launch arguments supplied by the user will be inserted into EELOAD later by eeloadHook2()
|
||||||
if (!elftoload.empty())
|
if (!elftoload.empty())
|
||||||
{
|
{
|
||||||
#if 0
|
// Find and save location of default/fallback call "rom0:OSDSYS"; to be used later by eeloadHook2()
|
||||||
// FIXME: you'd think that changing argc and argv would work but no, need to work out why not
|
for (g_osdsys_str = EELOAD_START; g_osdsys_str < EELOAD_START + EELOAD_SIZE; g_osdsys_str += 8) // strings are 64-bit aligned
|
||||||
// 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
|
if (!strcmp((char*)PSM(g_osdsys_str), "rom0:OSDSYS"))
|
||||||
cpuRegs.GPR.n.a0.SD[0] = 2; // argc = 2
|
{
|
||||||
// argv[0] = "EELOAD"
|
// Overwrite OSDSYS with game's ELF name
|
||||||
strcpy((char*)PSM(cpuRegs.GPR.n.a1.UD[0] + 0x40), "EELOAD");
|
strcpy((char*)PSM(g_osdsys_str), elftoload.c_str());
|
||||||
memWrite32(cpuRegs.GPR.n.a1.UD[0] + 0, cpuRegs.GPR.n.a1.UD[0] + 0x40);
|
g_GameLoading = true;
|
||||||
// argv[1] = elftoload
|
return;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,6 +707,50 @@ void __fastcall eeloadHook()
|
||||||
g_GameLoading = true;
|
g_GameLoading = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called from recompilers; __fastcall define is mandatory.
|
||||||
|
// Only called if g_SkipBiosHack is true
|
||||||
|
void __fastcall eeloadHook2()
|
||||||
|
{
|
||||||
|
if (g_Conf->CurrentGameArgs.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!g_osdsys_str)
|
||||||
|
{
|
||||||
|
Console.WriteLn("eeloadHook2: Called before \"rom0:OSDSYS\" was found by eeloadHook()!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *argString = g_Conf->CurrentGameArgs.c_str();
|
||||||
|
Console.WriteLn("eeloadHook2: Supplying launch argument(s) '%s' to ELF '%s'.", argString, (char *)PSM(g_osdsys_str));
|
||||||
|
|
||||||
|
// Add args string after game's ELF name that was written over "rom0:OSDSYS" by eeloadHook(). In between the ELF name and args
|
||||||
|
// string we insert a space character so that ParseArgumentString() has one continuous string to process.
|
||||||
|
int game_len = strlen((char *)PSM(g_osdsys_str));
|
||||||
|
memset(PSM(g_osdsys_str + game_len), 0x20, 1);
|
||||||
|
strcpy((char *)PSM(g_osdsys_str + game_len + 1), g_Conf->CurrentGameArgs.c_str());
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
Console.WriteLn("eeloadHook2: arg block is '%s'.", (char *)PSM(g_osdsys_str));
|
||||||
|
#endif
|
||||||
|
int argc = ParseArgumentString(g_osdsys_str);
|
||||||
|
|
||||||
|
// Back up 4 bytes from start of args block for every arg + 4 bytes for start of argv pointer block, write pointers
|
||||||
|
uptr block_start = g_osdsys_str - (argc * 4);
|
||||||
|
for (int a = 0; a < argc; a++)
|
||||||
|
{
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
Console.WriteLn("eeloadHook2: Writing address %p to location %p.", g_argPtrs[a], block_start + (a * 4));
|
||||||
|
#endif
|
||||||
|
memWrite32(block_start + (a * 4), g_argPtrs[a]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save argc and argv as incoming arguments for EELOAD function which calls ExecPS2()
|
||||||
|
#if DEBUG_LAUNCHARG
|
||||||
|
Console.WriteLn("eeloadHook2: Saving %d and %p in $a0 and $a1.", argc, block_start);
|
||||||
|
#endif
|
||||||
|
cpuRegs.GPR.n.a0.SD[0] = argc;
|
||||||
|
cpuRegs.GPR.n.a1.UD[0] = block_start;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isBranchOrJump(u32 addr)
|
inline bool isBranchOrJump(u32 addr)
|
||||||
{
|
{
|
||||||
u32 op = memRead32(addr);
|
u32 op = memRead32(addr);
|
||||||
|
|
|
@ -273,10 +273,11 @@ 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 u32 g_eeloadMain, g_eeloadExec;
|
||||||
|
|
||||||
extern void __fastcall eeGameStarting();
|
extern void __fastcall eeGameStarting();
|
||||||
extern void __fastcall eeloadHook();
|
extern void __fastcall eeloadHook();
|
||||||
|
extern void __fastcall eeloadHook2();
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// R5900cpu
|
// R5900cpu
|
||||||
|
|
|
@ -288,6 +288,8 @@ public:
|
||||||
|
|
||||||
wxString ElfFile;
|
wxString ElfFile;
|
||||||
|
|
||||||
|
wxString GameLaunchArgs;
|
||||||
|
|
||||||
// Specifies the CDVD source type to use when AutoRunning
|
// Specifies the CDVD source type to use when AutoRunning
|
||||||
CDVD_SourceType CdvdSource;
|
CDVD_SourceType CdvdSource;
|
||||||
|
|
||||||
|
|
|
@ -315,6 +315,7 @@ public:
|
||||||
wxString CurrentELF;
|
wxString CurrentELF;
|
||||||
wxString CurrentIRX;
|
wxString CurrentIRX;
|
||||||
CDVD_SourceType CdvdSource;
|
CDVD_SourceType CdvdSource;
|
||||||
|
wxString CurrentGameArgs;
|
||||||
|
|
||||||
// Memorycard options - first 2 are default slots, last 6 are multitap 1 and 2
|
// Memorycard options - first 2 are default slots, last 6 are multitap 1 and 2
|
||||||
// slots (3 each)
|
// slots (3 each)
|
||||||
|
|
|
@ -243,6 +243,7 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
|
||||||
parser.AddSwitch( wxEmptyString,L"nohacks", _("disables all speedhacks") );
|
parser.AddSwitch( wxEmptyString,L"nohacks", _("disables all speedhacks") );
|
||||||
parser.AddOption( wxEmptyString,L"gamefixes", _("use the specified comma or pipe-delimited list of gamefixes.") + fixlist, wxCMD_LINE_VAL_STRING );
|
parser.AddOption( wxEmptyString,L"gamefixes", _("use the specified comma or pipe-delimited list of gamefixes.") + fixlist, wxCMD_LINE_VAL_STRING );
|
||||||
parser.AddSwitch( wxEmptyString,L"fullboot", _("disables fast booting") );
|
parser.AddSwitch( wxEmptyString,L"fullboot", _("disables fast booting") );
|
||||||
|
parser.AddOption( wxEmptyString,L"gameargs", _("passes the specified space-delimited string of launch arguments to the game"), wxCMD_LINE_VAL_STRING);
|
||||||
|
|
||||||
parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING );
|
parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING );
|
||||||
parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use"), wxCMD_LINE_VAL_STRING );
|
parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use"), wxCMD_LINE_VAL_STRING );
|
||||||
|
@ -365,6 +366,10 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString game_args;
|
||||||
|
if (parser.Found(L"gameargs", &game_args) && !game_args.IsEmpty())
|
||||||
|
Startup.GameLaunchArgs = game_args;
|
||||||
|
|
||||||
if( parser.Found(L"usecd") )
|
if( parser.Found(L"usecd") )
|
||||||
{
|
{
|
||||||
Startup.CdvdSource = CDVD_SourceType::Plugin;
|
Startup.CdvdSource = CDVD_SourceType::Plugin;
|
||||||
|
@ -507,6 +512,7 @@ bool Pcsx2App::OnInit()
|
||||||
if (Startup.CdvdSource == CDVD_SourceType::Iso)
|
if (Startup.CdvdSource == CDVD_SourceType::Iso)
|
||||||
SysUpdateIsoSrcFile( Startup.IsoFile );
|
SysUpdateIsoSrcFile( Startup.IsoFile );
|
||||||
sApp.SysExecute( Startup.CdvdSource );
|
sApp.SysExecute( Startup.CdvdSource );
|
||||||
|
g_Conf->CurrentGameArgs = Startup.GameLaunchArgs;
|
||||||
}
|
}
|
||||||
else if ( Startup.SysAutoRunElf )
|
else if ( Startup.SysAutoRunElf )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1652,15 +1652,33 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
|
|
||||||
pxAssert(s_pCurBlockEx);
|
pxAssert(s_pCurBlockEx);
|
||||||
|
|
||||||
if (HWADDR(startpc) == EELOAD_START) {
|
if (HWADDR(startpc) == EELOAD_START)
|
||||||
// The EELOAD _start function is the same across all BIOS versions afaik
|
{
|
||||||
|
// The EELOAD _start function is the same across all BIOS versions
|
||||||
u32 mainjump = memRead32(EELOAD_START + 0x9c);
|
u32 mainjump = memRead32(EELOAD_START + 0x9c);
|
||||||
if (mainjump >> 26 == 3) // JAL
|
if (mainjump >> 26 == 3) // JAL
|
||||||
eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU);
|
g_eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eeloadMain && HWADDR(startpc) == HWADDR(eeloadMain)) {
|
if (g_eeloadMain && HWADDR(startpc) == HWADDR(g_eeloadMain))
|
||||||
|
{
|
||||||
xFastCall((void*)eeloadHook);
|
xFastCall((void*)eeloadHook);
|
||||||
|
if (g_SkipBiosHack)
|
||||||
|
{
|
||||||
|
// There are four known versions of EELOAD, identifiable by the location of the 'jal' to the EELOAD function which
|
||||||
|
// calls ExecPS2(). The function itself is at the same address in all BIOSs after v1.00-v1.10.
|
||||||
|
u32 typeAexecjump = memRead32(EELOAD_START + 0x470); // v1.00, v1.01?, v1.10?
|
||||||
|
u32 typeBexecjump = memRead32(EELOAD_START + 0x5B0); // v1.20, v1.50, v1.60 (3000x models)
|
||||||
|
u32 typeCexecjump = memRead32(EELOAD_START + 0x618); // v1.60 (3900x models)
|
||||||
|
u32 typeDexecjump = memRead32(EELOAD_START + 0x600); // v1.70, v1.90, v2.00, v2.20, v2.30
|
||||||
|
if ((typeBexecjump >> 26 == 3) || (typeCexecjump >> 26 == 3) || (typeDexecjump >> 26 == 3)) // JAL to 0x822B8
|
||||||
|
g_eeloadExec = EELOAD_START + 0x2B8;
|
||||||
|
else if (typeAexecjump >> 26 == 3) // JAL to 0x82170
|
||||||
|
g_eeloadExec = EELOAD_START + 0x170;
|
||||||
|
else // There might be other types of EELOAD, because these models' BIOSs have not been examined: 18000, 3500x, 3700x,
|
||||||
|
// 5500x, and 7900x. However, all BIOS versions have been examined except for v1.01 and v1.10.
|
||||||
|
Console.WriteLn("recRecompile: Could not enable launch arguments for fast boot mode; unidentified BIOS version! Please report this to the PCSX2 developers.");
|
||||||
|
}
|
||||||
|
|
||||||
// On fast/full boot this will have a crc of 0x0. But when the game/elf itself is
|
// On fast/full boot this will have a crc of 0x0. But when the game/elf itself is
|
||||||
// recompiled (below - ElfEntry && g_GameLoading), then the crc would be from the elf.
|
// recompiled (below - ElfEntry && g_GameLoading), then the crc would be from the elf.
|
||||||
|
@ -1670,6 +1688,9 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
doPlace0Patches();
|
doPlace0Patches();
|
||||||
g_patchesNeedRedo = 0;
|
g_patchesNeedRedo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_eeloadExec && HWADDR(startpc) == HWADDR(g_eeloadExec))
|
||||||
|
xFastCall((void*)eeloadHook2);
|
||||||
|
|
||||||
// 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 (g_GameLoading && HWADDR(startpc) == ElfEntry) {
|
if (g_GameLoading && HWADDR(startpc) == ElfEntry) {
|
||||||
|
|
Loading…
Reference in New Issue