BSNES Plus Hacking Information Thread
Zeldix :: MSU-1 Hacking :: MSU-1 Useful Things :: Tutorials
Page 1 of 1
BSNES Plus Hacking Information Thread
Hi all, I'm a bit of a new hacker, started about two months ago, so I might actually be TOTALLY off base with some of my suggestions here and we'd all be well off to listen to the more experienced hackers when they come around to tell me that I'm wrong.
Okay after that is said, let's look at the "tools of the trade" that I have chosen to use.
1. BSNES plus. https://bsnes.revenant1.net/
The debugger is worlds better than the SNES9x debugger, when I first started I had no idea how to read ASM code, how to use a debugger, or anything like that... SNES9x was so obtuse and difficult to use that I initially gave up entirely on my notions that this was even possible for me to do.
2. ASAR + its notepad++ language file. https://github.com/RPGHacker/asar/releases
makes everything much more readable when it comes time to actually write your patch.
and... that's actually about it! I wrote a simple batch file that I put into my wip folder to patch a fresh rom for me every time that I change my code for faster testing.
it looks like this internally:
Nothing you couldn't do yourself but feel free to use it. change the filenames in it, whatever you like.
Continuing in a second post with using bsnes debugger to try to identify points of interest, and common things you'll see happening in just about any rom.
Okay after that is said, let's look at the "tools of the trade" that I have chosen to use.
1. BSNES plus. https://bsnes.revenant1.net/
The debugger is worlds better than the SNES9x debugger, when I first started I had no idea how to read ASM code, how to use a debugger, or anything like that... SNES9x was so obtuse and difficult to use that I initially gave up entirely on my notions that this was even possible for me to do.
2. ASAR + its notepad++ language file. https://github.com/RPGHacker/asar/releases
makes everything much more readable when it comes time to actually write your patch.
and... that's actually about it! I wrote a simple batch file that I put into my wip folder to patch a fresh rom for me every time that I change my code for faster testing.
it looks like this internally:
- Code:
del wip_msu.sfc
copy .\original.sfc .\wip_msu.sfc /y
asar wip_msu.asm wip_msu.sfc
pause
Nothing you couldn't do yourself but feel free to use it. change the filenames in it, whatever you like.
Continuing in a second post with using bsnes debugger to try to identify points of interest, and common things you'll see happening in just about any rom.
Last edited by Cubear on Sun 10 Sep 2023 - 23:56; edited 3 times in total
Re: BSNES Plus Hacking Information Thread
On the bsnes debugger:
Here's where basically all your research is done. if I were you, I'd start on a game that has a sound test mode, it makes this whole process much faster... or at least it does for me.
just go to Tools-> Debugger ...
and this pops up.
Pretty cool, but how do we use it? It'll do basically nothing without breakpoints, so let's make one.
go to Tools -> Breakpoint Editor, and let's set some breakpoints on the APU channels. these are the same between every game, 2140, 2141, 2142, 2143. you want to breakpoint when these are Written, so check that W box.
And then run your game. It's very likely that the first thing you run into is going to be a data loader, loading SPC or sample data into the APU, and not at all the track information that you're looking for. you can kinda tell when you're in this type of thing by being in a pretty tight "loop" in the debugger and running the rom just leads you to the same address repeatedly (hundreds of times)
I think this one's actually a wait loop for the SPC to be ready, but it's essentially the same thing... not what we're looking for, but basically adjacent.
What we'd like to do is step through the code for a bit but that involves escaping the loop. the easy method here is to turn off your breakpoints and set one by clicking on the address just past the loop, like so..
When you click "run" again it should take you to your breakpoint, so you can start stepping through the code and get to that little "rtl" at the bottom, which will take you back up one level of code to whatever called this to be loaded.
What I normally do here is look at ram addresses being saved and loaded near data being sent to the APU ports. in assembly, an address is any value preceded by $, so $1a2c might be a ram address I'd like to watch through various tracks playing. there's usually some amount of data being saved by the game itself for its own internal workings that you can capitalize upon when it's time to write the code.
Here's where basically all your research is done. if I were you, I'd start on a game that has a sound test mode, it makes this whole process much faster... or at least it does for me.
just go to Tools-> Debugger ...
and this pops up.
Pretty cool, but how do we use it? It'll do basically nothing without breakpoints, so let's make one.
go to Tools -> Breakpoint Editor, and let's set some breakpoints on the APU channels. these are the same between every game, 2140, 2141, 2142, 2143. you want to breakpoint when these are Written, so check that W box.
And then run your game. It's very likely that the first thing you run into is going to be a data loader, loading SPC or sample data into the APU, and not at all the track information that you're looking for. you can kinda tell when you're in this type of thing by being in a pretty tight "loop" in the debugger and running the rom just leads you to the same address repeatedly (hundreds of times)
I think this one's actually a wait loop for the SPC to be ready, but it's essentially the same thing... not what we're looking for, but basically adjacent.
What we'd like to do is step through the code for a bit but that involves escaping the loop. the easy method here is to turn off your breakpoints and set one by clicking on the address just past the loop, like so..
When you click "run" again it should take you to your breakpoint, so you can start stepping through the code and get to that little "rtl" at the bottom, which will take you back up one level of code to whatever called this to be loaded.
What I normally do here is look at ram addresses being saved and loaded near data being sent to the APU ports. in assembly, an address is any value preceded by $, so $1a2c might be a ram address I'd like to watch through various tracks playing. there's usually some amount of data being saved by the game itself for its own internal workings that you can capitalize upon when it's time to write the code.
Re: BSNES Plus Hacking Information Thread
Using the memory viewer:
it's pretty simple. it's in the tools menu of the debugger, and you just enter the address that you'd like to look at.
The trick here is to enable "auto update" on the right hand side, like so:
This will ensure that you don't get fooled by something not changing when you change tracks in-game.
so let's look at 1a2c here..
here's an animated gif of what's happening in that area while a new track is loaded.. lots of good information here.
1a30 seems to go to 1 while a track is being loaded, 1a2a went from 3e to 3f (with some noise in between) but it might be important, this could be a track number or databank address. something of the sort.
So from here I start breakpointing reads and writes from those addresses, sometimes setting a specific value to cut down on the noise.
at first I get caught in what is almost definitely a data loader, but at the end of clicking run a lot of times, I can see another address that's getting written to.. sometimes this process is a wild goose chase but i've had it bear fruit. overall what you are trying to identify is:
1. How the game determines what data is getting loaded to the APU (track or databank)
2. If it's saved anywhere
3. How to mess with it so that no music plays (without breaking the game)
4. good places to hook (all data in the state you want, while still being able to change the outcome of writes to the APU in order to do mutes, etc)
it's pretty simple. it's in the tools menu of the debugger, and you just enter the address that you'd like to look at.
The trick here is to enable "auto update" on the right hand side, like so:
This will ensure that you don't get fooled by something not changing when you change tracks in-game.
so let's look at 1a2c here..
here's an animated gif of what's happening in that area while a new track is loaded.. lots of good information here.
1a30 seems to go to 1 while a track is being loaded, 1a2a went from 3e to 3f (with some noise in between) but it might be important, this could be a track number or databank address. something of the sort.
So from here I start breakpointing reads and writes from those addresses, sometimes setting a specific value to cut down on the noise.
at first I get caught in what is almost definitely a data loader, but at the end of clicking run a lot of times, I can see another address that's getting written to.. sometimes this process is a wild goose chase but i've had it bear fruit. overall what you are trying to identify is:
1. How the game determines what data is getting loaded to the APU (track or databank)
2. If it's saved anywhere
3. How to mess with it so that no music plays (without breaking the game)
4. good places to hook (all data in the state you want, while still being able to change the outcome of writes to the APU in order to do mutes, etc)
Re: BSNES Plus Hacking Information Thread
This can take a long time doing trial and error or following rabbitholes with no end in sight before you can find anything even remotely useful, but as a person that has a novice understanding of ASM at best, it was the only real way for me to proceed.
Re: BSNES Plus Hacking Information Thread
So let's talk about ASM!
You will not be able to do a hack without some level of understanding SNES ASM.
I used a lot of free resources available on the web to look up what various instructions do and try to puzzle out the purpose of the code the game was running.
Here's some of the better ones I found:
https://ersanio.gitbook.io/assembly-for-the-snes/
https://en.wikibooks.org/wiki/Super_NES_Programming/65c816_reference
https://wiki.superfamicom.org/65816-reference
All share a lot of information but i found that it helped me to understand by looking at multiple pages to see what was being done.
Unfortunately I can't really help you learn ASM at all, that's a you job. generally the code you're trying to hack can be pretty complex, but the code you write can be as basic and simple as you want, so don't go thinking you need to learn all of the language before you begin.
Most of my code is saving and loading addresses, comparing values to saved values, and branching code depending on matches or not.
You will not be able to do a hack without some level of understanding SNES ASM.
I used a lot of free resources available on the web to look up what various instructions do and try to puzzle out the purpose of the code the game was running.
Here's some of the better ones I found:
https://ersanio.gitbook.io/assembly-for-the-snes/
https://en.wikibooks.org/wiki/Super_NES_Programming/65c816_reference
https://wiki.superfamicom.org/65816-reference
All share a lot of information but i found that it helped me to understand by looking at multiple pages to see what was being done.
Unfortunately I can't really help you learn ASM at all, that's a you job. generally the code you're trying to hack can be pretty complex, but the code you write can be as basic and simple as you want, so don't go thinking you need to learn all of the language before you begin.
Most of my code is saving and loading addresses, comparing values to saved values, and branching code depending on matches or not.
Re: BSNES Plus Hacking Information Thread
So let's look at writing code!
Once you've found the information you need to mute tracks and determine what to play, it's time to tear things apart.
first off: your hook.
My hooks are usually basically right bang on an instruction like
STA $2140 as this is when data is being written to the APU, but you don't necessarily need to hook here, and it may not be advisable if the area is too busy.
anyways, once you've decided where to hook, you'll need to make your .asm file.
for ASAR, you'll want to put your rom type at the top, i've mostly just done lorom games so
lorom
Then your hook addresses will be like
org $00d25a
(this will change the data on and after this instruction to whatever you specify. be careful with this part since it's really easy to break the game)
So let's talk about instruction lengths. each instruction is a hexadecimal code, and each of those is followed by... more hexadecimal. something like STA $2140 is three bytes in length. one for the STA and two for the address.
JSL (address) is four bytes in length. but you'll probably need to use this to get to whatever freespace you have identified (there's tools for this, more later)
So when you change a STA to a JSL you overwrite part of the next line of code that the game has by default.
If it's a one byte instruction like TXA, you need to move that into your code near the rtl that takes you back into the game's code.
if the instruction has more bytes, like say SEP #$20 (two bytes) you need to put a nop after your JSL to blank out the second byte, or it will try to execute like it was code, which it was not.
This carries through for three byte and four byte instructions as well. You also need to put that whole instruction at the end of your code returning to the game's code, or things will break
my hooks on Pocky and Rocky mostly look like this:
let's get a bit into the functions of some of those pieces there.
php saves the processor flags to the stack to be restores when we're exiting to the game's code. there's ones for the other things you might be messing with as well, like:
pha (accumulator)
phy (y value)
phx (x value)
to restore the values before you exit your code, it is important to restore them in the opposite order that you wrote them in. otherwise you get the wrong values back out as the stack isn't smart. it just provides the data it was given in the order that it was requested.
So if entering your code you do
pha
phy
php
You need to exit your code with
plp
ply
pla
To ensure you reload the correct values.
Once you've found the information you need to mute tracks and determine what to play, it's time to tear things apart.
first off: your hook.
My hooks are usually basically right bang on an instruction like
STA $2140 as this is when data is being written to the APU, but you don't necessarily need to hook here, and it may not be advisable if the area is too busy.
anyways, once you've decided where to hook, you'll need to make your .asm file.
for ASAR, you'll want to put your rom type at the top, i've mostly just done lorom games so
lorom
Then your hook addresses will be like
org $00d25a
(this will change the data on and after this instruction to whatever you specify. be careful with this part since it's really easy to break the game)
So let's talk about instruction lengths. each instruction is a hexadecimal code, and each of those is followed by... more hexadecimal. something like STA $2140 is three bytes in length. one for the STA and two for the address.
JSL (address) is four bytes in length. but you'll probably need to use this to get to whatever freespace you have identified (there's tools for this, more later)
So when you change a STA to a JSL you overwrite part of the next line of code that the game has by default.
If it's a one byte instruction like TXA, you need to move that into your code near the rtl that takes you back into the game's code.
if the instruction has more bytes, like say SEP #$20 (two bytes) you need to put a nop after your JSL to blank out the second byte, or it will try to execute like it was code, which it was not.
This carries through for three byte and four byte instructions as well. You also need to put that whole instruction at the end of your code returning to the game's code, or things will break
my hooks on Pocky and Rocky mostly look like this:
- Code:
org $00d25a ;Most but not all track changes
jsl hook2trackplay
nop
- Code:
org $208000 ; the start of my freespace
hook2trackplay:
php
sep #$20 ;enter 8 bit mode
sta $0170 ; write accumulator to new ram, to be read later/soon
stz $2140 ; Zero value to $2140 means no music plays. reload this from $170 for SPC fallback
jsr trackselect
lda $0170
plp
rep #$f8 ;game's original code
rtl
let's get a bit into the functions of some of those pieces there.
php saves the processor flags to the stack to be restores when we're exiting to the game's code. there's ones for the other things you might be messing with as well, like:
pha (accumulator)
phy (y value)
phx (x value)
to restore the values before you exit your code, it is important to restore them in the opposite order that you wrote them in. otherwise you get the wrong values back out as the stack isn't smart. it just provides the data it was given in the order that it was requested.
So if entering your code you do
pha
phy
php
You need to exit your code with
plp
ply
pla
To ensure you reload the correct values.
Re: BSNES Plus Hacking Information Thread
I'm sure that I've missed a lot of things but I'm fried right now so if you're trying to follow along and going "I think something is missing" Just post about it. Ask questions.
I could not have gotten as far as I did without asking for and receiving help from people more experienced than me.
And of course, look at others' work. I heavily comment my code and so it may be good to look at what I have done. Conn does not comment his code (probably because he can read it so fluently) + bsinky 's SMT1 code is commented nicely.
You may not be able to steal much code from anybody but even just seeing the ways of tackling a problem can be useful.
I could not have gotten as far as I did without asking for and receiving help from people more experienced than me.
And of course, look at others' work. I heavily comment my code and so it may be good to look at what I have done. Conn does not comment his code (probably because he can read it so fluently) + bsinky 's SMT1 code is commented nicely.
You may not be able to steal much code from anybody but even just seeing the ways of tackling a problem can be useful.
Re: BSNES Plus Hacking Information Thread
How bout hacking star fox 2 ..that game u can go by 2140 to 2143.... Can I some stages it gives the address in ram...so yo hack it there is impossible unless u got the knowledge like Conn or Pev ..or other hackers..other way is tracing... And believe. Me some opcodes don't have all the values for all stages..some are in other opcodes further down...some stages don't trigger at all using 2140 to 2143
kurrono- Since : 2015-03-22
Re: BSNES Plus Hacking Information Thread
From what I've heard (and seen, from work on DOOM) is that SuperFX games can be really tricky. They don't expand nicely and everything on the cartridge seems to get copied to either the SuperFX or RAM and run from there. You're at the mercy of how much space is left in the ram after all the controller code and sound code has loaded.
It's odd that you say there's no signal via $2140-$2143 on some level loads, because that's literally the only way to communicate with the APU and tell it what to do. It may be possible the signal is sent at the end of the prior stage and then it delays X cycles before playing, however...?
It's odd that you say there's no signal via $2140-$2143 on some level loads, because that's literally the only way to communicate with the APU and tell it what to do. It may be possible the signal is sent at the end of the prior stage and then it delays X cycles before playing, however...?
Re: BSNES Plus Hacking Information Thread
I trace that... Like normal music. Stages are on 03e2ab...
Then star fox crash 06f7fc..
Stage clears on 079974
And battleship clear on 03d153..
Yes I'm hacking star fox 2
Then star fox crash 06f7fc..
Stage clears on 079974
And battleship clear on 03d153..
Yes I'm hacking star fox 2
kurrono- Since : 2015-03-22
Re: BSNES Plus Hacking Information Thread
Well, on my plate right now is fixing samurai shodown and releasing a beta of a new project, but I will look at Star Fox 2 after and see if I can come up with anything for you to use
Re: BSNES Plus Hacking Information Thread
Is there even a soundtrack replacement for Star Fox 2?
Relikk- Since : 2017-02-17
Re: BSNES Plus Hacking Information Thread
Not exactly my friend.. there are some songs remix on YouTube though..like the planets ..the title screen.. and character select screen and the stage before u get the planets..surprising attack
Hey Relikk long time ..how been bro... Ur the expert in music ..
Hey Relikk long time ..how been bro... Ur the expert in music ..
kurrono- Since : 2015-03-22
Re: BSNES Plus Hacking Information Thread
Sometimes you just want to make a patch because the hope will be that somebody will then be inspired to make the soundtrack....
Re: BSNES Plus Hacking Information Thread
kurrono wrote:Not exactly my friend.. there are some songs remix on YouTube though..like the planets ..the title screen.. and character select screen and the stage before u get the planets..surprising attack
Hey Relikk long time ..how been bro... Ur the expert in music ..
Long time indeed. Did you ever finish that WWF Wrestlemania?
Cubear wrote:Sometimes you just want to make a patch because the hope will be that somebody will then be inspired to make the soundtrack....
Aye, understandable.
Relikk- Since : 2017-02-17
Re: BSNES Plus Hacking Information Thread
The one I did was the 1st one...
Super wwf...Pev did the other 2..
Super wwf...Pev did the other 2..
kurrono- Since : 2015-03-22
Re: BSNES Plus Hacking Information Thread
@kurrono I'm starting to look into Star Fox 2 (Snes Classic rom) and it looks like the standard Nintendo sound driver to me.
Play signal should look like #$(tracknumber) to $2140.
It looks like the track to load/play is stored in CPU ram at address $001CDA
This is read from cpu ram and then written to the APU at $7F0F30, changing the ram when instruction $7F0F2E executes will load a different track.
$00 appears to be a mute track.
I hope this helps. This appears to be code executing from RAM same as I ran into with DOOM. This means your hook will need to be in the area of rom that gets put into RAM and not in the ram itself. You will also likely need to do some address translation for your code area and have it copied into ram as well, as SuperFX games are really difficult to find usable space in.
Play signal should look like #$(tracknumber) to $2140.
It looks like the track to load/play is stored in CPU ram at address $001CDA
This is read from cpu ram and then written to the APU at $7F0F30, changing the ram when instruction $7F0F2E executes will load a different track.
$00 appears to be a mute track.
I hope this helps. This appears to be code executing from RAM same as I ran into with DOOM. This means your hook will need to be in the area of rom that gets put into RAM and not in the ram itself. You will also likely need to do some address translation for your code area and have it copied into ram as well, as SuperFX games are really difficult to find usable space in.
Re: BSNES Plus Hacking Information Thread
Question. How does one get a MSU-1 track to fade out when the normal track would? Such as during a screen transition. I know you can specify fade ins/outs when creating a PCM but that only seems to apply when the track naturally begins or ends, not when it transitions into another track.
Kaiser Mazoku- Bee
- Since : 2022-08-28
Re: BSNES Plus Hacking Information Thread
Well, to fade out via APU, a signal is sent, once you detect that signal, you can set a byte to a flag that says "fade now"
Then you hook in NMI and check for your flag, if it's found, load a saved volume value, decrease it, save it to $2006 and your saved value again, and clear your flag when it reaches zero.
i'll tear some example code out of one of my hacks as an example. one moment
then in your NMI section...
i've done something kinda sneaky here, any operation that results in $00 will set the Z flag, which trips the beq. saves you a whole cmp
Then you hook in NMI and check for your flag, if it's found, load a saved volume value, decrease it, save it to $2006 and your saved value again, and clear your flag when it reaches zero.
i'll tear some example code out of one of my hacks as an example. one moment
- Code:
longfade:
lda #$02
sta !MSU_Fadeflag
rtl
shortfade:
lda #$01
sta !MSU_Fadeflag
rtl
then in your NMI section...
- Code:
doFade:
sep #$20
php
lda !MSU_Fadeflag
beq nofade
cmp #$02
beq slowfade
cmp #$01
beq fastfade
nofade:
plp
rtl
slowfade:
lda !MSU_Fadevolume
dec
beq donefade
sta !MSU_Fadevolume
sta $002006
plp
rtl
fastfade:
lda !MSU_Fadevolume
dec
dec
dec
beq donefade
sta !MSU_Fadevolume
sta $002006
plp
rtl
donefade:
lda #$00
sta !MSU_Fadevolume
sta $002006
sta !MSU_Fadeflag
sta $002007
plp
rtl
i've done something kinda sneaky here, any operation that results in $00 will set the Z flag, which trips the beq. saves you a whole cmp
Re: BSNES Plus Hacking Information Thread
Awesome. Thanks for the help.
Kaiser Mazoku- Bee
- Since : 2022-08-28
Re: BSNES Plus Hacking Information Thread
Additional to cubear explanation here's an example how it works for zelda:
$0129 = fade flag (free ram), can be f1, f2, f3
$012b = current volume (free ram), can be 00-FF
hijack inside nmi
nmi:
LDA $0129 ;fade flag
cmp #$f1 ; f1: fade to zero
beq fadeZeroVolume
cmp #$f2; f2: fade to half
beq fadeHalfVolume
cmp #$f3; f3: fade to full
beq fadeFullVolume
....
fadeZeroVolume:
lda $012b ; current volume
dec; number of dec:s = velocity of fade down
dec
dec
cmp #$10 ; if <= 10 then zero (mute completely)
bcs $05
lda #$00 ;branched over if not below 10
stz $0129; erase branch flag if below 10
sta $2006 ;store msu volume register
sta $012b ; store new current volume
bra end
fadeHalfVolume:
lda $012b ; current volume
dec ; ; number of dec:s = velocity of fade down
dec
dec
cmp #$40 ; <= 40, target (half) volume reached?
bcs $05
lda #$40 ; target volume
stz $0129; erase fade flag if reached
sta $2006 ; store new volume to msu register
sta $012b ; store new volume
bra end
fadeFullVolume:
lda $012b ; current volume
inc ; number of inc:s = velocity of fade up
inc
inc
cmp #$fb ; if >=FB is reached give full volume
bcc $05
lda #$FF ; full volume
stz $0129 ; erase fade flag
sta $2006 ; new volume to msu register
sta $012b ; new volume
jmp end
$0129 = fade flag (free ram), can be f1, f2, f3
$012b = current volume (free ram), can be 00-FF
hijack inside nmi
nmi:
LDA $0129 ;fade flag
cmp #$f1 ; f1: fade to zero
beq fadeZeroVolume
cmp #$f2; f2: fade to half
beq fadeHalfVolume
cmp #$f3; f3: fade to full
beq fadeFullVolume
....
fadeZeroVolume:
lda $012b ; current volume
dec; number of dec:s = velocity of fade down
dec
dec
cmp #$10 ; if <= 10 then zero (mute completely)
bcs $05
lda #$00 ;branched over if not below 10
stz $0129; erase branch flag if below 10
sta $2006 ;store msu volume register
sta $012b ; store new current volume
bra end
fadeHalfVolume:
lda $012b ; current volume
dec ; ; number of dec:s = velocity of fade down
dec
dec
cmp #$40 ; <= 40, target (half) volume reached?
bcs $05
lda #$40 ; target volume
stz $0129; erase fade flag if reached
sta $2006 ; store new volume to msu register
sta $012b ; store new volume
bra end
fadeFullVolume:
lda $012b ; current volume
inc ; number of inc:s = velocity of fade up
inc
inc
cmp #$fb ; if >=FB is reached give full volume
bcc $05
lda #$FF ; full volume
stz $0129 ; erase fade flag
sta $2006 ; new volume to msu register
sta $012b ; new volume
jmp end
Conn- Since : 2013-06-30
Re: BSNES Plus Hacking Information Thread
you can also set a fade flag on other triggers in a game to add fades where there weren't any. I did this for Uncharted Waters since i didn't like the transition from sailing to town being so abrupt, i hooked during loading tiles for the transition between the two modes and then set a fade flag there. just some food for thought.
Similar topics
» Windows Bsnes Emulator
» Converting PSF with looping information?
» Thread help
» How do I add MSU MD implementation to Mega Man: The Wily Wars
» Desktop Thread
» Converting PSF with looping information?
» Thread help
» How do I add MSU MD implementation to Mega Man: The Wily Wars
» Desktop Thread
Zeldix :: MSU-1 Hacking :: MSU-1 Useful Things :: Tutorials
Page 1 of 1
Permissions in this forum:
You cannot reply to topics in this forum