Log In  

Cart #webkit_proto-2 | 2021-11-01 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Long winded explanation:

Before I explain exactly what this is and why it exists, I need to explain the history behind it.

Some of you may have seen the (relatively small amount of) attempts to implement a BBS-type system by taking advantage of the General Use Memory region and it not being cleared by load(). It fascinated me when I first came across it, but I eventually forgot.
Recently, I came back to the concept with a new idea: static web pages. General use memory can contain 4864 32-bit numbers if not using the custom font, which is more than plenty for a page written in a simplified markup language. We can take that even further if we use the breadcrumb string passed to carts through load().

The first step for me was designing the simplified markup language. I decided on something I call PPML, Portable Pico Markup Language. The syntax is the following:

tagname> tag content

A paragraph, for example, would look like this:

p> This is a paragraph

I decided this was suitable and moved on to the next part.
This next part was the renderer for the PPML. This is what you see in the above cartridge, displaying a demo page. The renderer consisted of a list of tags with rendering functions, a Global Render table and a Frame Render table. The Global Render contained persistent stuff like the background colour, while the Frame Render contained things like the cursor position for text. This then took the PPML, contained in the first tab, and processed it into a table for easy use. The _draw() function then simply looped through this content table, calling the tag render functions with the necessary arguments.
It's a simple method, but works pretty well.

The next step would be the networking; loading the cartridge, processing the data it left in General Use Memory and converting it into usable PPML. Then that can be fed into the renderer, and you can see the page.

Of course, this renderer is a proof-of-concept prototype. A lot more tags still need to be added and hopefully a very simple scripting language.

When all this is done, I hope to have a fully functioning browser which would let you browse the PicoWeb and maybe play some small games on Newgrounds-esque sites. But, we can only hope.

Feel free to leave feedback on the renderer/game plan!


  • A bit more content to show possible use cases
  • Implemented scrolling with mouse wheel with @Einstein2's tips
  • Now shows mouse
P#93104 2021-06-06 10:52 ( Edited 2021-11-01 09:31)

Very nice! I once had a similar idea for a pico-8 operating system, where that region of memory could be used to download "packages" then write them (using printh) to a "disk" (a text file that would be #include-d each time the cart restarted).

A few things I'd like to say:

  • There are two general use regions: 0x4300..0x55ff and 0x5600..0x5dff. The first one is 4864 bytes (bytes, not 32-bit numbers: that's only 4864 characters, not 19456) long, and is the one that is not cleared upon load()ing. The second one is 2048 bytes long, can be used for the second font, and does get emptied upon load()ing just like any other section of memory.

  • The third parameter of load() is a (maximum 1024 characters long) string that will get passed to the cart you're loading. This increases the max transferable amount of chars/bytes to 5888.

  • With stat(36) you can detect mouse scroll events; it'd be quite simple to hook it up to your existing scrolling system.

  • poke(0x5f34,1) lets you include fill patterns inside the color value. This means you can have simple two-color patterns for a background without having to change much. From the manual:
    -- bit  0x1000.0000 means the non-color bits should be observed
    -- bit  0x0700.0000 0x1 transparency, 0x2 apply to sprites, 0x4 apply secondary palette 
    -- bits 0x00FF.0000 are the usual color bits
    -- bits 0x0000.FFFF are interpreted as the fill pattern

P#95957 2021-08-13 20:15

@Einstein2 (sorry for being late) Thanks for the tips! Also, your operating system idea is very interesting! Maybe I should try implementing that package system sometime.

P#97193 2021-09-11 10:59

No worries!

I tried to make the package system with the general-use memory section... it wasn't working at all, I have no clue why. So instead I resorted to only using the third load parameter:


h=split(stat(6),"•",false) --the string returned from cart2 is [package content]•[index of next package]
printh(h[1],"disk.txt",false) --print contents to file

if(h[2]!="0")load("cart2.p8",nil,"package•cart1.p8"..(h[2]and "•"..h[2]or "")) --[packagename]•[cart to load]•[index] ; don't download anymore if the index is equal to 0

#include disk.txt --disk.txt (or whatever you name it) does need to exist before this cart is run


pckgs.package=2 --number of loads needed to download the complete package
pckgs.package2="b=5" --package number starts from the highest and counts down (i.e. package2 is downloaded first, then package1)

h=split(stat(6),"•") --[packagename]•[cart to load]•[index of package to download] 
b=tonum(h[3])or(pckgs[h[1]]) --the first load, [index] will be nil, so it fetches the load number (in this case, 2)

load(h[2],nil,pckgs[h[1]..b].."•"..b-1) --load [cart to load], passing [package content]•[index-1]

This works fairly well, although it's a bit slow. Feel free to ask how specific parts work if the comments are not thorough enough.

P#97514 2021-09-19 02:19 ( Edited 2021-09-19 21:26)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-02-26 01:56:02 | 0.039s | Q:20