NES Patching - Batman RotJ Sound Test

Well, after my last blog entry about the sound test in gimmick, I remembered that in the sound test of batman return of the joker I did notice one bit of music clearly missing and while I wanted to look as to why I just didnt for some reason, until now. The sound test is pretty easily accessible by just pressing a+start on the title screen, leading you to this screen:
soundtest.jpg
As you can see, it starts on A and for the music goes up to M and for the sound effects up to Z.
Also I had a look on tcrf again and saw this little bit:
https://tcrf.net/Batman:_Return_of_the_Joker_(NES)#Unused_Music
"Track 6 in the NSF file is not present in the sound test. The fact it loops suggests it might have been intended for a stage."
So I was right in thinking that something was missing here.
I tried looking in a hex editor if I could find a string like "SOUND TEST" in it, but did not find anything so yet again, it was time to fire up the emulator and check out whats going on!
This was about as simple as it gets, right in the beginning of RAM it was very obvious what byte is used to represent the currently selected bit of music:
bgma.jpg
bgmb.jpg
See how when I select BGM A on the bottom the marked memory value is 00, and when I select BGM B its 01, well that just continues to count up when I go up further. All I had to do is set a write breakpoint to find what piece of code is responsible for increasing that value:
valinc.jpg

All that does is increase that position and if it finds out that position in address 0x11 is larger or equal to 0xD (N), it will loop back down to 0 (A). Also that bit of code above includes the same type of checks for the sound effects position in address 0x12 not going higher than Z, as well as when you want to go below A with the BGM, it will go back up to M, and with the sound effects go back up to Z. Next up I had to figure out how high those values really should go, because I had a feeling theres more sound effects than up to the letter "Z" and maybe even more BGM too, which was just a quick check of what reads from the music position at 0x11 when I press "A" to start playing that bit of music.
bgmplay.jpg

Ah yes, there is a list of actual music values involved of course at address 9C85, so it takes the position from 0x11, then loads whatever the corresponding music value is from that list, and stores that value into 0x41. Oh and for the sound effects that bit of code was again right above this, where it gets the position from 0x12, loads the sound effect value from a list at address 9C92 and stores that value into 0x42. Now it was time to take a look at those lists to see exactly whats going on.
Here is that list for the BGM:
bgmlist.jpg

If you know your hexadecimal system you may notice that 0x06 and 0x0E are missing from that list, I had a quick check if those are indeed music tracks by just manually writing 0x06 and 0x0E into address 0x41 as the game would do to start playing music and indeed, 2 music tracks you dont hear in the sound test started to play. So this would be the first set of patches, I replaced the comparison of larger or equal to 0xD (N) with larger or equal to 0xF (P) as well as when going below A it would go back up to O instead of M. Now the nice thing about how music works here is that it actually is not just a random list of values but its just going up by 1 every time, so the only difference from the selected position and the actual music value is that the music value is 1 higher than the position (position 0=music value 1 etc), so I replaced that load from list with it just increasing the position from 0x11 by 1, moving it over to register A where it normally loads the music value and just as a technicality a "nop" instruction, that one does literally nothing, I just had to add that because the original instruction to load the value from list took 3 bytes, but the increase of position and moving it to register A only takes 2 bytes, so that "nop" just acts as a "filler" byte.
bgmplaypatch.jpg

Great, now all the music is accessable! Of course I could not stop there, I had to take a look at the sound effect list as well, its right behind the music list, I marked it here:
effectlist.jpg

I noticed that right at the end there is that jump from 0x38 to 0x3B, and if you know your hexadecimal numbers that means at least 0x39 and 0x3A are missing, so I wrote those into address 0x42 and indeed, those are valid sound effects. I then just to see went up higher, so 0x3C, 0x3D... and all the way up to 0x48 there were valid sound effects, meaning that in total even though this is a sound test, a whole 15 sound effects were not selectable from it! Again since the sound effects were all in order and not all over the place, that list again was not needed, I replaced the sound effect load from a list to simply add 0x20 to the sound effect position from 0x12 (so position 0x00=sound effect value 0x20 etc) .
effectplaypatch.jpg

