PSF Files

PSF files are used in various places on the PSP to store metadata about other files. It contains a list of keys, and the values associated with these keys. This can be information such as parental level, and language.

Numerical data is stored in little endian format, I will use the notation ul32 for "unsigned little endian 32 bit" etc.

The file starts with a header, giving the number of key/value pairs and the offsets for the main parts of the file:

0..30 "PSF"A file type identification cookie. A zero byte is followed by the three uppercase ASCII characters "PSF".
4..71 1 0 0This might be some kind of indication of the PSF version. Currently it's always two 1 bytes followed by two 0 bytes.
8..11ul32Offset from the start of the file to the start of the key table (in bytes)
12..15ul32Offset from the start of the file to the start of the value table (in bytes)
16..19ul32Number of key/value pairs in the index

This header is immediately followed by the index table, which has one entry per key/value pair. This table seems to always be sorted alphabetically on the key string, allowing binary search to be used, although it is unknown if this is actually guaranteed. The entries look like this:

0..1ul16Offset of the key name into the key table (in bytes)
24Unknown, always 4. Maybe alignment requirement for the data?
3ul8Datatype of the value, see below.
4..7ul32Size of value data, in bytes
8..11ul32Size of value data plus padding, in bytes
12..15ul32Offset of the data value into the value table (in bytes)

Value data is always aligned to a 4 byte boundary, so if the size of the data is not dividable by four, the data is padded with zero bytes. The two size fields in the index entry gives the size with and without this padding, respectively. It is allowed to add arbitrary amounts of extra padding (as long as alignment is ensured), which makes it easier to modify data in place. Some games seem to take advantage of this to update the text descriptions as the player progresses in the game.

After the index table comes the key table, at the offset (from the beginning of the file) indicated in the file header. Each key is a NUL-terminated ASCII string. The keys are referenced from the index table by offset from tge key table start, so the first key will have offset 0.

The last part of the file is the value table, again at an offset indicated in the file header. Since value data is required to be aligned, zero padding may exist between the key table and the value table. The offset in the file header will indicate the true start of the value table though.

The type of data in the value table depends on the type field of the index entry that references that particular value. The known types are:

0BINArbitrary binary data, interpretation depending on key
2TXTUTF-8 text string, NUL-terminated. (The NUL is included in the data size.)
4INTAn sl32 integer

Before listing the various known keys, the key CATEGORY should be mentioned. This key exists in all PSF files, and indicate the type of entity described by the PSF file. It has TXT data, and the currertly known values are:

MSMemoryStick Save, i.e. a savegame
MGMemoryStick Game, a game runnable from MemoryStick
UGUMD Game, a game runnable from UMD

Depending on the category, different keys may be relevant. In the following table of observed keys, an * indicates that the key occurs in that category of PSF.

BOOTABLEINT**Setting this to 1 seems to indicate that the game should be autolaunched at bootup.
CATEGORYTXT***Category of PSF, as per the table above
DISC_IDTXT**Product number of the game(?), e.g. "ABCD-00000"
DISC_NUMBERINT*Which disc (out of DISC_TOTAL) is this? (Counts from 1.)
DISC_TOTALINT*Total number of UMD discs for this game.
DISC_VERSIONTXT**Version of the game(?), e.g. "1.00"
LANGUAGETXT*Language of the game. "JP" indicates Japanese, even though this is not the proper ISO 639 code...
PARENTAL_LEVELINT***Minimum parental control level needed to access this file (1-11, 1=general audience, 5=12 years, 7=15 years, 9=18 years)
PSP_SYSTEM_VERTXT**Version of PSP system software required to run the game(?), e.g. "1.00"
REGIONINT**Bitmask of allowed regions. 0x8000 is region 2?
SAVEDATA_DETAILTXT*Text shown under the "Details" heading in the save game menu. Can contain multiple lines of text by embedding CR LF.
SAVEDATA_DIRECTORYTXT*The name of the subdirectory to savedata where this game stores its savefiles (e.g. UCJS10001)
SAVEDATA_FILE_LISTBIN*A list of filenames the game uses for the actual save data (typically something like "DATA.BIN"). Data format currently unknown.
SAVEDATA_PARAMSBIN*Additional parameters of unknown function and data format.
SAVEDATA_TITLETXT*Text shown under the "Saved Data" heading in the save game menu.
TITLETXT***Text shown under the "Game" heading in the save game menu.
TITLE_0TXT***Localized version of the TITLE attribute: Japanese
TITLE_2TXT***Localized version of the TITLE attribute: French
TITLE_3TXT***Localized version of the TITLE attribute: Spanish
TITLE_4TXT***Localized version of the TITLE attribute: German
TITLE_5TXT***Localized version of the TITLE attribute: Italian
TITLE_6TXT***Localized version of the TITLE attribute: Dutch
TITLE_7TXT***Localized version of the TITLE attribute: Portuguese
TITLE_8TXT***Localized version of the TITLE attribute: Russian
UPDATER_VERTXT*Used by the firmware updater program to denote the version it upgrades the firmware to.