MSU1 Code Library
Zeldix :: MSU-1 Hacking :: MSU-1 Useful Things :: Tutorials
Page 1 of 1
MSU1 Code Library
Hi all. I figured it might be nice to have a spot to post some cleaned up code to insert into various games. a lot of times the MSU1 code can be shared easily between similar functions, so there's no need to write new code all the time...
I'll start with the very basics: Playing the track number in A on the MSU1
Play_Track
Can't take credit for this one: I stole it from conn
I'll start with the very basics: Playing the track number in A on the MSU1
Play_Track
- Code:
pha
sta $2004 ;store track to MSU1
stz $2005 ;zero to msu1 high byte.
stz $2006 ; zero to 2006. no volume. prevents crackle.
loop:
bit $2000 ;checking MSU1 busy
bvs loop
lda $2000;
and #$08 ; is the track found?
beq $03 ;if yes, don't play spc.
jmp notrack
pla
pha
cmp #$XX ;insert whatever number of tracks here that need to not loop.
beq noloop
cmp #$XX
beq noloop
cmp #$XX
beq noloop
lda #$03
bra $02
noloop:
lda #$01
sta $2007 ; sets MSU play
lda #$ff ;\raises volume
sta $2006;/
notrack:
pla
rts;rtl if you jumped long to get in here
Can't take credit for this one: I stole it from conn
Last edited by Cubear on Thu 21 Sep 2023 - 1:33; edited 1 time in total
Re: MSU1 Code Library
I think a lot of my patches are from Conn stolen bits, lol. He is legend.
pev- Since : 2017-10-16
Re: MSU1 Code Library
here's an absolute beast of a fade routine that i had to make for live-a-live
this part is for setting up the speed of the fade and which direction it goes (fade up vs fade down)
Set_Fade
once you had all these values set, you can hook in NMI and run this:
Do_Fade
this is some code that i'm pretty proud of, but i'm not sure it'll ever be useful again. just in case though, i'll put it here.
this part is for setting up the speed of the fade and which direction it goes (fade up vs fade down)
Set_Fade
- Code:
isfade:
lda #$00
phb
pha
plb ;lets do this in databank 00
lda #$03
sta !FADECLOCKLIMIT ;the fade clock will count to this number before resetting to 0 and doing a fade step. larger values = slower fade.
stz !FADECLOCK ;zero out whatever value might still be in there. sanity check.
;$30 was a native code value for fade time in live-a-live. put whatever value you like here for number of frames of fade.
lda $30 ;total time for fade in frames
sta !FADESTEP
;$31 was what volume the game wanted to fade to. you probably want #$00 or #$FF but this game would fade to specific volumes.
lda $31 ;get target volume.
sta !MSUVOLUMETARGET
cmp !MSUVOLUMECURRENT ;check if target is above or below current volume.
beq fadeSame
bcc fadeDown
bcs fadeUp
fadeDown:
lda !MSUVOLUMECURRENT
sec ;gets the difference between current and target values.
sbc $31
stz $4205 ;high byte (Zero)
sta $4204 ;low byte to be divided.
STA !FADEDIFFERENCE ;total amount to fade.
lda !FADESTEP ;number of frames to fade for.
sta $4206 ;divide volume difference by volume step (number of frames)
NOP
NOP
NOP
NOP
NOP ;wait 16 machine cycles
NOP
NOP
NOP
LDA $4216 ;check for remainder
CMP !FADEDIFFERENCE ;make sure it is NOT the entire thing.
beq slowFade ;if it is, do a slower fade
lda !MSUVOLUMECURRENT
sec ;subtract the division remainder from our current volume
sbc $4216 ;so that the math always comes to an exact multiple.
sta !MSUVOLUMECURRENT
lda $4214 ;get our result.
sta !FADESTEP ;save it to be subtracted once per frame.
noFadeEnd:
plb
plp
pla
rtl
fadeUp:
lda $31
sec ;gets the difference between current and target values.
sbc !MSUVOLUMECURRENT
stz $4205 ;high byte.
sta $4204 ;low byte to be divided.
STA !FADEDIFFERENCE
lda !FADESTEP
sta $4206 ;divide volume difference by volume step (number of frames)
NOP
NOP
NOP
NOP
NOP ;wait 16 machine cycles
NOP
NOP
NOP
lda !MSUVOLUMECURRENT
clc
adc $4216 ;check for remainder
CMP !FADEDIFFERENCE ;make sure it is NOT the entire thing.
beq slowFade ;if it is, do a slower fade
sta !MSUVOLUMECURRENT ;and remove it from the current volume so the math works out
lda $4214 ;get our result.
sta !FADESTEP ;save it to be subtracted once per frame.
slowFadedone:
plb
plp
pla
rtl
slowFade: ;3x slower than normal fade.
lda #$06
sta !FADECLOCKLIMIT
lda #$01
sta !FADESTEP
bra slowFadedone
once you had all these values set, you can hook in NMI and run this:
Do_Fade
- Code:
doFade: ;try to be really light in here, not sure how many cycles extra are here.
pha
php
sep #$20
lda !FADECLOCK
inc
CMP !FADECLOCKLIMIT
beq clockTime
sta !FADECLOCK
bra notTime ;exit if clock doesnt match
clockTime:
lda #$00
sta !FADECLOCK
lda !MSUVOLUMECURRENT
cmp !MSUVOLUMETARGET
beq doneFade ;if they're the same, get out of here NOW
bcs doDown ;otherwise doUp
;doUp:
clc
adc !FADESTEP ;add this once per frame until they match.
bcs overflowUp ;check for overflow? it shouldnt happen but maybe....
bra doneFade
doDown:
sec
sbc !FADESTEP ;subtract by step amount per frame
;maybe check for overflow here, even though it should not happen.
bcc overflowDown
doneFade:
sta !MSUVOLUMECURRENT
sta $2006
lda #$02
sta !FADECLOCKLIMIT
notTime:
plp
pla
rtl
overflowUp:
lda #$FF
bra doneFade
overflowDown:
lda #$00
bra doneFade
this is some code that i'm pretty proud of, but i'm not sure it'll ever be useful again. just in case though, i'll put it here.
Last edited by Cubear on Thu 21 Sep 2023 - 2:59; edited 2 times in total
Re: MSU1 Code Library
A much simpler fade code is here. set #$01 to a ram address to fade up, #$02 to fade down. It'll fade to the limits #$FF or #$00 and if your fade changes while it is running, it'll change directions too.
this is just the NMI routine since setting up the fade is so much simpler.
Do_Fade
this is just the NMI routine since setting up the fade is so much simpler.
Do_Fade
- Code:
dofade:
php
sep #$20
pha
lda !msufadeflag ;check for fade flag (01)
beq nofade
cmp #$01
bne nofadeup
lda !msuvol ;check to see if our volume is capped out
beq startfadeup
cmp #$FF
beq donefadeup
donestartfadeup:
inc
beq donefadeup
inc
beq donefadeup
inc
beq donefadeup
sta !msuvol
STA $2006
fadedownout:
pla
plp
rtl
startfadeup:
lda #$03
sta $2007
lda #$00
bra donestartfadeup
nofadeup:
cmp #$02
bne nofade
lda !msuvol ;check to see if our volume is capped out
beq donefadedown
dec
beq donefadedown
dec
beq donefadedown
dec
sta !msuvol
sta $2006
bra fadedownout
donefadeup:
lda #$FF
donefadedownout:
sta !msuvol
sta $2006
nofade:
stz !msufadeflag
pla
plp
rtl
pausetrack:
donefadedown:
lda #$04
sta $2007
lda #$00
bra donefadedownout
Re: MSU1 Code Library
yet another fade, this one just fades down, smaller and simpler for when that matters. set 01 to a ram address to fade down. I've set it up that you should set your volume to FE instead of FF because I like the speed of 2 units at a time instead of 1 or 3.
Do_Fade_Down
Do_Fade_Down
- Code:
dofade:
php
sep #$20 ;8 bit mode
pha
lda !MSUFadeFlag ;check for fade flag (01) if not, exit and max volume
beq nofade ;if 0, this branches.
lda !MSUVolume
cmp #$00
beq donefade ;if already at 0, done fading.
dec
dec ;2 decrease here with volume #$FE, if #FF do 1 or 3.
sta !MSUVolume
STA $002006 ;long addressed in case DB is set weird
pla
plp
rts
donefade:
lda #$00 ;sets our fades to 0
sta !MSUFadeFlag ;remove this one for Life Force since the internal system should remove the fade flag for us
sta !MSUVolume
STA $002006
nofade:
pla
plp
rts
Re: MSU1 Code Library
Too many cooks spoil the food. But what I noticed is for example:
The easiest code to fade imo is that I used for ALTTP lite patch:
All in one check msu ready/ fade down (full/half) and fade up in NMI cycle
Attachment is the working code in zelda as example
- Code:
lda !MSUVolume
cmp #$00
beq donefade ;if already at 0, done fading.
dec
dec ;2 decrease here with volume #$FE, if #FF do 1 or 3.
The easiest code to fade imo is that I used for ALTTP lite patch:
All in one check msu ready/ fade down (full/half) and fade up in NMI cycle
- Code:
; $0127 fade flag (in this example only), set at introducing new track/fade
; -- #$f1: fadeZero: in this example fade to Zero command
; -- #$f2: fadeHalf
; -- #$f3: fadeFull
; $0129 msu busy flag (this example only), set at introducing new track/fade
; -- #$00: no busy
; -- #$01: either fade or msu ready check given
; $012b current volume level to be stored to $2006, set at introducing new track/fade
; -- #$00: start value should be 00 if fade up requested
; -- #$ff: start value should be FF if fade down requested
; when introducing a new track
; do all the msu stuff:
;....
STA $2004
STA $0127 ;store track number or fading instruction (fading can also be stored atdifferent hook)
STZ $2005
STZ $2006
STZ $012b ; erase target volume
LDA #$01
STA $0129 ; set msu busy
;....
; check fade/msu busy (sd2snes) flag $0129 in !!! NMI cycle!!! - set it somewhere else
LDA $0129; in msu busy mode, e.g., fade flag or ready flag set
BNE $01
end:
RTL
LDA $0127 ; fade flag set?
cmp #$f1; fade down Zero set
beq fadeZero
cmp #$f2 ;fade down Half set?
beq fadeHalf
cmp #$f3 ; fade up Full set?
beq fadeFull
; if no fade, there's now sd2snes check whether track is ready
; here you can now check if track ready for sd2snes
bit $2000
bvs end ; track not ready
STZ $0129 ; clear msu busy flag
; store now $2007, 2006, check spc, whatever
;LDA $2000
;AND #$08
;BNE playSPC
;lda $loopValue ;load loop value (01 or 03)
;sta $2007
;lda #$FF ;volume
;sta $2006
;sta $012b ; set full volume to fade later
;RTL
;
;playSPC:
;LDA track
;STA $2140
;RTL
fadeZero:
lda $012b ; current volume
dec
dec
dec
cmp #$10 ; if below $10, zero
bcs $05 ; if not branch 5 bytes
lda #$00
sta $0129 ;reset msu busy flag
sta $2006
sta $012b ;set new current volume
jmp end
fadeHalf:
lda $012b
dec
dec
dec
cmp #$40 ; half volume reached?
bcs $03 ; if not branch 3 bytes
stz $0129 ; if half volume reset fade flag
sta $012b ; new current volume
sta $2006
jmp end
fadeFull:
lda $012b
inc
inc
inc
cmp #$fb ; is (more or less) max volume reached?
bcc $05 ; if not, branch 5 bytes
stz $0129 ; if yes reset fade Flag
lda #$FF; give full volume
sta $2006 ; set current volume
sta $012b
jmp end
Attachment is the working code in zelda as example
- Attachments
Last edited by Conn on Tue 26 Sep 2023 - 2:30; edited 2 times in total
Conn- Since : 2013-06-30
Re: MSU1 Code Library
lol, that's accounted for, sort of.
in the patches where i use that code i set the volume to FE instead of FF so it's divisible by 2 evenly.
That aside, I'm happy to have everybody contribute to this thread! it might make developing patches easier and more time efficient in the future when most things you could want from MSU1 is easily copy + pasted.
in the patches where i use that code i set the volume to FE instead of FF so it's divisible by 2 evenly.
That aside, I'm happy to have everybody contribute to this thread! it might make developing patches easier and more time efficient in the future when most things you could want from MSU1 is easily copy + pasted.
Re: MSU1 Code Library
Indeed an awesome idea!
Yes, it's better to work with BCS/BCC when greater/smaller, equal than... but I mix this up all time as well. Bcs is less but not equal than 0 in substraction, BCc is more or equal 0 on addition or way round. I forgot, lol
Yes, it's better to work with BCS/BCC when greater/smaller, equal than... but I mix this up all time as well. Bcs is less but not equal than 0 in substraction, BCc is more or equal 0 on addition or way round. I forgot, lol
Conn- Since : 2013-06-30
Re: MSU1 Code Library
lol, i have to google it a lot. every time i need to know i look at this:
https://ersanio.gitbook.io/assembly-for-the-snes/the-basics/branches
https://ersanio.gitbook.io/assembly-for-the-snes/the-basics/branches
Similar topics
» Code help
» right code for music?
» Brake pots with asm (new code)
» New, simplified LoZ3 MSU-1 code
» Commented Code Snippets
» right code for music?
» Brake pots with asm (new code)
» New, simplified LoZ3 MSU-1 code
» Commented Code Snippets
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