That was kind of the idea. Though I don't really have much experience with other trackers so I was just going to approach this as "the kind of editor I would want to use if i was using this". Though that might not be the best idea because existing trackers might be better than what I'm imagining.
But whatever. It's a funsie project. If it ends up being crappy I can update it later with better ideas. Or not. Whatever. =P
This is all step 10 though. I'm still on step 2.
As for import/export: no idea. Hadn't originally planned on it, but since it's popular maybe I'll consider it. But that's like step 14.
March 15, 2014, 10:39:02 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
So... here's the data on the musical score in Secret of Mana, based on what I've searched within the past few days:
00-B3 are tones
B4-C2 is sustain
C3-D1 is rest.
For all of the above, value%15 is the length of the note (run through a lut to get length in clocks)
For tones, the note (C, C#, D, etc) is determined by value/15. Where 0=C, 1=C#, 2=D, 3=D#, etc
Other values are 'commands' as illustrated below.
D2 aa = write aa to FC01+X Set volume to 'aa'
zero FC00+X disable/stop vol fading
D3 aa bb = fade to volume 'bb' over 'aa' updates
'bb' is the target volume
'aa' is time delay (higher values = slower fade)
D4 aa = write aa to FC41+X Set Pan to 'aa'
zero FC40+X disable/stop pan fading
D5 aa bb = fade to pan 'bb' over 'aa' updates
'bb' is the target pan
'aa' is time delay (higher values = slower fade)
D6 aa bb = write aa+1 to FCC1+X ???
write bb to 0120+X ??? not sure what this does.
causes some kind of eventual update
D7 aa bb cc = write aa to 0160+X depth?
write bb+1 to FCA0+X set vibrato counter reload value to bb+1
write 1 to FCE0+X set vibrato counter to 1 so it updates immediately
write cc to 0121+X set vibrato enable/phase selection
Enable/disable vibrato and set phase/rate (but not depth? Unless 0160 is depth?)
aa = ?vib depth?
bb = rate (00 = fastest, FF = slowest)
cc = enable/phase selection
D8 = disable vibrato (by writing 0 to 0121+X)
D9 aa bb cc = write aa to 0161+X depth?
write bb+1 to FCA1+X set tremolo counter reload value to bb+1
write 1 to FCE1+X set tremolo counter to 1 so it updates immediately
write cc to 0140+X set tremolo enable/phase selection
same as D7, but tremolo instead of vibrato
DA = disable tremolo by writing 0 to 0140+X
DB aa bb = ??? $0763 complex. Uses a lot of things I don't have ID'd yet: FCC0, FD00, FDA0, FDA1, 0141, FDE0, FDE1
DC = ??? $07B4 Zero's 0141, FDE0, FDE1
DD aa = Sets noise freq to aa & 0x1F. Does not enable/disable noise for this channel, it's just a pitch change
DE = Enable noise for this channel
DF = Disable noise for this channel
E0 = Enable Mod for this channel
E1 = Disable Mod for this channel
E2 = Enable Echo for this channel
E3 = Disable Echo for this channel
E4 aa = Set octave
E5 = Increment octave
E6 = Decrement octave
E7 aa = Set current key change value to 'aa' (00 = normal key, 01 = C becomes C#, 02 = C becomes D, etc)
E8 aa = Modify current key change value by 'aa' ('aa' is added to current key change)
E9 aa = ??? $09B0 --- sets FD40+X and exits. Not sure what that var is for. Used in pitch calculations.
EA aa = write aa to 5D+X = current instrument as written to reg.. and does a few other things:
copy 16 bit ptr from 1800+aa -> FD20+X ( ??? )
copy 16 bit ptr from 1880+aa -> FE80+X (resets ADSR data to instrument defaults)
EB aa = Sets attack rate to 'aa' & 0x0F
FE80+X = FE80+X & 0x70 | ('aa' & 0x0F) | 0x80
EC aa = Sets decay rate to 'aa' & 0x07
ED aa = Sets the sustain level to 'aa' & 0x07
EE aa = Sets the sustain rate to 'aa & 0x1F
EF = Reset ADSR values to instrument defaults
F0 aa = ??? $0944: increments 5C+X, then does a bunch of other crap
no idea what it's doing ???
F1 = ??? $096B: decrements 5C+X, then other stuff. No idea ???
F2 = $09BC ??? -- kills return address from stack and does a lot of heavy calls. End music/sfx maybe?
F3 aa = $0620 ??? -- if sfx, this is a NOP
for music: $7D = 'aa'
$7C = 0
$80 = 0
F4 aa bb = $062D ??? no freaking idea. Uses 80,81,82. Fairly complex
F5 aa = $06B3 - NOP (goes right to RET), 'aa' is unused
F6 aa bb = $06B0 - NOP. 'aa' and 'bb' are unused
F7 aa bb = $0733 - NOP. 'aa' and 'bb' are unused
F8 aa = Sets music master volume (FF = normal, 00 = silent). Does not apply to 'special' instrument
see $00AC variable description (all this command does is assign that var)
F9 aa bb cc = $0917 - NOP for sfx.
For music, a conditional jump. 'aa' is a loop counter, and 'ccbb' forms the address (add 6,7 to it just
like with the FA command)
The thing that's weird is that it's backwards. You only jump WHEN the loop counter reaches the given value.
I would expect it to jump UNTIL the loop counter reaches the value
Also, the loop counter doesn't get reset by this command. See command FC.
FA aa bb = $0905 NOP for sfx.
For music... Standard jump. $0C,D+X = bbaa + $06,7
jump to bbaa + [$06,7]. Not sure what significance
6,7 is, but in the track it is fixed at $E233 ???
FB aa bb = $0995 NOP for sfx. For music... conditional jump to bbaa + $06,7
jump only if the channel has its chan bitmask set in var $C4
Once jump is taken, that bit in C4 is cleared. Not sure if/how C4 can be set again. ???
FC = $093A NOP for sfx. For music, zero out the loop counter.
FD aa = $09B4 NOP for sfx. For music, sets special instrument ID (assigns $FF88). See $FF88 and $00AC description for details
FE = $09BC - same as F2
FF = $09BC - same as F2
A few other notes:
- Vibrato and Tremolo seem to be broken due to a bug in how they get initialized when a tone starts. The bug should be easy to fix, I just have to get around to doing it (and testing it out).
- 'Mod' enable is similar to Vibrato but uses the SPC's built-in "modulation" function rather than manually adjusting the pitch. This has many downsides over the manual vibrato: 1) it doesn't work on voice 0. 2) It doesn't work if the previous voice is inaudible. 3) You don't have control over things like rate/depth.
- All jump addresses in the SPC seem to be offset by a fixed amount. This amount is stored at $0006,7 in SPC memory. For the track I was examining (A Curious Tale), this value was fixed at $E233. I haven't checked but this probably varies per song and the value at 06,7 changes depending on where the score data resides in the SNES. That way addresses are relative to SNES memory rather than SPC memory.
- Sound effects (sfx) appear to use the exact same code as music. With a few differences... the biggest being that some commands (mainly jumps) are NOPs for sfx and only work for music.
- The conditional jump commands don't make any freaking sense. My test SPC didn't use any of them. I wouldn't be surprised if no songs in the game use them. They're totally asinine.
- On the SPC there is only one noise generator... so setting the noise freq (command DD) on one channel affects it for all channels. The music engine keeps track of music and sfx settings separately... and will use the music setting only if no sfx are currently playing anything with the noise.
I'm probably going to start on the editor next... to see if I can load up and play sounds from the ROM. We'll see how it goes. Wish me luck!