
I wanted to experiment with modifying SFX data via a cart.
Features:
- Compose and edit music
- Copy and Paste selections within patterns and between patterns
- Transpose selection by octaves
- Save to cart
Known issues:
- Modifying selections only works if the selection was made in a leftwards direction.
- The music staff isn't actually accurate at all. It just uses one px per semitone.
- Green play line isn't always accurate if you've changed the speed or pattern length, restarting playback fixes it.
SFX Data Layout for anyone interested:
Starting from 0x3200
Blocks of 68 bytes for each SFX pattern 64 bytes of sound data and then 4 bytes of metadata.
Each sound data chunk is made of a 16 bit value divided into
6 bits for the note, 3 bits for the instrument, 3 bits for the volume, 3 bits of the FX, 1 bit unused.
0bUFFFVVVIIINNNNNN
byte 65 is the speed
byte 66 is loop start
byte 67 is the loop end


Okay, honest question here about the way speed works. I've got a boss fight where I want the music to increase in speed as he takes damage, but when you modify the speed of all tracks while the music is playing, the current measure runs for as long as the old speed. So if the delay is decreased and notes play faster, there's a silent pause for a bit until the next measure starts up. And if the delay is increased then the last few slower notes get cut off and the next measure starts early.
Is there another place in memory where the current pattern speed/delay is stored, probably calculated as the max of the four tracks speed * 32 notes? Can I access this so the current measure timing gets updated?
For now I'm checking the current note index via stat(20)==31, and only updating the track speeds on that last note so it has a very short silence or cutoff on the last note. But there has to be a better way!


@Shazang I know! what I really like about pico8 is how quick it is to go from an idea to a working prototype, to a useful thing.
@innomin good question! I'm not sure how that music stuff works, might need to ask zep.
good to know about stat(20) though!


Why yes, this game does need mouse input!
p8: http://codepad.org/OeRl6oIq
Here's the patch:
3a4,23 > > mouse = { > init = function() > poke(0x5f2d, 1) > end, > -- return int:x, int:y, onscreen:bool > pos = function() > local x,y = stat(32)-1,stat(33)-1 > return stat(32)-1,stat(33)-1 > end, > -- return int:button [0..4] > -- 0 .. no button > -- 1 .. left > -- 2 .. right > -- 4 .. middle > button = function() > return stat(34) > end, > } > 7c27,28 < handx,handy=0,0 --- > mouse.init() > handx,handy=mouse.pos() 213,216c234 < if btn(0) then handx-=(fast and 2 or 1) end < if btn(1) then handx+=(fast and 2 or 1) end < if btn(2) then handy-=(fast and 2 or 1) end < if btn(3) then handy+=(fast and 2 or 1) end --- > handx,handy = mouse.pos() |


Amazing, will definitely try using this instead of the sfx editor. I actually had a similar idea (something more akin to a MIDI sequencer) but this is way better than what I had in mind.
[Please log in to post a comment]