MoonBit bindings for TIC-80.
moon add Milky2018/tic80import {
"Milky2018/tic80",
}
pkgtype(kind: "foreign_library")
options(
link: {
"wasm": {
"import-memory": { "module": "env", "name": "memory" },
"memory-limits": { "min": 4, "max": 4 },
"heap-start-address": 98304,
},
},
)Important: Do not omit pkgtype(kind: "foreign_library") from a cartridge package. It tells MoonBit to link the package as a foreign library whose exported callbacks can be loaded by TIC-80, rather than as a standalone program with a MoonBit main entry point.
moon build --target wasm --releasemoon build --target wasm --release gametic80 --skip --fs . --cmd 'new wasm & import binary _build/wasm/release/build/game/game.wasm & run'tic80 --fs .new wasm
save game.wasmpmoon build --target wasm --release game
tic80 --skip --fs . --cmd 'load game.wasmp & import binary _build/wasm/release/build/game/game.wasm & run'tic80 --cli --fs . --cmd 'load game.wasmp & import binary _build/wasm/release/build/game/game.wasm & save game.tic & exit'let previous = @tic80.vbank_set(Bank1)
// Drawing here targets Bank1.
@tic80.cls(0)
@tic80.print("overlay", x=8, y=8)
ignore(@tic80.vbank_set(previous))| Callback | WebAssembly signature | Required | Purpose |
|---|---|---|---|
| BOOT | () -> void | No | Initialize the cartridge once. |
| TIC | () -> void | Yes | Update and draw one frame at 60 FPS. |
| SCN | (i32) -> void | No | Apply per-scanline effects to the 240x136 game area. |
| BDR | (i32) -> void | No | Apply per-scanline effects to the full 256x144 output, including the border. |
| MENU | (i32) -> void | No | Handle a custom game-menu selection. |
load cartridge
-> initialize the WebAssembly VM
-> BOOT()
-> TIC()
-> BDR(row) and SCN(row) while the frame is presented///|
#export_name("BOOT")
pub fn boot() -> Unit {
// One-time initialization.
}///|
#export_name("TIC")
pub fn tic() -> Unit {
@tic80.cls(0)
@tic80.map()
@tic80.spr(1, 100, 60)
}///|
#export_name("SCN")
pub fn scn(row : Int) -> Unit {
// Adjust palette or screen-offset state for this game-area row.
}///|
#export_name("BDR")
pub fn bdr(row : Int) -> Unit {
// Adjust palette or border state for this full-output row.
}-- menu: RESTART MUSIC DIFFICULTY| Selection | Callback |
|---|---|
| RESTART | MENU(0) |
| MUSIC | MENU(1) |
| DIFFICULTY | MENU(2) |
///|
#export_name("MENU")
pub fn menu(index : Int) -> Unit {
match index {
0 => restart_game()
1 => toggle_music()
_ => ()
}
}pub(all) enum Key {
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Digit0
Digit1
Digit2
Digit3
Digit4
Digit5
Digit6
Digit7
Digit8
Digit9
Minus
Equals
LeftBracket
RightBracket
Backslash
Semicolon
Apostrophe
Grave
Comma
Period
Slash
Space
Tab
Return
Backspace
Delete
Insert
PageUp
PageDown
Home
End
Up
Down
Left
Right
CapsLock
Ctrl
Shift
Alt
Escape
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
Numpad0
Numpad1
Numpad2
Numpad3
Numpad4
Numpad5
Numpad6
Numpad7
Numpad8
Numpad9
NumpadPlus
NumpadMinus
NumpadMultiply
NumpadDivide
NumpadEnter
NumpadPeriod
} derive(Eq, Debug)fn circ(x : Int, y : Int, radius : Int, color : Int) -> Unitfn circb(x : Int, y : Int, radius : Int, color : Int) -> Unitfn elli(x : Int, y : Int, a : Int, b : Int, color : Int) -> Unitfn ellib(x : Int, y : Int, a : Int, b : Int, color : Int) -> Unitfn fget(sprite_id : Int, flag : Int) -> Boolfn font(text : StringView, x : Int, y : Int, transparent_colors? : Bytes, char_width? : Int, char_height? : Int, fixed? : Bool, scale? : Int, alt? : Bool) -> Intfn fset(sprite_id : Int, flag : Int, value : Bool) -> Unitfn line(x0 : Float, y0 : Float, x1 : Float, y1 : Float, color : Int) -> Unitfn map(x? : Int, y? : Int, w? : Int, h? : Int, sx? : Int, sy? : Int, transparent_colors? : Bytes, scale? : Int, remap? : FuncRef[(MapRemapResult, Int, Int) -> MapRemapResult]) -> Unitfn memcpy(dest : Int, src : Int, length : Int) -> Unitfn memset(address : Int, value : Byte, length : Int) -> Unitfn mset(x : Int, y : Int, tile_id : Int) -> Unitfn music(track : Int, frame? : Int, row? : Int, loop_? : Bool, sustain? : Bool, tempo? : Int, speed? : Int) -> Unitfn music_stop() -> Unitfn peek(address : Int) -> Bytefn peek1(address : Int) -> Bytefn peek2(address : Int) -> Bytefn peek4(address : Int) -> Bytefn pmem(index : Int) -> UIntfn pmem_set(index : Int, value : UInt) -> UIntfn poke(address : Int, value : Byte) -> Unitfn poke1(address : Int, value : Byte) -> Unitfn poke2(address : Int, value : Byte) -> Unitfn poke4(address : Int, value : Byte) -> Unitfn print(text : StringView, x? : Int, y? : Int, color? : Int, fixed? : Bool, scale? : Int, small_font? : Bool) -> Intfn rect(x : Int, y : Int, w : Int, h : Int, color : Int) -> Unitfn rectb(x : Int, y : Int, w : Int, h : Int, color : Int) -> Unitfn sfx(id : Int, note? : Int, duration? : Int, channel? : SfxChannel, volume_left? : Int, volume_right? : Int, speed? : Int) -> Unitfn trace(text : StringView, color? : Int) -> Unitfn tri(x1 : Float, y1 : Float, x2 : Float, y2 : Float, x3 : Float, y3 : Float, color : Int) -> Unitfn trib(x1 : Float, y1 : Float, x2 : Float, y2 : Float, x3 : Float, y3 : Float, color : Int) -> Unitfn ttri(x1 : Float, y1 : Float, x2 : Float, y2 : Float, x3 : Float, y3 : Float, u1 : Float, v1 : Float, u2 : Float, v2 : Float, u3 : Float, v3 : Float, texture_source? : TextureSource, transparent_colors? : Bytes, z1? : Float, z2? : Float, z3? : Float, depth? : Bool) -> UnitMoonBit bindings for TIC-80.