So to make all those sound effects selectable it was just a simple job of patching the effect comparisons up to not stop at Z but go much higher, now you may notice an issue with that, after Z theres not exactly any more letters to go up so while yes, I now could listen to all sound effects, the selection doesnt look all that great...
effectcorrupt.jpg
Ah yes, effect <garbled mess> is my favorite! So I could have just left it there because it was working just fine and it was very little I patched over all, it was just graphically weird to look at, but in the end I decided I wanted to change the select system from A-Z to numbers instead. This of course ended up making this patch quite a bit longer.
So address 0x11 and 0x12 dont just get read for increasing/decreasing and choosing a piece of BGM/sound effect to play, but also from a 3rd bit of code:
bgmsprite.jpg
This bit of code loads a tile number from a list at address 9C6B based on the music position at address 0x11 (A=tile 0x22 here), stores that in 0x21, then loads the X position where that tile should be on screen (0x9C in this case), stores that in 0x94, then the Y position going to 0x95 and 0x96 and 0x97 are irrelevant here, after that it calls a function at C247, this function basically takes the parameters just saved in those addresses and puts that tile on screen for us. Right below this bit of code is a near identical piece of code that loads from address 0x12 and has a different X and Y position and calls C247 then as well, of course this is for the sound effect tile. My idea now was to replace this tile list of letters with just the tile 0 repeated 10 times, then 1 repeated 10 times, and so on to be the upper digit for this number selection, now finding those number tiles was easy enough:
0tile.jpg
As you can see I am hovering over the 0 which is value 0x40, 1 is value 0x50 and so on, so I replaced that tile list at 9C6B accordingly:
upperdigit.jpg
You may notice, I just wrote right over the music list and sound effect list because at this point they were not used anymore. So now I have the upper digit in place, of course I still need the lower digit, which meant I needed to add some of my own code. Luckily, there is a giant section of memory just unused right below the sound test, so I could just work right into this:
emptyspace.jpg
You can see I still marked the sound effect list on top, and from that point its just a whole lot of nothing, and that is not even all of it, it goes further than that even, so lots of space to work with for once. Now time for some custom code! I decided to replace the function call to C247 for both BGM and sound effect with a call to some empty memory at 9E47, and placed this bit of code into that area:
customcode.jpg
This bit of code first secures the position of BGM/sound effect that called us so we can use this bit of code for both BGM and sound effect in the first place, else we would have to have separate code for loading both positions from 0x11 and 0x12, then it calls C247 to draw the upper digit part, after that it restores that position and loads the lower digit from a separate tile list I've made at 9E5E that just repeats 1,2,3,4,5,6,7,8,9,0 so often that it can cover all 41 different sound effects, we have enough free space after all, it then stores that tile position into address 0x21, adds 8 to the X position at 0x94 of the tile it just drew so we are exactly right of the tile of the upper digit it just drew, and then we call C247 again to draw our new lower digit tile, then we return to whatever BGM/sound effect called us.
With all that, we now replaced the A-Z system with a system that can go from 01-41, now of course its time to give this a shot on real hardware to make sure what I just wrote up all works!

And it is now working as it should, very good!

As always, I of course pushed that patch to my github.
https://github.com/FIX94/nes-various-patches

If you are for some reason interested in recordings of the PAL version from my hardware using this patched file, here you go:
https://mega.nz/#F!54xGSY7D!AHHPtY7q3ocuWZR-68KPBg!MgxFQRiT

I know, these patches are all pretty useless but still, I feel like just sharing the process this goes through so I have a reference for later and to maybe help others understand how things work in a bit more detail. Thanks for reading.
  • Like
Reactions: 6 people

Comments

Blog entry information

Author
FIX94
Views
177
Comments
2
Last update

More entries in Personal Blogs

More entries from FIX94

General chit-chat
Help Users
    SylverReZ @ SylverReZ: https://www.youtube.com/watch?v=7OwdCc81zHo