Merge Phase 7j: words indexing

This commit is contained in:
Orkun ÇAKILKAYA 2026-08-28 02:20:50 +03:00
commit 5cab68ea2e
17 changed files with 3032 additions and 3118 deletions

View file

@ -145,6 +145,8 @@ See `examples/menu.ludic` for a complete title screen.
| `entity` | entity handle | `i32` | | `entity` | entity handle | `i32` |
| `str` | string literal | `ptr` | | `str` | string literal | `ptr` |
| `ptr` | raw address (runtime/FFI) | `ptr` | | `ptr` | raw address (runtime/FFI) | `ptr` |
| `byte` | pointer to bytes — `p[i]` reads/writes one byte | `ptr` |
| `words` | pointer to 32-bit words — `w[i]` reads/writes an `int` | `ptr` |
Numeric literals: `42` and `0x1affff` are `int`; a literal with a decimal Numeric literals: `42` and `0x1affff` are `int`; a literal with a decimal
point (`1.5`) is `fixed`. Arithmetic on two `fixed` values lowers to point (`1.5`) is `fixed`. Arithmetic on two `fixed` values lowers to

View file

@ -20,10 +20,10 @@
# ============================================================================ # ============================================================================
# ---- state ---------------------------------------------------------------- # ---- state ----------------------------------------------------------------
var rt_fb: ptr = null # framebuffer, one i32 (0x00RRGGBB) per pixel var rt_fb: words = null # framebuffer, one i32 (0x00RRGGBB) per pixel
var rt_fbw: int = 320 var rt_fbw: int = 320
var rt_fbh: int = 240 var rt_fbh: int = 240
var rt_regs: ptr = null # the 64 general-purpose game registers var rt_regs: words = null # the 64 general-purpose game registers
var rt_rng: int = 305419896 # xorshift32 state var rt_rng: int = 305419896 # xorshift32 state
var rt_alive: int = 1 # platform still running? var rt_alive: int = 1 # platform still running?
@ -62,7 +62,7 @@ fn rt_shutdown() -> void {
fn rt_clear(c: int) -> void { fn rt_clear(c: int) -> void {
let n = rt_fbw * rt_fbh let n = rt_fbw * rt_fbh
for i in 0 .. n { for i in 0 .. n {
poke32(rt_fb, i, c) rt_fb[i] = c
} }
} }
@ -71,7 +71,7 @@ fn rt_put_px(x: int, y: int, c: int) -> void {
if y < 0 { return } if y < 0 { return }
if x >= rt_fbw { return } if x >= rt_fbw { return }
if y >= rt_fbh { return } if y >= rt_fbh { return }
poke32(rt_fb, y * rt_fbw + x, c) rt_fb[y * rt_fbw + x] = c
} }
fn rt_fill_rect(x: int, y: int, w: int, h: int, c: int) -> void { fn rt_fill_rect(x: int, y: int, w: int, h: int, c: int) -> void {
@ -84,7 +84,7 @@ fn rt_fill_rect(x: int, y: int, w: int, h: int, c: int) -> void {
let row = j * rt_fbw let row = j * rt_fbw
var i = x0 var i = x0
while i < x1 { while i < x1 {
poke32(rt_fb, row + i, c) rt_fb[row + i] = c
i = i + 1 i = i + 1
} }
j = j + 1 j = j + 1
@ -175,13 +175,13 @@ fn rt_text_int(x: int, y: int, n: int, colour: int, sc: int) -> void {
fn rt_reg(i: int) -> int { fn rt_reg(i: int) -> int {
if i < 0 { return 0 } if i < 0 { return 0 }
if i >= 64 { return 0 } if i >= 64 { return 0 }
return peek32(rt_regs, i) return rt_regs[i]
} }
fn rt_set_reg(i: int, v: int) -> void { fn rt_set_reg(i: int, v: int) -> void {
if i < 0 { return } if i < 0 { return }
if i >= 64 { return } if i >= 64 { return }
poke32(rt_regs, i, v) rt_regs[i] = v
} }
# ---- rng (xorshift32) ----------------------------------------------------- # ---- rng (xorshift32) -----------------------------------------------------
@ -290,7 +290,7 @@ fn rt_dump_ppm(path: str) -> void {
let px = rt_fbw * rt_fbh let px = rt_fbw * rt_fbh
let buf = mem_alloc(px * 3) let buf = mem_alloc(px * 3)
for i in 0 .. px { for i in 0 .. px {
let c = peek32(rt_fb, i) let c = rt_fb[i]
buf[i * 3] = (c / 65536) % 256 buf[i * 3] = (c / 65536) % 256
buf[i * 3 + 1] = (c / 256) % 256 buf[i * 3 + 1] = (c / 256) % 256
buf[i * 3 + 2] = c % 256 buf[i * 3 + 2] = c % 256
@ -369,11 +369,11 @@ fn rt_status_text() -> ptr {
# only it knows their shape. Everything below belongs to the runtime, so the # only it knows their shape. Everything below belongs to the runtime, so the
# runtime writes it — same order both ways. # runtime writes it — same order both ways.
fn rt_save_state(f: ptr) -> void { fn rt_save_state(f: ptr) -> void {
let w = mem_alloc(16) let w: words = mem_alloc(16)
poke32(w, 0, rt_rng) w[0] = rt_rng
poke32(w, 1, rt_mapw) w[1] = rt_mapw
poke32(w, 2, rt_maph) w[2] = rt_maph
poke32(w, 3, rt_alive) w[3] = rt_alive
file_write(f, w, 16) file_write(f, w, 16)
file_write(f, rt_regs, 64 * 4) file_write(f, rt_regs, 64 * 4)
file_write(f, rt_map, 96 * 64) file_write(f, rt_map, 96 * 64)
@ -382,11 +382,11 @@ fn rt_save_state(f: ptr) -> void {
} }
fn rt_load_state(f: ptr) -> void { fn rt_load_state(f: ptr) -> void {
let w = mem_alloc(16) let w: words = mem_alloc(16)
file_read(f, w, 16) file_read(f, w, 16)
rt_rng = peek32(w, 0) rt_rng = w[0]
rt_mapw = peek32(w, 1) rt_mapw = w[1]
rt_maph = peek32(w, 2) rt_maph = w[2]
file_read(f, rt_regs, 64 * 4) file_read(f, rt_regs, 64 * 4)
file_read(f, rt_map, 96 * 64) file_read(f, rt_map, 96 * 64)
file_read(f, rt_statusbuf, 96) file_read(f, rt_statusbuf, 96)

View file

@ -14,11 +14,11 @@ const SPR_MAX: int = 160
const SPR_SZ: int = 16 const SPR_SZ: int = 16
var img_px: ptr = null # IMG_MAX pointers to RGBA buffers var img_px: ptr = null # IMG_MAX pointers to RGBA buffers
var img_w: ptr = null var img_w: words = null
var img_h: ptr = null var img_h: words = null
var img_n: int = 0 var img_n: int = 0
var spr_px: ptr = null # SPR_MAX * 16 * 16 RGBA pixels, one block var spr_px: words = null # SPR_MAX * 16 * 16 RGBA pixels, one block
var spr_n: int = 0 var spr_n: int = 0
fn rt_image_init() -> void { fn rt_image_init() -> void {
@ -60,7 +60,7 @@ var rt_file_len: int = 0
# decoded image is left in these; -1 width means failure # decoded image is left in these; -1 width means failure
var png_w: int = 0 var png_w: int = 0
var png_h: int = 0 var png_h: int = 0
var png_px: ptr = null var png_px: words = null
fn rt_decode_png(path: str) -> bool { fn rt_decode_png(path: str) -> bool {
png_w = 0 png_w = 0
@ -168,7 +168,7 @@ fn rt_decode_png(path: str) -> bool {
} }
# expand to 0xAARRGGBB # expand to 0xAARRGGBB
let out = mem_alloc(w * h * 4) let out: words = mem_alloc(w * h * 4)
let maxv = (1 << bd) - 1 let maxv = (1 << bd) - 1
for y in 0 .. h { for y in 0 .. h {
let row = y * (stride + 1) + 1 let row = y * (stride + 1) + 1
@ -211,7 +211,7 @@ fn rt_decode_png(path: str) -> bool {
G = g G = g
B = g B = g
} }
poke32(out, y * w + x, (((A << 24) | (R << 16)) | ((G << 8) | B))) out[y * w + x] = (((A << 24) | (R << 16)) | ((G << 8) | B))
} }
} }
@ -233,8 +233,8 @@ fn rt_image_load(path: str) -> int {
let id = img_n let id = img_n
img_n = img_n + 1 img_n = img_n + 1
pokep(img_px, id, png_px) pokep(img_px, id, png_px)
poke32(img_w, id, png_w) img_w[id] = png_w
poke32(img_h, id, png_h) img_h[id] = png_h
return id return id
} }
@ -249,7 +249,7 @@ fn rt_blend_px(x: int, y: int, argb: int) -> void {
var g = ((argb >> 8) & 255) var g = ((argb >> 8) & 255)
var b = (argb & 255) var b = (argb & 255)
if a != 255 { if a != 255 {
let dst = peek32(rt_fb, y * rt_fbw + x) let dst = rt_fb[y * rt_fbw + x]
let dr = ((dst >> 16) & 255) let dr = ((dst >> 16) & 255)
let dg = ((dst >> 8) & 255) let dg = ((dst >> 8) & 255)
let db = (dst & 255) let db = (dst & 255)
@ -257,18 +257,18 @@ fn rt_blend_px(x: int, y: int, argb: int) -> void {
g = (g * a + dg * (255 - a)) / 255 g = (g * a + dg * (255 - a)) / 255
b = (b * a + db * (255 - a)) / 255 b = (b * a + db * (255 - a)) / 255
} }
poke32(rt_fb, y * rt_fbw + x, (((r << 16) | (g << 8)) | b)) rt_fb[y * rt_fbw + x] = (((r << 16) | (g << 8)) | b)
} }
fn rt_draw_image(id: int, dx: int, dy: int) -> void { fn rt_draw_image(id: int, dx: int, dy: int) -> void {
if id < 0 { return } if id < 0 { return }
if id >= img_n { return } if id >= img_n { return }
let w = peek32(img_w, id) let w = img_w[id]
let h = peek32(img_h, id) let h = img_h[id]
let s = peekp(img_px, id) let s: words = peekp(img_px, id)
for y in 0 .. h { for y in 0 .. h {
for x in 0 .. w { for x in 0 .. w {
rt_blend_px(dx + x, dy + y, peek32(s, y * w + x)) rt_blend_px(dx + x, dy + y, s[y * w + x])
} }
} }
} }
@ -278,12 +278,12 @@ fn rt_draw_image_scaled(id: int, dx: int, dy: int, dw: int, dh: int) -> void {
if id >= img_n { return } if id >= img_n { return }
if dw <= 0 { return } if dw <= 0 { return }
if dh <= 0 { return } if dh <= 0 { return }
let w = peek32(img_w, id) let w = img_w[id]
let h = peek32(img_h, id) let h = img_h[id]
let s = peekp(img_px, id) let s: words = peekp(img_px, id)
for y in 0 .. dh { for y in 0 .. dh {
for x in 0 .. dw { for x in 0 .. dw {
rt_blend_px(dx + x, dy + y, peek32(s, (y * h / dh) * w + x * w / dw)) rt_blend_px(dx + x, dy + y, s[(y * h / dh) * w + x * w / dw])
} }
} }
} }
@ -303,13 +303,13 @@ fn rt_draw_9slice(id: int, dx: int, dy: int, dw: int, dh: int, inset: int) -> vo
if id >= img_n { return } if id >= img_n { return }
if dw <= 0 { return } if dw <= 0 { return }
if dh <= 0 { return } if dh <= 0 { return }
let w = peek32(img_w, id) let w = img_w[id]
let h = peek32(img_h, id) let h = img_h[id]
let s = peekp(img_px, id) let s: words = peekp(img_px, id)
for y in 0 .. dh { for y in 0 .. dh {
let sy = rt_9map(y, dh, h, inset) let sy = rt_9map(y, dh, h, inset)
for x in 0 .. dw { for x in 0 .. dw {
rt_blend_px(dx + x, dy + y, peek32(s, sy * w + rt_9map(x, dw, w, inset))) rt_blend_px(dx + x, dy + y, s[sy * w + rt_9map(x, dw, w, inset)])
} }
} }
} }
@ -326,11 +326,11 @@ fn rt_png_load(path: str) -> int {
var px = 0 var px = 0
if x < png_w { if x < png_w {
if y < png_h { if y < png_h {
let c = peek32(png_px, y * png_w + x) let c = png_px[y * png_w + x]
if ((c >> 24) & 255) >= 128 { px = ((255 << 24) | (c & 16777215)) } if ((c >> 24) & 255) >= 128 { px = ((255 << 24) | (c & 16777215)) }
} }
} }
poke32(spr_px, base + y * SPR_SZ + x, px) spr_px[base + y * SPR_SZ + x] = px
} }
} }
mem_free(png_px) mem_free(png_px)
@ -344,7 +344,7 @@ fn rt_draw_sprite(id: int, px: int, py: int) -> void {
let base = id * SPR_SZ * SPR_SZ let base = id * SPR_SZ * SPR_SZ
for y in 0 .. SPR_SZ { for y in 0 .. SPR_SZ {
for x in 0 .. SPR_SZ { for x in 0 .. SPR_SZ {
let p = peek32(spr_px, base + y * SPR_SZ + x) let p = spr_px[base + y * SPR_SZ + x]
if ((p >> 24) & 255) != 0 { if ((p >> 24) & 255) != 0 {
rt_put_px(px + x, py + y, (p & 16777215)) rt_put_px(px + x, py + y, (p & 16777215))
} }
@ -359,7 +359,7 @@ fn rt_draw_sprite_scaled(id: int, px: int, py: int, sc: int) -> void {
let base = id * SPR_SZ * SPR_SZ let base = id * SPR_SZ * SPR_SZ
for y in 0 .. SPR_SZ { for y in 0 .. SPR_SZ {
for x in 0 .. SPR_SZ { for x in 0 .. SPR_SZ {
let p = peek32(spr_px, base + y * SPR_SZ + x) let p = spr_px[base + y * SPR_SZ + x]
if ((p >> 24) & 255) != 0 { if ((p >> 24) & 255) != 0 {
rt_fill_rect(px + x * sc, py + y * sc, sc, sc, (p & 16777215)) rt_fill_rect(px + x * sc, py + y * sc, sc, sc, (p & 16777215))
} }
@ -379,7 +379,7 @@ fn rt_sprites_load(path: str) -> void {
let d = rt_read_file(path) let d = rt_read_file(path)
if (d == null) { spr_n = 0; return } if (d == null) { spr_n = 0; return }
let size = rt_file_len let size = rt_file_len
let pal = mem_alloc(128 * 4) let pal: words = mem_alloc(128 * 4)
mem_set(pal, 0, 128 * 4) mem_set(pal, 0, 128 * 4)
var cur = 0 - 1 var cur = 0 - 1
var row = 0 var row = 0
@ -400,7 +400,7 @@ fn rt_sprites_load(path: str) -> void {
let hv = rt_hexval(d[start + 6 + k]) let hv = rt_hexval(d[start + 6 + k])
if hv >= 0 { v = v * 16 + hv } if hv >= 0 { v = v * 16 + hv }
} }
if ch < 128 { poke32(pal, ch, ((255 << 24) | v)) } if ch < 128 { pal[ch] = ((255 << 24) | v) }
} }
if c0 == 115 { # 's' — "spr" starts a new sprite if c0 == 115 { # 's' — "spr" starts a new sprite
cur = 0 - 1 cur = 0 - 1
@ -418,8 +418,7 @@ fn rt_sprites_load(path: str) -> void {
if row < SPR_SZ { if row < SPR_SZ {
for x in 0 .. SPR_SZ { for x in 0 .. SPR_SZ {
if x < len { if x < len {
poke32(spr_px, cur * SPR_SZ * SPR_SZ + row * SPR_SZ + x, spr_px[cur * SPR_SZ * SPR_SZ + row * SPR_SZ + x] = pal[(d[start + x] & 127)]
peek32(pal, (d[start + x] & 127)))
} }
} }
row = row + 1 row = row + 1

View file

@ -53,40 +53,40 @@ fn z_table_new(nsym: int) -> ptr {
} }
# lengths[i] = code length of symbol i (0 = symbol unused) # lengths[i] = code length of symbol i (0 = symbol unused)
fn z_table_build(table: ptr, lengths: ptr, n: int) -> void { fn z_table_build(table: words, lengths: words, n: int) -> void {
for i in 0 .. 16 { for i in 0 .. 16 {
poke32(table, i, 0) table[i] = 0
} }
for s in 0 .. n { for s in 0 .. n {
let l = peek32(lengths, s) let l = lengths[s]
poke32(table, l, peek32(table, l) + 1) table[l] = table[l] + 1
} }
poke32(table, 0, 0) # length 0 means "not present" table[0] = 0 # length 0 means "not present"
# offset of each length's first symbol # offset of each length's first symbol
let offs = mem_alloc(16 * 4) let offs: words = mem_alloc(16 * 4)
poke32(offs, 1, 0) offs[1] = 0
for l in 1 .. 15 { for l in 1 .. 15 {
poke32(offs, l + 1, peek32(offs, l) + peek32(table, l)) offs[l + 1] = offs[l] + table[l]
} }
for s in 0 .. n { for s in 0 .. n {
let l = peek32(lengths, s) let l = lengths[s]
if l != 0 { if l != 0 {
poke32(table, 16 + peek32(offs, l), s) table[16 + offs[l]] = s
poke32(offs, l, peek32(offs, l) + 1) offs[l] = offs[l] + 1
} }
} }
mem_free(offs) mem_free(offs)
} }
fn z_decode(table: ptr) -> int { fn z_decode(table: words) -> int {
var code = 0 var code = 0
var first = 0 var first = 0
var index = 0 var index = 0
for len in 1 .. 16 { for len in 1 .. 16 {
code = (code | z_bits(1)) code = (code | z_bits(1))
let count = peek32(table, len) let count = table[len]
if code - first < count { if code - first < count {
return peek32(table, 16 + index + (code - first)) return table[16 + index + (code - first)]
} }
index = index + count index = index + count
first = ((first + count) << 1) first = ((first + count) << 1)
@ -173,13 +173,13 @@ fn z_codes(out: ptr, at: int, cap: int, lit: ptr, dist: ptr) -> int {
} }
fn z_fixed_tables(lit: ptr, dist: ptr) -> void { fn z_fixed_tables(lit: ptr, dist: ptr) -> void {
let lengths = mem_alloc(288 * 4) let lengths: words = mem_alloc(288 * 4)
for i in 0 .. 144 { poke32(lengths, i, 8) } for i in 0 .. 144 { lengths[i] = 8 }
for i in 144 .. 256 { poke32(lengths, i, 9) } for i in 144 .. 256 { lengths[i] = 9 }
for i in 256 .. 280 { poke32(lengths, i, 7) } for i in 256 .. 280 { lengths[i] = 7 }
for i in 280 .. 288 { poke32(lengths, i, 8) } for i in 280 .. 288 { lengths[i] = 8 }
z_table_build(lit, lengths, 288) z_table_build(lit, lengths, 288)
for i in 0 .. 30 { poke32(lengths, i, 5) } for i in 0 .. 30 { lengths[i] = 5 }
z_table_build(dist, lengths, 30) z_table_build(dist, lengths, 30)
mem_free(lengths) mem_free(lengths)
} }
@ -191,13 +191,13 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
if nlen > 286 { return 0 } if nlen > 286 { return 0 }
if ndist > 30 { return 0 } if ndist > 30 { return 0 }
let lengths = mem_alloc(320 * 4) let lengths: words = mem_alloc(320 * 4)
for i in 0 .. 19 { poke32(lengths, i, 0) } for i in 0 .. 19 { lengths[i] = 0 }
# the code-length alphabet is transmitted in this fixed permutation # the code-length alphabet is transmitted in this fixed permutation
# 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 — biased by '0' so it is one literal # 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 — biased by '0' so it is one literal
let order = "@AB08796:5;4<3=2>1?" let order = "@AB08796:5;4<3=2>1?"
for i in 0 .. ncode { for i in 0 .. ncode {
poke32(lengths, order[i] - 48, z_bits(3)) lengths[order[i] - 48] = z_bits(3)
} }
let clen = z_table_new(19) let clen = z_table_new(19)
z_table_build(clen, lengths, 19) z_table_build(clen, lengths, 19)
@ -207,7 +207,7 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
let sym = z_decode(clen) let sym = z_decode(clen)
if sym < 0 { return 0 } if sym < 0 { return 0 }
if sym < 16 { if sym < 16 {
poke32(lengths, n, sym) lengths[n] = sym
n = n + 1 n = n + 1
} }
if sym >= 16 { if sym >= 16 {
@ -215,14 +215,14 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
var rep = 0 var rep = 0
if sym == 16 { if sym == 16 {
if n == 0 { return 0 } if n == 0 { return 0 }
prev = peek32(lengths, n - 1) prev = lengths[n - 1]
rep = 3 + z_bits(2) rep = 3 + z_bits(2)
} }
if sym == 17 { rep = 3 + z_bits(3) } if sym == 17 { rep = 3 + z_bits(3) }
if sym == 18 { rep = 11 + z_bits(7) } if sym == 18 { rep = 11 + z_bits(7) }
for k in 0 .. rep { for k in 0 .. rep {
if n < 320 { if n < 320 {
poke32(lengths, n, prev) lengths[n] = prev
n = n + 1 n = n + 1
} }
} }
@ -230,8 +230,8 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
} }
z_table_build(lit, lengths, nlen) z_table_build(lit, lengths, nlen)
# the distance lengths follow the literal ones in the same buffer # the distance lengths follow the literal ones in the same buffer
let dl = mem_alloc(32 * 4) let dl: words = mem_alloc(32 * 4)
for i in 0 .. ndist { poke32(dl, i, peek32(lengths, nlen + i)) } for i in 0 .. ndist { dl[i] = lengths[nlen + i] }
z_table_build(dist, dl, ndist) z_table_build(dist, dl, ndist)
mem_free(dl) mem_free(dl)
mem_free(lengths) mem_free(lengths)

View file

@ -19,26 +19,26 @@ const TT_GC: int = 512 # glyph cache entries
# ---- per-font tables (parallel arrays; index = font id) ------------------- # ---- per-font tables (parallel arrays; index = font id) -------------------
var tt_data: ptr = null var tt_data: ptr = null
var tt_size: ptr = null var tt_size: words = null
var tt_upem: ptr = null var tt_upem: words = null
var tt_nglyf: ptr = null var tt_nglyf: words = null
var tt_locfm: ptr = null var tt_locfm: words = null
var tt_nhm: ptr = null var tt_nhm: words = null
var tt_asc: ptr = null var tt_asc: words = null
var tt_desc: ptr = null var tt_desc: words = null
var tt_gap: ptr = null var tt_gap: words = null
var tt_glyf: ptr = null var tt_glyf: words = null
var tt_loca: ptr = null var tt_loca: words = null
var tt_hmtx: ptr = null var tt_hmtx: words = null
var tt_cmap: ptr = null var tt_cmap: words = null
var tt_cfmt: ptr = null var tt_cfmt: words = null
var tt_n: int = 0 var tt_n: int = 0
# ---- outline + edge scratch (reused for every glyph) ---------------------- # ---- outline + edge scratch (reused for every glyph) ----------------------
var ol_x: ptr = null var ol_x: ptr = null
var ol_y: ptr = null var ol_y: ptr = null
var ol_on: ptr = null var ol_on: words = null
var ol_ends: ptr = null var ol_ends: words = null
var ol_n: int = 0 var ol_n: int = 0
var ol_ne: int = 0 var ol_ne: int = 0
@ -49,18 +49,18 @@ var ed_y1: ptr = null
var ed_n: int = 0 var ed_n: int = 0
var sc_x: ptr = null # scanline crossings var sc_x: ptr = null # scanline crossings
var sc_d: ptr = null var sc_d: words = null
# ---- glyph cache ---------------------------------------------------------- # ---- glyph cache ----------------------------------------------------------
var gc_used: ptr = null var gc_used: words = null
var gc_font: ptr = null var gc_font: words = null
var gc_cp: ptr = null var gc_cp: words = null
var gc_px: ptr = null var gc_px: words = null
var gc_w: ptr = null var gc_w: words = null
var gc_h: ptr = null var gc_h: words = null
var gc_ox: ptr = null var gc_ox: words = null
var gc_oy: ptr = null var gc_oy: words = null
var gc_adv: ptr = null var gc_adv: words = null
var gc_bmp: ptr = null var gc_bmp: ptr = null
fn rt_tt_init() -> void { fn rt_tt_init() -> void {
@ -139,8 +139,8 @@ fn tt_find_table(d: ptr, base: int, a: int, b: int, c: int, e: int) -> int {
# pick the most capable Unicode subtable, as the C loader did # pick the most capable Unicode subtable, as the C loader did
fn tt_pick_cmap(id: int, d: ptr, co: int) -> void { fn tt_pick_cmap(id: int, d: ptr, co: int) -> void {
poke32(tt_cmap, id, 0 - 1) tt_cmap[id] = 0 - 1
poke32(tt_cfmt, id, 0) tt_cfmt[id] = 0
if co < 0 { return } if co < 0 { return }
let n = tt_u16(d, co + 2) let n = tt_u16(d, co + 2)
var best = 0 - 1 var best = 0 - 1
@ -162,8 +162,8 @@ fn tt_pick_cmap(id: int, d: ptr, co: int) -> void {
} }
} }
if best < 0 { return } if best < 0 { return }
poke32(tt_cmap, id, best) tt_cmap[id] = best
poke32(tt_cfmt, id, tt_u16(d, best)) tt_cfmt[id] = tt_u16(d, best)
} }
fn rt_font_load(path: str) -> int { fn rt_font_load(path: str) -> int {
@ -194,19 +194,19 @@ fn rt_font_load(path: str) -> int {
let id = tt_n let id = tt_n
tt_n = tt_n + 1 tt_n = tt_n + 1
pokep(tt_data, id, d) pokep(tt_data, id, d)
poke32(tt_size, id, size) tt_size[id] = size
var upem = tt_u16(d, head + 18) var upem = tt_u16(d, head + 18)
if upem <= 0 { upem = 1000 } if upem <= 0 { upem = 1000 }
poke32(tt_upem, id, upem) tt_upem[id] = upem
poke32(tt_locfm, id, tt_i16(d, head + 50)) tt_locfm[id] = tt_i16(d, head + 50)
poke32(tt_nglyf, id, tt_u16(d, maxp + 4)) tt_nglyf[id] = tt_u16(d, maxp + 4)
poke32(tt_asc, id, tt_i16(d, hhea + 4)) tt_asc[id] = tt_i16(d, hhea + 4)
poke32(tt_desc, id, tt_i16(d, hhea + 6)) tt_desc[id] = tt_i16(d, hhea + 6)
poke32(tt_gap, id, tt_i16(d, hhea + 8)) tt_gap[id] = tt_i16(d, hhea + 8)
poke32(tt_nhm, id, tt_u16(d, hhea + 34)) tt_nhm[id] = tt_u16(d, hhea + 34)
poke32(tt_glyf, id, glyf) tt_glyf[id] = glyf
poke32(tt_loca, id, loca) tt_loca[id] = loca
poke32(tt_hmtx, id, hmtx) tt_hmtx[id] = hmtx
tt_pick_cmap(id, d, tt_find_table(d, base, 99, 109, 97, 112)) tt_pick_cmap(id, d, tt_find_table(d, base, 99, 109, 97, 112))
return id return id
} }
@ -214,9 +214,9 @@ fn rt_font_load(path: str) -> int {
# ---- codepoint -> glyph id ------------------------------------------------ # ---- codepoint -> glyph id ------------------------------------------------
fn tt_glyph_index(id: int, cp: int) -> int { fn tt_glyph_index(id: int, cp: int) -> int {
let d = peekp(tt_data, id) let d = peekp(tt_data, id)
let s = peek32(tt_cmap, id) let s = tt_cmap[id]
if s < 0 { return 0 } if s < 0 { return 0 }
let fmt = peek32(tt_cfmt, id) let fmt = tt_cfmt[id]
if fmt == 4 { if fmt == 4 {
if cp > 65535 { return 0 } if cp > 65535 { return 0 }
@ -263,8 +263,8 @@ fn tt_glyph_index(id: int, cp: int) -> int {
fn tt_advance(id: int, gid: int) -> int { fn tt_advance(id: int, gid: int) -> int {
let d = peekp(tt_data, id) let d = peekp(tt_data, id)
let hmtx = peek32(tt_hmtx, id) let hmtx = tt_hmtx[id]
let n = peek32(tt_nhm, id) let n = tt_nhm[id]
if gid < n { return tt_u16(d, hmtx + gid * 4) } if gid < n { return tt_u16(d, hmtx + gid * 4) }
return tt_u16(d, hmtx + (n - 1) * 4) return tt_u16(d, hmtx + (n - 1) * 4)
} }
@ -274,33 +274,33 @@ fn ol_pt(x: fixed, y: fixed, on: int) -> void {
if ol_n >= TT_PTS { return } if ol_n >= TT_PTS { return }
pokef(ol_x, ol_n, x) pokef(ol_x, ol_n, x)
pokef(ol_y, ol_n, y) pokef(ol_y, ol_n, y)
poke32(ol_on, ol_n, on) ol_on[ol_n] = on
ol_n = ol_n + 1 ol_n = ol_n + 1
} }
fn tt_glyph_start(id: int, gid: int) -> int { fn tt_glyph_start(id: int, gid: int) -> int {
let d = peekp(tt_data, id) let d = peekp(tt_data, id)
let loca = peek32(tt_loca, id) let loca = tt_loca[id]
if peek32(tt_locfm, id) == 0 { return tt_u16(d, loca + gid * 2) * 2 } if tt_locfm[id] == 0 { return tt_u16(d, loca + gid * 2) * 2 }
return tt_u32(d, loca + gid * 4) return tt_u32(d, loca + gid * 4)
} }
fn tt_glyph_end(id: int, gid: int) -> int { fn tt_glyph_end(id: int, gid: int) -> int {
let d = peekp(tt_data, id) let d = peekp(tt_data, id)
let loca = peek32(tt_loca, id) let loca = tt_loca[id]
if peek32(tt_locfm, id) == 0 { return tt_u16(d, loca + (gid + 1) * 2) * 2 } if tt_locfm[id] == 0 { return tt_u16(d, loca + (gid + 1) * 2) * 2 }
return tt_u32(d, loca + (gid + 1) * 4) return tt_u32(d, loca + (gid + 1) * 4)
} }
# Append glyph `gid`, transformed by [a b c e] + (dx,dy), to the outline. # Append glyph `gid`, transformed by [a b c e] + (dx,dy), to the outline.
fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx: fixed, dy: fixed, depth: int) -> void { fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx: fixed, dy: fixed, depth: int) -> void {
if gid < 0 { return } if gid < 0 { return }
if gid >= peek32(tt_nglyf, id) { return } if gid >= tt_nglyf[id] { return }
if depth > 5 { return } if depth > 5 { return }
let goff = tt_glyph_start(id, gid) let goff = tt_glyph_start(id, gid)
let gend = tt_glyph_end(id, gid) let gend = tt_glyph_end(id, gid)
if goff >= gend { return } if goff >= gend { return }
let d = peekp(tt_data, id) let d = peekp(tt_data, id)
let g = peek32(tt_glyf, id) + goff let g = tt_glyf[id] + goff
let nc = tt_i16(d, g) let nc = tt_i16(d, g)
if nc >= 0 { if nc >= 0 {
@ -327,8 +327,8 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
} }
} }
let xs = mem_alloc((npts + 1) * 4) let xs: words = mem_alloc((npts + 1) * 4)
let ys = mem_alloc((npts + 1) * 4) let ys: words = mem_alloc((npts + 1) * 4)
var xv = 0 var xv = 0
for k in 0 .. npts { for k in 0 .. npts {
let fl = flags[k] let fl = flags[k]
@ -339,7 +339,7 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
} else { } else {
if (fl & 16) == 0 { xv = xv + tt_i16(d, p); p = p + 2 } if (fl & 16) == 0 { xv = xv + tt_i16(d, p); p = p + 2 }
} }
poke32(xs, k, xv) xs[k] = xv
} }
var yv = 0 var yv = 0
for k in 0 .. npts { for k in 0 .. npts {
@ -351,19 +351,19 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
} else { } else {
if (fl & 32) == 0 { yv = yv + tt_i16(d, p); p = p + 2 } if (fl & 32) == 0 { yv = yv + tt_i16(d, p); p = p + 2 }
} }
poke32(ys, k, yv) ys[k] = yv
} }
var start = 0 var start = 0
for ci in 0 .. nc { for ci in 0 .. nc {
let last = tt_u16(d, endpts + ci * 2) let last = tt_u16(d, endpts + ci * 2)
for k in start .. last + 1 { for k in start .. last + 1 {
let X = fx(peek32(xs, k)) let X = fx(xs[k])
let Y = fx(peek32(ys, k)) let Y = fx(ys[k])
ol_pt(a * X + c * Y + dx, b * X + e * Y + dy, (flags[k] & 1)) ol_pt(a * X + c * Y + dx, b * X + e * Y + dy, (flags[k] & 1))
} }
if ol_ne < 256 { if ol_ne < 256 {
poke32(ol_ends, ol_ne, ol_n) ol_ends[ol_ne] = ol_n
ol_ne = ol_ne + 1 ol_ne = ol_ne + 1
} }
start = last + 1 start = last + 1

View file

@ -52,7 +52,7 @@ var gr_oy: int = 0
var gr_adv: int = 0 var gr_adv: int = 0
fn tt_raster(id: int, gid: int, px: int) -> ptr { fn tt_raster(id: int, gid: int, px: int) -> ptr {
let upem = peek32(tt_upem, id) let upem = tt_upem[id]
let scale = fx(px) / upem let scale = fx(px) / upem
gr_adv = flr(fx(tt_advance(id, gid)) * scale + 0.5) gr_adv = flr(fx(tt_advance(id, gid)) * scale + 0.5)
gr_w = 0 gr_w = 0
@ -95,12 +95,12 @@ fn tt_raster(id: int, gid: int, px: int) -> ptr {
# build edges in supersample space (y grows downward) # build edges in supersample space (y grows downward)
var start = 0 var start = 0
for ci in 0 .. ol_ne { for ci in 0 .. ol_ne {
let end = peek32(ol_ends, ci) let end = ol_ends[ci]
let cnt = end - start let cnt = end - start
if cnt >= 2 { if cnt >= 2 {
var first_on = 0 - 1 var first_on = 0 - 1
for i in 0 .. cnt { for i in 0 .. cnt {
if first_on < 0 { if peek32(ol_on, start + i) == 1 { first_on = i } } if first_on < 0 { if ol_on[start + i] == 1 { first_on = i } }
} }
var sx = 0.0 var sx = 0.0
var sy = 0.0 var sy = 0.0
@ -122,7 +122,7 @@ fn tt_raster(id: int, gid: int, px: int) -> ptr {
let i = (first_on + 1 + step) % cnt let i = (first_on + 1 + step) % cnt
let ix = (peekf(ol_x, start + i) * scale - fx(x0)) * TT_SS let ix = (peekf(ol_x, start + i) * scale - fx(x0)) * TT_SS
let iy = (fx(y1) - peekf(ol_y, start + i) * scale) * TT_SS let iy = (fx(y1) - peekf(ol_y, start + i) * scale) * TT_SS
if peek32(ol_on, start + i) == 1 { if ol_on[start + i] == 1 {
ed_add(curx, cury, ix, iy) ed_add(curx, cury, ix, iy)
curx = ix curx = ix
cury = iy cury = iy
@ -132,7 +132,7 @@ fn tt_raster(id: int, gid: int, px: int) -> ptr {
let jy = (fx(y1) - peekf(ol_y, start + j) * scale) * TT_SS let jy = (fx(y1) - peekf(ol_y, start + j) * scale) * TT_SS
var ex = jx var ex = jx
var ey = jy var ey = jy
if peek32(ol_on, start + j) == 1 { if ol_on[start + j] == 1 {
step = step + 1 step = step + 1
} else { } else {
ex = (ix + jx) / 2 # implied on-curve midpoint ex = (ix + jx) / 2 # implied on-curve midpoint
@ -167,37 +167,37 @@ fn tt_raster(id: int, gid: int, px: int) -> ptr {
if hit == 1 { if hit == 1 {
let t = (yc - ya) / (yb - ya) let t = (yc - ya) / (yb - ya)
pokef(sc_x, m, peekf(ed_x0, i) + t * (peekf(ed_x1, i) - peekf(ed_x0, i))) pokef(sc_x, m, peekf(ed_x0, i) + t * (peekf(ed_x1, i) - peekf(ed_x0, i)))
if yb > ya { poke32(sc_d, m, 1) } else { poke32(sc_d, m, 0 - 1) } if yb > ya { sc_d[m] = 1 } else { sc_d[m] = 0 - 1 }
m = m + 1 m = m + 1
} }
} }
# insertion sort the crossings by x # insertion sort the crossings by x
for i in 1 .. m { for i in 1 .. m {
let kx = peekf(sc_x, i) let kx = peekf(sc_x, i)
let kd = peek32(sc_d, i) let kd = sc_d[i]
var j = i - 1 var j = i - 1
var placed = 0 var placed = 0
while j >= 0 { while j >= 0 {
if peekf(sc_x, j) > kx { if peekf(sc_x, j) > kx {
pokef(sc_x, j + 1, peekf(sc_x, j)) pokef(sc_x, j + 1, peekf(sc_x, j))
poke32(sc_d, j + 1, peek32(sc_d, j)) sc_d[j + 1] = sc_d[j]
j = j - 1 j = j - 1
} else { } else {
pokef(sc_x, j + 1, kx) pokef(sc_x, j + 1, kx)
poke32(sc_d, j + 1, kd) sc_d[j + 1] = kd
placed = 1 placed = 1
j = 0 - 1 j = 0 - 1
} }
} }
if placed == 0 { if placed == 0 {
pokef(sc_x, 0, kx) pokef(sc_x, 0, kx)
poke32(sc_d, 0, kd) sc_d[0] = kd
} }
} }
var wind = 0 var wind = 0
let oy = sy / TT_SS let oy = sy / TT_SS
for i in 0 .. m - 1 { for i in 0 .. m - 1 {
wind = wind + peek32(sc_d, i) wind = wind + sc_d[i]
if wind != 0 { if wind != 0 {
var xa = peekf(sc_x, i) var xa = peekf(sc_x, i)
var xb = peekf(sc_x, i + 1) var xb = peekf(sc_x, i + 1)
@ -239,30 +239,30 @@ fn tt_glyph_get(font: int, cp: int, px: int) -> int {
let h = gc_hash(font, cp, px) let h = gc_hash(font, cp, px)
for k in 0 .. 8 { for k in 0 .. 8 {
let s = ((h + k) & (TT_GC - 1)) let s = ((h + k) & (TT_GC - 1))
if peek32(gc_used, s) == 1 { if gc_used[s] == 1 {
if peek32(gc_font, s) == font { if gc_font[s] == font {
if peek32(gc_cp, s) == cp { if gc_cp[s] == cp {
if peek32(gc_px, s) == px { return s } if gc_px[s] == px { return s }
} }
} }
} }
} }
let s = h let s = h
if peek32(gc_used, s) == 1 { if gc_used[s] == 1 {
let old = peekp(gc_bmp, s) let old = peekp(gc_bmp, s)
if (old == null) == false { mem_free(old) } if (old == null) == false { mem_free(old) }
} }
let bmp = tt_raster(font, tt_glyph_index(font, cp), px) let bmp = tt_raster(font, tt_glyph_index(font, cp), px)
pokep(gc_bmp, s, bmp) pokep(gc_bmp, s, bmp)
poke32(gc_used, s, 1) gc_used[s] = 1
poke32(gc_font, s, font) gc_font[s] = font
poke32(gc_cp, s, cp) gc_cp[s] = cp
poke32(gc_px, s, px) gc_px[s] = px
poke32(gc_w, s, gr_w) gc_w[s] = gr_w
poke32(gc_h, s, gr_h) gc_h[s] = gr_h
poke32(gc_ox, s, gr_ox) gc_ox[s] = gr_ox
poke32(gc_oy, s, gr_oy) gc_oy[s] = gr_oy
poke32(gc_adv, s, gr_adv) gc_adv[s] = gr_adv
return s return s
} }
@ -313,11 +313,11 @@ fn tt_blit(bmp: ptr, w: int, h: int, dx: int, dy: int, colour: int) -> void {
let pxx = dx + x let pxx = dx + x
if pxx >= 0 { if pxx >= 0 {
if pxx < rt_fbw { if pxx < rt_fbw {
let d = peek32(rt_fb, py * rt_fbw + pxx) let d = rt_fb[py * rt_fbw + pxx]
let rr = (cr * a + ((d >> 16) & 255) * (255 - a)) / 255 let rr = (cr * a + ((d >> 16) & 255) * (255 - a)) / 255
let rg = (cg * a + ((d >> 8) & 255) * (255 - a)) / 255 let rg = (cg * a + ((d >> 8) & 255) * (255 - a)) / 255
let rb = (cb * a + (d & 255) * (255 - a)) / 255 let rb = (cb * a + (d & 255) * (255 - a)) / 255
poke32(rt_fb, py * rt_fbw + pxx, (((rr << 16) | (rg << 8)) | rb)) rt_fb[py * rt_fbw + pxx] = (((rr << 16) | (rg << 8)) | rb)
} }
} }
} }
@ -331,10 +331,10 @@ fn rt_text_ttf(font: int, x: int, y: int, s: str, colour: int, px: int) -> void
if font < 0 { return } if font < 0 { return }
if font >= tt_n { return } if font >= tt_n { return }
if px <= 0 { return } if px <= 0 { return }
let upem = peek32(tt_upem, font) let upem = tt_upem[font]
let scale = fx(px) / upem let scale = fx(px) / upem
var baseline = y + flr(fx(peek32(tt_asc, font)) * scale + 0.5) var baseline = y + flr(fx(tt_asc[font]) * scale + 0.5)
let lineh = flr(fx(peek32(tt_asc, font) - peek32(tt_desc, font) + peek32(tt_gap, font)) * scale + 0.5) let lineh = flr(fx(tt_asc[font] - tt_desc[font] + tt_gap[font]) * scale + 0.5)
var penx = x var penx = x
var i = 0 var i = 0
while s[i] != 0 { while s[i] != 0 {
@ -345,8 +345,8 @@ fn rt_text_ttf(font: int, x: int, y: int, s: str, colour: int, px: int) -> void
baseline = baseline + lineh baseline = baseline + lineh
} else { } else {
let g = tt_glyph_get(font, cp, px) let g = tt_glyph_get(font, cp, px)
tt_blit(peekp(gc_bmp, g), peek32(gc_w, g), peek32(gc_h, g), penx + peek32(gc_ox, g), baseline - peek32(gc_oy, g), colour) tt_blit(peekp(gc_bmp, g), gc_w[g], gc_h[g], penx + gc_ox[g], baseline - gc_oy[g], colour)
penx = penx + peek32(gc_adv, g) penx = penx + gc_adv[g]
} }
} }
} }
@ -365,7 +365,7 @@ fn rt_text_w(font: int, s: str, px: int) -> int {
if w > best { best = w } if w > best { best = w }
w = 0 w = 0
} else { } else {
w = w + peek32(gc_adv, tt_glyph_get(font, cp, px)) w = w + gc_adv[tt_glyph_get(font, cp, px)]
} }
} }
if w > best { best = w } if w > best { best = w }
@ -375,6 +375,6 @@ fn rt_text_w(font: int, s: str, px: int) -> int {
fn rt_text_h(font: int, px: int) -> int { fn rt_text_h(font: int, px: int) -> int {
if font < 0 { return 0 } if font < 0 { return 0 }
if font >= tt_n { return 0 } if font >= tt_n { return 0 }
let scale = fx(px) / peek32(tt_upem, font) let scale = fx(px) / tt_upem[font]
return flr(fx(peek32(tt_asc, font) - peek32(tt_desc, font) + peek32(tt_gap, font)) * scale + 0.5) return flr(fx(tt_asc[font] - tt_desc[font] + tt_gap[font]) * scale + 0.5)
} }

View file

@ -45,33 +45,33 @@ const K_VISIBLE: int = 18
const K_IMG: int = 19 const K_IMG: int = 19
const K_SKIN: int = 20 const K_SKIN: int = 20
var ui_type: ptr = null var ui_type: words = null
var ui_parent: ptr = null var ui_parent: words = null
var ui_w: ptr = null var ui_w: words = null
var ui_h: ptr = null var ui_h: words = null
var ui_x: ptr = null var ui_x: words = null
var ui_y: ptr = null var ui_y: words = null
var ui_haspos: ptr = null var ui_haspos: words = null
var ui_pad: ptr = null var ui_pad: words = null
var ui_gap: ptr = null var ui_gap: words = null
var ui_bg: ptr = null var ui_bg: words = null
var ui_fg: ptr = null var ui_fg: words = null
var ui_border: ptr = null var ui_border: words = null
var ui_align: ptr = null var ui_align: words = null
var ui_grow: ptr = null var ui_grow: words = null
var ui_font: ptr = null var ui_font: words = null
var ui_size: ptr = null var ui_size: words = null
var ui_skin: ptr = null var ui_skin: words = null
var ui_inset: ptr = null var ui_inset: words = null
var ui_img: ptr = null var ui_img: words = null
var ui_focusable: ptr = null var ui_focusable: words = null
var ui_rx: ptr = null var ui_rx: words = null
var ui_ry: ptr = null var ui_ry: words = null
var ui_rw: ptr = null var ui_rw: words = null
var ui_rh: ptr = null var ui_rh: words = null
var ui_visible: ptr = null var ui_visible: words = null
var ui_fired: ptr = null var ui_fired: words = null
var ui_hasdyn: ptr = null var ui_hasdyn: words = null
var ui_dyn: ptr = null # UI_MAX * 96 bytes var ui_dyn: ptr = null # UI_MAX * 96 bytes
var ui_text: ptr = null # UI_MAX static string pointers var ui_text: ptr = null # UI_MAX static string pointers
@ -115,29 +115,29 @@ fn rt_ui_init() -> void {
fn rt_ui_reset(n: int) -> void { fn rt_ui_reset(n: int) -> void {
ui_n = n ui_n = n
for i in 0 .. n { for i in 0 .. n {
poke32(ui_type, i, 0) ui_type[i] = 0
poke32(ui_parent, i, 0 - 1) ui_parent[i] = 0 - 1
poke32(ui_w, i, 0) ui_w[i] = 0
poke32(ui_h, i, 0) ui_h[i] = 0
poke32(ui_x, i, 0) ui_x[i] = 0
poke32(ui_y, i, 0) ui_y[i] = 0
poke32(ui_haspos, i, 0) ui_haspos[i] = 0
poke32(ui_pad, i, 0) ui_pad[i] = 0
poke32(ui_gap, i, 0) ui_gap[i] = 0
poke32(ui_bg, i, 0 - 1) ui_bg[i] = 0 - 1
poke32(ui_fg, i, 0 - 1) ui_fg[i] = 0 - 1
poke32(ui_border, i, 0 - 1) ui_border[i] = 0 - 1
poke32(ui_align, i, 0 - 1) ui_align[i] = 0 - 1
poke32(ui_grow, i, 0) ui_grow[i] = 0
poke32(ui_font, i, 0 - 1) ui_font[i] = 0 - 1
poke32(ui_size, i, 8) ui_size[i] = 8
poke32(ui_skin, i, 0 - 1) ui_skin[i] = 0 - 1
poke32(ui_inset, i, 6) ui_inset[i] = 6
poke32(ui_img, i, 0 - 1) ui_img[i] = 0 - 1
poke32(ui_focusable, i, 0) ui_focusable[i] = 0
poke32(ui_visible, i, 1) ui_visible[i] = 1
poke32(ui_fired, i, 0) ui_fired[i] = 0
poke32(ui_hasdyn, i, 0) ui_hasdyn[i] = 0
pokep(ui_text, i, null) pokep(ui_text, i, null)
} }
} }
@ -145,27 +145,27 @@ fn rt_ui_reset(n: int) -> void {
fn rt_ui_set(i: int, k: int, v: int) -> void { fn rt_ui_set(i: int, k: int, v: int) -> void {
if i < 0 { return } if i < 0 { return }
if i >= UI_MAX { return } if i >= UI_MAX { return }
if k == K_TYPE { poke32(ui_type, i, v) } if k == K_TYPE { ui_type[i] = v }
if k == K_PARENT { poke32(ui_parent, i, v) } if k == K_PARENT { ui_parent[i] = v }
if k == K_W { poke32(ui_w, i, v) } if k == K_W { ui_w[i] = v }
if k == K_H { poke32(ui_h, i, v) } if k == K_H { ui_h[i] = v }
if k == K_X { poke32(ui_x, i, v) } if k == K_X { ui_x[i] = v }
if k == K_Y { poke32(ui_y, i, v) } if k == K_Y { ui_y[i] = v }
if k == K_HASPOS { poke32(ui_haspos, i, v) } if k == K_HASPOS { ui_haspos[i] = v }
if k == K_PAD { poke32(ui_pad, i, v) } if k == K_PAD { ui_pad[i] = v }
if k == K_GAP { poke32(ui_gap, i, v) } if k == K_GAP { ui_gap[i] = v }
if k == K_BG { poke32(ui_bg, i, v) } if k == K_BG { ui_bg[i] = v }
if k == K_FG { poke32(ui_fg, i, v) } if k == K_FG { ui_fg[i] = v }
if k == K_BORDER { poke32(ui_border, i, v) } if k == K_BORDER { ui_border[i] = v }
if k == K_ALIGN { poke32(ui_align, i, v) } if k == K_ALIGN { ui_align[i] = v }
if k == K_GROW { poke32(ui_grow, i, v) } if k == K_GROW { ui_grow[i] = v }
if k == K_FONT { poke32(ui_font, i, v) } if k == K_FONT { ui_font[i] = v }
if k == K_SIZE { poke32(ui_size, i, v) } if k == K_SIZE { ui_size[i] = v }
if k == K_SKININSET { poke32(ui_inset, i, v) } if k == K_SKININSET { ui_inset[i] = v }
if k == K_FOCUSABLE { poke32(ui_focusable, i, v) } if k == K_FOCUSABLE { ui_focusable[i] = v }
if k == K_VISIBLE { poke32(ui_visible, i, v) } if k == K_VISIBLE { ui_visible[i] = v }
if k == K_IMG { poke32(ui_img, i, v) } if k == K_IMG { ui_img[i] = v }
if k == K_SKIN { poke32(ui_skin, i, v) } if k == K_SKIN { ui_skin[i] = v }
} }
fn rt_ui_static_text(i: int, s: str) -> void { fn rt_ui_static_text(i: int, s: str) -> void {
@ -176,7 +176,7 @@ fn rt_ui_static_text(i: int, s: str) -> void {
# ---- text helpers: TrueType when a font is loaded, bitmap otherwise ------- # ---- text helpers: TrueType when a font is loaded, bitmap otherwise -------
fn ui_str(i: int) -> ptr { fn ui_str(i: int) -> ptr {
if peek32(ui_hasdyn, i) == 1 { return ptr_add(ui_dyn, i * 96) } if ui_hasdyn[i] == 1 { return ptr_add(ui_dyn, i * 96) }
let t = peekp(ui_text, i) let t = peekp(ui_text, i)
if (t == null) { return ptr_add(ui_dyn, i * 96) } if (t == null) { return ptr_add(ui_dyn, i * 96) }
return t return t
@ -222,7 +222,7 @@ fn ui_under(i: int, root: int) -> bool {
var k = i var k = i
while k >= 0 { while k >= 0 {
if k == root { return true } if k == root { return true }
k = peek32(ui_parent, k) k = ui_parent[k]
} }
return false return false
} }
@ -231,55 +231,55 @@ fn ui_under(i: int, root: int) -> bool {
fn ui_measure() -> void { fn ui_measure() -> void {
var i = ui_n - 1 var i = ui_n - 1
while i >= 0 { while i >= 0 {
if peek32(ui_visible, i) == 0 { if ui_visible[i] == 0 {
poke32(ui_rw, i, 0) ui_rw[i] = 0
poke32(ui_rh, i, 0) ui_rh[i] = 0
} else { } else {
let t = peek32(ui_type, i) let t = ui_type[i]
let pad = peek32(ui_pad, i) let pad = ui_pad[i]
var cw = 0 var cw = 0
var ch = 0 var ch = 0
if t == WT_LABEL { cw = 0 - 1 } if t == WT_LABEL { cw = 0 - 1 }
if t == WT_BUTTON { cw = 0 - 1 } if t == WT_BUTTON { cw = 0 - 1 }
if cw == 0 - 1 { if cw == 0 - 1 {
let s = ui_str(i) let s = ui_str(i)
cw = ui_tw(peek32(ui_font, i), s, peek32(ui_size, i)) + 2 * pad cw = ui_tw(ui_font[i], s, ui_size[i]) + 2 * pad
ch = ui_th(peek32(ui_font, i), peek32(ui_size, i)) + 2 * pad ch = ui_th(ui_font[i], ui_size[i]) + 2 * pad
if t == WT_BUTTON { if t == WT_BUTTON {
cw = cw + 10 cw = cw + 10
ch = ch + 6 ch = ch + 6
} }
} else { } else {
if t == WT_IMAGE { if t == WT_IMAGE {
let im = peek32(ui_img, i) let im = ui_img[i]
if im >= 0 { if im >= 0 {
cw = peek32(img_w, im) cw = img_w[im]
ch = peek32(img_h, im) ch = img_h[im]
} }
} else { } else {
if t == WT_SPACER { if t == WT_SPACER {
cw = peek32(ui_w, i) cw = ui_w[i]
ch = peek32(ui_h, i) ch = ui_h[i]
} else { } else {
let dir = ui_dir(t) let dir = ui_dir(t)
var mainsz = 0 var mainsz = 0
var cross = 0 var cross = 0
var nc = 0 var nc = 0
for c in 0 .. ui_n { for c in 0 .. ui_n {
if peek32(ui_parent, c) == i { if ui_parent[c] == i {
if peek32(ui_visible, c) == 1 { if ui_visible[c] == 1 {
if dir == 1 { if dir == 1 {
mainsz = mainsz + peek32(ui_rh, c) mainsz = mainsz + ui_rh[c]
cross = max(cross, peek32(ui_rw, c)) cross = max(cross, ui_rw[c])
} else { } else {
mainsz = mainsz + peek32(ui_rw, c) mainsz = mainsz + ui_rw[c]
cross = max(cross, peek32(ui_rh, c)) cross = max(cross, ui_rh[c])
} }
nc = nc + 1 nc = nc + 1
} }
} }
} }
if nc > 1 { mainsz = mainsz + peek32(ui_gap, i) * (nc - 1) } if nc > 1 { mainsz = mainsz + ui_gap[i] * (nc - 1) }
mainsz = mainsz + 2 * pad mainsz = mainsz + 2 * pad
cross = cross + 2 * pad cross = cross + 2 * pad
if dir == 1 { if dir == 1 {
@ -292,20 +292,20 @@ fn ui_measure() -> void {
} }
} }
} }
var rw = peek32(ui_w, i) var rw = ui_w[i]
var rh = peek32(ui_h, i) var rh = ui_h[i]
if rw == 0 { rw = cw } if rw == 0 { rw = cw }
if rh == 0 { rh = ch } if rh == 0 { rh = ch }
poke32(ui_rw, i, rw) ui_rw[i] = rw
poke32(ui_rh, i, rh) ui_rh[i] = rh
} }
i = i - 1 i = i - 1
} }
} }
fn ui_eff_align(child: int, parent: int) -> int { fn ui_eff_align(child: int, parent: int) -> int {
if peek32(ui_align, child) >= 0 { return peek32(ui_align, child) } if ui_align[child] >= 0 { return ui_align[child] }
if peek32(ui_align, parent) >= 0 { return peek32(ui_align, parent) } if ui_align[parent] >= 0 { return ui_align[parent] }
return 0 return 0
} }

View file

@ -3,24 +3,24 @@
# ---- arrange: rects, parents before children ------------------------------ # ---- arrange: rects, parents before children ------------------------------
fn ui_arrange(i: int, x: int, y: int) -> void { fn ui_arrange(i: int, x: int, y: int) -> void {
poke32(ui_rx, i, x) ui_rx[i] = x
poke32(ui_ry, i, y) ui_ry[i] = y
let t = peek32(ui_type, i) let t = ui_type[i]
if ui_is_container(t) == false { return } if ui_is_container(t) == false { return }
let dir = ui_dir(t) let dir = ui_dir(t)
let pad = peek32(ui_pad, i) let pad = ui_pad[i]
let gap = peek32(ui_gap, i) let gap = ui_gap[i]
let innerw = peek32(ui_rw, i) - 2 * pad let innerw = ui_rw[i] - 2 * pad
let innerh = peek32(ui_rh, i) - 2 * pad let innerh = ui_rh[i] - 2 * pad
var total = 0 var total = 0
var ng = 0 var ng = 0
var grows = 0 var grows = 0
for c in 0 .. ui_n { for c in 0 .. ui_n {
if peek32(ui_parent, c) == i { if ui_parent[c] == i {
if peek32(ui_visible, c) == 1 { if ui_visible[c] == 1 {
if dir == 1 { total = total + peek32(ui_rh, c) } else { total = total + peek32(ui_rw, c) } if dir == 1 { total = total + ui_rh[c] } else { total = total + ui_rw[c] }
ng = ng + 1 ng = ng + 1
grows = grows + peek32(ui_grow, c) grows = grows + ui_grow[c]
} }
} }
} }
@ -31,18 +31,18 @@ fn ui_arrange(i: int, x: int, y: int) -> void {
var cx = x + pad var cx = x + pad
var cy = y + pad var cy = y + pad
for c in 0 .. ui_n { for c in 0 .. ui_n {
if peek32(ui_parent, c) == i { if ui_parent[c] == i {
if peek32(ui_visible, c) == 1 { if ui_visible[c] == 1 {
var kw = peek32(ui_rw, c) var kw = ui_rw[c]
var kh = peek32(ui_rh, c) var kh = ui_rh[c]
if peek32(ui_grow, c) != 0 { if ui_grow[c] != 0 {
if grows > 0 { if grows > 0 {
if dir == 1 { kh = kh + extra / grows } else { kw = kw + extra / grows } if dir == 1 { kh = kh + extra / grows } else { kw = kw + extra / grows }
} }
} }
let al = ui_eff_align(c, i) let al = ui_eff_align(c, i)
poke32(ui_rw, c, kw) ui_rw[c] = kw
poke32(ui_rh, c, kh) ui_rh[c] = kh
if dir == 1 { if dir == 1 {
var ax = x + pad var ax = x + pad
if al == 1 { ax = x + pad + (innerw - kw) / 2 } if al == 1 { ax = x + pad + (innerw - kw) / 2 }
@ -64,11 +64,11 @@ fn ui_arrange(i: int, x: int, y: int) -> void {
fn ui_layout() -> void { fn ui_layout() -> void {
if ui_active < 0 { return } if ui_active < 0 { return }
ui_measure() ui_measure()
var px = (rt_fbw - peek32(ui_rw, ui_active)) / 2 var px = (rt_fbw - ui_rw[ui_active]) / 2
var py = (rt_fbh - peek32(ui_rh, ui_active)) / 2 var py = (rt_fbh - ui_rh[ui_active]) / 2
if peek32(ui_haspos, ui_active) == 1 { if ui_haspos[ui_active] == 1 {
px = peek32(ui_x, ui_active) px = ui_x[ui_active]
py = peek32(ui_y, ui_active) py = ui_y[ui_active]
} }
ui_arrange(ui_active, px, py) ui_arrange(ui_active, px, py)
} }
@ -85,77 +85,77 @@ fn ui_lighten(c: int) -> int {
} }
fn ui_draw_node(i: int) -> void { fn ui_draw_node(i: int) -> void {
if peek32(ui_visible, i) == 0 { return } if ui_visible[i] == 0 { return }
let t = peek32(ui_type, i) let t = ui_type[i]
let rx = peek32(ui_rx, i) let rx = ui_rx[i]
let ry = peek32(ui_ry, i) let ry = ui_ry[i]
let rw = peek32(ui_rw, i) let rw = ui_rw[i]
let rh = peek32(ui_rh, i) let rh = ui_rh[i]
let skin = peek32(ui_skin, i) let skin = ui_skin[i]
var focused = 0 var focused = 0
if i == ui_focus { focused = 1 } if i == ui_focus { focused = 1 }
if t == WT_PANEL { if t == WT_PANEL {
if skin >= 0 { if skin >= 0 {
rt_draw_9slice(skin, rx, ry, rw, rh, peek32(ui_inset, i)) rt_draw_9slice(skin, rx, ry, rw, rh, ui_inset[i])
} else { } else {
if peek32(ui_bg, i) >= 0 { rt_fill_rect(rx, ry, rw, rh, peek32(ui_bg, i)) } if ui_bg[i] >= 0 { rt_fill_rect(rx, ry, rw, rh, ui_bg[i]) }
if peek32(ui_border, i) >= 0 { rt_frame_rect(rx, ry, rw, rh, peek32(ui_border, i)) } if ui_border[i] >= 0 { rt_frame_rect(rx, ry, rw, rh, ui_border[i]) }
} }
} }
if t == WT_BUTTON { if t == WT_BUTTON {
var bg = peek32(ui_bg, i) var bg = ui_bg[i]
if bg < 0 { bg = 0x2a2a3a } if bg < 0 { bg = 0x2a2a3a }
if focused == 1 { bg = ui_lighten(bg) } if focused == 1 { bg = ui_lighten(bg) }
if skin >= 0 { if skin >= 0 {
rt_draw_9slice(skin, rx, ry, rw, rh, peek32(ui_inset, i)) rt_draw_9slice(skin, rx, ry, rw, rh, ui_inset[i])
} else { } else {
rt_fill_rect(rx, ry, rw, rh, bg) rt_fill_rect(rx, ry, rw, rh, bg)
} }
var bc = peek32(ui_border, i) var bc = ui_border[i]
if bc < 0 { bc = 0x555577 } if bc < 0 { bc = 0x555577 }
if focused == 1 { bc = 0xffff00 } if focused == 1 { bc = 0xffff00 }
rt_frame_rect(rx, ry, rw, rh, bc) rt_frame_rect(rx, ry, rw, rh, bc)
let s = ui_str(i) let s = ui_str(i)
var fg = peek32(ui_fg, i) var fg = ui_fg[i]
if fg < 0 { fg = 0xffffff } if fg < 0 { fg = 0xffffff }
let font = peek32(ui_font, i) let font = ui_font[i]
let size = peek32(ui_size, i) let size = ui_size[i]
ui_draw_text(font, rx + (rw - ui_tw(font, s, size)) / 2, ry + (rh - ui_th(font, size)) / 2, s, fg, size) ui_draw_text(font, rx + (rw - ui_tw(font, s, size)) / 2, ry + (rh - ui_th(font, size)) / 2, s, fg, size)
} }
if t == WT_LABEL { if t == WT_LABEL {
let s = ui_str(i) let s = ui_str(i)
var fg = peek32(ui_fg, i) var fg = ui_fg[i]
if fg < 0 { fg = 0xffffff } if fg < 0 { fg = 0xffffff }
let font = peek32(ui_font, i) let font = ui_font[i]
let size = peek32(ui_size, i) let size = ui_size[i]
let pad = peek32(ui_pad, i) let pad = ui_pad[i]
let tw = ui_tw(font, s, size) let tw = ui_tw(font, s, size)
var tx = rx + pad var tx = rx + pad
let al = peek32(ui_align, i) let al = ui_align[i]
if al == 1 { tx = rx + (rw - tw) / 2 } if al == 1 { tx = rx + (rw - tw) / 2 }
if al == 2 { tx = rx + rw - pad - tw } if al == 2 { tx = rx + rw - pad - tw }
ui_draw_text(font, tx, ry + pad, s, fg, size) ui_draw_text(font, tx, ry + pad, s, fg, size)
} }
if t == WT_IMAGE { if t == WT_IMAGE {
if peek32(ui_img, i) >= 0 { rt_draw_image_scaled(peek32(ui_img, i), rx, ry, rw, rh) } if ui_img[i] >= 0 { rt_draw_image_scaled(ui_img[i], rx, ry, rw, rh) }
} }
for c in 0 .. ui_n { for c in 0 .. ui_n {
if peek32(ui_parent, c) == i { ui_draw_node(c) } if ui_parent[c] == i { ui_draw_node(c) }
} }
} }
# ---- focus and activation ------------------------------------------------- # ---- focus and activation -------------------------------------------------
var ui_fl: ptr = null var ui_fl: words = null
fn ui_focusables() -> int { fn ui_focusables() -> int {
if (ui_fl == null) { ui_fl = mem_alloc(UI_MAX * 4) } if (ui_fl == null) { ui_fl = mem_alloc(UI_MAX * 4) }
var n = 0 var n = 0
for i in 0 .. ui_n { for i in 0 .. ui_n {
if peek32(ui_focusable, i) == 1 { if ui_focusable[i] == 1 {
if peek32(ui_visible, i) == 1 { if ui_visible[i] == 1 {
if ui_under(i, ui_active) { if ui_under(i, ui_active) {
poke32(ui_fl, n, i) ui_fl[n] = i
n = n + 1 n = n + 1
} }
} }
@ -168,12 +168,12 @@ fn rt_ui_open(root: int) -> void {
ui_active = root ui_active = root
let n = ui_focusables() let n = ui_focusables()
ui_focus = 0 - 1 ui_focus = 0 - 1
if n > 0 { ui_focus = peek32(ui_fl, 0) } if n > 0 { ui_focus = ui_fl[0] }
} }
fn rt_ui_tick(k: int) -> void { fn rt_ui_tick(k: int) -> void {
if ui_active < 0 { return } if ui_active < 0 { return }
for i in 0 .. ui_n { poke32(ui_fired, i, 0) } for i in 0 .. ui_n { ui_fired[i] = 0 }
ui_layout() ui_layout()
let n = ui_focusables() let n = ui_focusables()
if n == 0 { if n == 0 {
@ -182,23 +182,23 @@ fn rt_ui_tick(k: int) -> void {
} }
var cur = 0 - 1 var cur = 0 - 1
for i in 0 .. n { for i in 0 .. n {
if peek32(ui_fl, i) == ui_focus { cur = i } if ui_fl[i] == ui_focus { cur = i }
} }
if cur < 0 { if cur < 0 {
cur = 0 cur = 0
ui_focus = peek32(ui_fl, 0) ui_focus = ui_fl[0]
} }
if k == 119 { # 'w' if k == 119 { # 'w'
cur = (cur - 1 + n) % n cur = (cur - 1 + n) % n
ui_focus = peek32(ui_fl, cur) ui_focus = ui_fl[cur]
} }
if k == 115 { # 's' if k == 115 { # 's'
cur = (cur + 1) % n cur = (cur + 1) % n
ui_focus = peek32(ui_fl, cur) ui_focus = ui_fl[cur]
} }
if k == 32 { poke32(ui_fired, ui_focus, 1) } if k == 32 { ui_fired[ui_focus] = 1 }
if k == 10 { poke32(ui_fired, ui_focus, 1) } if k == 10 { ui_fired[ui_focus] = 1 }
if k == 13 { poke32(ui_fired, ui_focus, 1) } if k == 13 { ui_fired[ui_focus] = 1 }
} }
fn rt_ui_render() -> void { fn rt_ui_render() -> void {
@ -211,7 +211,7 @@ fn rt_ui_render() -> void {
fn rt_ui_clicked(id: int) -> bool { fn rt_ui_clicked(id: int) -> bool {
if id < 0 { return false } if id < 0 { return false }
if id >= ui_n { return false } if id >= ui_n { return false }
return peek32(ui_fired, id) == 1 return ui_fired[id] == 1
} }
fn rt_ui_set_text(id: int, s: str) -> void { fn rt_ui_set_text(id: int, s: str) -> void {
@ -229,7 +229,7 @@ fn rt_ui_set_text(id: int, s: str) -> void {
} }
} }
ui_dyn[base + i] = 0 ui_dyn[base + i] = 0
poke32(ui_hasdyn, id, 1) ui_hasdyn[id] = 1
} }
fn rt_ui_set_int(id: int, n: int) -> void { fn rt_ui_set_int(id: int, n: int) -> void {
@ -263,7 +263,7 @@ fn rt_ui_set_int(id: int, n: int) -> void {
} }
} }
ui_dyn[base + at] = 0 ui_dyn[base + at] = 0
poke32(ui_hasdyn, id, 1) ui_hasdyn[id] = 1
} }
fn rt_ui_focus(id: int) -> void { fn rt_ui_focus(id: int) -> void {
@ -279,5 +279,5 @@ fn rt_ui_focused() -> int {
fn rt_ui_visible(id: int, v: int) -> void { fn rt_ui_visible(id: int, v: int) -> void {
if id < 0 { return } if id < 0 { return }
if id >= ui_n { return } if id >= ui_n { return }
poke32(ui_visible, id, v) ui_visible[id] = v
} }

View file

@ -21,9 +21,14 @@ fn emit_member_addr(e: Node) -> ptr {
# address of `base[index]` (slices only in this subset) # address of `base[index]` (slices only in this subset)
fn emit_index_addr(e: Node) -> ptr { fn emit_index_addr(e: Node) -> ptr {
let base = emit_expr(e.a) let base = emit_expr(e.a)
if not is_slice_ty(base.ty) { # a raw ptr/str: address of byte i. if not is_slice_ty(base.ty) { # a raw pointer: address of element i
let bi = emit_expr(e.b) # (evaluate index first — it may set g_addr_ty) let bi = emit_expr(e.b) # (evaluate index first — it may set g_addr_ty)
let r = emit_bind(`getelementptr inbounds i8, ptr {base.code}, i32 {bi.code}`) if (base.ty == "words") { # a `words` buffer: 32-bit elements
let rw = emit_bind(`getelementptr inbounds i32, ptr {base.code}, i32 {bi.code}`)
g_addr_ty = "int"
return rw
}
let r = emit_bind(`getelementptr inbounds i8, ptr {base.code}, i32 {bi.code}`) # a ptr/str: bytes
g_addr_ty = "byte" # set last so the caller sees it g_addr_ty = "byte" # set last so the caller sees it
return r return r
} }

View file

@ -54,6 +54,7 @@ fn lbl(pfx: ptr) -> ptr { let r = (pfx + itoa(ll_lbl)); ll_lbl = ll_lbl + 1; r
fn llty(t: ptr) -> ptr { fn llty(t: ptr) -> ptr {
if (t == "int") or (t == "bool") or (t == "fixed") { return "i32" } if (t == "int") or (t == "bool") or (t == "fixed") { return "i32" }
if (t == "byte") { return "i8" } # a single byte (p[i] on a raw ptr) if (t == "byte") { return "i8" } # a single byte (p[i] on a raw ptr)
if (t == "words") { return "ptr" } # a 32-bit-word buffer (w[i] is i32)
if (t == "void") { return "void" } if (t == "void") { return "void" }
return "ptr" return "ptr"
} }

View file

@ -13,7 +13,6 @@ fn is_intrinsic(name: ptr) -> bool {
if (name == "os_argc") or (name == "os_arg") or (name == "os_exit") or (name == "file_stderr") { return true } if (name == "os_argc") or (name == "os_arg") or (name == "os_exit") or (name == "file_stderr") { return true }
if (name == "file_stdout") { return true } if (name == "file_stdout") { return true }
if (name == "os_system") or (name == "os_getenv") { return true } if (name == "os_system") or (name == "os_getenv") { return true }
if (name == "peek32") or (name == "poke32") { return true }
return false return false
} }
# emit " <r> = <rest>\n" and return r # emit " <r> = <rest>\n" and return r
@ -87,19 +86,7 @@ fn emit_intrinsic(name: ptr, e: Node) -> Val {
return val(emit_bind(`call ptr @getenv(ptr {n})`), "str") return val(emit_bind(`call ptr @getenv(ptr {n})`), "str")
} }
# bitwise ops are the operators & | ^ << >> ~ now (see emit_bin / p_mul). # bitwise ops are the operators & | ^ << >> ~ now (see emit_bin / p_mul).
if (name == "peek32") { # peek32 / poke32 are `words` indexing now: w[i] and w[i] = v (see emit_index_addr).
let p = arg_code(e, 0); let i = arg_code(e, 1)
let g = nreg()
emit(" "); emit(g); emit(" = getelementptr inbounds i32, ptr "); emit(p); emit(", i32 "); emit(i); emit("\n")
return val(emit_bind(`load i32, ptr {g}`), "int")
}
if (name == "poke32") {
let p = arg_code(e, 0); let i = arg_code(e, 1); let v = arg_code(e, 2)
let g = nreg()
emit(" "); emit(g); emit(" = getelementptr inbounds i32, ptr "); emit(p); emit(", i32 "); emit(i); emit("\n")
emit(" store i32 "); emit(v); emit(", ptr "); emit(g); emit("\n")
return val("0", "void")
}
g_intrin_ok = false g_intrin_ok = false
return val("0", "void") return val("0", "void")
} }

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ program T {
print((1 << 4)) # 16 print((1 << 4)) # 16
print(((4 | 1) & 6)) # 4 print(((4 | 1) & 6)) # 4
let p = mem_alloc(16) let p = mem_alloc(16)
poke32(p, 1, 9999) p[1] = 9999
print(peek32(p, 1)) # 9999 print(p[1]) # 9999
} }
} }

View file

@ -52,7 +52,7 @@ object LudicVocabulary {
"enable", "disable", "match", "machine", "state", "become", "where", "enable", "disable", "match", "machine", "state", "become", "where",
"and", "or", "not", "break", "continue", "new" "and", "or", "not", "break", "continue", "new"
) )
val PRIMITIVES = setOf("int", "fixed", "bool", "entity", "str", "ptr", "void") val PRIMITIVES = setOf("int", "fixed", "bool", "entity", "str", "ptr", "byte", "words", "void")
val PHASES = setOf("Start", "Input", "FixedUpdate", "Update", "LateUpdate", "Render") val PHASES = setOf("Start", "Input", "FixedUpdate", "Update", "LateUpdate", "Render")
val WIDGETS = setOf("panel", "col", "row", "label", "button", "image", "spacer") val WIDGETS = setOf("panel", "col", "row", "label", "button", "image", "spacer")
@ -66,9 +66,8 @@ object LudicVocabulary {
"ui_focused", "ui_visible", "key", "reg", "set_reg", "self", "save", "load", "ui_focused", "ui_visible", "key", "reg", "set_reg", "self", "save", "load",
"status", "print", "str", "quit", "status", "print", "str", "quit",
// compiler intrinsics: the floor the Ludic-written runtime stands on // compiler intrinsics: the floor the Ludic-written runtime stands on
"mem_alloc", "mem_realloc", "mem_free", "mem_copy", "mem_set", "peek32", "mem_alloc", "mem_realloc", "mem_free", "mem_copy", "mem_set", "os_argc", "os_arg", "file_stderr", "file_stdout",
"os_argc", "os_arg", "file_stderr", "file_stdout", "peekp", "pokep", "peekf", "pokef", "ptr_add",
"poke32", "peekp", "pokep", "peekf", "pokef", "ptr_add",
"as_fixed", "as_int", "file_open", "file_read", "file_write", "as_fixed", "as_int", "file_open", "file_read", "file_write",
"file_seek", "file_tell", "file_close", "read_byte", "write_byte", "file_seek", "file_tell", "file_close", "read_byte", "write_byte",
"str_len", "os_exit", "os_time", "str_len", "os_exit", "os_time",

View file

@ -177,7 +177,7 @@
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|on)\\b" }, { "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|on)\\b" },
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" }, { "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
{ "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|fn|handler|entry|state)\\b" }, { "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|fn|handler|entry|state)\\b" },
{ "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|void)\\b" }, { "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|byte|words|void)\\b" },
{ "name": "constant.language.boolean.ludic", "match": "\\b(true|false|null)\\b" }, { "name": "constant.language.boolean.ludic", "match": "\\b(true|false|null)\\b" },
{ "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" } { "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" }
] ]
@ -209,7 +209,7 @@
{ {
"comment": "compiler intrinsics — these lower straight to libc or the OS", "comment": "compiler intrinsics — these lower straight to libc or the OS",
"name": "support.function.intrinsic.ludic", "name": "support.function.intrinsic.ludic",
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()" "match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
} }
] ]
}, },

View file

@ -177,7 +177,7 @@
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|on)\\b" }, { "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|on)\\b" },
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" }, { "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
{ "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|fn|handler|entry|state)\\b" }, { "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|fn|handler|entry|state)\\b" },
{ "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|void)\\b" }, { "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|byte|words|void)\\b" },
{ "name": "constant.language.boolean.ludic", "match": "\\b(true|false|null)\\b" }, { "name": "constant.language.boolean.ludic", "match": "\\b(true|false|null)\\b" },
{ "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" } { "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" }
] ]
@ -209,7 +209,7 @@
{ {
"comment": "compiler intrinsics — these lower straight to libc or the OS", "comment": "compiler intrinsics — these lower straight to libc or the OS",
"name": "support.function.intrinsic.ludic", "name": "support.function.intrinsic.ludic",
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()" "match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
} }
] ]
}, },

View file

@ -71,7 +71,7 @@ static const char* LUDIC_KW_STMT[] = {
"and","or","not","break","continue","new", 0 "and","or","not","break","continue","new", 0
}; };
static const char* LUDIC_TYPES[] = { static const char* LUDIC_TYPES[] = {
"int","fixed","bool","entity","str","ptr","void", 0 "int","fixed","bool","entity","str","ptr","byte","words","void", 0
}; };
static const char* LUDIC_PHASES[] = { static const char* LUDIC_PHASES[] = {
"Start","Input","FixedUpdate","Update","LateUpdate","Render", 0 "Start","Input","FixedUpdate","Update","LateUpdate","Render", 0
@ -154,8 +154,6 @@ static const LBuiltin LUDIC_INTRINSICS[] = {
{"mem_free","mem_free(p: ptr)","Release an allocation."}, {"mem_free","mem_free(p: ptr)","Release an allocation."},
{"mem_copy","mem_copy(dst: ptr, src: ptr, n: int)","memcpy."}, {"mem_copy","mem_copy(dst: ptr, src: ptr, n: int)","memcpy."},
{"mem_set","mem_set(p: ptr, byte: int, n: int)","memset."}, {"mem_set","mem_set(p: ptr, byte: int, n: int)","memset."},
{"peek32","peek32(p: ptr, off: int) -> int","Read a 32-bit word."},
{"poke32","poke32(p: ptr, off: int, v: int)","Write a 32-bit word."},
{"peekp","peekp(p: ptr, off: int) -> ptr","Read a pointer-sized word."}, {"peekp","peekp(p: ptr, off: int) -> ptr","Read a pointer-sized word."},
{"pokep","pokep(p: ptr, off: int, v: ptr)","Write a pointer-sized word."}, {"pokep","pokep(p: ptr, off: int, v: ptr)","Write a pointer-sized word."},
{"peekf","peekf(p: ptr, off: int) -> fixed","Read a fixed-point word."}, {"peekf","peekf(p: ptr, off: int) -> fixed","Read a fixed-point word."},