Character and Chapter-specific battle themes hack

Tags: #<Tag:0x00007f0e419acf30> #<Tag:0x00007f0e419acd00>

porting it to fe8 shouldn’t be difficult unless the routine ends up being drastically difficult

I am also intending to do theme priority eventually, but that’s pretty far down on my todo list; this was like the first asm i did ever ever so it could probably be improved a lot

Did this ever get ported to FE8? If not, how should I go about doing that?

I have not done that yet. You’d probably have to find where the routine that loads the index of music to play during battle is in FE8, then replace it.

Started out simple enough, the FE8 routine is exactly the same as the FE7 routine and a quick search showed that the routine is at 0x08072D80 and the table is at 0x0875A60. So I just swapped the values in, giving me:

FILE_ST:

@ Offset of routine - 0x080728D0

.align  2
.long 0x08000000

.set  PCTH_ORG, 0x080728D0
.set  PCTH_SIZE, (PCTH_END - PCTH_ST) + 4
@.org PCTH_ORG
.long PCTH_ORG
.long 0x00000000
.long PCTH_SIZE

.thumb

@ R0 - 

PCTH_ST:
  push  {r4, r5}    @ Store necessary values.
  ldr   r0, [r0]    @ Load enemy data.
  ldrb  r2, [r0,#0x4] @ R2 = character number
  ldr   r0, =0x8758A60  @ 0x08758A60 = offset of music table
  mov   r4, #0x0    @ Set R4 equal to our "null" pointer (0x00)
  mov   r5, r0      @ Store data in R5, I suppose.
  ldrb  r0, [r2, r5]  @ Load music byte for enemy.
  cmp   r0, r4      @ If our result is 0x00, then check for player music (allows for boss music to override)
  bne   FIN
  mov   r0, r6      @ Replace enemy memory slot with player.
  ldr   r0, [r0]    @ Load player data.
  ldrb  r2, [r0,#0x4] @ R2 = player number
  ldrb  r0, [r5, r2]  @ Load music byte for player.
  cmp   r0, r4      @ Check for null pointer again
  bne   FIN
  mov   r4, #0x1
  neg   r4, r4
  mov   r0, r4      @ If it is the null pointer, replace it with negative 1.
  
FIN:
  pop   {r4, r5}    @ Clean up.
  bx    lr        @ Return.
  lsl   r0, #0x0    @ Padding.
PCTH_END:

I assembled that and got:

0000 0008 d028 0708
0000 0000 2e00 0000
30b4 0068 0279 0948
0024 051c 505d a042
08d1 301c 0068 0279
a85c a042 02d1 0124
6442 201c 30bc 7047
0000 0000 608a 7508

So the first line looks like a pointer to the routine’s offset, the second line I don’t know, and the rest is the routine. So I insert the routine, and test it. Instead of battle music, I get random sounds like Fimbulvetr and Beep(confirm). So I went to the table and replaced everything with 00, and everyone gets default music, as expected.

But when I try to use the Character Music Editor.nmm (updated with FE8 offsets and lists), it only works for enemies. I did some messing around and found that changing 0x80 (0x00758AE0) will change the music of the generic Fighter on the right, while 0x82 (0x00758AE2) changes the music for the generic fighter on the right. 0x68 changes the boss (O’Neill) music. But setting these to 00 gives the default music whether or not Eirika and Seth have set music.

What did I do wrong?

how are you inserting the routine

if you use an assembly patcher it should just work if you have the location correct

it’s entirely possible there’s some jank involved with fe8 that we just haven’t looked at yet

I used a hex editor and pasted it on top of the existing routine. It doesn’t seem to be any different than using a patcher:

EDIT: Success! Turns out FE8 stores player data in r7 instead of r6. Changed that and it works. So here’s a patch and stuff.

1 Like

the patcher is just a fancy way of writing the data in verbatim; the first line is always metadata (hextator’s doc has a good description of it) but everything else is up for grabs

good on you for the patch, though; i will probably end up hijacking that offset to make a better version (aka making the custom asm not suck)

Has this ever been ported to FE8?

Shouldn’t take that long. Someone else will need to do that research, though, at least until I get my apps in.

Thanks, Cam.
Let’s see if someone else takes the task for now, then!
It’d be very sweet for the FE8 hackers.

Having some trouble assembling impl.asm, it gives me the error:

L:\Fire Emblem Hack\ASM\impl.asm: Assembler messages:
L:\Fire Emblem Hack\ASM\impl.asm:32: Error: branch out of range
readelf: Error: 'impl.elf': No such file
C:\devkitPro\devkitARM\bin\arm-eabi-objcopy: 'impl.elf': No such file
Could Not Find L:\Fire Emblem Hack\ASM\impl.elf
Press any key to continue . . .

The offending line seems to be
GNM_CALL 0x08068140
which is a macro for
bl \address - (GNMH_HOOK_ORG + (FILE_ST - GNMH_HOOK_ST))

The offsets for FE8 were easy enough to find - I think. I don’t know because I can’t actually assemble it to test.

a recent update of gas breaks my bl macro; i can’t remember the workaround offhand.

Screw it I did it manually in debugger

Link to patch - adds both PC and Generic theme patches, writes to 0xE90000 and 0xEB0000 areas

Nightmare modules for editing

1 Like

You, sir, are such an epic person and deserve my most sincere thanks.

Also many thanks to @CT075 for the original code ^^
Time to make some eargasming new themes, with @Agro’s 16 Tracks/12 Notes patch!

Edit: @circleseverywhere, I tried to use one of your modules after applying the patch.

1 Like

Huh, never seen that before. Are you using NM1? Maybe try adding a line with “255” (or whatever the line count is) to the start of the .txt files?

1 Like

That was the issue. It’s working like a charm now, thanks!

There is only one thing that I’m not happy with the character-based hack.
The fact is that it has higher priority than boss themes or generic enemy themes.
Is it possible to find a workaround where the character’s theme plays only during the player phase, while having the generic enemy theme during the Enemy Phase when the character is attacked, and always having the boss theme in both Phases?

tl;dr Giving the character’s theme the same priority as any other allies’ theme

If you give an enemy a personal theme it should have priority over a player’s personal theme. As for making it player phase only, it shouldn’t be too hard.

at the moment, any non-generic enemy theme will override any player theme

i’ve been meaning (for a while) to go through and clean it up and add, say, priorities (as these were the first and second ASM things i’d written ever), but I haven’t had the time

1 Like

@circleseverywhere Hmmmm let’s think about it…

It’d solve the problem regarding bosses, but not the one regarding generic enemies…

Making it play only during player phases seems a good solution.

@CT075 's solution is great as well, since that way it’d be possible to decide whether the theme should play in both phases or just one…