I thought I'd see if I can have the arcade board's AY-3-8912 make some beeps.

But I need to have some delays or it doesn't work. Without delays everything happens all at once... so let's fiddle some more with coroutines.

The advantage of this is that we can call a delay() function.

So for example if you want

Code
for i = 1,60 do
  sound(7,24)
  settonevol(0,175,15)
  delay(2)  -- delays for 2 frames
  settonevol(0,175,0)
  delay(2)
end

then you call:

Code
add_func_string([[local i; for i=1,30 do sound(7,24); settonevol(0,175,8); delay(2); settonevol(0,175,0); delay(2); end ]])

and what's cool is that you can enter little tests from the command line quite easily with add_func_string.

Code

-- ===========================================================================
-- FRAME DISPATCHER

dispatch_list={}

function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end


function dispatch_list_remove(a_func)
for my_index,my_func in pairs(dispatch_list) do if my_func == a_func then table.remove(dispatch_list,my_index) end end
end

function print_dispatch_list() for my_index,my_func in pairs(dispatch_list) do print(my_func) end end

print("type cld() and hit enter to stop a runaway dispatch")

if already_registered_frame_dispatcher == nil then
   emu.register_frame(frame_dispatcher);
   already_registered_frame_dispatcher = 1
end

function cld()
dispatch_list = {}
end


-- ===========================================================================
-- COROUTINE DISPATCHER

coroutine_frame_list = { }

function coroutine_frame_dispatch()
local i,thread
  for i,thread in pairs(coroutine_frame_list) do coroutine.resume(thread) end
  for i = #coroutine_frame_list,1,-1 do if coroutine.status(coroutine_frame_list[i]) == "dead" then table.remove(coroutine_frame_list,i) end end
end

function delay(frames)
  local f
  for f = 1,frames do coroutine.yield() end
end

function add_func_exec(myfunc)
local newthread
  newthread = coroutine.create(myfunc)
  table.insert(coroutine_frame_list,newthread)
end

function add_func_string(func_string)
local newfunc
  newfunc = assert(loadstring(func_string))
  if newfunc ~= nil then add_func_exec(newfunc) end
end 




function addco()
-- once you clear your dispatch list, you must add the coroutine_frame_dispatch
-- to get the coroutine_dispatch to work
table.insert(dispatch_list,coroutine_frame_dispatch)
end


cld()
addco()


function lobyte(x)
 return x & 255
end
function hibyte(x)
  return (x & (255<<8))>>8
end

function checkrange(x,lo,hi)
if not(x >= lo and x <= hi) then print("checkrange failed ",x,lo,hi); return false 
else return true; end
end


aystr = ":sl7:ssprite:ssprite_ay"
aystr = ":sl4:arcbd:arcbd_ay"

function sound(regnum,value)
emu.item(manager:machine().devices[aystr].items["0/m_regs"]):write(regnum,value)
end



function settone(chan,tone)
  if checkrange(chan,0,2) then
    regnum = chan*2  
    sound(regnum,lobyte(tone))
    sound(regnum+1,hibyte(tone))
  end
end

function setvol(chan,vol)
  if checkrange(chan,0,2) then
    regnum = chan+8  
    sound(regnum,vol)
  end
end

function settonevol(chan,tone,vol)
  settone(chan,tone)
  setvol(chan,vol)
end

-- two different ways to add a function, pass a function to add_func_exec
-- or pass add_func_string a string and if you use double brackets you don't have to escape the quotes

add_func_exec(function () local i; for i = 1,10 do print("yoyo",i);delay(5);end end)

add_func_string("local i; for i=1,15 do print(\"hello\",i);delay(5); end")


-- sound(7,24) turns on sound ABC and turns off the noise channels

add_func_string([[local d; local i; for d = 1,4 do print("delay="..d) for i=1,30 do sound(7,24); settonevol(0,175,8); delay(d); settonevol(0,175,0); delay(d); end end ]])



Last edited by Golden Child; 11/07/17 09:06 AM.