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...

2


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...



[Please log in to post a comment]