Music replacement: Detecting which music is being played

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Music replacement: Detecting which music is being played
by on (#111230)
Hi, I'm making an emulator and I'm thinking if it is possible to not play the original music and instead play some custom mp3(for example you own performance of the same background music) when the game is playing. This will involve a few steps:

1. Detect when and which music is being played.

2. Stop the emulator from playing the music without affecting other sound output.

3. Play the custom music.

With so much info about NSF ripping, will it be simple to do step 1? How about step 2? Any idea?

Thanks.
Re: Is it possible to detect which music is being played
by on (#111231)
There is no difference between music and sound, so no, it can't be detected automatically. This would require patching the game, i.e. manually examining the code, making a hack to prevent music from playing (nop'ing a jsr or something), then detect the game in an emulator using a checksum and apply this patch.
Re: Is it possible to detect which music is being played
by on (#111233)
An NSF rip would probably help you figure out how music is played by the game, since the INIT routine should usually point to the music select/setup routine, which is where you'd be detecting the music.

Once you figure out where the music is played in the game's code, probably you might not need to do any patching to the code. Just have the emulator inspect the number that's being used to call up the music, play the appropriate music, and then modify the number so it'll play nothing instead before continuing emulation.
Re: Is it possible to detect which music is being played
by on (#111235)
rainwarrior wrote:
Just have the emulator inspect the number that's being used to call up the music, play the appropriate music, and then modify the number so it'll play nothing instead before continuing emulation.

It'd almost be easier to make the equivalent of a Game Genie patch that writes the song number to a mapper port instead of starting a song. The advantage of that way is that it would work on hardware too, as a Famicom cart can have an MP3 player on-board. Moero Pro Yakyuu did something similar, although for short speech samples instead of music.
Re: Music replacement: Detecting which music is being played
by on (#111239)
Ha ha, that's only an advantage if you happen to have such hardware already built. ;P
Re: Music replacement: Detecting which music is being played
by on (#111240)
Or if you know someone interested in building such hardware. Or if you're convinced that a "Famicom game" needs to at least theoretically run on a Famicom.

In other news, someone almost built this, just without programmatic start/stop.
Re: Music replacement: Detecting which music is being played
by on (#111251)
Like almost anything on the NES, there's absolutely no standard when it comes to sound/music, so each game does things differently. This means that it's not possible to automatically detect songs, or even tell songs and sound effects apart. Whatever you do, will require specific knowledge about each game.
Re: Music replacement: Detecting which music is being played
by on (#111252)
Seems it can help to make a simple variable finder.

1. Play game, doing various things in level that don't change song. During this, emulator scans memory every frame and any bytes changing are marked as "not related to current song number".
2. Tell emulator you're just about to change song number. It stops scanning memory.
3. Just after new song starts, tell emulator to scan memory one more time. It compares with previous scan before song changed, and lists all bytes that just changed.'

Perhaps the same song plays in two different areas. You tell emulator this so it can find, among the bytes that change when the song changes, any that are the same in these two areas. THEN, you can set a breakpoint for when these bytes are changed, and try changing the byte written and in a register to go about finding the music code.
Re: Music replacement: Detecting which music is being played
by on (#111253)
The song number doesn't necessarily have to be in RAM anywhere, it can be used just for starting the track (i.e. setting up pointers and such) and then be discarded. Pointers might not tell you much either, since they'll most likely be modified in order to be able to access more than 256 bytes of data. Personally, I haven't looked into the working of many NES music engines, but I wouldn't feel safe assuming anything about them.
Re: Music replacement: Detecting which music is being played
by on (#111255)
Music repeating needs some sort of state variable. My music engine has a repeat point pointer variable that's modified no more than twice over the course of a song: once at song start, and optionally once after the intro. If you use memory following, consider that some other engines are likely to treat the intro as a separate song in a similar way.
Re: Music replacement: Detecting which music is being played
by on (#111257)
Good points. I figured that most music engines would keep a byte telling which song is currently playing, so that if the game requested the same song again, it wouldn't restart the track. But as you say, the game could easily be made to not request the same song in most cases. Maybe I'm thinking in terms of the SNES with music engines on the SPC-700, where they naturally use this method of changing the song via the only four shared bytes.
Re: Music replacement: Detecting which music is being played
by on (#111276)
Thanks for the replies! So the detection must be game specific, I can think of two ways to go about this.

One way is to predefine a number of game specific detection methods, then list out the music being used in that game and the users just need to choose which mp3 to play. This has the benefit that even users with no knowledge of the NES hardware can use this feature. However that also means the users have to wait for me to add the games to the emulator.

The second way is to let the user to find out and define what to monitor and what to change. I can detect any read to specific PRG address, write to RAM, execution of certain pieces of code etc but this will require the user to have in-depth knowledge of the game and the NES hardware. Also this will need a debugger and that will take me forever to add one.

On the other hand, besides changing the music I can think of some interesting tricks that can be done with this. For example many earlier games do not play any music at title screen, now it will be possible to tell the emulator to play something at that point. I can also tell the emulator to play a different music or sound effect when my character has low health.

What do you think?
Re: Music replacement: Detecting which music is being played
by on (#111283)
Someone can use FCEUX, Nintendulator, or NESICIDE for the debugging while looking for places to patch the music init code. Then he can make an IPS to turn music inits into mapper writes, which your emulator can use.
Re: Music replacement: Detecting which music is being played
by on (#111379)
I think I'll let the user define how to detect it for a particular game by two methods:

1. By monitoring a write to a certain address with a certain value. Then the emulator will either block the write or write another value to stop the music from starting.

2. By monitoring a read for an address range. Then the emulator will play a mp3 file and return a different value (maybe 0x00?) to stop the music from starting.

Do you think this will cover most cases?

Now I need a way to detect when the game wants to stop playing.