Have you ever wanted to be able to use a different color for your text aside from dark grey and dark red? Maybe that off-white background is driving you bonkers? Are the limitations of [ToggleColorInvert] getting you down? Well, here’s an edit that allows you to change those things. WARNING: I am new to assembly; therefore, this may be messy and error-prone. I’m going into excruciating detail to explain what I did, just in case it breaks horribly and I have no idea how to fix it. Or if one of the wizards thinks there’s a more efficient way of doing things.
Overview
First, the text palette and text box background palette are loaded into palette RAM (500 series).
Next, the text in question is copied into WRAM (200 series).
Finally, the functions that actually put text on the screen are called. If you have [ToggleColorInvert], that loads a different text and background palette in the same space in palette RAM as the normal palettes. [ToggleRed] actually uses the same text palette, albeit a different part of it. NOTE: In case you didn’t know, you CAN combine both toggles, but they won’t look great (unless you change the inverted palette). The game reads through each byte in WRAM, goes to a jump table (basically a table of pointers), and executes code depending on the byte it read. Bytes 08-0F (which is the Open Speech Bubble class) go through this same process in a different jump table to determine how long the text box has to be.
This modification basically does the same thing as the [ToggleColorInvert] command: it overwrites the current palette, using the unused FEditor code 0x1E. The syntax is [0x1E][0xXX][0xYY], where XX is the background palette byte and YY is the text palette byte. Here’s a look at the assembly code for FE7/8:
ldr r0,BackgroundTable
ldrb r3,[r4,#0x1] @load background palette byte
sub r3,r3,#0x26
lsl r3,r3,#0x5
add r0,r0,r3 @new background palette location now in r0
ldr r1,TextTable
ldrb r3,[r4,#0x2] @load text palette byte
sub r3,r3,#0x26
lsl r3,r3,#0x5
add r1,r1,r3 @new text palette location now in r1
add r4,r4,#0x3 @increment wram pointer to next instruction
ldr r2,[r7] @r7 has iram pointer to wram pointer
str r4,[r2] @store new wram pointer
push {r4-r7}
ldr r2,PaletteOffset
ldmia r1!, {r4-r7}
stmia r2!, {r4-r7}
ldmia r1!, {r4-r7}
stmia r2!, {r4-r7} @finish loading new text palette
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7} @finish loading new bg palette
pop {r4-r7}
ldr r1, ReadNextCommand
bx r1
.align
BackgroundTable:
.long 0x08B2B200
TextTable:
.long 0x08B2B600
PaletteOffset:
.long 0x05000040
ReadNextCommand:
.long 0x08007015
BackgroundTable and Textable are where you, the person using this, pastes the new palette tables in free space. PaletteOffset is the same in all 3 games, while ReadNextCommand varies (don’t worry, I’ll include the hex further down in this post, along with detailed instructions on what to change).
What does this do? We find the palettes that were called for both background and text. Next, we increment the wram pointer by 2 (this makes it so that the parameters themselves aren’t read as text to be displayed). Finally, we store the new palettes in palette RAM and branch back to the instructions leading to the first jump table.
Now hold on, I hear you say. What’s that sub r3,r3,#0x26 doing there? Good catch! At this time, your palette parameters have to range from 26-FF. Why? FEditor acts funny if you use the reserved opcodes. I am looking for someone to update FEditor so that it will display, for instance, [0x1E][0x26][0x26], rather than changing the parameters to their respective ASCII codes. Similar to the way [LoadFace] works, basically. However, even if this is implemented, you’ll still be stuck with a maximum of FE palettes, because [0x00] is read as “End of text” when the text is being put in WRAM, so everything afterward isn’t going to show up. I could probably do something about it, but I’m not going to, because 1) who is honestly going to use DA (218) palettes, and 2) if, by some freaky chance you do need more, it’s quite easy to make the parameters halfwords instead of bytes, letting you use something like 65000 palettes.
Is that all? Not quite. Remember I mentioned earlier that a different jump table is used when the Open Speech Bubble functions are called? Gotta add something here, too. Fortunately, it’s a lot shorter.
.thumb
.org 0x2
add r4,r4,#0x3
ldr r0,NextValue
bx r0
.align
NextValue:
.long 0x08008B67
This just increments that same pointer to WRAM by 3, again bypassing the parameters. If you don’t, and you do too many palette changes in one box, you’ll get something like this:
Aaaand that’s pretty much it! So…here’s the part you actually want: adding this to your hack!
Adding this to your hack
FE7 and FE8:
00 00 0D 48 63 78 26 3B 5B 01 C0 18 0B 49 A3 78 26 3B 5B 01 C9 18 03 34 3A 68 14 60 F0 B4 08 4A F0 C9 F0 C2 F0 C9 F0 C2 F0 C8 F0 C2 F0 C8 F0 C2 F0 BC 04 49 08 47 C0 46 00 B2 B2 08 00 B6 B2 08 40 00 00 05 15 70 00 08
This is part that does the palette overwriting. You’re going to paste this in free space, and you’re going to change the pointer at (FE7: 8694, FE8: 70A8) to the offset that you pasted this to. Next, in the last 2 rows, you can see 4 pointers: 8B2B200, 8B2B600, 5000040, 8007015. If you’re in FE8 (which is where I wrote this), ignore the last pointer. If you’re in FE7, change it to 8008601. The first two pointers are to your background palette table and your text palette table, respectively, which you will also have somewhere in free space. The areas I wrote are free space in FE8, but you might not want them there, so just repoint accordingly. Each palette is 0x20 bytes long, so a full table will be 0xDA*0x20 = 0x1B40 bytes long, so make sure you have enough space. And always remember to reverse your pointers!
00 00 03 34 00 48 00 47 67 8B 00 08
This is the part that prevents the text box from being too large. Similar to above, you paste this in free space, then change the pointer at (FE7: A1D0, FE8: 8BF8) to the offset you pasted this to. At the very end of this function there’s also a pointer; if you’re in FE7, change this to 800A13F (otherwise, you’re good).
FE6:
I did this pretty much for Omni, but I’ll post it here anyway. The basic premise is exactly the same, but there’s a few modifications.
F0 B4 0D 48 0D 4D 2C 68 A3 78 26 3B 5B 01 C0 18 0B 49 23 79 26 3B 5B 01 C9 18 05 34 2C 60 09 4A F0 C9 F0 C2 F0 C9 F0 C2 F0 C8 F0 C2 F0 C8 F0 C2 F0 BC 05 49 08 47 C0 46 80 00 A3 08 38 00 00 03 E0 00 A3 80 40 00 00 05 E9 99 00 08
Paste this in free space, then write the pointer to this location at 9A84. In the bottom tow, there’s 5 pointers: 8A30080, 3000038, 8A300E0, 5000040, 800999E. You’ll want to change the first and third to your background and text palette tables, respectively (see FE7/8 section for more details).
38 68 05 30 38 60 01 48 00 47 C0 46 B7 C5 00 08
Paste this in free space, then write the pointer to this location at C648.
NOTE: This function will most likely have to be updated if I get that FEditor edit I talked about. Characters in FE6 are written into the ROM as 0x82 0xZZ (where ZZ has some relation to the normal ASCII characters), which means the parameters are also saved as 82 XX 82 YY. So the incrementing function adds 5 instead of 3.
Palettes
Alright, you’ve implemented the code. Now you’ve got 2 tables full of 00s and no idea what to fill it with. What to do? First, let’s look at what part of the palette is actually used where.
NOTE: All my testing has been done in FE8. I think it’s reasonable to assume that it’s the same in the other two (or at the very least, FE7), but it’s not assured. Please let me know if you discover anything wrong.
Background:
If you open up the palette editor in your editor of choice and look at 5000060 (fourth palette in the Background section), you should see this (the colors aren’t exactly the same between games, but fairly similar):
The first color is, as usual, transparent. Colors 2-4 are used in the border. Color #5 is the main fill, ie, the important one. Generally speaking, you can probably copy and paste the basic palette (located at 9E84D4 in FE8, no idea in the others) and only change #5 to whatever you want and leave the rest alone. I have no idea what 6-16 do; if someone finds out, let me know, and I’ll add it to this post and give credit.
Text:
Same thing as background, but look at the one before (5000040). Should look something like this:
This is a bit different. Zahlman believes that there’s 4 groups of 4, with each group having 1 transparent color and the others actually being useful. As far as I can tell, this isn’t the case. Here’s what I’ve discovered:
1 is transparent. 3 and 4 are used for the world map text in FE8. 6 and 7 are the normal text box colors; these are the ones you’ll be changing most of the time. 15 and 16 are called with [ToggleRed]. I have no idea what the other ones are used for; again, if you find out, let me know. In all of these cases, the first one of the two is the anti-aliasing color, and the second is the main color. If you look at the example at the end of this post, I just changed color 7 and left color 6 alone. Again, you can probably get away with copying the basic palette and modifying only specific bytes; in FE8, it’s located at 59EF20.
Calculating palette values
If you have a color’s RGB value, you can change it into the hex value required for GBA fairly easily.
First, divide and floor each value by 8. Each pigment will range from 0-31. Change this number to hex (0x00-0x1F).
For red: Leave it alone.
For green: Multiply by 0x20 (lsl 0x5)
For blue: Multiply by 0x400 (lsl 0x10)
Add everything together. Voila!
Here is the hex calculator I use, if you need one.
Confused? Here’s an example. White is (255,255,255). We divide by 8 and floor, netting us (31,31,31), or (1F,1F,1F).
0x1F0x20 = 0x3E0.
0x1F0x400 = 0x7C00.
0x7C00+0x3E0+0x1F = 0x7FFFF
Go wild! And if you find a really nice palette, perhaps share it with the rest of us! Just remember to make it legible; pretty colors are all well and good, but if we can’t read your text then it’s kinda useless.
What if I want to change other text boxes?
Originally, I wanted to make something that could change the palette of any kind of text box, but that kinda proved impossible because they’re in different locations or loaded at different times. That being said, you can use code similar to mine and just change the palette offsets. Fiddle around with it! Here is a summary of my notes for FE8; at the very least, you got some palette offsets to look at.
Checklist
- Add the palette overriding function to free space. Update pointers as needed.
- Add the parameter skipping function to free space. Update pointers as needed.
- Add actual palettes to your background and text palette tables.
- When you want to change palettes, call it in FEditor with [0x1E][0xXX][0xYY], where XX is the (background palette + 0x26) and YY is the (text palette + 0x26) (THE 26 IS REALLY IMPORTANT, GUYS).
Enjoy!
As far as testing goes, I did some slightly more rigorous testing in FE8, and then the bare minimum in FE7/6 (just enough to verify it works). It’s possible, nay, probable, that there’s glitches; please let me know so I can hang my head in shame (and maybe fix them).
If your FEditor text looks like this, don’t panic! For now, it’s supposed to.
Because, the end result is this:
C’mon, you gotta admit that looks cool!
CREDIT: Zahlman helped alot with analyzing code and bouncing ideas, and Crazycolorz corrected some broken code.