Description:
Amico8 is a PICO-8 fantasy console emulator for Amiga computers with a
68020 or better processor. It loads and runs PICO-8 cartridges in
both text (.p8) and image (.p8.png) format directly from the Amiga
file system.
Project status:
Amico8 is almost finished. A baseline of roughly 1100 cartridges has
been tested, and 100% of them launch and start playing - with the
AOT/JIT native compiler ON just as with it OFF. Audio support is
at about 90%: all waveforms, the note effects and the music sequencer
are in place, with a few timbres still being tuned to match real
PICO-8 more closely. Bear in mind that "it launches" is not the same
as "bug-free" - while you are actually playing, an individual cart can
still reveal glitches, and a few very memory-heavy carts can run the
Amiga out of RAM. These are being fixed as they turn up.
Features:
- Runs the vast majority of PICO-8 cartridges (.p8 and .p8.png)
- Full 128x128 pixel display, 2x scaled to 256x256 via Amiga copper tricks
- 16-colour PICO-8 palette mapped to Amiga 12-bit hardware palette
- Joystick (port 2) and keyboard input
- Mouse support (port 1) for carts that use mouse API
- Paula audio: all 8 PICO-8 waveforms (triangle, tilted-saw, saw, square,
pulse, organ, noise, phaser) plus the buzz/noiz timbre variants, the note
effects (slide, vibrato, drop, fade in/out, arpeggio) and custom instruments
- Serial PCM streaming - serial(0x808) digitised audio for carts with
sampled speech or music (Berzerk, Impossible Mission, Amstrad chip tunes)
- AOT (Ahead-of-Time) native m68k code compiler - ON by default for a
noticeably faster emulator (switch it off in the launcher, or with the
NOAOT CLI option, if a particular cart misbehaves under it)
- Multi-cart support: load() chains between cartridges (e.g. POOM, The Mind)
- BBS cart browser: browse and download cartridges from the Lexaloffle BBS
directly from the Amiga (requires AmiSSL + bsdsocket.library)
- GUI launcher, with a Check Version button that asks juen.in whether a
newer release is available and can install it for you: it fetches the
build you are running, keeps the old one as <name>.old, and restarts
- Auto Update checkbox: does that check by itself at every start, installs
what it finds and restarts into it, without asking each time
Two executables are provided:
Amico8 - 68020/030 version, no FPU required.
Runs on any Amiga with a 68020 or better.
Amico8_040 - 68040/060 version, optimised instruction scheduling.
Recommended for 040/060 systems.
Recommended processor: 68060.
Usage:
Amico8 - start with GUI! (recommended)
or from CLI:
Amico8 CART=<cartridge.p8.png>
Amico8 ? (show all CLI options)
Controls:
Joystick port 2 / cursor keys - d-pad (btn 0..3)
Z / Y / C / Alt (or fire 1) - O button (btn 4)
X / Ctrl (or fire 2) - X button (btn 5)
Enter - open / close pause menu
P - freeze (debug pause)
F4 - jump to the previous cart *
F5 - jump to a random cart *
F6 - jump to the next cart *
ESC - return to launcher
* F4/F5/F6 work only when started from the GUI launcher (they
step through the launcher's games-folder list). A short
"now loading <name>" splash shows which cart was picked
(press ESC during it to drop back to the launcher instead).
When you return to the launcher, the selection lands on the
cart you were last playing - including one reached via F4/F5/F6.
Limitations:
- Some newer PICO-8 API calls may not be implemented
- Serial PCM (digitised) audio plays on a single Paula channel, so while a
cart streams it the PCM comes out of one speaker (mono), the synth timbre
is close to but not bit-exact with real PICO-8
---
Tested games:
Over 1100 tested PICO-8 cartridges now launch and run - 100% of them, with
the AOT/JIT native compiler ON just as well as with it OFF - and the large
majority already play correctly.
0.9.8
New: an Auto Update checkbox in the launcher. With it ticked, Amico8 asks
juen.in at every start whether a newer release has been posted and, if there
is one, downloads it, keeps the version you were running as <name>.old and
restarts into the new one.
Fixed: a download that broke off part-way through - a timeout, a dropped
connection - was reported as if it had finished, so what arrived was used as
though it were the whole file. That affected the BBS catalogue as well as the
updater. A short read now counts as a failed read.
Single-pixel effects are single pixels again. Asking for a filled circle with no
radius draws one four pixels wide, which is right - but a cart that passes the
radius as an empty value means zero, one pixel, and we were drawing the four-pixel
one there too.
A cart's own font now covers the whole character set. A custom font replaces all
256 characters, but we kept drawing the built-in symbols for everything above
127, so a cart that redefines those got ours instead of its own.
printh(text, "@clip") puts the text on PICO-8's clipboard, which stat(4) reads
back, it used to create a file called "@clip" in the Amico8 drawer. Thirty-three
of the tested cartridges use it to hand you a save string or an exported level.
Carts that build their own graphics in memory work again. sget() and sset() read
and write the real sprite sheet, the memory register that redirects graphics to
another page applies to what the drawing calls read, not to that pair.
Demos that follow the music now keep time with it. A cart can ask how far into
the current music pattern playback is, and how many patterns have gone by.
Carts that draw into single bitplanes now come out right. PICO-8 lets a cart
restrict a draw to some of the four bits of each pixel (poke 0x5f5e), which is
how several demos compose a few pictures into one screen and then flip between
them with the palette.
Sprite transparency is one rule again. A cart may mark a colour transparent by
writing the palette itself rather than calling palt(), and half of the drawing
paths honoured that while the other half did not - so the same sprite came out
transparent when drawn one way and opaque when drawn another.
A cart that has _draw but no _update runs at 30 frames per second, as it does
on PICO-8, instead of at the display rate - so its animation and its t() clock
keep the speed the author intended. A cart that defines its update function
later than usual is no longer stuck at the wrong rate either.
peek2/peek4 at the very top of memory now read their remaining bytes from
address 0, the way PICO-8 wraps, instead of reading zeros. And tonum() accepts
the raw-bit forms that tostr() writes (flags 0x2 and 0x3), so a cart that saves
numbers with one and reads them back with the other gets the same number.
Commented-out code is read the way PICO-8 reads it. PICO-8 lets a block comment
contain text in double brackets, which plain Lua does not, and we allowed that -
but we allowed it one step too far. Where a cart ends such a comment with the
closing brackets of the text inside it, we carried on reading, and the next
hundred lines of real code vanished into the comment.
sub() no longer stops a cart when handed something that is not text. PICO-8
returns an empty string and carries on, we raised an error.
A cart that halts itself now gets its message across. A cart can stop with an
explanation, and we printed it as a single unbroken line, cut off at about
thirty characters, with its colour codes shown as stray letters.
A cart's one-line "if" nested inside another one is read correctly. Written
without "then", an if ends at the end of the line, and where one such if sat
inside another the inner one cancelled the outer one's ending - so the outer
else ran on into the following line and quietly ate it.
0.9.7
Fixed: removing an item from a list while looping over it could let the item
be thrown away while the list still pointed at it, so the loop then read a
damaged value and the cart died a few seconds into play.
Dividing by a very small number - the idiom carts use to read a value's raw
bits - returned the same huge constant every time, so scores and counters
built that way printed as garbage (Snatch the Wench, Nest2). sub() with only a
string now returns the whole string instead of an error.
Runtime errors from compiled code used to name the wrong line - always the
function's first one - and could print a blank where the value's type belongs.
Both now report what actually happened, which is what made the bug above
findable.
0.9.6
Restores the native compiler on a cart's biggest functions. To fix a
fault there, 0.9.5 had to hand the heaviest routines of ten carts back to the
interpreter, Linecraft's world generator among them. They compile again now,
with the fault fixed rather than avoided.
Games that stopped for a fraction of a second every so often should not any
more. Memory was reclaimed in one big sweep once it ran low, which froze the
machine while it happened, the work is now spread across frames, in the idle
time after each one is drawn. GCSTEP=0 on the command line restores the old
behaviour.
0.9.5
Check Version now installs what it finds. Each executable knows which of the
two builds it is and fetches its own file, the old one is kept as <name>.old
and Amico8 restarts into the new one.
Faster: tline got a vertical path (that is how raycasters draw walls - POOM
uses it for every wall column), diagonal lines got the treatment horizontal
ones already had, and memcpy moves longwords. Output is unchanged, machine-
checked over thousands of randomised cases.
Fixed: reading past the end of a string gave an empty text instead of nothing,
which hung carts that scan strings in a loop. btn()/btnp() now accept a button
glyph, not only a number. A second player's buttons read as unpressed instead
of repeating player one. A cart running its own game loop is no longer killed
half a minute in. Two native-compiler faults that corrupted a function's
captured locals - a dropped step when a comparison and its jump were merged,
and a register number above 127 passed as negative.
0.9.4
Is a major speed release. The native-code compiler no longer silently
drops a cart's heaviest functions to the slow interpreter over two internal
size limits - everything compiles now. Compiled code also keeps the screen
updating and ESC/F4-F6 alive during long stretches a cart runs on its own.
Four drawing routines got faster with identical output: scaled sprites, filled
circles and ovals, patterned rectangles and horizontal lines.
Accuracy: a missing numbered table entry returned a global variable instead
of nothing, which corrupted cart data and crashed later somewhere else.
Runtime errors report the offending value, the table it came from and that
table's fields.
NOAOTWIDE and NOAOTPATCH on the command line restore the old compiler limits.
0.9.3
Many games should simply run faster. Two of the drawing routines the emulator
leans on hardest - scaled sprites (sspr) and filled circles (circfill) - were
rewritten to work a row at a time instead of a pixel at a time, which removes
two divisions and a pile of bookkeeping from every single pixel they touch.
Roughly two thirds of the tested cartridges use one or both, so the gain is
broad rather than aimed at one game, carts that scale sprites or fill large
circles benefit most.
On the accuracy side, a batch of palette and drawing bugs found by play-testing
are fixed. Underneath they came down to: the clip box, pen, text cursor and fill
pattern now readable through the @, % and $ operators (only the camera was
before), palette tables indexed the way PICO-8 documents. On graphics-card
screens the display palette is now applied at every window scale instead of
only at 2x.
The launcher gained a Check Version button (shortcut C) which asks juen.in
whether a newer release has been posted and tells you where to get it.
---
Code used:
Lua 5.2 - scripting engine base
Copyright (C) 1994-2015 Lua.org, PUC-Rio
Authors: R. Ierusalimschy, L. H. de Figueiredo, W. Celes
License: MIT (http://www.lua.org/license.html)
The Lua VM and standard libraries form the core of the interpreter.
z8lua - PICO-8-compatible Lua fork (from the Zepto-8 project)
Copyright (C) 2016-2024 Sam Hocevar <sam@hocevar.net>
License: WTFPL (http://www.wtfpl.net/)
Source: https://github.com/samhocevar/zepto8
z8lua extends Lua 5.2 with PICO-8-specific syntax (short-if, compound
assignment operators, integer division, fix32 number type, PICO-8 math
functions). The file z8lua/lpico8lib.c is taken directly from Zepto-8.
p8_compress - PICO-8 cartridge decompression
Copyright (C) 2014-2022 Lexaloffle Games LLP
License: MIT
Decompresses PICO-8 Lua source code from both old ":c:" format and
modern "pxa" compressed format.
stb_image - PNG image loader
Author: Sean Barrett
License: MIT / Public Domain
Source: https://github.com/nothings/stb
Used for loading .p8.png cartridge images.
FAKE-08 - reference PICO-8 implementation
Author: Jonathan (jtothebell)
License: MIT
Source: https://github.com/jtothebell/fake-08
A HUGE thank-you here. FAKE-08's source was by far the most
valuable reference in this whole project - over and over it was
what let us pin down exactly how PICO-8 really behaves: API
semantics, the audio synthesis model, iterator and metatable
edge cases, the fill-pattern glyph values, the _update_buttons
contract, music-pattern timing, and countless smaller details
were all settled by reading it. Many bugs would have taken days
longer (or stayed unsolved) without it. Not a single line of
FAKE-08 is in the Amico8 binary - it was only consulted during
development - but its clarity made this port possible. Thank you,
Jonathan.
---
Thanks:
Kempy/Veezya, MWB113, Tytus, Paluch, tomcat666, Aladin - testing
Quad, OlekW200i, Wozik, Mirq, Borsuk - moral support
Jonathan (jtothebell) - FAKE-08 reference implementation
---
Pawel "Juen" Nowak
Contact: j@ki.je or via imp3!
|