pico-8 cartridge // http://www.pico-8.com version 42 __lua__ -- splubp data transport -- by kistaro windrider -- shrinko-8 hints DEBUG = true --[[const]] -- >8 -- utilities -- generate standard "overlay" -- constructor for type tt. -- if tt.init is defined, generated -- new calls tt.init(ret) after -- ret is definitely not nil, -- after calling setmetatable. -- use to initialize mutables. -- -- if there was a previous new, -- it is invoked before -- setting tt's metatable, so -- each new will see its -- inheritance chain. function mknew(tt) local mt,oldinit,more = {__index=tt},tt.superinit,rawget(tt, "init") tt.new=function(ret) if(not ret) ret = {} ret.new = false setmetatable(ret, mt) if(oldinit) oldinit(ret) if (more) more(ret) return ret end if oldinit and more then tt.superinit = function(ret) oldinit(ret) more(ret) end elseif more then tt.superinit = more end return tt end function trim(s) local f, e = 1, #s while (f <= e and s[f]==" ") f += 1 while (e >= f and s[e]==" ") e -= 1 if (f 0) add(row, cell) end if (#row > 0) add(ret, row) end return ret end function crush(s) ret = "" for line in shatter(s) do for tok in line do ret..=tok.." " end ret = sub(ret, 1, -2).."\n" end if (#ret > 0) return sub(ret, 1, -2) return "" end -- >8 -- common --[[preserve-keys]] splubp = mknew{ ptr = 0x8000, init = function(self) -- fill from ffile or saved file self.fmts = {} if (not self.ffile) self.ffile, self.ptr = self:e() for f in all(split(self.ffile, "===", false)) do local tok = shatter(f) assert(#tok > 1, "not enough rows in "..tostr(tok)) -- debug assert(#tok[1] == 1 and tok[1][1][1] == ".", "bad extension row: "..tostr(tok[1])) -- debug self.fmts[sub(deli(tok, 1)[1], 1)] = tok end end, } function splubp:e() local ret = chr(peek(self.ptr + 2, %self.ptr)) return ret, self.ptr + 2 + #ret end -- >8 -- writer function splubp:emit_fmts() self.ptr = self:emit_e(self.ffile) end function splubp:emit_item(obj, filename) debug_last_emit = obj -- global debug filename = filename or obj._file obj._addr = self.ptr self.ptr = self:write_s(filename) for row in all(self.fmts[split(filename, ".")[2]]) do local alt = self.wdirectives[row[1]] if alt then self.ptr = alt(self, obj, row) else self.ptr = self:write_fmt(obj[row[1]], row, 2) end end end -- TODO: splubp.wdirectives -- a -- table mapping non-key -- special values to -- functions to write them -- TODO: write_fmt: recursive -- writing thing function splubp:write_s(s) poke(self.ptr, #s, ord(s, 1, #s)) return self.ptr + 1 + #s ) end function splubp:write_e(s) poke2(self.ptr, #s) poke(self.ptr+2, ord(s, 1, #s)) return self.ptr + 2 + #s end -->8 -- loader function splubp:s() local ret = chr(peek(self.ptr + 1, @self.ptr)) return ret, self.ptr + 1 + #ret end