Log In  


Hello there!
For the past 2 years me together with @MatheusMortatti have been slowly working on a full featured PICO-8 emulator with full RAM emulation and so on. And we are happy to announce, that the project is now finally in a playable state!

You can grab it for free on steam or compile it from source!

Huge thanks to all the authors, who allowed to include their carts in the release collection, and I hope this work will be useful for the community!

The code is written in a way to be easily ported to new platforms, right now we have pinvoke and SDL2 backends, and thats enough to run inside of Unity and all current gen consoles, but it's really easy to add support for platforms like 3DS and so on!

5


It's been an amazing journey! I'm super happy with how it turned out. If anyone is interested in helping with development, please reach out!!


Wow, PICO-8 really is a console now if we've got an emulator for it.

(haven't been able to mess with it, but I may sometime soon)


Super exciting! You know, consoles like Android really struggle to run Pico-8 games well. Hopefully, someone will port this to Android. Besides that, though, this is very impressive. I hope Pico-8 can become like Doom or Bad Apple where a whole bunch of devices can run it.


1

Hi @egordorichev. Superb work. May I suggest you also please upload your compiled project to ITCH.IO and if possible, here.

Uploading to STEAM requires you to download the STEAM engine executable installer (which I don't want to do) just to even run your project or even get a copy of it. Try clicking Play Game to see that you must have STEAM installed on your computer or it just won't play it.

Itch.io has no such restrictions or requirements.

http://itch.io

Thank you !


(I think egodorichev knows about itch.io...) 😜


1

The fact that @zep posted his own recent project, Pico-8 v0.2.4c on itch.io and NOT Steam tells me quite a bit right there, @MBoffin.

It's his choice of course, however I won't be able to examine or critique his project if the ONLY place it appears readily compiled is on STEAM. I suspect I am not alone in this.


1

You don't need to necessarily surmise why PICO-8 is not on Steam. He's been pretty open about his thoughts on the topic. That said, fortunately pemsa has been posted on Github, so until it's on itch, you're welcome to make your own compiled version from that, and even submit issues and changes there if you have critiques.

All that aside, amazing work, egordorichev and Matheus! This is seriously incredible work. I can't imagine how much time and effort you've put into it. And it was so wonderful to see it up on Github as well. Thank you! :)


3

@dw817 thanks for the suggestion! I have no idea, why I didn't do it earlier. Here is pemsa on itch! :)


Nicely done, thank you for posting your program on Itch, @egordorichev. I am trying out your program now and am suitably impressed. Gold star work.

I may have some questions and suggestions later. For now though this is quite exciting and interesting to examine !

. . .

OK:

  1. I noticed that if you run the EXE in Windows it boots precisely as Pico-8, opening animation, timing and everything, so I am assuming you modified the original Pico-8 source code to build this project ?

  2. You have SPLORE. Since Pico-8 can now be run freely online HERE:

https://www.lexaloffle.com/bbs/?tid=47278

SPLORE is the one item that @zep left out in this online version requiring others to purchase Pico-8 properly for $15 in order to have it. Your program has SPLORE, in fact it boots to Splore - so those people interested in merely playing games can now use your engine with P8 files - not needing to purchase Pico-8.

  1. Selecting the first cartridge, "8legstolove" with the 🅾️ key, it runs as normal. swapping between pressing the ESC key to bring up the menu with RESET and BACK TO MENU can at times turn the screen black and hang the EXE. I haven't been able to isolate where it happens exactly so it must be random.

  2. You have included many sample games from authors I suspect without permission. This in itself is not an entirely bad thing as many I suspect are quite honored to be included in your list here. Some, however, may not be.

  3. If all the above are accepted and not considered a problem then I have a few suggestions, starting with A.

A. You are only looking for the arrow keys for navigation in your menus and ignoring the number keypad. Suggest you either include the number keypad as an added input or have an option for keyboard/joystick configuration.

B. Your speed of key repeat is very slow, about 2-keystrokes per second. You can see this by booting your EXE and holding the DOWN arrow key to see how slowly it goes from one title to the next.

C. You do not have the OPTIONS menu option available in your menu when you press ENTER or the ESC key. In OPTIONS you can turn the audio sound on or off, change the volume level of it, go to full-screen or not, and view the controls.

D. Add option to EXIT in menu. This will exit the executable neatly and in the case with Windows, return back to Windows. Currently you must press ALT-F4 to close this task or manually close it in the Task Manager.

. . .

I will be running tests of my own to see if my own code runs properly, including saving/loading SRAM of 12288 bytes. I will let you know. All in all, a marvelous program. There will always be questions and concerns for a program of this usefulness and magnitude.


These are some carts I tested running in your PEMSA, @egordorichev, by merely copying over the original P8 sourcecode to the directory your PEMSA runs from. The results were not good.

Prove 32-Colors: Fail, incorrect display
Trucolor: Fail, hangs with no display
Prove 12288: Fail, says "attempt to index a nil" where the program runs just fine in modern Pico-8.
Mildew's Manor: Fail, hangs, no display, verdict: you are not running FLIP() the correct way.
23 Pages: Fail, hangs, no display
Fillp Editor: Fail, hangs, no display

That's enough for now. I think and correct if I am wrong, you are using an early source-code of @zep's that at the time did not run properly, FLIP() in addition to many other things including extended memory access, yes ?

Additionally in your program if you remove all the P8 source-code and transfer just one, say, one of the original that you included such as 8legslove.p8, running your program gives the notice, "NO CART. This is PEMSA. Insert a cart."


8

Congrats Egor & Matheus! Being intimately aware of PICO-8's dark corners and oddities, I can vouch that this is quite a feat of engineering!

I'm glad that projects like this exist -- it's fascinating to read alternative implementations, and acts as a proof of concept that it would be possible to recover from some catastrophic loss of the PICO-8 source code: e.g. I get hit by a bus and noone knows where it is or what should be done with it. Neither of those two things will happen (and the second one I have more control over), but it means that noone needs to take my word for it.

On that note, I do plan on making the source for PICO-8's runtime available sometime after 1.0. But it might still be some time away so haven't made any firm promises about it. pemsa and other implementations are a great way for authors to reach extra platforms that I haven't supported (yet).

@egordorichev
I do have a request ~ the Steam build looks an awful lot like PICO-8 to a casual newcomer. Would it be possible to rework it (and the logo / product description) to make it clearer this is a separate third-party product? I'm counting on Steam sales to be a large part of the 1.0 release, including the player demographic that makes up most of Steam (rather than authors / students), and I'm afriad this could potentially cause confusion.

@dw817
I don't think any of pemsa is using decompiled P8 source code or anything like that, just designed to imitate the thing it's emulating, which is a reasonable starting point!

On making splore less attractive as a feature to purchase for: it's possible to some degree, but I think being able to freely use the BBS web player is a similar consideration: it becomes clear that you can get a more integrated console-like experience with splore. This will be even more true with the addition of logins & scores at 0.3. I'm more worried about unpredictable secondary effects -- e.g. opportunists from outside the PICO-8 community who move to repackage carts and present them as an official thing slathered in advertising. But I don't want to unnecessarily add barriers for well-intended projects in order to combat these kind of hypothetical scenarios.


bug report: button presses leak through to the cart when launching it from the menu. pressing a button on the menu should cause that button to no longer register until it's been released


I understand, @zep.

If you're greenlighting this, that's fine with me. And yes, the ability to save global data in v 0.3 will definitely be of interest to me.

Likely for me not so much for simple high-scores as the ability to transfer shared complex data such as maps, sprites, and complex interpretive scripting code in the form of single strings exceeding 64-characters in length.

As for your worries about packaged Pico-8, we already have such programs available for the cellphone to run Pico-8 programs, primitive programs but programs nonetheless, such as the "P8 Player."

"Nest 2" looks like they jacked your 96-character font, every single character, pixel-per-pixel copy. Wow.

Likely there are other programs not just in Google Play but available for computers as well such as Windows and Macintosh. And they may be repackages.

Nonetheless if you can toss a cheery hat to all of this, I definitely welcome what the future holds for cosy Pico-8 and ultimately Picotron.


1
"Nest 2" looks like they jacked your 96-character font,
every single character, pixel-per-pixel copy. Wow.

@dw817 The PICO-8 font (and palette) are licensed as CC-0 (public domain), per the FAQ. So not really "jacked" so much as "used with permission."


@MBoffin:

"Nonetheless if you can toss a cheery hat to all of this, I definitely welcome what the future holds for cosy Pico-8 and ultimately Picotron."

And so it has.


@dw817 to address all your messages.

No, we have never decompiled PICO-8 or looked at it's source code in any way. For some technical things, like music bits and such the wiki does a pretty great job in explaining the memory layout.

Yes, the emulation is not perfect. The project started over 2 years ago, and since then PICO-8 was getting regular updates, for example oval() is not implemented what so ever. We had to not include some carts because we couldn't figure out how to get them working. But we thought that running complex carts like danktombs and such is enough of a feat to share with the community, instead of waiting for forever until this whole project is 100% accurate (and that will never be true, sadly). We will do our best to bring the project as close to perfect emulation, as possible, but again, it is really tough, people do all sorts of crazy things with their code, for example I've just learned that you could pass strings instead of numbers to some functions. Crazy!

About the carts. All the carts authors gave their permission to run their carts inside of the collection, some preferred to stay away from the project and we did not include their carts.

> I noticed that if you run the EXE in Windows it boots precisely as Pico-8, opening animation, timing and everything, so I am assuming you modified the original Pico-8 source code to build this project ?

If you look at BBS there are plenty of examples of people recreating the boot effect in PICO-8 itself :)

