I know this is old, but I couldn't find any information regarding this topic anywhere, even though Xplora 2 can be booted from ef0 and still access both ef0 and memory stick, and since I've discovered how it does it I'll leave the information here.
When the xmb launches a homebrew from the internal storage it uses apitype 0x152, which prevents all access from the application to the memory stick. When it launches a hombrew from the memory stick it uses apitype 0x141, which allows access to ef0 and ms0.
The trick is: there's nothing that prevents us from executing an aplication from ef0 with apitype 0x141 ( sctrlKernelLoadExecVSHWithApitype(apitype, path, ¶m) ), so that's it. This is what I think Xplora 2 does: the ef0:/PSP/GAME/XPLORA/EBOOT.PBP is just a simple loader that loads ef0:/XPLORA/EBOOT.PBP with apitype 0x141, which is the main app and with this double boot process it achieves access to ef0 and ms0.
Of course, you can just put your homebrew in the memory stick and your life would be easier.
Also, regarding plugins, when a prx plugin resides in ef0 (i.e. ef0:/seplugins/myplugin.prx) it will be patched by the custom firmware so all ms0, fatms0 and fatms references remap to ef0, fatef0 and fatef
even when launching from the memory stick (and thus having teoricall access to ms0 and ef0). I think this is done for compatibility reasons. This won't happen if the plugin resides in the memory stick (ms0:/seplugins/myplugin.prx). Here's the patch function from the Pro CFW source code
Pro CFW source code plugins.c:
Code: Select all
static void patch_devicename(SceUID modid)
{
SceModule2 *mod;
int i;
mod = (SceModule2*)sctrlKernelFindModuleByUID(modid);
if(mod == NULL) {
return;
}
for(i=0; i<mod->nsegment; ++i) {
u32 addr;
u32 end;
end = mod->segmentaddr[i] + mod->segmentsize[i];
for(addr = mod->segmentaddr[i]; addr < end; addr += 4) {
char *str = (char*)addr;
if (0 == strncmp(str, "ms0", 3)) {
str[0] = 'e';
str[1] = 'f';
} else if (0 == strncmp(str, "fatms", 5)) {
str[3] = 'e';
str[4] = 'f';
}
}
}
sync_cache();
}
Note: remember that you can have a game.txt in ef0:/seplugins that contains plugins stored in the memory stick, but those plugins will only be loaded when using apitypes compatible with both ef0 and ms0
Note 2: if there is a game.txt in ef0:/seplugins and a game.txt in ms0:/seplugins each one will be used for the corresponding devices, with independent configurations.
So if you want to do something like " sceIoDopen("ms0:/PSP/GAME);" it will actually try to open "ef0:/PSP/GAME". To bypass this is simple:
Code: Select all
sprintf(path, "ms0:/ISO");
if (kuKernelGetModel() == 4 && IsApiIS() == 0){ //This ensures that we only bypass the patch when runing under an apitype that can access the memory stick
buf[0]='m';
buf[1]='s';
}
sceIoDopen(path);
//////////////////////////////////
// Will report if we are running under internal storage (ef0) or not
int IsApiIS()
{
int InitApitype = kuKernelInitApitype();
if (InitApitype == 0x125){//NP9660/ISO MODE
return 1;
}else if (InitApitype == 0x155){//POPS
return 1;
}else if (InitApitype == 0x151){//UPDATER
return 1;
}else if (InitApitype == 0x152){//GAME
return 1;
}else{
return 0;
}
}
With this one can access the memory stick from a plugin that is stored in the internal storage, just be careful with the paths and the fact that the PSPGo might not have a memory stick inserted (one can check it with MScmIsMediumInserted() (pspmscm.h). Remember that as I wrote earlier, if the plugin is running under an apitype that forbids the memory stick (i.e. launching a game from internal storage) all the ms0 references will still be remaped to the internal storage.