Skip to content

Instantly share code, notes, and snippets.

Last active May 26, 2024 09:00
Show Gist options
  • Save josefnpat/bfe4aaa5bbb44f572cd0 to your computer and use it in GitHub Desktop.
Save josefnpat/bfe4aaa5bbb44f572cd0 to your computer and use it in GitHub Desktop.
Going from Lua 5.2 to PICO-8's Lua

This information applies to the PICO-8 0.1.6 release.

This document is here to help folks with a proficiency in Lua understand the limitations and discrepencies between Lua and PICO-8's Lua.

You can always view the manual or yellowafterlife's extended 0.1.1 manual.


  • anything written in uppercase the PICO-8 editor or .p8 is made lowercase by the editor. → editing the .p8 file directly can work
  • print(function() end) outputs the string function instead of the string function: 0x0000000.
  • print takes three arguments (string,x,y) → use printh() instead
  • PICO-8's Lua supports a few Compound assignment operators: +=,-=,*=,/=,%=
  • PICO-8's Lua has single line shorthand for if then else operators. → Compare to ternary?: PICO-8 Lua: IF (NOT B) THEN I=1 J=2 END vs Lua: i,j = not b and 1,j or i,2.
  • PICO-8's Lua has a different precision (16:16 fixed point) vs Lua's double-precision floating-point.
  • PICO-8's Lua has additional Comparison operators/relational operators for "Not Equal To" (~=): !=
  • There is no io object. → There is technically "Cartridge Data" that you can use for persistant information - see cartdata()
  • load() has been overwritten with a PICO-8 function.
  • PICO-8 introduces many other global functions (see manual).
  • There are general rounding errors: print("-1"*1 == -1") -- false
  • Global functions and variables have been removed: collectgarbage, dofile, error, ipairs, loadfile, loadstring, math, module, package, pcall, rawequal, rawlen, rawget, require, select, string, table, tonumber, tostring, unpack, xpcall, _VERSION, and getmetatable.
  • _G global table has been removed.
  • assert() and type() were removed in 0.1.3 but added back in 0.1.4.
  • coroutine.[create|resume|status|yield]() was removed in 0.1.3 but added in 0.1.6 as coroutine(), cocreate(), coresume(), costatus() and yield() respectively.
  • setmetatable was removed in 0.1.3 but added back in 0.1.6

Alternates to missing functions


function munpack(t, from, to)
  from = from or 1
  to = to or #t
  if from > to then return end
  return t[from], munpack(t, from+1, to)

print(munpack{1, 2, 3, 4})

Thanks to bartbes for this much better version

function pow(x,a)
	if (a==0) return 1
	if (a<0) x,a=1/x,-a
	local ret,a0,xn=1,flr(a),x
	while a0>=1 do
	if (a0%2>=1) ret*=xn
	while a>0 do
	while a<1 do x,a=sqrt(x),a+a end
	return ret

Thanks to samhocevar for this implementation (link)

Lua's String Library


The string table is no longer available.


  • strings that use upper case pattern matching will not be able to be entered into the editor directly.
  • string.byte returns a fraction [incorrect value]
  • string.char operates differently:

  • string.dump returns the characters va but offset I think? [incorrect value?]
  • string.find returns small fractions [invalid indexes]
  • string.gmatch does not return a working iterator [broken iterator index]
  • string.gsub does not return the correct index [incorrect second value]
  • string.len returns a rather small fraction [incorrect value] → use the # operator instead
  • string.[upper|lower] while both of these functions technically work correctly, because the char table has had the upper case characters removed, it will not work as intended.

Lua's Table Library


The table table is no longer available.


  • table.insert(t,o) does not insert the proper key. → use add(t,o) instead
  • table.insert(t,p,o) does not insert the proper key. Attempting to insert beyond table initialization causes an position out of bounds error.
  • table.remove(t,p) removes the correct value, but then assocates every following value with the key before it. → use del(t,o) instead

Lua's Math Library


The math table is no longer available.


  • math.a[cos|sin|tan][2] does not work correctly. [Rounding errors?] → use atan2() instead of math.atan2(). Untested versions here
  • math.[floor|ceil] returns input [incorrect value] → use flr() instead. For math.ceil(), use function ceil(x) return -flr(-x) end
  • math.[cos|sin] return zero [incorrect value] → use cos() and sin(). Functions take 0..1 instead of 0..PI*2, and sin() is inverted.
  • math.tan does not work correctly. [Rounding errors?] → use math instead:
  • math.[cos|sin|tan]h does not work correctly. [Rounding errors?]
  • math.[deg|rad] return zero [incorrect value] → use math instead:
  • math.[exp|log] does not work correctly [Rounding errors?]
  • math.log10 is nil [does not exist]
  • math.pow does not work correctly [returns -maxint] → use the ^ operator instead
  • math.modf returns two zeros [incorrect value] → use the % operator instead
  • math.sqrt does not work correctly [Rounding errors?] → use sqrt() instead
  • math.random does not work correctly [returns zero] → use rnd() instead
  • math.randomseed cannot be verified until math.random is fixed [dependency issue] → use srand() instead
  • math.frexp does not return a value [incorrect return type] → but math.ldexp() works for some reason!
  • math.huge is 0.5 [incorrect value and type]
  • math.pi is 5.341e-05 [incorrect value] → use a fixed value instead, e.g.: 3.14159

Lua's OS library


The os table is no longer available.


  • works correctly, but due to a lack of upper case characters, it does not render correctly.
  • os.time returns the incorrect value [rounding issues]
  • os.getenv works correctly, but the editor cannot write upper case characters.
  • os.difftime does not work correctly, but I think that this could be used to get os.time() to work correctly.
  •[name|move] this probably works, but operates where the binary for pico8 is located.
  • os.clock doesn't work correctly, but could probably be scaled to the correct value. → pico8 is forced at 30fps; calculate time by incrementing a variable in _update() by 1/30.

Debug Library


The debug table is no longer available.


This function has not been compared, but seems intact.

Undocumented PICO-8 functions

  • shutdown quits the pico8 binary.
  • _update_buttons function. Has no arguments.
  • _p8_program function. Causes out of memory error when called.
  • decompress function. Not sure what it does.
  • c variable may sometime be globally set. Seems to be a scope error for some other function.
  • trace function. I'm guessing it's for the runtime errors.
  • all function. Not sure what it does.
  • _set_mainloop_exists function. Most likely toggles a variable in a local scope.
  • stop function. Stops game at current point so you can debug things.


bit32 library


The bit32 table is no longer available.


  • bit32 table contains: extract,bnot,rrotate,arshift,btest,bxor,replace,band,lshift,rshift,lrotate,bor
Copy link

merwok commented May 29, 2020

Recent versions added chr, ord, ipairs, unpack!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment