New, simplified LoZ3 MSU-1 code
Page 1 of 3
Page 1 of 3 • 1, 2, 3
New, simplified LoZ3 MSU-1 code
I was wanting to make a small change to Conn's MSU-1 code, but ended up realizing that the original code was considerably more complicated than necessary, so I went ahead and wrote my own. Rather than having a dozen different hooks everywhere, it only has the single NMI hook, and then one more to wait for the boss crystal fanfare to complete before starting the telepathic messages. I also implemented a fade-to-half-volume function for entering houses in Kakariko village, opening the map, etc. which Conn's code didn't do. The only issue I currently have is that it causes the PW title screen graphical glitches to return, so I'm still looking into that. I also need to complete a full playthrough to confirm that everything is working, but so far the rest of my testing looks good.
- Code:
arch snes.cpu
macro seek(variable offset) {
origin ((offset & $7F0000) >> 1) | (offset & $7FFF)
base offset
}
define REG_MSU_STATUS($2000)
define REG_MSU_ID_0($2002)
define REG_MSU_ID_1($2003)
define REG_MSU_ID_2($2004)
define REG_MSU_ID_3($2005)
define REG_MSU_ID_4($2006)
define REG_MSU_ID_5($2007)
define REG_MSU_ID_01($2002)
define REG_MSU_ID_23($2004)
define REG_MSU_ID_45($2006)
define VAL_MSU_ID_0(#$53) // 'S'
define VAL_MSU_ID_1(#$2D) // '-'
define VAL_MSU_ID_2(#$4D) // 'M'
define VAL_MSU_ID_3(#$53) // 'S'
define VAL_MSU_ID_4(#$55) // 'U'
define VAL_MSU_ID_5(#$31) // '1'
define VAL_MSU_ID_01(#$2D53) // 'S-'
define VAL_MSU_ID_23(#$534D) // 'MS'
define VAL_MSU_ID_45(#$3155) // 'U1'
define REG_MSU_TRACK($2004)
define REG_MSU_TRACK_LO($2004)
define REG_MSU_TRACK_HI($2005)
define REG_MSU_VOLUME($2006)
define REG_MSU_CONTROL($2007)
define FLAG_MSU_PLAY(#$01)
define FLAG_MSU_REPEAT(#$02)
define FLAG_MSU_STATUS_TRACK_MISSING(#$08)
define FLAG_MSU_STATUS_AUDIO_PLAYING(#$10)
define FLAG_MSU_STATUS_AUDIO_REPEATING(#$20)
define FLAG_MSU_STATUS_AUDIO_BUSY(#$40)
define FLAG_MSU_STATUS_DATA_BUSY(#$80)
define REG_CURRENT_VOLUME($0127)
define REG_TARGET_VOLUME($0129)
define REG_CURRENT_MSU_TRACK($012B)
define REG_MUSIC_CONTROL($012C)
define REG_CURRENT_TRACK($0130)
define REG_CURRENT_COMMAND($0133)
define REG_SPC_CONTROL($2140)
define REG_NMI_FLAGS($4210)
define VAL_COMMAND_FADE_OUT(#$F1)
define VAL_COMMAND_FADE_HALF(#$F2)
define VAL_COMMAND_FULL_VOLUME(#$F3)
define VAL_COMMAND_LOAD_NEW_BANK(#$FF)
define VAL_VOLUME_INCREMENT(#$10)
define VAL_VOLUME_DECREMENT(#$02)
define VAL_VOLUME_MUTE(#$0F)
define VAL_VOLUME_HALF(#$80)
define VAL_VOLUME_FULL(#$FF)
seek($0080D7)
spc_nmi:
jml msu_main
nop
spc_continue:
seek($008103)
spc_skip:
seek($08C3FD)
jml pendant_fanfare
nop
pendant_continue:
seek($08C407)
pendant_done:
seek($08C606)
jml crystal_fanfare
nop
crystal_done:
seek($08C613)
crystal_continue:
seek($0EBD14)
jsl ending_wait
seek($07F89D)
track_list:
db $00,$01,$03,$03,$03,$03,$03,$03
db $01,$03,$01,$03,$03,$03,$03,$03
db $03,$03,$03,$01,$03,$03,$03,$03
db $03,$03,$03,$03,$03,$01,$03,$03
db $03,$01,$01
seek($07F8C0)
msu_main:
lda $4210
lda {REG_MSU_ID_01}
cmp {VAL_MSU_ID_01}
beq +
msu_not_found:
sep #$30
jml spc_continue
+; lda {REG_MSU_ID_23}
cmp {VAL_MSU_ID_23}
bne msu_not_found
lda {REG_MSU_ID_45}
cmp {VAL_MSU_ID_45}
bne msu_not_found
sep #$30
ldx {REG_MUSIC_CONTROL}
bne command_ff
do_fade:
lda {REG_CURRENT_VOLUME}
cmp {REG_TARGET_VOLUME}
bne +
jml spc_skip
+; bcc +
sbc {VAL_VOLUME_DECREMENT}
// cmp {VAL_VOLUME_MUTE}
bcs ++
stz {REG_CURRENT_VOLUME}
stz {REG_MSU_CONTROL}
stz {REG_MUSIC_CONTROL}
stz {REG_CURRENT_TRACK}
stz {REG_CURRENT_COMMAND}
stz {REG_CURRENT_MSU_TRACK}
bra ++
+; adc {VAL_VOLUME_INCREMENT}
bcc +
lda {VAL_VOLUME_FULL}
+; sta {REG_CURRENT_VOLUME}
sta {REG_MSU_VOLUME}
jml spc_continue
command_ff:
cpx {VAL_COMMAND_LOAD_NEW_BANK}
bne command_f3
jml spc_continue
command_f3:
cpx {VAL_COMMAND_FULL_VOLUME}
bne command_f2
stx {REG_SPC_CONTROL}
stx {REG_CURRENT_COMMAND}
lda {VAL_VOLUME_FULL}
sta {REG_TARGET_VOLUME}
stz {REG_MUSIC_CONTROL}
jml spc_skip
command_f2:
cpx {VAL_COMMAND_FADE_HALF}
bne command_f1
stx {REG_SPC_CONTROL}
stx {REG_CURRENT_COMMAND}
lda {VAL_VOLUME_HALF}
sta {REG_TARGET_VOLUME}
stz {REG_MUSIC_CONTROL}
jml spc_skip
command_f1:
cpx {VAL_COMMAND_FADE_OUT}
bne load_track
stx {REG_SPC_CONTROL}
stx {REG_CURRENT_COMMAND}
stx {REG_CURRENT_TRACK}
stz {REG_TARGET_VOLUME}
stz {REG_MUSIC_CONTROL}
jml spc_skip
load_track:
cpx {REG_CURRENT_MSU_TRACK}
bne +
cpx #$1B
beq +
jml spc_skip
+; stx {REG_MSU_TRACK_LO}
stz {REG_MSU_TRACK_HI}
stz {REG_MSU_CONTROL}
lda {VAL_VOLUME_FULL}
sta {REG_TARGET_VOLUME}
sta {REG_CURRENT_VOLUME}
sta {REG_MSU_VOLUME}
msu_check_busy:
lda {REG_MSU_STATUS}
bit {FLAG_MSU_STATUS_AUDIO_BUSY}
bne msu_check_busy
bit {FLAG_MSU_STATUS_TRACK_MISSING}
beq msu_play
spc_fallback:
stz {REG_MSU_CONTROL}
stz {REG_CURRENT_MSU_TRACK}
stz {REG_TARGET_VOLUME}
stz {REG_CURRENT_VOLUME}
stz {REG_MSU_VOLUME}
jml spc_continue
msu_play:
lda {VAL_COMMAND_FADE_OUT}
sta {REG_SPC_CONTROL}
lda track_list,x
sta {REG_MSU_CONTROL}
stx {REG_CURRENT_COMMAND}
stx {REG_CURRENT_TRACK}
stx {REG_CURRENT_MSU_TRACK}
stz {REG_MUSIC_CONTROL}
jml spc_skip
pendant_fanfare:
rep #$20
lda {REG_MSU_ID_01}
cmp {VAL_MSU_ID_01}
bne pendant_spc
lda {REG_MSU_ID_23}
cmp {VAL_MSU_ID_23}
bne pendant_spc
lda {REG_MSU_ID_45}
cmp {VAL_MSU_ID_45}
bne pendant_spc
sep #$20
lda {REG_MSU_STATUS}
bit {FLAG_MSU_STATUS_AUDIO_PLAYING}
bne +
-; jml pendant_done
-;+;jml pendant_continue
pendant_spc:
sep #$20
lda {REG_SPC_CONTROL}
bne -
bra --
crystal_fanfare:
rep #$20
lda {REG_MSU_ID_01}
cmp {VAL_MSU_ID_01}
bne crystal_spc
lda {REG_MSU_ID_23}
cmp {VAL_MSU_ID_23}
bne crystal_spc
lda {REG_MSU_ID_45}
cmp {VAL_MSU_ID_45}
bne crystal_spc
sep #$20
lda {REG_MSU_STATUS}
bit {FLAG_MSU_STATUS_AUDIO_PLAYING}
bne +
-; jml crystal_done
-;+;jml crystal_continue
crystal_spc:
sep #$20
lda {REG_SPC_CONTROL}
bne -
bra --
ending_wait:
rep #$20
lda {REG_MSU_ID_01}
cmp {VAL_MSU_ID_01}
bne +
lda {REG_MSU_ID_23}
cmp {VAL_MSU_ID_23}
bne +
lda {REG_MSU_ID_45}
cmp {VAL_MSU_ID_45}
bne +
sep #$20
-; lda {REG_MSU_STATUS}
bit {FLAG_MSU_STATUS_AUDIO_PLAYING}
bne -
+; sep #$20
lda #$22
rtl
Last edited by qwertymodo on Thu 12 Jan 2017 - 18:01; edited 8 times in total
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
Alright, let me know in case I shall change something to the alttp archieve.
But my code actually features the fade to half when entering a house in Kakariko village and map.
But my code actually features the fade to half when entering a house in Kakariko village and map.
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
Yours cuts directly to half volume, mine does a smooth fade (like the fade out to mute). Plus, there was a minor issue where it didn't get set to half until you were already inside, where the original SPC music starts fading to half as you step into the door. Very minor things, I just recall you saying you didn't want to fix them (and I don't blame you, I remember how many minor issues we all kept reporting, you were pretty done dealing with it at that point ).
I do really need to figure out why the PW title screen is glitching out though...
I do really need to figure out why the PW title screen is glitching out though...
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
If it is caused by your hack, you can selectively reverse the jumps to see which part causes this bug. Maybe you overwrote an register or hooked in a routine that must not be interrupted...
Ah well, situation didn't change. I am still happy with my hack and probably leave it as it is. You can still publish is at DX++ patch or whatever ^^
Ah well, situation didn't change. I am still happy with my hack and probably leave it as it is. You can still publish is at DX++ patch or whatever ^^
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
You to that! It's working perfect as is in my hack...with the one hundred tracks in all the parts...I don't ever want to mess with that ever again lol!Conn wrote:I am still happy with my hack and probably leave it as it is.
Floki- Since : 2012-06-19
Re: New, simplified LoZ3 MSU-1 code
I get the feeling that it's a timing issue, akin to the original problem before ikari's fix.
As far as your hack goes, do whatever you want, I'm just putting this out there. I'll probably use it in my DX patch if I ever do another update, but only if there's some other reason to update (like possibly adding this patch). No reason to replace your code if you don't want to. If it ain't broke, and all that... but if you want it, it's freely available. For anybody else wanting to add this to their own hack, this is probably the better choice, simply because there's only the two hooks, so less chance of unintended side effects when mixing with other code.
I'm not in anyway trying to bash your work, Conn. Your patch was the catalyst for many others (thanks to the fact that you actually released your work, unlike certain others at the time...), and frankly, if it works, who cares what the code looks like? I just got to the point where 1) I wanted to write my own for the sake of experience, and 2) I couldn't quite figure out how to get yours to do the one extra thing I wanted, so it became easier to just write my own.
I'm almost positive that's not the case. I only have 1 hook (other than the crystal fix, but the bug occurs without that code present), and it's in exactly the same place as yours, right at the beginning of NMI (well, not exactly, it's one byte earlier so I could take advantage of the 16-bit mode for faster ID checking). Also, I experienced exactly the same bug, with the black square in exactly the same place, using your code, but I was able to alleviate it by shortening one of the code paths. I'm not sure where the offending code path is in mine, but I'll poke around a bit...Conn wrote:Maybe you overwrote an register or hooked in a routine that must not be interrupted...
As far as your hack goes, do whatever you want, I'm just putting this out there. I'll probably use it in my DX patch if I ever do another update, but only if there's some other reason to update (like possibly adding this patch). No reason to replace your code if you don't want to. If it ain't broke, and all that... but if you want it, it's freely available. For anybody else wanting to add this to their own hack, this is probably the better choice, simply because there's only the two hooks, so less chance of unintended side effects when mixing with other code.
I'm not in anyway trying to bash your work, Conn. Your patch was the catalyst for many others (thanks to the fact that you actually released your work, unlike certain others at the time...), and frankly, if it works, who cares what the code looks like? I just got to the point where 1) I wanted to write my own for the sake of experience, and 2) I couldn't quite figure out how to get yours to do the one extra thing I wanted, so it became easier to just write my own.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
Ok, I managed to rework the volume fade code to fail-fast, which fixed the title screen. I'll update the original post shortly. Now, the only issue I know of is that if you have a track fall back to SPC, then load an MSU track, the MSU starts playing faster than the SPC fades out, which causes overlap. More timing tweaks...
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
Aaaaaaaand that extra little surprise I was working on "just works" with the new code. I love when that happens
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
Congratulations
If you get more experienced, I'd rather suggest however to create msu1 patches for games that do not feature this yet from the msu1 wishlist, like Donkey Kong1, Street FighterII, Super Mario Kart etc.
Of course I do not see your work as bashing mine or concurence! I am happy if someone develops it further (like Colines with SMW plus) and you with DX. It's just that I am too tired and retired to adapt your code and change all my files (all-in and such) and again playtesting, release at romhacking, etc. Your code is definitively better but instead of replacing my code with it, I suggest a parallel release due to the reasons.I'm not in anyway trying to bash your work, Conn. Your patch was the catalyst for many others (thanks to the fact that you actually released your work, unlike certain others at the time...), and frankly, if it works, who cares what the code looks like? I just got to the point where 1) I wanted to write my own for the sake of experience, and 2) I couldn't quite figure out how to get yours to do the one extra thing I wanted, so it became easier to just write my own.
If you get more experienced, I'd rather suggest however to create msu1 patches for games that do not feature this yet from the msu1 wishlist, like Donkey Kong1, Street FighterII, Super Mario Kart etc.
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
I'm actually hoping to tackle the FMV's in Chrono Trigger next (current hacks only implement the first one, none of the in-game ones). No promises, that's a really big project, not to mention just the sheer amount of gameplay involved just to *get to* the right place in the game to test things... but we'll see.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
I've updated the OP with the fixed code. I still need to do a full playtest run through aLttP to confirm that everything works, but so far I've tested everything I can think of. I may add one extra hook to the ending sequence to allow me to use the aLBW track that I want to, which is about 3 seconds longer than the original, and ends up getting cut off, so I'd like to add a wait-until-track-completes routine there, we'll see if I can figure that out.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
I've added the ending sequence wait. Only really useful if your track 33 is longer than the original, which mine is by a few seconds. I'm about halfway through my playtest, and so far haven't encountered any issues, so that's always nice.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
One question qwertymodo, is there an easy way to implement a fade-out? Do you lower the volume with each nmi or is there something else one can do?
I ask since I probably will need to make a fade out for AST week4, in case you switch to the bad end, and the only solution I have is a nmi- dependent music lowering (like my alttp code works). Which is sophisticated to code, and also runtime-consuming; and you need a different lowering rate for sd2snes and emulation (since the both systems have a different global music volume level).
I ask since I probably will need to make a fade out for AST week4, in case you switch to the bad end, and the only solution I have is a nmi- dependent music lowering (like my alttp code works). Which is sophisticated to code, and also runtime-consuming; and you need a different lowering rate for sd2snes and emulation (since the both systems have a different global music volume level).
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
Do you guys have a recommended emulator version of bsnes I should use for LoZ3 MSU? I've been using 0.70 so far.
Zanak- Snap Dragon
- Since : 2016-04-28
Re: New, simplified LoZ3 MSU-1 code
That's the best I think. I also only recommend this one. High compatible, xml, pcm. Only flaw, it has no spc fallback
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
That explains why there's no sound when the MSU fails to work. I was considering using the latest version of higan, but after I saw where he was going with the emulator, I didn't see the point. I do appreciate his mission though, to preserve the snes the best he can.
Zanak- Snap Dragon
- Since : 2016-04-28
Re: New, simplified LoZ3 MSU-1 code
I also can retrace byuu's ambitions but for the players and hackers, this is close to the edge.
Here's just what the users of msu1 do need to deal with:
bsnes until v.70: xml, header/non header
bsnes ff.: xml, restricted to non-headered rom, sphisticated game import
higan v.94: bml, non-header, some strange folder to store the pcm:s into
higan v.97: no more bml. msu file must be named to msu1.rom, tracks must be named track-x.pcm (since you cannot set the name in the bml anymore
sd2snes: no so much changes, but also playback rate changed in 0.1.7, which caused problems with the bszelda/ast project.
So, play bsnes v70: one xml, pcm_s in the same folder and all is fine
I asked byuu to code the spc fallback to bsnes v70, but failed. Maybe you have more luck? Should be 5 lines of code (which he has in his documents) and a recompilation....
Here's just what the users of msu1 do need to deal with:
bsnes until v.70: xml, header/non header
bsnes ff.: xml, restricted to non-headered rom, sphisticated game import
higan v.94: bml, non-header, some strange folder to store the pcm:s into
higan v.97: no more bml. msu file must be named to msu1.rom, tracks must be named track-x.pcm (since you cannot set the name in the bml anymore
sd2snes: no so much changes, but also playback rate changed in 0.1.7, which caused problems with the bszelda/ast project.
So, play bsnes v70: one xml, pcm_s in the same folder and all is fine
I asked byuu to code the spc fallback to bsnes v70, but failed. Maybe you have more luck? Should be 5 lines of code (which he has in his documents) and a recompilation....
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
I implemented fade the same way you did, within the NMI. The only difference is that I dedicated separate "current volume" and "target volume" variables, so you could fade in, fade out, or fade to half. If you want to fade, set the target volume, and it does the fade for you (I separated the increment and decrement sizes, because I only wanted a slow fade out, but a rapid fade in). Take a look at my do_fade block. The commented out line is if you wanted to cut the fade out short the way your code does. Otherwise, it stops playback once the current volume reaches 0 (and it properly handles over/underflow so you don't get wraparound).
If you wanted to do an instant volume jump (e.g. immediately initialize to full volume, you would just want to set both the current volume and target volume to the same value, and then write that value to $2006 as well.
My code does clobber A and X, as well as assumes that you enter msu_main with 16-bit A and X, then switches to 8-bit, so keep that in mind. Because of where I placed the jump in the LoZ3 NMI routine, I was able to do that without any side effects, but YMMV.
If you wanted to do an instant volume jump (e.g. immediately initialize to full volume, you would just want to set both the current volume and target volume to the same value, and then write that value to $2006 as well.
My code does clobber A and X, as well as assumes that you enter msu_main with 16-bit A and X, then switches to 8-bit, so keep that in mind. Because of where I placed the jump in the LoZ3 NMI routine, I was able to do that without any side effects, but YMMV.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
I see, thanks. BTW: is your asm for sd2snes only (define VAL_VOLUME_FULL(#$FF) )? bsnes/higan best adjustment is 60 I think. This makes the fade-out/in problematic since the target volume is reached much faster in bsnes/higan. I am no perfectionist, so in my patch I left it this way and didn't adjust the increment/decrement rate. I think for the players it is no much difference whether the target is reached in 4 seconds or 2.
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
I use FF as full volume. If the tracks sound too loud at FF, then the PCM files should have been normalized to a lower volume. Adjusting the volume in higan is solving the wrong problem. However, if you want to use 60 as full volume, then you would also want to adjust half volume to 30, and then adjust the increment/decrement values as well, but everything should work just fine with those adjustments. Also, it's worth mentioning that the code location I picked is unused in aLttP, but it definitely is used by some other hacks (PW, for one). So that's why I'm only uploading the asm here, no IPS. It's written for bass v14.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
Yes, that's what I did (half volume at map and such is 30 then on higan). Well it works with the adjustment and for players it is surely easier to apply a patch instead lowering the global volume. So for me it is solving the right problem. With FF and normal pcm:s (like those I offer) you do not hear a sfx anymore in higan.
Conn- Since : 2013-06-30
Re: New, simplified LoZ3 MSU-1 code
I just came across at least one more special case I need to handle (light world pendants are handled separately from dark world crystals). I should probably check all of the other non-looping tracks to be sure they don't also have a "wait-until-track-is-done" check. So maybe mine won't be quite as compact as I originally hoped, but at the very least, I know I don't need separate hooks for the half volume house/map/bird call, or for the fairy fountain.
As far as the volume thing goes, the problem is that it's the SD2SNES that's wrong, not higan. So, to compensate for the SD2SNES, the PCM's get recorded too loud. So now you have the hardware too soft and the files too loud, when the correct solution was to record the PCM's at the right volume to begin with, and for the SD2SNES to actually use the right amplification settings, but at this point, I'm not sure if that's even possible.
As far as the volume thing goes, the problem is that it's the SD2SNES that's wrong, not higan. So, to compensate for the SD2SNES, the PCM's get recorded too loud. So now you have the hardware too soft and the files too loud, when the correct solution was to record the PCM's at the right volume to begin with, and for the SD2SNES to actually use the right amplification settings, but at this point, I'm not sure if that's even possible.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
RE: MSU-1 volume. It looks like ikari increased the MSU-1 volume with release v1.7. I need to test out how much that actually increases things, but if it manages to be on par with higan, then we really need to get rid of the whole separate volume patches thing and use $FF as max volume. Existing tracks should be normalized in the files themselves. I'll update when I get around to testing.
qwertymodo- Since : 2014-10-21
Re: New, simplified LoZ3 MSU-1 code
Woops, I left a PW-specific check in there. It probably wouldn't have affected anything in aLttP, but I removed it for the sake of clarity.
qwertymodo- Since : 2014-10-21
Page 1 of 3 • 1, 2, 3
Similar topics
» Code help
» right code for music?
» MSU1 Code Library
» Commented Code Snippets
» Brake pots with asm (new code)
» right code for music?
» MSU1 Code Library
» Commented Code Snippets
» Brake pots with asm (new code)
Page 1 of 3
Permissions in this forum:
You cannot reply to topics in this forum