Creating a 60Hz European copy of Ape Escape

Introduction
Ape Escape is a famous PlayStation One game released in 1999 by Sony Computer Entertainment Inc.
Games released for PSX were created in three versions: NTSC, PAL and JP.
As most of you may know, back in 1999, PAL games were about 17% slower than their NTSC/JP counterparts, because our European televisions were slower (50Hz). On top of that game creators based their FPS, physics and all that stuff on the CPU clock instead of some timer. I actually don’t know much about the MIPS processor (used in the PSX), but AFAIK some games can be accelerated just by simulating a NTSC console.
This is not the case for Ape Escape, as if you simulate NTSC, it simply increases the whole game speed, including audio and all movements, which is not something we want.
If you play the NTSC/JP version of this game you instantly notice that is way smoother and more playable overall, so a crazy man like me started to reverse it to see if a PAL copy can run smoothly too.
Bad news, a PAL copy can’t do that, but good news, we can move localized content from a PAL copy to a NTSC copy so that the NTSC code runs at 60Hz and shows PAL content!
Prerequisites
To create a 60Hz copy of Ape Escape we will simply replace some data from the PAL copy of your language to the NTSC one.
To do this we will use the following tools:
dumpsxiso
/ https://github.com/Lameguy64/mkpsxisomkpsxiso
/ https://github.com/Lameguy64/mkpsxisojPSXdec
/ https://github.com/m35/jpsxdecaemt
/ https://github.com/pfrankw/aemt
dumpsxiso
is needed to extract the iso content into a directory.
mkpsxiso
is needed to re-pack the ISO content after modification have been made.
jPSXdec
is a tool that helps to see inside the ISO file. Also decodes some audio / images.
aemt
is a small tool I created to work with the KKIIDDZZ files.
Structure
The following is the directory structure of the Ape Escape’s NTSC ISO:
|
|
DEMO
DEMO
is a folder that contains lots of cutscenes.
They are stored inside the STR files, which is a file format that contains, among the things, ADPCM to be sent to the SPU.
For more info on the STR fromat check the excellent description linked in the references of this document.
We will, in fact, replace NTSC’s STR files with our PAL’s STR files and then adjust pointers/sizes in the HED, but this is work for later.
.ALL
files contain images and other unknown stuff. Some of them can be replaced as they contain localized text.
MINIGAME
Contains stuff (images, also audio i think) about the minigames. Did not touch them as I wasn’t interested, but a simple replace with other versions should work.
STR
This folder also contains cutscenes, but these are continuously repeated, like at the end of each level or when you have a new gadget.
Developers decided to put them here, but they are of the same type of the DEMO
folder.
SCUS_944.23
This is the “program” of the game. It is a executable file that contains MIPS assembly. Can be decompiled using Ghidra with a PSX plugin. More on that on another post. In PAL versions you will find it under a different name.
KKIIDDZZ.HED / DAT / BNS
The KKIIDDZZ files compose a big archive that contain other files. And not only this. A portion of the HED file is dedicated to the pointing of some STR files, but let’s start from the beginning.
1. HED
The HED file is simply a kind of “index” composed by 32-bit numbers stored in little endian. The first 20 bits are the file offset and the remaining 12 bits are the file size. Offsets and sizes are expressed in CDROM data sectors (each data sector is 2048 bytes). You will notice that in PlayStation One games everything is aligned to CDROM sectors.
The offsets are related to the start of the KKIIDDZZ.DAT
file. HED also contains offsets/sizes of STR files (cutscenes) inside the CDROM. These offsets are absolute instead.
2. DAT / BNS
The DAT / BNS files are containers of other files. It’s as simple as that. For example if you read the 6th 32-bit number from the HED file, you will get Offset: 54
and Size: 9
, this means that you will find a blob of data at the (54*2048) position from the start of the DAT file and it will be (9*2048) bytes long. This data can be of any type. Think of it like a .zip archive. If you are interested to go into detail please look at the references.
The BNS file is just the continuation of the DAT file. I don’t know why developers did split them, but offsets that points in the BNS are always related to the start of the DAT.
I strongly suggest the usage jPSXdec
to explore the ISO and its content before trying to modify stuff. It’s useful also for debugging/understanding where the data lies.
To modify HED/DAT/BNS you don’t actually need to understand all of this. You can just use aemt
, which is a tool made for this specific purpose.
Patch archives
As previously said, we must patch the NTSC archive with some data from the PAL version.
Some data will be easily swapped as files, some other lies inside the KKIIDDZZ archive.
We start from the “easy” one.
Dump time!
First thing is to dump all the ISO content using dumpsxiso
. Run the following commands:
Dump the PAL version of your choice (mine is italian):
dumpsxiso -x dump_ita -s dump_ita/mkpsxiso.xml Ape\ Escape\ \(Italy\).bin
Dump the NTSC version:
dumpsxiso -x dump_ntsc -s dump_ntsc/mkpsxiso.xml Ape\ Escape.bin
We now need to use aemt
to patch the NTSC KKIIDDZZ
archive with some data from the PAL one.
First off run ./aemt extracted_ntsc list --decimal
. It will yield this kind of output:
|
|
This simply is the list of files contained in the KKIIDDZZ archive. Notice that index starts from 0 (zero).
Patch time!
Simply run ./aemt dump_ita extract 10 ita_10.dat
to extract the file at index 10 and save it to a file named ita_10.dat
.
Now run ./aemt dump_ntsc patch 10 ita_10.dat
to patch the file at index 10 with the previously extracted PAL version.
This is the list of the known files to be patched:
- 10: Sound pack of Spike doing stuff.
- 11: Pointers of this sound pack. Must be patched along with 10.
- 20: All the in-game mails.
There are others for sure, but at the time of writing they are unknown. Please discover them and tell us!
Hedit time!
Yes you read correctly, hedit
. This is the aemt
command to RAW edit the HED file. We will use this command to adjust the offsets and lengths of the STR files.
This command does not modify any file but it is only used to adjust offset/length.
This is the STR portion of the output of ./aemt dump_ntsc list --decimal
:
|
|
This means that if we hedit
the file at index 448 we are modifying its offset/length, in sectors, in the CDROM. This sounds complicated but thanks to jPSXdec we can easily see this info:
As you can see the output of the list
command perfectly matches what’s under the “Sectors” column in jPSXdec. For example the TALK.STR
file is located at sector 51083 and it’s 1008 sectors long. If you see under jPSXdec, the TALK.STR
file starts at sector 51083 and ends at 52090. If we do the math 52090 - 51083 = 1007. We must always add 1 to this calculation as jPSXdec’s range is inclusive.
As you may have noticed, some STR files aren’t mentioned in the aemt list
command and therefore aren’t present in the HED file. I believe that the game program gets their offsets at run time via PsyQ, but that’s food for another post.
Well, now that we know how to see the sectors each file lies on, we must replace every .STR file inside STR/
and DEMO/
folder and then rebuild the ISO. I personally did not replace TITLE.STR
as it was different in size and added nothing in terms of locale.
Copy all STR files from your PAL dump to the NTSC one and then rebuild the ISO with the following command:
mkpsxiso dump_ntsc/mkpsxiso.xml -o new_ape_escape.bin -c new_ape_escape.cue
.bin is equal to .iso
Now if you open the new_ape_escape.bin
file with jPSXdec, you will notice that sectors of STR files changed, and also their sizes. Time to hedit
.. finally.
Run ./aemt dump_ntsc hedit <INDEX> <OFFSET> <LENGTH>
to edit these properties inside the HED file.
For example, after copying all Italian STR we discover that TALK.STR
moved a bit back:
To fix it we issue ./aemt dump_ntsc hedit 453 49436 864
.
453
is the index ofTALK.STR
inside the HED file.49436
is the new sector position.864
is the new size. (In italian TALK is a bit smaller as you may notice).
We must do this for all the files.
Remember that if you touch other files and rebuild the ISO, STR files positions may vary and you may need to adjust them again with hedit
.
After this re-run:
mkpsxiso dump_ntsc/mkpsxiso.xml -o new_ape_escape.bin -c new_ape_escape.cue
And you’ve got a working 60Hz copy of Ape Escape in your favorite language!
Conclusion
This work is sourced from the deep passion I have about this game and from the help my brother Daddiu gave me during the research.
There is still something missing, especially regarding texts in the UI. I only cared about voices/cutscenes, hence this guide doesn’t cover any text besides mails.
I sincerely hope that by creating AEMT some modding possibilities could open for the community.
Thank you for reading and do not hesitate to contact me if you have any problem!
References
- https://github.com/m35/jpsxdec/blob/readme/jpsxdec/PlayStation1_STR_format.txt
- https://psx-spx.consoledev.net/soundprocessingunitspu/
- https://psx-spx.consoledev.net/cdromfileformats/#cdrom-file-archive-heddatbnsstr-ape-escape
- https://psx-spx.consoledev.net/cdromfileformats/#ape-escape-sound-archive-magdemo22kidzkkiiddzzheddat1bh-1dh49h-53h
- https://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf
- https://psx.arthus.net/sdk/Psy-Q/DOCS/LibRef47.pdf
- https://psx.arthus.net/sdk/Psy-Q/DOCS/XATUT.pdf