Log In  
:: Unfold ::

Puzzle Duck

Cart #puzzle_duck-0 | 2023-09-27 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

A simple Puzzle Bobble / Bust-a-Move - Clone.

from URL Wikipedia:
Puzzle Bobble,[b] internationally known as Bust-A-Move, is a 1994 tile-matching puzzle arcade game developed and published by Taito.

At the start of each round, the rectangular playing arena contains a prearranged pattern of colored "bubbles". At the bottom of the screen, the player controls a device called a "pointer", which aims and fires bubbles up the screen. The color of bubbles fired is randomly generated and chosen from the colors of bubbles still left on the screen.

The objective of the game is to clear all the bubbles from the arena without any bubble crossing the bottom line. Bubbles will fire automatically if the player remains idle. After clearing the arena, the next round begins with a new pattern of bubbles to clear. [...] The fired bubbles travel in straight lines (possibly bouncing off the sidewalls of the arena), stopping when they touch other bubbles or reach the top of the arena. If a bubble touches identically-colored bubbles, forming a group of three or more, those bubbles—as well as any bubbles hanging from them—are removed from the field of play, and points are awarded. After every few shots, the "ceiling" of the playing arena drops downwards slightly, along with all the bubbles stuck to it. The number of shots between each drop of the ceiling is influenced by the number of bubble colors remaining. [...] If they cross the line at the bottom then the game is over.

Special bubbles


When you shoot on a fire bubble, it exploded.


When a bubble hit the water bubble, all bubble below it will be recoloured to the colour of the hitting bubble.


Destroy all bubbles left or right from hit.


Remove all bubbles with the same colour of the hitting bubble.

Game modes


Single player game, simple clear all 99 levels.


Play against a cpu all 99 levels. At the beginning the cpu is very slow and stupid, but will increase in the higher levels.
You can send bubbles to the cpu field, when you drop bubbles from your field.

VS Human

Two player game. Every player has three lives. When you win a round, you steal a live from your opponent.


There is an inbuilt level editor, to run it, load the cartridge and type

run "edit"

With left/right choose your level, left click will place a bubble, right click will remove it. To store the level, hit the S-Key or click on the save button. Don't forget to save the Cartridge (ctrl+s) otherwise your work will lost.

Feel free to publish your own level pack!


Download for native windows, mac, linux and raspi version can be found here: https://gpi.itch.io/puzzle-duck


Puzzle Bobble Main Theme
Composition by ‎Kazuko Umino and Yasuko Yamada

Pico-8-Version based on the version from Thomas Alberg

P#134948 2023-09-27 10:20 ( Edited 2023-09-27 10:51)

:: Unfold ::

according to the manual:

 A += 2   -- EQUIVALENT TO: A = A + 2

// note that the LHS appears twice, so for TBL[FN()]+=1, FN() will be called twice.

ok, let's test it:

 function fn()
   print("in function")
   return 1

 f={ 10 }
 print("f[1] is "..f[1]) 
 print("f[1] is "..f[1])

the function fn is only called once!

P#134947 2023-09-27 09:42

:: Unfold ::

by GPI
Cart #mosaik-1 | 2022-11-14 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#120604 2022-11-13 13:24 ( Edited 2022-11-14 14:39)

:: Unfold ::

Cart #crillion-2 | 2022-10-31 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

A very simple game. Your goal is to destroy all blocks. The problem: You can only move the ball horizontally, the ball moves up and down automatically.

Crillion is an adaptation of the game of the same name on the C64. This release contains the levels of the three official Crillion releases: Crillion, Crillion '93 (hard), Crillion II (very hard). In addition, the levels of Brainion are included, which are designed more than puzzles. And "Junior" from Crillion Junior - a very easy level set.




In order for the blocks to break, the ball must be the same color as the blocks.



This allows the ball to be colored.



Skulls destroy the character.



Rings can be pushed in one direction if the color matches the ball.


Binaries for Linux, MacOs, Raspi and Windows:


This release contains the levels from


Published in Happy Computer, 1988/07
By Oliver Kirwa

Crillion '93

Published in 64'er Sonderheft 85
By Oliver Kirwa

Crillion II

Published in 64'er Sonderheft 54
By Oliver Kirwa


Published in "Digital Talk #104"
By "The Joker" and "Dr.Guru"

Crillion Junior

by holy moses

Level editor

