![]() 10 ![]() ![]() |
Puzzle Duck




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
Fire
![]() |
[8x8] |
Water
![]() |
[8x8] |
Flash
![]() |
[8x8] |
Joker
![]() |
[8x8] |
Game modes
Puzzle
Single player game, simple clear all 99 levels.
VS CPU
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.
Editor

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
Download for native windows, mac, linux and raspi version can be found here: https://gpi.itch.io/puzzle-duck
Music
Puzzle Bobble Main Theme
Composition by Kazuko Umino and Yasuko Yamada
Pico-8-Version based on the version from Thomas Alberg
https://musescore.com/user/17124701/scores/3979026
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 end f={ 10 } print("f[1] is "..f[1]) f[fn()]+=1 print("f[1] is "..f[1]) |
the function fn is only called once!

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.
Rules
Block
![]() |
[64x8] |
In order for the blocks to break, the ball must be the same color as the blocks.
Changer
![]() |
[64x8] |
This allows the ball to be colored.
Skulls
![]() |
[8x8] |
Skulls destroy the character.
Rings
![]() |
[64x8] |
Rings can be pushed in one direction if the color matches the ball.
Download
Binaries for Linux, MacOs, Raspi and Windows:
https://github.com/GPIforGit/crillion/releases
Episodes
This release contains the levels from
Crillion
Published in Happy Computer, 1988/07
https://archive.org/details/happycomputer-magazine-1988-07/page/n51/mode/2up
By Oliver Kirwa
https://www.c64-wiki.com/wiki/Crillion
Crillion '93
Published in 64'er Sonderheft 85
https://archive.org/details/64er_sonderheft_85/page/n5/mode/2up
http://www.homecomputerworld.com/64ersh.html
By Oliver Kirwa
https://www.c64-wiki.com/wiki/Crillion_%2793
Crillion II
Published in 64'er Sonderheft 54
https://archive.org/details/64er_sonderheft_54/page/n7/mode/2up
By Oliver Kirwa
Brainion
Published in "Digital Talk #104"
https://digital-talk.github.io/
By "The Joker" and "Dr.Guru"
https://www.c64-wiki.de/wiki/Brainion
Crillion Junior
https://www.c64games.de/phpseiten/spieledetail.php?filnummer=7614
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".
https://github.com/GPIforGit/crillion/blob/main/moduleCrillion.lua
Credits:
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)
https://www.dafont.com/de/sloppy-paint.font
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) debug if not a or not b then print("this should not happen! Got nils!") end enddebug ... end |
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!") end --]] ... end |
So the token-limit should not be affect by the debug - enddebug block.


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.
type
load "#variablefont" |
in pico-8 to load the cartridge.
Created with jaP8e - https://www.lexaloffle.com/bbs/?tid=49307
I tried to decompress the source code of my dithering-demo:
https://www.lexaloffle.com/bbs/?tid=49309
and my code failed.
First i thought my code is wrong, I translated from this source:
https://github.com/dansanderson/lexaloffle/blob/main/pxa_compress_snippets.c
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]; dest_pos++; block_len--; } |
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.


A little demo of importing dithered pictures. The rom contain 3 pictures, switch with x/o.
Images are created with jaP8e
https://www.lexaloffle.com/bbs/?tid=49307

Features
- 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
IMPORTANT
This is a beta release! This means, there are bugs, the program can crash. Make backups before using the editor.
Download
https://github.com/GPIforGit/jaP8e/releases
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:
Functions
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.
Sprites
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
Charset
Click on a char to add this in the source code.
Sound
When you select a number in the source code, the sound with the same id is highlighted. Press ALT + SPACE to playback this sfx.
Music
same as sound
Palette
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:
\^@5f100010\0¹²³⁴⁵⁶⁷⁸\t\nᵇᶜ\rᵉᶠ |
IMPORTANT all data above 0x4300 are saved as meta-data and are not accessible directly by a pico-8 program.
pico-8-support
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.
https://github.com/GPIforGit/Luatik
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.
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.
Story
Playing the game
Obstacles
Editor
Working with the editor
behind the scenes
sources
I have translated and extend the lua code from here
https://rosettacode.org/wiki/LZW_compression
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:
https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch
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.
it would be nice, when the poke() would return the address after the poke, like print() does.
for example:
adr=poke(adr,1) |
should do the same as
poke(adr,1) adr+=1 |
or
adr=poke2(adr,0xffff) |
instead of
poke2(adr,0xffff) adr+=2 |
or
str="abcdef" adr = poke(adr,ord(str,1,#str)) |
instead
str="abcdef" poke(adr,ord(str,1,#str)) adr+=#str |
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.
Suggestion:
menustyle([<position>[,<draw-function>]])
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.
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:
![]() |
[16x16] |
Also second palette you can reuse sprites like here (cloud/bush)
![]() |
[24x16] |
oh, and of course a combination would be nice:
![]() |
[16x16] |
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
[16x16]
But this could be a little bit confusing. It should orientate on Map-Values, not display.

Controls
It is a Pac-Man close, so simple use the direction-buttons to control Pic-Man.
Rules
![]() |
[24x16] |
You control Pic and your goal is to eat all pills to win the maze.
![]() |
[16x16] |
Don't touch the ghosts, they will kill you.
![]() |
[16x16] |
When you eat a power pill you become strong enough to eat the ghosts.
![]() |
[16x16] |
![]() |
[16x16] |
In every maze two fruit will appear in the middle of the maze, don't miss them.
![]() |
[64x8] |
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?
Credits
Used Tools
URL CharSet Editor
URL GFXedit
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 GAME OVER
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
It is possible to write a string (for example for a hiscore-table) to the memory with:
poke(0x5e00,ord("hallo",1,5)) |
but this:
? chr(peek(0x5e00,5)) |
doesn't work, because chr only accept one value.
GFXedit for Pico8

Short
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.
Download
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:
![]() |
[16x16] |
And draw a Box, it will look like this:
![]() |
[16x16] |
"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.
Export
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 m,str,i=t[a],t[a+1],1 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 end end end data = [[ --some funny chars from the export ]] str2mem(data) |
Import
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.
Keyboard
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)".
Infos
Icon made by https://www.freepik.com from https://www.flaticon.com/
CharSet Editor for Pico 8

Download
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 m,str,i=t[a],t[a+1],1 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 end end end myfont = [[0x5600, --some funny chars ]] str2mem(myfont) |
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 |
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?
View Older Posts