Luna
Fully customizable PSP shell
0. Introduction
Luna is a homebrew PSP shell designed to replace the XMB and provide total customizability via Lua scripting. It is intended to serve as an alternative to risky and difficult custom theme hacks, with the goal that skins remain compatible with newer versions.
0.1. Version History
1. Installation
Luna is installed just like any other homebrew: Copy the luna directory into /PSP/GAME on your memory stick. Of course you need hacked firmware.
You will also want to copy the __SCE__webbrowser directory into /PSP/GAME. This program is a simple stub to display the built-in web browser. It can be called from any application. Since its name begins with __SCE__ it does not show up in the menus. It is used when launching the browser from Luna.
1.1. Replacing XMB
A plugin is provided to allow you to have Luna completely replace XMB. Copy luna.prx into /seplugins on the memory stick, and add the line: ms0:/seplugins/luna.prx 1 to the vsh.txt file. This will start Luna any time XMB would normally start. You can bypass it by holding the L trigger. It is also possible to run XMB from within Luna.
2. Usage
Luna leaves the entire user interface up to the skin, so different skins may behave differently. These instructions apply to the included skins. (Skin designers: follow these conventions when possible. Consistency is a good thing.)
Press L or R to cycle through the menus.
When Luna starts you should see a menu listing all programs installed in /PSP/GAME, in alphabetical order. Use the directional pad to select one. Luna respects the firmware O/X swap setting, so use whichever button you've set to be Accept to choose one.
The next menu lists the programs built into the firmware, such as the web browser and XMB. Most of these are not implemented yet.
The third menu lets you select a file from your memory stick. You can select a PBP or PRX file to execute it (currently only user-mode PRXes are supported), or an MP3 file to play it (replacing the current background music if any). Currently MP3s may not play if they have ID3 tags or are encoded at 48khz. (There are no plans to turn Luna into a full-fledged music player; use LightMP3 for that.)
The last menu is not really a menu at all; it displays the contents of /PSP/GAME/Luna/notes.txt, for convenient access to useful information. This is a good place to put a schedule, list of phone numbers, etc.
2.1. Simple Customization
Most skins will use wallpaper.bmp and startup.mp3 (in /PSP/GAME/Luna) as a background image and startup sound. These can easily be replaced. wallpaper.bmp must be a 24-bit 480x272 bitmap image, and startup.mp3 must be a 44khz MP3 file with no ID3 tags. You can also edit boot.lua to change the paths to these files, make them randomly selected, etc. The startup sound will play in the background while Luna is running, so it can be as long as you want.

