Code quality fixes
This commit is contained in:
		
							
								
								
									
										191
									
								
								engine.lua
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								engine.lua
									
									
									
									
									
								
							| @@ -1,191 +0,0 @@ | ||||
| function klass() | ||||
|  local k={} | ||||
|  k.__index=k | ||||
|  function k:new(...) | ||||
|   local n={} | ||||
|   setmetatable(n,k) | ||||
|   n:init(...) | ||||
|   return n | ||||
|  end | ||||
|  return k | ||||
| end | ||||
|  | ||||
| song=klass() | ||||
| function song:init() | ||||
|  self.frames={} | ||||
|  self.ix_to_frame={} | ||||
|  self.next_frame_start=0 | ||||
| end | ||||
| function song:add(len) | ||||
|  for i=0,len-1 do | ||||
|   self.ix_to_frame[self.next_frame_start+i]={#self.frames+1,i} | ||||
|  end | ||||
|  add(self.frames,{ | ||||
|   pattern:new({len=len}), | ||||
|   pattern:new({len=len}), | ||||
|   pattern:new({len=len}), | ||||
|   pattern:new({len=len}), | ||||
|  }) | ||||
|  self.next_frame_start+=len | ||||
| end | ||||
| function song:pattern(channel,offset) | ||||
|  offset = offset or -1 | ||||
|  channel &= 0xffff | ||||
|  offset &= 0xffff | ||||
|  assert(channel>=0 and channel<4, "channel must be [0,4)") | ||||
|  local n_frames_long=#self.frames | ||||
|  if offset<0 then | ||||
|   assert(offset>=-n_frames_long, "offset must not exceed -"..n_frames_long) | ||||
|   offset+=n_frames_long+1 | ||||
|  else | ||||
|   assert(offset>=0 and offset<n_frames_long) | ||||
|   offset+=1 | ||||
|  end | ||||
|  return self.frames[offset][channel+1] | ||||
| end | ||||
| function song:plot(channel,offset,instant) | ||||
|  assert(channel>=0 and channel<4, "channel must be [0,4)") | ||||
|  local tup=self.ix_to_frame[offset] | ||||
|  assert(tup, "invalid offset for current length: "..offset)  | ||||
|  local f,offset=unpack(tup) | ||||
|  self.frames[f][channel+1]:plot(offset, instant) | ||||
| end | ||||
|  | ||||
| function song:build( | ||||
|  free_patterns, | ||||
|  frame_a, | ||||
|  frame_z | ||||
| ) | ||||
|  local n_frames_long = #self.frames | ||||
|  if (not frame_z) frame_z = frame_a + n_frames_long | ||||
|  assert(frame_z-frame_a == n_frames_long, "wrong number of frames (must be "..frame_a.." to "..frame_a+n_frames_long..")") | ||||
|  | ||||
|  -- dump patterns and frames | ||||
|  mapped_patterns={} | ||||
|  function map_to_real_pattern(pat) | ||||
|   if (pat:silent()) return 0 | (1<<6) | ||||
|  | ||||
|   local key = pat:key() | ||||
|   mapped_patterns[key] = mapped_patterns[key] or {} | ||||
|   for other in all(mapped_patterns[key]) do | ||||
|    if (pat:eq(other)) return other.map_ix | ||||
|   end | ||||
|   assert(#free_patterns>0, "out of free patterns") | ||||
|   pat:map_to(deli(free_patterns,1)) | ||||
|   add(mapped_patterns[key],pat) | ||||
|   return pat.map_ix  | ||||
|  end | ||||
|  | ||||
|  local fmaddr=0x3100+(frame_a)*4 | ||||
|  for frame=1,n_frames_long do | ||||
|   for i=1,4 do | ||||
|    poke(fmaddr+i-1,map_to_real_pattern(self.frames[frame][i])) | ||||
|   end | ||||
|   fmaddr+=1 | ||||
|  end | ||||
| end | ||||
|  | ||||
| pattern=klass() | ||||
| function pattern:init(o) | ||||
|  speed = o.speed or 15 | ||||
|  len = o.len or 32 | ||||
|  noiz = o.noiz or 0 | ||||
|  buzz = o.buzz or 0 | ||||
|  detune = o.detune or 0 | ||||
|  reverb = o.reverb or 0 | ||||
|  dampen = o.dampen or 0 | ||||
|  editormode = true | ||||
|  | ||||
|  assert(speed >= 1 and speed <255, "speed must be [1,255)") | ||||
|  assert(len >= 1 and len < 33, "len must be [1,33)") | ||||
|  assert(noiz >= 0 and noiz < 2, "noiz must be [0,2)") | ||||
|  assert(buzz >= 0 and buzz < 2, "buzz must be [0,2)") | ||||
|  assert(detune >= 0 and detune < 3, "detune must be [0,3)") | ||||
|  assert(reverb >= 0 and reverb < 3, "reverb must be [0,3)") | ||||
|  assert(dampen >= 0 and dampen < 3, "dampen must be [0,3)") | ||||
|  | ||||
|  self.instants={} | ||||
|  self.len=len  | ||||
|  -- https://pico-8.fandom.com/wiki/Memory#Music | ||||
|  self.speed=speed | ||||
|  self.pattern_flags=( | ||||
|   ( | ||||
|    tonum(editormode) | | ||||
|    noiz<<1 | | ||||
|    buzz<<2 | ||||
|   ) +  | ||||
|   detune*8 +  | ||||
|   reverb*24 +  | ||||
|   dampen*72 | ||||
|  ) | ||||
|  | ||||
|  for i=0,self.len-1 do | ||||
|   self.instants[i]=0 | ||||
|  end | ||||
| end | ||||
| function pattern:plot(ix, iat) | ||||
|  assert(ix>=0 and ix<self.len, "index invalid") | ||||
|  self.instants[ix]=encode_instant(iat) | ||||
| end | ||||
| function pattern:silent() | ||||
|  for i=0,self.len-1 do | ||||
|   if (self.instants[i]&0x0e00!=0) return | ||||
|  end | ||||
|  return true | ||||
| end | ||||
| function pattern:key() | ||||
|  local key=0 | ||||
|  for i=0,self.len-1 do | ||||
|   key ^= self.instants[i]<<(i%16) | ||||
|  end | ||||
|  return key | ||||
| end | ||||
| function pattern:eq(other) | ||||
|  if (self.len!=other.len) return  | ||||
|  for i=0,self.len-1 do | ||||
|   if (self.instants[i]!=other.instants[i]) return  | ||||
|  end | ||||
|  return true | ||||
| end | ||||
| function pattern:map_to(ix) | ||||
|  self.map_ix=ix | ||||
|  local at=0x3200+ix*68 | ||||
|  for i=0,31 do | ||||
|   poke2(at+i*2,self.instants[i] or 0) | ||||
|  end | ||||
|  poke(at+64,self.pattern_flags) | ||||
|  poke(at+65,self.speed) | ||||
|  -- start, end | ||||
|  poke(at+66,self.len) | ||||
|  poke(at+67,0) | ||||
| end | ||||
|  | ||||
| function encode_instant(o) | ||||
|  custom = o.c or false | ||||
|  effect = o.e or 0 | ||||
|  volume = o.v or 0 | ||||
|  waveform = o.w or 0 | ||||
|  pitch = o.p or 0 | ||||
|  | ||||
|  assert(custom == false or custom == true, "custom must be true or false") | ||||
|  assert(effect >= 0 and effect < 8, "effect must be [0,8)") | ||||
|  assert(volume >= 0 and volume < 8, "volume must be [0,8)") | ||||
|  assert(waveform >= 0 and waveform < 8, "waveform must be [0,8)") | ||||
|  assert(pitch >= 0 and pitch < 64, "pitch must be [0,64)") | ||||
|  | ||||
|  custom = custom | ||||
|  effect = effect & 0xffff | ||||
|  volume = volume & 0xffff | ||||
|  waveform = waveform & 0xffff | ||||
|  pitch = pitch & 0xffff | ||||
|  | ||||
|  -- not a method: handle the nil instant | ||||
|  -- https://pico-8.fandom.com/wiki/Memory#Music | ||||
|  return ( | ||||
|   (tonum(custom) << 15) | | ||||
|   (effect << 12) | | ||||
|   (volume << 9) | | ||||
|   (waveform << 6) | | ||||
|   (pitch) | ||||
|  ) | ||||
| end | ||||
| @@ -1,8 +1,12 @@ | ||||
| pico-8 cartridge // http://www.pico-8.com | ||||
| version 42 | ||||
| __lua__ | ||||
| #include engine.lua | ||||
| #include song.lua | ||||
| #include shared/_meta.lua | ||||
| #include shared/nflags.lua | ||||
| #include shared/pattern.lua | ||||
| #include shared/pflags.lua | ||||
| #include shared/track.lua | ||||
| #include unique.lua | ||||
| __gfx__ | ||||
| 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
|   | ||||
							
								
								
									
										15
									
								
								shared/_meta.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								shared/_meta.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| function klass() | ||||
|  local k={} | ||||
|  k.__index=k | ||||
|  function k:new(...) | ||||
|   local n={} | ||||
|   setmetatable(n,k) | ||||
|   n:init(...) | ||||
|   return n | ||||
|  end | ||||
|  return k | ||||
| end | ||||
|  | ||||
| function assert_range(i,mn,mx,name) | ||||
|  assert(i >= mn and i < mx, name.." must be ["..mn..","..mx..")") | ||||
| end | ||||
							
								
								
									
										41
									
								
								shared/nflags.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								shared/nflags.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| nflags=klass() | ||||
| function nflags:init(o) | ||||
|  self.c = o.c or 0  -- custom | ||||
|  self.e = o.e or 0 -- effect | ||||
|  self.v = o.v or 0 -- volume | ||||
|  self.w = o.w or 0 -- waveform | ||||
|  self.p = o.p or 0 -- pitch | ||||
|  | ||||
|  self:validate() | ||||
| end | ||||
|  | ||||
| function nflags:validate() | ||||
|  local c,e,v,w,p | ||||
|   =self.c,self.e,self.v,self.w,self.p | ||||
|  | ||||
|  assert_range(c,0,2,"custom") | ||||
|  assert_range(e,0,8,"effect") | ||||
|  assert_range(v,0,8,"volume") | ||||
|  assert_range(w,0,8,"waveform") | ||||
|  assert_range(p,0,64,"pitch") | ||||
| end | ||||
|  | ||||
| function nflags:encode() | ||||
|  self:validate() | ||||
|  local c,e,v,w,p | ||||
|   =self.c,self.e,self.v,self.w,self.p | ||||
|  | ||||
|  c &= 0xffff | ||||
|  e &= 0xffff | ||||
|  v &= 0xffff | ||||
|  w &= 0xffff | ||||
|  p &= 0xffff | ||||
|  | ||||
|  return ( | ||||
|   (c << 15) | | ||||
|   (e << 12) | | ||||
|   (v << 9) | | ||||
|   (w << 6) | | ||||
|   (p) | ||||
|  ) | ||||
| end | ||||
							
								
								
									
										45
									
								
								shared/pattern.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								shared/pattern.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
|  | ||||
| pattern=klass() | ||||
| function pattern:init(p) | ||||
|  self.pflags=pflags:new(p) | ||||
|  | ||||
|  self.nflags={} | ||||
|  for i=0,31 do  -- because the user could change the length | ||||
|   self.nflags[i]=nflags:new{} | ||||
|  end | ||||
| end | ||||
| function pattern:plot(ix, n) | ||||
|  assert_range(ix,0,self.pflags.len,"ix") | ||||
|  self.nflags[ix]=nflags:new(n) | ||||
| end | ||||
| function pattern:silent() | ||||
|  for i=0,31 do | ||||
|   if (self.nflags[i].v!=0) return | ||||
|  end | ||||
|  return true | ||||
| end | ||||
| function pattern:key() | ||||
|  local key=0 | ||||
|  for i=0,self.pflags.len-1 do | ||||
|   key ^= self.nflags[i]:encode()>>(i%16) | ||||
|  end | ||||
|  return key | ||||
| end | ||||
| function pattern:eq(other) | ||||
|  if (self.pflags:encode() != other.pflags:encode()) return | ||||
|  | ||||
|  for i=0,self.pflags.len-1 do | ||||
|   if (self.nflags[i]:encode()!= other.nflags[i]:encode()) return | ||||
|  end | ||||
|  return true | ||||
| end | ||||
| function pattern:map_to(ix) | ||||
|  self.map_ix=ix | ||||
|  | ||||
|  local at=0x3200+ix*68 | ||||
|  poke4(at+64,self.pflags:encode()) | ||||
|  | ||||
|  for i=0,31 do | ||||
|   poke2(at+i*2,self.nflags[i]:encode()) | ||||
|  end | ||||
| end | ||||
							
								
								
									
										53
									
								
								shared/pflags.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								shared/pflags.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| pflags=klass() | ||||
| function pflags:init(o) | ||||
|  self.speed = o.speed or 15 | ||||
|  self.len = o.len or 32 | ||||
|  self.noiz = o.noiz or 0 | ||||
|  self.buzz = o.buzz or 0 | ||||
|  self.detune = o.detune or 0 | ||||
|  self.reverb = o.reverb or 0 | ||||
|  self.dampen = o.dampen or 0 | ||||
|  self.editormode = o.editormode or 1 | ||||
| end | ||||
|  | ||||
| function pflags:validate() | ||||
|  local speed,len,noiz,buzz,detune,reverb,dampen,editormode | ||||
|   =self.speed,self.len,self.noiz,self.buzz, | ||||
|    self.detune,self.reverb,self.dampen,self.editormode | ||||
|   | ||||
|  assert_range(speed,1,255,"speed") | ||||
|  assert_range(len,1,33,"len") | ||||
|  assert_range(noiz,0,2,"noiz") | ||||
|  assert_range(buzz,0,2,"buzz") | ||||
|  assert_range(detune,0,3,"detune") | ||||
|  assert_range(reverb,0,3,"reverb") | ||||
|  assert_range(dampen,0,3,"dampen") | ||||
|  assert_range(editormode,0,2,"editormode") | ||||
| end | ||||
|  | ||||
| function pflags:encode() | ||||
|  local speed,len,noiz,buzz,detune,reverb,dampen,editormode | ||||
|   =self.speed,self.len,self.noiz,self.buzz, | ||||
|    self.detune,self.reverb,self.dampen,self.editormode | ||||
|  | ||||
|  speed &= 0xffff | ||||
|  len &= 0xffff | ||||
|  noiz &= 0xffff | ||||
|  buzz &= 0xffff | ||||
|  detune &= 0xffff | ||||
|  reverb &= 0xffff | ||||
|  dampen &= 0xffff | ||||
|  editormode &= 0xffff | ||||
|  | ||||
|  self:validate() | ||||
|  local byte0 = ( | ||||
|   dampen*72 + | ||||
|   reverb*24 + | ||||
|   detune*8 + | ||||
|   buzz*4 + | ||||
|   noiz*2 + | ||||
|   editormode  -- "in editor mode" flag | ||||
|  ) | ||||
|  return len | speed>>8 | byte0 >>16 | ||||
| end | ||||
|  | ||||
							
								
								
									
										78
									
								
								shared/track.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								shared/track.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| track=klass() | ||||
| function track:init() | ||||
|  self.frames={} | ||||
|  self.ix_to_frame={} | ||||
|  self.next_frame_start=0 | ||||
| end | ||||
| function track:add(len) | ||||
|  for i=0,len-1 do | ||||
|   self.ix_to_frame[self.next_frame_start+i]={#self.frames,i} | ||||
|  end | ||||
|  add(self.frames,{ | ||||
|   pattern:new({len=len}), | ||||
|   pattern:new({len=len}), | ||||
|   pattern:new({len=len}), | ||||
|   pattern:new({len=len}), | ||||
|  }) | ||||
|  self.next_frame_start+=len | ||||
| end | ||||
|  | ||||
| function track:pattern(channel,offset) | ||||
|  offset = offset or -1 | ||||
|  channel &= 0xffff | ||||
|  offset &= 0xffff | ||||
|  | ||||
|  assert_range(channel,0,4,"channel") | ||||
|  local n_frames_long=#self.frames | ||||
|  assert_range(offset,-n_frames_long,n_frames_long,"offset") | ||||
|  if offset<0 then | ||||
|   offset+=n_frames_long | ||||
|  end | ||||
|  return self.frames[offset+1][channel+1] | ||||
| end | ||||
|  | ||||
| function track:plot(channel,offset,inst) | ||||
|  assert_range(channel,0,4,"channel") | ||||
|  assert_range(offset,0,self.next_frame_start,"offset") | ||||
|  local tup=self.ix_to_frame[offset] | ||||
|  assert(tup)  -- should be unable to fail | ||||
|  local frame,offset=unpack(tup) | ||||
|  self.frames[frame+1][channel+1]:plot(offset,inst) | ||||
| end | ||||
|  | ||||
| function track:build( | ||||
|  free_patterns, | ||||
|  frame_a, | ||||
|  frame_z | ||||
| ) | ||||
|  local n_frames_long = #self.frames | ||||
|  if (not frame_z) frame_z = frame_a + n_frames_long | ||||
|  assert(frame_z-frame_a == n_frames_long,  | ||||
|   "wrong number of frames (must be ".. | ||||
|   frame_a.." to "..frame_a+n_frames_long..")") | ||||
|  | ||||
|  -- dump patterns and frames | ||||
|  local mapped_patterns={} | ||||
|  local function map_to_real_pattern(pat) | ||||
|   if (pat:silent()) return 0 | (1<<6) | ||||
|  | ||||
|   local key = pat:key() | ||||
|   mapped_patterns[key] = mapped_patterns[key] or {} | ||||
|   local t = mapped_patterns[key] | ||||
|   for other in all(t) do | ||||
|    if (pat:eq(other)) return other.map_ix | ||||
|   end | ||||
|   assert(#free_patterns>0, "out of free patterns") | ||||
|   pat:map_to(deli(free_patterns,1)) | ||||
|   add(t,pat) | ||||
|   return pat.map_ix  | ||||
|  end | ||||
|  | ||||
|  local fmaddr=0x3100+(frame_a)*4 | ||||
|  for frame=1,n_frames_long do | ||||
|   for i=0,3 do | ||||
|    poke(fmaddr+i,map_to_real_pattern(self.frames[frame][i+1])) | ||||
|   end | ||||
|   fmaddr+=1 | ||||
|  end | ||||
| end | ||||
| @@ -16,7 +16,7 @@ function _draw() | ||||
| end | ||||
| 
 | ||||
| function build_bgm() | ||||
|  local bgm=song:new() | ||||
|  local bgm=track:new() | ||||
| 
 | ||||
|  bgm:add(32) | ||||
| 
 | ||||
		Reference in New Issue
	
	Block a user