[Technical] [PSX] Breath of Fire IV Controller Layout Text

Started by ioev/gukid, January 11, 2022, 11:46:01 AM

Previous topic - Next topic


The toggle to change HP&AP/Stats is mapped to the circle button in the subscreen (layout 1)
Skill copying is a part of the game's skill mechanic. You can learn skills from enemies by guarding when that enemy uses the skill, or from masters. Learned skills are displayed on the skill list
Doesn't this just beat all?


I remember that part, I just don't remember this thing about skill scrolls.  Guess I'll probably get to it while I'm testing.

Also finding references to some mini-game where you have to push "Iggy" off a mast, that I don't remember at all :)


Ah, what I meant to say was that skill scroll = skill list in the camp. If you no longer want to use a skill, that skill is "returned" to the skill list
Doesn't this just beat all?


Then this must all be some unused feature?  The text is in CAMP.EMI (there's some other control codes in there):

[Triangle button] Copy skill to Skill Scroll Copy to Skill Scroll? Not enough space. Return skill to Skill Scroll and take ? Return skill to Skill Scroll and take?


"Copy skill to skill scroll" is used when a master teaches you a skill
"Not enough space. Return skill to Skill Scroll and take ? Return skill to Skill Scroll and take?" is used when a character has too many skills and wants to take that skill from the master

These two string are also present in MASTER.EMI, which I think is what the game actually uses when displaying these texts.
Doesn't this just beat all?


Oh perfect, thanks for digging this up!  I guess I would have eventually found it in my testing (Haven't had much time to play yet.)  I'm guessing this one should just stay at Square, but I'll dig around in the Japanese text tonight and see what it was mapped to in that version.


So I've run into another wall that I can't quite figure out, which is the X button prompt to skip a summon/spell, O in the Japanese version.  I've already changed the button constant, so pressing O now skips, but I can't for the life of me figure out how it's drawing the X button.  As far as I can tell, it's using a regular textbox (I've found the "Pass" text and the X button in vram) but it doesn't seem to be using the same codes as other textboxes.  When I had made changes to the button layout on the settings screen, there is a string being referenced that is only the X button string code (050a150106) which is then positioned on the screen, and I've located this string in memory at the time the Pass prompt is being displayed, but it's not being read.

I've mapped out lots of the memory around the battle system, as to how the windows and prompts are positioned, but it seems the Pass prompt is no where near this stuff by the time it displays on screen.

This is the location of all of the X button constants that I've already changed (1st is address, 2nd is value of the result).  I'm guessing the code for displaying the prompt could be around the same place?  Since the prompt only shows up on the 2+ time you use the spell/summon, I figured they would share some logic around when to enable reading the button press, and displaying the box, but I haven't had much luck finding the button icon mapping with this either.

./extracted/BIN/BATTLE/BTLMOVE.EMI: 0000B174: 4000423008004010
./extracted/BIN/BATTLE/BTLMOVE.EMI: 0000B1F4: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC060.EMI: 00015A5C: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC061.EMI: 0001423C: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC062.EMI: 000151E8: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC063.EMI: 00000A80: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC064.EMI: 000009F0: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC065.EMI: 00014188: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC066.EMI: 000149D4: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC067.EMI: 000159F0: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC068.EMI: 000149C8: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC069.EMI: 000151C0: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC070.EMI: 00011A80: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC071.EMI: 0001521C: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC072.EMI: 0000B260: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC073.EMI: 00013998: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC074.EMI: 0001598C: 4000423008004010
./extracted/BIN/BMAGIC/MAGIC075.EMI: 00010230: 4000423008004010


GPU instructions which draw the (X) button:

64808080   Color+Command     (CcBbGgRrh)
00CC011A   Vertex            (YyyyXxxxh)
3C0AB8B4   Texcoord+Palette  (ClutYyXxh)
000C000C   Width+Height      (YsizXsizh)

From CPU trace we get:

801ec010 acc30004: sw     $v1(64808080), 0x0004(a2)([80024150] = 2c808080) # Color+Command     (CcBbGgRrh)
801ec020 acc8000c: sw     $t0(3c0ab8b4), 0x000c(a2)([80024158] = 7d40a0c0) # Texcoord+Palette  (ClutYyXxh)
801ec040 acc20008: sw     $v0(00cc011a), 0x0008(a2)([80024154] = 00000100) # Vertex            (YyyyXxxxh)
801ec024 acc70010: sw     $a3(000c000c), 0x0010(a2)([8002415c] = 00000120) # Width+Height      (YsizXsizh)

Since we're dealing the texture let's check the texcoord

801ebff0 3c083c0a: lui    $t0(80110000), 0x3c0a
801ebff4 3508b8b4: ori    $t0(3c0a0000), 0xb8b4
801ec020 acc8000c: sw     $t0(3c0ab8b4), 0x000c(a2)([80024158] = 7d40a0c0) # Texcoord+Palette  (ClutYyXxh)

Searching for the first two instructions in the game files yields:


To change this to another button, you'll need to change the x value, which is assigned by this instruction

801ebff4 3508b8b4: ori    $t0(3c0a0000), 0xb8b4

Change this to 3508b8a8 (or a8b80835 in little-endian) if you want a circle to appear

It doesn't appear to be text at all. Hope that helps
Doesn't this just beat all?


Thank you again!  I just checked out the operands for those instructions in the Japanese files, and it is in fact A8 for O, B4 for X.

Actually, one of many the things I was thinking of trying (basically brute force) was to figure out the difference between the X coords of the X/O buttons (12) and then run a diff on one of these files looking for changes of that amount.   I didn't end up doing this though because there were more changes than I expected, but I guess if I had kept with it I may have gotten lucky?

And thank you for your detailed notes!  I know very little about the Playstation hardware and instruction set so this will be really useful in trying to find other cases like this one.  Can I ask how you went about doing the CPU trace?  Normally I just poke around in the assembly while the game is running, but it sounds like running a dump might be a better way of looking at the data.

Also, in your trace, I can se it's saving these GPU instructions to 80024150-8002415c, are these memory addresses mapped to the gpu?  I tried putting a write breakpoint on 80024158, but it only seems to trigger at one point where it appears to be initializing the instruction to 3c01b8b4.

Edit: Also also just made all the changes and things are working perfectly!


In PCSX-Redux, you can turn on the CPU tracer by going to Debug > Show Assembly, and checking the "CPU Trace" option, which will start tracing the CPU until you stop the game, or the emulator crashes. You'll need to set a breakpoint or else the emulator will continue tracing until it's out of memory. If you're not sure what breakpoint to use, you can just use Debug > Breakpoint on Vsync.

you probably want to make sure this option is off when you open the emulator next time. a mistake I learned the hard way too many times

80024xxx - ??? is a memory region related to the GPU. Putting a write breakpoint there is almost useless, because the data there changes too frequently.
Doesn't this just beat all?


Quote from: navarchos on April 04, 2022, 06:33:42 PM
80024xxx - ??? is a memory region related to the GPU. Putting a write breakpoint there is almost useless, because the data there changes too frequently.

That makes sense. It's probably writing there on every quad/triangle in the scene so would hit it possibly hundreds (thousands?) of times per frame, so finding the one time that it was writing the data I want would take forever.  In my mind I thought maybe I could watch it draw each piece and try to record the data of right before it draws parts of the Pass prompt.

Thanks again for your help!


Yeah, it's much more difficult to pinpoint how a moving object is being drawn. As for the (X) button, it doesn't move at all, so the instructions that correspond to it in the memory don't change (until it goes away), and it's fairly easy to locate it.
First, I used NO$PSX's GPU debugger to get the GPU instructions which draw the button. Then, I made a savestate in PCSX-Redux when the button appears. Using a hex editor, I searched for the GPU instructions in the savestate. Once I found it, I calculated the corresponding location in the emulator's RAM. I turned on CPU trace and Breakpoint on Vsync. I advanced frame by frame, while the CPU trace captures the CPU instructions. I remove the trace log if the screen doesn't display the button, and I stop when the button appears. I copy the CPU trace to a text editor and then I searched for instructions that modify the RAM address. Someday I'll explain my full workflow in a document.

Oh, and I forgot to mention that the CPU traces appear in the log window.
Doesn't this just beat all?