initiale Übernahme

This commit is contained in:
2026-06-03 13:56:26 +02:00
parent c281c28563
commit 262fc39737
805 changed files with 660083 additions and 0 deletions

View File

@@ -0,0 +1,427 @@
PICO-8 Advanced Manual
By ReplayCoding
:: TOC
Video Modes
Palette Changes
Undocumented Functions
Memory Layout
Draw State
Hardware State
Javascript Export
PNG Export
Audio and SFX
Cart Format
BBS
-----------
:: Video modes
Pico-8 has multiple video modes, the default being 128x128. Different video modes can be enabled by setting a value at at 0x5F2C. The multiple modes are listed below
-- from https://neko250.github.io/pico8-api/
poke(0x5f2c, 0) -- standard, 128x128
poke(0x5f2c, 1) -- horizontal stretch, 64x128
poke(0x5f2c, 2) -- vertical stretch, 128x64
poke(0x5f2c, 3) -- zoomed, 64x64
poke(0x5f2c, 4) -- standard, 128x128
poke(0x5f2c, 5) -- mirror left half
poke(0x5f2c, 6) -- mirror top half
poke(0x5f2c, 7) -- mirror top-left quarter
:: Palette changes
The palette can be changed by modifying the PICO8.DAT file. Search for the hex string listed below and replace it with a palette of your own choosing. As far as I know, you cant do this with exported carts.
-- Hex color palette
000000 1d2b53 7e2553 008751 ab5236 5f574f c2c3c7 fff1e8 ff004d ffa300 ffec27 00e436 29adff 83769c ff77a8 ffccaa
-- Actual colors with RGB
From https://www.romanzolotarev.com/pico-8-color-palette/
#000000 (0, 0, 0) black
#1D2B53 (29, 43, 83) dark-blue
#7E2553 (126, 37, 83) dark-purple
#008751 (0, 135, 81) dark-green
#AB5236 (171, 82, 54) brown
#5F574F (95, 87, 79) dark-gray
#C2C3C7 (194, 195, 199) light-gray
#FFF1E8 (255, 241, 232) white
#FF004D (255, 0, 77) red
#FFA300 (255, 163, 0) orange
#FFEC27 (255, 236, 39) yellow
#00E436 (0, 228, 54) green
#29ADFF (41, 173, 255) blue
#83769C (131, 118, 156) indigo
#FF77A8 (255, 119, 168) pink
#FFCCAA (255, 204, 170) peach
:: Undocumented functions
-- From http://pico-8.wikia.com/wiki/Category:Undocumented_API
holdframe() forces display not to update until flip() is called
_set_fps(framerate) sets the current framerate (15, 30, or 60 FPS)
_update_buttons() refreshes gamepad state
-- Other functions [ seem to do nothing ]
_startframe
_get_menu_item_selected
_update_framerate
_set_mainloop_exists
_mark_cpu
_set_paused
:: Memory layout
There are 32 kilobytes of addressable memory. Most of the the stuff is self-explanatory, but I will explain the draw and hardware state in the following sections.
-- Taken from the manual
0x0 gfx
0x1000 gfx2/map2 (shared)
0x2000 map
0x3000 gfx_props
0x3100 song
0x3200 sfx
0x4300 user data
0x5e00 persistent cart data (256 bytes)
0x5f00 draw state
0x5f40 hardware state
0x5f80 gpio pins (128 bytes)
0x6000 screen (8k)
:: Draw state
-- Taken from http://pico-8.wikia.com/wiki/Memory
0x5f00-0x5f1f: Palette filtering (pal(), palt()). 0x5f00-0x5f0f is palette #0 (the draw palette), and 0x5f10-0x5f1f is palette #1 (the screen palette). The index is the original color number, and bits 0-7 are the replacement color number. Bit 8 indicates whether the color should be treated as transparent (1=true).
0x5f20-0x5f23: Clipping region (clip()). The bounding box is described in four bytes, as coordinates from the top-left origin (0,0): 0x5f20=x1, 0x5f21=y1, 0x5f22=x2, 0x5f23=y2. Notice that this differs from the arguments to clip(): x2=x1+w, y2=y1+h.
0x5f24: (unknown, please update this if you know)
0x5f25: Pen color (color()). The bottom 4 bits are the current color index, from 0-15. The top 4 bits are typically 0 and unused, but when using fill patterns, they will be the secondary color index.
0x5f26-0x5f27: Print cursor (cursor()). 0x5f26=x, 0x5f27=y.
0x5f28-0x5f2b: Camera position (camera()). The x and y offsets are stored as 16-bit signed integers with the least significant byte first. 0x5f28-0x5f29=x offset, 0x5f2a-0x5f2b=y offset.
0x5f2c: Bit 2 (value 4) controls what this value does. If clear, bits 0 and 1 (values 1 and 2) control horizontal and vertical pixel-doubling. If bit 2 is set, they instead control screen mirroring, left-to-right and top-to-bottom, respectively. Thus, a value of 3 would produce a 64x64 screen, and a value of 7 would produce a 4-way kaleidoscope effect.
0x5f2d: If set to 1, devkit mode is enabled, allowing mouse coordinates and keyboard status to be checked via the stat() command.
0x5f2e: (undocumented, but confirmed by zep) If set to 1, causes the current palette scheme (see pal() and/or the 0x5f00-0x5f1f memory range, above) to persist instead of being reset at the end of the program.
0x5f30: (undocumented) If set to 1, suppresses the next attempt to bring up the pause menu. This can be done as late as discovering the pause button has been pressed this frame:
if(band(btn(),64)!=0) poke(0x5f30,1)
0x5f31-0x5f33: Fill pattern (fillp()). 0x5f31-0x5f32 contain the fill pattern as a 16-bit unsigned integer with the least significant byte first. 0x5f33's bit 0 is the related transparency bit.
0x5f34: If set to 1, changes the PICO-8 drawing API to accept color values that incorporate not just one or two colors, but optionally include information about both the fill pattern and transparency right in the color value. From the manual:
-- bit 0x1000.0000 means the non-colour bits should be observed
-- bit 0x0100.0000 transparency bit
-- bits 0x00FF.0000 are the usual colour bits
-- bits 0x0000.FFFF are interpreted as the fill pattern
The remaining values up to 0x5f3f otherwise appear to be either undocumented or reserved for future use.
:: Hardware state
-- Also from http://pico-8.wikia.com/wiki/Memory
These memory addresses represent or control various aspects of the hardware. These are undocumented.
0x5f40: Bitmask to half each audio channel's clock rate. Bit 0 (value 1) is for Channel 1, Bit 1 (value 2) is for Channel 2, and so on. The upper four bits are not used.
0x5f41: Bitmask to enable reverb for each channel. The bits have the same effect as 0x5f40.
0x5f42: Bitmask to distort the waveforms of each channel.
0x5f43: Bitmask to enable a lowpass filter for each channel.
The remaining values up to 0x5f7f are undocumented.
:: Javascript export -- html
When you export a cart in PICO-8 there are two variables that you can set: pico8_gpio and pico8_buttons. pico8_gpio is a list of 128 8-bit numbers. You can access it by peeking at 0x5f80 to 0x5fff. pico8_buttons is a little endian array of 8 binary numbers.
:: Javascript export -- js
The javascript file is an emscripten compiled program. The cart data is stored at _cartdat in compressed form. The compression algorithm is an LZ-like algorithm. A python program is at https://git.io/fx6Gx
:: PNG export
PICO-8 also allows you to export carts in a PNG format. The cart is stored in the two least significant bits of each color channel in the order ARGB (alpha, red, green, blue). The PNG is 160x205, so we have at most 32800 bytes (although only 32769 bytes are actually used.
-- Taken from https://www.lexaloffle.com/bbs/?tid=2400
0x0000~0x42FF: Ram initializer (simply copied to RAM on load, see manual memory map for details)
0x4300~0x7FFF: Code (version 0 is ASCII encoded, version 1 is
0x8000: File version
This is all fairly straight forward and should not surprise anyone. If the version is 1, it means the code is likely compressed and will follow the following format:
0x0~0x3: the string ":c:\x00"
0x4~0x5: length of code (decompressed, big-endian)
0x6~0x7: always zero (could be used for compression scheme in the future?)
0x8+: Compressed data
Compressed data is an LZ like format, supporting a minimized character set so some text takes less space. It takes 8-bit codes to generate a chain of characters, this loops until the output data matches the value located in the header.
The codes are as follows
0x00 xx: "Extended" code. The following byte is copied to the output stream
0x01: Emit a new line
0x02~0x3B: Maps to: " 0123456789abcdefghijklmnopqrstuvwxyz!#%(){}[]<>+=/*:;.,~_"
0x3C~0xFF xx: Copy from buffer
The 'copy' call copies N bytes from -X bytes from the end of the current stream.
offset = (code - 0x3C) * 16 + (code2 & 0xF);
length = (code2 >> 4) + 2;
For a working example, this is what "Hello hello" would be encoded as.
// Header
"3a", "63", "3a", "0", "0", "b", "0", "0",
// Encoded text
"0", "48", // "H"
"11", "18", "18", "1b", // "ello"
"2", // [space]
"14", // "h"
"3c", "26" // "ello", 4 bytes copied from 6 bytes ago
Note: There are no capital letters in the short form encoding, so don't ever use them in your program. Also the maximum number of characters that can be copied from a previous point in the stream is 17 characters, so try to keep your variable names below this threshold. Interestingly enough, minus signs are also not supported by the base character set.
:: Audio and SFX
-- Taken from https://www.lexaloffle.com/bbs/?tid=2341
I didn't see this documented anywhere, and I had to work it out for my drumbeat cart, so I thought I'd save everyone else the trouble and publish what I know.
SFX:
A sound effect is stored in 68 bytes. Sfx 0 starts at address 0x3200, sfx 1 at address 0x3244, and so on.
The first 64 bytes (offset 0..63) store the 32 notes of the sound effect as described below.
Offset 64 is a byte that determines the editor mode: 0 for graph mode, nonzero for tracker mode. This has no effect on playback, just on the mode opened in the editor by default.
Offset 65 stores the playback speed. (Higher values correspond to slower playback, so "speed" isn't exactly the right name, but that is what is used in the editor.)
Offsets 66 and 67 store the loop begin and loop end times. A sound effect contains only 32 notes, but these times may be set to any byte value. All times past 32 simply play silence.
Note format:
A note is stored in 16 bits, two bytes little-endian.
Bits 0..5 store the pitch, ranging from 0 (C in octave 0) to 63 (D# in octave 5). The tracker mode editor can only enter pitches up to 60 (C 5), but it can display and play higher pitches.
Bits 6..8 store the instrument; the values are the same as in the tracker mode editor.
Bits 9..11 store the volume. Volume 0 corresponds to silence.
Bits 12..14 store the effect; the values are the same as in the tracker mode editor.
Bit 15 appears to be unused.
Example code:
-- This code is public domain, feel free to copy, use, and modify however you'd like
function make_note(pitch, instr, vol, effect)
return { pitch + 64*(inst%4) , 16*effect + 2*vol + flr(instr/4) } -- flr may be redundant when this is poke'd into memory
end
function get_note(sfx, time)
local addr = 0x3200 + 68*sfx + 2*time
return { peek(addr) , peek(addr + 1) }
end
function set_note(sfx, time, note)
local addr = 0x3200 + 68*sfx + 2*time
poke(addr, note[1])
poke(addr+1, note[2])
end
function get_speed(sfx)
return peek(0x3200 + 68*sfx + 65)
end
function set_speed(sfx, speed)
poke(0x3200 + 68*sfx + 65, speed)
end
function get_loop_start(sfx)
return peek(0x3200 + 68*sfx + 66)
end
function get_loop_end(sfx)
return peek(0x3200 + 68*sfx + 67)
end
function set_loop(sfx, start, end)
local addr = 0x3200 + 68*sfx
poke(addr + 66, start)
poke(addr + 67, end)
end
Music format:
A music pattern consists of four channels, each of which may have a sound effect played on it, plus some playback control flags.
The patterns are stored in four bytes, with pattern 0 at address 0x3100. Each byte describes one channel.
Bits 0..5 are the sfx to be played on the channel.
Bit 6 is mute. If it is 0, the channel is played; if it is 1, the channel is silenced.
Bit 7 contains the playback control flags:
Byte 0 bit 7 is the loop start flag
Byte 1 bit 7 is the loop end flag
Byte 2 bit 7 is the stop flag
Byte 3 bit 7 is unused
Playback control is as follows (I haven't tested all possibilities here):
When a pattern reaches the end, if the stop flag is set on this pattern, playback stops.
Otherwise, if the loop end flag is set on this pattern, move back until a pattern with the loop start flag set is found, and continue playback from there.
Otherwise, continue playback with the next pattern.
:: Cart format
The format of PICO-8 carts is quite simple. There are seven sections in total: __lua__; __gfx__; __gff__; __label__; __map__; __sfx__; __music__. These sections are described below:
-- header
Each cart begins with the following header:
pico-8 cartridge // http://www.pico-8.com
version [#]
-- __lua__
The __lua__ section contains the code that you write in the code editor. Glyphs may not show properly in an external code editor.
-- __gfx__
-- Taken from http://pico-8.wikia.com/wiki/P8FileFormat
The spritesheet section begins with the delimiter __gfx__.
The spritesheet is represented in the .p8 file as 128 lines of 128 hexadecimal digits. Each line is a pixel row, and each hexadecimal digit is a pixel color value, in pixel order.
This differs from the in-memory representation in that the 4-bit hexadecimal digits appear in pixel order in the .p8 file, while pairs are swapped (least significant nybble first) in memory. This allows you to identify and draw images using hex digits with a text editor, if you like.
A cart is allowed to use the bottommost 128 sprites as the bottommost 128x32 tiles of the map data. That is, if the cart calls map() with coordinates in that region, the data is read from the bottom of the spritesheet, and the map editor can view this memory either way.
In the .p8 file, this data is always saved in the __gfx__ section, even if the cart uses it as map data. Note that this is encoded as a linear series of 4-bit pixels, rather than a series of 8-bit bytes. Tools reading this section and converting to byte format should treat the first hex digit of each pair as the bottom 4 bits and the second digit as the top 4 bits.
-- __gff__
The __gff__ section contains the sprite flags. The flags are stored in two lines of 128 bytes in hexadecimal. The sprite flags are ordered MSB to LSB in the editor: red=1, orange=2, yellow=4, green=8, blue=16, purple=32, pink=64, and peach=128.
-- __label__
The label section stores the label used in the p8.png format. Its format is identical to the spritesheet.
-- __map__
-- Taken from http://pico-8.wikia.com/wiki/P8FileFormat
The map section begins with the delimiter __map__.
Map data is stored in the .p8 file as 32 lines of 256 hexadecimal digits (128 bytes). Each pair of digits (most significant nybble first) is the sprite ID for a tile on the map, ordered left to right, top to bottom, for the first 32 rows of the map.
The map area is 128 tiles wide by 64 tiles high. Map memory describes the top 32 rows. If the cart author draws tiles in the bottom 32 rows, this is stored in the bottom of the __gfx__ section.
-- __sfx__
-- Taken from http://pico-8.wikia.com/wiki/P8FileFormat
Sound data is stored in the .p8 file as 64 lines of 168 hexadecimal digits (84 bytes, most significant nybble first), one line per sound effect (0-63).
The byte values (hex digit pairs, MSB) are as follows:
byte 0: The editor mode: 0 for pitch mode, 1 for note entry mode.
byte 1: The note duration, in multiples of 1/128 second.
byte 2: Loop range start, as a note number (0-63).
byte 3: Loop range end, as a note number (0-63).
bytes 4-84: 32 notes
Each note is represented by 20 bits = 5 nybbles = 5 hex digits. (Two notes use five bytes.) The nybbles are:
nybble 0-1: pitch (0-63): c-0 to d#-5, chromatic scale
nybble 2: waveform (0-F): 0 sine, 1 triangle, 2 sawtooth, 3 long square, 4 short square, 5 ringing, 6 noise, 7 ringing sine; 8-F are the custom waveforms corresponding to sound effects 0 through 7 (Pico-8 0.1.11 "version 11" and later)
nybble 3: volume (0-7)
nybble 4: effect (0-7): 0 none, 1 slide, 2 vibrato, 3 drop, 4 fade_in, 5 fade_out, 6 arp fast, 7 arp slow; arpeggio commands loop over groups of four notes at speed 2 (fast) and 4 (slow)
Note that this is very different from the in-memory layout for sound data.
-- __music__
Taken from http://pico-8.wikia.com/wiki/P8FileFormat (may be incorrect, please tell me is so)
The sound effects section begins with the delimiter __music__.
Music patterns are represented in the .p8 file as 64 lines, one for each pattern. Each line consists of a hex-encoded flags byte (two digits), a space, and four hex-encoded one-byte (MSB-first) sound effect IDs.
The flags byte has three flags on the lower bits (the higher five bits are unused):
0: begin pattern loop
1: end pattern loop
2: stop at end of pattern
The sound effect ID is in the range 0-63. If a channel is silent for a song pattern, its number is 64 + the channel number (0x41, 0x42, 0x43, or 0x44).
Note that this is different from the in-memory layout for music data.
:: BBS
In the following sections, you will find details about API endpoints used by the splore command in PICO-8. Some of them are internal and are not used as far as I know.
https://www.lexaloffle.com/bbs/snippet.php?cart_id=${cart_id}:
This will return a hex encoded P8.PNG file wrapped by a bbcode style tag called cart. If you add a "src" parameter with any value to the url, it will return the source code of the cart.
https://www.lexaloffle.com/bbs/cpost_lister3.php?max={$max_results}&cat=${bbs_area}&start_index=${start_index}&sub=${sub_section}&version=${version_of_asking_program}&search=${search}&cfil=1:
This will return the results of the splore command. It is returned as a PNG file. This PNG presumably contains the search results (No evidence here, just guessing).
https://www.lexaloffle.com/bimg/pi/pi${image_number}.png:
This will return one of the many default profile images. The are 32 different pictures starting from 0.
There are a couple others, but I will not document them here.
:: End
Ummm, what are you even supposed to write here anyway? Is "I hope you find this useful" good enough? Uhhhh.....