Log In  

Hi all,

New here... just discovered this wonderful system yesterday... I still haven't experimented with actual game development on the platform, but did try the music tracker to check out its possibilities...

While dabbling around with a simple idea for a song with different parts, I assumed I could define each part as a self contained loop and then from the code just switch parts as appropiate. For example: play the first part twice, then the second part twice and then the third part once.

But when I went to search how that could be done I found no simple answer so I gave it a try and made two methods that both seem to work:

  1. Keep track of what pattern is playing and for how long and just when it's about to end use the music command to start playing the next part of the song. As the ticks received from the stat(56) change in jumps (the timing of music playing seems to be different than the one for the update function) you can't wait right unitl the end of the pattern, so I guess sometimes the jump might be noticeable. But the advantage is that you can switch to any other pattern freely...

Cart #pibuwiyego-2 | 2023-10-29 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

  1. Keep track of what pattern is playing and dynamically change the loop start/end flags using the poke command to keep looping a part until you want to go to the next part. This has the advantage that the timing is perfect but you can't structure your song freely. You always either go back to the begining of the current part or let it run into the next one.

Cart #niwowufopo-2 | 2023-10-29 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

I put all the code into a function that initializes everything and retuns its own songupdate function to be called from _update, so it should be a matter of pasting it and defining the structure.

Right now the speed has to be manually entered and be the same for the whole song. I guess it'd be possible to get it from memory for each pattern...

Last, in the first method you have to set the loop flags on the tracker to define each section of the song, then define just the starting patterns for each section on the initial table. With the second method no loop flags should be set on the tracker and you define each section with the starting and ending pattern, adding a last section used to set the flags to go back to the begining of the song after it ends

Let me know if there're other ways of acomplishing this or any problems you might see...

P#136566 2023-10-29 01:27 ( Edited 2023-10-29 12:52)

To get the speed for each playing pattern:

function getspeed(p)
    adr=0x3100+p*0x4
    sfx=@(adr) & 0000000000011111
    return @(0x3200 + 68*sfx + 65)
end

It assumes the first track is active on the tracker...

Here's the whole code for case 1 (case 2 doesn't really need the speed):

function _init()
    -- define song structure
    -- each section has 
    -- start pattern number
    -- times to play
    -- times played
    msections={{0,2,0},{2,2,0},{4,1,0}}
    initsong(msections)
end

function initsong(msections)
    local playing=1

    function getspeed(p)
        adr=0x3100+p*0x4
        sfx=@(adr) & 0000000000011111
        return @(0x3200 + 68*sfx + 65)
    end

    function songupdate()
        local p=stat(54)
        local t=stat(56)
        -- check if this is the last
        -- pattern
        last=peek(0x3100+p*0x4+0x1)>=128
        if last then
            if t>(getspeed(p)*32)-5 then
                msections[playing][3]+=1
            end
            if msections[playing][3]==msections[playing][2] then
                msections[playing][3]=0
                playing+=1
                if playing>#msections then
                    playing=1
                end
                music(msections[playing][1])
            end
        end
    end
    music(msections[playing][1])
end

function _update()
    p=stat(54)
    t=stat(56)
    songupdate()
end

function _draw() 
cls()
print("pat:"..p.." - t:"..t)
end

And the updated code for case 2:

function _init()
    cls()
    -- define song structure
    -- each section has 
    -- start pattern number
    -- end pattern number
    -- times to play
    -- last section is the whole
    -- song, to go back to the
    -- start when finished
    msections={{0,1,2},{2,3,2},{4,5,1},{0,5,1}}
    songupdate=initmusic(msections,0)
end

function initmusic(msections)
    local playing=1
    local times=0
    local changed=false

    -- a should be true or false
    -- to set the flag or remove it
    function changeloop(s,a)
        adds=0x3100+msections[s][1]*0x4
        adde=0x3100+(msections[s][2]*0x4)+0x1
        vs=peek(adds)
        ve=peek(adde)
        if a then
            poke(adds,vs | 0b10000000)
            poke(adde,ve | 0b10000000)
        else
            poke(adds,vs & 0b1111111101111111.1111111111111111)
            poke(adde,ve & 0b1111111101111111.1111111111111111)
        end
    end

    function songupdate()
        local p=stat(54)
        last=p==msections[playing][2]
        if last then
            if not changed then
                times+=1
                changed=true
            end
            if times==msections[playing][3] then
                times=0
                changeloop(playing,false)
                playing+=1
                if playing>#msections-1 then
                    changeloop(playing,true)
                    playing=1
                    changeloop(playing,true)    
                else
                    changeloop(playing,true)
                end
            end
        else
            changed=false
        end
    end

    -- init:
    changeloop(playing,true)
    music(msections[playing][0])
    return songupdate
end

function _update()
    songupdate()
end

function _draw() 
    cls()
    p=stat(54)
    t=stat(56)
    print("pat:"..p.." - t:"..t)
end

I've updated the carts too...

P#136579 2023-10-29 12:50 ( Edited 2023-10-29 12:54)

[Please log in to post a comment]