• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

BGM Extension

UnclePunch

Smash Ace
Joined
Nov 9, 2014
Messages
673
This code allows you to add additional hps files to Melee's song table. The additional songs will start at ID 98 (0x62). You must assemble this code to use it. I recommend using CodeWrite to assemble into a gecko code, or MCM to assemble into an ISO mod.

To modify the extended song list:
Navigate to the song table near the end of the code, surrounded in #'s. To add songs, simply add the following to the bottom of the list:
.string "SONGNAMEHERE.hps"

1577216852394.png


MCM Library File

Code:
#To be inserted at 80023f50

.macro backup
mflr r0
stw r0, 0x4(r1)
stwu    r1,-0x100(r1)    # make space for 12 registers
stmw  r20,0x8(r1)
.endm
.macro restore
lmw  r20,0x8(r1)
lwz r0, 0x104(r1)
addi    r1,r1,0x100    # release the space
mtlr r0
.endm
.macro branchl reg, address
lis \reg, \address @h
ori \reg,\reg,\address @l
mtctr \reg
bctrl
.endm
.macro branch reg, address
lis \reg, \address @h
ori \reg,\reg,\address @l
mtctr \reg
bctr
.endm
.macro load reg, address
lis \reg, \address @h
ori \reg, \reg, \address @l
.endm
.set strlen,0x80325b04

#Check if custom song
  cmpwi r3,98
  blt Injection_Exit

#Init search loop
.set  REG_CustomSongIndex,31
.set  REG_SongList,30
.set  REG_LoopCount,29
  backup
  subi  REG_CustomSongIndex,r3,98
  bl  SongTable
  mflr  REG_SongList
  li  REG_LoopCount,0
StringSearchLoop:
#Check if end of list
  lbz r3,0x0(REG_SongList)
  extsb r3,r3
  cmpwi r3,-1
  beq SongNotFound
#Check if this is the song we are looking for
  cmpw  REG_LoopCount,REG_CustomSongIndex
  beq SongFound
#Get next string
  mr  r3,REG_SongList
  branchl r12,strlen
  add REG_SongList,REG_SongList,r3
  addi  REG_SongList,REG_SongList,1       #add 1 to skip past the 0 terminator
  addi  REG_LoopCount,REG_LoopCount,1
  b StringSearchLoop

#####################################

SongTable:
blrl
#First song on this list is song ID 98 (0x62)
.string "FirstSong.hps"             #this will be song 0x62
.string "SecondSong.hps"            #this will be song 0x63
.string "YouGetTheIdea.hps"         #etc
.byte -1
.align 2

#####################################
SongFound:
  mr  r4,REG_SongList
  restore
  load  r3,0x803bb300+128
  lwz    r5, -0x7DCC (r13)
  add r3,r3,r5
  branch  r12,0x80023f98

SongNotFound:
  restore
  branch  r12,0x80023fc0

Injection_Exit:
 

Attachments

Last edited:

Punkline

Dr. Frankenstack
Joined
May 15, 2015
Messages
423
Fantastic idea! I tested this out last night, and I should mention that your MCM version is missing a return branch at the end of the injection. I don't really have any experience with custom music in Melee, but with your code I was quickly able to play around after a little fiddling with dsp2hps, DTW, and MCM. Great stuff!


Since the code needs to remain unassembled, I have a suggestion for a small but important change to the table interface that would make this much easier to use when developing other codes that use custom music. The problem I’m seeing is that -- while there’s no issue in making a complete table of BGM extensions -- individual extensions for modular codes (meant to be combined) would risk creating ID conflicts with other custom music unless the assets that use those IDs are refactored.

My suggestion is to split the table into a separate recallable text file, and use an if-block inside of it to create a conditional macro definition that defines an overridable default method for interpreting the string arguments -- depending on which code is interpreting it.

This would simply involve replacing the table with a .include directive, and prefixing it with a macro that defines your override behavior:
Rich (BB code):
...
#####################################
  
.macro BGMpath, s; .string "\s"; .endm
BGMpath.override = 1 # injection overrides default macro to create string emitters
  
SongTable: blrl
.include "BGM Extension Table.txt"
.byte -1
.align 2
  
#####################################
...

-- then creating a table file, and writing a default macro into it that defines itself only when a special symbol is not detected:
Rich (BB code):
.ifndef BGMpath.override; BGMpath.override=0; .endif # default = 0 if undefined
.if BGMpath.override==0
  # 0    = macro just sets IDs
  # else = macro is overridden with custom behavior
  .macro BGMpath, s; BGMID.last=BGMID.last+1; BGMID.\s = BGMID.last; .endm; BGMID.last = 0x61
.endif
  
#####################################
# --- SongTable:
  
BGMpath "old_kb2.hps"
BGMpath "izumi2.hps"
BGMpath "customAltMenu.hps"
  
#####################################


This will keep the mod working like it normally does, but with extra features for retrieving the information written to the table file.

The logic in the table file causes the macro BGMpath to be defined in a way that simply takes its given string and creates a symbol name out of it that stores the ID it uses (increment starting at 0x62). This allows the IDs to be recalled by any code that uses .include to include the table with a name rather than by an ID; preventing possible conflicts with other codes using the same module to create custom music. So, for example, instead of using the line li r3, 0x64 to load a custom BGMID in a code somewhere, you could instead use the unique identifier li r3, BGMID.myMusic.hps to prevent hardcoding the ID into the insruction without using the order established by the table file.

Since the injection code defines the symbol BGMpath.override = 1 before including the table, it is allowed to define its own definition for the BGMpath macro to take the place of the normal one -- which it uses to instead invoke the .string directive and emit the actual ascii data like the code normally does.

This polymorphism lets you reuse the table information from a singular source without having to refactor any numerical IDs when installing codes that use this mod.

---


Below is a simple example of an MCM code that uses the proposed interface change:

Rich (BB code):
-==- 
  
Custom Menu Music plays 50% of the time 
Plays custom menu music called "customAltMenu.hps" in main menu 50% of the time 
[Punkline] 
1.02 ----- 8015ecb4 --- 88631851 -> Branch 
.include "BGM Extension Table.txt" 
lbz r3, 0x1851(r3)   # default = normal menu BGMID load 
lwz r0, -0x3F44(r13) # r0 = retrace frame counter 
andi. r0, r0, 1      # if on odd frame... 
beq+ 0f; li r3, BGMID.customAltMenu.hps; 0:  # mod = BGMID for customAltMenu.hps 
.long 0 

So long as BGM Extension Table.txt is in the active directory of your assembler and the line BGMpath "customAltMenu.hps" is defined somewhere in the table (and the file is on your disk) -- this code should install correctly despite not explicitly stating a numerical BGM ID.
 
Last edited:
Top Bottom