This is my first PSF. I do not write a generic ripping tips here, but I shall report my research result of this game.
Since my initial attempt was to convert the song sequence into MIDI, this document explains what file formats are used in the driver. If you are interested in how to decode them, please check my "dmfMus" tool out. http://loveemu.googlecode.com
First of all, this game does not use the generic SEQ/VAB driver.
The driver uses VAB for instruments, and it uses custom sequence format. I call the sequence DMF, since the file header always starts with a signature "DMF".
These music sets are stored in archives, that are DATA/*.PAC in the game CD. (Note that all archives are for the music. They are also used for other data.) PAC archive has [offset, size] pairs at the beginning, and each files in PAC has a short header. It indicates if the file is LZSS compressed or not, and also there is the uncompressed size of the file.
As far as I know, a music archive can have 12 files at maximum. In other words, it can have 4 sets of SIF, VH, and VB. SIF is a very simple archive that has song offsets and DMFs. (I call the archive SIF because it is loaded in a function named sound_sif_open) The 4th set seems to be used for BGMs, and others seem to be used for SFXs. Remember, a set can have multiple songs and the only one common instrument collection.
DMF sequence is something like a "simplified SEQ". There are only a few of differences:
- DMF has multiple tracks. (It is like SMF format 1)
- DMF does not have channel bits in status byte. Events are more like usual VGM style. (e.g. 8E xx)
- Effects/Parameters of the most of DMF events are the same as SEQ though.
- DMF has subroutine (call-return) events. Repeated phrases can be expressed smaller than SEQ.
There are DATA/BGMALL*.PAC files, as their names say, they contain probably all BGMs in the game. However, they are probably never used in the game, because the game has PAC for each files. (Yes, there are a lot of duplicated sequences.)
In short, the game plays a song by the following steps:
- Initialize the sound unit
- Load PAC archive file into memory (In PSF, this is done by making psflib)
- Decompress [SIF, VH, VB] set(s)
- Play the song (Nth song of the 4th set, if it is BGM)
Luckily, PAC seems to be always loaded to a constant address, 800FE000.
- 800373D8 (main): Initialize everything
- 800129DC: Load PAC from CD (?) and open it
- 80012808: Load VAB and SIF in the specified set(s)
- 80012378 (vab_load_main): Extract VH/VB and load them into SPU
- 80011938 (sound_sif_open): Extract SIF (i.e. DMFs)
- 80016314: Read a file in PAC
- 8003A670: Read a header of file in PAC
- 8003A888: Decompress the whole of file
- 8003A738: Decompress LZSS
- 80016314: Read a file in PAC
- 80012808: Load VAB and SIF in the specified set(s)
- 8003B714: Play a song
- 8003C8A4: Dispatch an event of DMF
C-style declaration:
void sub_80012808(void *pPAC, int loadTargetBits);
int sound_sif_open(void *pPAC, int internalSetIndex, int fileIndexInPAC);
// return 0 if succeeded.
int sub_80016314(int fileIndexInPAC, void *pPAC, uint8_t *outBuffer);
// return rawFileSize;
int sub_8003A670(void *outBuffer, void *pFileHeaderInPAC);
// return rawFileSize;
int sub_8003A888(void);
int sub_8003A738(int readSize);
// return fileSize - actualReadSize;
void? sub_8003B714(int a0, int internalSetIndex, int songIndex, int a3);
// a0 = 0?
// a3 = (usually 1=BGM, 0=SE?)
- 80079B60 + N * 0x38: Current score data address of track N
The structure is quite simple.
- hokuto.psflib: the music driver (altered SLPS_029.93, by using PSF-o-Cycle)
- hokuto-bgmxx.psflib: BGMALLxx.PAC, located at 0x800FE000
- hokuto-xx.minipsf: a few bytes data, that are arguments for sub_8003B714() the destination address and the structure is defined in hokutodrv.c
If you want to listen a sequence in other PAC file, you can do it as follows:
- Open PSFLab. Click Import Binary Data, then choose a PAC file and set the destination to 0x800FE000. Finally, save the file as psflib.
- Copy a random minipsf, then edit _lib2 tag and the song number (at 0x80075804) by PSFLib.
Like as other PSF does, the driver includes reverb parameters in the PSF driver section. You can edit them by PSF-o-Cycle.
PS-X EXE offsets (just a guess):
- 000800-000EEC
- 001FD8-003F4C
- 006200-006C84
- 02AE70-02E820
- 0317D4-0579CC, 05EC60-060130? (runtime, rough copy)
- 0669D8-067458