I've been working on a pet project of mine that I thought would be fun to do. I've been able to write and compile code for running on custom firmware on the PSP for a while now, but I haven't decided on what to do.
I've wanted to make a decent game, perhaps a bike-physics game clone of the one on teagames that I enjoyed so much playing during dull hours at the office, or a tower defense game with nice graphics and interesting weapons.
I've finally got more or less of a hang on the use of makefiles, enough that tweaking them a bit doesn't faze me like it used to. I don't exactly bother to write one from scratch though, as there are still some things I don't fully understand.
I've also enjoyed using plugins, which are really fantastic as it really lets you do so many more things with the PSP than what it can out-of-the-box.
So now I've tried to write my own plugin, based on an existing one, but with different features. It's been considered by some extremely difficult to put folders for games in the XMB. And I wholly agree.
But I've come up with an idea that might work.
When you place a folder in your /PSP/GAME folder that doesn't contain an EBOOT.PBP (the executable) , the XMB will display it as "Corrupted Data". This is just the way it's designed, zero levels deep.
There are plugins that allow you to categorize your games, and by placing them in different folders, you can select which category is currently active, and it displays only those games in the xmb.
These plugins use a button combination or a menu to select the category.
I thought of a way to let a folder show up in GAME, by spoofing an EBOOT when the firmware is trying to read the name and icon for the EBOOT.
The firmware tries to load an EBOOT for each folder it sees in /PSP/GAME. In the empty folder, it tries to load an EBOOT.PBP and as there is none, it fails and tells the firmware that the game is probably corrupt.
With my plugin in place, the code fails, but the plugin catches it and instead generates a fake EBOOT on the fly using the name of the folder and a default icon stored somewhere accessible, and tells the firmware
everything is OK, don't worry, there is an EBOOT here.
Right now this is all the plugin does - it just allows folders to be displayed as EBOOTs in the XMB.
[screenshot goes here]
Now comes the hard part - intercepting when the user tries to open my fake EBOOT.
Normally the firmware tries to load the game, displaying the gameboot intro before launching the game.
What I need to do is catch the keypress before the firmware does, figure out what EBOOT the user is pointed at, check if it is one of mine, and if so, cancel loading the EBOOT and switch "categories" - folders really - and flush the memory stick cache.
This is where it gets interesting.
The PSP firmware is made up of several modules that load other modules as needed. The vshmain module (?) is the module that displays the top-level menu, the XMB.
When you select a top level item, vshmain (?) loads the approriate module - game_plugin in my case.
game_plugin is now responsible for reading the memory stick, drawing the icons, handling the menu. I'm not sure if it is entirely responsible though, it probably makes calls to other existing modules.
I makes sense that the game_plugin module contains a subroutine for checking if the user has pressed a button, or acting on button presses. What I need to do is patch the module to jump to my own code for checking button presses, before I call the original code.
As of now, I only have a fleeting understanding of how this can be done. With my previous knowlege of patching ROM code, I have some idea, but this is a 32-bit RISC platform with relocatable code, making things much more difficult for someone from a 8/16-bit fixed code background. There is probably some mechanism to locate the module's base entry point, and offset from there to some function.
I don't know how to find that function yet. But I have some ideas.
Learn MIPS assembly.
The module loads gameboot.pmf prior to launching the game. Look for the string gameboot.pmf, and to the code that references it and backtrack until you can find where the button presses are. Hopefully button polling/testing can be easily identified in assembly. (HAH!) NOPping out code is a time-honored method of isolating code.
Patch the code somewhere appropriate to jump to a function in my plugin.
This function needs to know what EBOOT the game_plugin module is currently "looking" at. Even after finding the right place to patch and patching the code, this is much more difficult to do. Perhaps the module's memory space contains an array of paths, and an index to the current entry.
Or perhaps there is a function that does this. With the caching that the XMB implements, this makes things much more difficult. Perhaps recoding a game_plugin
is easier in the long run.
One thing fir sure, I would have learned a lot more by the time I'm done with this project, whether it is complete or not.