> Additionally in your program if you remove all the P8 source-code and transfer just one, say, one of the original that you included such as 8legslove.p8, running your program gives the notice, "NO CART. This is PEMSA. Insert a cart."

That's how pemsa-sdl is designed to run. It looks for a cart named splore, if it finds it it boots it (or any other cart supplied by the command line arguments), otherwise it plays the no cart animation. So if you want to run your single cart, do pemsa cart.p8 (or pemsa.exe cart.p8).

Splore is not really splore, it's just a way to select a cart, it has no web access or anything, no favorite carts, etc, it's just a basic menu. So I don't really see an issue with it being a thing. Maybe just calling it splore is not the best thing ever, but that's just out of habbit.

Otherwise, thanks for the bug reports, will be working on them in the near future :)

@zep Sure. Messaged you on discord about the details.


Hi @egordorichev. Thanks for the information. I also tried to examine SPLORE, curious to see if you were just calling, "SPLORE" or something more complex. What I got was this:

pico-8 cartridge // http://www.pico-8.com
version 29
__code__
 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z = -2560.5, 31455.5, 32125.5, 1, 6943.5, 3855.5, 2, -19008.5, 4, -20032.5,0.5, -20128.5, 3, -18402.5, -1632.5, 20927.5, -26208.5, -20192.5, 0, 21845.5, 5, 20767.5, -2624.5, 23130.5, -25792.5, -24351.5  sub, cocreate, coresume, yield, costatus, __debug, debug, run, unpack, pack = string.sub, coroutine.create, coroutine.resume, coroutine.yield, coroutine.status, debug, nil, __reset, table.unpack, table.pack function __error(e)  print('runtime error',nil,nil,14)  print(e,nil,nil,6)  print(__debug.traceback(),nil,nil,13) end function foreach(a, f)  for i in all(a) do f(i) end end function count(a) if not a then return 0 end return #a end  function arraylen(t)  local len = 0   for i, _ in pairs(t) do    if type(i) == "number" then    len = i    end   end   return len  end  function all(a)   local n = arraylen(a)  if a == nil or n == 0 then    return function() end   end   local i = 1  local previous_i = nil  return function()    if (a[i] == previous_i) then    i = i + 1   end   while (a[i] == nil and i <= n) do     i = i + 1    end    previous_i = a[i]   return a[i]   end  end  function add(a, v, i) 	if a == nil then return end  	if i then 		table.insert(a, i, v) 	else 		table.insert(a, v) 	end 	return v end function del(a, dv) 	if a == nil then return end 	for i, v in ipairs(a) do 		if v == dv then 			table.remove(a, i) 			return dv 		end 	end end function deli(a, i) 	if a ~= nil then table.remove(a, i) end end function __load_splore() 	__load("splore") 	__reset_graphics() end local __menu_options_custom={} local __current_option=1 local __menu_on=false local __menu_functions={} local __favorite=false function __update_menu() 	if not btnp(6) and not __menu_on then return end  	local __menu_options={} 	for o in all(__menu_options_custom) do 		add(__menu_options,o) 	end  	add(__menu_options,"continue",1) 	add(__menu_options,"favorite") 	add(__menu_options,"reset cart") 	add(__menu_options,"back to menu")  	if (btnp(6) or (__menu_on and (btnp(5) or btnp(4)))) and __cart~="splore" then 		if __menu_on and __current_option==#__menu_options-2 then 			__favorite=not __favorite 		else 			__menu_on=not __menu_on 			__set_audio_paused(__menu_on) 			__set_paused(__menu_on)  			if not __menu_on then 				local fn=__menu_functions[__current_option-1] 				if __current_option==#__menu_options -1 then fn=__reset end 				if __current_option==#__menu_options then fn=__load_splore end  				if fn then fn() end 				cls() 			end 		end 	end  	if not __menu_on then return end  	if btnp(2) then 		__current_option=__current_option-1 		if __current_option<1 then 			__current_option=#__menu_options 		end 	end  	if btnp(3) then 		__current_option=__current_option+1 		if __current_option>#__menu_options then 			__current_option=1 		end 	end  	local h=10+#__menu_options*8 	local x=24 	local y=(128-h)/2 	rectfill(x,y,x+81,y+h-1,0) 	rect(x+1,y+1,x+80,y+h-2,7)  	local ax=x+5 	local ay=y-1+__current_option*8  	for i=0,2 do 		line(ax+i,ay+i,ax+i,ay+4-i,7) 	end  	for i=1,#__menu_options do 		local current=__current_option==i 		print(__menu_options[i],x+11+(__menu_options[i] and 1 or 0),y-1+i*8,7) 		if i==#__menu_options-2 then 			print("\135",x+51,y-1+i*8,__favorite and 8 or 13) 		end 	end end function menuitem(i,name,fn) 	if i<1 or i>5 then return end 	__menu_options_custom[i]=name 	__menu_functions[i]=fn end function rnd(i) 	if type(i)=="table" then return i[flr(__rnd(#i))+1] end 	return __rnd(i) end function split(i,s,c) 	if s==nil then s="," end 	if c==nil then c=true end 	local t={} 	for p in string.gmatch(i,"([^"..s.."]*)("..s.."?)") do 		local n 		if c~=false then n=tonum(p) end 		add(t,n==nil and p or n) 	end 	return t end if not __skip then 	local data="00077770007777700070700000777000007770000000000000777770007777700070707000700070000000000077777000777770000770000000770000077000007777700077777000000000000770700077707000707770007077700000000000777770007777700070700000777770000777700000000090a0b000001000008111c00000100000f0e0d000" 	local function wait(a) for i = 1,a do flip() end end 	cls() 	for y=0,127 do 	 for x=2,127,8 do 	  pset(x,y,rnd(6)) 	 end 	end 	wait(3) 	for y=0,127,2 do 	 for x=0,127,4 do 	  pset(x,y,6+flr((x+y)/8)%8) 	 end 	end 	wait(3) 	for y=0,127,3 do 	 for x=2,127,4 do 	  pset(x,y,10+rnd(4)) 	 end 	end 	wait(3) 	for y=0,127 do 	 for x=1,127,2 do 	  pset(x,y,pget(x+1,y)) 	 end 	end 	wait(2) 	for y=1,127,4 do 	 memset(0x6000+64*y,0,64*3) 	end 	wait(3) 	cls() 	wait(15) 	local osfx="" 	for i=0,67 do 	 osfx=osfx..tostr(peek(0x3200+i),true) 	end 	local s="0070.00000059.0000006b.0000005b.00000070.0000005b.00000075.00000059.00000075.00000053.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001.0000000c.00000000.00000000.0000" 	local function psfx(d) 		for i=0,67 do 		 local ind=i*9+1 		 poke(0x3200+i,tonum("0x"..sub(d,ind,ind+8))) 		end 	end 	psfx(s) 	sfx(0) 	for x=0,34 do 	 for y=0,7 do 	  local i=x*8+y+1 	  pset(x+1,y+3,tonum("0x"..sub(data,i,i))) 	 end 	end 	wait(5) 	color(6) 	cursor(0,18) 	print("pemsa v0.1 v0.1-9-ge7ffe33") 	wait(5) 	print("(c) 2014-20 unofficial\n") 	print("\nbooting catridge...") 	wait(40) 	psfx(osfx) end 