A level editor is available. It is based on "jaP8e" ( https://www.lexaloffle.com/bbs/?tid=49307 ) and must be copied to the "libs" directory of "jaP8e".


Oliver Kirwa for Crillion, Crillion'93, Crillion-Construction-Kit and Crillion II.

"The Joker" and "Dr.Guru" for Brainion

holy moses for "Crillion Junior"

Darrell Flood for the "Sloppy Paint" font (used for the Logo)

P#119855 2022-10-30 13:23 ( Edited 2022-10-31 13:04)

:: Unfold ::

SDK-Units of consoles have normally more memory.

This can be useful during developing - simple try something without care about limits. Or store additional debug information.

it would be nice, if pico-8 would emulate this.

This can be done very simple:
The project must be saved as ".p8"-utf8-file.
When the project hit the limit of characters, compressed size and token it will display the known warning with a little addition: "Ignore? (Project can't be exported!) (y/n):" - when you hit y - it will start anyway. Save as .p8 is always possible, since there are no limits.
Of course the export to bin, web, rom, png or whatever is not possible. also the cli-command "-run" should not work on this oversized p8.

This would be usfull, when you want to check, if something work. Or when you developed a tool / level editor for a game, which you don't want to share.

additional it would be nice to have an debug - enddebug - command

function test(a,b)
   if not a or not b then
     print("this should not happen! Got nils!")

this code should only start when pico-8 is in devoloping-mode.
when it saved to p8.png ( or p8.rom, bin, web), pico-8 should interpret this as comment.

function test(a,b)
   if not a or not b then
     print("this should not happen! Got nils!")

So the token-limit should not be affect by the debug - enddebug block.

P#118304 2022-10-01 19:34

:: Unfold ::

Cart #variablefont-0 | 2022-09-28 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

A very simple font. A little bit bigger than the original, but better readable.
the UTF Latin-1-Suppliment-Characters are included instead the Japanese characters.


load "#variablefont"

in pico-8 to load the cartridge.

Created with jaP8e - https://www.lexaloffle.com/bbs/?tid=49307

P#118120 2022-09-28 18:08 ( Edited 2022-09-28 18:24)

:: Unfold ::

I tried to decompress the source code of my dithering-demo:
and my code failed.

First i thought my code is wrong, I translated from this source:
the decompress-code to lua, so it is possible that I made a mistake.

I can't find a erro, so I looked at the rom-data:

4300  00 70 78 61 03 BC 02 39 02 40 C1 AC CE 6D 8C 2E  .pxa.¼.9.@Á¬ÎmŒ.

the first 8 bytes (00 70 78 61 03 BC 02 39) are the header, so the first databyte is 02
or binary: 00000010

When I look in decompress code:

while (src_pos < comp_len && dest_pos < raw_len && dest_pos < max_len)
        int block_type = getbit();

        // printf("%d %d\n", src_pos, block_type); fflush(stdout);

        if (block_type == 0)
            // block

            int block_offset = getnum() + 1;
            int block_len = getchain(BLOCK_LEN_CHAIN_BITS, 100000) + PXA_MIN_BLOCK_LEN;

            // copy // don't just memcpy because might be copying self for repeating pattern
            while (block_len > 0){
                out_p[dest_pos] = out_p[dest_pos - block_offset];

it read the first bit (a zero) from 0x02 and go through the block_type==0 code.
At this moment the out_p is complete empty and dest_pos is 0, so when the code comes to "out_p[dest_pos] = out_p[dest_pos - block_offset];" it copied data BELOW the output-buffer.

P#117305 2022-09-12 20:31

:: Unfold ::

Cart #yemapepoke-0 | 2022-09-12 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

A little demo of importing dithered pictures. The rom contain 3 pictures, switch with x/o.

Images are created with jaP8e

P#117283 2022-09-12 16:50

:: Unfold ::


  • Source code in lua!
  • Editor for sprite, map, sound, music, charset
  • Map editor with support of custom width / size
  • Name sound and music
  • Custom palette with the extended 128+ color-ids (32 Colors in total)
  • Charset editor with possible to export single characters and variable width
  • Hex editor to copy & past memory to pico-8 string (URL raw memory access format )
  • Modular design
  • Import images as sprite sheet, map(!), label - with optional dithering


This is a beta release! This means, there are bugs, the program can crash. Make backups before using the editor.



basic control/setup

Set the path to pico-8.exe

jaP8e needs to know where the pico-8 execute is. Choose in the Menu the "Pico-8" > "Set Pico8 exectuable" option to set the path. Otherwise it can't run any code or playback sound.

Pico-8 Remote

Since I don't know how to program sounds like in pico-8, jaP8e can't playback sound by default. But it is possible to start a "Remote"-pico-8, which runs in the background and is controlled by jaP8e. Activate this option in the "Pico-8"-menu. After this you can playback any sound effect and music during jaP8e.
This function starts a pico-8 with the remote.p8 file in the background. I send commands through stdin/stdout to this remote.

Change Values in the grey input boxes

You can change the values of the grey input boxes by left click in it and use the keyboard. Alternative you can press and hold the right mousebutton and change the value with x-mouse-movement. The third possibility is to use the mouse wheel over the input fields.

basic layout

On the top you find the modules-tab to switch the editors. On the right top side are currently open files. A Star in the file name indicates that the file has unchanged data.

memory layout

jaP8e "simulate" the memory of pico-8, with a rom and ram section. The rom-section is stored normaly like pico8 does and can access normaly. RAM is stored as meta-data and can't access directly in pico-8, but you can export ram as string to copy in the source code (HEX-Editor).
Also you can reposition the map, sprite, sound, music, spriteflags to any memory location, even when pico 8 doesn't support it.
For example, when you don't use a map in your pico-8-project, you can store there additional sprite data. Simple reposition the sprite to 0x1000 to draw in the map-data. In pico-8 you must manually copy the memory (memcpy) to access this additional sprite data.

Error-message and disable a module

When a error happen, a message box with ok and cancel will open. With ok jaP8e will ignore the error. With cancel the module which cause the error will disabled. At least you can try to save your work when a error happen.

Source Editor

on the left side of the window you find some information tabs:


display every function that jaP8e found in the current tab. Also all comments which start and end with "--" should be visible here.
You can click in the list to jump to the position.
When the cursor in the source code is inside a function, this function will be highlighted in the list.


Fast display of all sprites. When you select a number in the source code, the sprite with the same id is highlighted.
Click on a sprite will add the id-nummer in the source code


Click on a char to add this in the source code.


When you select a number in the source code, the sound with the same id is highlighted. Press ALT + SPACE to playback this sfx.


same as sound


show the custom palette (when not changed, this is identical to default), the default palette and the extended palette

Source code editor

Should react nearly the same as the default editor in Pico-8 with some extras. Tabs work as in Pico 8 - simple click in the "+" above. You can also name the tabs, when the first line is a comment.
When you select a word, it will highlight this word in the complete source code. Also when the cursor is over the a brace the matching other brace is highlighted.
When you don't like the color-scheme, you can edit the jaP8e.ini file.
By default the puny-font is disabled and a normal font is used, so all text should be written in lower case!
Copy & past will always ignore the puny-setting.
Look in the menu for many additional functions / keyboard shortcuts.

Map editor

On the left side you can select a Sprite - you can select more than one.
Grid add a grid, id will display the ids, flags draw a bar with the spriteflags and count shows how often a sprite is used in the map.
With CTRL + Click the current Sprite will exchange the position in the Spritesheet and the map will be corrected.
With CTRL + SHIFT + Click it will exchanged without correction.

You can also quick-select patterns in the map by right click and hold. Middle-Mouse button will scroll and the wheel will change the zoom.

Below you find some options:
Grid will add a grid to the map, ID will draw the ids of the tiles, when find is active, the selected sprites of the sprite sheet will highlighted in the map.
Also you have different tools like stamp, line etc.
With POS you can change the position of the map in the memory and Width will change the width of the map.
With Background you can select a color to change the background.

You can quickselect a sprite with the shift/a/s/d/w-keys

In the Menu with File > import > map image you can import an image as Map! The image will sliced in tiles and added to the sprite sheet, when an empty slot is available.

Sprite editor

Control nearly the same as the map editor.
POS and FLAG-Buttons will change where the sprite / spriteflags are located in the memory.
Set Icon will change the icon when you export an binary.
Right click on the color to change the palette.
Important: Palette changes are stored in the ram-section and must be exported in the hex editor to the source code.

Sound editor

Should work like the original pico-8 editors. Like in sprites you can with CTRL+Click / CTRL+SHIFT+Click exchange the SFX.
You can additonal name a SFX with 8 characters. This information is stored in the meta-data of the p8-file and is only for your information and not directly useable in pico8.

Music editor

Can do the same as the pico8 editor.
When you paste a music, the sfx-pattern will be insert at top by default (pico 8 start at bottom). You can change this behaviour in the edit-menu.

Label editor

Also very basic. You can import an image with the file->import->label image in the menu bar. In the settings-menu you can select activate dithering.

Charset editor

Important note: Charset is always located in the memory section (0x5600). When you want to use it, you must copy it in the hex editor!
Work like the Sprite editor, but only with two colors. On the right button you can set some basic settings. Variable font with is supported, when you activate "Adj.Enable", then you can use the "Adj"-field to change the with of the current char (like in the picture, I is here only 2 pixel with.
When you click on the "lazy dog" text you can switch between different example text.
When you ctrl+c on a char, it will copy as a string, that can be use directly in pico 8 URL pico8-manual. In the edit - menu you can select between binary-char and hexadecimal-char version.
Of course you can paste chars in both formats.

hex editor

On the left side you have some select buttons. The "ROM" button select the default position of the items. Under "RAM" you can select some areas which are used by jaP8e. When you move the Sprite/Map/and so on with the "POS"-button, you can select the area here with the "POS"-mark.
The Hex-Buttons below select the memory 0x8000 - 0xff00 location. Click with shift to select to the end of this memory-block.
You can Copy & Paste memory blocks. It is stored as string in the clipboard in the URL raw memory access format and can be simple copied in the source code!
For example the default palette from memory look like this:


IMPORTANT all data above 0x4300 are saved as meta-data and are not accessible directly by a pico-8 program.


In the Pico-8 menu you can start your project. At default jaP8e switch to write protect mode and will reload after pico8 is closed (this can be disabled in the pico-8 menu). Your project must be saved before this will work.
You can also export here binarys (you can select a icon in the sprite editor), webpage, .p8.png and more.
The RAM-Section of the current project will be stored as meta data in the .p8 - file. This is way jaP8e can only p8 files directly.

what is luatik?

Luatik is my lua interpreter variant. I patch lua with some features (auto load libraries, += -= is possible and some other goodies). Look in the lunatik-order to get more information.

P#117276 2022-09-12 15:56 ( Edited 2022-09-12 16:11)

:: Unfold ::

I think, that it is common to print a text in center of the screen.

With the variable font it become a little bit complicated..
When the text is variable we must do something like this.

str = "text"
len = print(str,0,-0x4000) -- print outside to get the length
print(str, 64-len\2, 128)

it would be nice, when instead of the x-coordinate a string with the position could be added

str = "text"
print(str, "center", 128)

possible "key-words" would be: "left", "center", "right"
for y would be "top", "center", "bottom"

btw. a "printsize" function would be nice, don't draw anything, only return width and height in pixels.

P#117266 2022-09-12 10:30

:: Unfold ::

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

Recreation of a C64 classic: Castles of Dr. Creep.
Compared to the original there are some changes, on the one hand because the layout is different (40x24 vs 16x16), on the other hand because I have defused some "backtracking" and death traps. Nevertheless, please note, the levels are from 1984 - there you have something different design.


So, you're looking for a place to work? Something special, challenging, with a good salary? Well, we have just the thing for you.
Many different options open for your inspection. Just step inside ... Oh? You want to leave already? I'm afraid that's simply not possible ... not until you have taken the complete tour.
You'll notice that we have all the modern conveniences. Electrostatic energy generators to warm things up. Piped-in music which I'm sure you will find quite haunting. Doors galore, and you never know what you will find on the other side. Once the death rays start lining up behind you, however, I know you will be eager to find out.
You may want to step lively over trap doors and through the force fields - we've lost several potential applicants that way. Over there, of course, is mummy's room. Mummy seems to be all wrapped up at the moment, but probably not for long. And a break room? At the Laboratories, all the rooms are restful, although many of the occupants are not.
Neighbours, you ask? I Know you will love them. Frankenstein's Monster just seems to pop up whenever you least expect him.
Well, I really must be leaving now. I'm sure you can find your way around. Don't be alarmed. There's a key in here somewhere. You will find your way out eventually... and if not, Doctor Creep will be back shortly and you can help him with his, ah, experiments.
Goodbye now ... and good luck.

Playing the game

You are captured in a Laboratories and your goal is to escape.
Open a map with 🅾️.
In the pause menu you can save a game state. Note that the status is stored before entering the room.




Doors and Doorbells


One way to open a door is to use the doorbell. Operate the doorbell by standing in front of it and pressing the ❎ button. To go out an open door, stand in front of the door and press ⬆️ or ❎.



To get on a ladder, stand directly behind it and push ⬆️ or ⬇️. You can get off of a ladder whenever your feet are even with the front of a walkway.

Sliding Poles


To get on a sliding pole, stand directly in front of it and pull ⬇️. you cannot climb up the sliding poles. You can get off of a pole whenever your feet are even with the middle of a walkway.

Lightning Machine


Turn the sparks on or off by standing in front of the switch and push ⬆️,⬇️,❎.

Force Field


Turn off the force field by standing in front of the control and pushing ❎. The force field will remain off for a few seconds after the button is released.



When you run in front of the ankh, the mummy slides out of its tomb. Mummies are
too stiff to use ladders or sliding poles.

Locks and Keys


To pick up a key, stand in front of it and push ❎. You can open a lock only after you have picked up a key of matching color. Stand in front of the lock and push ❎.

Ray Gun


Operate the gun by standing in front of the control and using ⬆️ and ⬇️ to aim and ❎ to fire. The gun fires automatically when it is at the same level as a player.

Matter Transmitter


Stand in the booth and hold ⬆️ until the color in the booth matches the color of the desired receiver oval. Push ❎ to transmit.



The trapdoor opens or closes whenever anyone runs in front of the control.

Frankensteins Monster


When you walk in front of his coffin, frankensteins monster awakens and begins to chase you. frankensteins monster is able to use the ladders and sliding poles.

Conveyor Belt


To change the motion of the conveyor belt, stand in front of the control and push ❎.

The exit Door


The door at the right leads out of the laboratory. When you go out this door you have escaped.


https://github.com/GPIforGit/The-Laboratories-of-Dr.-Creep/releases - download the assets

There is a editor, splitted in several files:
creep.p8 - the game - stand-alone
creepbuild.p8 - pack all the data and store it in creep.p8
creepedit.p8 - the level-editor

And some data - no lua code here. Also only parts of the p8 are packed from this files:
creep_endscreen.p8 - the End-Screen, must be placed completely in the shared gfx rom!
creep_levels.p8 - the level-data
creep_mainback.p8 - the main-menu background, must be placed completely in the shared gfx rom
creep_music.p8 - main-menu music.
creep_sprites_sound.p8 - gfx (only 0x0000-0x1000), gfx-flags and sfx are used from here.

You need all the files to edit levels, for playing only the creep.p8

Note that when you save the level data, it is stored in "creep_levels.p8". When you want to test your level, you must run creepbuild.p8 or choose in the pause-menu "build".

There is a limit of 31 rooms and 15 of every object. First select a object with the keys, than place it with the left mouse button.

A switch can operate more than one machine. After placing a switch you can link the switch to a machine by simple click left on the machine. Right-click will quit link mode. To relink right click on a switch.

Doorbells and locks work the same, link them with doors.

When you place a door, you must set an connected door. Move the room with + - < > or switch room over the map (tab) and place there the second door. When you place the second door in the same room you create an exit-door.

With tab you enter map mode. Move the cursor over one map and press tab again to enter the room. With left-click on a room you can move it, right click to resize it.

The best way to edit the labs is to open pico8 twice, once the editor and once the game. If you want to try something out, select "build" in the editor pause menu and then ctrl+r in the game to reload the changes.

Working with the editor

Important - keyboard is only detected, when the pico8-window is activ and the mouse cursor is in the window!

left mouse button --- set object or move the object under the cursor

right mouse button --- change size of object under the cursor or go through a door or start/stop linking object (switches, door bells or locks)

0-9 * / . , --- change state/color of the object, for example the color of the walk ways, active/deactivate, change direction and so on

backspace --- delete the active selected object. Important, when you delete a lightning machine or a door, you should check every machine, switch and doorbells - they may be invalid.

space -- walk through door

w -- walkway
l -- ladder
s -- sliding poles
d -- door
b -- doorbell
o -- lock
k -- key
c -- conver belts
m -- lightning machine
i -- switch for lightning machine
f -- force field
t -- trapdoor
x -- matter transmitter booth
v -- transmitter destination
u -- mummy
r -- frankenstein monster
g -- ray gun

  • > -- next room
  • < -- previous room

shift+r -- rename lab when you empty the name, the lab will be deleted.

shift+s -- save (but not build!) the level data.

shift+e shift+1 -- start position player 1

shift+w shift+2 -- start position player 2

tab -- enter map mode

ctrl+c shift+c -- export lab as clipboard-string

ctrl+v shift+v -- import lab from clipboard

behind the scenes

Some may have guessed it already, the game is a "The Castle of Dr. Creep" clone. A classic on the C64 from 1984 and was quite unique at the time.

The original game is relatively complex and uses a complete floppy disk. The problem here is that I wanted to insert as many of the castles as possible. To put them "classically" in the map data does not work, much too large, so a level editor had to be created. Writing it in Pico8 was not so easy, it is almost more complex than the game.

A special feature of the level data is that I do not save byte wise, but bit wise. For example, to save the status of a trapdoor, I need exactly one bit. This method is also used for the game saves, otherwise it would be partly impossible to accommodate this in 256 bytes. However, I had to cheat a bit, for example, a round position of the creatures is stored. It is possible that a loaded game does not always remain solvable. But I think I've solved the problem.

In addition, I use the lzw logarithm to store even more data. it is possible to place data in source code via string, but somehow I find that inelegant. The packed data also has the advantage that it can be edited more easily with tools without changing the lua code.

Compared to the original castle, there are some changes, on the one hand because the layout is different (40x24 vs 16x16), on the other hand because I have defused some "backtracking" and death traps. Nevertheless, please note, the levels are from 1984 - there you have something different design.

The game should be similar to the original, but not just copy it. I've made some changes. The monsters, for example, always go at the closer player (in the original it was always player one). Likewise the map, in the original it appears after each level and you have to confirm it, I immediately switch here to the next room. This increases the game speed enormously.

The story text is a variant of the text on the back of the box. The object descriptions are variants of original tutorial.


P#99419 2021-10-31 16:09 ( Edited 2022-09-21 11:31)

:: Unfold ::

by GPI
Cart #lzw-1 | 2021-10-30 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I have translated and extend the lua code from here
I tried to reduce the token count, but I wouldn't surprised when someone will shrink it more.

lzw is the codec that for example gif use, it was patented, but it expired 2004.
more information:

I tested the code with the JELPI-Graphic&Sound data - and it will compress it to 6094 Bytes (from 17152 - ~36%).

With the next update the high-memory above 0x8000 will be useable (at the moment only with a undocumented poke), my plan is to place there 32kbit of graphic and sound data. The problem is, that this memory is not saved and I don't want to store it in the source-code because it is too big.

With this code I can compress the 32kbit and store it in the "rom" (the lower 0x4300 bytes). Create a "build"-cart which fill the 32kbit (for example with the reload()-function from other carts), compress the data and cstore() the compressed data.
Copy the compressed data to the the "game-cart", on start decompress the data in the high-memory-area and copy then the part currently needed in the map/sprite-memory.

About the tape_()-function: Think about it like a "punched tape" - it can be used to store datas with variable bit-size. You can use it also for the "Persistent cart data". Normaly you can place 256 Bytes. When you want for example to save if a door is open or closed, you need only one bit. With this routines you can easily store 256*8 = 2048 Doors. The routine should handle 1 to 16 bit values.

P#99373 2021-10-30 13:10 ( Edited 2021-10-30 18:27)

:: Unfold ::

it would be nice, when the poke() would return the address after the poke, like print() does.

for example:


should do the same as




instead of



adr = poke(adr,ord(str,1,#str))


P#99326 2021-10-29 18:14

:: Unfold ::

it would be nice to select where the pause menu should appear. Also the possiblity to draw a custom background for the pause.

For example for a RPG. It would be useful to draw the player-status on screen and the pause-menu on the right button of the screen. In combination with the menuitem-command it would be an easy and "cheap" possibility to create a status-menu. Or display a map of the current level, an inventory and so on.



position could be 0=top left, 1=top, 2 top right, 3 left, 4 center (default), 5 right, 6 bottom left, 7 bottom, 8 bottem right
And draw-function is a function which is called direct before the pause-menu appears.

P#99173 2021-10-26 18:26

:: Unfold ::

When you want to use the shared part of the worldmap, you can only definied 127 Sprites. In Map-Editor the high-bit 0x80 is completly unused.

It would be nice to set a "Map mode" to use this "wasted" bit. Possible solutions would be one of this

  • Flip X
  • Flip Y
  • Use second palette / apply fill pattern

With Flip you can simple reduce the needed sprites with flipping:

Also second palette you can reuse sprites like here (cloud/bush)

oh, and of course a combination would be nice:

It would be nice to set all effects for every cell, but we only have one bit....

Maybe an additional mode would be nice

  • flip depending on screen quarter

    But this could be a little bit confusing. It should orientate on Map-Values, not display.
P#98122 2021-10-02 13:12

:: Unfold ::

by GPI
Cart #picman-1 | 2021-10-02 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA


It is a Pac-Man close, so simple use the direction-buttons to control Pic-Man.



You control Pic and your goal is to eat all pills to win the maze.

Don't touch the ghosts, they will kill you.

When you eat a power pill you become strong enough to eat the ghosts.

In every maze two fruit will appear in the middle of the maze, don't miss them.

Every 1000,2000,4000,... points you get a extra live.

Behind The Scenes

I watched URL Game Maker's Toolkit and was amazed, how "complex" the ai of the ghost are. Since Pic-Man was my first PICO8-Project I decide to re-program Pac-Man. And so many problem started.
First problem, the maze, with a 8x8 tile size it is simple to big for the 128x128 screen. 6x6 would fit, but the map-system is not flexible enough. And so I remembered, that on the old classic c64 you often used the print-command. And again a new problem, how to design the font and how to store it? So hours later a created a URL CharSet Editor and this problem was solved. So the maze is on the screen, now place the pills. First I tried to place the pill exact like the original, but it doesn't work, since my maze is compacter. So i placed more pills and between the "tiles". First I used sprites to draw the pills-dot, in other systems it is nearly always better to use a sprite/texture instead of drawing direct. Big mistake, it will consume around 90% of the virtual cpu - so I changed it to pset()-commands and now I only consume around 50%.
Next step: The main character. Not difficult, he simple runs in tiles and can only change the direction on every tile. The first version couldn't go backwards, but because in the first levels Pic-Man is faster then the Ghost, I changed this. Also the Original could do this. To draw Pic-Man I used 4 sprites, since I only draw a quarter of Pic-Man and use the flip options of the spr-command.
I wanted as less sprites as possible.
The ghost AI was also many try and errors. My ghost react a little different from the original, they have similar behave, but the ghost go more randomized. Also one Ghost really like the fruits. One Problem was, that it could happen, that two ghosts are run exact the same way and nearly the exact same position. So now when two ghost touch each other and go to the same direction, I forced to change one to choose a different direction at the next possible tile. Same as Pic-Man, the ghost are 4 Sprites. Two for the top, one for the bottom (because of the wave-animation) and the eyes.
So now how to create the title-screen. I don't find that the original looks nice, so I searched for artwork. And the next problem - how can I got a picture to a PICO8-rom? Again hours later a new tool was born: URL GFXedit. I used only the the shared part of the spritesheet to save the graphic for the title screen. My plan was to use more artwork and replace the shared part. At the end I only add a game over screen, because I run out of space.
So next big problem Music. I'm not a musician and have no idea of music work. I don't like the original wakka-wakka sound of Pac-Man, I like more the Pac-Mania-Music, but how transfer this to PICO8? Midi-files would maybe a solution, but PICO8 can't open it and I have no idea, how the midi-files work. By accident I found MuseScore 3 and the possibility to export to musicxml, a text-based format. So again hours later a wrote a little program to convert the musicxml to pico8 (Sorry unpublished at the moment, because it miss any interface). I'm not really happy with it, but it work.
In the first version I only add one Level, the original one. But since I draw 12 Fruits, I want more than one level. This was first a problem, because I added the pill-position as static data, now I must phrase the level-data to generate the Borders, add the pills, where the fruit appears and where the ghosts and Pic-Man starts. You can edit the mazes in the source-code and more, if you like.
Since the music used much more than 64 sfx-sounds, I placed the sound-date in the sourcecode. I have optimized the data-format (first one was a big hex-string [[0000a0e01002]], second improve the format [[,,a0,e0,10,2]] and the third uses a special-char-format, so it used nearly everywhere only one char per byte. BTW. one song is too long, it has more than 64 sfx. When the first part is finished, I poke new sfx and music-data in the memory and play part 2.
I had planed to add a third song, but he doesn't sound good and I had again a Problem: over 100% compression. Sadly I must delete the first tab of the code - a big comment with the global variables and what they do.
Now the project is complete - It missed the Intermission from the original, but I have no place any more. I also don't have a good idea to add new ones...
And finally I add a volume-control. It live-patch the sfx-data to reduce the volume.

Very long text - did someone read it complete?


Used Tools

URL CharSet Editor
MuseScore 3
Corel PaintShop Pro X7

Used resources

URL Pac-Man Wiki - Pac-Man Gallery
URL Pac-Man Maze Generation
URL Pac-Man by MineWarz
URL Pac Man Death by YaketyGrass
URL Block Town / Sequenced by: Oedipus / Originally Composed by: Ben Daglish
URL Pacman's Park / Sequenced by: Oedipus / Originally Composed by: Ben Daglish

P#98065 2021-09-30 22:02 ( Edited 2021-10-02 19:11)

:: Unfold ::

It is possible to write a string (for example for a hiscore-table) to the memory with:


but this:

? chr(peek(0x5e00,5))

doesn't work, because chr only accept one value.

P#97989 2021-09-29 17:11

:: Unfold ::

GFXedit for Pico8


GFXedit is a small tool to handle the sprite, map und label data from a p8-file with many features, like export and import as png or lua-data, copy&paste, display the usage of sprite and many more.


github.com - GFXedit

Sprite-Overview (left side)

You can simple select an sprite with a left click. If you hold down the mouse button, you can select a group of sprites.
With a right click you can Copy the current selected sprite to the "red border" place. When you have selected only one sprite, shift + right click will replace every appearance in the map.
Over/Under the Sprite overviews are Tabs. "Low" to show the sprites <= 127, "High" for sprites >=128 and "Minimap" to activate the minimap.
Under the Sprite-overview you can find the coordinates in the world (if the cursor is in the Worldmap, the ID of the sprite under the cursor and the flags of the ID under the cursor. You can also sets flags of the current selected sprite here.
Below that you find some views:

"Flags" activate a small bar under every sprite with small indicators which flag is activ.

"ID" show the HEX-Id over every Sprite

"Count" show of often a sprite is used.

"Grid" activate a small grid

Editor-Overview (right side)

You can select between "Map" - the world editor, "Sprite" - the sprite editor and "Label" a label-viewer of the p8-file. Map and Sprite can be edit, labels only displayed (but in- and exported).
With left click you draw in the map/sprite, with right-click you select a current object under the cursor. You can select multiply objects with the rubber band to copy complete structures. You can even select multiply objects in the map and switch to the sprite-mode to edit this object.
Under the editor field you find some options:

"Stamp" - simple draw in the map / sprite

"Line" - draw a line

"Box" - draw a box

"Ellipse" - draw a ellipse

"Fill" - fill (on map it is clipped by the current visible screen)

"Filled Box" - a filled box

"Smart Box" - a variant of box, when you select an 3x3 pattern in the sprite sheet, it will then draw a box in the editor, it will more "stretch" the selection to the draw box.
For Example, when you right-select something like this:

And draw a Box, it will look like this:

"Filled Ellipse" - a filled ellipse

"ID" - display the id over every tile in the editor.

"Grid" - display a grid over the editor

"Copy 00" - when active (default) sprite-id 00 and color 0 is draw with stamp/box. Otherwise it will be ignored / transparent.

"Find Sel." - the current objects blinks now in the editor and minimap.

"Hi as Hex" - A special and experimental mode. Since "Sprite High" and "Map High" use the same memory, many prefer the map data. Now the high bit is completed unused in the map data. The idea here is, that you can use the useless High-Sprites as indicators in the world. For example place a sign the world (from the lower sprites), activate the "Hi as Hex"-mode, now select a high-sprite (for example "80") and place it over the sign in the map. The sign-ID is now copied to the Sprite-flag of "80" and the editor shows a sign with an 80 over it.
Of course PICO8 can't handle this, you must write a code that scan the map-data for sprites over 128, store the places in a table and replace the map-data with the sprite-flag of the high-byte-sprite.

"Colorfield" - in map mode you can select a background color, in sprite mode the current color.

"1" to "10" - a zoom level.

"Load Cart" - load data from an p8-file. Only graphics, sound and lua data are ignored.

"Merge Cart" - select an p8-file and it will replace the graphic-data in this file.


You have here multiply options to export any kind of data.
You can export as image:

"Sprite complete" - export the complete sprite-sheet (128x128 pixels)

"Sprites low" - export the sprites 0-127 (128x64 pixels)

"Sprites high" - export the sprites 128-255 in the shared memory (128x64 pixels)

"Map complete" - export the complete world map (1024x512 pixels)

"Map low" - export the "upper" part of the map (1024x256 pixels)

"Map high" - export the "lower" part of the map in shared memory (1024x256 pixels)

"Label" - export the label used for cartridge-export of pico8

"Map screen" - the middle 16x16 tile big screen in the map-editor as image (128x128 pixels)

"Sprite selection" - the current selected sprite (vary in size)

You can also export as lua-data. You can then copy this data in the pico8 code editor and switch dynamical between diffrent sprite oder mapdata. You can also use this to exchange maps between p8-files.

"complete" - contains all map, sprite and spriteflags.

"sprites complete" - contains low and high sprites

"sprites low " - contains sprites with id <= 127

"Map low " - the upper part of the map

"Shared" - the shared part the sprite/map data

"Sprites-flags" - the flag data of the spritesheet

"label" - the cart-label - it use address 0x6000 (Screen data), when you want for example a title-screen.

To load the data you need some additional code:

    function str2mem(data)
        local t,a,i,c,d,str,m = split(data)
        for a = 1,#t,2 do  
            while i <= #str do
                c,d= ord(str,i,2)
                i+=c==255 and 2 or 1
                if (c>16) poke(m, c==255 and d or c^^0x80) m+=1

    data = [[
    --some funny chars from the export



Almost the same as the export. You can import any image. Colours are automatic translated to the pico8 colour palette. When a image is too big, it can be cropped or resized.
Something special is "Map screen (center)" for images. It will split the image in 8x8 tiles and try to find this tiles in the Sprite sheet. If it not exist, it will replace the first free tile (complete black ones) with this tile.
When you import text/lua, the exported destination is ignored. You can for example import a label as sprite sheet.


Mouse wheel - change selection of sprite (map) or color (sprite)

ctrl + wheel - change zoom

0-8/ shift + 0-8 - change current/background color

Num0 - Num9 - change zoom level

Cursor keys / asdw - change selected sprite (map) or color ( sprite)

shift + cursor keys / asdw - move world map

ctrl + cursor keys / asdw - move world map screen wide

ctrl + z - undo

ctrl + y - redo

ctrl + c - copy/export menu

ctrl + v - pate/import menu

ctrl + o - open

ctrl + s - merge/save

alt + cursor - Sprite-editor: shift sprite

alt+shift + cursor - Sprite-editor: flip sprite

R - Sprite-editor: rotate sprite

About the string format

Graphic data are too big for a string in "", but enclose it with [[]] has the disadvantage that escape-sequenzes are not possible. Also chars lower 16 are not printable.
Chars lower than code 16 must be encode in a special form. Also some special characters like "[]," must be encoded to prevent conflicts.
Because chars lower than code 16 are very common (especially code zero), I first flip the high-bit of the char (m = char ^^ 0x80). If m is now lower 16 or one of the special characters, I store the in the string a sequenz of "chr(0xff)..chr(m ^^ 0x80)" otherwise a simple "chr(m)".


Icon made by https://www.freepik.com from https://www.flaticon.com/

P#97892 2021-09-27 19:19 ( Edited 2021-10-02 18:41)

:: Unfold ::

CharSet Editor for Pico 8


github.com - CharsetEditor_Pico8

Short manual

A simple tool to create fonts for the virtual console pico8.

Left click on the charset to edit this char. Right click will copy the current char to this position.

Left click on the char will set a dot, right click will delete it. With the cursor keys you can shift the current char. "Set Default" will reset the current charater to the default.

"Lo Width" are for chars with a code <= 127, "Hi Width" for code >=128.

With "Copy" and "Paste" you can copy the complete Charset to the clipboard as a string embeded in [[ ]]. Don't indent the string, it could change the font! In pico 8 you need the following code to transfer the string to the memory:

    function str2mem(data)
        local t,a,i,c,d,str,m = split(data)
        for a = 1,#t,2 do  
            while i <= #str do
                c,d= ord(str,i,2)
                i+=c==255 and 2 or 1
                if (c>16) poke(m, c==255 and d or c^^0x80) m+=1

    myfont = [[0x5600,
    --some funny chars


With "Load" and "Save" you can load/save the current font as ascii-file with the extension ".lua". It is the same format as the clipboard routines.

About the string format

A Font is too big for a string in "", but enclose it with [[]] has the disadvantage that escape-sequenzes are not possible. Also chars lower 16 are not printable.

Chars lower than code 16 must be encode in a special form. Also some special characters like "[]," must be encoded to prevent conflicts.

Because chars lower than code 16 are very common (especially code zero), I first flip the high-bit of the char (m = char ^^ 0x80). If m is now lower 16 or one of the special characters, I store the in the string a sequenz of "chr(0xff)..chr(m ^^ 0x80)" otherwise a simple "chr(m)".

Example code

load #customfont_example-0

Cart #customfont_example-0 | 2021-09-26 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#97849 2021-09-26 11:12 ( Edited 2021-09-26 11:16)

:: Unfold ::

I had written a small tool for pico8, but it is written in pure basic and the resulting program is a nativ windows application.

Is it allowed to present this tool here with a link to a github-page, including the source code, the binary and how to use it with pico8?

P#97842 2021-09-26 08:54

View Older Posts
Follow Lexaloffle:          
Generated 2023-10-01 14:40:09 | 0.124s | Q:61