Don't be afraid to look at boot.lua, where the user settings are stored. This is where you can enable some useful things, such as holding certain button combinations at startup to boot a program before the skin has even loaded, selecting a random skin at startup, etc.
2.2. Included Skins
2.2.1. Simple
(screenshot)
This is a basic skin, good for basing your own skins on. It uses the default font to display text-based menus, using the default wallpaper and startup sound, with sound effects.
2.2.2. Icons
(screenshot) (screenshot)
This is a variation on the Simple skin in which the built-in programs menu is replaced with a 3D icon ring. Icons are loaded from the icons subdirectory and named after the programs' IDs. The ring rotates so that the selected icon is displayed at the front. The icons are scaled so that the selected icon is displayed at a 1:1 ratio (e.g. one pixel in the image occupies exactly one pixel on the screen) regardless of the icons' dimensions. (However, all icons must have the same dimensions.) It should work with any number of icons.
It also displays an analog clock. By editing some variables near the beginning of script.lua, you can move or disable the clock, and switch to a 2D icon ring or a grid.
The other menus are not changed, however a future version will replace the memory stick programs menu with an icon ring as well, using the icons built into each program. Similar may be done for the file selector, using icons based on the file type and/or thumbnails of image files.
(If you can make some half-decent icons to replace these, I'd very much appreciate it. <_<)
2.2.3. Colours
(screenshot) (screenshot)
This skin is like a cross between a trippy visual and a Hollywood hacker desktop, complete with cool background music and sound effects. A spinning RGB cube is displayed on a background of spinning colours. Random numbers scroll up the left side and some interesting-looking debug output displays on the right, with hex strings scrolling by the top of the screen.
The colours of the text also cycle with the background, and some pieces are drawn using various XOR effects.
Near the bottom is a small piece of text where the user can add in their name and phone number, so that anyone who finds the PSP can return it to them.
The analog stick can be used to adjust the saturation and value of the background colour.
(Note that the firmware version displayed in the scroller is hardcoded in this version.)
2.2.4. Zelda
(screenshot) (screenshot)
This skin uses graphics and sound effects from various Zelda games, and mimics the inventory menus in Ocarina of Time. Battery life is displayed as hearts (with the double-defense outline when charging), and free disk space as magic.
This skin is not finished - some graphics still need to be extracted and implemented, and Zelda-style icons need to be made. Unfortunately, I suck at graphics, so I'll probably need to find someone to make those.
3. Creating Skins
Luna's skins are in fact Lua scripts that are responsible for drawing the interface, responding to input, launching programs, etc. Each skin has a directory in /PSP/GAME/Luna/skins. The file script.lua is executed when the skin is loaded. It should define at least one of the functions FrameBegin and FrameEnd.
FrameBegin will be called at the beginning of each frame (just after sceGuStart()), and FrameEnd will be called at the end (after sceGuFinish() and sceGuSync()). Typically, FrameBegin is where the interface will be drawn and the user input will be handled, and FrameEnd is where any drawing onto the framebuffer will be done (a good way to implement text-based menus and status displays).
Nearly all of the functions in pspgu.h and pspgum.h are available to skins (although those that require pointers to matrices or vectors are not usable at the moment), as well as some convenience functions to make common tasks easier. Look at the included skins for examples.
(Note that LoadGU() must be called before 3D functions can be used.)
For information on coding in Lua, see the manual and the tutorial directory. The website also has a live demo page where you can test simple scripts.
3.1. Skin Design Guidelines
Please follow these guidelines to ensure your skins can be enjoyed by all users.
4. Skin API
In addition to these, some useful functions are defined and documented in utils.lua.
4.1. System Control
These functions allow the script to do useful things such as launching programs and reading user input.
4.2. Files
These functions provide convenient methods to read the directory structure from a device.
4.3. Skins
These functions are used to load skins and their resources.
4.4. Math
These functions perform some math operations not natively supported in Lua. Note that the PSP Lua interpreter will crash when given large numbers (over 0x7FFFFFBF) in some places, so be careful using these functions.
4.5. 3D
These functions are used to create and load arrays of vertices, and provide some convenience wrappers around GU functions.
Note that all of the functions in pspgu.h and pspgum.h are available; however, those that require a pointer to a matrix or vector are not currently usable. Also, those that take a colour have it split into the individual R, G, B and A components (in that order) to work around math bugs in the Lua engine.
4.6. Images
These functions are used to load and manipulate images and VRAM.
4.7. Bitmap Fonts
These functions are used to load and render bitmap fonts. Bitmap fonts are stored as a .bmp and .dat file. The .dat file contains two lines. The first specifies information about the font in the format:
UnknownChar,TranspColour,MainColour,MarkerColour,LineHeight,TabWidth
There should be no spaces between values, and colours should be 6-digit hex values (BBGGRR).
The second line contains the list of characters in the order they appear in the image.
The image contains each character in a line. At the top row, a pixel (whose colour is specified by MarkerColour) is drawn between each character to separate them. No markers should appear before the first character or after the last.
4.8. MP3 Playback
These functions are used to play MP3 files. Currently, only MP3 files at 44khz with no ID3 tags can be played, and only one MP3 can be loaded at a time. The main use of these functions is to implement background music, either provided by the skin or from an MP3 file selected from a menu.
MP3 playback uses the media engine, and is updated in a background thread, so it does not have any significant impact on performance.
To delete an MP3 object, so that another can be loaded, stop it and then set it to nil.
4.9. Sound Effects
These functions are used to play WAV files. They work almost identically to the MP3 versions; however, multiple sound effects can be loaded and played at once. Sound effects are played on the CPU.
5. Info
Luna is written by HyperHacker, who can be emailed at hyperhacker@gmail.com. PSPLink was used extensively during development and is also very useful for testing skin scripts as it eliminates the need to copy them to the memory stick.
5.1. License
Copyright (c) 2009, HyperHacker
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
	* Redistributions of source code must retain the above copyright
	  notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above copyright
	  notice, this list of conditions and the following disclaimer in the
	  documentation and/or other materials provided with the distribution.
	* Neither the name of HyperNova Software nor the
	  names of its contributors may be used to endorse or promote products
	  derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY HYPERHACKER ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL HYPERHACKER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.