cartdata("__splore")
local current=max(1,dget(0)or 1)

function read_card()
 title,author=__read_cdata(carts[current][1])
 carts[current]={
  carts[current][1],
  author,
  title
 }
end

function _init()
 carts=__list_carts()
 current=min(#carts,current)

 for c in all(carts)do
  title,author,label=__read_cdata(c[1])
  c[2]=author
  c[3]=title=="unknown" and c[1] or title
  c[4]=label
 end

 if #carts == 0 then
  while true do
    cls()
    print("no carts found", 1, 1)
    flip()
  end
 end

 update_bg()
end

function update_bg()
 dset(0,current)
 local c = carts[current]

 if not c then return end

 local d=c[4]
 for i=0,128*128-1 do
  sset(
   i%128,flr(i/128),
   tonum("0x"..
   sub(d,i+1,i+1))
  )
 end
end

function _update()
 if(btnp(G)) then current=max(1,current-1)update_bg()sfx(0) end
 if(btnp(M)) then current=min(#carts,current+1)update_bg()sfx(1) end
 if(btnp(U)or btnp(I)or btnp(6))then
  __load(carts[current][1])
 end
end

function _draw()
 cls()
 sspr(0,0,128,128,0,0)

 local x,y=16,72
 local ex,ey=112,127

 rectfill(x-1,y-1,ex+1,ey+1,7)
 rectfill(x,y,ex,ey,0)
 clip(x,y,ex-x-1,ey-y+1)

 local mod=current>6 and (current-6)or 0
 for i=1,9 do
  local cart=carts[i+mod]

  if cart then
   local yy=y+1+(i-1)*8
   local l=#cart[3]*4
   local c=7

   if i+mod==current then
    rectfill(x+1,yy,x+2+l,yy+6,14)
    rectfill(x+2+l,yy,ex-1,yy+6,15)
    c=0
   end

   print(cart[3],x+2,yy+1,c)

  end
 end
 clip()
end

Here, for instance, is the opening code to, 8legstolove:

pico-8 cartridge // http://www.pico-8.com
version 29
__code__
 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z = -2560.5, 31455.5, 32125.5, 1, 6943.5, 3855.5, 2, -19008.5, 4, -20032.5,0.5, -20128.5, 3, -18402.5, -1632.5, 20927.5, -26208.5, -20192.5, 0, 21845.5, 5, 20767.5, -2624.5, 23130.5, -25792.5, -24351.5  sub, cocreate, coresume, yield, costatus, __debug, debug, run, unpack, pack = string.sub, coroutine.create, coroutine.resume, coroutine.yield, coroutine.status, debug, nil, __reset, table.unpack, table.pack function __error(e)  print('runtime error',nil,nil,14)  print(e,nil,nil,6)  print(__debug.traceback(),nil,nil,13) end function foreach(a, f)  for i in all(a) do f(i) end end function count(a) if not a then return 0 end return #a end  function arraylen(t)  local len = 0   for i, _ in pairs(t) do    if type(i) == "number" then    len = i    end   end   return len  end  function all(a)   local n = arraylen(a)  if a == nil or n == 0 then    return function() end   end   local i = 1  local previous_i = nil  return function()    if (a[i] == previous_i) then    i = i + 1   end   while (a[i] == nil and i <= n) do     i = i + 1    end    previous_i = a[i]   return a[i]   end  end  function add(a, v, i) 	if a == nil then return end  	if i then 		table.insert(a, i, v) 	else 		table.insert(a, v) 	end 	return v end function del(a, dv) 	if a == nil then return end 	for i, v in ipairs(a) do 		if v == dv then 			table.remove(a, i) 			return dv 		end 	end end function deli(a, i) 	if a ~= nil then table.remove(a, i) end end function __load_splore() 	__load("splore") 	__reset_graphics() end local __menu_options_custom={} local __current_option=1 local __menu_on=false local __menu_functions={} local __favorite=false function __update_menu() 	if not btnp(6) and not __menu_on then return end  	local __menu_options={} 	for o in all(__menu_options_custom) do 		add(__menu_options,o) 	end  	add(__menu_options,"continue",1) 	add(__menu_options,"favorite") 	add(__menu_options,"reset cart") 	add(__menu_options,"back to menu")  	if (btnp(6) or (__menu_on and (btnp(5) or btnp(4)))) and __cart~="splore" then 		if __menu_on and __current_option==#__menu_options-2 then 			__favorite=not __favorite 		else 			__menu_on=not __menu_on 			__set_audio_paused(__menu_on) 			__set_paused(__menu_on)  			if not __menu_on then 				local fn=__menu_functions[__current_option-1] 				if __current_option==#__menu_options -1 then fn=__reset end 				if __current_option==#__menu_options then fn=__load_splore end  				if fn then fn() end 				cls() 			end 		end 	end  	if not __menu_on then return end  	if btnp(2) then 		__current_option=__current_option-1 		if __current_option<1 then 			__current_option=#__menu_options 		end 	end  	if btnp(3) then 		__current_option=__current_option+1 		if __current_option>#__menu_options then 			__current_option=1 		end 	end  	local h=10+#__menu_options*8 	local x=24 	local y=(128-h)/2 	rectfill(x,y,x+81,y+h-1,0) 	rect(x+1,y+1,x+80,y+h-2,7)  	local ax=x+5 	local ay=y-1+__current_option*8  	for i=0,2 do 		line(ax+i,ay+i,ax+i,ay+4-i,7) 	end  	for i=1,#__menu_options do 		local current=__current_option==i 		print(__menu_options[i],x+11+(__menu_options[i] and 1 or 0),y-1+i*8,7) 		if i==#__menu_options-2 then 			print("\135",x+51,y-1+i*8,__favorite and 8 or 13) 		end 	end end function menuitem(i,name,fn) 	if i<1 or i>5 then return end 	__menu_options_custom[i]=name 	__menu_functions[i]=fn end function rnd(i) 	if type(i)=="table" then return i[flr(__rnd(#i))+1] end 	return __rnd(i) end function split(i,s,c) 	if s==nil then s="," end 	if c==nil then c=true end 	local t={} 	for p in string.gmatch(i,"([^"..s.."]*)("..s.."?)") do 		local n 		if c~=false then n=tonum(p) end 		add(t,n==nil and p or n) 	end 	return t end if not __skip then 	local data="00077770007777700070700000777000007770000000000000777770007777700070707000700070000000000077777000777770000770000000770000077000007777700077777000000000000770700077707000707770007077700000000000777770007777700070700000777770000777700000000090a0b000001000008111c00000100000f0e0d000" 	local function wait(a) for i = 1,a do flip() end end 	cls() 	for y=0,127 do 	 for x=2,127,8 do 	  pset(x,y,rnd(6)) 	 end 	end 	wait(3) 	for y=0,127,2 do 	 for x=0,127,4 do 	  pset(x,y,6+flr((x+y)/8)%8) 	 end 	end 	wait(3) 	for y=0,127,3 do 	 for x=2,127,4 do 	  pset(x,y,10+rnd(4)) 	 end 	end 	wait(3) 	for y=0,127 do 	 for x=1,127,2 do 	  pset(x,y,pget(x+1,y)) 	 end 	end 	wait(2) 	for y=1,127,4 do 	 memset(0x6000+64*y,0,64*3) 	end 	wait(3) 	cls() 	wait(15) 	local osfx="" 	for i=0,67 do 	 osfx=osfx..tostr(peek(0x3200+i),true) 	end 	local s="0070.00000059.0000006b.0000005b.00000070.0000005b.00000075.00000059.00000075.00000053.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001.0000000c.00000000.00000000.0000" 	local function psfx(d) 		for i=0,67 do 		 local ind=i*9+1 		 poke(0x3200+i,tonum("0x"..sub(d,ind,ind+8))) 		end 	end 	psfx(s) 	sfx(0) 	for x=0,34 do 	 for y=0,7 do 	  local i=x*8+y+1 	  pset(x+1,y+3,tonum("0x"..sub(data,i,i))) 	 end 	end 	wait(5) 	color(6) 	cursor(0,18) 	print("pemsa v0.1 v0.1-9-ge7ffe33") 	wait(5) 	print("(c) 2014-20 unofficial\n") 	print("\nbooting catridge...") 	wait(40) 	psfx(osfx) end 

cartdata("bridgs_8legstolove_1")

local scene
local next_scene
local transition_frames_left=0
local scene_frame
local level_num
local level
local level_tileset
local score
local score_cumulative
local bugs_eaten
local timer
local frames_until_spawn_bug
local spawns_until_pause
local spider
local entities
local new_entities
local web_points
local web_strands
local moving_platforms
local tiles
local level_spawn_points
local wind_frames
local wind_dir
local wind_x
local wind_y
local menu_buttons
local is_story_mode

local tile_flip_matrix={8,4,2,1,128,64,32,16}
local scenes={}

... more code ...

Which not only doesn't run in Pico-8, but if you change the code to lua which is standard with Pico-8, it still doesn't run - it shows errors.

So ... these games you've included have all been converted to a format that does not recognize standard Pico-8 ? Which is odd as if you add a normal Pico-8 game to the directory, such as "Pico Monsters," it =DOES= run properly. so ... why convert all those games to a non-Pico-8 format if in their original format they run just fine ?


@dw817 it's called code for a reason. Pemsa is perfectly capable of running the regular p8 files. But it needs to preprocess PICO-8 lua code into regular lua to run it properly. The result can be stored in the code section. For this collection, I've opted to include preprocessed cards to reduce load times and avoid potential issues.

If you take 8legstolove from PICO-8 BBS in the p8 format and run it with pemsa it will run just fine :)


Wow geeze, you're really tearing into them, aren't you dw817? Ease up a lil...

I don't know for sure, but I think my cart might be the first one that just, blindly recreated the boot animation, including the sound effect?

Cart #16286 | 2015-11-06 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Those low cart numbers, ah. It's been a while.


Not at all, @JTE. I'm observant. What egordorichev has done goes beyond regular thanks. It is absolutely incredible and wonderful what he has written. I am not doubting this and it is definitely worthy of everyone's gold stars.

A large part of my understanding things comes from being observant when something doesn't function conventionally. From examining absolutely everything around me. It is part of my learning process and leads me to discovering things others may miss.

And yes I did earlier mention that PEMSA does run "most" regular Pico-8 carts, no problem. Which ... is why I was first concerned I could not load any of the demo carts from PEMSA in regular Pico-8.

Which prompted me to examine both of them side-by-side seeing character additions and discrepancies. Especially of note having, "__code__" instead of "__lua__"

... I suppose if PEMSA just originally ran my own carts without fail, such as Mildew's Manor where it crashes, I wouldn't have taken the time to find out why it wasn't working and would've placed a green checkmark beside it and moved on.



[Please log in to post a comment]