Skip to content

Instantly share code, notes, and snippets.

@amacdougall
Last active September 12, 2021 01:03
Show Gist options
  • Save amacdougall/409e5bae2ac3517ce529ab23238ac587 to your computer and use it in GitHub Desktop.
Save amacdougall/409e5bae2ac3517ce529ab23238ac587 to your computer and use it in GitHub Desktop.
Simple song player utility for PICO-8
songs = (function()
local music_address = 0x3100 -- in cartridge ram
local music_data = {} -- store original music ram bytes
for offset = 0, 255 do
music_data[offset] = peek(music_address + offset)
end
function set_control_bit(byte, value)
return value > 0 and byte | 0b10000000 or byte & 0b01111111
end
return {
-- Given a list of pattern numbers, plays those patterns in order. If the
-- optional loop_points parameter is given, applies loop_start and loop_end
-- flags to the patterns at those indices; otherwise, stops at the end.
--
-- Example: play({10, 14, 14, 9}) -- play 10, then 14 twice, then 9, and stop
-- Example: play({8, 9, 10, 11, 12}, {2, 4}) -- plays 8, then loops 9, 10, 11
-- note that in the second example, 12 is never reached!
--
-- Implemented by "flashing" the music ram from the data stored during init().
play = function(patterns, loop_points)
for p_index = 1, #patterns do
local pattern_offset = patterns[p_index] * 4
for b_offset = 0, 3 do
local b = set_control_bit(music_data[pattern_offset + b_offset], 0)
if loop_points then
if p_index == loop_points[1] and b_offset == 0 then
b = set_control_bit(b, 1) -- loop start
end
if p_index == loop_points[2] and b_offset == 1 then
b = set_control_bit(b, 1) -- loop end
end
elseif p_index == #patterns then
b = set_control_bit(b, 1) -- stop
end
local address = music_address + (p_index - 1) * 4 + b_offset
poke(address, b)
end
end
-- begin playing the newly configured music
music(0)
end
}
end)()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment