Lua on Pokitto

I’ve been playing around with Lua recently because of one of the non-Pokitto projects I’m assisting with, so I thought it was about time I finally had a go at trying to get Lua working on the Pokitto.

I was expecting to have to gut the internals because of the differences regarding io streams and file streams, but to my amazement all I had to do was declare an extra define and Lua compiled practically right out of the box, and with a minor bit of setup I managed to get it drawing rectangles.

Here’s the code I used.

I’d like to develop this further at a later date to hopefully get the Pokitto running a full Lua environment, and if it’s too resource hungry maybe give eLua a go.

I expect that to get a lot of the basic Lua features working I’d have to go through and edit a lot of the io and file stream code, but really the only important bit is being able to load files from the SD card and maybe displaying error messages.

Theoretically this could mean that eventually it would be possible to write games in Lua and load .lua files from the SD card.
It wouldn’t be ideal for large games where you need all the space, but it would be good for smallish games and it would be another language that people could use with Pokitto.
Without meaning to play language wars, I find Lua a lot easier to use than Python

In case anyone wants to read up on Lua, here’s a few links:

And for those that care, Lua uses the MIT licence, so you’re free to hack it to pieces.

9 Likes

Amazing, please make this happen. I’m a Python fan, but I can’t see any language wars going on, I’d love to learn Lua with this, as I haven’t fully gotten into it yet and it seems very nice.

2 Likes

I believe I’ve mentioned it before, but Lua was actually the 3rd language that I ever learned (after VB .Net and C#, and before C++).
I learned it through the ComputerCraft Minecraft mod.

Of course, back then I wasn’t anywhere near as experienced as I am now, so I can vouch for how easy it is to learn.

The Lua REPL is also one of the few tools I keep on my %PATH%.
(Though I don’t use it as often as I should.)

If you want an example of some relatively complex code, I’ve just dropped into my code archive and dug out a queue library that I wrote back in 2013.

local Queue= 
	function(tab)
		local queue = {}
		local items = tab or {}
			for i,v in next,items,nil do
				if(type(i)~='number')then
					tab[i]=nil 
					items[#items+1]=v
				end
			end
		queue.Enqueue= 
			function(item)
				items[#items+1]=item
			end
		queue.Dequeue=
			function()
				local item = items[1]
					for cnt = 1,#items-1 do
						items[cnt] = items[cnt+1]
					end
				items[#items]=nil
				return item
			end
		queue.Peek= 
			function()
				return items[1]
			end
		queue.Clear= 
			function()
				for cnt = #items,1 do
					items[cnt]=nil
				end
			end		
		queue.Contains=
			function(item)
				for cnt = 1, #items do
					if(type(item)==type(items[cnt]))
					and(tostring(item)==tostring(items[cnt]))
					then return true
					end
				end
				return false
			end
		queue.CopyTo=
			function(tab)
				for cnt = 1, #items do
					tab[cnt]=items[cnt]
				end
			end
		queue.ToArray=
			function()
				local tab = {}
					queue.CopyTo(tab)
				return tab
			end
		queue.Clone=
			function()
				return Queue(queue.ToArray())
			end
		return queue
	end

Bear in mind that 5 years ago I wasn’t anywhere near as experienced as I am now,
so the code is a bit messy and might have some bugs.

Looking at it, I think my functional capability was still pretty good back then,
but my style was lacking - using abbreviated names, not using spaces around operators, not using semicolons etc.

(I blame one of my teachers to a degree, he tried to get us using hungarian notation and using strange variable names like cnt instead of count or i or index'.)


Obviously, Lua is dynamically typed, so there’s not a lot of static type information around,
but I still think it’s easier to get to grips with than e.g. JavaScript.
And if it wasn’t obvious, Lua has optional semicolons because the grammar is really simple.

1 Like

I’d like to learn to embed it into games and make them more flexible, because that’s what it’s for, right? But it really depends on how much RAM it will eat. With keyboard coming to Pokitto, it would be very nice to have some kind of REPL running right on Pokitto, do some “realtime” programming, plotting things, play sounds, …

1 Like

Indeed. Some well-known games are essentially just a game engine with a Lua wrapper, e.g. GMod is basically Valve’s source engine with a Lua wrapper, most of Don’t Starve’s behaviour is implemented in Lua, and more recently Scrap Mechanic has opened up a Lua API for modding.

I’m still getting to grips with the C API myself.

I’m currently working on a basic interface between Lua and SDL, to allow Lua to call SDL functions, and so far I’ve got it working to the degree where I can open windows and do basic rendering:

local width = 800
local height = 400

local window = SDL_CreateWindow("Lua!", 200, 200, width, height);
local renderer = SDL_CreateRenderer(window);

local running = true
while(running) do
	
	local event = SDL_CreateEvent();
	while (SDL_PollEvent(event) > 0) do
		--local n = SDL_EventTypeGetName(t);
		--print(n);
		
		local data = SDL_GetEventData(event);
		
		--[[if(data ~= nil) then
			for k, v in pairs(data) do
				print(k.." = "..v);
			end
			print();
		end]]--
		
		local t = SDL_EventGetType(event);
		if(t == SDL_EventType.SDL_QUIT) then
			running = false
		end
	end
	
	SDL_SetRenderDrawColour(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);

	SDL_SetRenderDrawColour(renderer, 255, 0, 0, 255);
	SDL_RenderDrawLine(renderer, 0, 0, width, height);
	
	SDL_SetRenderDrawColour(renderer, 0, 255, 0, 255);
	SDL_RenderDrawLine(renderer, width, 0, 0, height);
	
	SDL_SetRenderDrawColour(renderer, 0, 0, 255, 255);
	SDL_RenderFillRect(renderer, 40, 40, 80,80);
	
	SDL_SetRenderDrawColour(renderer, 0, 255, 255, 255);
	SDL_RenderDrawRect(renderer, 40, 40, 80,80);
	
	SDL_RenderPresent(renderer);
end
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

Creating a function that interacts with Lua is mostly quite simple.

The function interracts with Lua via Lua’s data stack, by pushing and pulling data, which can be one of several types (an integer, a floating point, a lua table, a lua function, a C or C++ function, a string, light userdata or heavy userdata).
That much is pretty simple to get to grips with.

Where it gets complicated is when you want to make use of non-lua data constructs, like SDL’s SDL_Window, then you have to learn about metatables, and have to be vaguely aware of how the garbage collector behaves, in particular the __gc metamethod.

Overall it’s simple, but I still have a few complaints.

The function naming could be better (e.g. lua_pushInteger or lua_push_integer instead of lua_pushinteger),
the documentation could be better,
and there aren’t as many examples floating around as I’d like.

I also wish it had been C++ based instead of C based,
partly because it would have allowed function overloading,
which would have greatly reduced the number of function names,
and partly because I get fed up of doing lua_somefunction(state) instead of state->somefunction().

That’s something I’m still not sure of, I haven’t been measuring at all.
Dynamic languages will always eat more RAM and be slower than statically typed languages (unless JITed)

I doubt you’d be able to write large games entirely in Lua, but it would be perfectly adequate for situations where you might want to regularly load and unload chunks of code, so it’s good for things like scripted events and minigames.

One thing worth noting is that it implements proper tail calls, so if you write a recursive function in a tail-recursive style then it won’t chew up the stack.
(However, there are caveats.)

Lua would be perfect for this.

If you replaced the input, output and file stream systems (and the OS library),
I’m sure you could just use the default Lua REPL program.

I’m sure it could also transmit data over a serial connection,
or over the internet if we ever got a suitable wifi hat.

1 Like

Would it be potentially possible to run LIKO-12 ??

1 Like

I’m not sure offhand.

I’ve had a quick skim of the documentation and the problem is that it needs Löve2D as well, so that’s potentially 2-3 layers of indirection depending on how it works internally, so that might be a bit too much.

Plus it seems to have a lot of features, so it’s probably quite memory hungry.
And some of the APIs simply couldn’t be implemented without extra peripherals for the Pokitto, e.g. the “WEB” API, the “TouchControls” API, the “Keyboard” API.

It might be possible to just implement a subset of commands though.
If there was better documentation then it would be possible to cut out the Löve2D layer altogether and just implement a subset of the API itself.

2 Likes

Or even Pico-8? :+1::sunglasses:
I wonder if Zep could make it so that the carts could be exported to run directly via Pokitto?

1 Like

The problem with Pico8 is that it’s not open source,
so if even if we wanted to just port the API it would probably have to be negotiated.

Otherwise I think it would be quite easy looking at the limitations they’ve built in.

  • 128x128 16 colour
  • 6 buttons
  • 128 8x8 sprites
  • 128x32 8-bit cell map
  • 8192 token limit on code.

I’m not sure how the cartridge size works,
whether that’s pure Lua bytecode or something else as well.

The only thing I can think might be an issue is speed.
There’s no mention of how fast the Pico-8 system runs.
If it’s slow enough then it would possibly be possible to get round memory limitations by paging code in and out as required,
though that would be a relatively difficult thing to get working.

The strangest limitation is “PICO-8 numbers only go up to 32767.99”.
The first part makes sense but the .99 seems really arbitrary.

I actually really like this bit:
“cos() and sin() take 0…1 instead of 0…PI*2, and sin() is inverted.”
Using fractions of a turn instead of degrees or radians makes many things a lot easier.

1 Like

Seems like they prefer human-friendly numbers which explains the .99 limit which is a byte storing hundredths, since powers of two aren’t able to represent some numbers in finite number of bits, such as 0.1, which would lead to rounding errors. Then they should have rounded the whole part too though.

Actually, now I think about it…
I think they might be using Q16.16 and just rounding the number they give to avoid scaring people,
because SQ15x16 goes up to 32767.9999847412109375 ((2**15 - 1) + (((2**16) - 1) / 2**16)).

1 Like

Seems about right!

Actually I’d be glad if someone made an open-source Pico8 API implementation. But what about the games? I suppose they’re mostly binary only?

EDIT:

so if even if we wanted to just port the API it would probably have to be negotiated.

Can you “own” an API? I don’t know. From the number of open-source clones of various games and systems I thought you couldn’t.

EDIT:

Seems like it’s not clear at all. EU court says no copyright on APIs, but a US court says different? Anyway, a lot of programs out there rely on the former.

The games are stored as “carts”.
They are all written in LUA and contain all code, gfx, sfx and music.
Can be exported to html 5…iirc
Each cart has a gif on the front which is the game itself.
The code is open source afaik. you are free to do anything with it but if you want to make money from it you have to either re-write it in something else or go to Lexaloffle for permission etc.

Examples of carts: https://www.lexaloffle.com/bbs/?uid=1&mode=carts

Some Lua code from Twitter in the less than 250 chars category:

These guys post code which is essentially like mini demos that fit within the Twitter character limit.

#demoscene ftw :+1::metal::sunglasses:

So the code is accessible, that’s something at least but if it doesn’t allow commercial use, it can’t be called open-source. I’d be careful here, because if these games are e.g. distributed on the SD card with Pokitto, it’s commercial use and therefore illegal. So I’d only be looking for games with a proper license.

Do you know this?

https://www.dwitter.net

Nope, never heard of Dwitter thanks for that :+1::sunglasses:

They should just be Lua bytecode chunks, which have a standardised format.
Any specialised functions are taken by name from the global table, which is set up by the environment loading the bytecode, not the bytecode itself.
As long as the names and types match up, it doesn’t matter how the functions are implemented.

I would err on the side of caution and assume you probably can,
but I’m not aware of any cases that have ruled either way.

I’d rather ask either way, out of courtesy, as Jonne did when asking about porting the Arduboy2 API, despite the code itself being MIT licensed.

It depends how the graphics and sound are stored.
If they’re just stored as lua constant strings then it wouldn’t be an issue, otherwise they would have to be reverse engineered.

Perhaps the disks are .zip files? That happens a lot.

Technically if a licence prevents you from selling modifications of the code then it’s not strictly open source.

If there’s a clause to prevent re-sale then it’ll be a custom licence.

That’s not valid Lua.
Lua doesn’t have goto and ifs must be accompanied by then and end.
If that’s valid Pico8 code then they’re not using standard Lua, they’re using a modified variant, which would greatly complicate matters.

Someone here says the author is okay with reimplementing the API and that a few such implementations already exist (LIKO-12, Picolove?). Also here I found a few MIT licensed pico-8 games.

The licensing and such is why I explicitly mentioned LIKO-12 :slight_smile: but I of course really like all most fantasy consoles.

I’d still probably want to ask to be sure.
If the licence doesn’t give any hint about whether the API can be reproduced then there’s nothing to stop the author suddenly being ‘not fine’ with it.

I tried to find what licence pico-8 has, but all I could find were the terms of use, and they hardly constitute a licence.

Either there is no full licence document or the licence isn’t readable until after purchasing pico-8 (which probably isn’t illegal, but in my opinion it should be).

If liko-12 is just an enhanced version of pico-8 then we’re back to square one.

This thread on the PICO-8 forum says you are right about the fixed point layout, Pharap.

2 Likes