ROMhacking PSP Basics
ROMhacking PSP Basics
This guide contains explanations to reverse engineering (RE from now on) the “digivice ver.
portable psp” ISO, and use that to create a patch for translating the game.
Warning: Some files and/or methods of this project might be only as a proof of concept, hence
they lead nowhere further on. If you don’t know why something is there, it’s probably that.
Considerations
- This is a PDF version of: https://github.com/Bunkai9448/digipet_PSP. To help clarity and
visibility.
- This guide is, also, basically a cleaned-up version of:
https://www.romhacking.net/forum/index.php?topic=35699.msg437896#msg437896. If you
want more details about how or why something was done, go there.
- You must provide your own game files. Do not ask here for them.
Digivice Ver. Portable (Japan) PSP ISO. ID: NPJH-00126
ISO: Digivice_Ver_Portable_JPN_PSN_PSP-PLAYASiA.iso
CRC32: 986e0198
SHA1: e15cd56748525babbb402868ea3df8b44bb6a5c8
SHA256:
ae16195736eb15ba9b2b93f1af31a55401097bc8dff2edf22f304cf4abc69fbc
- Althought everythinbg has been tested without any major problem, it’s provided “as is”, use it
at your own responsability.
1
INDEX
• Extra Tools required
• First Steps
• Working with the CPK file
• Text File
• More unpackaging inside the CPK
• Images and GIM files
• Remaining text in the Eboot
• The Font
• Repackaging the CPK
• System Messages
• Last Steps
• Extra: Making the patch
• Extra 2: Making a cheatcode
• List of References
• Author
• Special thanks
• License
2
First Steps
3
Now with astrogrep, look for a word used in the game, here はじめから it’s used. In this case, it
throws results in the FILEDATA.CPK, which means, tinkering with that file will be the next step.
Mind you, there are a lot of text in the EBOOT file which is encrypted, those words won’t appear
here, that part will be explained later in the guide
4
Working with the CPK file
In the previous section you were leaded to the FILEDATA.CPK, now it’s time to get your hands
dirty on it. This guide will use Crystal Tile 2 for the hex part, but you can use any other editor if
you feel more confortable. When you open the FILEDATA.CPK with your text editor, you’ll
notice it has more than just text. That is because the file is a package of files, which you want to
unpack.
5
This time, you can either go one by one checking what’s inside, or use Astrogrep again to find
the text you want to edit. In any case, you’ll end up in file: ID00033.
Text File
There are several ways to approach this section, this guide uses one which relies on brute force.
If you want to go and find any other guide for dumping and reinserting the text, feel free. In this
project, text uses s-jis but you’d need a table file if you don’t see the text properly
Basically you have to understand how the file and header work, using a hex editor. Then, with
that info, you create a code with armips to create a replica of the file. The Armips_files folder in
this repo contains this section’s scripts. If you want to create a 1:1 file to double-check; edit the
script with the original pointers and japanese text.
6
More unpackaging inside the CPK
It’s time to look for the images and sprites in the game. To do that, you want to search in the
other files of the ISO. In this guide the ID00000 file will be used as example, but the idea is the
same for all of them.
The current approach is the same you used for the text script, you use the hex editor to
understand how the file and header work. Put that knowledge into a code for
packaging/unpackaging.
7
If you want to use the scripts from this guide, go to SCRIPTS_bms and use quickBMS with the
scripts in that folder.
In this method the same script works for packaging and unpackaging.
After unpackaging the files from the previous section, you’ll have a lot of GIM files. Those are
image files in PSP’s propietary format. It’s time to work with them.
You could have been lucky if Gimconv made the full conversion (from GIM to PNG, and back to
GIM) with default configuration and commands. However for this game that’s not how it went,
that leads you again to open your hex editor and look at the header to see your image properties.
In addition, you want to make a sanity check and get an “output.GIM” equal to “input.GIM”. In
this example: edit Gimconv configuration, and execute the command with the new created
option:
option -digi {
image_format = index4
palette_format = rgba4444
format_style = psp
format_endian = little
output_image = on
output_palette = on
output_sequence = on
check_limit = off
}
Once you have the loseless GIM to GIM conversion you can start working with a PNG
transformation in the middle. The remaining part of the section is also copied down ‘as is’ into
Gim2png_bat/GIM_RE.bat for easy trial.
Based on the post by akadewboy on Fri Apr 01, 2011 9:11 pm in
https://forum.xentax.com/viewtopic.php?t=6313
With snipped code to add -digi option in GimConv.cfg file, by ethanol.
8
2. Edit GIM_000000bd.PNG with whatever graphic program you want.
Work with PNG in 16/32bit PNG, save it as Indexed and run it through
https://tinypng.com/
For this project, you can use the PSDs files with the default options if you have problems
with colors after insertion.
There is still text missing and, from previous steps, apparently nothing useful for that in
FILEDATA.CPK, BOOT.BIN, or OPNSSMP.BIN. The last chance of something easy is to find it
in the unencrypted version of EBOOT.BIN. Hence you want to decrypt it to see its content,
luckyly DecEboot can deal with that part. Use DecEboot to get the decrypted file, then use a hex
editor to see the inners of that file… Jackpot! You found the remaining text:
9
To make the edits easier, you can also unpack the sections in the eboot with the script
parse_exe.bms for quickbms. That was done in this guide, the file with the text is:
“000f5e90_000f5f50_00012768_”.
➢ In some rare cases, the EBOOT needs to be re-encrypted for the game to work. Lucky
you, for this game, the EBOOT can be reimported unencrypted.
Now you can go back to Text File and do the same thing for the remaining part of the section.
To avoid dealing with random crashes, this repo didn’t change any EBOOT text pointers. In that
sense, you don’t have to worry about the header or any different address block here.
The Font
You eventually have most files analysed, leaving GMO files (PSP 3d model format) and code
aside. The font must be in the remaining ID00029 file. Time to open it with your hex editor and
find out.
PSP usually puts fonts in 4BPP format, you’ll want to try that before scrolling. Once you have
found the characters, if they are uncompressed (like in this digivice game) the only thing to do is
discovering the actual size of the tiles.
This font parameters are:
BGA 4bpp "tiled" with 16x16 tiles
10
Now it’s time to edit the file to add the characters you want. Example:
To end this task, do not forget to modify your table file accordingly.
You won’t be able to use the new characters properly otherwise.
11
Repackaging the CPK
Remember the second step of this guide? You used CriPackedFileMaker to get the files from
inside your CPK. This is the opposite task, with the same tool.
Before rebuilding/repackaging, you want to get the CPK original info. To create one with the
same parameters later.
12
You can do a repackage without edits as a sanity check. For this game:
Data alignment: 2048 ; File Mode: ID ; any other box unmarked.
13
System Messages
14
PSP plugin
More details at: https://github.com/Bunkai9448/digipet_PSP/blob/main/Syscalls/README.md
Disclaimer
• Don’t forget to write this in your “game.txt”, you can copy paste.
ms0:/seplugins/LangSwapper.prx 1
15
With that we have taken care of all the syscalls required for our translation:
sceImposeSetLanguageMode(), sceUtilityDialogInitStart() and sceUtilitySavedataInitStart().
The following subsections show how to find them should you want to patch them in the game
binaries instead. If you want to jump to the next step, go to Last Steps.
PPSSPP debugger
16
In the opened window, go to the left panel and select Func(tions), see image:
Now, find the 3 functions that deal with system messages: sceImposeSetLanguageMode(),
sceUtilityMsgDialogInitStart(), and sceUtilitySavedataInitStart().
17
Set a breakpoint in the call you want to change, to find the code that makes use of it, see image:
Minimize the debugger window or move it aside and open a system menu in the emulator (For
example, with sceUtilitySavedataInitStart(), click “continue” at the in-game main screen).
The emulator will freeze in this step. Don’t worry, it just means the breakpoint has
been reached. This is the address to copy for the define part in armips.
Now, we need to see what were the parameters passed to the subroutine (which is the actual code
we need to patch). The stack frames are in charge of that task in the code.
18
To do that, go to the stack frames tab at the bottom of the window where you put the breakpoint,
see image:
19
In the stack frames, you’ll see now the sce call instruction and the following instructions, double
click in the second row. It will show us the code where the actual sceUtilitySavedataInitStart() is.
• There you have the address to copy for the edit part in armips.
20
Ghidra
This will explain how to use ghidra to find any of the previous addresses You might want to have
this near: https://ghidra-sre.org/CheatSheet.html
• Now open ghidra, if it’s the first time you’ll get welcome with
Go to File > New Project (ctrl+n).
21
Select shared or Non shared project. Then click next and choose your working directory (this
guide will use a folder called PSP_Ghidra). Don’t forget to give a name to your project, Digivice
for this guide. If you did it properly, you’ll see something like this:
• Drag the decrypted EBOOT in ELF/PRX/BIN format into Ghidra. It should get
automatically detected as PSP Executable (ELF) / Allegrex.
22
Now is your chance to set the file initial base address (this is the BIN address in execution time).
Do it clicking Options and changing the value at ImageBase. Set it to 08804000 to match the
usual base address where games are loaded (it could be different in others, you’ll see that looking
at the defines in PPSSPP debugger or after reading some calls in the code).
Click Ok to import the file. Then you’ll see “Import Results Info” in a prompt, click OK.
After importing and opening the file you should do the auto analysis. Default options are fine.
23
Besides, PPSSPP identifies many functions automatically, it’s useful to get those into Ghidra
after doing the initial analysis. Export the .sym file from PPSSPP (click on debugger >
export .sym).
To use that sym File in Ghidra, go to the “Display Script Manager” button and double-click on it.
24
Now you can import your Sym File with the script PpssppImportSymFile with language allegrex
(use “0” for the base address if you defined the BIN baseAddress, otherwise, you’ll have to use
that here).
• With all the previous steps in ghidra done, you can see the functions and code like you do
in PPSSPP. The moment for finding the addresses has come. Just click the syscall (sce…)
from the list in ghidra and it will take you to the address. For those who need the tip,
finding functions and code is similar to the PPSSPP subsection, but with a static (without
running the game) approach.
25
Subsequent to ghidra / PPSSPP
In addition to the function address, you need the base address for the armips script.
The base address is obtained with the formula: original BIN baseAddress (0x8804000) - header
size. From a quick hex view of the EBOOT.BIN you can see where the header ends and the elf
(actual executable) starts. See image:
With it, you can use to get the arguments for the above formula, for this digivice, means:
Base Address = 0x8804000 - header = 0x8804000 - 0xC0
26
Let’s tart with defines & sceImposeSetLanguageMode (the easiest of them)
.psp
.open "EBOOT.BIN", 0x08803F40 ; as such it excludes header
; Uncommonly, this elf basically treats everything inside the header as start
relative not ram absolute
; hence we need to substract the base to each function define address to use
the right one.
sceImposeSetLanguageMode equ 0x088F96E4 - 0x08804000
sceUtilityMsgDialogInitStart equ 0x088F9724 - 0x08804000
sceUtilitySavedataInitStart equ 0x088F972C - 0x08804000
.close
• Do the same for sceUtilityMsgDialogInitStart, and sceUtilitySavedataInitStart.
Once you’ve done all the changes to the code run your armips script.
Last Steps
This section is just for completionist sake. - As you might guessed, you need to rebuild your ISO
file to play. Use UMDGen to overwrite the old files with the new, edited, ones. Enjoy your
modified game!
27
Making the patch
To share your modification with the world without sharing the full ISO, you better create a patch.
This section is to teach you how to do so.
For this explanation, all the needed files are in the same folder to make it quick and easy to
show, it also avoid any mistakes at chosing the wrong file. However you can have them anywhere
you want.
There are many patch creator tools out there, this guide uses xdeltaUI. Now gather the following
files:
Digidemo.iso: Your modified ISO game.
Digivice_Ver_Portable_JPN_PSN_PSP-PLAYASiA.iso: The original ISO game.
xdelta.exe: The patcher.
xdeltaUI.exe: A tool to use the patcher with a GUI to make it more user
friendly.
Click on the “patch” button and wait a few seconds. A window will appear to tell you everything
went well… You have successfully created your patch!
28
Making a cheatcode
As a bonus for this project, I wanted to create a Quality of Life improvement for this game.
• This will cheat at the steps parameter of this game.
Game ID, just google for it, in this guide case is:
Digivice Ver. Portable (Japan) PSP ISO. ID: NPJH-00126
• The idea is to study how RAM values are passed and changed during executions.
First you need to go to the screen where those values appear (they don’t need to be displayed, as
long as the game is using them, but knowing the actual value will help to find them).
Once you have the values located in-game, you want their RAM location, hence the next step is
making a RAM Dump.
In PPSSPP, go to Debug > Dissassembly. See image below:
29
And right-click in the “Memory” pannel down below, then click on Dump.
There are a few ways to look at the dump, you can even do it by hex editor. However, to make
your work easier, you’re going to use a tool created for that purpose. Download and install/open
ArtMoney from the following link https://www.artmoney.ru/e_download_se.htm you can study
how the parameters for steps change. Another popular tool to make this is
https://www.cheatengine.org/.
30
Open ArtMoney (or your selected tool), and load your RAM.dump.
31
It’s time to look for that number in the tool (ArtMoney or Cheatengine). Don’t worry when you
encounter many candidates for the digits you typed, your next step will be reduce it. Use the
‘Search’ button, and write the digits you want to find.
32
To decrease the matches you want to keep the tool (ArtMoney or Cheatengine) open, play to
change the in-game value and then dump the RAM again. This way you’re going to track down
the values in the RAM, using the filter button.
33
After you have done the previous steps a few times and only one candidate, it’s time to double-
check your results. When you double click over the address obtained in the left pannel (red arrow
in the image below), A new information will show in the right pannel (blue arrow in the image
below). This left pannel shows (theoretically) the value digits in the RAM (and the dump file).
The next step is double-check that with your game. Copy your address from the left pannel (the
red arrow above). Open your emulator’s memory viewer, and go to that address to change its
digits. If everything went well, you’re going to see your parameters change in game. The
addresses on this game steps are: 0959724 for remainings steps, and 0959728 for walked steps.
Tip: for some reason PPSSPP not always shows RAM values because you have to set something
properly in it. Don’t worry, you won’t get a sanity-check but, you can keep going with the
process and the results won’t change.
34
How to use it: As a way to test it, a cheat code for PPSSPP was created following the guide from:
https://www.almarsguides.com/retro/walkthroughs/PSP/HowToUsePSPCodes/
• WARNING: This cheat was made quickly, and due to the nature of the routines for steps
in this digivice game, the result of the cheat is buggy. However it works as a Proof Of
Concept to learn and make more, in fact you can use it for its original purpose with little
effort.
• Code was tested and working both in PPSSPP and PS Vita’s adrenaline, which means
also works on PSP.
35
List of References and Documentation (in no particular order)
• https://haroohie.club/blog/2022-11-02-chokuretsu-archives/ (a RE guide for nds, helps
with a few concepts).
• https://datacrystal.romhacking.net/wiki/Blaze_Union:Tutorials (mini tuto about the
PPSSPP debugger).
• https://gbatemp.net/threads/psp-debugging.452408/ (more about PPSSPP debugger).
• https://gbatemp.net/threads/psp-asm-hacking-for-variable-width-font.374967/page-3
• https://forum.xentax.com/viewtopic.php?t=6313 (about GIM format, for PSP images).
• http://personal.denison.edu/~bressoud/cs281-s10/ (MIPS, PSP uses those with some
custom instructions/encodings).
• https://github.com/uofw/upspd (PSP unofficial documentation repo).
• https://www.psdevwiki.com/ps3/Graphic_Image_Map_(GIM) (wiki entry about GIM
files).
• https://www.psdevwiki.com/ps3/GimConv (wiki entry about GIMconv).
• https://www.vg-resource.com/thread-28180.html (tuto for making BMS scripts).
• http://gitaroopals.shoutwiki.com/wiki/PSP:Patching_the_executable_(BOOT.BIN) (info
about BOOT.bin & EBOOT.bin).
• https://wiki.vg-resource.com/GMO (info about GMO files, 3d models).
• https://winmerge.org/downloads/ (helps comparing files, to get proper gim format in
reinsertion).
• https://www.romhacking.net/documents/765/ (font table).
• http://psp.jim.sh/pspsdk-doc/psputility__sysparam_8h.html
(sceImposeSetLanguageMode).
• http://psp.jim.sh/pspsdk-doc/psputility__msgdialog_8h.html
(sceUtilityMsgDialogInitStart).
• http://psp.jim.sh/pspsdk-doc/psputility__savedata_8h.html (sceUtilitySavedataInitStart).
• https://github.com/NationalSecurityAgency/ghidra (To find sceUtilityMsgDialogInitStart,
and more).
• https://github.com/kotcrab/ghidra-allegrex/blob/master/README.md (PSP’s CPU
module for ghidra).
• https://wololo.net/talk/viewtopic.php?f=28&t=42910&p=389277 (plugin to avoid dealing
with syscalls, sce functions).
36
• https://github.com/kokibits/LangSwapper (source code for the plugin to avoid dealing
with syscalls, sce functions).
Author
• Bunkai
Special thanks
• All the authors of the tools and documents used in this project.
License
• Creative Commons
• All the text in this guide is free to use, modify and distribute. But you must give credit
when it’s due.
37