Hacking Persona 3, Part 1

Persona 3 is one of my favorite games of all time.  I originally watched a friend play through the game, then bought Persona 3 Portable to see it through myself.  Now, I’ve decided to play through Persona 3 FES, the fully-3D PlayStation 2 version.  I wanted to spice it up a little though, since I’d already seen a friend play through it once before.  So I created a tool that allows you to change and add music, randomly selecting between alternates for songs.  This series of articles is a (heavily edited) look at the path I took to create this tool.

If you just want to use the tool, you can download it on my Misc projects page.

So these are my qualifications:

  • Somewhat experienced C++ coder
  • Intermediate CS knowledge
  • Never touched assembly in my life (still don’t know what MIPS stands for)
  • Know nothing about the PS2 hardware

Sounds good! Time to dig in.

First, we need the game files. So we must acquire a Persona 3 FES disc image. Easy enough, since PS2 games don’t seem to have much in the way of copy protection. ImgBurn has a “Create Image from Disc” option – pop the disc in the tray, enter a path, and hit the button. Done!

Let’s see what we’ve got. windows_iso

So, some “.CVM” files, and a…”.21″ file? What? After some research, it turns out the “SLUS_*” file is the game’s executable, and the “.CVM” files are a format developed by CRI Middleware. The format’s also referred to as “CRI ROFS” (short for “Read Only File System,” I suspect). It’s basically an ISO file with a special header.

So, we’re going to need some software to inspect these files. Luckily, a handy tool by the name of DkZ Studio is like a swiss army knife for this type of thing.

dkz_1

With DkZ Studio, we can open up BGM.CVM…

dkz_2

It’s entirely ADX files, another file format developed by CRI Middleware! It looks like ADX files hold sound. You can open them up with DkZ Studio’s built-in ADX player or VLC to hear them.

All of the game’s music is stored inside this “BGM.CVM” file. There are also a lot of seemingly unused files in here, including little slices of some of the songs. I still have no idea where “THEME.ADX” plays. (Trivia: the Persona 4 BGM.CVM contains the entire Persona 3 soundtrack, though most of it goes unused.)

Let’s start small and try replacing one of the songs. Let’s convert a test MP3 – I chose to replace 26.ADX, the battle music, with the Persona 3 Reincarnation Mass Destruction remix – to WAV then to ADX, replace the original file, and…

dkz_warning

Err, okay, I’ll re-save BGM.CVM and reopen it then.

dkz_error

Drat. It seems DkZ Studio can’t handle creating a new CVM file from scratch, as evidenced by the completely broken BGM.CVM it generated (look at those file sizes!). Time to find a tool that can.

After many hours of research, I stumbled upon this tool created by a fellow named roxfan. It’s a command-line utility that allows you to convert a CVM to an ISO and back again! Excellent. Using that utility, we split the original CVM into an ISO and the CVM header. We pack a new ISO with a tool like ImgBurn, containing the old contents of BGM.CVM but instead of the original 26.ADX, we use our test song.

Finally, we have a new BGM.CVM! Let’s replace the original one in DkZ Studio, re-save the PS2 ISO, and…oh dear. It quits halfway through the save process! I’m not totally sure why this happens, but I have a hunch.

dkz_1

See the file size field for DATA.CVM? It’s not only incorrect, but it’s negative. The actual size of DATA.CVM is around 3gb. I’m guessing it’s being stored as a signed integer instead of unsigned, and the overflow is causing a problem during saving.

After more research, let’s try a tool named UltraISO.

ultraISO

Exactly what we need! With this, we successfully export a new PS2 ISO. Let’s open it in an emulator (PCSX2), and see what happens. Or rather, hear.

We hear some music, but not all. Specifically, all the songs listed before the song we replaced in the ISO table of contents will work perfectly, the song we changed will play but be cut off, and (almost) all the songs after it won’t play anything. To top it all off, with my choice of test files, the dorm music is replaced by the school music for some reason…

Running roxfan’s cvmtool on both the new and old BGM.CVM, we find the following entries in the table of contents:

CVM_NEW

entry flags 0x00, extent 60333 (extattr 0), size 0x2A6000, name '51.ADX;1'

CVM_ORIG

entry flags 0x00, extent 60333 (extattr 0), size 0x1B0000, name '53.ADX;1'

By sheer luck, in the new BGM.CVM, file 53.ADX’s file offset (named “extent” by cvmtool) exactly matches the original BGM.CVM’s file offset for 51.ADX. 53.ADX is the dorm music, which is the music that plays when my save game loaded. If I hadn’t gotten this lucky, the project probably would’ve been dead in the water, because I never would’ve noticed that the game still seems to be loading files from the original BGM.CVM’s ToC, despite the fact that it’s been completely replaced. Which means the game’s not loading files entirely from the CVM!

In part 2, I’ll investigate the source code.