refactor(runtime,packages,examples): named constants, package enums, idiom sweep
- runtime: HEADLESS_FRAME_PATH, STICK_DEADZONE / STICK_LEFT_X/Y, key and byte codes as char literals throughout (`k == 'w'`, `fill(rt_map, ' ', …)`) - ludic.gameplay/stats: drop the duplicate `stat_field` (it answered "atk" for every build stat); Stats.base uses stats_field_name - ludic.shooter: compare aim modes and fire patterns with AimMode.* and WeaponPattern.* instead of raw ints; STICK_RIGHT_X/Y - ludic.npcai: DecisionMade / brain_set_state use AiState.* - examples/games/menu.ludic uses Font.load / Ui.* with FONT_PATH and BACKDROP named; strings.ludic header says what it prints - whole tree: `x = x + 1` → `x += 1` (single-term right-hand sides only), `0 - x` → `-x`, ASCII codes → char literals; every .ludic and every ```ludic fence reformatted with the fixed formatter (whitespace only) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
e3e1bc7784
commit
bf36bc8a8f
103 changed files with 1256 additions and 1252 deletions
|
|
@ -77,40 +77,40 @@ function atlas_register_name(name: pointer, id: int) -> void {
|
|||
if at_nname >= ATLAS_MAX_NAME { return }
|
||||
at_name_str[at_nname] = name
|
||||
at_name_id[at_nname] = id
|
||||
at_nname = at_nname + 1
|
||||
at_nname += 1
|
||||
}
|
||||
|
||||
# load a spritesheet PNG whose cells are cw x ch px; returns a sheet handle (>= 0).
|
||||
function atlas_sheet(path: pointer, cw: int, ch: int) -> int {
|
||||
atlas_init()
|
||||
if at_nsheet >= ATLAS_MAX_SHEET { return 0 - 1 }
|
||||
if at_nsheet >= ATLAS_MAX_SHEET { return -1 }
|
||||
let img = rt_image_load(path)
|
||||
if img < 0 { return 0 - 1 }
|
||||
if img < 0 { return -1 }
|
||||
let h = at_nsheet
|
||||
at_sheet_img[h] = img
|
||||
at_sheet_cw[h] = cw
|
||||
at_sheet_ch[h] = ch
|
||||
at_nsheet = at_nsheet + 1
|
||||
at_nsheet += 1
|
||||
return h
|
||||
}
|
||||
|
||||
# register an atlas sprite for a sub-rect (px) of a sheet's image.
|
||||
function atlas_make(sheet: int, sx: int, sy: int, w: int, h: int) -> int {
|
||||
atlas_init()
|
||||
if at_nspr >= ATLAS_MAX_SPR { return 0 - 1 }
|
||||
if at_nspr >= ATLAS_MAX_SPR { return -1 }
|
||||
let id = at_nspr
|
||||
at_spr_sheet[id] = sheet
|
||||
at_spr_sx[id] = sx
|
||||
at_spr_sy[id] = sy
|
||||
at_spr_w[id] = w
|
||||
at_spr_h[id] = h
|
||||
at_nspr = at_nspr + 1
|
||||
at_nspr += 1
|
||||
return id
|
||||
}
|
||||
|
||||
# one cell (col, row) of a sheet, addressed by grid coords.
|
||||
function atlas_cell(sheet: int, col: int, row: int) -> int {
|
||||
if (sheet < 0) or (sheet >= at_nsheet) { return 0 - 1 }
|
||||
if (sheet < 0) or (sheet >= at_nsheet) { return -1 }
|
||||
let cw = at_sheet_cw[sheet]
|
||||
let ch = at_sheet_ch[sheet]
|
||||
return atlas_make(sheet, col * cw, row * ch, cw, ch)
|
||||
|
|
@ -119,7 +119,7 @@ function atlas_cell(sheet: int, col: int, row: int) -> int {
|
|||
# a sprite spanning cols x rows cells from (col, row) — some sprites cover more
|
||||
# than one cell (a tall character, a wide object).
|
||||
function atlas_cell_span(sheet: int, col: int, row: int, cols: int, rows: int) -> int {
|
||||
if (sheet < 0) or (sheet >= at_nsheet) { return 0 - 1 }
|
||||
if (sheet < 0) or (sheet >= at_nsheet) { return -1 }
|
||||
let cw = at_sheet_cw[sheet]
|
||||
let ch = at_sheet_ch[sheet]
|
||||
return atlas_make(sheet, col * cw, row * ch, cols * cw, rows * ch)
|
||||
|
|
@ -129,11 +129,11 @@ function atlas_cell_span(sheet: int, col: int, row: int, cols: int, rows: int) -
|
|||
function atlas_define(name: pointer, sheet: int, col: int, row: int) -> int {
|
||||
atlas_init()
|
||||
let id = atlas_cell(sheet, col, row)
|
||||
if id < 0 { return 0 - 1 }
|
||||
if id < 0 { return -1 }
|
||||
if at_nname < ATLAS_MAX_NAME {
|
||||
at_name_str[at_nname] = name
|
||||
at_name_id[at_nname] = id
|
||||
at_nname = at_nname + 1
|
||||
at_nname += 1
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
|
@ -144,24 +144,24 @@ function atlas_named(name: pointer) -> int {
|
|||
var i = 0
|
||||
while i < at_nname {
|
||||
if at_name_str[i] == name { return at_name_id[i] }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# load a whole image file as one atlas sprite (a 1x1 sheet the size of the image).
|
||||
function atlas_image(path: pointer) -> int {
|
||||
atlas_init()
|
||||
if at_nsheet >= ATLAS_MAX_SHEET { return 0 - 1 }
|
||||
if at_nsheet >= ATLAS_MAX_SHEET { return -1 }
|
||||
let img = rt_image_load(path)
|
||||
if img < 0 { return 0 - 1 }
|
||||
if img < 0 { return -1 }
|
||||
let w = img_w[img]
|
||||
let h = img_h[img]
|
||||
let sh = at_nsheet
|
||||
at_sheet_img[sh] = img
|
||||
at_sheet_cw[sh] = w
|
||||
at_sheet_ch[sh] = h
|
||||
at_nsheet = at_nsheet + 1
|
||||
at_nsheet += 1
|
||||
return atlas_make(sh, 0, 0, w, h)
|
||||
}
|
||||
|
||||
|
|
@ -191,10 +191,10 @@ function atlas_draw(id: int, dx: int, dy: int) -> void {
|
|||
let px = s[srcy * iw + srcx]
|
||||
if ((px >> 24) & 255) >= 128 { rt_put_px(dx + x, dy + y, px & 16777215) }
|
||||
}
|
||||
x = x + 1
|
||||
x += 1
|
||||
}
|
||||
}
|
||||
y = y + 1
|
||||
y += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,10 +223,10 @@ function atlas_draw_scaled(id: int, dx: int, dy: int, sc: int) -> void {
|
|||
let px = s[srcy * iw + srcx]
|
||||
if ((px >> 24) & 255) >= 128 { rt_fill_rect(dx + x * sc, dy + y * sc, sc, sc, px & 16777215) }
|
||||
}
|
||||
x = x + 1
|
||||
x += 1
|
||||
}
|
||||
}
|
||||
y = y + 1
|
||||
y += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -265,22 +265,22 @@ function atlas_draw_ex(id: int, dx: int, dy: int, sc0: int, flip: int, tint: int
|
|||
else { rt_fill_rect(dx + x * sc, dy + y * sc, sc, sc, col) }
|
||||
}
|
||||
}
|
||||
x = x + 1
|
||||
x += 1
|
||||
}
|
||||
}
|
||||
y = y + 1
|
||||
y += 1
|
||||
}
|
||||
}
|
||||
|
||||
# a strip of `count` frames starting at (col,row), each `rows` cells tall, registered
|
||||
# as consecutive ids so `first + SpriteAnim.frame` addresses the current frame.
|
||||
function atlas_strip(sheet: int, col: int, row: int, count: int, rows: int) -> int {
|
||||
var first = 0 - 1
|
||||
var first = -1
|
||||
var i = 0
|
||||
while i < count {
|
||||
let id = atlas_cell_span(sheet, col + i, row, 1, rows)
|
||||
if first < 0 { first = id }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return first
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ function atlas_draw_meter(x: int, y: int, value: int, max: int, per_icon: int, s
|
|||
if value >= i * per_icon + per_icon / 2 { id = half }
|
||||
if value >= (i + 1) * per_icon { id = full }
|
||||
atlas_draw(id, x + i * spacing, y)
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -312,9 +312,9 @@ function assets_enqueue_dir(dir: pointer) -> void {
|
|||
while i < len(names) {
|
||||
let file = names[i]
|
||||
var dot = len(file) - 1
|
||||
while (dot > 0) and (file[dot] != 46) { dot = dot - 1 }
|
||||
while (dot > 0) and (file[dot] != '.') { dot -= 1 }
|
||||
if dot > 0 { assets_enqueue(file[0..dot], dir + ("/") + file) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ function assets_enqueue(name: pointer, path: pointer) -> void {
|
|||
if at_q_n >= ATLAS_MAX_QUEUE { return }
|
||||
at_q_name[at_q_n] = name
|
||||
at_q_path[at_q_n] = path
|
||||
at_q_n = at_q_n + 1
|
||||
at_q_n += 1
|
||||
}
|
||||
|
||||
# Load up to `max` queued assets this frame, registering each under its name, and
|
||||
|
|
@ -338,8 +338,8 @@ function assets_pump(max: int) -> int {
|
|||
var done = 0
|
||||
while (done < max) and (at_q_pos < at_q_n) {
|
||||
assets_load_one(at_q_name[at_q_pos], at_q_path[at_q_pos])
|
||||
at_q_pos = at_q_pos + 1
|
||||
done = done + 1
|
||||
at_q_pos += 1
|
||||
done += 1
|
||||
}
|
||||
if (at_q_pos >= at_q_n) and (not at_q_announced) { at_q_announced = true; emit AssetsReady() }
|
||||
return done
|
||||
|
|
@ -362,7 +362,7 @@ function path_has_suffix(path: pointer, suffix: pointer) -> bool {
|
|||
var i = 0
|
||||
while i < m {
|
||||
if path[n - m + i] != suffix[i] { return false }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
@ -380,7 +380,7 @@ function assets_load_one(name: pointer, path: pointer) -> void {
|
|||
if at_font_n < ATLAS_MAX_FONT {
|
||||
at_font_name[at_font_n] = name
|
||||
at_font_id[at_font_n] = rt_font_load(path)
|
||||
at_font_n = at_font_n + 1
|
||||
at_font_n += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -391,7 +391,7 @@ function assets_font(name: pointer) -> int {
|
|||
var i = 0
|
||||
while i < at_font_n {
|
||||
if at_font_name[i] == name { return at_font_id[i] }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function audio_define(name: pointer, path: pointer) -> int {
|
|||
if snd_bank_n < AUDIO_CAP {
|
||||
snd_bank_name[snd_bank_n] = name
|
||||
snd_bank_id[snd_bank_n] = id
|
||||
snd_bank_n = snd_bank_n + 1
|
||||
snd_bank_n += 1
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ function audio_named(name: pointer) -> int {
|
|||
var i = 0
|
||||
while i < snd_bank_n {
|
||||
if snd_bank_name[i] == name { return snd_bank_id[i] }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ function audio_load(path: pointer) -> int {
|
|||
snd_tab[i] = p
|
||||
return i + 1
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ function audio_stop_all() -> void {
|
|||
var i = 0
|
||||
while i < AUDIO_CAP {
|
||||
if snd_tab[i] != null { snd_stop(snd_tab[i]) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
snd_music = 0
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ function audio_volume(v: fixed) -> void {
|
|||
var i = 0
|
||||
while i < AUDIO_CAP {
|
||||
if snd_tab[i] != null { snd_set_volume(snd_tab[i], v) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ function audio_pitch(v: fixed) -> void {
|
|||
var i = 0
|
||||
while i < AUDIO_CAP {
|
||||
if snd_tab[i] != null { snd_set_rate(snd_tab[i], v) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@
|
|||
# the standard alphabet value of a base64 character, or -1 for anything else
|
||||
# (whitespace, '=', stray bytes — the decoder skips them / stops on '=').
|
||||
function b64_val(c: int) -> int {
|
||||
if c >= 65 and c <= 90 { return c - 65 } # 'A'..'Z' -> 0..25
|
||||
if c >= 97 and c <= 122 { return c - 71 } # 'a'..'z' -> 26..51
|
||||
if c >= 48 and c <= 57 { return c + 4 } # '0'..'9' -> 52..61
|
||||
if c == 43 { return 62 } # '+'
|
||||
if c == 47 { return 63 } # '/'
|
||||
return 0 - 1
|
||||
if c >= 'A' and c <= 'Z' { return c - 65 } # 'A'..'Z' -> 0..25
|
||||
if c >= 'a' and c <= 'z' { return c - 71 } # 'a'..'z' -> 26..51
|
||||
if c >= '0' and c <= '9' { return c + 4 } # '0'..'9' -> 52..61
|
||||
if c == '+' { return 62 } # '+'
|
||||
if c == '/' { return 63 } # '/'
|
||||
return -1
|
||||
}
|
||||
|
||||
# decode NUL-terminated base64 `src` into the caller's `out` buffer; returns the
|
||||
|
|
@ -33,18 +33,18 @@ function b64_decode(src: pointer, out: pointer) -> int {
|
|||
var i = 0
|
||||
var c = src[i]
|
||||
while c != 0 {
|
||||
if c == 61 { return w } # '=' -> done
|
||||
if c == '=' { return w } # '=' -> done
|
||||
let v = b64_val(c)
|
||||
if v >= 0 {
|
||||
acc = (acc << 6) | v
|
||||
nbits = nbits + 6
|
||||
nbits += 6
|
||||
if nbits >= 8 {
|
||||
nbits = nbits - 8
|
||||
nbits -= 8
|
||||
out[w] = (acc >> nbits) & 255
|
||||
w = w + 1
|
||||
w += 1
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
c = src[i]
|
||||
}
|
||||
return w
|
||||
|
|
@ -79,9 +79,9 @@ function base64_encode(src: pointer) -> pointer {
|
|||
let e2 = ((b1 & 15) << 2) | (b2 >> 6)
|
||||
let e3 = b2 & 63
|
||||
out = out + tab[e0..e0 + 1] + tab[e1..e1 + 1]
|
||||
if have >= 2 { out = out + tab[e2..e2 + 1] } else { out = out + "=" }
|
||||
if have >= 3 { out = out + tab[e3..e3 + 1] } else { out = out + "=" }
|
||||
i = i + 3
|
||||
if have >= 2 { out += tab[e2..e2 + 1] } else { out += "=" }
|
||||
if have >= 3 { out += tab[e3..e3 + 1] } else { out += "=" }
|
||||
i += 3
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ function bn_alloc(cap: int) -> BigNum {
|
|||
let b = new BigNum
|
||||
b.sign = 0; b.n = 0; b.limbs = words(c)
|
||||
var i = 0
|
||||
while i < c { b.limbs[i] = 0; i = i + 1 }
|
||||
while i < c { b.limbs[i] = 0; i += 1 }
|
||||
return b
|
||||
}
|
||||
|
||||
# drop high zero limbs; a magnitude of zero forces sign 0
|
||||
function bn_norm(b: BigNum) -> BigNum {
|
||||
var k = b.n
|
||||
while k > 0 and b.limbs[k - 1] == 0 { k = k - 1 }
|
||||
while k > 0 and b.limbs[k - 1] == 0 { k -= 1 }
|
||||
b.n = k
|
||||
if k == 0 { b.sign = 0 }
|
||||
return b
|
||||
|
|
@ -58,7 +58,7 @@ function bigint_from(value: int) -> BigNum {
|
|||
if value == 0 { return bigint_zero() }
|
||||
var sign = 1
|
||||
var v: long = value
|
||||
if v < 0 { sign = -1; v = 0 - v }
|
||||
if v < 0 { sign = -1; v = -v }
|
||||
let b = bn_alloc(3)
|
||||
var i = 0
|
||||
while v > 0 {
|
||||
|
|
@ -66,7 +66,7 @@ function bigint_from(value: int) -> BigNum {
|
|||
let lo: int = v - q * BN_BASE
|
||||
b.limbs[i] = lo
|
||||
v = q
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
b.n = i; b.sign = sign
|
||||
return bn_norm(b)
|
||||
|
|
@ -77,9 +77,9 @@ function bigint_from_str(text: pointer) -> BigNum {
|
|||
let e = len(text)
|
||||
var i = 0
|
||||
var sign = 1
|
||||
if e > 0 and text[0] == 45 { sign = -1; i = 1 } # '-'
|
||||
if e > 0 and text[0] == 43 { i = 1 } # '+'
|
||||
while i < e - 1 and text[i] == 48 { i = i + 1 } # skip leading zeros
|
||||
if e > 0 and text[0] == '-' { sign = -1; i = 1 } # '-'
|
||||
if e > 0 and text[0] == '+' { i = 1 } # '+'
|
||||
while i < e - 1 and text[i] == '0' { i += 1 } # skip leading zeros
|
||||
let ndig = e - i
|
||||
if ndig <= 0 { return bigint_zero() }
|
||||
let nlimb = (ndig + 8) / 9
|
||||
|
|
@ -91,8 +91,8 @@ function bigint_from_str(text: pointer) -> BigNum {
|
|||
if start < i { start = i }
|
||||
var v = 0
|
||||
var k = start
|
||||
while k < pos { v = v * 10 + (text[k] - 48); k = k + 1 }
|
||||
b.limbs[li] = v; li = li + 1
|
||||
while k < pos { v = v * 10 + (text[k] - 48); k += 1 }
|
||||
b.limbs[li] = v; li += 1
|
||||
pos = start
|
||||
}
|
||||
b.n = nlimb; b.sign = sign
|
||||
|
|
@ -105,7 +105,7 @@ function bn_ucmp(a: BigNum, b: BigNum) -> int {
|
|||
var i = a.n - 1
|
||||
while i >= 0 {
|
||||
if a.limbs[i] != b.limbs[i] { if a.limbs[i] > b.limbs[i] { return 1 }; return -1 }
|
||||
i = i - 1
|
||||
i -= 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -119,10 +119,10 @@ function bn_uadd(a: BigNum, b: BigNum) -> BigNum {
|
|||
var i = 0
|
||||
while i < m {
|
||||
var s = carry
|
||||
if i < a.n { s = s + a.limbs[i] }
|
||||
if i < b.n { s = s + b.limbs[i] }
|
||||
if i < a.n { s += a.limbs[i] }
|
||||
if i < b.n { s += b.limbs[i] }
|
||||
if s >= BN_BASE { r.limbs[i] = s - BN_BASE; carry = 1 } else { r.limbs[i] = s; carry = 0 }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
r.limbs[m] = carry
|
||||
r.n = m + 1
|
||||
|
|
@ -136,10 +136,10 @@ function bn_usub(a: BigNum, b: BigNum) -> BigNum {
|
|||
var i = 0
|
||||
while i < a.n {
|
||||
var s = a.limbs[i] - borrow
|
||||
if i < b.n { s = s - b.limbs[i] }
|
||||
if s < 0 { s = s + BN_BASE; borrow = 1 } else { borrow = 0 }
|
||||
if i < b.n { s -= b.limbs[i] }
|
||||
if s < 0 { s += BN_BASE; borrow = 1 } else { borrow = 0 }
|
||||
r.limbs[i] = s
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
r.n = a.n
|
||||
return bn_norm(r)
|
||||
|
|
@ -148,8 +148,8 @@ function bn_usub(a: BigNum, b: BigNum) -> BigNum {
|
|||
function bigint_neg(a: BigNum) -> BigNum {
|
||||
let r = bn_alloc(a.n)
|
||||
var i = 0
|
||||
while i < a.n { r.limbs[i] = a.limbs[i]; i = i + 1 }
|
||||
r.n = a.n; r.sign = 0 - a.sign
|
||||
while i < a.n { r.limbs[i] = a.limbs[i]; i += 1 }
|
||||
r.n = a.n; r.sign = -a.sign
|
||||
return r
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ function bigint_mul(a: BigNum, b: BigNum) -> BigNum {
|
|||
let lo: int = t - q * BN_BASE
|
||||
r.limbs[i + j] = lo
|
||||
carry = q
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
var k = i + b.n
|
||||
while carry > 0 {
|
||||
|
|
@ -195,9 +195,9 @@ function bigint_mul(a: BigNum, b: BigNum) -> BigNum {
|
|||
let lo2: int = t2 - q2 * BN_BASE
|
||||
r.limbs[k] = lo2
|
||||
carry = q2
|
||||
k = k + 1
|
||||
k += 1
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
r.n = a.n + b.n; r.sign = a.sign * b.sign
|
||||
return bn_norm(r)
|
||||
|
|
@ -211,7 +211,7 @@ function bigint_pow(a: BigNum, exp: int) -> BigNum {
|
|||
while e > 0 {
|
||||
if e - (e / 2) * 2 == 1 { result = bigint_mul(result, base) }
|
||||
base = bigint_mul(base, base)
|
||||
e = e / 2
|
||||
e /= 2
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -220,7 +220,7 @@ function bigint_pow(a: BigNum, exp: int) -> BigNum {
|
|||
function bigint_div_int(a: BigNum, d: int) -> BigNum {
|
||||
var dd = d
|
||||
var dsign = 1
|
||||
if d < 0 { dsign = -1; dd = 0 - d }
|
||||
if d < 0 { dsign = -1; dd = -d }
|
||||
let r = bn_alloc(a.n)
|
||||
var rem: long = 0
|
||||
let ddl: long = dd
|
||||
|
|
@ -230,7 +230,7 @@ function bigint_div_int(a: BigNum, d: int) -> BigNum {
|
|||
let q: long = cur / ddl
|
||||
rem = cur - q * ddl
|
||||
r.limbs[i] = q
|
||||
i = i - 1
|
||||
i -= 1
|
||||
}
|
||||
r.n = a.n; r.sign = a.sign * dsign
|
||||
return bn_norm(r)
|
||||
|
|
@ -239,14 +239,14 @@ function bigint_div_int(a: BigNum, d: int) -> BigNum {
|
|||
# remainder of dividing by a nonzero int; carries the sign of `a`
|
||||
function bigint_mod_int(a: BigNum, d: int) -> int {
|
||||
var dd = d
|
||||
if d < 0 { dd = 0 - d }
|
||||
if d < 0 { dd = -d }
|
||||
let ddl: long = dd
|
||||
var rem: long = 0
|
||||
var i = a.n - 1
|
||||
while i >= 0 {
|
||||
let cur: long = rem * BN_BASE + a.limbs[i]
|
||||
rem = cur - (cur / ddl) * ddl
|
||||
i = i - 1
|
||||
i -= 1
|
||||
}
|
||||
let r: int = rem
|
||||
return r * a.sign
|
||||
|
|
@ -257,7 +257,7 @@ function bigint_cmp(a: BigNum, b: BigNum) -> int {
|
|||
if a.sign == 0 { return 0 }
|
||||
let c = bn_ucmp(a, b)
|
||||
if a.sign > 0 { return c }
|
||||
return 0 - c
|
||||
return -c
|
||||
}
|
||||
|
||||
function bigint_eq(a: BigNum, b: BigNum) -> bool { return bigint_cmp(a, b) == 0 }
|
||||
|
|
@ -268,12 +268,12 @@ function bigint_to_int(a: BigNum) -> int {
|
|||
if a.sign == 0 { return 0 }
|
||||
var v: long = 0
|
||||
var i = a.n - 1
|
||||
while i >= 0 { v = v * BN_BASE + a.limbs[i]; i = i - 1 }
|
||||
if a.sign < 0 { v = 0 - v }
|
||||
while i >= 0 { v = v * BN_BASE + a.limbs[i]; i -= 1 }
|
||||
if a.sign < 0 { v = -v }
|
||||
let hi: long = 2147483647
|
||||
let lo: long = 0 - hi - 1
|
||||
let lo: long = -hi - 1
|
||||
if v > hi { let r: int = hi; return r }
|
||||
if v < lo { return 0 - 2147483647 - 1 }
|
||||
if v < lo { return -2147483647 - 1 }
|
||||
let r: int = v
|
||||
return r
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ function bn_pad9(x: int) -> pointer {
|
|||
var s = string(x)
|
||||
var pad = 9 - len(s)
|
||||
var out = ""
|
||||
while pad > 0 { out = out + "0"; pad = pad - 1 }
|
||||
while pad > 0 { out += "0"; pad -= 1 }
|
||||
return out + s
|
||||
}
|
||||
|
||||
|
|
@ -291,9 +291,9 @@ function bigint_str(a: BigNum) -> pointer {
|
|||
if a.sign == 0 { return "0" }
|
||||
var out = ""
|
||||
if a.sign < 0 { out = "-" }
|
||||
out = out + string(a.limbs[a.n - 1])
|
||||
out += string(a.limbs[a.n - 1])
|
||||
var i = a.n - 2
|
||||
while i >= 0 { out = out + bn_pad9(a.limbs[i]); i = i - 1 }
|
||||
while i >= 0 { out += bn_pad9(a.limbs[i]); i -= 1 }
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
@ -312,12 +312,12 @@ function decimal_from(value: int) -> Dec { return dec_make(bigint_from(value), 0
|
|||
# "[-]int[.frac]" -> Dec, scale = number of fractional digits
|
||||
function decimal_from_str(text: pointer) -> Dec {
|
||||
let e = len(text)
|
||||
var dot = 0 - 1
|
||||
var dot = -1
|
||||
var i = 0
|
||||
while i < e { if text[i] == 46 { dot = i }; i = i + 1 } # '.'
|
||||
while i < e { if text[i] == '.' { dot = i }; i += 1 } # '.'
|
||||
if dot < 0 { return dec_make(bigint_from_str(text), 0) }
|
||||
let intp = text[0..dot]
|
||||
let fracp = text[dot + 1 .. e]
|
||||
let fracp = text[dot + 1..e]
|
||||
let scale = len(fracp)
|
||||
return dec_make(bigint_from_str(intp + fracp), scale)
|
||||
}
|
||||
|
|
@ -360,7 +360,7 @@ function decimal_rescale(d: Dec, places: int) -> Dec {
|
|||
var diff = d.scale - places
|
||||
var m = d.m
|
||||
var i = 0
|
||||
while i < diff { m = bigint_div_int(m, 10); i = i + 1 }
|
||||
while i < diff { m = bigint_div_int(m, 10); i += 1 }
|
||||
return dec_make(m, places)
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ function decimal_str(d: Dec) -> pointer {
|
|||
if d.scale == 0 { return neg + digits }
|
||||
var nd = len(digits)
|
||||
var pad = d.scale + 1 - nd
|
||||
while pad > 0 { digits = "0" + digits; pad = pad - 1; nd = nd + 1 }
|
||||
while pad > 0 { digits = "0" + digits; pad -= 1; nd += 1 }
|
||||
let cut = nd - d.scale
|
||||
let ip = digits[0..cut]
|
||||
let fp = digits[cut..nd]
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
# ============================================================================
|
||||
|
||||
# ---- state ----------------------------------------------------------------
|
||||
# where a headless build leaves its last frame (relative to the working directory)
|
||||
const HEADLESS_FRAME_PATH: string = "build/out.ppm"
|
||||
|
||||
var rt_fb: words = null # framebuffer, one i32 (0x00RRGGBB) per pixel
|
||||
var rt_fbw: int = 320
|
||||
var rt_fbh: int = 240
|
||||
|
|
@ -63,7 +66,7 @@ function rt_init() -> void {
|
|||
rt_regs = words(64)
|
||||
fill(rt_regs, 0, 64 * 4)
|
||||
rt_map = bytes(96 * 64)
|
||||
fill(rt_map, 32, 96 * 64)
|
||||
fill(rt_map, ' ', 96 * 64)
|
||||
rt_clip_x1 = rt_fbw
|
||||
rt_clip_y1 = rt_fbh
|
||||
rt_statusbuf = bytes(96)
|
||||
|
|
@ -82,7 +85,7 @@ function rt_shutdown() -> void {
|
|||
win_close()
|
||||
return
|
||||
}
|
||||
rt_dump_ppm("build/out.ppm")
|
||||
rt_dump_ppm(HEADLESS_FRAME_PATH)
|
||||
}
|
||||
|
||||
# ---- framebuffer ----------------------------------------------------------
|
||||
|
|
@ -153,9 +156,9 @@ function rt_fill_rect(x: int, y: int, w: int, h: int, c: int) -> void {
|
|||
while i < x1 {
|
||||
if rt_blend == 1 { rt_fb[row + i] = rt_blend_add(rt_fb[row + i], c) }
|
||||
else { rt_fb[row + i] = c }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,16 +172,16 @@ function rt_frame_rect(x: int, y: int, w: int, h: int, c: int) -> void {
|
|||
# A straight line by Bresenham's algorithm — integer only, any direction.
|
||||
function rt_line(x0: int, y0: int, x1: int, y1: int, c: int) -> void {
|
||||
var x = x0; var y = y0
|
||||
let dx = abs(x1 - x0); let dy = 0 - abs(y1 - y0)
|
||||
var sx = 0 - 1; if x0 < x1 { sx = 1 }
|
||||
var sy = 0 - 1; if y0 < y1 { sy = 1 }
|
||||
let dx = abs(x1 - x0); let dy = -abs(y1 - y0)
|
||||
var sx = -1; if x0 < x1 { sx = 1 }
|
||||
var sy = -1; if y0 < y1 { sy = 1 }
|
||||
var err = dx + dy
|
||||
while true {
|
||||
rt_put_px(x, y, c)
|
||||
if (x == x1) and (y == y1) { return }
|
||||
let e2 = 2 * err
|
||||
if e2 >= dy { err = err + dy; x = x + sx }
|
||||
if e2 <= dx { err = err + dx; y = y + sy }
|
||||
if e2 >= dy { err += dy; x += sx }
|
||||
if e2 <= dx { err += dx; y += sy }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,9 +194,9 @@ function rt_circle(cx: int, cy: int, r: int, c: int) -> void {
|
|||
rt_put_px(cx - y, cy + x, c); rt_put_px(cx - x, cy + y, c)
|
||||
rt_put_px(cx - x, cy - y, c); rt_put_px(cx - y, cy - x, c)
|
||||
rt_put_px(cx + y, cy - x, c); rt_put_px(cx + x, cy - y, c)
|
||||
y = y + 1
|
||||
y += 1
|
||||
if err < 0 { err = err + 2 * y + 1 }
|
||||
else { x = x - 1; err = err + 2 * (y - x) + 1 }
|
||||
else { x -= 1; err = err + 2 * (y - x) + 1 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,12 +204,12 @@ function rt_circle(cx: int, cy: int, r: int, c: int) -> void {
|
|||
function rt_fill_circle(cx: int, cy: int, r: int, c: int) -> void {
|
||||
if r < 0 { return }
|
||||
let r2 = r * r
|
||||
var dy = 0 - r
|
||||
var dy = -r
|
||||
while dy <= r {
|
||||
var dx = 0
|
||||
while (dx + 1) * (dx + 1) + dy * dy <= r2 { dx = dx + 1 }
|
||||
while (dx + 1) * (dx + 1) + dy * dy <= r2 { dx += 1 }
|
||||
rt_fill_rect(cx - dx, cy + dy, 2 * dx + 1, 1, c)
|
||||
dy = dy + 1
|
||||
dy += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,9 +234,9 @@ function rt_fill_triangle(x0: int, y0: int, x1: int, y1: int, x2: int, y2: int,
|
|||
let neg = (d0 < 0) or (d1 < 0) or (d2 < 0)
|
||||
let pos = (d0 > 0) or (d1 > 0) or (d2 > 0)
|
||||
if not (neg and pos) { rt_put_px(px, py, c) }
|
||||
px = px + 1
|
||||
px += 1
|
||||
}
|
||||
py = py + 1
|
||||
py += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,18 +264,18 @@ function rt_oval(x: int, y: int, rx: int, ry: int, c: int) -> void {
|
|||
rt_oval_pts(x, y, ex, ey, c)
|
||||
var p = ry2 - rx2 * ry + rx2 / 4 # region 1
|
||||
while px < py {
|
||||
ex = ex + 1
|
||||
px = px + two_ry2
|
||||
ex += 1
|
||||
px += two_ry2
|
||||
if p < 0 { p = p + ry2 + px }
|
||||
else { ey = ey - 1; py = py - two_rx2; p = p + ry2 + px - py }
|
||||
else { ey -= 1; py -= two_rx2; p = p + ry2 + px - py }
|
||||
rt_oval_pts(x, y, ex, ey, c)
|
||||
}
|
||||
p = ry2 * (ex * 2 + 1) * (ex * 2 + 1) / 4 + rx2 * (ey - 1) * (ey - 1) - rx2 * ry2 # region 2
|
||||
while ey > 0 {
|
||||
ey = ey - 1
|
||||
py = py - two_rx2
|
||||
ey -= 1
|
||||
py -= two_rx2
|
||||
if p > 0 { p = p + rx2 - py }
|
||||
else { ex = ex + 1; px = px + two_ry2; p = p + rx2 - py + px }
|
||||
else { ex += 1; px += two_ry2; p = p + rx2 - py + px }
|
||||
rt_oval_pts(x, y, ex, ey, c)
|
||||
}
|
||||
}
|
||||
|
|
@ -291,7 +294,7 @@ function rt_get_px(x: int, y: int) -> int {
|
|||
# glyph (5 wide + 1 gap), matching rt_text's cursor step.
|
||||
function rt_measure_text(text: string) -> int {
|
||||
var i = 0
|
||||
while text[i] != 0 { i = i + 1 }
|
||||
while text[i] != 0 { i += 1 }
|
||||
return i * 6
|
||||
}
|
||||
|
||||
|
|
@ -316,8 +319,8 @@ function rt_camera_follow(x: int, y: int, lerp: fixed) -> void {
|
|||
let ty = y - rt_fbh / 2
|
||||
let sx = fixed(tx - rt_cam_x) * lerp # fixed * fixed, then floor to whole pixels
|
||||
let sy = fixed(ty - rt_cam_y) * lerp
|
||||
rt_cam_x = rt_cam_x + floor(sx)
|
||||
rt_cam_y = rt_cam_y + floor(sy)
|
||||
rt_cam_x += floor(sx)
|
||||
rt_cam_y += floor(sy)
|
||||
}
|
||||
|
||||
# Add a random screen shake of up to +/- amount pixels, drawn from the seeded
|
||||
|
|
@ -325,8 +328,8 @@ function rt_camera_follow(x: int, y: int, lerp: fixed) -> void {
|
|||
# amount <= 0 clears it.
|
||||
function rt_camera_shake(amount: int) -> void {
|
||||
if amount <= 0 { rt_shake_x = 0; rt_shake_y = 0; return }
|
||||
rt_shake_x = rt_rng_range(0 - amount, amount)
|
||||
rt_shake_y = rt_rng_range(0 - amount, amount)
|
||||
rt_shake_x = rt_rng_range(-amount, amount)
|
||||
rt_shake_y = rt_rng_range(-amount, amount)
|
||||
}
|
||||
|
||||
# Camera.shake_for(amount, frames): shake by up to +/- amount pixels for `frames`
|
||||
|
|
@ -340,7 +343,7 @@ function rt_camera_shake_for(amount: int, frames: int) -> void {
|
|||
}
|
||||
function rt_camera_tick() -> void {
|
||||
if rt_shake_left > 0 {
|
||||
rt_shake_left = rt_shake_left - 1
|
||||
rt_shake_left -= 1
|
||||
rt_camera_shake(rt_shake_amount)
|
||||
return
|
||||
}
|
||||
|
|
@ -377,11 +380,11 @@ function rt_present() -> void {
|
|||
# ---- text -----------------------------------------------------------------
|
||||
function rt_glyph(x: int, y: int, ch: int, colour: int, sc: int) -> void {
|
||||
var c = ch
|
||||
if c >= 97 {
|
||||
if c <= 122 { c = c - 32 }
|
||||
if c >= 'a' {
|
||||
if c <= 'z' { c -= 32 }
|
||||
}
|
||||
if c < 32 { return }
|
||||
if c > 90 { return }
|
||||
if c < ' ' { return }
|
||||
if c > 'Z' { return }
|
||||
let base = (c - 32) * 7
|
||||
let font = rt_font()
|
||||
for row in 0 .. 7 {
|
||||
|
|
@ -404,38 +407,38 @@ function rt_text(x: int, y: int, s: string, colour: int, sc: int) -> void {
|
|||
while ch != 0 {
|
||||
rt_glyph(cx, y, ch, colour, sc)
|
||||
cx = cx + 6 * sc
|
||||
i = i + 1
|
||||
i += 1
|
||||
ch = s[i]
|
||||
}
|
||||
}
|
||||
|
||||
function rt_text_int(x: int, y: int, n: int, colour: int, sc: int) -> void {
|
||||
if n == 0 {
|
||||
rt_glyph(x, y, 48, colour, sc)
|
||||
rt_glyph(x, y, '0', colour, sc)
|
||||
return
|
||||
}
|
||||
var v = n
|
||||
var cx = x
|
||||
if v < 0 {
|
||||
rt_glyph(cx, y, 45, colour, sc)
|
||||
rt_glyph(cx, y, '-', colour, sc)
|
||||
cx = cx + 6 * sc
|
||||
v = 0 - v
|
||||
v = -v
|
||||
}
|
||||
var digits = 0
|
||||
var t = v
|
||||
while t > 0 {
|
||||
digits = digits + 1
|
||||
t = t / 10
|
||||
digits += 1
|
||||
t /= 10
|
||||
}
|
||||
var p = digits
|
||||
while p > 0 {
|
||||
var div = 1
|
||||
for k in 1 .. p {
|
||||
div = div * 10
|
||||
div *= 10
|
||||
}
|
||||
rt_glyph(cx, y, 48 + (v / div) % 10, colour, sc)
|
||||
cx = cx + 6 * sc
|
||||
p = p - 1
|
||||
p -= 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -496,7 +499,7 @@ function rt_rng_int(max: int) -> int {
|
|||
# a deterministic +1 or -1
|
||||
function rt_rng_sign() -> int {
|
||||
if rt_rng_chance(50) { return 1 }
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# ---- platform: input ------------------------------------------------------
|
||||
|
|
@ -509,7 +512,7 @@ function rt_poll() -> int {
|
|||
rt_alive = 0
|
||||
return 0
|
||||
}
|
||||
if c == 113 { # 'q' quits, as in the headless C platform
|
||||
if c == 'q' { # 'q' quits, as in the headless C platform
|
||||
rt_alive = 0
|
||||
}
|
||||
return c
|
||||
|
|
@ -529,8 +532,8 @@ function rt_put_str(buf: pointer, at: int, s: string) -> int {
|
|||
var ch = s[0]
|
||||
while ch != 0 {
|
||||
buf[n] = ch
|
||||
n = n + 1
|
||||
i = i + 1
|
||||
n += 1
|
||||
i += 1
|
||||
ch = s[i]
|
||||
}
|
||||
return n
|
||||
|
|
@ -538,25 +541,25 @@ function rt_put_str(buf: pointer, at: int, s: string) -> int {
|
|||
|
||||
function rt_put_int(buf: pointer, at: int, v: int) -> int {
|
||||
if v == 0 {
|
||||
buf[at] = 48
|
||||
buf[at] = '0'
|
||||
return at + 1
|
||||
}
|
||||
var digits = 0
|
||||
var t = v
|
||||
while t > 0 {
|
||||
digits = digits + 1
|
||||
t = t / 10
|
||||
digits += 1
|
||||
t /= 10
|
||||
}
|
||||
var n = at
|
||||
var p = digits
|
||||
while p > 0 {
|
||||
var div = 1
|
||||
for k in 1 .. p {
|
||||
div = div * 10
|
||||
div *= 10
|
||||
}
|
||||
buf[n] = 48 + (v / div) % 10
|
||||
n = n + 1
|
||||
p = p - 1
|
||||
n += 1
|
||||
p -= 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
|
@ -604,7 +607,7 @@ var rt_maph: int = 0
|
|||
function rt_map_size(w: int, h: int) -> void {
|
||||
rt_mapw = clamp(w, 0, 96)
|
||||
rt_maph = clamp(h, 0, 64)
|
||||
fill(rt_map, 32, 96 * 64)
|
||||
fill(rt_map, ' ', 96 * 64)
|
||||
}
|
||||
|
||||
function rt_map_row(y: int, s: string) -> void {
|
||||
|
|
@ -615,7 +618,7 @@ function rt_map_row(y: int, s: string) -> void {
|
|||
while ch != 0 {
|
||||
if x >= 96 { return }
|
||||
rt_map[y * 96 + x] = ch
|
||||
x = x + 1
|
||||
x += 1
|
||||
ch = s[x]
|
||||
}
|
||||
}
|
||||
|
|
@ -627,12 +630,12 @@ function rt_map_set(x: int, y: int, glyph: int) -> void {
|
|||
}
|
||||
function rt_map_fill(glyph: int) -> void {
|
||||
var y = 0
|
||||
while y < rt_maph { var x = 0; while x < rt_mapw { rt_map[y * 96 + x] = glyph; x = x + 1 }; y = y + 1 }
|
||||
while y < rt_maph { var x = 0; while x < rt_mapw { rt_map[y * 96 + x] = glyph; x += 1 }; y += 1 }
|
||||
}
|
||||
# every cell of the rectangle (x, y, w, h)
|
||||
function rt_map_rect(x: int, y: int, w: int, h: int, glyph: int) -> void {
|
||||
var yy = y
|
||||
while yy < y + h { var xx = x; while xx < x + w { rt_map_set(xx, yy, glyph); xx = xx + 1 }; yy = yy + 1 }
|
||||
while yy < y + h { var xx = x; while xx < x + w { rt_map_set(xx, yy, glyph); xx += 1 }; yy += 1 }
|
||||
}
|
||||
# the outermost ring of cells
|
||||
function rt_map_border(glyph: int) -> void {
|
||||
|
|
@ -648,11 +651,11 @@ function rt_map_random_cell(glyph: int) -> IVec2 {
|
|||
let x = rt_rng_range(0, rt_mapw - 1)
|
||||
let y = rt_rng_range(0, rt_maph - 1)
|
||||
if rt_tile(x, y) == glyph { return IVec2.make(x, y) }
|
||||
tries = tries + 1
|
||||
tries += 1
|
||||
}
|
||||
var y2 = 0
|
||||
while y2 < rt_maph { var x2 = 0; while x2 < rt_mapw { if rt_tile(x2, y2) == glyph { return IVec2.make(x2, y2) }; x2 = x2 + 1 }; y2 = y2 + 1 }
|
||||
return IVec2.make(0 - 1, 0 - 1)
|
||||
while y2 < rt_maph { var x2 = 0; while x2 < rt_mapw { if rt_tile(x2, y2) == glyph { return IVec2.make(x2, y2) }; x2 += 1 }; y2 += 1 }
|
||||
return IVec2.make(-1, -1)
|
||||
}
|
||||
# a random cell holding `glyph` at least `min_tiles` from `from` (tiles); falls back to any such cell
|
||||
function rt_map_random_cell_far(glyph: int, from: IVec2, min_tiles: int) -> IVec2 {
|
||||
|
|
@ -661,7 +664,7 @@ function rt_map_random_cell_far(glyph: int, from: IVec2, min_tiles: int) -> IVec
|
|||
while tries < 40 {
|
||||
if not IVec2.within(tile, from, min_tiles - 1) { return tile }
|
||||
tile = rt_map_random_cell(glyph)
|
||||
tries = tries + 1
|
||||
tries += 1
|
||||
}
|
||||
return tile
|
||||
}
|
||||
|
|
@ -696,8 +699,8 @@ function rt_ivec_step(degrees: int) -> IVec2 {
|
|||
}
|
||||
function rt_angle_diff_degrees(a: int, b: int) -> int {
|
||||
var d = (b - a) % 360
|
||||
if d > 180 { d = d - 360 }
|
||||
if d <= 0 - 180 { d = d + 360 }
|
||||
if d > 180 { d -= 360 }
|
||||
if d <= -180 { d += 360 }
|
||||
return d
|
||||
}
|
||||
|
||||
|
|
@ -714,18 +717,18 @@ function rt_bar(x: int, y: int, w: int, h: int, value: int, max: int, color: int
|
|||
function rt_rng_weighted(weights: []int) -> int {
|
||||
var total = 0
|
||||
var i = 0
|
||||
while i < len(weights) { if weights[i] > 0 { total = total + weights[i] }; i = i + 1 }
|
||||
if total <= 0 { return 0 - 1 }
|
||||
while i < len(weights) { if weights[i] > 0 { total += weights[i] }; i += 1 }
|
||||
if total <= 0 { return -1 }
|
||||
var roll = rt_rng_range(0, total - 1)
|
||||
i = 0
|
||||
while i < len(weights) {
|
||||
if weights[i] > 0 {
|
||||
if roll < weights[i] { return i }
|
||||
roll = roll - weights[i]
|
||||
roll -= weights[i]
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# List.sample(pool, count): `count` picks from an int slice, distinct while the
|
||||
|
|
@ -735,20 +738,20 @@ function rt_list_sample(pool: []int, count: int) -> []int {
|
|||
let n = len(pool)
|
||||
var i = 0
|
||||
while i < count {
|
||||
if n == 0 { push(out, 0); i = i + 1; continue }
|
||||
if n == 0 { push(out, 0); i += 1; continue }
|
||||
var pick = rt_rng_range(0, n - 1)
|
||||
var distinct = n > i
|
||||
var tries = 0
|
||||
while distinct and (tries < 64) {
|
||||
var seen = false
|
||||
var j = 0
|
||||
while j < len(out) { if out[j] == pool[pick] { seen = true }; j = j + 1 }
|
||||
while j < len(out) { if out[j] == pool[pick] { seen = true }; j += 1 }
|
||||
if not seen { break }
|
||||
pick = rt_rng_range(0, n - 1)
|
||||
tries = tries + 1
|
||||
tries += 1
|
||||
}
|
||||
push(out, pool[pick])
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
@ -773,7 +776,7 @@ function rt_status(s: string) -> void {
|
|||
if i >= 95 { ch = 0 }
|
||||
if ch != 0 {
|
||||
rt_statusbuf[i] = ch
|
||||
i = i + 1
|
||||
i += 1
|
||||
ch = s[i]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,27 +40,27 @@ function dict_new() -> Dict {
|
|||
|
||||
# FNV-1a over the key's bytes -> a non-negative slot index in [0, cap)
|
||||
function dict_slot(key: pointer, cap: int) -> int {
|
||||
var h = 0 - 2128831035 # FNV-1a offset basis, as a signed i32
|
||||
var h = -2128831035 # FNV-1a offset basis, as a signed i32
|
||||
var i = 0
|
||||
while key[i] != 0 { h = (h ^ key[i]) * 16777619; i = i + 1 }
|
||||
while key[i] != 0 { h = (h ^ key[i]) * 16777619; i += 1 }
|
||||
h = h & 2147483647 # clear the sign bit -> non-negative
|
||||
return h - (h / cap) * cap # h % cap
|
||||
}
|
||||
|
||||
# slot index of `key`, or -1 if absent
|
||||
function dict_find(d: Dict, key: pointer) -> int {
|
||||
if d.cap == 0 { return 0 - 1 }
|
||||
if d.cap == 0 { return -1 }
|
||||
var idx = dict_slot(key, d.cap)
|
||||
var probes = 0
|
||||
while probes < d.cap {
|
||||
let u = d.used[idx]
|
||||
if u == DICT_EMPTY { return 0 - 1 }
|
||||
if u == DICT_EMPTY { return -1 }
|
||||
if u == DICT_USED and d.keys[idx] == key { return idx }
|
||||
idx = idx + 1
|
||||
idx += 1
|
||||
if idx >= d.cap { idx = 0 }
|
||||
probes = probes + 1
|
||||
probes += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# grow to double capacity and reinsert every live key
|
||||
|
|
@ -75,7 +75,7 @@ function dict_grow(d: Dict) -> void {
|
|||
var i = 0
|
||||
while i < oldcap {
|
||||
if oldused[i] == DICT_USED { dict_set(d, oldkeys[i], oldvals[i]) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ function dict_set(d: Dict, key: pointer, value: int) -> void {
|
|||
if d.cap == 0 { dict_init(d, 16) }
|
||||
if (d.count + 1) * 10 >= d.cap * 7 { dict_grow(d) } # load factor 0.7
|
||||
var idx = dict_slot(key, d.cap)
|
||||
var tomb = 0 - 1
|
||||
var tomb = -1
|
||||
var probes = 0
|
||||
while probes < d.cap {
|
||||
let u = d.used[idx]
|
||||
|
|
@ -92,18 +92,18 @@ function dict_set(d: Dict, key: pointer, value: int) -> void {
|
|||
var slot = idx
|
||||
if tomb >= 0 { slot = tomb }
|
||||
d.keys[slot] = key; d.vals[slot] = value; d.used[slot] = DICT_USED
|
||||
d.count = d.count + 1
|
||||
d.count += 1
|
||||
return
|
||||
}
|
||||
if u == DICT_TOMB { if tomb < 0 { tomb = idx } }
|
||||
if u == DICT_USED and d.keys[idx] == key { d.vals[idx] = value; return }
|
||||
idx = idx + 1
|
||||
idx += 1
|
||||
if idx >= d.cap { idx = 0 }
|
||||
probes = probes + 1
|
||||
probes += 1
|
||||
}
|
||||
if tomb >= 0 {
|
||||
d.keys[tomb] = key; d.vals[tomb] = value; d.used[tomb] = DICT_USED
|
||||
d.count = d.count + 1
|
||||
d.count += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ function dict_remove(d: Dict, key: pointer) -> void {
|
|||
if i < 0 { return }
|
||||
d.used[i] = DICT_TOMB
|
||||
d.keys[i] = null
|
||||
d.count = d.count - 1
|
||||
d.count -= 1
|
||||
}
|
||||
|
||||
function dict_size(d: Dict) -> int { return d.count }
|
||||
|
|
@ -146,7 +146,7 @@ function dict_keys(d: Dict) -> []pointer {
|
|||
var i = 0
|
||||
while i < d.cap {
|
||||
if d.used[i] == DICT_USED { push(out, d.keys[i]) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,13 +52,13 @@ function fx_sparks(x: int, y: int, color: int, count: int) -> void {
|
|||
if fx_sn >= FX_MAX_SPARKS { return }
|
||||
fx_sx[fx_sn] = x
|
||||
fx_sy[fx_sn] = y
|
||||
fx_svx[fx_sn] = rt_rng_range(0 - FX_SPARK_SPEED, FX_SPARK_SPEED)
|
||||
fx_svy[fx_sn] = rt_rng_range(0 - FX_SPARK_SPEED, FX_SPARK_SPEED)
|
||||
fx_svx[fx_sn] = rt_rng_range(-FX_SPARK_SPEED, FX_SPARK_SPEED)
|
||||
fx_svy[fx_sn] = rt_rng_range(-FX_SPARK_SPEED, FX_SPARK_SPEED)
|
||||
fx_slife[fx_sn] = FX_SPARK_LIFE + rt_rng_range(0, FX_SPARK_LIFE_JITTER)
|
||||
fx_scolor[fx_sn] = color
|
||||
fx_ssize[fx_sn] = 1 + rt_rng_range(0, 2)
|
||||
fx_sn = fx_sn + 1
|
||||
i = i + 1
|
||||
fx_sn += 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ function fx_number(x: int, y: int, value: int, color: int) -> void {
|
|||
fx_nvalue[fx_nn] = value
|
||||
fx_nlife[fx_nn] = FX_NUMBER_LIFE
|
||||
fx_ncolor[fx_nn] = color
|
||||
fx_nn = fx_nn + 1
|
||||
fx_nn += 1
|
||||
}
|
||||
|
||||
function fx_clear() -> void { fx_sn = 0; fx_nn = 0 }
|
||||
|
|
@ -95,16 +95,16 @@ function fx_tick() -> void {
|
|||
if not fx_ready { return }
|
||||
var i = 0
|
||||
while i < fx_sn {
|
||||
fx_sx[i] = fx_sx[i] + fx_svx[i]
|
||||
fx_sy[i] = fx_sy[i] + fx_svy[i]
|
||||
fx_slife[i] = fx_slife[i] - 1
|
||||
if fx_slife[i] <= 0 { fx_drop_spark(i) } else { i = i + 1 }
|
||||
fx_sx[i] += fx_svx[i]
|
||||
fx_sy[i] += fx_svy[i]
|
||||
fx_slife[i] -= 1
|
||||
if fx_slife[i] <= 0 { fx_drop_spark(i) } else { i += 1 }
|
||||
}
|
||||
i = 0
|
||||
while i < fx_nn {
|
||||
fx_nlife[i] = fx_nlife[i] - 1
|
||||
if fx_nlife[i] % 2 == 0 { fx_ny[i] = fx_ny[i] - 1 }
|
||||
if fx_nlife[i] <= 0 { fx_drop_number(i) } else { i = i + 1 }
|
||||
fx_nlife[i] -= 1
|
||||
if fx_nlife[i] % 2 == 0 { fx_ny[i] -= 1 }
|
||||
if fx_nlife[i] <= 0 { fx_drop_number(i) } else { i += 1 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,11 +114,11 @@ function fx_draw() -> void {
|
|||
var i = 0
|
||||
while i < fx_sn {
|
||||
rt_fill_rect(fx_sx[i], fx_sy[i], fx_ssize[i], fx_ssize[i], fx_scolor[i])
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
i = 0
|
||||
while i < fx_nn {
|
||||
rt_text_int(fx_nx[i] - 4, fx_ny[i] - 10, fx_nvalue[i], fx_ncolor[i], 1)
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
property Cell { x: int = 0, y: int = 0 }
|
||||
|
||||
function grid_abs(v: int) -> int { if v < 0 { return 0 - v }; return v }
|
||||
function grid_abs(v: int) -> int { if v < 0 { return -v }; return v }
|
||||
function grid_in_bounds(x: int, y: int) -> bool { return x >= 0 and y >= 0 and x < rt_mapw and y < rt_maph }
|
||||
# a cell blocks movement if it is out of bounds or holds the `wall` tile.
|
||||
function grid_blocked(x: int, y: int, wall: int) -> bool {
|
||||
|
|
@ -30,9 +30,9 @@ function grid_line(x0: int, y0: int, x1: int, y1: int) -> []Cell {
|
|||
var y = y0
|
||||
let dx = grid_abs(x1 - x0)
|
||||
let dy = grid_abs(y1 - y0)
|
||||
var sx = 0 - 1
|
||||
var sx = -1
|
||||
if x0 < x1 { sx = 1 }
|
||||
var sy = 0 - 1
|
||||
var sy = -1
|
||||
if y0 < y1 { sy = 1 }
|
||||
var err = dx - dy
|
||||
while true {
|
||||
|
|
@ -41,8 +41,8 @@ function grid_line(x0: int, y0: int, x1: int, y1: int) -> []Cell {
|
|||
push(out, c)
|
||||
if x == x1 and y == y1 { break }
|
||||
let e2 = 2 * err
|
||||
if e2 > 0 - dy { err = err - dy; x = x + sx }
|
||||
if e2 < dx { err = err + dx; y = y + sy }
|
||||
if e2 > -dy { err -= dy; x += sx }
|
||||
if e2 < dx { err += dx; y += sy }
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ function grid_line_of_sight(x0: int, y0: int, x1: int, y1: int, wall: int) -> bo
|
|||
var i = 0
|
||||
while i < len(cells) {
|
||||
if grid_blocked(cells[i].x, cells[i].y, wall) { return false }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
@ -66,17 +66,17 @@ function grid_flood(sx: int, sy: int, wall: int) -> []Cell {
|
|||
let n = w * rt_maph
|
||||
let seen = bytes(n)
|
||||
var i = 0
|
||||
while i < n { seen[i] = 0; i = i + 1 }
|
||||
while i < n { seen[i] = 0; i += 1 }
|
||||
let qx = words(n)
|
||||
let qy = words(n)
|
||||
var head = 0
|
||||
var tail = 0
|
||||
qx[tail] = sx; qy[tail] = sy; tail = tail + 1
|
||||
qx[tail] = sx; qy[tail] = sy; tail += 1
|
||||
seen[sy * w + sx] = 1
|
||||
while head < tail {
|
||||
let cx = qx[head]
|
||||
let cy = qy[head]
|
||||
head = head + 1
|
||||
head += 1
|
||||
let c = new Cell
|
||||
c.x = cx; c.y = cy
|
||||
push(out, c)
|
||||
|
|
@ -90,9 +90,9 @@ function grid_flood(sx: int, sy: int, wall: int) -> []Cell {
|
|||
if dir == 3 { ny = cy - 1 }
|
||||
if grid_in_bounds(nx, ny) and seen[ny * w + nx] == 0 and not grid_blocked(nx, ny, wall) {
|
||||
seen[ny * w + nx] = 1
|
||||
qx[tail] = nx; qy[tail] = ny; tail = tail + 1
|
||||
qx[tail] = nx; qy[tail] = ny; tail += 1
|
||||
}
|
||||
dir = dir + 1
|
||||
dir += 1
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
|
@ -113,14 +113,14 @@ function path_a_star(x0: int, y0: int, x1: int, y1: int, wall: int) -> []Cell {
|
|||
let inopen = bytes(n)
|
||||
let closed = bytes(n)
|
||||
var i = 0
|
||||
while i < n { g[i] = INF; came[i] = 0 - 1; inopen[i] = 0; closed[i] = 0; i = i + 1 }
|
||||
while i < n { g[i] = INF; came[i] = -1; inopen[i] = 0; closed[i] = 0; i += 1 }
|
||||
let start = y0 * w + x0
|
||||
let goal = y1 * w + x1
|
||||
g[start] = 0
|
||||
inopen[start] = 1
|
||||
var found = false
|
||||
while true {
|
||||
var best = 0 - 1
|
||||
var best = -1
|
||||
var bestf = INF
|
||||
i = 0
|
||||
while i < n {
|
||||
|
|
@ -130,7 +130,7 @@ function path_a_star(x0: int, y0: int, x1: int, y1: int, wall: int) -> []Cell {
|
|||
let f = g[i] + grid_abs(cx - x1) + grid_abs(cy - y1)
|
||||
if f < bestf { bestf = f; best = i }
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
if best < 0 { break }
|
||||
if best == goal { found = true; break }
|
||||
|
|
@ -153,7 +153,7 @@ function path_a_star(x0: int, y0: int, x1: int, y1: int, wall: int) -> []Cell {
|
|||
if ng < g[ni] { g[ni] = ng; came[ni] = best; inopen[ni] = 1 }
|
||||
}
|
||||
}
|
||||
dir = dir + 1
|
||||
dir += 1
|
||||
}
|
||||
}
|
||||
if not found { return out }
|
||||
|
|
@ -169,6 +169,6 @@ function path_a_star(x0: int, y0: int, x1: int, y1: int, wall: int) -> []Cell {
|
|||
cur = came[cur]
|
||||
}
|
||||
var k = len(rev) - 1
|
||||
while k >= 0 { push(out, rev[k]); k = k - 1 }
|
||||
while k >= 0 { push(out, rev[k]); k -= 1 }
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ function http_init() -> void {
|
|||
h_used[i] = 0; h_native[i] = 0; h_sent[i] = 0; h_res[i] = 0
|
||||
h_status[i] = 0; h_blen[i] = 0
|
||||
h_req[i] = null; h_body[i] = null; h_hdr[i] = null
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
h_ready = true
|
||||
}
|
||||
|
|
@ -62,9 +62,9 @@ function http_slot_alloc() -> int {
|
|||
h_req[i] = null; h_body[i] = null; h_hdr[i] = null
|
||||
return i
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
function http_valid(h: int) -> bool {
|
||||
|
|
@ -77,7 +77,7 @@ function http_valid(h: int) -> bool {
|
|||
function http_cstr_len(p: pointer) -> int {
|
||||
if p == null { return 0 }
|
||||
var n = 0
|
||||
while p[n] != 0 { n = n + 1 }
|
||||
while p[n] != 0 { n += 1 }
|
||||
return n
|
||||
}
|
||||
|
||||
|
|
@ -147,9 +147,9 @@ function http_poll(h: int) -> int {
|
|||
if not http_valid(h) { return 0 }
|
||||
let s = h - 1
|
||||
if h_native[s] == 0 { return h_status[s] } # a parsed handle is ready immediately
|
||||
if h_sent[s] == 0 { return 0 - 1 }
|
||||
if h_sent[s] == 0 { return -1 }
|
||||
if h_res[s] == 1 { return h_status[s] }
|
||||
if hs_done(s) == 0 { return 0 - 1 }
|
||||
if hs_done(s) == 0 { return -1 }
|
||||
# first time we see it finished: cache the fields off the worker.
|
||||
h_status[s] = hs_status(s)
|
||||
h_body[s] = hs_body(s)
|
||||
|
|
@ -204,13 +204,13 @@ function http_slice_dup(src: pointer, a: int, b: int) -> pointer {
|
|||
if n < 0 { n = 0 }
|
||||
let out = bytes(n + 1)
|
||||
var i = 0
|
||||
while i < n { out[i] = src[a + i]; i = i + 1 }
|
||||
while i < n { out[i] = src[a + i]; i += 1 }
|
||||
out[n] = 0
|
||||
return out
|
||||
}
|
||||
|
||||
function http_is_digit(c: int) -> bool { return (c >= 48) and (c <= 57) }
|
||||
function http_lower(c: int) -> int { if (c >= 65) and (c <= 90) { return c + 32 }; return c }
|
||||
function http_is_digit(c: int) -> bool { return (c >= '0') and (c <= '9') }
|
||||
function http_lower(c: int) -> int { if (c >= 'A') and (c <= 'Z') { return c + 32 }; return c }
|
||||
|
||||
# Parse a raw HTTP/1.1 response (status line + headers + blank line + body) into
|
||||
# a ready handle. Useful for cached/custom transports and offline tests.
|
||||
|
|
@ -221,20 +221,20 @@ function http_parse(resp: pointer, len: int) -> int {
|
|||
|
||||
# status: the token after the first space on the status line.
|
||||
var i = 0
|
||||
while (i < len) and (resp[i] != 32) { i = i + 1 } # skip "HTTP/1.1"
|
||||
while (i < len) and (resp[i] == 32) { i = i + 1 } # skip the space(s)
|
||||
while (i < len) and (resp[i] != ' ') { i += 1 } # skip "HTTP/1.1"
|
||||
while (i < len) and (resp[i] == ' ') { i += 1 } # skip the space(s)
|
||||
var st = 0
|
||||
while (i < len) and http_is_digit(resp[i]) { st = (st * 10) + (resp[i] - 48); i = i + 1 }
|
||||
while (i < len) and http_is_digit(resp[i]) { st = (st * 10) + (resp[i] - 48); i += 1 }
|
||||
h_status[s] = st
|
||||
|
||||
# header/body split at the first CRLFCRLF.
|
||||
var split = 0 - 1
|
||||
var split = -1
|
||||
var j = 0
|
||||
while (j + 3) < len {
|
||||
if (resp[j] == 13) and (resp[j + 1] == 10) and (resp[j + 2] == 13) and (resp[j + 3] == 10) {
|
||||
if (resp[j] == '\r') and (resp[j + 1] == '\n') and (resp[j + 2] == '\r') and (resp[j + 3] == '\n') {
|
||||
split = j
|
||||
j = len
|
||||
} else { j = j + 1 }
|
||||
} else { j += 1 }
|
||||
}
|
||||
var hdr_end = split
|
||||
var body_start = split + 4
|
||||
|
|
@ -243,8 +243,8 @@ function http_parse(resp: pointer, len: int) -> int {
|
|||
# header block starts after the status line's CRLF.
|
||||
var hs = 0
|
||||
while (hs + 1) < len {
|
||||
if (resp[hs] == 13) and (resp[hs + 1] == 10) { hs = hs + 2; break }
|
||||
hs = hs + 1
|
||||
if (resp[hs] == '\r') and (resp[hs + 1] == '\n') { hs += 2; break }
|
||||
hs += 1
|
||||
}
|
||||
if hs > hdr_end { hs = hdr_end }
|
||||
h_hdr[s] = http_slice_dup(resp, hs, hdr_end)
|
||||
|
|
@ -264,17 +264,17 @@ function http_find_header(hdr: pointer, name: pointer) -> pointer {
|
|||
while i < hlen {
|
||||
# match name at the start of a line, followed by ':'.
|
||||
var k = 0
|
||||
while (k < nlen) and ((i + k) < hlen) and (http_lower(hdr[i + k]) == http_lower(name[k])) { k = k + 1 }
|
||||
if (k == nlen) and ((i + k) < hlen) and (hdr[i + k] == 58) {
|
||||
while (k < nlen) and ((i + k) < hlen) and (http_lower(hdr[i + k]) == http_lower(name[k])) { k += 1 }
|
||||
if (k == nlen) and ((i + k) < hlen) and (hdr[i + k] == ':') {
|
||||
var v = i + k + 1
|
||||
while (v < hlen) and (hdr[v] == 32) { v = v + 1 } # skip spaces after ':'
|
||||
while (v < hlen) and (hdr[v] == ' ') { v += 1 } # skip spaces after ':'
|
||||
var e = v
|
||||
while (e < hlen) and (hdr[e] != 13) and (hdr[e] != 10) { e = e + 1 }
|
||||
while (e < hlen) and (hdr[e] != '\r') and (hdr[e] != '\n') { e += 1 }
|
||||
return http_slice_dup(hdr, v, e)
|
||||
}
|
||||
# advance to the next line.
|
||||
while (i < hlen) and (hdr[i] != 10) { i = i + 1 }
|
||||
i = i + 1
|
||||
while (i < hlen) and (hdr[i] != '\n') { i += 1 }
|
||||
i += 1
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ function rt_decode_png(path: string) -> bool {
|
|||
let size = rt_file_len
|
||||
if size < 8 { free(d); return false }
|
||||
if d[0] != 137 { free(d); return false }
|
||||
if d[1] != 80 { free(d); return false }
|
||||
if d[1] != 'P' { free(d); return false }
|
||||
|
||||
var w = 0
|
||||
var h = 0
|
||||
|
|
@ -110,7 +110,7 @@ function rt_decode_png(path: string) -> bool {
|
|||
}
|
||||
if png_tag(d, typ, 73, 68, 65, 84) { # IDAT
|
||||
for k in 0 .. ln { idat[idlen + k] = d[body + k] }
|
||||
idlen = idlen + ln
|
||||
idlen += ln
|
||||
}
|
||||
if png_tag(d, typ, 73, 69, 78, 68) { done = 1 } # IEND
|
||||
i = i + 12 + ln
|
||||
|
|
@ -150,8 +150,8 @@ function rt_decode_png(path: string) -> bool {
|
|||
if y > 0 { b = raw[prev + x] }
|
||||
if x >= fbpp { if y > 0 { c = raw[prev + x - fbpp] } }
|
||||
var v = raw[cur + x]
|
||||
if ft == 1 { v = v + a }
|
||||
if ft == 2 { v = v + b }
|
||||
if ft == 1 { v += a }
|
||||
if ft == 2 { v += b }
|
||||
if ft == 3 { v = v + (a + b) / 2 }
|
||||
if ft == 4 {
|
||||
let p = a + b - c
|
||||
|
|
@ -161,7 +161,7 @@ function rt_decode_png(path: string) -> bool {
|
|||
var pick = c
|
||||
if pb <= pc { pick = b }
|
||||
if pa <= pb { if pa <= pc { pick = a } }
|
||||
v = v + pick
|
||||
v += pick
|
||||
}
|
||||
raw[cur + x] = (v & 255)
|
||||
}
|
||||
|
|
@ -228,10 +228,10 @@ function rt_decode_png(path: string) -> bool {
|
|||
|
||||
# ---- images ---------------------------------------------------------------
|
||||
function rt_image_load(path: string) -> int {
|
||||
if img_n >= IMG_MAX { return 0 - 1 }
|
||||
if rt_decode_png(path) == false { return 0 - 1 }
|
||||
if img_n >= IMG_MAX { return -1 }
|
||||
if rt_decode_png(path) == false { return -1 }
|
||||
let id = img_n
|
||||
img_n = img_n + 1
|
||||
img_n += 1
|
||||
img_px[id] = png_px
|
||||
img_w[id] = png_w
|
||||
img_h[id] = png_h
|
||||
|
|
@ -316,10 +316,10 @@ function rt_draw_9slice(id: int, dx: int, dy: int, dw: int, dh: int, inset: int)
|
|||
|
||||
# ---- sprites (16x16 art) --------------------------------------------------
|
||||
function rt_png_load(path: string) -> int {
|
||||
if spr_n >= SPR_MAX { return 0 - 1 }
|
||||
if rt_decode_png(path) == false { return 0 - 1 }
|
||||
if spr_n >= SPR_MAX { return -1 }
|
||||
if rt_decode_png(path) == false { return -1 }
|
||||
let id = spr_n
|
||||
spr_n = spr_n + 1
|
||||
spr_n += 1
|
||||
let base = id * SPR_SZ * SPR_SZ
|
||||
for y in 0 .. SPR_SZ {
|
||||
for x in 0 .. SPR_SZ {
|
||||
|
|
@ -395,10 +395,10 @@ function rt_draw_sprite_ex(id: int, px: int, py: int, sc: int, flip: int, tint:
|
|||
|
||||
# ---- .lspr sprite sheets (palette + ASCII rows) ---------------------------
|
||||
function rt_hexval(c: int) -> int {
|
||||
if c >= 48 { if c <= 57 { return c - 48 } }
|
||||
if c >= 97 { if c <= 102 { return c - 87 } }
|
||||
if c >= 65 { if c <= 70 { return c - 55 } }
|
||||
return 0 - 1
|
||||
if c >= '0' { if c <= '9' { return c - 48 } }
|
||||
if c >= 'a' { if c <= 'f' { return c - 87 } }
|
||||
if c >= 'A' { if c <= 'F' { return c - 55 } }
|
||||
return -1
|
||||
}
|
||||
|
||||
function rt_sprites_load(path: string) -> void {
|
||||
|
|
@ -407,7 +407,7 @@ function rt_sprites_load(path: string) -> void {
|
|||
let size = rt_file_len
|
||||
let pal: words = words(128)
|
||||
fill(pal, 0, 128 * 4)
|
||||
var cur = 0 - 1
|
||||
var cur = -1
|
||||
var row = 0
|
||||
var i = 0
|
||||
while i < size {
|
||||
|
|
@ -416,10 +416,10 @@ function rt_sprites_load(path: string) -> void {
|
|||
var j = start
|
||||
while j < size {
|
||||
let ch = d[j]
|
||||
if ch == 10 { j = size } else { len = len + 1; j = j + 1 }
|
||||
if ch == '\n' { j = size } else { len += 1; j += 1 }
|
||||
}
|
||||
let c0 = d[start]
|
||||
if c0 == 112 { # 'p' — "pal <char> <rrggbb>"
|
||||
if c0 == 'p' { # 'p' — "pal <char> <rrggbb>"
|
||||
let ch = d[start + 4]
|
||||
var v = 0
|
||||
for k in 0 .. 6 {
|
||||
|
|
@ -428,18 +428,18 @@ function rt_sprites_load(path: string) -> void {
|
|||
}
|
||||
if ch < 128 { pal[ch] = ((255 << 24) | v) }
|
||||
}
|
||||
if c0 == 115 { # 's' — "spr" starts a new sprite
|
||||
cur = 0 - 1
|
||||
if c0 == 's' { # 's' — "spr" starts a new sprite
|
||||
cur = -1
|
||||
if spr_n < SPR_MAX {
|
||||
cur = spr_n
|
||||
spr_n = spr_n + 1
|
||||
spr_n += 1
|
||||
fill(offset(spr_px, cur * SPR_SZ * SPR_SZ * 4), 0, SPR_SZ * SPR_SZ * 4)
|
||||
}
|
||||
row = 0
|
||||
}
|
||||
if c0 != 112 {
|
||||
if c0 != 115 {
|
||||
if c0 != 35 { # '#' comment
|
||||
if c0 != 'p' {
|
||||
if c0 != 's' {
|
||||
if c0 != '#' { # '#' comment
|
||||
if cur >= 0 {
|
||||
if row < SPR_SZ {
|
||||
for x in 0 .. SPR_SZ {
|
||||
|
|
@ -447,7 +447,7 @@ function rt_sprites_load(path: string) -> void {
|
|||
spr_px[cur * SPR_SZ * SPR_SZ + row * SPR_SZ + x] = pal[(d[start + x] & 127)]
|
||||
}
|
||||
}
|
||||
row = row + 1
|
||||
row += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ function z_bits(need: int) -> int {
|
|||
return 0
|
||||
}
|
||||
val = (val | (z_src[z_pos] << z_bitcnt))
|
||||
z_pos = z_pos + 1
|
||||
z_bitcnt = z_bitcnt + 8
|
||||
z_pos += 1
|
||||
z_bitcnt += 8
|
||||
}
|
||||
z_bitbuf = (val >> need)
|
||||
z_bitcnt = z_bitcnt - need
|
||||
z_bitcnt -= need
|
||||
return (val & ((1 << need) - 1))
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ function z_table_build(table: words, lengths: words, n: int) -> void {
|
|||
}
|
||||
for s in 0 .. n {
|
||||
let l = lengths[s]
|
||||
table[l] = table[l] + 1
|
||||
table[l] += 1
|
||||
}
|
||||
table[0] = 0 # length 0 means "not present"
|
||||
# offset of each length's first symbol
|
||||
|
|
@ -72,7 +72,7 @@ function z_table_build(table: words, lengths: words, n: int) -> void {
|
|||
let l = lengths[s]
|
||||
if l != 0 {
|
||||
table[16 + offs[l]] = s
|
||||
offs[l] = offs[l] + 1
|
||||
offs[l] += 1
|
||||
}
|
||||
}
|
||||
free(offs)
|
||||
|
|
@ -88,7 +88,7 @@ function z_decode(table: words) -> int {
|
|||
if code - first < count {
|
||||
return table[16 + index + (code - first)]
|
||||
}
|
||||
index = index + count
|
||||
index += count
|
||||
first = ((first + count) << 1)
|
||||
code = (code << 1)
|
||||
}
|
||||
|
|
@ -130,14 +130,14 @@ function z_stored(out: pointer, at: int, cap: int) -> int {
|
|||
z_bitcnt = 0 # stored blocks are byte-aligned
|
||||
if z_pos + 4 > z_len { return -1 }
|
||||
let n = z_src[z_pos] + (z_src[z_pos + 1] << 8)
|
||||
z_pos = z_pos + 4 # LEN then its one's complement
|
||||
z_pos += 4 # LEN then its one's complement
|
||||
var w = at
|
||||
for i in 0 .. n {
|
||||
if z_pos >= z_len { return -1 }
|
||||
if w >= cap { return -1 }
|
||||
out[w] = z_src[z_pos]
|
||||
w = w + 1
|
||||
z_pos = z_pos + 1
|
||||
w += 1
|
||||
z_pos += 1
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ function z_codes(out: pointer, at: int, cap: int, lit: pointer, dist: pointer) -
|
|||
if sym < 256 {
|
||||
if w >= cap { return -1 }
|
||||
out[w] = sym
|
||||
w = w + 1
|
||||
w += 1
|
||||
}
|
||||
if sym > 256 {
|
||||
let s = sym - 257
|
||||
|
|
@ -164,7 +164,7 @@ function z_codes(out: pointer, at: int, cap: int, lit: pointer, dist: pointer) -
|
|||
for k in 0 .. length {
|
||||
if w >= cap { return -1 }
|
||||
out[w] = out[w - distance]
|
||||
w = w + 1
|
||||
w += 1
|
||||
}
|
||||
}
|
||||
sym = z_decode(lit)
|
||||
|
|
@ -208,7 +208,7 @@ function z_dynamic_tables(lit: pointer, dist: pointer) -> int {
|
|||
if sym < 0 { return 0 }
|
||||
if sym < 16 {
|
||||
lengths[n] = sym
|
||||
n = n + 1
|
||||
n += 1
|
||||
}
|
||||
if sym >= 16 {
|
||||
var prev = 0
|
||||
|
|
@ -223,7 +223,7 @@ function z_dynamic_tables(lit: pointer, dist: pointer) -> int {
|
|||
for k in 0 .. rep {
|
||||
if n < 320 {
|
||||
lengths[n] = prev
|
||||
n = n + 1
|
||||
n += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -294,14 +294,14 @@ function z_gunzip(src: pointer, len: int, out: pointer, cap: int) -> int {
|
|||
pos = pos + 2 + xlen
|
||||
}
|
||||
if (flg & 8) != 0 { # FNAME: NUL-terminated
|
||||
while pos < len and src[pos] != 0 { pos = pos + 1 }
|
||||
pos = pos + 1
|
||||
while pos < len and src[pos] != 0 { pos += 1 }
|
||||
pos += 1
|
||||
}
|
||||
if (flg & 16) != 0 { # FCOMMENT: NUL-terminated
|
||||
while pos < len and src[pos] != 0 { pos = pos + 1 }
|
||||
pos = pos + 1
|
||||
while pos < len and src[pos] != 0 { pos += 1 }
|
||||
pos += 1
|
||||
}
|
||||
if (flg & 2) != 0 { pos = pos + 2 } # FHCRC: 2-byte header CRC
|
||||
if (flg & 2) != 0 { pos += 2 } # FHCRC: 2-byte header CRC
|
||||
if pos + 8 > len { return -1 }
|
||||
return z_inflate(offset(src, pos), len - pos - 8, out, cap)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ function input_find(name: pointer) -> int {
|
|||
var i = 0
|
||||
while i < input_nact {
|
||||
if input_names[i] == name { return i }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# get-or-create the slot for `name`.
|
||||
|
|
@ -63,7 +63,7 @@ function input_slot(name: pointer) -> int {
|
|||
if input_nact >= INPUT_MAX_ACT { return INPUT_MAX_ACT - 1 } # silently reuse the last slot when full
|
||||
let s = input_nact
|
||||
input_names[s] = name
|
||||
input_nact = input_nact + 1
|
||||
input_nact += 1
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -75,12 +75,12 @@ function input_bind(name: pointer, key: int) -> void {
|
|||
var i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_keys[base + i] == key { return } # already bound
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_keys[base + i] == 0 { input_keys[base + i] = key; return }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ function input_default(name: pointer, key: int) -> void {
|
|||
var i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_keys[base + i] != 0 { return } # already has a binding — keep it
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
input_keys[base] = key
|
||||
}
|
||||
|
|
@ -107,12 +107,12 @@ function input_bind_pad(name: pointer, button: int) -> void {
|
|||
var i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_pads[base + i] == (button + 1) { return } # already bound
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_pads[base + i] == 0 { input_pads[base + i] = button + 1; return }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ function input_rebind(name: pointer, oldkey: int, newkey: int) -> void {
|
|||
var i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_keys[base + i] == oldkey { input_keys[base + i] = newkey; return }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ function input_slot_has(s: int, k: int) -> bool {
|
|||
var i = 0
|
||||
while i < INPUT_MAX_KEYS {
|
||||
if input_keys[base + i] == k { return true }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ function input_commit() -> int {
|
|||
input_last = input_frame
|
||||
if input_mode == 2 { # replay
|
||||
var k = 0
|
||||
if input_pos < input_recn { k = input_rec[input_pos]; input_pos = input_pos + 1 }
|
||||
if input_pos < input_recn { k = input_rec[input_pos]; input_pos += 1 }
|
||||
input_frame = k
|
||||
input_device_commit(k, 1) # rebuild the device state from the tape
|
||||
return k
|
||||
|
|
@ -166,7 +166,7 @@ function input_commit() -> int {
|
|||
let k = rt_poll()
|
||||
if input_mode == 1 { # record
|
||||
if input_rec == null { input_rec = words(INPUT_REC_CAP) }
|
||||
if input_recn < INPUT_REC_CAP { input_rec[input_recn] = k; input_recn = input_recn + 1 }
|
||||
if input_recn < INPUT_REC_CAP { input_rec[input_recn] = k; input_recn += 1 }
|
||||
}
|
||||
input_frame = k
|
||||
input_device_commit(k, 0)
|
||||
|
|
@ -264,9 +264,9 @@ function in_bit_set(set: words, k: int, on: bool) -> void {
|
|||
let m = 1 << (k & 31)
|
||||
if on { set[w] = set[w] | m } else { set[w] = set[w] & (~m) }
|
||||
}
|
||||
function in_set_clear(set: words) -> void { var i = 0; while i < IN_WORDS { set[i] = 0; i = i + 1 } }
|
||||
function in_set_copy(dst: words, src: words) -> void { var i = 0; while i < IN_WORDS { dst[i] = src[i]; i = i + 1 } }
|
||||
function in_set_or(dst: words, a: words, b: words) -> void { var i = 0; while i < IN_WORDS { dst[i] = a[i] | b[i]; i = i + 1 } }
|
||||
function in_set_clear(set: words) -> void { var i = 0; while i < IN_WORDS { set[i] = 0; i += 1 } }
|
||||
function in_set_copy(dst: words, src: words) -> void { var i = 0; while i < IN_WORDS { dst[i] = src[i]; i += 1 } }
|
||||
function in_set_or(dst: words, a: words, b: words) -> void { var i = 0; while i < IN_WORDS { dst[i] = a[i] | b[i]; i += 1 } }
|
||||
|
||||
# ---- the per-frame device commit (called by input_poll) --------------------
|
||||
# Snapshot the committed set into prev (for edges), refresh the platform set (or
|
||||
|
|
@ -278,7 +278,7 @@ function input_device_commit(k: int, replaying: int) -> void {
|
|||
# Taken before the platform refresh (win_pad, below, runs after this), so it holds
|
||||
# the previous frame's committed value against which this frame's edge is measured.
|
||||
var pj = 0
|
||||
while pj < IN_PADS { in_pad_btn0[pj] = in_pad_btn[pj]; pj = pj + 1 }
|
||||
while pj < IN_PADS { in_pad_btn0[pj] = in_pad_btn[pj]; pj += 1 }
|
||||
|
||||
if replaying == 1 {
|
||||
# rebuild the platform set + mouse from the tape; sim/injection is ignored so
|
||||
|
|
@ -286,7 +286,7 @@ function input_device_commit(k: int, replaying: int) -> void {
|
|||
let base = (input_pos - 1) * IN_STRIDE
|
||||
if (in_tape != null) and (base >= 0) {
|
||||
var i = 0
|
||||
while i < IN_WORDS { in_dev[i] = in_tape[base + i]; i = i + 1 }
|
||||
while i < IN_WORDS { in_dev[i] = in_tape[base + i]; i += 1 }
|
||||
in_mx = in_tape[base + 8]
|
||||
in_my = in_tape[base + 9]
|
||||
in_mbtn = in_tape[base + 10]
|
||||
|
|
@ -312,7 +312,7 @@ function input_device_commit(k: int, replaying: int) -> void {
|
|||
input_set_pad(pi, pbuf[pb] != 0, pbuf[pb + 1],
|
||||
as_fixed(pbuf[pb + 2]), as_fixed(pbuf[pb + 3]),
|
||||
as_fixed(pbuf[pb + 4]), as_fixed(pbuf[pb + 5]))
|
||||
pi = pi + 1
|
||||
pi += 1
|
||||
}
|
||||
let tbuf = words(IN_TOUCH * 3) # [active, x, y]/point
|
||||
win_touch(tbuf)
|
||||
|
|
@ -320,7 +320,7 @@ function input_device_commit(k: int, replaying: int) -> void {
|
|||
while ti < IN_TOUCH {
|
||||
let tb = ti * 3
|
||||
input_set_touch(ti, tbuf[tb + 1], tbuf[tb + 2], tbuf[tb] != 0)
|
||||
ti = ti + 1
|
||||
ti += 1
|
||||
}
|
||||
} else {
|
||||
in_set_clear(in_dev)
|
||||
|
|
@ -345,7 +345,7 @@ function input_device_record() -> void {
|
|||
if (f < 0) or (f >= INPUT_REC_CAP) { return }
|
||||
let base = f * IN_STRIDE
|
||||
var i = 0
|
||||
while i < IN_WORDS { in_tape[base + i] = in_held[i]; i = i + 1 }
|
||||
while i < IN_WORDS { in_tape[base + i] = in_held[i]; i += 1 }
|
||||
in_tape[base + 8] = in_mx
|
||||
in_tape[base + 9] = in_my
|
||||
in_tape[base + 10] = in_mbtn
|
||||
|
|
@ -366,8 +366,8 @@ function input_release(k: int) -> void { in_init(); in_bit_set(in_sim, k, false
|
|||
function input_axis(neg: int, pos: int) -> fixed {
|
||||
in_init()
|
||||
var v = fixed(0)
|
||||
if in_bit_get(in_held, pos) { v = v + fixed(1) }
|
||||
if in_bit_get(in_held, neg) { v = v - fixed(1) }
|
||||
if in_bit_get(in_held, pos) { v += fixed(1) }
|
||||
if in_bit_get(in_held, neg) { v -= fixed(1) }
|
||||
return v
|
||||
}
|
||||
# #79 — a directional intent as a plain int: +1 if the positive key is held, -1 if
|
||||
|
|
@ -377,38 +377,44 @@ function input_axis(neg: int, pos: int) -> fixed {
|
|||
function input_axis_i(neg: int, pos: int) -> int {
|
||||
in_init()
|
||||
var v = 0
|
||||
if in_bit_get(in_held, pos) { v = v + 1 }
|
||||
if in_bit_get(in_held, neg) { v = v - 1 }
|
||||
if in_bit_get(in_held, pos) { v += 1 }
|
||||
if in_bit_get(in_held, neg) { v -= 1 }
|
||||
return v
|
||||
}
|
||||
# a stick has to leave its centre by this much before it counts as a direction
|
||||
const STICK_DEADZONE: fixed = 0.35
|
||||
# gamepad axis indices as input_pad_axis numbers them
|
||||
const STICK_LEFT_X: int = 0
|
||||
const STICK_LEFT_Y: int = 1
|
||||
|
||||
# The standard top-down movement intent as -1/0/1 per axis: WASD or the arrow
|
||||
# keys, and the left stick of pad 0 (past a 0.35 deadzone) when one is connected.
|
||||
# keys, and the left stick of pad 0 (past the deadzone) when one is connected.
|
||||
function input_move_i() -> IVec2 {
|
||||
in_init()
|
||||
var x = input_axis_i(Key.A, Key.D) + input_axis_i(Key.Left, Key.Right)
|
||||
var y = input_axis_i(Key.W, Key.S) + input_axis_i(Key.Up, Key.Down)
|
||||
if input_pad_connected(0) {
|
||||
let sx = input_pad_axis(0, 0)
|
||||
let sy = input_pad_axis(0, 1)
|
||||
if sx > 0.35 { x = 1 }
|
||||
if sx < -0.35 { x = 0 - 1 }
|
||||
if sy > 0.35 { y = 1 }
|
||||
if sy < -0.35 { y = 0 - 1 }
|
||||
let sx = input_pad_axis(0, STICK_LEFT_X)
|
||||
let sy = input_pad_axis(0, STICK_LEFT_Y)
|
||||
if sx > STICK_DEADZONE { x = 1 }
|
||||
if sx < -STICK_DEADZONE { x = -1 }
|
||||
if sy > STICK_DEADZONE { y = 1 }
|
||||
if sy < -STICK_DEADZONE { y = -1 }
|
||||
}
|
||||
return IVec2.make(clamp(x, 0 - 1, 1), clamp(y, 0 - 1, 1))
|
||||
return IVec2.make(clamp(x, -1, 1), clamp(y, -1, 1))
|
||||
}
|
||||
# A 2D vector from four direction keys, normalized so a diagonal is not faster.
|
||||
function input_vector(left: int, right: int, up: int, down: int) -> Vector {
|
||||
in_init()
|
||||
var x = fixed(0)
|
||||
var y = fixed(0)
|
||||
if in_bit_get(in_held, right) { x = x + fixed(1) }
|
||||
if in_bit_get(in_held, left) { x = x - fixed(1) }
|
||||
if in_bit_get(in_held, down) { y = y + fixed(1) }
|
||||
if in_bit_get(in_held, up) { y = y - fixed(1) }
|
||||
if in_bit_get(in_held, right) { x += fixed(1) }
|
||||
if in_bit_get(in_held, left) { x -= fixed(1) }
|
||||
if in_bit_get(in_held, down) { y += fixed(1) }
|
||||
if in_bit_get(in_held, up) { y -= fixed(1) }
|
||||
if (x != 0) and (y != 0) { # diagonal: scale by 1/sqrt(2)
|
||||
x = x * 0.7071 # fixed multiply (64-bit intermediate)
|
||||
y = y * 0.7071
|
||||
x *= 0.7071 # fixed multiply (64-bit intermediate)
|
||||
y *= 0.7071
|
||||
}
|
||||
return Vector.make(x, y)
|
||||
}
|
||||
|
|
@ -486,7 +492,7 @@ function input_touch_count() -> int {
|
|||
in_init()
|
||||
var n = 0
|
||||
var i = 0
|
||||
while i < IN_TOUCH { if in_touch_on[i] != 0 { n = n + 1 }; i = i + 1 }
|
||||
while i < IN_TOUCH { if in_touch_on[i] != 0 { n += 1 }; i += 1 }
|
||||
return n
|
||||
}
|
||||
function input_touch_x(i: int) -> int { in_init(); if (i < 0) or (i >= IN_TOUCH) { return 0 }; return in_touch_x[i] }
|
||||
|
|
@ -523,7 +529,7 @@ function input_active_in(name: pointer, held: words, padmask: int) -> bool {
|
|||
if (k != 0) and in_bit_get(held, k) { return true }
|
||||
let pb = input_pads[base + i]
|
||||
if (pb != 0) and ((padmask & (1 << (pb - 1))) != 0) { return true }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ function jb_alloc(kind: int) -> int {
|
|||
jb_nmem[i] = 0
|
||||
return i + 1
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -161,16 +161,16 @@ function jb_refresh_group(s: int) -> void {
|
|||
let ms = mh - 1
|
||||
let mst = jb_state[ms]
|
||||
if mst != J_PENDING {
|
||||
settled = settled + 1
|
||||
settled += 1
|
||||
if mst == J_DONE {
|
||||
ok = ok + 1
|
||||
ok += 1
|
||||
if first_ok == 0 { first_ok = mh }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
settled = settled + 1 # a freed/invalid member counts as settled-failed
|
||||
settled += 1 # a freed/invalid member counts as settled-failed
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
if k == JK_ALL {
|
||||
if ok == n { jb_state[s] = J_DONE; jb_result[s] = n }
|
||||
|
|
@ -227,8 +227,8 @@ function job_pending() -> int {
|
|||
var n = 0
|
||||
var i = 0
|
||||
while i < JOB_SLOTS {
|
||||
if jb_state[i] == J_PENDING { n = n + 1 }
|
||||
i = i + 1
|
||||
if jb_state[i] == J_PENDING { n += 1 }
|
||||
i += 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ function jb_step(s: int) -> int {
|
|||
var i = jb_i[s]
|
||||
if k == JK_SUM {
|
||||
jb_acc[s] = jb_acc[s] + (i + 1)
|
||||
i = i + 1
|
||||
i += 1
|
||||
jb_i[s] = i
|
||||
if i >= n { jb_state[s] = J_DONE; jb_result[s] = jb_acc[s]; return 1 }
|
||||
return 0
|
||||
|
|
@ -256,14 +256,14 @@ function jb_step(s: int) -> int {
|
|||
let t = jb_acc[s] + jb_acc2[s]
|
||||
jb_acc[s] = jb_acc2[s]
|
||||
jb_acc2[s] = t
|
||||
i = i + 1
|
||||
i += 1
|
||||
jb_i[s] = i
|
||||
if i >= n { jb_state[s] = J_DONE; jb_result[s] = jb_acc[s]; return 1 }
|
||||
return 0
|
||||
}
|
||||
if k == JK_PRIMES {
|
||||
if jb_is_prime(i) { jb_acc[s] = jb_acc[s] + 1 }
|
||||
i = i + 1
|
||||
if jb_is_prime(i) { jb_acc[s] += 1 }
|
||||
i += 1
|
||||
jb_i[s] = i
|
||||
if i > n { jb_state[s] = J_DONE; jb_result[s] = jb_acc[s]; return 1 }
|
||||
return 0
|
||||
|
|
@ -276,7 +276,7 @@ function jb_is_prime(v: int) -> bool {
|
|||
var d = 2
|
||||
while d * d <= v {
|
||||
if v - (v / d) * d == 0 { return false }
|
||||
d = d + 1
|
||||
d += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
@ -296,10 +296,10 @@ function job_pump(budget: int) -> int {
|
|||
while (jb_state[s] == J_PENDING) and compute {
|
||||
if (budget > 0) and (spent >= budget) { s = JOB_SLOTS + 1; break }
|
||||
let fin = jb_step(s)
|
||||
spent = spent + 1
|
||||
if fin == 1 { completed = completed + 1 }
|
||||
spent += 1
|
||||
if fin == 1 { completed += 1 }
|
||||
}
|
||||
s = s + 1
|
||||
s += 1
|
||||
}
|
||||
# settle groups after the compute jobs advanced this frame.
|
||||
s = 0
|
||||
|
|
@ -308,10 +308,10 @@ function job_pump(budget: int) -> int {
|
|||
let k = jb_kind[s]
|
||||
if (k == JK_ALL) or (k == JK_RACE) {
|
||||
jb_refresh_group(s)
|
||||
if jb_state[s] != J_PENDING { completed = completed + 1 }
|
||||
if jb_state[s] != J_PENDING { completed += 1 }
|
||||
}
|
||||
}
|
||||
s = s + 1
|
||||
s += 1
|
||||
}
|
||||
return completed
|
||||
}
|
||||
|
|
@ -324,7 +324,7 @@ function jb_set_members(s: int, handles: []int) -> void {
|
|||
if n > JOB_MAXMEM { n = JOB_MAXMEM }
|
||||
let base = s * JOB_MAXMEM
|
||||
var i = 0
|
||||
while i < n { jb_mem[base + i] = handles[i]; i = i + 1 }
|
||||
while i < n { jb_mem[base + i] = handles[i]; i += 1 }
|
||||
jb_nmem[s] = n
|
||||
}
|
||||
|
||||
|
|
@ -354,8 +354,8 @@ function prom_count_done(handles: []int) -> int {
|
|||
var n = 0
|
||||
var i = 0
|
||||
while i < len(handles) {
|
||||
if job_done(handles[i]) { n = n + 1 }
|
||||
i = i + 1
|
||||
if job_done(handles[i]) { n += 1 }
|
||||
i += 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
|
@ -364,7 +364,7 @@ function prom_all_done(handles: []int) -> bool {
|
|||
var i = 0
|
||||
while i < len(handles) {
|
||||
if not job_done(handles[i]) { return false }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
@ -415,7 +415,7 @@ function sync_mutex() -> int {
|
|||
var i = 0
|
||||
while i < SYNC_MUTEX {
|
||||
if mx_used[i] == 0 { mx_used[i] = 1; mx_held[i] = 0; return i + 1 }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -447,7 +447,7 @@ function sync_atomic() -> int {
|
|||
var i = 0
|
||||
while i < SYNC_ATOMIC {
|
||||
if at_used[i] == 0 { at_used[i] = 1; at_val[i] = 0; return i + 1 }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -468,7 +468,7 @@ function sync_set(a: int, v: int) -> void {
|
|||
function sync_add(a: int, delta: int) -> int {
|
||||
sy_init()
|
||||
if (a < 1) or (a > SYNC_ATOMIC) { return 0 }
|
||||
at_val[a - 1] = at_val[a - 1] + delta
|
||||
at_val[a - 1] += delta
|
||||
return at_val[a - 1]
|
||||
}
|
||||
|
||||
|
|
@ -487,7 +487,7 @@ function sync_channel() -> int {
|
|||
var i = 0
|
||||
while i < SYNC_CHAN {
|
||||
if ch_used[i] == 0 { ch_used[i] = 1; ch_head[i] = 0; ch_count[i] = 0; return i + 1 }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -500,9 +500,9 @@ function sync_send(c: int, v: int) -> bool {
|
|||
if ch_count[s] >= CHAN_CAP { return false }
|
||||
let pos = ch_head[s] + ch_count[s]
|
||||
var idx = pos
|
||||
if idx >= CHAN_CAP { idx = idx - CHAN_CAP }
|
||||
if idx >= CHAN_CAP { idx -= CHAN_CAP }
|
||||
ch_buf[s * CHAN_CAP + idx] = v
|
||||
ch_count[s] = ch_count[s] + 1
|
||||
ch_count[s] += 1
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -516,7 +516,7 @@ function sync_recv(c: int) -> int {
|
|||
var nh = ch_head[s] + 1
|
||||
if nh >= CHAN_CAP { nh = 0 }
|
||||
ch_head[s] = nh
|
||||
ch_count[s] = ch_count[s] - 1
|
||||
ch_count[s] -= 1
|
||||
return v
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ function light_occlude(x: int, y: int, w: int, h: int) -> void {
|
|||
rt_light_occ[i + 1] = y
|
||||
rt_light_occ[i + 2] = w
|
||||
rt_light_occ[i + 3] = h
|
||||
rt_light_occ_n = rt_light_occ_n + 1
|
||||
rt_light_occ_n += 1
|
||||
}
|
||||
|
||||
# ---- shadow geometry ------------------------------------------------------
|
||||
|
|
@ -63,7 +63,7 @@ function light_occlude(x: int, y: int, w: int, h: int) -> void {
|
|||
function light_orient(ax: int, ay: int, bx: int, by: int, cx: int, cy: int) -> int {
|
||||
let v = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)
|
||||
if v > 0 { return 1 }
|
||||
if v < 0 { return 0 - 1 }
|
||||
if v < 0 { return -1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ function light_blocked(lx: int, ly: int, px: int, py: int) -> bool {
|
|||
if light_seg_cross(lx, ly, px, py, x1, y0, x1, y1) { return true } # right
|
||||
if light_seg_cross(lx, ly, px, py, x1, y1, x0, y1) { return true } # bottom
|
||||
if light_seg_cross(lx, ly, px, py, x0, y1, x0, y0) { return true } # left
|
||||
k = k + 1
|
||||
k += 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ function light_fsqrt(v: fixed) -> fixed {
|
|||
var rt_light_falloff: int = 1 # brightness ramp exponent: 1 linear, 2 quadratic, 3 cubic…
|
||||
var rt_light_soft: int = 0 # penumbra radius in px (0 = hard single-sample shadow)
|
||||
var rt_light_gel: int = 0 # outer gel colour 0x00RRGGBB (used only when rt_light_gel_on)
|
||||
var rt_light_gel_on: bool = false # gel active? off = a flat single-colour light
|
||||
var rt_light_gel_on: bool = false # gel active? off = a flat single-colour light
|
||||
var rt_light_h: int = 64 # virtual light height above the surface, for normal-map N·L
|
||||
|
||||
function light_set_falloff(exp: int) -> void {
|
||||
|
|
@ -163,7 +163,7 @@ function light_clear_normals() -> void {
|
|||
if rt_light_nrm == null { return }
|
||||
let n = rt_fbw * rt_fbh
|
||||
var i = 0
|
||||
while i < n { rt_light_nrm[i] = 0; i = i + 1 }
|
||||
while i < n { rt_light_nrm[i] = 0; i += 1 }
|
||||
}
|
||||
|
||||
# stamp a rectangular region's surface normal. nx, ny are the normal's x/y as a
|
||||
|
|
@ -182,10 +182,10 @@ function light_normal_rect(x: int, y: int, w: int, h: int, nx: fixed, ny: fixed)
|
|||
var px = x
|
||||
while px < x + w {
|
||||
if (px >= 0) and (px < rt_fbw) { rt_light_nrm[py * rt_fbw + px] = packed }
|
||||
px = px + 1
|
||||
px += 1
|
||||
}
|
||||
}
|
||||
py = py + 1
|
||||
py += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ function light_atan2_deg(y: int, x: int) -> int {
|
|||
# smallest absolute difference between two whole-degree angles, 0..180.
|
||||
function light_ang_diff(a: int, b: int) -> int {
|
||||
var d = a - b
|
||||
if d < 0 { d = 0 - d }
|
||||
if d < 0 { d = -d }
|
||||
if d > 180 { d = 360 - d }
|
||||
return d
|
||||
}
|
||||
|
|
@ -231,7 +231,7 @@ function light_pow_t(t: fixed, exp: int) -> fixed {
|
|||
if exp <= 1 { return t }
|
||||
var r = t
|
||||
var i = 1
|
||||
while i < exp { r = r * t; i = i + 1 }
|
||||
while i < exp { r *= t; i += 1 }
|
||||
return r
|
||||
}
|
||||
|
||||
|
|
@ -246,11 +246,11 @@ function light_vis(cx: int, cy: int, px: int, py: int) -> fixed {
|
|||
}
|
||||
let s = rt_light_soft
|
||||
var hit = 0
|
||||
if not light_blocked(cx, cy, px, py) { hit = hit + 1 }
|
||||
if not light_blocked(cx + s, cy, px, py) { hit = hit + 1 }
|
||||
if not light_blocked(cx - s, cy, px, py) { hit = hit + 1 }
|
||||
if not light_blocked(cx, cy + s, px, py) { hit = hit + 1 }
|
||||
if not light_blocked(cx, cy - s, px, py) { hit = hit + 1 }
|
||||
if not light_blocked(cx, cy, px, py) { hit += 1 }
|
||||
if not light_blocked(cx + s, cy, px, py) { hit += 1 }
|
||||
if not light_blocked(cx - s, cy, px, py) { hit += 1 }
|
||||
if not light_blocked(cx, cy + s, px, py) { hit += 1 }
|
||||
if not light_blocked(cx, cy - s, px, py) { hit += 1 }
|
||||
return fixed(hit) / fixed(5)
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ function light_ambient(color: int) -> void {
|
|||
let ng = (((cur >> 8) & 255) * ag) / 255
|
||||
let nb = ((cur & 255) * ab) / 255
|
||||
rt_fb[i] = (nr << 16) | (ng << 8) | nb
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -368,17 +368,17 @@ function light_emit(cx: int, cy: int, radius: int, color: int, energy: fixed, di
|
|||
}
|
||||
}
|
||||
}
|
||||
px = px + 1
|
||||
px += 1
|
||||
}
|
||||
}
|
||||
py = py + 1
|
||||
py += 1
|
||||
}
|
||||
}
|
||||
|
||||
# a radial (omnidirectional) point light — the original short-signature call,
|
||||
# now a thin wrapper over light_emit with the cone disabled.
|
||||
function light_point(cx: int, cy: int, radius: int, color: int, energy: fixed) -> void {
|
||||
light_emit(cx, cy, radius, color, energy, 0, 0 - 1)
|
||||
light_emit(cx, cy, radius, color, energy, 0, -1)
|
||||
}
|
||||
|
||||
# a cone / spot light aimed at `direction` degrees (0 = +x, CCW) with a half-angle
|
||||
|
|
@ -396,7 +396,7 @@ function light_spot(cx: int, cy: int, radius: int, color: int, energy: fixed, di
|
|||
function light_time_of_day(t: fixed) -> void {
|
||||
# day factor 0..1: 0 at midnight, 1 at noon (triangle over the day).
|
||||
var day = t * fixed(2) # 0..2 across the day
|
||||
if day > fixed(1) { day = fixed(2) - day } # fold 0.5..1 back down: peak at noon
|
||||
if day > fixed(1) { day = fixed(2) - day } # fold 0.5..1 back down: peak at noon
|
||||
if day < 0 { day = fixed(0) }
|
||||
# night tint 0x14142a (deep blue) -> day 0xffffff, per channel.
|
||||
let nr = 20; let ng = 20; let nb = 42
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ function huge_make(m: fixed, e: int) -> Huge {
|
|||
var mm = m
|
||||
if mm < 0.0 { neg = true; mm = 0.0 - mm }
|
||||
var ee = e
|
||||
while mm >= HUGE_TEN { mm = mm / HUGE_TEN; ee = ee + 1 }
|
||||
while mm < HUGE_ONE { mm = mm * HUGE_TEN; ee = ee - 1 }
|
||||
while mm >= HUGE_TEN { mm /= HUGE_TEN; ee += 1 }
|
||||
while mm < HUGE_ONE { mm *= HUGE_TEN; ee -= 1 }
|
||||
if neg { mm = 0.0 - mm }
|
||||
h.m = mm; h.e = ee
|
||||
return h
|
||||
|
|
@ -45,10 +45,10 @@ function huge_from(value: int) -> Huge {
|
|||
if value == 0 { return huge_make(0.0, 0) }
|
||||
var neg = false
|
||||
var v: long = value
|
||||
if v < 0 { neg = true; v = 0 - v }
|
||||
if v < 0 { neg = true; v = -v }
|
||||
var e = 0
|
||||
var p: long = 1
|
||||
while p * 10 <= v { p = p * 10; e = e + 1 }
|
||||
while p * 10 <= v { p *= 10; e += 1 }
|
||||
let raw: long = (v * 65536) / p # v / 10^e in Q16.16 (in [1,10))
|
||||
let rawi: int = raw
|
||||
var m: fixed = as_fixed(rawi)
|
||||
|
|
@ -78,7 +78,7 @@ function huge_add(a: Huge, b: Huge) -> Huge {
|
|||
if diff > 8 { return big } # negligible at display precision
|
||||
var sm = small.m
|
||||
var k = 0
|
||||
while k < diff { sm = sm / HUGE_TEN; k = k + 1 }
|
||||
while k < diff { sm /= HUGE_TEN; k += 1 }
|
||||
return huge_make(big.m + sm, big.e)
|
||||
}
|
||||
|
||||
|
|
@ -90,9 +90,9 @@ function huge_cmp(a: Huge, b: Huge) -> int {
|
|||
if sa != sb { if sa > sb { return 1 }; return -1 }
|
||||
if sa == 0 { return 0 }
|
||||
var c = 0
|
||||
if a.e != b.e { if a.e > b.e { c = 1 } else { c = 0 - 1 } }
|
||||
else { if a.m > b.m { c = 1 } else { if a.m < b.m { c = 0 - 1 } else { c = 0 } } }
|
||||
if sa < 0 { c = 0 - c }
|
||||
if a.e != b.e { if a.e > b.e { c = 1 } else { c = -1 } }
|
||||
else { if a.m > b.m { c = 1 } else { if a.m < b.m { c = -1 } else { c = 0 } } }
|
||||
if sa < 0 { c = -c }
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
@ -109,8 +109,8 @@ function huge_str(a: Huge) -> pointer {
|
|||
let frac: fixed = m - fixed(ip)
|
||||
var dd: int = floor(frac * 100.0 + 0.5) # round the two decimals to nearest
|
||||
var ex = a.e
|
||||
if dd >= 100 { dd = 0; ip = ip + 1 } # rounding carried into the ones place
|
||||
if ip >= 10 { ip = 1; ex = ex + 1 } # ...and on into the exponent
|
||||
if dd >= 100 { dd = 0; ip += 1 } # rounding carried into the ones place
|
||||
if ip >= 10 { ip = 1; ex += 1 } # ...and on into the exponent
|
||||
var ds = string(dd)
|
||||
if dd < 10 { ds = "0" + ds }
|
||||
return neg + string(ip) + "." + ds + "e" + string(ex)
|
||||
|
|
@ -124,8 +124,8 @@ const ANGLE_TAU: fixed = 6.28318531
|
|||
# wrap any radian value into the half-open range [-pi, pi)
|
||||
function angle_wrap(a: fixed) -> fixed {
|
||||
var x = a
|
||||
while x >= ANGLE_PI { x = x - ANGLE_TAU }
|
||||
while x < 0.0 - ANGLE_PI { x = x + ANGLE_TAU }
|
||||
while x >= ANGLE_PI { x -= ANGLE_TAU }
|
||||
while x < 0.0 - ANGLE_PI { x += ANGLE_TAU }
|
||||
return x
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ function query_count(prop: int) -> int {
|
|||
var n = 0
|
||||
var e = world_query_next(prop, 0)
|
||||
while e >= 0 {
|
||||
n = n + 1
|
||||
n += 1
|
||||
e = world_query_next(prop, e + 1)
|
||||
}
|
||||
return n
|
||||
|
|
@ -40,7 +40,7 @@ function query_first(prop: int) -> int {
|
|||
# y_field); pass the same id for `prop` and `pos` to query by the position
|
||||
# component itself, or a separate tag for `prop` (e.g. "nearest Enemy").
|
||||
function query_nearest(prop: int, pos: int, x_field: int, y_field: int, px: int, py: int) -> int {
|
||||
var best = 0 - 1
|
||||
var best = -1
|
||||
var bestd = 0
|
||||
var e = world_query_next(prop, 0)
|
||||
while e >= 0 {
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ function reflect_serialize(e: int) -> Val {
|
|||
var node = value_int(raw)
|
||||
if world_field_type(p, f) == "fixed" { node = value_fixed(raw) }
|
||||
value_put(comp, fname, node)
|
||||
f = f + 1
|
||||
f += 1
|
||||
}
|
||||
value_put(obj, world_prop_name(p), comp)
|
||||
}
|
||||
p = p + 1
|
||||
p += 1
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ function reflect_apply(e: int, v: Val) -> int {
|
|||
var i = 0
|
||||
while i < value_count(v) {
|
||||
let pname = value_key_at(v, i)
|
||||
if pname[0] != 64 { # skip reserved "@…" keys
|
||||
if pname[0] != '@' { # skip reserved "@…" keys
|
||||
let p = world_prop_id(pname)
|
||||
if p >= 0 and world_has(e, p) != 0 {
|
||||
let comp = value_at(v, i)
|
||||
|
|
@ -59,13 +59,13 @@ function reflect_apply(e: int, v: Val) -> int {
|
|||
let f = world_field_id(p, fname)
|
||||
if f >= 0 {
|
||||
world_set(e, p, f, value_as_int(value_at(comp, j)))
|
||||
set = set + 1
|
||||
set += 1
|
||||
}
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
# ============================================================================
|
||||
|
||||
# ---- small helpers ----------------------------------------------------------
|
||||
function rx_slen(s: pointer) -> int { var n = 0; while s[n] != 0 { n = n + 1 }; return n }
|
||||
function rx_slen(s: pointer) -> int { var n = 0; while s[n] != 0 { n += 1 }; return n }
|
||||
|
||||
# ---- growable int vector ----------------------------------------------------
|
||||
property IVec { d: words, n: int, cap: int }
|
||||
|
|
@ -37,17 +37,17 @@ function iv_new() -> IVec {
|
|||
function iv_grow(v: IVec, need: int) -> void {
|
||||
if v.n + need <= v.cap { return }
|
||||
var nc = v.cap * 2
|
||||
while nc < v.n + need { nc = nc * 2 }
|
||||
while nc < v.n + need { nc *= 2 }
|
||||
let nd = words(nc)
|
||||
var i = 0
|
||||
while i < v.n { nd[i] = v.d[i]; i = i + 1 }
|
||||
while i < v.n { nd[i] = v.d[i]; i += 1 }
|
||||
v.d = nd; v.cap = nc
|
||||
}
|
||||
function iv_push(v: IVec, x: int) -> int {
|
||||
iv_grow(v, 1)
|
||||
let idx = v.n
|
||||
v.d[v.n] = x
|
||||
v.n = v.n + 1
|
||||
v.n += 1
|
||||
return idx
|
||||
}
|
||||
|
||||
|
|
@ -80,13 +80,13 @@ const N_EMPTY: int = 13
|
|||
|
||||
property RNode {
|
||||
op: int = 0, ch: int = 0, cls: int = 0, lo: int = 0, hi: int = 0,
|
||||
greedy: int = 1, gidx: int = 0 - 1, kids: []RNode
|
||||
greedy: int = 1, gidx: int = -1, kids: []RNode
|
||||
}
|
||||
function rx_node(op: int) -> RNode {
|
||||
let n = new RNode
|
||||
n.op = op
|
||||
n.greedy = 1
|
||||
n.gidx = 0 - 1
|
||||
n.gidx = -1
|
||||
n.kids = new []RNode
|
||||
return n
|
||||
}
|
||||
|
|
@ -101,16 +101,16 @@ var rx_err: int = 0
|
|||
var rx_ngroup: int = 0
|
||||
var rx_prog: Prog = null
|
||||
|
||||
function rx_peek() -> int { if rx_pos < rx_len { return rx_pat[rx_pos] & 255 }; return 0 - 1 }
|
||||
function rx_peek2() -> int { if rx_pos + 1 < rx_len { return rx_pat[rx_pos + 1] & 255 }; return 0 - 1 }
|
||||
function rx_adv() -> int { let c = rx_peek(); rx_pos = rx_pos + 1; return c }
|
||||
function rx_peek() -> int { if rx_pos < rx_len { return rx_pat[rx_pos] & 255 }; return -1 }
|
||||
function rx_peek2() -> int { if rx_pos + 1 < rx_len { return rx_pat[rx_pos + 1] & 255 }; return -1 }
|
||||
function rx_adv() -> int { let c = rx_peek(); rx_pos += 1; return c }
|
||||
|
||||
# ---- character classes ------------------------------------------------------
|
||||
# a class is 8 i32 words (256 bits) in prog.cls; class k occupies cls[8k .. 8k+8)
|
||||
function rx_class_new() -> int {
|
||||
let idx = rx_prog.cls.n / 8
|
||||
var i = 0
|
||||
while i < 8 { iv_push(rx_prog.cls, 0); i = i + 1 }
|
||||
while i < 8 { iv_push(rx_prog.cls, 0); i += 1 }
|
||||
return idx
|
||||
}
|
||||
function rx_class_set(idx: int, c: int) -> void {
|
||||
|
|
@ -119,11 +119,11 @@ function rx_class_set(idx: int, c: int) -> void {
|
|||
}
|
||||
function rx_class_set_range(idx: int, a: int, b: int) -> void {
|
||||
var c = a
|
||||
while c <= b { rx_class_set(idx, c); c = c + 1 }
|
||||
while c <= b { rx_class_set(idx, c); c += 1 }
|
||||
}
|
||||
function rx_class_negate(idx: int) -> void {
|
||||
var i = 0
|
||||
while i < 8 { let w = idx * 8 + i; rx_prog.cls.d[w] = ~rx_prog.cls.d[w]; i = i + 1 }
|
||||
while i < 8 { let w = idx * 8 + i; rx_prog.cls.d[w] = ~rx_prog.cls.d[w]; i += 1 }
|
||||
}
|
||||
function rx_class_unset(idx: int, c: int) -> void {
|
||||
let w = idx * 8 + (c >> 5)
|
||||
|
|
@ -131,11 +131,11 @@ function rx_class_unset(idx: int, c: int) -> void {
|
|||
}
|
||||
function rx_class_unset_range(idx: int, a: int, b: int) -> void {
|
||||
var c = a
|
||||
while c <= b { rx_class_unset(idx, c); c = c + 1 }
|
||||
while c <= b { rx_class_unset(idx, c); c += 1 }
|
||||
}
|
||||
function rx_class_set_all(idx: int) -> void {
|
||||
var i = 0
|
||||
while i < 8 { rx_prog.cls.d[idx * 8 + i] = 0 - 1; i = i + 1 }
|
||||
while i < 8 { rx_prog.cls.d[idx * 8 + i] = -1; i += 1 }
|
||||
}
|
||||
function rx_class_set_word(idx: int) -> void {
|
||||
rx_class_set_range(idx, 48, 57)
|
||||
|
|
@ -151,12 +151,12 @@ function rx_class_has(prog: Prog, idx: int, c: int) -> bool {
|
|||
let w = prog.cls.d[idx * 8 + (c >> 5)]
|
||||
return (w & (1 << (c & 31))) != 0
|
||||
}
|
||||
function rx_is_digit(c: int) -> bool { return c >= 48 and c <= 57 }
|
||||
function rx_is_digit(c: int) -> bool { return c >= '0' and c <= '9' }
|
||||
function rx_is_word(c: int) -> bool {
|
||||
return (c >= 48 and c <= 57) or (c >= 65 and c <= 90) or (c >= 97 and c <= 122) or c == 95
|
||||
return (c >= '0' and c <= '9') or (c >= 'A' and c <= 'Z') or (c >= 'a' and c <= 'z') or c == '_'
|
||||
}
|
||||
function rx_is_ws(c: int) -> bool {
|
||||
return c == 32 or c == 9 or c == 10 or c == 13 or c == 12 or c == 11
|
||||
return c == ' ' or c == '\t' or c == '\n' or c == '\r' or c == 12 or c == 11
|
||||
}
|
||||
# OR the set named by \d \D \w \W \s \S into class idx. The negated forms OR in
|
||||
# the complement set bit-by-bit (never via set-all+unset, which would clobber a
|
||||
|
|
@ -170,7 +170,7 @@ function rx_class_add_pre(idx: int, kind: int) -> void {
|
|||
if kind == 68 { if not rx_is_digit(c) { rx_class_set(idx, c) } } # \D
|
||||
else if kind == 87 { if not rx_is_word(c) { rx_class_set(idx, c) } } # \W
|
||||
else if kind == 83 { if not rx_is_ws(c) { rx_class_set(idx, c) } } # \S
|
||||
c = c + 1
|
||||
c += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +186,7 @@ function rx_parse_class() -> RNode {
|
|||
var lo = rx_adv()
|
||||
if lo == 92 { # escape inside class
|
||||
let e = rx_adv()
|
||||
if e == 100 or e == 68 or e == 119 or e == 87 or e == 115 or e == 83 {
|
||||
if e == 'd' or e == 'D' or e == 'w' or e == 'W' or e == 's' or e == 'S' {
|
||||
rx_class_add_pre(idx, e)
|
||||
continue
|
||||
}
|
||||
|
|
@ -210,12 +210,12 @@ function rx_parse_class() -> RNode {
|
|||
}
|
||||
# map an escaped char inside a class to its byte
|
||||
function rx_class_escape_char(e: int) -> int {
|
||||
if e == 110 { return 10 }
|
||||
if e == 116 { return 9 }
|
||||
if e == 114 { return 13 }
|
||||
if e == 102 { return 12 }
|
||||
if e == 118 { return 11 }
|
||||
if e == 48 { return 0 }
|
||||
if e == 'n' { return 10 }
|
||||
if e == 't' { return 9 }
|
||||
if e == 'r' { return 13 }
|
||||
if e == 'f' { return 12 }
|
||||
if e == 'v' { return 11 }
|
||||
if e == '0' { return 0 }
|
||||
return e
|
||||
}
|
||||
|
||||
|
|
@ -223,21 +223,21 @@ function rx_class_escape_char(e: int) -> int {
|
|||
function rx_parse_escape() -> RNode {
|
||||
rx_adv() # consume '\'
|
||||
let e = rx_adv()
|
||||
if e == 100 or e == 68 or e == 119 or e == 87 or e == 115 or e == 83 {
|
||||
if e == 'd' or e == 'D' or e == 'w' or e == 'W' or e == 's' or e == 'S' {
|
||||
let idx = rx_class_new()
|
||||
rx_class_add_pre(idx, e)
|
||||
let node = rx_node(N_CLASS)
|
||||
node.cls = idx
|
||||
return node
|
||||
}
|
||||
if e >= 49 and e <= 57 { rx_err = 1; return rx_node(N_EMPTY) } # backrefs unsupported
|
||||
if e >= '1' and e <= '9' { rx_err = 1; return rx_node(N_EMPTY) } # backrefs unsupported
|
||||
var ch = e
|
||||
if e == 110 { ch = 10 }
|
||||
else if e == 116 { ch = 9 }
|
||||
else if e == 114 { ch = 13 }
|
||||
else if e == 102 { ch = 12 }
|
||||
else if e == 118 { ch = 11 }
|
||||
else if e == 48 { ch = 0 }
|
||||
if e == 'n' { ch = 10 }
|
||||
else if e == 't' { ch = 9 }
|
||||
else if e == 'r' { ch = 13 }
|
||||
else if e == 'f' { ch = 12 }
|
||||
else if e == 'v' { ch = 11 }
|
||||
else if e == '0' { ch = 0 }
|
||||
else if e < 0 { rx_err = 1; return rx_node(N_EMPTY) }
|
||||
let node = rx_node(N_LIT)
|
||||
node.ch = ch
|
||||
|
|
@ -261,7 +261,7 @@ function rx_parse_concat() -> RNode {
|
|||
let cat = rx_node(N_CONCAT)
|
||||
while true {
|
||||
let c = rx_peek()
|
||||
if c < 0 or c == 124 or c == 41 { break }
|
||||
if c < 0 or c == '|' or c == ')' { break }
|
||||
push(cat.kids, rx_parse_repeat())
|
||||
if rx_err == 1 { break }
|
||||
}
|
||||
|
|
@ -278,17 +278,17 @@ function rx_parse_repeat() -> RNode {
|
|||
let atom = rx_parse_atom()
|
||||
if rx_err == 1 { return atom }
|
||||
let c = rx_peek()
|
||||
if c == 42 or c == 43 or c == 63 {
|
||||
if c == '*' or c == '+' or c == '?' {
|
||||
rx_adv()
|
||||
var op = N_STAR
|
||||
if c == 43 { op = N_PLUS }
|
||||
if c == 63 { op = N_QUEST }
|
||||
if c == '+' { op = N_PLUS }
|
||||
if c == '?' { op = N_QUEST }
|
||||
let r = rx_node(op)
|
||||
r.greedy = rx_lazy()
|
||||
push(r.kids, atom)
|
||||
return r
|
||||
}
|
||||
if c == 123 { return rx_parse_brace(atom) }
|
||||
if c == '{' { return rx_parse_brace(atom) }
|
||||
return atom
|
||||
}
|
||||
# {n} {n,} {n,m}
|
||||
|
|
@ -300,7 +300,7 @@ function rx_parse_brace(atom: RNode) -> RNode {
|
|||
while rx_peek() >= 48 and rx_peek() <= 57 { lo = lo * 10 + (rx_adv() - 48); haslo = true }
|
||||
var hi = lo
|
||||
var hasComma = false
|
||||
if rx_peek() == 44 { hasComma = true; rx_adv(); hi = 0 - 1
|
||||
if rx_peek() == 44 { hasComma = true; rx_adv(); hi = -1
|
||||
var hashi = false
|
||||
while rx_peek() >= 48 and rx_peek() <= 57 { if not hashi { hi = 0 }; hi = hi * 10 + (rx_adv() - 48); hashi = true }
|
||||
}
|
||||
|
|
@ -319,18 +319,18 @@ function rx_parse_brace(atom: RNode) -> RNode {
|
|||
}
|
||||
function rx_parse_atom() -> RNode {
|
||||
let c = rx_peek()
|
||||
if c == 40 { # '('
|
||||
if c == '(' { # '('
|
||||
rx_adv()
|
||||
var gidx = 0 - 1
|
||||
var gidx = -1
|
||||
if rx_peek() == 63 { # (? ...
|
||||
rx_adv()
|
||||
let d = rx_peek()
|
||||
if d == 58 { rx_adv() } # (?: non-capturing
|
||||
else if d == 80 { rx_adv(); rx_skip_name() } # (?P<name> (captured, name ignored for now)
|
||||
else if d == 60 { rx_skip_name() } # (?<name>
|
||||
if d == ':' { rx_adv() } # (?: non-capturing
|
||||
else if d == 'P' { rx_adv(); rx_skip_name() } # (?P<name> (captured, name ignored for now)
|
||||
else if d == '<' { rx_skip_name() } # (?<name>
|
||||
else { rx_err = 1; return rx_node(N_EMPTY) }
|
||||
} else {
|
||||
rx_ngroup = rx_ngroup + 1
|
||||
rx_ngroup += 1
|
||||
gidx = rx_ngroup
|
||||
}
|
||||
let inner = rx_parse_alt()
|
||||
|
|
@ -341,12 +341,12 @@ function rx_parse_atom() -> RNode {
|
|||
push(g.kids, inner)
|
||||
return g
|
||||
}
|
||||
if c == 91 { return rx_parse_class() }
|
||||
if c == 46 { rx_adv(); return rx_node(N_ANY) }
|
||||
if c == 94 { rx_adv(); return rx_node(N_BOL) }
|
||||
if c == 36 { rx_adv(); return rx_node(N_EOL) }
|
||||
if c == 92 { return rx_parse_escape() }
|
||||
if c == 42 or c == 43 or c == 63 or c == 41 { rx_err = 1; return rx_node(N_EMPTY) }
|
||||
if c == '[' { return rx_parse_class() }
|
||||
if c == '.' { rx_adv(); return rx_node(N_ANY) }
|
||||
if c == '^' { rx_adv(); return rx_node(N_BOL) }
|
||||
if c == '$' { rx_adv(); return rx_node(N_EOL) }
|
||||
if c == '\\' { return rx_parse_escape() }
|
||||
if c == '*' or c == '+' or c == '?' or c == ')' { rx_err = 1; return rx_node(N_EMPTY) }
|
||||
if c < 0 { rx_err = 1; return rx_node(N_EMPTY) }
|
||||
rx_adv()
|
||||
let n = rx_node(N_LIT)
|
||||
|
|
@ -359,7 +359,7 @@ function rx_skip_name() -> void {
|
|||
if rx_peek() == 60 { rx_adv() } # consume '<'
|
||||
while rx_peek() != 62 and rx_peek() >= 0 { rx_adv() }
|
||||
if rx_peek() == 62 { rx_adv() } # consume '>'
|
||||
rx_ngroup = rx_ngroup + 1
|
||||
rx_ngroup += 1
|
||||
# note: the caller set gidx = -1; fix it up to a real capture index
|
||||
rx_named_gidx = rx_ngroup
|
||||
}
|
||||
|
|
@ -387,7 +387,7 @@ function rx_compile(node: RNode) -> void {
|
|||
if op == N_EOL { pg_emit(OP_EOL, 0, 0); return }
|
||||
if op == N_CONCAT {
|
||||
var i = 0
|
||||
while i < len(node.kids) { rx_compile(node.kids[i]); i = i + 1 }
|
||||
while i < len(node.kids) { rx_compile(node.kids[i]); i += 1 }
|
||||
return
|
||||
}
|
||||
if op == N_GROUP {
|
||||
|
|
@ -414,11 +414,11 @@ function rx_compile(node: RNode) -> void {
|
|||
} else {
|
||||
rx_compile(node.kids[i])
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
let end = pg_pc()
|
||||
i = 0
|
||||
while i < jmps.n { pg_set_a(jmps.d[i], end); i = i + 1 }
|
||||
while i < jmps.n { pg_set_a(jmps.d[i], end); i += 1 }
|
||||
return
|
||||
}
|
||||
if op == N_STAR {
|
||||
|
|
@ -453,7 +453,7 @@ function rx_compile(node: RNode) -> void {
|
|||
if op == N_REP {
|
||||
let kid = node.kids[0]
|
||||
var i = 0
|
||||
while i < node.lo { rx_compile(kid); i = i + 1 }
|
||||
while i < node.lo { rx_compile(kid); i += 1 }
|
||||
if node.hi < 0 {
|
||||
let st = rx_node(N_STAR)
|
||||
st.greedy = node.greedy
|
||||
|
|
@ -466,7 +466,7 @@ function rx_compile(node: RNode) -> void {
|
|||
q.greedy = node.greedy
|
||||
push(q.kids, kid)
|
||||
rx_compile(q)
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
@ -503,4 +503,3 @@ function regex_compile(pattern: pointer) -> Prog {
|
|||
pg_emit(OP_MATCH, 0, 0)
|
||||
return p
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ function rx_add(list: TList, pc: int, caps: words, sp: int, s: pointer, slen: in
|
|||
let t = list.n
|
||||
list.pc[t] = pc
|
||||
var i = 0
|
||||
while i < rx_nc { list.caps[t * rx_nc + i] = caps[i]; i = i + 1 }
|
||||
list.n = list.n + 1
|
||||
while i < rx_nc { list.caps[t * rx_nc + i] = caps[i]; i += 1 }
|
||||
list.n += 1
|
||||
}
|
||||
|
||||
# run prog over s (length slen) from startpos; returns caps words or null
|
||||
|
|
@ -54,7 +54,7 @@ function rx_run(prog: Prog, s: pointer, slen: int, startpos: int) -> words {
|
|||
let ncode = prog.code.n / 3
|
||||
rx_seen = words(ncode)
|
||||
var i = 0
|
||||
while i < ncode { rx_seen[i] = 0; i = i + 1 }
|
||||
while i < ncode { rx_seen[i] = 0; i += 1 }
|
||||
rx_gen = 0
|
||||
var clist = new TList
|
||||
clist.pc = words(ncode); clist.caps = words(ncode * rx_nc); clist.n = 0
|
||||
|
|
@ -63,29 +63,29 @@ function rx_run(prog: Prog, s: pointer, slen: int, startpos: int) -> words {
|
|||
let wcaps = words(rx_nc)
|
||||
var matched: words = null
|
||||
|
||||
rx_gen = rx_gen + 1
|
||||
rx_gen += 1
|
||||
i = 0
|
||||
while i < rx_nc { wcaps[i] = 0 - 1; i = i + 1 }
|
||||
while i < rx_nc { wcaps[i] = -1; i += 1 }
|
||||
rx_add(clist, 0, wcaps, startpos, s, slen)
|
||||
|
||||
var sp = startpos
|
||||
while true {
|
||||
if clist.n == 0 { break }
|
||||
var c = 0 - 1
|
||||
var c = -1
|
||||
if sp < slen { c = s[sp] & 255 }
|
||||
nlist.n = 0
|
||||
rx_gen = rx_gen + 1
|
||||
rx_gen += 1
|
||||
var ti = 0
|
||||
var stop = false
|
||||
while ti < clist.n and not stop {
|
||||
let pc = clist.pc[ti]
|
||||
var k = 0
|
||||
while k < rx_nc { wcaps[k] = clist.caps[ti * rx_nc + k]; k = k + 1 }
|
||||
while k < rx_nc { wcaps[k] = clist.caps[ti * rx_nc + k]; k += 1 }
|
||||
let op = rx_code[3 * pc]
|
||||
if op == OP_CHAR {
|
||||
if c >= 0 and c == rx_code[3 * pc + 1] { rx_add(nlist, pc + 1, wcaps, sp + 1, s, slen) }
|
||||
} else if op == OP_ANY {
|
||||
if c >= 0 and c != 10 { rx_add(nlist, pc + 1, wcaps, sp + 1, s, slen) }
|
||||
if c >= 0 and c != '\n' { rx_add(nlist, pc + 1, wcaps, sp + 1, s, slen) }
|
||||
} else if op == OP_ANYNL {
|
||||
if c >= 0 { rx_add(nlist, pc + 1, wcaps, sp + 1, s, slen) }
|
||||
} else if op == OP_CLASS {
|
||||
|
|
@ -93,14 +93,14 @@ function rx_run(prog: Prog, s: pointer, slen: int, startpos: int) -> words {
|
|||
} else if op == OP_MATCH {
|
||||
if matched == null { matched = words(rx_nc) }
|
||||
k = 0
|
||||
while k < rx_nc { matched[k] = wcaps[k]; k = k + 1 }
|
||||
while k < rx_nc { matched[k] = wcaps[k]; k += 1 }
|
||||
stop = true
|
||||
}
|
||||
ti = ti + 1
|
||||
ti += 1
|
||||
}
|
||||
let tmp = clist; clist = nlist; nlist = tmp
|
||||
if sp >= slen { break }
|
||||
sp = sp + 1
|
||||
sp += 1
|
||||
}
|
||||
return matched
|
||||
}
|
||||
|
|
@ -143,11 +143,11 @@ function regex_next(str: pointer, re: Prog, from: int) -> Match {
|
|||
function regex_ok(m: Match) -> bool { return m != null }
|
||||
function regex_group_count(m: Match) -> int { if m == null { return 0 }; return m.ng }
|
||||
function regex_start(m: Match, n: int) -> int {
|
||||
if m == null or n < 0 or n > m.ng { return 0 - 1 }
|
||||
if m == null or n < 0 or n > m.ng { return -1 }
|
||||
return m.caps[2 * n]
|
||||
}
|
||||
function regex_end(m: Match, n: int) -> int {
|
||||
if m == null or n < 0 or n > m.ng { return 0 - 1 }
|
||||
if m == null or n < 0 or n > m.ng { return -1 }
|
||||
return m.caps[2 * n + 1]
|
||||
}
|
||||
function regex_group(m: Match, n: int) -> pointer {
|
||||
|
|
@ -157,7 +157,7 @@ function regex_group(m: Match, n: int) -> pointer {
|
|||
if a < 0 or b < 0 { return "" }
|
||||
let out = bytes(b - a + 1)
|
||||
var i = 0
|
||||
while i < b - a { out[i] = m.str[a + i]; i = i + 1 }
|
||||
while i < b - a { out[i] = m.str[a + i]; i += 1 }
|
||||
out[b - a] = 0
|
||||
return out
|
||||
}
|
||||
|
|
@ -167,7 +167,7 @@ function regex_valid(pattern: pointer) -> bool { return regex_compile(pattern) !
|
|||
# repl expands \0..\9 (groups; \0 = whole match) and \\ (a literal backslash).
|
||||
function rx_append(out: IVec, s: pointer, a: int, b: int) -> void {
|
||||
var i = a
|
||||
while i < b { iv_push(out, s[i] & 255); i = i + 1 }
|
||||
while i < b { iv_push(out, s[i] & 255); i += 1 }
|
||||
}
|
||||
function regex_replace(str: pointer, pattern: pointer, repl: pointer) -> pointer {
|
||||
let p = regex_compile(pattern)
|
||||
|
|
@ -186,16 +186,16 @@ function regex_replace(str: pointer, pattern: pointer, repl: pointer) -> pointer
|
|||
# expand replacement
|
||||
var i = 0
|
||||
while i < rn {
|
||||
if repl[i] == 92 and i + 1 < rn {
|
||||
if repl[i] == '\\' and i + 1 < rn {
|
||||
let d = repl[i + 1] & 255
|
||||
if d >= 48 and d <= 57 {
|
||||
if d >= '0' and d <= '9' {
|
||||
let g = d - 48
|
||||
if g <= p.ngroups { let a = caps[2 * g]; let b = caps[2 * g + 1]; if a >= 0 and b >= 0 { rx_append(out, str, a, b) } }
|
||||
i = i + 2
|
||||
} else if d == 92 { iv_push(out, 92); i = i + 2 }
|
||||
else { iv_push(out, d); i = i + 2 }
|
||||
i += 2
|
||||
} else if d == '\\' { iv_push(out, 92); i += 2 }
|
||||
else { iv_push(out, d); i += 2 }
|
||||
} else {
|
||||
iv_push(out, repl[i] & 255); i = i + 1
|
||||
iv_push(out, repl[i] & 255); i += 1
|
||||
}
|
||||
}
|
||||
prev = me
|
||||
|
|
@ -204,8 +204,7 @@ function regex_replace(str: pointer, pattern: pointer, repl: pointer) -> pointer
|
|||
rx_append(out, str, prev, n) # trailing text
|
||||
let res = bytes(out.n + 1)
|
||||
var i = 0
|
||||
while i < out.n { res[i] = out.d[i]; i = i + 1 }
|
||||
while i < out.n { res[i] = out.d[i]; i += 1 }
|
||||
res[out.n] = 0
|
||||
return res
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function anim_clip(name: pointer, frames: int, fps: int, mode: int) -> void {
|
|||
anim_clip_frames[i] = frames; anim_clip_fps[i] = fps; anim_clip_mode[i] = mode
|
||||
return
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
if anim_nclips >= ANIM_MAX_CLIPS { return } # silently ignore past capacity
|
||||
let s = anim_nclips
|
||||
|
|
@ -68,7 +68,7 @@ function anim_clip(name: pointer, frames: int, fps: int, mode: int) -> void {
|
|||
anim_clip_frames[s] = frames
|
||||
anim_clip_fps[s] = fps
|
||||
anim_clip_mode[s] = mode
|
||||
anim_nclips = anim_nclips + 1
|
||||
anim_nclips += 1
|
||||
}
|
||||
|
||||
function anim_clip_find(name: pointer) -> int {
|
||||
|
|
@ -76,9 +76,9 @@ function anim_clip_find(name: pointer) -> int {
|
|||
var i = 0
|
||||
while i < anim_nclips {
|
||||
if anim_clip_names[i] == name { return i }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# ---- Anim.play / Anim.on_frame / Anim.fired (#48) --------------------------
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ function esys_bounds() -> void {
|
|||
if y < by { y = by; hity = 1 }
|
||||
if y + h > y1 { y = y1 - h; hity = 1 }
|
||||
if pol == BND_BOUNCE {
|
||||
if (hitx == 1) and (f_vx >= 0) { World.set(e, PBody, f_vx, 0 - World.get(e, PBody, f_vx)) }
|
||||
if (hity == 1) and (f_vy >= 0) { World.set(e, PBody, f_vy, 0 - World.get(e, PBody, f_vy)) }
|
||||
if (hitx == 1) and (f_vx >= 0) { World.set(e, PBody, f_vx, -World.get(e, PBody, f_vx)) }
|
||||
if (hity == 1) and (f_vy >= 0) { World.set(e, PBody, f_vy, -World.get(e, PBody, f_vy)) }
|
||||
}
|
||||
}
|
||||
World.set(e, PP, fx, x)
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ function esys_light2d() -> void {
|
|||
light_set_soft(soft)
|
||||
if lgf >= 0 { light_set_gel(World.get(e, pl, lgf)) } else { light_clear_gel() }
|
||||
|
||||
var spread = 0 - 1
|
||||
var spread = -1
|
||||
if lsf >= 0 { spread = World.get(e, pl, lsf) }
|
||||
var direction = 0
|
||||
if ldf >= 0 { direction = World.get(e, pl, ldf) }
|
||||
|
|
|
|||
|
|
@ -60,18 +60,18 @@
|
|||
const PHYS_ONE: int = 65536 # Q16.16 one whole pixel
|
||||
|
||||
# ---- per-frame config + reflected ids (filled at the top of esys_move) -------
|
||||
var pm_pos: int = 0 - 1 # Position prop id
|
||||
var pm_pos_x: int = 0 - 1
|
||||
var pm_pos_y: int = 0 - 1
|
||||
var pm_col: int = 0 - 1 # Collider prop id
|
||||
var pm_c_w: int = 0 - 1
|
||||
var pm_c_h: int = 0 - 1
|
||||
var pm_c_offx: int = 0 - 1
|
||||
var pm_c_offy: int = 0 - 1
|
||||
var pm_c_trig: int = 0 - 1
|
||||
var pm_c_oneway: int = 0 - 1
|
||||
var pm_c_layer: int = 0 - 1
|
||||
var pm_c_mask: int = 0 - 1
|
||||
var pm_pos: int = -1 # Position prop id
|
||||
var pm_pos_x: int = -1
|
||||
var pm_pos_y: int = -1
|
||||
var pm_col: int = -1 # Collider prop id
|
||||
var pm_c_w: int = -1
|
||||
var pm_c_h: int = -1
|
||||
var pm_c_offx: int = -1
|
||||
var pm_c_offy: int = -1
|
||||
var pm_c_trig: int = -1
|
||||
var pm_c_oneway: int = -1
|
||||
var pm_c_layer: int = -1
|
||||
var pm_c_mask: int = -1
|
||||
var phys_ts: int = 0 # tile size px (0 = grid off)
|
||||
var phys_wall: int = 0 # solid glyph
|
||||
var phys_wall2: int = 0 # optional second solid glyph (Solids.solid2), e.g. a closed door
|
||||
|
|
@ -96,7 +96,7 @@ var phys_trig_prev: words = null
|
|||
function phys_floordiv(a: int, b: int) -> int {
|
||||
var q = a / b
|
||||
let r = a - q * b
|
||||
if (r != 0) and ((a < 0) != (b < 0)) { q = q - 1 }
|
||||
if (r != 0) and ((a < 0) != (b < 0)) { q -= 1 }
|
||||
return q
|
||||
}
|
||||
|
||||
|
|
@ -123,13 +123,13 @@ function phys_tile_oneway(c: int, r: int) -> bool {
|
|||
# is any full-solid tile present in column c over the row span [r0, r1]?
|
||||
function phys_col_solid(c: int, r0: int, r1: int) -> bool {
|
||||
var r = r0
|
||||
while r <= r1 { if phys_tile_solid(c, r) { return true }; r = r + 1 }
|
||||
while r <= r1 { if phys_tile_solid(c, r) { return true }; r += 1 }
|
||||
return false
|
||||
}
|
||||
# is any full-solid tile present in row r over the column span [c0, c1]?
|
||||
function phys_row_solid(r: int, c0: int, c1: int) -> bool {
|
||||
var c = c0
|
||||
while c <= c1 { if phys_tile_solid(c, r) { return true }; c = c + 1 }
|
||||
while c <= c1 { if phys_tile_solid(c, r) { return true }; c += 1 }
|
||||
return false
|
||||
}
|
||||
# is any full-OR-one-way tile present in row r over [c0, c1]? (downward landings)
|
||||
|
|
@ -138,7 +138,7 @@ function phys_row_land(r: int, c0: int, c1: int) -> bool {
|
|||
while c <= c1 {
|
||||
if phys_tile_solid(c, r) { return true }
|
||||
if phys_tile_oneway(c, r) { return true }
|
||||
c = c + 1
|
||||
c += 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -147,10 +147,10 @@ function phys_row_land(r: int, c0: int, c1: int) -> bool {
|
|||
# 0 mask reads as "all" (all-ones), so default-0 components still collide.
|
||||
function phys_match(la: int, ma: int, lb: int, mb: int) -> bool {
|
||||
var al = la; var bl = lb; var am = ma; var bm = mb
|
||||
if al == 0 { al = 0 - 1 }
|
||||
if bl == 0 { bl = 0 - 1 }
|
||||
if am == 0 { am = 0 - 1 }
|
||||
if bm == 0 { bm = 0 - 1 }
|
||||
if al == 0 { al = -1 }
|
||||
if bl == 0 { bl = -1 }
|
||||
if am == 0 { am = -1 }
|
||||
if bm == 0 { bm = -1 }
|
||||
if (am & bl) == 0 { return false }
|
||||
if (bm & al) == 0 { return false }
|
||||
return true
|
||||
|
|
@ -223,7 +223,7 @@ function phys_clamp_x(self_e: int, px: int, py: int, w: int, h: int, dx: int) ->
|
|||
let allow = c * ts - (px + w)
|
||||
if allow < best { best = allow }
|
||||
c = endc + 1 # nearest wins; stop
|
||||
} else { c = c + 1 }
|
||||
} else { c += 1 }
|
||||
}
|
||||
} else {
|
||||
let startc = phys_floordiv(px, ts)
|
||||
|
|
@ -234,7 +234,7 @@ function phys_clamp_x(self_e: int, px: int, py: int, w: int, h: int, dx: int) ->
|
|||
let allow = (c + 1) * ts - px
|
||||
if allow > best { best = allow }
|
||||
c = endc - 1 # nearest wins; stop
|
||||
} else { c = c - 1 }
|
||||
} else { c -= 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -305,7 +305,7 @@ function phys_clamp_y(self_e: int, px: int, py: int, w: int, h: int, dy: int) ->
|
|||
let allow = r * ts - (py + h)
|
||||
if allow < best { best = allow }
|
||||
r = endr + 1
|
||||
} else { r = r + 1 }
|
||||
} else { r += 1 }
|
||||
}
|
||||
} else {
|
||||
let startr = phys_floordiv(py, ts)
|
||||
|
|
@ -316,7 +316,7 @@ function phys_clamp_y(self_e: int, px: int, py: int, w: int, h: int, dy: int) ->
|
|||
let allow = (r + 1) * ts - py
|
||||
if allow > best { best = allow }
|
||||
r = endr - 1
|
||||
} else { r = r - 1 }
|
||||
} else { r -= 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -429,7 +429,7 @@ function esys_move() -> void {
|
|||
var vy = 0; if f_vy >= 0 { vy = World.get(e, pb, f_vy) }
|
||||
var policy = 0; if f_pol >= 0 { policy = World.get(e, pb, f_pol) }
|
||||
if policy != 1 {
|
||||
if f_grav >= 0 { vy = vy + World.get(e, pb, f_grav) }
|
||||
if f_grav >= 0 { vy += World.get(e, pb, f_grav) }
|
||||
if f_maxf >= 0 {
|
||||
let mf = World.get(e, pb, f_maxf)
|
||||
if (mf > 0) and (vy > mf) { vy = mf }
|
||||
|
|
@ -476,9 +476,9 @@ function esys_move() -> void {
|
|||
phys_set_y(e, phys_pos_y(e) + cdy)
|
||||
|
||||
# derived flags + contact normal
|
||||
if phys_hit_x == 1 { hit_wall = 1; vx = 0; if dx > 0 { nx = 0 - 1 } else { nx = 1 } }
|
||||
if phys_hit_x == 1 { hit_wall = 1; vx = 0; if dx > 0 { nx = -1 } else { nx = 1 } }
|
||||
if phys_hit_up == 1 { hit_ceiling = 1; vy = 0; ny = 1 }
|
||||
if phys_hit_down == 1 { vy = 0; ny = 0 - 1 }
|
||||
if phys_hit_down == 1 { vy = 0; ny = -1 }
|
||||
let gy = phys_aabb_y(e)
|
||||
if phys_grounded(e, px, gy, w, h) { on_ground = 1 }
|
||||
# a body pressed onto the ground carries no downward velocity, whatever
|
||||
|
|
@ -531,7 +531,7 @@ function esys_triggers() -> void {
|
|||
let tx = phys_aabb_x(t); let ty = phys_aabb_y(t)
|
||||
let tw = phys_c_int(t, pm_c_w); let th = phys_c_int(t, pm_c_h)
|
||||
let tl = phys_c_int(t, pm_c_layer); let tm = phys_c_int(t, pm_c_mask)
|
||||
var cur = 0 - 1
|
||||
var cur = -1
|
||||
var b = World.query_next(pm_col, 0)
|
||||
while b >= 0 {
|
||||
if b != t {
|
||||
|
|
|
|||
|
|
@ -57,17 +57,17 @@ function esys_sprite() -> void {
|
|||
let f_atlas = World.field_id(P, "atlas")
|
||||
|
||||
let SA = World.prop_id("SpriteAnim")
|
||||
var f_frame = 0 - 1
|
||||
var f_frame = -1
|
||||
if SA >= 0 { f_frame = World.field_id(SA, "frame") }
|
||||
let f_move = World.field_id(P, "move_id")
|
||||
let f_face = World.field_id(P, "face")
|
||||
let f_flash = World.field_id(P, "flash")
|
||||
let f_blink = World.field_id(P, "blink")
|
||||
let TD = World.prop_id("TopDown")
|
||||
var f_wx = 0 - 1; var f_wy = 0 - 1
|
||||
var f_wx = -1; var f_wy = -1
|
||||
if TD >= 0 { f_wx = World.field_id(TD, "want_x"); f_wy = World.field_id(TD, "want_y") }
|
||||
let PB = World.prop_id("Body")
|
||||
var f_vx = 0 - 1; var f_vy = 0 - 1
|
||||
var f_vx = -1; var f_vy = -1
|
||||
if PB >= 0 { f_vx = World.field_id(PB, "vx"); f_vy = World.field_id(PB, "vy") }
|
||||
|
||||
var e = World.query_next(P, 0)
|
||||
|
|
@ -94,12 +94,12 @@ function esys_sprite() -> void {
|
|||
}
|
||||
# add the current animation frame when the entity also carries SpriteAnim.
|
||||
if (SA >= 0) and (f_frame >= 0) {
|
||||
if World.has(e, SA) != 0 { id = id + World.get(e, SA, f_frame) }
|
||||
if World.has(e, SA) != 0 { id += World.get(e, SA, f_frame) }
|
||||
}
|
||||
var x = spr_pos(e, 0)
|
||||
var y = spr_pos(e, 1)
|
||||
if f_offx >= 0 { x = x + World.get(e, P, f_offx) }
|
||||
if f_offy >= 0 { y = y + World.get(e, P, f_offy) }
|
||||
if f_offx >= 0 { x += World.get(e, P, f_offx) }
|
||||
if f_offy >= 0 { y += World.get(e, P, f_offy) }
|
||||
var sc = 1
|
||||
if f_scale >= 0 { let sv = World.get(e, P, f_scale); if sv > 1 { sc = sv } }
|
||||
var flip = 0
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ function esys_tileskin() -> void {
|
|||
if is_atlas != 0 { atlas_draw_ex(sprite, tx * size, ty * size, sc, 0, 0) }
|
||||
else { rt_draw_sprite_ex(sprite, tx * size, ty * size, sc, 0, 0) }
|
||||
}
|
||||
tx = tx + 1
|
||||
tx += 1
|
||||
}
|
||||
ty = ty + 1
|
||||
ty += 1
|
||||
}
|
||||
e = World.query_next(P, e + 1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ function tiled_csv_list(text: pointer) -> Val {
|
|||
var have = 0
|
||||
while i < n {
|
||||
let c = text[i]
|
||||
if c >= 48 and c <= 57 { cur = cur * 10 + (c - 48); have = 1 }
|
||||
if c >= '0' and c <= '9' { cur = cur * 10 + (c - 48); have = 1 }
|
||||
else {
|
||||
if c == 44 or c == 32 or c == 9 or c == 10 or c == 13 {
|
||||
if c == ',' or c == ' ' or c == '\t' or c == '\n' or c == '\r' {
|
||||
if have == 1 { push(out.kids, value_int(cur)); cur = 0; have = 0 }
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
if have == 1 { push(out.kids, value_int(cur)) }
|
||||
return out
|
||||
|
|
@ -59,7 +59,7 @@ function tiled_b64_list(text: pointer, compression: pointer, count: int) -> Val
|
|||
while i + 3 < rawlen {
|
||||
let g = raw[i] | (raw[i + 1] << 8) | (raw[i + 2] << 16) | (raw[i + 3] << 24)
|
||||
push(out.kids, value_int(g))
|
||||
i = i + 4
|
||||
i += 4
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
@ -83,8 +83,8 @@ function tiled_chunked_layer(data: Xml, o: Val) -> void {
|
|||
# pass 1: bounds over every chunk (tile coordinates)
|
||||
var minx = 1000000000
|
||||
var miny = 1000000000
|
||||
var maxx = 0 - 1000000000
|
||||
var maxy = 0 - 1000000000
|
||||
var maxx = -1000000000
|
||||
var maxy = -1000000000
|
||||
var i = 0
|
||||
while i < xml_child_count(data) {
|
||||
let ch = xml_child(data, i)
|
||||
|
|
@ -96,13 +96,13 @@ function tiled_chunked_layer(data: Xml, o: Val) -> void {
|
|||
if cx + xml_attr_int(ch, "width", 0) > maxx { maxx = cx + xml_attr_int(ch, "width", 0) }
|
||||
if cy + xml_attr_int(ch, "height", 0) > maxy { maxy = cy + xml_attr_int(ch, "height", 0) }
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
let W = maxx - minx
|
||||
let H = maxy - miny
|
||||
let gids = value_list()
|
||||
var k = 0
|
||||
while k < W * H { push(gids.kids, value_int(0)); k = k + 1 }
|
||||
while k < W * H { push(gids.kids, value_int(0)); k += 1 }
|
||||
# pass 2: place each chunk's decoded data at its offset
|
||||
i = 0
|
||||
while i < xml_child_count(data) {
|
||||
|
|
@ -118,12 +118,12 @@ function tiled_chunked_layer(data: Xml, o: Val) -> void {
|
|||
var xx = 0
|
||||
while xx < cw {
|
||||
gids.kids[(cy + yy) * W + (cx + xx)] = value_at(cdata, yy * cw + xx)
|
||||
xx = xx + 1
|
||||
xx += 1
|
||||
}
|
||||
yy = yy + 1
|
||||
yy += 1
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
value_put(o, "width", value_int(W))
|
||||
value_put(o, "height", value_int(H))
|
||||
|
|
@ -152,7 +152,7 @@ function tmx_props_list(parent: Xml) -> Val {
|
|||
value_put(o, "value", value_str(v))
|
||||
push(out.kids, o)
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
@ -201,18 +201,18 @@ function tmx_points_list(s: pointer) -> Val {
|
|||
let n = len(s)
|
||||
var i = 0
|
||||
while i < n {
|
||||
while i < n and (s[i] == 32 or s[i] == 9) { i = i + 1 }
|
||||
while i < n and (s[i] == ' ' or s[i] == '\t') { i += 1 }
|
||||
if i >= n { break }
|
||||
# read "x,y"
|
||||
var xv = 0; var xn = 0; var xs = 0
|
||||
if s[i] == 45 { xs = 1; i = i + 1 }
|
||||
while i < n and s[i] >= 48 and s[i] <= 57 { xv = xv * 10 + (s[i] - 48); xn = 1; i = i + 1 }
|
||||
if xs == 1 { xv = 0 - xv }
|
||||
if i < n and s[i] == 44 { i = i + 1 }
|
||||
if s[i] == '-' { xs = 1; i += 1 }
|
||||
while i < n and s[i] >= '0' and s[i] <= '9' { xv = xv * 10 + (s[i] - 48); xn = 1; i += 1 }
|
||||
if xs == 1 { xv = -xv }
|
||||
if i < n and s[i] == ',' { i += 1 }
|
||||
var yv = 0; var ys = 0
|
||||
if i < n and s[i] == 45 { ys = 1; i = i + 1 }
|
||||
while i < n and s[i] >= 48 and s[i] <= 57 { yv = yv * 10 + (s[i] - 48); i = i + 1 }
|
||||
if ys == 1 { yv = 0 - yv }
|
||||
if i < n and s[i] == '-' { ys = 1; i += 1 }
|
||||
while i < n and s[i] >= '0' and s[i] <= '9' { yv = yv * 10 + (s[i] - 48); i += 1 }
|
||||
if ys == 1 { yv = -yv }
|
||||
if xn == 1 {
|
||||
let o = value_object()
|
||||
value_put(o, "x", value_int(xv))
|
||||
|
|
@ -252,7 +252,7 @@ function tmx_tile_to_value(t: Xml) -> Val {
|
|||
value_put(f, "duration", value_int(xml_attr_int(fr, "duration", 0)))
|
||||
push(frames.kids, f)
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
value_put(o, "animation", frames)
|
||||
}
|
||||
|
|
@ -264,7 +264,7 @@ function tmx_tile_to_value(t: Xml) -> Val {
|
|||
while j < xml_child_count(og) {
|
||||
let ch = xml_child(og, j)
|
||||
if xml_tag(ch) == "object" { push(objs.kids, tmx_object_to_value(ch)) }
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
let ogo = value_object()
|
||||
value_put(ogo, "objects", objs)
|
||||
|
|
@ -296,7 +296,7 @@ function tmx_fill_tileset(o: Val, ts: Xml) -> void {
|
|||
while i < xml_child_count(ts) {
|
||||
let ch = xml_child(ts, i)
|
||||
if xml_tag(ch) == "tile" { push(tiles.kids, tmx_tile_to_value(ch)) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
if len(tiles.kids) > 0 { value_put(o, "tiles", tiles) }
|
||||
}
|
||||
|
|
@ -366,7 +366,7 @@ function tmx_objectlayer_to_value(el: Xml) -> Val {
|
|||
while i < xml_child_count(el) {
|
||||
let ch = xml_child(el, i)
|
||||
if xml_tag(ch) == "object" { push(objs.kids, tmx_object_to_value(ch)) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
value_put(o, "objects", objs)
|
||||
return o
|
||||
|
|
@ -402,7 +402,7 @@ function tmx_to_value(root: Xml) -> Val {
|
|||
else { if tag == "objectgroup" { push(layers.kids, tmx_objectlayer_to_value(ch)) }
|
||||
else { if tag == "imagelayer" { push(layers.kids, tmx_imagelayer_to_value(ch)) }
|
||||
else { if tag == "group" { push(layers.kids, tmx_group_to_value(ch, mapw, maph)) } } } } }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
let props = tmx_props_list(root)
|
||||
if len(props.kids) > 0 { value_put(m, "properties", props) }
|
||||
|
|
@ -437,7 +437,7 @@ function tmx_group_to_value(el: Xml, mapw: int, maph: int) -> Val {
|
|||
else { if tag == "objectgroup" { push(layers.kids, tmx_objectlayer_to_value(ch)) }
|
||||
else { if tag == "imagelayer" { push(layers.kids, tmx_imagelayer_to_value(ch)) }
|
||||
else { if tag == "group" { push(layers.kids, tmx_group_to_value(ch, mapw, maph)) } } } }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
value_put(o, "layers", layers)
|
||||
return o
|
||||
|
|
@ -453,7 +453,7 @@ function tmj_normalize_layer(layer: Val) -> void {
|
|||
if ty == "group" {
|
||||
let ls = value_get(layer, "layers")
|
||||
var i = 0
|
||||
while i < value_count(ls) { tmj_normalize_layer(value_at(ls, i)); i = i + 1 }
|
||||
while i < value_count(ls) { tmj_normalize_layer(value_at(ls, i)); i += 1 }
|
||||
return
|
||||
}
|
||||
if ty != "tilelayer" { return }
|
||||
|
|
@ -484,8 +484,8 @@ function tmj_chunk_gids(chunk: Val, enc: pointer, comp: pointer, count: int) ->
|
|||
function tmj_flatten_chunks(layer: Val, chunks: Val, enc: pointer, comp: pointer) -> void {
|
||||
var minx = 1000000000
|
||||
var miny = 1000000000
|
||||
var maxx = 0 - 1000000000
|
||||
var maxy = 0 - 1000000000
|
||||
var maxx = -1000000000
|
||||
var maxy = -1000000000
|
||||
var i = 0
|
||||
while i < value_count(chunks) {
|
||||
let c = value_at(chunks, i)
|
||||
|
|
@ -495,13 +495,13 @@ function tmj_flatten_chunks(layer: Val, chunks: Val, enc: pointer, comp: pointer
|
|||
if cy < miny { miny = cy }
|
||||
if cx + value_as_int(value_get(c, "width")) > maxx { maxx = cx + value_as_int(value_get(c, "width")) }
|
||||
if cy + value_as_int(value_get(c, "height")) > maxy { maxy = cy + value_as_int(value_get(c, "height")) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
let W = maxx - minx
|
||||
let H = maxy - miny
|
||||
let gids = value_list()
|
||||
var k = 0
|
||||
while k < W * H { push(gids.kids, value_int(0)); k = k + 1 }
|
||||
while k < W * H { push(gids.kids, value_int(0)); k += 1 }
|
||||
i = 0
|
||||
while i < value_count(chunks) {
|
||||
let c = value_at(chunks, i)
|
||||
|
|
@ -515,11 +515,11 @@ function tmj_flatten_chunks(layer: Val, chunks: Val, enc: pointer, comp: pointer
|
|||
var xx = 0
|
||||
while xx < cw {
|
||||
gids.kids[(cy + yy) * W + (cx + xx)] = value_at(cdata, yy * cw + xx)
|
||||
xx = xx + 1
|
||||
xx += 1
|
||||
}
|
||||
yy = yy + 1
|
||||
yy += 1
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
value_put(layer, "width", value_int(W))
|
||||
value_put(layer, "height", value_int(H))
|
||||
|
|
@ -529,7 +529,7 @@ function tmj_flatten_chunks(layer: Val, chunks: Val, enc: pointer, comp: pointer
|
|||
function tmj_normalize(m: Val) -> Val {
|
||||
let ls = value_get(m, "layers")
|
||||
var i = 0
|
||||
while i < value_count(ls) { tmj_normalize_layer(value_at(ls, i)); i = i + 1 }
|
||||
while i < value_count(ls) { tmj_normalize_layer(value_at(ls, i)); i += 1 }
|
||||
return m
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +540,7 @@ function tiled_first_byte(s: pointer) -> int {
|
|||
let n = len(s)
|
||||
while i < n {
|
||||
let c = s[i]
|
||||
if c == 32 or c == 9 or c == 10 or c == 13 { i = i + 1 } else { return c }
|
||||
if c == ' ' or c == '\t' or c == '\n' or c == '\r' { i += 1 } else { return c }
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -580,7 +580,7 @@ property TmTileset {
|
|||
spacing: int = 0
|
||||
margin: int = 0
|
||||
tilecount: int = 0
|
||||
imgid: int = 0 - 1 # loaded image handle (rt_image_load), -1 = none
|
||||
imgid: int = -1 # loaded image handle (rt_image_load), -1 = none
|
||||
meta: Val # the tileset Value object (per-tile metadata)
|
||||
}
|
||||
|
||||
|
|
@ -590,7 +590,7 @@ property TmLayer {
|
|||
w: int = 0
|
||||
h: int = 0
|
||||
visible: int = 1
|
||||
imgid: int = 0 - 1 # loaded image handle (imagelayer only), -1 = none
|
||||
imgid: int = -1 # loaded image handle (imagelayer only), -1 = none
|
||||
gids: []int # dense w*h GID array (tilelayer only)
|
||||
data: Val # the layer Value object (objects, image, …)
|
||||
}
|
||||
|
|
@ -604,12 +604,12 @@ property Tmap {
|
|||
layers: []TmLayer
|
||||
tilesets: []TmTileset
|
||||
tree: Val # the source intermediate tree
|
||||
coll: int = 0 - 1 # designated collision layer index, or -1
|
||||
coll: int = -1 # designated collision layer index, or -1
|
||||
}
|
||||
|
||||
# ---- GID resolver ----------------------------------------------------------
|
||||
property GidInfo {
|
||||
tileset: int = 0 - 1 # index into Tmap.tilesets (-1 = none/empty)
|
||||
tileset: int = -1 # index into Tmap.tilesets (-1 = none/empty)
|
||||
local: int = 0 # local tile id within that tileset
|
||||
fh: int = 0 # horizontal flip
|
||||
fv: int = 0 # vertical flip
|
||||
|
|
@ -622,7 +622,7 @@ property GidInfo {
|
|||
# whose firstgid is the greatest not exceeding it. gid == 0 is the empty cell.
|
||||
function tmap_resolve(m: Tmap, gid: int) -> GidInfo {
|
||||
let r = new GidInfo
|
||||
if gid == 0 { r.empty = 1; r.tileset = 0 - 1; return r }
|
||||
if gid == 0 { r.empty = 1; r.tileset = -1; return r }
|
||||
let H = 1 << 31
|
||||
let V = 1 << 30
|
||||
let D = 1 << 29
|
||||
|
|
@ -630,13 +630,13 @@ function tmap_resolve(m: Tmap, gid: int) -> GidInfo {
|
|||
if (gid & V) != 0 { r.fv = 1 }
|
||||
if (gid & D) != 0 { r.fd = 1 }
|
||||
let id = gid & 536870911 # low 29 bits = global tile id
|
||||
var best = 0 - 1
|
||||
var best = -1
|
||||
var bestfg = 0
|
||||
var i = 0
|
||||
while i < len(m.tilesets) {
|
||||
let fg = m.tilesets[i].firstgid
|
||||
if fg <= id and fg >= bestfg { bestfg = fg; best = i }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
r.tileset = best
|
||||
if best >= 0 { r.local = id - m.tilesets[best].firstgid }
|
||||
|
|
@ -678,7 +678,7 @@ function tmap_tile_meta(m: Tmap, gid: int) -> Val {
|
|||
while i < value_count(tiles) {
|
||||
let t = value_at(tiles, i)
|
||||
if value_as_int(value_get(t, "id")) == r.local { return t }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return value_null()
|
||||
}
|
||||
|
|
@ -696,7 +696,7 @@ function tmap_tile_prop(m: Tmap, gid: int, name: pointer) -> int {
|
|||
if value_as_str(value_get(p, "value")) == "true" { return 1 }
|
||||
return 0
|
||||
}
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -750,14 +750,14 @@ function tmap_project_layer(m: Tmap, layer: int, whole_layer_solid: int) -> void
|
|||
if gid != 0 {
|
||||
var k = tmap_collision_kind(m, gid)
|
||||
if k == 0 and whole_layer_solid != 0 { k = 1 } # collision-layer fallback
|
||||
if k == 1 { rt_map[y * 96 + x] = 35 } # '#'
|
||||
if k == 2 { rt_map[y * 96 + x] = 61 } # '='
|
||||
if k == 1 { rt_map[y * 96 + x] = '#' } # '#'
|
||||
if k == 2 { rt_map[y * 96 + x] = '=' } # '='
|
||||
}
|
||||
}
|
||||
x = x + 1
|
||||
x += 1
|
||||
}
|
||||
}
|
||||
y = y + 1
|
||||
y += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -775,9 +775,9 @@ function tmap_find_collision(m: Tmap) -> int {
|
|||
while i < len(m.layers) {
|
||||
let n = m.layers[i].name
|
||||
if m.layers[i].kind == 0 and (n == "collision" or n == "solids" or n == "walls" or n == "Collision" or n == "Solids") { return i }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# ---- rendering -------------------------------------------------------------
|
||||
|
|
@ -799,9 +799,9 @@ function tmap_blit_tile(imgid: int, sx: int, sy: int, tw: int, th: int, dx: int,
|
|||
if fv == 1 { v = th - 1 - v }
|
||||
let argb = s[(sy + v) * iw + (sx + u)]
|
||||
rt_blend_px(dx + i, dy + j, argb)
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -832,7 +832,7 @@ function tmap_gids_from_layer(lv: Val) -> []int {
|
|||
let out = new []int
|
||||
let data = value_get(lv, "data")
|
||||
var i = 0
|
||||
while i < value_count(data) { push(out, value_as_int(value_at(data, i))); i = i + 1 }
|
||||
while i < value_count(data) { push(out, value_as_int(value_at(data, i))); i += 1 }
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
@ -887,12 +887,12 @@ function tmap_build(tree: Val, basedir: pointer) -> Tmap {
|
|||
let img = value_as_str(value_get(tv, "image"))
|
||||
if img != "" { ts.imgid = rt_image_load(tiled_join(imgdir, img)) }
|
||||
push(m.tilesets, ts)
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
# layers (flat; groups' children are lifted so tile layers render/resolve)
|
||||
let ls = value_get(tree, "layers")
|
||||
i = 0
|
||||
while i < value_count(ls) { tmap_add_layer(m, value_at(ls, i)); i = i + 1 }
|
||||
while i < value_count(ls) { tmap_add_layer(m, value_at(ls, i)); i += 1 }
|
||||
# image layers (#73): load each <imagelayer> image relative to the map file
|
||||
i = 0
|
||||
while i < len(m.layers) {
|
||||
|
|
@ -900,7 +900,7 @@ function tmap_build(tree: Val, basedir: pointer) -> Tmap {
|
|||
let img = value_as_str(value_get(m.layers[i].data, "image"))
|
||||
if img != "" { m.layers[i].imgid = rt_image_load(tiled_join(basedir, img)) }
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
# infinite map (#74): the header w/h are 0 — take the flattened layer bounds.
|
||||
if m.w <= 0 or m.h <= 0 {
|
||||
|
|
@ -912,7 +912,7 @@ function tmap_build(tree: Val, basedir: pointer) -> Tmap {
|
|||
if m.layers[i].w > mw { mw = m.layers[i].w }
|
||||
if m.layers[i].h > mh { mh = m.layers[i].h }
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
m.w = mw
|
||||
m.h = mh
|
||||
|
|
@ -954,7 +954,7 @@ function tmap_add_layer(m: Tmap, lv: Val) -> void {
|
|||
l.kind = 3; push(m.layers, l)
|
||||
let sub = value_get(lv, "layers")
|
||||
var i = 0
|
||||
while i < value_count(sub) { tmap_add_layer(m, value_at(sub, i)); i = i + 1 }
|
||||
while i < value_count(sub) { tmap_add_layer(m, value_at(sub, i)); i += 1 }
|
||||
return
|
||||
}
|
||||
push(m.layers, l)
|
||||
|
|
@ -1005,7 +1005,7 @@ function tmap_frame_gid(m: Tmap, gid: int, frame: int) -> int {
|
|||
if nfr == 0 { return gid }
|
||||
var total = 0
|
||||
var i = 0
|
||||
while i < nfr { total = total + value_as_int(value_get(value_at(anim, i), "duration")); i = i + 1 }
|
||||
while i < nfr { total = total + value_as_int(value_get(value_at(anim, i), "duration")); i += 1 }
|
||||
if total <= 0 { return gid }
|
||||
let t_ms = (frame * 1000 / 60) % total
|
||||
var cur = value_as_int(value_get(value_at(anim, 0), "tileid"))
|
||||
|
|
@ -1015,7 +1015,7 @@ function tmap_frame_gid(m: Tmap, gid: int, frame: int) -> int {
|
|||
let fr = value_at(anim, i)
|
||||
acc = acc + value_as_int(value_get(fr, "duration"))
|
||||
if t_ms < acc { cur = value_as_int(value_get(fr, "tileid")); i = nfr }
|
||||
else { i = i + 1 }
|
||||
else { i += 1 }
|
||||
}
|
||||
let ts = m.tilesets[r.tileset]
|
||||
return (ts.firstgid + cur) | tmap_flag_bits(gid)
|
||||
|
|
@ -1049,9 +1049,9 @@ function tmap_draw_full(m: Tmap, camx: int, camy: int, frame: int, animate: int)
|
|||
# orientation transform places the cell (orthogonal / iso / hex / staggered)
|
||||
tmap_draw_gid(m, gid, tmap_cell_sx(m, x, y) + lox - camx, tmap_cell_sy(m, x, y) + loy - camy)
|
||||
}
|
||||
x = x + 1
|
||||
x += 1
|
||||
}
|
||||
y = y + 1
|
||||
y += 1
|
||||
}
|
||||
}
|
||||
if l.kind == 2 and l.visible != 0 { # image layer (parallax / repeat)
|
||||
|
|
@ -1070,10 +1070,10 @@ function tmap_draw_full(m: Tmap, camx: int, camy: int, frame: int, animate: int)
|
|||
# Tiled anchors a tile object by its bottom-left corner
|
||||
tmap_draw_gid(m, g, ox - camx, oy - m.tileh - camy)
|
||||
}
|
||||
oi = oi + 1
|
||||
oi += 1
|
||||
}
|
||||
}
|
||||
li = li + 1
|
||||
li += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1125,7 +1125,7 @@ function tiled_prop_node(container: Val, name: pointer) -> Val {
|
|||
while i < value_count(props) {
|
||||
let p = value_at(props, i)
|
||||
if value_as_str(value_get(p, "name")) == name { return p }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return value_null()
|
||||
}
|
||||
|
|
@ -1201,12 +1201,12 @@ function tiled_load_types(path: pointer) -> int {
|
|||
value_put(o, "value", value_str(xml_attr(pr, "default")))
|
||||
push(props.kids, o)
|
||||
}
|
||||
j = j + 1
|
||||
j += 1
|
||||
}
|
||||
value_put(tbl, xml_attr(ot, "name"), props)
|
||||
n = n + 1
|
||||
n += 1
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
|
@ -1220,7 +1220,7 @@ function tiled_type_default(typename: pointer, propname: pointer) -> Val {
|
|||
while i < value_count(props) {
|
||||
let p = value_at(props, i)
|
||||
if value_as_str(value_get(p, "name")) == propname { return p }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return value_null()
|
||||
}
|
||||
|
|
@ -1251,7 +1251,7 @@ function tiled_merge_template(inst: Val, tmpl: Val) -> void {
|
|||
while i < value_count(tmpl) {
|
||||
let k = value_key_at(tmpl, i)
|
||||
if value_has(inst, k) == 0 { value_put(inst, k, value_at(tmpl, i)) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1268,10 +1268,10 @@ function tmap_resolve_templates(m: Tmap, basedir: pointer) -> void {
|
|||
let ob = value_at(objs, oi)
|
||||
let tp = value_as_str(value_get(ob, "template"))
|
||||
if tp != "" { tiled_merge_template(ob, tiled_read_template(tiled_join(basedir, tp))) }
|
||||
oi = oi + 1
|
||||
oi += 1
|
||||
}
|
||||
}
|
||||
li = li + 1
|
||||
li += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1330,9 +1330,9 @@ function tmap_draw_imagelayer(m: Tmap, l: TmLayer, camx: int, camy: int) -> void
|
|||
let repy = value_as_int(value_get(l.data, "repeaty"))
|
||||
# starting origin: for a repeating axis, back up to before the screen
|
||||
var sx0 = px
|
||||
if repx != 0 { while sx0 > 0 { sx0 = sx0 - iw }; }
|
||||
if repx != 0 { while sx0 > 0 { sx0 -= iw }; }
|
||||
var sy0 = py
|
||||
if repy != 0 { while sy0 > 0 { sy0 = sy0 - ih }; }
|
||||
if repy != 0 { while sy0 > 0 { sy0 -= ih }; }
|
||||
var yy = sy0
|
||||
var first_y = 1
|
||||
while (yy < rt_screen_h()) and (first_y == 1 or repy != 0) {
|
||||
|
|
@ -1341,16 +1341,16 @@ function tmap_draw_imagelayer(m: Tmap, l: TmLayer, camx: int, camy: int) -> void
|
|||
while (xx < rt_screen_w()) and (first_x == 1 or repx != 0) {
|
||||
rt_draw_image(l.imgid, xx, yy)
|
||||
first_x = 0
|
||||
if repx == 0 { xx = rt_screen_w() } else { xx = xx + iw }
|
||||
if repx == 0 { xx = rt_screen_w() } else { xx += iw }
|
||||
}
|
||||
first_y = 0
|
||||
if repy == 0 { yy = rt_screen_h() } else { yy = yy + ih }
|
||||
if repy == 0 { yy = rt_screen_h() } else { yy += ih }
|
||||
}
|
||||
}
|
||||
|
||||
# ---- image/group-layer accessors -------------------------------------------
|
||||
function tmap_layer_kind(m: Tmap, layer: int) -> int {
|
||||
if layer < 0 or layer >= len(m.layers) { return 0 - 1 }
|
||||
if layer < 0 or layer >= len(m.layers) { return -1 }
|
||||
return m.layers[layer].kind
|
||||
}
|
||||
function tmap_layer_opacity(m: Tmap, layer: int) -> pointer {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ function tiled_apply_field(e: int, fname: pointer, v: int) -> void {
|
|||
let fid = world_field_id(pi, fname)
|
||||
if fid >= 0 { world_set(e, pi, fid, v) }
|
||||
}
|
||||
pi = pi + 1
|
||||
pi += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ function tiled_apply_field(e: int, fname: pointer, v: int) -> void {
|
|||
# unknown. Opt-in — the core load never calls this.
|
||||
function tiled_spawn_object(m: Tmap, obj: Val, model_name: pointer) -> int {
|
||||
let mid = world_model_id(model_name)
|
||||
if mid < 0 { return 0 - 1 }
|
||||
if mid < 0 { return -1 }
|
||||
let e = world_spawn(mid)
|
||||
let pp = world_prop_id("Position")
|
||||
if pp >= 0 and world_has(e, pp) == 1 {
|
||||
|
|
@ -40,7 +40,7 @@ function tiled_spawn_object(m: Tmap, obj: Val, model_name: pointer) -> int {
|
|||
while i < value_count(props) {
|
||||
let p = value_at(props, i)
|
||||
tiled_apply_field(e, value_as_str(value_get(p, "name")), tiled_prop_int(obj, value_as_str(value_get(p, "name"))))
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
|
@ -50,6 +50,6 @@ function tiled_spawn_layer(m: Tmap, layer: int, model_name: pointer) -> int {
|
|||
var n = 0
|
||||
let c = tmap_object_count(m, layer)
|
||||
var i = 0
|
||||
while i < c { if tiled_spawn_object(m, tmap_object(m, layer, i), model_name) >= 0 { n = n + 1 }; i = i + 1 }
|
||||
while i < c { if tiled_spawn_object(m, tmap_object(m, layer, i), model_name) >= 0 { n += 1 }; i += 1 }
|
||||
return n
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,23 +134,23 @@ function tt_find_table(d: pointer, base: int, a: int, b: int, c: int, e: int) ->
|
|||
}
|
||||
}
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# pick the most capable Unicode subtable, as the C loader did
|
||||
function tt_pick_cmap(id: int, d: pointer, co: int) -> void {
|
||||
tt_cmap[id] = 0 - 1
|
||||
tt_cmap[id] = -1
|
||||
tt_cfmt[id] = 0
|
||||
if co < 0 { return }
|
||||
let n = tt_u16(d, co + 2)
|
||||
var best = 0 - 1
|
||||
var bestscore = 0 - 1
|
||||
var best = -1
|
||||
var bestscore = -1
|
||||
for i in 0 .. n {
|
||||
let rec = co + 4 + i * 8
|
||||
let plat = tt_u16(d, rec)
|
||||
let enc = tt_u16(d, rec + 2)
|
||||
let off = tt_u32(d, rec + 4)
|
||||
var score = 0 - 1
|
||||
var score = -1
|
||||
if plat == 0 { score = 2 }
|
||||
if plat == 0 { if enc == 4 { score = 4 } }
|
||||
if plat == 0 { if enc == 6 { score = 4 } }
|
||||
|
|
@ -167,14 +167,14 @@ function tt_pick_cmap(id: int, d: pointer, co: int) -> void {
|
|||
}
|
||||
|
||||
function rt_font_load(path: string) -> int {
|
||||
if tt_n >= TT_MAX { return 0 - 1 }
|
||||
if tt_n >= TT_MAX { return -1 }
|
||||
let d = rt_read_file(path)
|
||||
if (d == null) { return 0 - 1 }
|
||||
if (d == null) { return -1 }
|
||||
let size = rt_file_len
|
||||
var base = 0
|
||||
# a .ttc collection points at its first font
|
||||
if size >= 16 {
|
||||
if d[0] == 116 { if d[1] == 116 { if d[2] == 99 { if d[3] == 102 {
|
||||
if d[0] == 't' { if d[1] == 't' { if d[2] == 'c' { if d[3] == 'f' {
|
||||
base = tt_u32(d, 12)
|
||||
} } } }
|
||||
}
|
||||
|
|
@ -184,15 +184,15 @@ function rt_font_load(path: string) -> int {
|
|||
let loca = tt_find_table(d, base, 108, 111, 99, 97)
|
||||
let glyf = tt_find_table(d, base, 103, 108, 121, 102)
|
||||
let hmtx = tt_find_table(d, base, 104, 109, 116, 120)
|
||||
if head < 0 { return 0 - 1 }
|
||||
if maxp < 0 { return 0 - 1 }
|
||||
if hhea < 0 { return 0 - 1 }
|
||||
if loca < 0 { return 0 - 1 }
|
||||
if glyf < 0 { return 0 - 1 }
|
||||
if hmtx < 0 { return 0 - 1 }
|
||||
if head < 0 { return -1 }
|
||||
if maxp < 0 { return -1 }
|
||||
if hhea < 0 { return -1 }
|
||||
if loca < 0 { return -1 }
|
||||
if glyf < 0 { return -1 }
|
||||
if hmtx < 0 { return -1 }
|
||||
|
||||
let id = tt_n
|
||||
tt_n = tt_n + 1
|
||||
tt_n += 1
|
||||
tt_data[id] = d
|
||||
tt_size[id] = size
|
||||
var upem = tt_u16(d, head + 18)
|
||||
|
|
@ -275,7 +275,7 @@ function ol_pt(x: fixed, y: fixed, on: int) -> void {
|
|||
ol_x[ol_n] = x
|
||||
ol_y[ol_n] = y
|
||||
ol_on[ol_n] = on
|
||||
ol_n = ol_n + 1
|
||||
ol_n += 1
|
||||
}
|
||||
|
||||
function tt_glyph_start(id: int, gid: int) -> int {
|
||||
|
|
@ -314,15 +314,15 @@ function tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fix
|
|||
var i = 0
|
||||
while i < npts {
|
||||
let fl = d[p]
|
||||
p = p + 1
|
||||
p += 1
|
||||
flags[i] = fl
|
||||
i = i + 1
|
||||
i += 1
|
||||
if (fl & 8) != 0 { # REPEAT
|
||||
var r = d[p]
|
||||
p = p + 1
|
||||
p += 1
|
||||
while r > 0 {
|
||||
if i < npts { flags[i] = fl; i = i + 1 }
|
||||
r = r - 1
|
||||
if i < npts { flags[i] = fl; i += 1 }
|
||||
r -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -334,10 +334,10 @@ function tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fix
|
|||
let fl = flags[k]
|
||||
if (fl & 2) != 0 {
|
||||
let dxv = d[p]
|
||||
p = p + 1
|
||||
if (fl & 16) != 0 { xv = xv + dxv } else { xv = xv - dxv }
|
||||
p += 1
|
||||
if (fl & 16) != 0 { xv += dxv } else { xv -= dxv }
|
||||
} else {
|
||||
if (fl & 16) == 0 { xv = xv + tt_i16(d, p); p = p + 2 }
|
||||
if (fl & 16) == 0 { xv += tt_i16(d, p); p += 2 }
|
||||
}
|
||||
xs[k] = xv
|
||||
}
|
||||
|
|
@ -346,10 +346,10 @@ function tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fix
|
|||
let fl = flags[k]
|
||||
if (fl & 4) != 0 {
|
||||
let dyv = d[p]
|
||||
p = p + 1
|
||||
if (fl & 32) != 0 { yv = yv + dyv } else { yv = yv - dyv }
|
||||
p += 1
|
||||
if (fl & 32) != 0 { yv += dyv } else { yv -= dyv }
|
||||
} else {
|
||||
if (fl & 32) == 0 { yv = yv + tt_i16(d, p); p = p + 2 }
|
||||
if (fl & 32) == 0 { yv += tt_i16(d, p); p += 2 }
|
||||
}
|
||||
ys[k] = yv
|
||||
}
|
||||
|
|
@ -364,7 +364,7 @@ function tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fix
|
|||
}
|
||||
if ol_ne < 256 {
|
||||
ol_ends[ol_ne] = ol_n
|
||||
ol_ne = ol_ne + 1
|
||||
ol_ne += 1
|
||||
}
|
||||
start = last + 1
|
||||
}
|
||||
|
|
@ -378,17 +378,17 @@ function tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fix
|
|||
while more == 1 {
|
||||
let flags = tt_u16(d, p)
|
||||
let cgid = tt_u16(d, p + 2)
|
||||
p = p + 4
|
||||
p += 4
|
||||
var arg1 = 0
|
||||
var arg2 = 0
|
||||
if (flags & 1) != 0 {
|
||||
arg1 = tt_i16(d, p)
|
||||
arg2 = tt_i16(d, p + 2)
|
||||
p = p + 4
|
||||
p += 4
|
||||
} else {
|
||||
arg1 = tt_i8(d, p)
|
||||
arg2 = tt_i8(d, p + 1)
|
||||
p = p + 2
|
||||
p += 2
|
||||
}
|
||||
var ca = 1.0
|
||||
var cb = 0.0
|
||||
|
|
@ -397,19 +397,19 @@ function tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fix
|
|||
if (flags & 8) != 0 {
|
||||
ca = as_fixed((tt_i16(d, p) << 2)) # F2Dot14 -> Q16.16
|
||||
ce = ca
|
||||
p = p + 2
|
||||
p += 2
|
||||
}
|
||||
if (flags & 64) != 0 {
|
||||
ca = as_fixed((tt_i16(d, p) << 2))
|
||||
ce = as_fixed((tt_i16(d, p + 2) << 2))
|
||||
p = p + 4
|
||||
p += 4
|
||||
}
|
||||
if (flags & 128) != 0 {
|
||||
ca = as_fixed((tt_i16(d, p) << 2))
|
||||
cb = as_fixed((tt_i16(d, p + 2) << 2))
|
||||
cc = as_fixed((tt_i16(d, p + 4) << 2))
|
||||
ce = as_fixed((tt_i16(d, p + 6) << 2))
|
||||
p = p + 8
|
||||
p += 8
|
||||
}
|
||||
var odx = dx
|
||||
var ody = dy
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ function ed_add(x0: fixed, y0: fixed, x1: fixed, y1: fixed) -> void {
|
|||
ed_y0[ed_n] = y0
|
||||
ed_x1[ed_n] = x1
|
||||
ed_y1[ed_n] = y1
|
||||
ed_n = ed_n + 1
|
||||
ed_n += 1
|
||||
}
|
||||
|
||||
function tt_isqrt(v: int) -> int {
|
||||
|
|
@ -18,7 +18,7 @@ function tt_isqrt(v: int) -> int {
|
|||
while b > 0 {
|
||||
let t = r + b
|
||||
if t * t <= v { r = t }
|
||||
b = b / 2
|
||||
b /= 2
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ function tt_raster(id: int, gid: int, px: int) -> pointer {
|
|||
let end = ol_ends[ci]
|
||||
let cnt = end - start
|
||||
if cnt >= 2 {
|
||||
var first_on = 0 - 1
|
||||
var first_on = -1
|
||||
for i in 0 .. cnt {
|
||||
if first_on < 0 { if ol_on[start + i] == 1 { first_on = i } }
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ function tt_raster(id: int, gid: int, px: int) -> pointer {
|
|||
var ex = jx
|
||||
var ey = jy
|
||||
if ol_on[start + j] == 1 {
|
||||
step = step + 1
|
||||
step += 1
|
||||
} else {
|
||||
ex = (ix + jx) / 2 # implied on-curve midpoint
|
||||
ey = (iy + jy) / 2
|
||||
|
|
@ -142,7 +142,7 @@ function tt_raster(id: int, gid: int, px: int) -> pointer {
|
|||
curx = ex
|
||||
cury = ey
|
||||
}
|
||||
step = step + 1
|
||||
step += 1
|
||||
}
|
||||
ed_add(curx, cury, sx, sy)
|
||||
}
|
||||
|
|
@ -167,8 +167,8 @@ function tt_raster(id: int, gid: int, px: int) -> pointer {
|
|||
if hit == 1 {
|
||||
let t = (yc - ya) / (yb - ya)
|
||||
sc_x[m] = ed_x0[i] + t * (ed_x1[i] - ed_x0[i])
|
||||
if yb > ya { sc_d[m] = 1 } else { sc_d[m] = 0 - 1 }
|
||||
m = m + 1
|
||||
if yb > ya { sc_d[m] = 1 } else { sc_d[m] = -1 }
|
||||
m += 1
|
||||
}
|
||||
}
|
||||
# insertion sort the crossings by x
|
||||
|
|
@ -181,12 +181,12 @@ function tt_raster(id: int, gid: int, px: int) -> pointer {
|
|||
if sc_x[j] > kx {
|
||||
sc_x[j + 1] = sc_x[j]
|
||||
sc_d[j + 1] = sc_d[j]
|
||||
j = j - 1
|
||||
j -= 1
|
||||
} else {
|
||||
sc_x[j + 1] = kx
|
||||
sc_d[j + 1] = kd
|
||||
placed = 1
|
||||
j = 0 - 1
|
||||
j = -1
|
||||
}
|
||||
}
|
||||
if placed == 0 {
|
||||
|
|
@ -197,7 +197,7 @@ function tt_raster(id: int, gid: int, px: int) -> pointer {
|
|||
var wind = 0
|
||||
let oy = sy / TT_SS
|
||||
for i in 0 .. m - 1 {
|
||||
wind = wind + sc_d[i]
|
||||
wind += sc_d[i]
|
||||
if wind != 0 {
|
||||
var xa = sc_x[i]
|
||||
var xb = sc_x[i + 1]
|
||||
|
|
@ -271,7 +271,7 @@ var u8_next: int = 0 # byte index just past the codepoint last decoded
|
|||
|
||||
function tt_utf8(s: string, at: int) -> int {
|
||||
let c = s[at]
|
||||
var extra = 0 - 1
|
||||
var extra = -1
|
||||
if c < 128 { extra = 0 }
|
||||
if (c >> 5) == 6 { extra = 1 }
|
||||
if (c >> 4) == 14 { extra = 2 }
|
||||
|
|
@ -342,11 +342,11 @@ function rt_text_ttf(font: int, x: int, y: int, s: string, colour: int, px: int)
|
|||
i = u8_next
|
||||
if cp == 10 {
|
||||
penx = x
|
||||
baseline = baseline + lineh
|
||||
baseline += lineh
|
||||
} else {
|
||||
let g = tt_glyph_get(font, cp, px)
|
||||
tt_blit(gc_bmp[g], gc_w[g], gc_h[g], penx + gc_ox[g], baseline - gc_oy[g], colour)
|
||||
penx = penx + gc_adv[g]
|
||||
penx += gc_adv[g]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -365,7 +365,7 @@ function rt_text_w(font: int, s: string, px: int) -> int {
|
|||
if w > best { best = w }
|
||||
w = 0
|
||||
} else {
|
||||
w = w + gc_adv[tt_glyph_get(font, cp, px)]
|
||||
w += gc_adv[tt_glyph_get(font, cp, px)]
|
||||
}
|
||||
}
|
||||
if w > best { best = w }
|
||||
|
|
|
|||
|
|
@ -60,15 +60,15 @@ function tw_alloc() -> int {
|
|||
var i = 0
|
||||
while i < TW_MAX {
|
||||
if tw_used[i] == 0 { return i }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
# none free: reuse the first finished handle so long-lived games don't leak.
|
||||
i = 0
|
||||
while i < TW_MAX {
|
||||
if tw_done[i] != 0 { return i }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
|
||||
# append one segment to a handle (internal). Silently ignored past TW_SEGS.
|
||||
|
|
@ -88,7 +88,7 @@ function tw_push(h: int, kind: int, from: int, to: int, dur: int, ease: int) ->
|
|||
# start a new tween handle: from -> to over `dur` ticks with easing `ease`.
|
||||
function tween_to(from: int, to: int, dur: int, ease: int) -> int {
|
||||
let h = tw_alloc()
|
||||
if h < 0 { return 0 - 1 }
|
||||
if h < 0 { return -1 }
|
||||
tw_used[h] = 1
|
||||
tw_seg[h] = 0
|
||||
tw_nseg[h] = 0
|
||||
|
|
@ -187,7 +187,7 @@ function tw_advance_one(h: int) -> void {
|
|||
# (a delay segment holds tw_value unchanged.)
|
||||
if tick >= dur { # this segment finished: advance
|
||||
if kind == 0 { tw_value[h] = tw_to[s] } # rest exactly on the target
|
||||
seg = seg + 1
|
||||
seg += 1
|
||||
tw_seg[h] = seg
|
||||
tw_tick[h] = 0
|
||||
if seg >= n { tw_done[h] = 1 }
|
||||
|
|
@ -203,6 +203,6 @@ function esys_tween() -> void {
|
|||
var i = 0
|
||||
while i < TW_MAX {
|
||||
if (tw_used[i] != 0) and (tw_done[i] == 0) { tw_advance_one(i) }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ function rt_ui_reset(n: int) -> void {
|
|||
ui_n = n
|
||||
for i in 0 .. n {
|
||||
ui_type[i] = 0
|
||||
ui_parent[i] = 0 - 1
|
||||
ui_parent[i] = -1
|
||||
ui_w[i] = 0
|
||||
ui_h[i] = 0
|
||||
ui_x[i] = 0
|
||||
|
|
@ -124,16 +124,16 @@ function rt_ui_reset(n: int) -> void {
|
|||
ui_haspos[i] = 0
|
||||
ui_pad[i] = 0
|
||||
ui_gap[i] = 0
|
||||
ui_bg[i] = 0 - 1
|
||||
ui_fg[i] = 0 - 1
|
||||
ui_border[i] = 0 - 1
|
||||
ui_align[i] = 0 - 1
|
||||
ui_bg[i] = -1
|
||||
ui_fg[i] = -1
|
||||
ui_border[i] = -1
|
||||
ui_align[i] = -1
|
||||
ui_grow[i] = 0
|
||||
ui_font[i] = 0 - 1
|
||||
ui_font[i] = -1
|
||||
ui_size[i] = 8
|
||||
ui_skin[i] = 0 - 1
|
||||
ui_skin[i] = -1
|
||||
ui_inset[i] = 6
|
||||
ui_img[i] = 0 - 1
|
||||
ui_img[i] = -1
|
||||
ui_focusable[i] = 0
|
||||
ui_visible[i] = 1
|
||||
ui_fired[i] = 0
|
||||
|
|
@ -197,7 +197,7 @@ function ui_tw(font: int, s: pointer, size: int) -> int {
|
|||
if font < tt_n { return rt_text_w(font, s, size) }
|
||||
}
|
||||
var n = 0
|
||||
while s[n] != 0 { n = n + 1 }
|
||||
while s[n] != 0 { n += 1 }
|
||||
return n * 6 * max(size / 8, 1)
|
||||
}
|
||||
|
||||
|
|
@ -239,15 +239,15 @@ function ui_measure() -> void {
|
|||
let pad = ui_pad[i]
|
||||
var cw = 0
|
||||
var ch = 0
|
||||
if t == WT_LABEL { cw = 0 - 1 }
|
||||
if t == WT_BUTTON { cw = 0 - 1 }
|
||||
if cw == 0 - 1 {
|
||||
if t == WT_LABEL { cw = -1 }
|
||||
if t == WT_BUTTON { cw = -1 }
|
||||
if cw == -1 {
|
||||
let s = ui_str(i)
|
||||
cw = ui_tw(ui_font[i], s, ui_size[i]) + 2 * pad
|
||||
ch = ui_th(ui_font[i], ui_size[i]) + 2 * pad
|
||||
if t == WT_BUTTON {
|
||||
cw = cw + 10
|
||||
ch = ch + 6
|
||||
cw += 10
|
||||
ch += 6
|
||||
}
|
||||
} else {
|
||||
if t == WT_IMAGE {
|
||||
|
|
@ -269,13 +269,13 @@ function ui_measure() -> void {
|
|||
if ui_parent[c] == i {
|
||||
if ui_visible[c] == 1 {
|
||||
if dir == 1 {
|
||||
mainsz = mainsz + ui_rh[c]
|
||||
mainsz += ui_rh[c]
|
||||
cross = max(cross, ui_rw[c])
|
||||
} else {
|
||||
mainsz = mainsz + ui_rw[c]
|
||||
mainsz += ui_rw[c]
|
||||
cross = max(cross, ui_rh[c])
|
||||
}
|
||||
nc = nc + 1
|
||||
nc += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ function ui_measure() -> void {
|
|||
ui_rw[i] = rw
|
||||
ui_rh[i] = rh
|
||||
}
|
||||
i = i - 1
|
||||
i -= 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ function ui_arrange(i: int, x: int, y: int) -> void {
|
|||
for c in 0 .. ui_n {
|
||||
if ui_parent[c] == i {
|
||||
if ui_visible[c] == 1 {
|
||||
if dir == 1 { total = total + ui_rh[c] } else { total = total + ui_rw[c] }
|
||||
ng = ng + 1
|
||||
grows = grows + ui_grow[c]
|
||||
if dir == 1 { total += ui_rh[c] } else { total += ui_rw[c] }
|
||||
ng += 1
|
||||
grows += ui_grow[c]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ function ui_focusables() -> int {
|
|||
if ui_visible[i] == 1 {
|
||||
if ui_under(i, ui_active) {
|
||||
ui_fl[n] = i
|
||||
n = n + 1
|
||||
n += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -169,12 +169,12 @@ function ui_focusables() -> int {
|
|||
event UiClicked { id: int = 0 }
|
||||
|
||||
# Ui.close(): no menu is active (the same as opening root -1)
|
||||
function rt_ui_close() -> void { rt_ui_open(0 - 1) }
|
||||
function rt_ui_close() -> void { rt_ui_open(-1) }
|
||||
|
||||
function rt_ui_open(root: int) -> void {
|
||||
ui_active = root
|
||||
let n = ui_focusables()
|
||||
ui_focus = 0 - 1
|
||||
ui_focus = -1
|
||||
if n > 0 { ui_focus = ui_fl[0] }
|
||||
}
|
||||
|
||||
|
|
@ -184,10 +184,10 @@ function rt_ui_tick(k: int) -> void {
|
|||
ui_layout()
|
||||
let n = ui_focusables()
|
||||
if n == 0 {
|
||||
ui_focus = 0 - 1
|
||||
ui_focus = -1
|
||||
return
|
||||
}
|
||||
var cur = 0 - 1
|
||||
var cur = -1
|
||||
for i in 0 .. n {
|
||||
if ui_fl[i] == ui_focus { cur = i }
|
||||
}
|
||||
|
|
@ -195,18 +195,18 @@ function rt_ui_tick(k: int) -> void {
|
|||
cur = 0
|
||||
ui_focus = ui_fl[0]
|
||||
}
|
||||
if k == 119 { # 'w'
|
||||
if k == 'w' { # 'w'
|
||||
cur = (cur - 1 + n) % n
|
||||
ui_focus = ui_fl[cur]
|
||||
}
|
||||
if k == 115 { # 's'
|
||||
if k == 's' { # 's'
|
||||
cur = (cur + 1) % n
|
||||
ui_focus = ui_fl[cur]
|
||||
}
|
||||
var fire = 0
|
||||
if k == 32 { fire = 1 }
|
||||
if k == 10 { fire = 1 }
|
||||
if k == 13 { fire = 1 }
|
||||
if k == ' ' { fire = 1 }
|
||||
if k == '\n' { fire = 1 }
|
||||
if k == '\r' { fire = 1 }
|
||||
if fire == 1 { ui_fired[ui_focus] = 1; emit UiClicked(id: ui_focus) }
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ function rt_ui_set_text(id: int, s: string) -> void {
|
|||
if i >= 95 { ch = 0 }
|
||||
if ch != 0 {
|
||||
ui_dyn[base + i] = ch
|
||||
i = i + 1
|
||||
i += 1
|
||||
ch = s[i]
|
||||
}
|
||||
}
|
||||
|
|
@ -248,27 +248,27 @@ function rt_ui_set_int(id: int, n: int) -> void {
|
|||
var at = 0
|
||||
var v = n
|
||||
if v < 0 {
|
||||
ui_dyn[base] = 45
|
||||
ui_dyn[base] = '-'
|
||||
at = 1
|
||||
v = 0 - v
|
||||
v = -v
|
||||
}
|
||||
if v == 0 {
|
||||
ui_dyn[base + at] = 48
|
||||
at = at + 1
|
||||
ui_dyn[base + at] = '0'
|
||||
at += 1
|
||||
} else {
|
||||
var digits = 0
|
||||
var t = v
|
||||
while t > 0 {
|
||||
digits = digits + 1
|
||||
t = t / 10
|
||||
digits += 1
|
||||
t /= 10
|
||||
}
|
||||
var p = digits
|
||||
while p > 0 {
|
||||
var div = 1
|
||||
for k in 1 .. p { div = div * 10 }
|
||||
for k in 1 .. p { div *= 10 }
|
||||
ui_dyn[base + at] = 48 + (v / div) % 10
|
||||
at = at + 1
|
||||
p = p - 1
|
||||
at += 1
|
||||
p -= 1
|
||||
}
|
||||
}
|
||||
ui_dyn[base + at] = 0
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ function value_object() -> Val { return value_new(6) }
|
|||
function value_add(list: Val, item: Val) -> Val { push(list.kids, item); return list }
|
||||
function value_put(obj: Val, key: pointer, item: Val) -> Val {
|
||||
var i = 0
|
||||
while i < len(obj.keys) { if obj.keys[i] == key { obj.kids[i] = item; return obj }; i = i + 1 }
|
||||
while i < len(obj.keys) { if obj.keys[i] == key { obj.kids[i] = item; return obj }; i += 1 }
|
||||
push(obj.keys, key); push(obj.kids, item)
|
||||
return obj
|
||||
}
|
||||
|
|
@ -65,12 +65,12 @@ function value_key_at(obj: Val, i: int) -> pointer {
|
|||
}
|
||||
function value_get(obj: Val, key: pointer) -> Val {
|
||||
var i = 0
|
||||
while i < len(obj.keys) { if obj.keys[i] == key { return obj.kids[i] }; i = i + 1 }
|
||||
while i < len(obj.keys) { if obj.keys[i] == key { return obj.kids[i] }; i += 1 }
|
||||
return value_null()
|
||||
}
|
||||
function value_has(obj: Val, key: pointer) -> int {
|
||||
var i = 0
|
||||
while i < len(obj.keys) { if obj.keys[i] == key { return 1 }; i = i + 1 }
|
||||
while i < len(obj.keys) { if obj.keys[i] == key { return 1 }; i += 1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
@ -82,11 +82,11 @@ function json_quote(s: pointer) -> pointer {
|
|||
let n = len(s)
|
||||
while i < n {
|
||||
let c = s[i]
|
||||
if c == 34 { out = out + "\\\"" }
|
||||
else { if c == 92 { out = out + "\\\\" }
|
||||
else { if c == 10 { out = out + "\\n" }
|
||||
else { out = out + s[i..i + 1] } } }
|
||||
i = i + 1
|
||||
if c == '"' { out += "\\\"" }
|
||||
else { if c == '\\' { out += "\\\\" }
|
||||
else { if c == '\n' { out += "\\n" }
|
||||
else { out += s[i..i + 1] } } }
|
||||
i += 1
|
||||
}
|
||||
return out + "\""
|
||||
}
|
||||
|
|
@ -99,14 +99,14 @@ function json_quote(s: pointer) -> pointer {
|
|||
function json_fixed_str(raw: int) -> pointer {
|
||||
var a = raw
|
||||
var sign = ""
|
||||
if a < 0 { sign = "-"; a = 0 - a }
|
||||
if a < 0 { sign = "-"; a = -a }
|
||||
let ip = a / 65536
|
||||
var frac = a % 65536
|
||||
if frac == 0 { return sign + string(ip) + ".0" }
|
||||
var fs = ""
|
||||
while frac != 0 {
|
||||
frac = frac * 10
|
||||
fs = fs + string(frac / 65536)
|
||||
frac *= 10
|
||||
fs += string(frac / 65536)
|
||||
frac = frac % 65536
|
||||
}
|
||||
return sign + string(ip) + "." + fs
|
||||
|
|
@ -122,18 +122,18 @@ function json_encode(v: Val) -> pointer {
|
|||
var out = "["
|
||||
var i = 0
|
||||
while i < len(v.kids) {
|
||||
if i > 0 { out = out + "," }
|
||||
out = out + json_encode(v.kids[i])
|
||||
i = i + 1
|
||||
if i > 0 { out += "," }
|
||||
out += json_encode(v.kids[i])
|
||||
i += 1
|
||||
}
|
||||
return out + "]"
|
||||
}
|
||||
var out = "{"
|
||||
var i = 0
|
||||
while i < len(v.keys) {
|
||||
if i > 0 { out = out + "," }
|
||||
if i > 0 { out += "," }
|
||||
out = out + json_quote(v.keys[i]) + ":" + json_encode(v.kids[i])
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return out + "}"
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ property JP { s: pointer = null, i: int = 0, n: int = 0 }
|
|||
function jp_skip_ws(p: JP) -> void {
|
||||
while p.i < p.n {
|
||||
let c = p.s[p.i]
|
||||
if c == 32 or c == 9 or c == 10 or c == 13 { p.i = p.i + 1 }
|
||||
if c == ' ' or c == '\t' or c == '\n' or c == '\r' { p.i += 1 }
|
||||
else { return }
|
||||
}
|
||||
}
|
||||
|
|
@ -162,33 +162,33 @@ function jp_value(p: JP) -> Val {
|
|||
jp_skip_ws(p)
|
||||
if p.i >= p.n { return value_null() }
|
||||
let c = p.s[p.i]
|
||||
if c == 123 { return jp_object(p) } # '{'
|
||||
if c == 91 { return jp_list(p) } # '['
|
||||
if c == 34 { return value_str(jp_string(p)) } # '"'
|
||||
if c == 116 { p.i = p.i + 4; return value_bool(1) } # true
|
||||
if c == 102 { p.i = p.i + 5; return value_bool(0) } # false
|
||||
if c == 110 { p.i = p.i + 4; return value_null() } # null
|
||||
if c == '{' { return jp_object(p) } # '{'
|
||||
if c == '[' { return jp_list(p) } # '['
|
||||
if c == '"' { return value_str(jp_string(p)) } # '"'
|
||||
if c == 't' { p.i += 4; return value_bool(1) } # true
|
||||
if c == 'f' { p.i += 5; return value_bool(0) } # false
|
||||
if c == 'n' { p.i += 4; return value_null() } # null
|
||||
return jp_number(p)
|
||||
}
|
||||
|
||||
# read a quoted string (cursor on the opening quote) -> the unescaped contents.
|
||||
function jp_string(p: JP) -> pointer {
|
||||
p.i = p.i + 1 # skip opening quote
|
||||
p.i += 1 # skip opening quote
|
||||
var out = ""
|
||||
while p.i < p.n {
|
||||
let c = p.s[p.i]
|
||||
if c == 34 { p.i = p.i + 1; return out } # closing quote
|
||||
if c == 92 { # escape
|
||||
p.i = p.i + 1
|
||||
if c == '"' { p.i += 1; return out } # closing quote
|
||||
if c == '\\' { # escape
|
||||
p.i += 1
|
||||
if p.i < p.n {
|
||||
let e = p.s[p.i]
|
||||
if e == 110 { out = out + "\n" }
|
||||
else { out = out + p.s[p.i..p.i + 1] } # \" \\ \/ -> the literal char
|
||||
p.i = p.i + 1
|
||||
if e == 'n' { out += "\n" }
|
||||
else { out += p.s[p.i..p.i + 1] } # \" \\ \/ -> the literal char
|
||||
p.i += 1
|
||||
}
|
||||
} else {
|
||||
out = out + p.s[p.i..p.i + 1]
|
||||
p.i = p.i + 1
|
||||
out += p.s[p.i..p.i + 1]
|
||||
p.i += 1
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
|
@ -197,18 +197,18 @@ function jp_string(p: JP) -> pointer {
|
|||
# read a number; a '.' makes it a fixed node, otherwise an int node.
|
||||
function jp_number(p: JP) -> Val {
|
||||
var neg = 0
|
||||
if p.i < p.n and p.s[p.i] == 45 { neg = 1; p.i = p.i + 1 } # '-'
|
||||
if p.i < p.n and p.s[p.i] == '-' { neg = 1; p.i += 1 } # '-'
|
||||
var ip = 0
|
||||
while p.i < p.n and p.s[p.i] >= 48 and p.s[p.i] <= 57 {
|
||||
while p.i < p.n and p.s[p.i] >= '0' and p.s[p.i] <= '9' {
|
||||
ip = ip * 10 + (p.s[p.i] - 48)
|
||||
p.i = p.i + 1
|
||||
p.i += 1
|
||||
}
|
||||
if p.i < p.n and p.s[p.i] == 46 { # '.', a fixed
|
||||
p.i = p.i + 1
|
||||
if p.i < p.n and p.s[p.i] == '.' { # '.', a fixed
|
||||
p.i += 1
|
||||
let digits = new []int
|
||||
while p.i < p.n and p.s[p.i] >= 48 and p.s[p.i] <= 57 {
|
||||
while p.i < p.n and p.s[p.i] >= '0' and p.s[p.i] <= '9' {
|
||||
push(digits, p.s[p.i] - 48)
|
||||
p.i = p.i + 1
|
||||
p.i += 1
|
||||
}
|
||||
# exact inverse of json_fixed_str's generation: fold the digits back from the
|
||||
# last, frac_{i-1} = (d_i*65536 + frac_i)/10. Every intermediate stays < 2^16*10,
|
||||
|
|
@ -218,49 +218,49 @@ function jp_number(p: JP) -> Val {
|
|||
var di = len(digits) - 1
|
||||
while di >= 0 {
|
||||
frac = (digits[di] * 65536 + frac) / 10
|
||||
di = di - 1
|
||||
di -= 1
|
||||
}
|
||||
var raw = ip * 65536 + frac
|
||||
if neg != 0 { raw = 0 - raw }
|
||||
if neg != 0 { raw = -raw }
|
||||
return value_fixed(raw)
|
||||
}
|
||||
if neg != 0 { ip = 0 - ip }
|
||||
if neg != 0 { ip = -ip }
|
||||
return value_int(ip)
|
||||
}
|
||||
|
||||
function jp_list(p: JP) -> Val {
|
||||
let out = value_list()
|
||||
p.i = p.i + 1 # '['
|
||||
p.i += 1 # '['
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 93 { p.i = p.i + 1; return out } # empty ']'
|
||||
if p.i < p.n and p.s[p.i] == ']' { p.i += 1; return out } # empty ']'
|
||||
while p.i < p.n {
|
||||
push(out.kids, jp_value(p))
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 44 { p.i = p.i + 1; continue } # ','
|
||||
if p.i < p.n and p.s[p.i] == ',' { p.i += 1; continue } # ','
|
||||
break
|
||||
}
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 93 { p.i = p.i + 1 }
|
||||
if p.i < p.n and p.s[p.i] == ']' { p.i += 1 }
|
||||
return out
|
||||
}
|
||||
|
||||
function jp_object(p: JP) -> Val {
|
||||
let out = value_object()
|
||||
p.i = p.i + 1 # '{'
|
||||
p.i += 1 # '{'
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 125 { p.i = p.i + 1; return out } # empty '}'
|
||||
if p.i < p.n and p.s[p.i] == '}' { p.i += 1; return out } # empty '}'
|
||||
while p.i < p.n {
|
||||
jp_skip_ws(p)
|
||||
let key = jp_string(p)
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 58 { p.i = p.i + 1 } # ':'
|
||||
if p.i < p.n and p.s[p.i] == ':' { p.i += 1 } # ':'
|
||||
push(out.keys, key)
|
||||
push(out.kids, jp_value(p))
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 44 { p.i = p.i + 1; continue } # ','
|
||||
if p.i < p.n and p.s[p.i] == ',' { p.i += 1; continue } # ','
|
||||
break
|
||||
}
|
||||
jp_skip_ws(p)
|
||||
if p.i < p.n and p.s[p.i] == 125 { p.i = p.i + 1 }
|
||||
if p.i < p.n and p.s[p.i] == '}' { p.i += 1 }
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ function xml_child(n: Xml, i: int) -> Xml {
|
|||
function xml_attr_count(n: Xml) -> int { return len(n.akeys) }
|
||||
function xml_has(n: Xml, key: pointer) -> int {
|
||||
var i = 0
|
||||
while i < len(n.akeys) { if n.akeys[i] == key { return 1 }; i = i + 1 }
|
||||
while i < len(n.akeys) { if n.akeys[i] == key { return 1 }; i += 1 }
|
||||
return 0
|
||||
}
|
||||
function xml_attr(n: Xml, key: pointer) -> pointer {
|
||||
var i = 0
|
||||
while i < len(n.akeys) { if n.akeys[i] == key { return n.avals[i] }; i = i + 1 }
|
||||
while i < len(n.akeys) { if n.akeys[i] == key { return n.avals[i] }; i += 1 }
|
||||
return ""
|
||||
}
|
||||
# attribute as an integer (decimal, optional leading '-'); `dflt` when absent.
|
||||
|
|
@ -61,14 +61,14 @@ function xml_attr_int(n: Xml, key: pointer, dflt: int) -> int {
|
|||
# the first direct child named `tag`, or the synthetic empty node if none.
|
||||
function xml_find(n: Xml, tag: pointer) -> Xml {
|
||||
var i = 0
|
||||
while i < len(n.kids) { if n.kids[i].tag == tag { return n.kids[i] }; i = i + 1 }
|
||||
while i < len(n.kids) { if n.kids[i].tag == tag { return n.kids[i] }; i += 1 }
|
||||
return xml_new("")
|
||||
}
|
||||
# count direct children named `tag`.
|
||||
function xml_count(n: Xml, tag: pointer) -> int {
|
||||
var c = 0
|
||||
var i = 0
|
||||
while i < len(n.kids) { if n.kids[i].tag == tag { c = c + 1 }; i = i + 1 }
|
||||
while i < len(n.kids) { if n.kids[i].tag == tag { c += 1 }; i += 1 }
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
@ -77,13 +77,13 @@ function xml_atoi(s: pointer) -> int {
|
|||
var i = 0
|
||||
let n = len(s)
|
||||
var neg = 0
|
||||
if i < n and s[i] == 45 { neg = 1; i = i + 1 } # '-'
|
||||
if i < n and s[i] == '-' { neg = 1; i += 1 } # '-'
|
||||
var v = 0
|
||||
while i < n and s[i] >= 48 and s[i] <= 57 {
|
||||
while i < n and s[i] >= '0' and s[i] <= '9' {
|
||||
v = v * 10 + (s[i] - 48)
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
if neg != 0 { return 0 - v }
|
||||
if neg != 0 { return -v }
|
||||
return v
|
||||
}
|
||||
|
||||
|
|
@ -97,41 +97,41 @@ function xml_unescape(s: pointer) -> pointer {
|
|||
var k = 0
|
||||
let m = len(s)
|
||||
var amp = 0
|
||||
while k < m { if s[k] == 38 { amp = 1; k = m } else { k = k + 1 } }
|
||||
while k < m { if s[k] == '&' { amp = 1; k = m } else { k += 1 } }
|
||||
if amp == 0 { return s }
|
||||
var out = ""
|
||||
var i = 0
|
||||
while i < m {
|
||||
let c = s[i]
|
||||
if c != 38 { # not '&'
|
||||
if c != '&' { # not '&'
|
||||
# copy the run up to the next '&' in one slice
|
||||
var j = i
|
||||
while j < m and s[j] != 38 { j = j + 1 }
|
||||
out = out + s[i..j]
|
||||
while j < m and s[j] != '&' { j += 1 }
|
||||
out += s[i..j]
|
||||
i = j
|
||||
} else {
|
||||
# find the ';'
|
||||
var j = i + 1
|
||||
while j < m and s[j] != 59 { j = j + 1 } # ';'
|
||||
if j >= m { out = out + s[i..m]; i = m }
|
||||
while j < m and s[j] != ';' { j += 1 } # ';'
|
||||
if j >= m { out += s[i..m]; i = m }
|
||||
else {
|
||||
let ent = s[i + 1..j]
|
||||
if ent == "amp" { out = out + "&" }
|
||||
else { if ent == "lt" { out = out + "<" }
|
||||
else { if ent == "gt" { out = out + ">" }
|
||||
else { if ent == "quot" { out = out + "\"" }
|
||||
else { if ent == "apos" { out = out + "'" }
|
||||
if ent == "amp" { out += "&" }
|
||||
else { if ent == "lt" { out += "<" }
|
||||
else { if ent == "gt" { out += ">" }
|
||||
else { if ent == "quot" { out += "\"" }
|
||||
else { if ent == "apos" { out += "'" }
|
||||
else {
|
||||
if len(ent) >= 2 and ent[0] == 35 { # '#' numeric reference
|
||||
if len(ent) >= 2 and ent[0] == '#' { # '#' numeric reference
|
||||
var code = 0
|
||||
if ent[1] == 120 or ent[1] == 88 { # '#x' hex
|
||||
if ent[1] == 'x' or ent[1] == 'X' { # '#x' hex
|
||||
var h = 2
|
||||
while h < len(ent) { code = code * 16 + xml_hexval(ent[h]); h = h + 1 }
|
||||
while h < len(ent) { code = code * 16 + xml_hexval(ent[h]); h += 1 }
|
||||
} else {
|
||||
var d = 1
|
||||
while d < len(ent) { code = code * 10 + (ent[d] - 48); d = d + 1 }
|
||||
while d < len(ent) { code = code * 10 + (ent[d] - 48); d += 1 }
|
||||
}
|
||||
out = out + xml_byte(code & 255)
|
||||
out += xml_byte(code & 255)
|
||||
} else {
|
||||
out = out + "&" + ent + ";" # unknown entity, keep literal
|
||||
}
|
||||
|
|
@ -144,9 +144,9 @@ function xml_unescape(s: pointer) -> pointer {
|
|||
}
|
||||
|
||||
function xml_hexval(c: int) -> int {
|
||||
if c >= 48 and c <= 57 { return c - 48 }
|
||||
if c >= 97 and c <= 102 { return c - 87 }
|
||||
if c >= 65 and c <= 70 { return c - 55 }
|
||||
if c >= '0' and c <= '9' { return c - 48 }
|
||||
if c >= 'a' and c <= 'f' { return c - 87 }
|
||||
if c >= 'A' and c <= 'F' { return c - 55 }
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ function xml_byte(b: int) -> pointer {
|
|||
if xml_bytetab == null {
|
||||
let t = bytes(257)
|
||||
var i = 0
|
||||
while i < 256 { t[i] = i + 1; i = i + 1 } # table[i] = byte (i+1), so 0 never appears
|
||||
while i < 256 { t[i] = i + 1; i += 1 } # table[i] = byte (i+1), so 0 never appears
|
||||
t[256] = 0
|
||||
xml_bytetab = t
|
||||
}
|
||||
|
|
@ -168,34 +168,34 @@ function xml_byte(b: int) -> pointer {
|
|||
# --- parser -----------------------------------------------------------------
|
||||
property XP { s: pointer = null, i: int = 0, n: int = 0 }
|
||||
|
||||
function xp_ws(c: int) -> bool { return c == 32 or c == 9 or c == 10 or c == 13 }
|
||||
function xp_ws(c: int) -> bool { return c == ' ' or c == '\t' or c == '\n' or c == '\r' }
|
||||
|
||||
function xp_skip_ws(p: XP) -> void {
|
||||
while p.i < p.n and xp_ws(p.s[p.i]) { p.i = p.i + 1 }
|
||||
while p.i < p.n and xp_ws(p.s[p.i]) { p.i += 1 }
|
||||
}
|
||||
|
||||
# skip a `<?...?>`, `<!-- ... -->` or `<!DOCTYPE ...>` at the cursor. Returns true
|
||||
# if it consumed one (cursor on '<').
|
||||
function xp_skip_misc(p: XP) -> bool {
|
||||
if p.i + 1 >= p.n or p.s[p.i] != 60 { return false } # '<'
|
||||
if p.i + 1 >= p.n or p.s[p.i] != '<' { return false } # '<'
|
||||
let c = p.s[p.i + 1]
|
||||
if c == 63 { # '<?' ... '?>'
|
||||
p.i = p.i + 2
|
||||
while p.i + 1 < p.n and not (p.s[p.i] == 63 and p.s[p.i + 1] == 62) { p.i = p.i + 1 }
|
||||
p.i = p.i + 2
|
||||
if c == '?' { # '<?' ... '?>'
|
||||
p.i += 2
|
||||
while p.i + 1 < p.n and not (p.s[p.i] == '?' and p.s[p.i + 1] == '>') { p.i += 1 }
|
||||
p.i += 2
|
||||
return true
|
||||
}
|
||||
if c == 33 { # '<!'
|
||||
if p.i + 3 < p.n and p.s[p.i + 2] == 45 and p.s[p.i + 3] == 45 { # '<!--' comment
|
||||
p.i = p.i + 4
|
||||
while p.i + 2 < p.n and not (p.s[p.i] == 45 and p.s[p.i + 1] == 45 and p.s[p.i + 2] == 62) { p.i = p.i + 1 }
|
||||
p.i = p.i + 3
|
||||
if c == '!' { # '<!'
|
||||
if p.i + 3 < p.n and p.s[p.i + 2] == '-' and p.s[p.i + 3] == '-' { # '<!--' comment
|
||||
p.i += 4
|
||||
while p.i + 2 < p.n and not (p.s[p.i] == '-' and p.s[p.i + 1] == '-' and p.s[p.i + 2] == '>') { p.i += 1 }
|
||||
p.i += 3
|
||||
return true
|
||||
}
|
||||
# '<!DOCTYPE ...>' or other declaration — skip to the matching '>'
|
||||
p.i = p.i + 2
|
||||
while p.i < p.n and p.s[p.i] != 62 { p.i = p.i + 1 }
|
||||
p.i = p.i + 1
|
||||
p.i += 2
|
||||
while p.i < p.n and p.s[p.i] != '>' { p.i += 1 }
|
||||
p.i += 1
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -206,8 +206,8 @@ function xp_name(p: XP) -> pointer {
|
|||
let start = p.i
|
||||
while p.i < p.n {
|
||||
let c = p.s[p.i]
|
||||
let ok = (c >= 65 and c <= 90) or (c >= 97 and c <= 122) or (c >= 48 and c <= 57)
|
||||
if ok or c == 95 or c == 45 or c == 58 or c == 46 { p.i = p.i + 1 }
|
||||
let ok = (c >= 'A' and c <= 'Z') or (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9')
|
||||
if ok or c == '_' or c == '-' or c == ':' or c == '.' { p.i += 1 }
|
||||
else { break }
|
||||
}
|
||||
return p.s[start..p.i]
|
||||
|
|
@ -219,21 +219,21 @@ function xp_attrs(p: XP, node: Xml) -> void {
|
|||
xp_skip_ws(p)
|
||||
if p.i >= p.n { return }
|
||||
let c = p.s[p.i]
|
||||
if c == 62 or c == 47 or c == 63 { return } # '>' '/' '?'
|
||||
if c == '>' or c == '/' or c == '?' { return } # '>' '/' '?'
|
||||
let key = xp_name(p)
|
||||
if len(key) == 0 { p.i = p.i + 1; continue } # stray char, don't stall
|
||||
if len(key) == 0 { p.i += 1; continue } # stray char, don't stall
|
||||
xp_skip_ws(p)
|
||||
var val = ""
|
||||
if p.i < p.n and p.s[p.i] == 61 { # '='
|
||||
p.i = p.i + 1
|
||||
if p.i < p.n and p.s[p.i] == '=' { # '='
|
||||
p.i += 1
|
||||
xp_skip_ws(p)
|
||||
if p.i < p.n and (p.s[p.i] == 34 or p.s[p.i] == 39) {
|
||||
if p.i < p.n and (p.s[p.i] == '"' or p.s[p.i] == '\'') {
|
||||
let q = p.s[p.i]
|
||||
p.i = p.i + 1
|
||||
p.i += 1
|
||||
let start = p.i
|
||||
while p.i < p.n and p.s[p.i] != q { p.i = p.i + 1 }
|
||||
while p.i < p.n and p.s[p.i] != q { p.i += 1 }
|
||||
val = xml_unescape(p.s[start..p.i])
|
||||
p.i = p.i + 1 # skip closing quote
|
||||
p.i += 1 # skip closing quote
|
||||
}
|
||||
}
|
||||
push(node.akeys, key)
|
||||
|
|
@ -243,34 +243,34 @@ function xp_attrs(p: XP, node: Xml) -> void {
|
|||
|
||||
# parse one element (cursor on its opening '<'). Recurses for children.
|
||||
function xp_element(p: XP) -> Xml {
|
||||
p.i = p.i + 1 # skip '<'
|
||||
p.i += 1 # skip '<'
|
||||
let name = xp_name(p)
|
||||
let node = xml_new(name)
|
||||
xp_attrs(p, node)
|
||||
# self-closing '/>'
|
||||
if p.i < p.n and p.s[p.i] == 47 { # '/'
|
||||
p.i = p.i + 1
|
||||
if p.i < p.n and p.s[p.i] == 62 { p.i = p.i + 1 } # '>'
|
||||
if p.i < p.n and p.s[p.i] == '/' { # '/'
|
||||
p.i += 1
|
||||
if p.i < p.n and p.s[p.i] == '>' { p.i += 1 } # '>'
|
||||
return node
|
||||
}
|
||||
if p.i < p.n and p.s[p.i] == 62 { p.i = p.i + 1 } # '>'
|
||||
if p.i < p.n and p.s[p.i] == '>' { p.i += 1 } # '>'
|
||||
# content until the matching close tag
|
||||
while p.i < p.n {
|
||||
if p.s[p.i] == 60 { # '<'
|
||||
if p.i + 1 < p.n and p.s[p.i + 1] == 47 { # '</' close
|
||||
p.i = p.i + 2
|
||||
if p.s[p.i] == '<' { # '<'
|
||||
if p.i + 1 < p.n and p.s[p.i + 1] == '/' { # '</' close
|
||||
p.i += 2
|
||||
let cn = xp_name(p)
|
||||
while p.i < p.n and p.s[p.i] != 62 { p.i = p.i + 1 }
|
||||
p.i = p.i + 1 # skip '>'
|
||||
while p.i < p.n and p.s[p.i] != '>' { p.i += 1 }
|
||||
p.i += 1 # skip '>'
|
||||
return node
|
||||
}
|
||||
if p.i + 3 < p.n and p.s[p.i + 1] == 33 and p.s[p.i + 2] == 91 { # '<![' CDATA
|
||||
if p.i + 3 < p.n and p.s[p.i + 1] == '!' and p.s[p.i + 2] == '[' { # '<![' CDATA
|
||||
# <![CDATA[ ... ]]>
|
||||
p.i = p.i + 9 # past "<![CDATA["
|
||||
p.i += 9 # past "<![CDATA["
|
||||
let start = p.i
|
||||
while p.i + 2 < p.n and not (p.s[p.i] == 93 and p.s[p.i + 1] == 93 and p.s[p.i + 2] == 62) { p.i = p.i + 1 }
|
||||
node.text = node.text + p.s[start..p.i]
|
||||
p.i = p.i + 3 # past "]]>"
|
||||
while p.i + 2 < p.n and not (p.s[p.i] == ']' and p.s[p.i + 1] == ']' and p.s[p.i + 2] == '>') { p.i += 1 }
|
||||
node.text += p.s[start..p.i]
|
||||
p.i += 3 # past "]]>"
|
||||
} else {
|
||||
if xp_skip_misc(p) { } # comment / PI inside content
|
||||
else { push(node.kids, xp_element(p)) }
|
||||
|
|
@ -278,8 +278,8 @@ function xp_element(p: XP) -> Xml {
|
|||
} else {
|
||||
# character data run up to the next '<'
|
||||
let start = p.i
|
||||
while p.i < p.n and p.s[p.i] != 60 { p.i = p.i + 1 }
|
||||
node.text = node.text + xml_unescape(p.s[start..p.i])
|
||||
while p.i < p.n and p.s[p.i] != '<' { p.i += 1 }
|
||||
node.text += xml_unescape(p.s[start..p.i])
|
||||
}
|
||||
}
|
||||
return node
|
||||
|
|
@ -292,10 +292,10 @@ function xml_parse(s: pointer) -> Xml {
|
|||
while p.i < p.n {
|
||||
xp_skip_ws(p)
|
||||
if p.i >= p.n { break }
|
||||
if p.s[p.i] == 60 { # '<'
|
||||
if p.s[p.i] == '<' { # '<'
|
||||
if xp_skip_misc(p) { } # prolog / comment / doctype
|
||||
else { return xp_element(p) }
|
||||
} else { p.i = p.i + 1 }
|
||||
} else { p.i += 1 }
|
||||
}
|
||||
return xml_new("")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ function zf_read(n: int) -> int {
|
|||
while k < n {
|
||||
let b = (zf_src[zf_pos] >> zf_bit) & 1
|
||||
v = v | (b << k)
|
||||
zf_bit = zf_bit + 1
|
||||
if zf_bit == 8 { zf_bit = 0; zf_pos = zf_pos + 1 }
|
||||
k = k + 1
|
||||
zf_bit += 1
|
||||
if zf_bit == 8 { zf_bit = 0; zf_pos += 1 }
|
||||
k += 1
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
|
@ -45,18 +45,18 @@ var zb_skip: int = 0 # padding bits above the sentinel in the last byt
|
|||
var zb_cur: int = 0 # data-bit index consumed so far
|
||||
|
||||
function zstd_highbit(v: int) -> int {
|
||||
var r = 0 - 1
|
||||
var r = -1
|
||||
var x = v & 255
|
||||
while x > 0 { r = r + 1; x = x >> 1 }
|
||||
while x > 0 { r += 1; x = x >> 1 }
|
||||
return r # position of the most-significant set bit (-1 if 0)
|
||||
}
|
||||
|
||||
# init over stream bytes [s, s+L); the sentinel is the top set bit of the last.
|
||||
function zb_init(src: pointer, s: int, L: int) -> int {
|
||||
zb_src = src; zb_s = s; zb_L = L; zb_cur = 0
|
||||
if L <= 0 { return 0 - 1 }
|
||||
if L <= 0 { return -1 }
|
||||
let hb = zstd_highbit(src[s + L - 1])
|
||||
if hb < 0 { return 0 - 1 } # a zero last byte is invalid
|
||||
if hb < 0 { return -1 } # a zero last byte is invalid
|
||||
zb_skip = 8 - hb # the sentinel bit + anything above it is padding
|
||||
return 0
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ function zb_bit() -> int {
|
|||
let j = zb_skip + zb_cur
|
||||
let byteidx = (zb_L - 1) - (j >> 3)
|
||||
let bit = 7 - (j & 7)
|
||||
zb_cur = zb_cur + 1
|
||||
zb_cur += 1
|
||||
if byteidx < 0 { return 0 }
|
||||
return (zb_src[zb_s + byteidx] >> bit) & 1
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ function zb_bit() -> int {
|
|||
function zb_read(n: int) -> int {
|
||||
var v = 0
|
||||
var k = 0
|
||||
while k < n { v = (v << 1) | zb_bit(); k = k + 1 }
|
||||
while k < n { v = (v << 1) | zb_bit(); k += 1 }
|
||||
return v
|
||||
}
|
||||
function zb_total() -> int { return 8 * (zb_L - 1) + (8 - zb_skip) } # usable data bits
|
||||
|
|
@ -101,14 +101,14 @@ function fse_build(norm: words, nsym: int, tableLog: int) -> FseDT {
|
|||
var highThreshold = size - 1
|
||||
var s = 0
|
||||
while s < nsym {
|
||||
if norm[s] == (0 - 1) {
|
||||
if norm[s] == (-1) {
|
||||
dt.sym[highThreshold] = s
|
||||
highThreshold = highThreshold - 1
|
||||
highThreshold -= 1
|
||||
symnext[s] = 1
|
||||
} else {
|
||||
symnext[s] = norm[s]
|
||||
}
|
||||
s = s + 1
|
||||
s += 1
|
||||
}
|
||||
# spread the remaining symbols with the standard step
|
||||
let step = (size >> 1) + (size >> 3) + 3
|
||||
|
|
@ -122,21 +122,21 @@ function fse_build(norm: words, nsym: int, tableLog: int) -> FseDT {
|
|||
dt.sym[pos] = s
|
||||
pos = (pos + step) & mask
|
||||
while pos > highThreshold { pos = (pos + step) & mask } # skip the low-prob zone
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
s = s + 1
|
||||
s += 1
|
||||
}
|
||||
# assign nbBits + newState for each cell
|
||||
var u = 0
|
||||
while u < size {
|
||||
let sy = dt.sym[u]
|
||||
let nextState = symnext[sy]
|
||||
symnext[sy] = symnext[sy] + 1
|
||||
symnext[sy] += 1
|
||||
let nbits = tableLog - zstd_highbit32(nextState)
|
||||
dt.nb[u] = nbits
|
||||
dt.ns[u] = (nextState << nbits) - size
|
||||
u = u + 1
|
||||
u += 1
|
||||
}
|
||||
free(symnext)
|
||||
return dt
|
||||
|
|
@ -144,9 +144,9 @@ function fse_build(norm: words, nsym: int, tableLog: int) -> FseDT {
|
|||
|
||||
# highbit for a full 32-bit-ish value (nextState < size <= 2^tableLog)
|
||||
function zstd_highbit32(v: int) -> int {
|
||||
var r = 0 - 1
|
||||
var r = -1
|
||||
var x = v
|
||||
while x > 0 { r = r + 1; x = x >> 1 }
|
||||
while x > 0 { r += 1; x = x >> 1 }
|
||||
return r
|
||||
}
|
||||
|
||||
|
|
@ -167,11 +167,11 @@ function fse_read_ncount(norm: words, maxsym: int) -> int {
|
|||
var n0 = sym
|
||||
var rep = zf_read(2)
|
||||
while rep == 3 {
|
||||
n0 = n0 + 3
|
||||
n0 += 3
|
||||
rep = zf_read(2)
|
||||
}
|
||||
n0 = n0 + rep
|
||||
while sym < n0 { norm[sym] = 0; sym = sym + 1 }
|
||||
n0 += rep
|
||||
while sym < n0 { norm[sym] = 0; sym += 1 }
|
||||
prev0 = 0
|
||||
} else {
|
||||
let maxv = (2 * threshold - 1) - remaining
|
||||
|
|
@ -183,22 +183,22 @@ function fse_read_ncount(norm: words, maxsym: int) -> int {
|
|||
zf_skip(bitsLeft - 1)
|
||||
} else {
|
||||
count = zf_read(bitsLeft)
|
||||
if count >= threshold { count = count - maxv }
|
||||
if count >= threshold { count -= maxv }
|
||||
}
|
||||
let val = count - 1 # -1 means low-prob (stored as -1)
|
||||
norm[sym] = val
|
||||
if val == (0 - 1) { remaining = remaining - 1 }
|
||||
else { remaining = remaining - val }
|
||||
sym = sym + 1
|
||||
if val == (-1) { remaining -= 1 }
|
||||
else { remaining -= val }
|
||||
sym += 1
|
||||
if val == 0 { prev0 = 1 }
|
||||
# shrink the threshold as `remaining` falls
|
||||
while remaining < threshold {
|
||||
bitsLeft = bitsLeft - 1
|
||||
bitsLeft -= 1
|
||||
threshold = threshold >> 1
|
||||
}
|
||||
}
|
||||
}
|
||||
while sym <= maxsym { norm[sym] = 0; sym = sym + 1 }
|
||||
while sym <= maxsym { norm[sym] = 0; sym += 1 }
|
||||
fse_ncount_n = sym
|
||||
return accLog
|
||||
}
|
||||
|
|
@ -222,13 +222,13 @@ function fse_decompress(dt: FseDT, out: words, cap: int) -> int {
|
|||
# two states alternate; when a state-advance read overruns the stream, the
|
||||
# other state's residual symbol is the final one (FSE_decompress tail).
|
||||
while true {
|
||||
out[n] = dt.sym[s1]; n = n + 1
|
||||
out[n] = dt.sym[s1]; n += 1
|
||||
s1 = dt.ns[s1] + zb_read(dt.nb[s1])
|
||||
if zb_cur > zb_total() { out[n] = dt.sym[s2]; n = n + 1; return n }
|
||||
if zb_cur > zb_total() { out[n] = dt.sym[s2]; n += 1; return n }
|
||||
if n >= cap { return n }
|
||||
out[n] = dt.sym[s2]; n = n + 1
|
||||
out[n] = dt.sym[s2]; n += 1
|
||||
s2 = dt.ns[s2] + zb_read(dt.nb[s2])
|
||||
if zb_cur > zb_total() { out[n] = dt.sym[s1]; n = n + 1; return n }
|
||||
if zb_cur > zb_total() { out[n] = dt.sym[s1]; n += 1; return n }
|
||||
if n >= cap { return n }
|
||||
}
|
||||
return n
|
||||
|
|
@ -245,7 +245,7 @@ property SeqDT { log: int = 0, base: words, addbits: words, nb: words, ns: words
|
|||
function zstd_lits(s: pointer) -> words {
|
||||
var n = 1
|
||||
var i = 0
|
||||
while i < len(s) { if s[i] == 59 { n = n + 1 }; i = i + 1 }
|
||||
while i < len(s) { if s[i] == ';' { n += 1 }; i += 1 }
|
||||
let a = words(n)
|
||||
var idx = 0
|
||||
var cur = 0
|
||||
|
|
@ -253,11 +253,11 @@ function zstd_lits(s: pointer) -> words {
|
|||
i = 0
|
||||
while i < len(s) {
|
||||
let c = s[i]
|
||||
if c == 59 { if neg == 1 { cur = 0 - cur }; a[idx] = cur; idx = idx + 1; cur = 0; neg = 0 }
|
||||
else { if c == 45 { neg = 1 } else { cur = cur * 10 + (c - 48) } }
|
||||
i = i + 1
|
||||
if c == ';' { if neg == 1 { cur = -cur }; a[idx] = cur; idx += 1; cur = 0; neg = 0 }
|
||||
else { if c == '-' { neg = 1 } else { cur = cur * 10 + (c - 48) } }
|
||||
i += 1
|
||||
}
|
||||
if neg == 1 { cur = 0 - cur }
|
||||
if neg == 1 { cur = -cur }
|
||||
a[idx] = cur
|
||||
return a
|
||||
}
|
||||
|
|
@ -309,36 +309,35 @@ function zstd_seq_tables_init() -> void {
|
|||
if zstd_ll_base != null { return }
|
||||
let llb = words(36)
|
||||
var i = 0
|
||||
while i < 16 { llb[i] = i; i = i + 1 }
|
||||
llb[16]=16; llb[17]=18; llb[18]=20; llb[19]=22; llb[20]=24; llb[21]=28
|
||||
llb[22]=32; llb[23]=40; llb[24]=48; llb[25]=64; llb[26]=128; llb[27]=256
|
||||
llb[28]=512; llb[29]=1024; llb[30]=2048; llb[31]=4096; llb[32]=8192
|
||||
llb[33]=16384; llb[34]=32768; llb[35]=65536
|
||||
while i < 16 { llb[i] = i; i += 1 }
|
||||
llb[16] = 16; llb[17] = 18; llb[18] = 20; llb[19] = 22; llb[20] = 24; llb[21] = 28
|
||||
llb[22] = 32; llb[23] = 40; llb[24] = 48; llb[25] = 64; llb[26] = 128; llb[27] = 256
|
||||
llb[28] = 512; llb[29] = 1024; llb[30] = 2048; llb[31] = 4096; llb[32] = 8192
|
||||
llb[33] = 16384; llb[34] = 32768; llb[35] = 65536
|
||||
let llx = words(36)
|
||||
i = 0
|
||||
while i < 16 { llx[i] = 0; i = i + 1 }
|
||||
llx[16]=1; llx[17]=1; llx[18]=1; llx[19]=1; llx[20]=2; llx[21]=2
|
||||
llx[22]=3; llx[23]=3; llx[24]=4; llx[25]=6; llx[26]=7; llx[27]=8
|
||||
llx[28]=9; llx[29]=10; llx[30]=11; llx[31]=12; llx[32]=13; llx[33]=14
|
||||
llx[34]=15; llx[35]=16
|
||||
while i < 16 { llx[i] = 0; i += 1 }
|
||||
llx[16] = 1; llx[17] = 1; llx[18] = 1; llx[19] = 1; llx[20] = 2; llx[21] = 2
|
||||
llx[22] = 3; llx[23] = 3; llx[24] = 4; llx[25] = 6; llx[26] = 7; llx[27] = 8
|
||||
llx[28] = 9; llx[29] = 10; llx[30] = 11; llx[31] = 12; llx[32] = 13; llx[33] = 14
|
||||
llx[34] = 15; llx[35] = 16
|
||||
let mlb = words(53)
|
||||
i = 0
|
||||
while i < 32 { mlb[i] = i + 3; i = i + 1 }
|
||||
mlb[32]=35; mlb[33]=37; mlb[34]=39; mlb[35]=41; mlb[36]=43; mlb[37]=47
|
||||
mlb[38]=51; mlb[39]=59; mlb[40]=67; mlb[41]=83; mlb[42]=99; mlb[43]=131
|
||||
mlb[44]=259; mlb[45]=515; mlb[46]=1027; mlb[47]=2051; mlb[48]=4099
|
||||
mlb[49]=8195; mlb[50]=16387; mlb[51]=32771; mlb[52]=65539
|
||||
while i < 32 { mlb[i] = i + 3; i += 1 }
|
||||
mlb[32] = 35; mlb[33] = 37; mlb[34] = 39; mlb[35] = 41; mlb[36] = 43; mlb[37] = 47
|
||||
mlb[38] = 51; mlb[39] = 59; mlb[40] = 67; mlb[41] = 83; mlb[42] = 99; mlb[43] = 131
|
||||
mlb[44] = 259; mlb[45] = 515; mlb[46] = 1027; mlb[47] = 2051; mlb[48] = 4099
|
||||
mlb[49] = 8195; mlb[50] = 16387; mlb[51] = 32771; mlb[52] = 65539
|
||||
let mlx = words(53)
|
||||
i = 0
|
||||
while i < 32 { mlx[i] = 0; i = i + 1 }
|
||||
mlx[32]=1; mlx[33]=1; mlx[34]=1; mlx[35]=1; mlx[36]=2; mlx[37]=2
|
||||
mlx[38]=3; mlx[39]=3; mlx[40]=4; mlx[41]=4; mlx[42]=5; mlx[43]=7
|
||||
mlx[44]=8; mlx[45]=9; mlx[46]=10; mlx[47]=11; mlx[48]=12; mlx[49]=13
|
||||
mlx[50]=14; mlx[51]=15; mlx[52]=16
|
||||
while i < 32 { mlx[i] = 0; i += 1 }
|
||||
mlx[32] = 1; mlx[33] = 1; mlx[34] = 1; mlx[35] = 1; mlx[36] = 2; mlx[37] = 2
|
||||
mlx[38] = 3; mlx[39] = 3; mlx[40] = 4; mlx[41] = 4; mlx[42] = 5; mlx[43] = 7
|
||||
mlx[44] = 8; mlx[45] = 9; mlx[46] = 10; mlx[47] = 11; mlx[48] = 12; mlx[49] = 13
|
||||
mlx[50] = 14; mlx[51] = 15; mlx[52] = 16
|
||||
zstd_ll_base = llb; zstd_ll_bits = llx; zstd_ml_base = mlb; zstd_ml_bits = mlx
|
||||
}
|
||||
|
||||
|
||||
# ---- Huffman literal decode ------------------------------------------------
|
||||
property HufDT { maxbits: int = 0, sym: words, nb: words }
|
||||
|
||||
|
|
@ -347,7 +346,7 @@ property HufDT { maxbits: int = 0, sym: words, nb: words }
|
|||
function huf_build(weight: words, nweights: int) -> HufDT {
|
||||
var total = 0
|
||||
var i = 0
|
||||
while i < nweights { if weight[i] > 0 { total = total + (1 << (weight[i] - 1)) }; i = i + 1 }
|
||||
while i < nweights { if weight[i] > 0 { total = total + (1 << (weight[i] - 1)) }; i += 1 }
|
||||
let maxbits = zstd_highbit32(total) + 1
|
||||
let left = (1 << maxbits) - total
|
||||
weight[nweights] = zstd_highbit32(left) + 1 # last symbol's weight
|
||||
|
|
@ -360,13 +359,13 @@ function huf_build(weight: words, nweights: int) -> HufDT {
|
|||
# rank start positions: weight w occupies rankCount[w] << (w-1) cells, low weights first
|
||||
let rankcount = words(maxbits + 2)
|
||||
var w = 0
|
||||
while w <= maxbits { rankcount[w] = 0; w = w + 1 }
|
||||
while w <= maxbits { rankcount[w] = 0; w += 1 }
|
||||
i = 0
|
||||
while i < nsym { rankcount[weight[i]] = rankcount[weight[i]] + 1; i = i + 1 }
|
||||
while i < nsym { rankcount[weight[i]] = rankcount[weight[i]] + 1; i += 1 }
|
||||
let rankval = words(maxbits + 2)
|
||||
var next = 0
|
||||
w = 1
|
||||
while w <= maxbits { rankval[w] = next; next = next + (rankcount[w] << (w - 1)); w = w + 1 }
|
||||
while w <= maxbits { rankval[w] = next; next = next + (rankcount[w] << (w - 1)); w += 1 }
|
||||
i = 0
|
||||
while i < nsym {
|
||||
let ww = weight[i]
|
||||
|
|
@ -374,10 +373,10 @@ function huf_build(weight: words, nweights: int) -> HufDT {
|
|||
let len = 1 << (ww - 1)
|
||||
let nb = maxbits + 1 - ww
|
||||
var k = 0
|
||||
while k < len { dt.sym[rankval[ww] + k] = i; dt.nb[rankval[ww] + k] = nb; k = k + 1 }
|
||||
rankval[ww] = rankval[ww] + len
|
||||
while k < len { dt.sym[rankval[ww] + k] = i; dt.nb[rankval[ww] + k] = nb; k += 1 }
|
||||
rankval[ww] += len
|
||||
}
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
free(rankcount); free(rankval)
|
||||
return dt
|
||||
|
|
@ -387,7 +386,7 @@ function huf_build(weight: words, nweights: int) -> HufDT {
|
|||
# leaves zf_pos just past the description.
|
||||
function huf_read_tree() -> HufDT {
|
||||
let header = zf_src[zf_pos]
|
||||
zf_pos = zf_pos + 1
|
||||
zf_pos += 1
|
||||
let weight = words(256)
|
||||
if header >= 128 { # direct: (header-127) 4-bit weights
|
||||
let n = header - 127
|
||||
|
|
@ -397,7 +396,7 @@ function huf_read_tree() -> HufDT {
|
|||
var w = 0
|
||||
if (i & 1) == 0 { w = zf_src[bpos] >> 4 } else { w = zf_src[bpos] & 15 }
|
||||
weight[i] = w
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
zf_pos = zf_pos + ((n + 1) >> 1)
|
||||
return huf_build(weight, n)
|
||||
|
|
@ -423,8 +422,8 @@ function huf_decode_stream(dt: HufDT, out: pointer, at: int, n: int) -> void {
|
|||
while i < n {
|
||||
let bits = zstd_peek_rev(dt.maxbits)
|
||||
out[at + i] = dt.sym[bits]
|
||||
zb_cur = zb_cur + dt.nb[bits]
|
||||
i = i + 1
|
||||
zb_cur += dt.nb[bits]
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
# peek maxbits bits (MSB-first) without consuming — for the Huffman table index.
|
||||
|
|
@ -466,7 +465,7 @@ function zstd_lit_decode(src: pointer, pos: int, blockend: int) -> int {
|
|||
let buf = bytes(regen + 1)
|
||||
let b = src[pos + hdr]
|
||||
var i = 0
|
||||
while i < regen { buf[i] = b; i = i + 1 }
|
||||
while i < regen { buf[i] = b; i += 1 }
|
||||
zstd_lit = buf
|
||||
zstd_litn = regen
|
||||
return pos + hdr + 1
|
||||
|
|
@ -507,7 +506,7 @@ function zstd_lit_huff(src: pointer, pos: int, ltype: int, sf: int) -> int {
|
|||
zf_init(src, hs)
|
||||
dt = huf_read_tree()
|
||||
let treesize = zf_bytepos() - hs
|
||||
hs = hs + treesize
|
||||
hs += treesize
|
||||
payn = comp - treesize
|
||||
zstd_huf_prev = dt
|
||||
}
|
||||
|
|
@ -523,11 +522,11 @@ function zstd_lit_huff(src: pointer, pos: int, ltype: int, sf: int) -> int {
|
|||
let seg = (regen + 3) / 4
|
||||
var o = hs + 6
|
||||
zb_init(src, o, s1); huf_decode_stream(dt, buf, 0, seg)
|
||||
o = o + s1
|
||||
o += s1
|
||||
zb_init(src, o, s2); huf_decode_stream(dt, buf, seg, seg)
|
||||
o = o + s2
|
||||
o += s2
|
||||
zb_init(src, o, s3); huf_decode_stream(dt, buf, 2 * seg, seg)
|
||||
o = o + s3
|
||||
o += s3
|
||||
zb_init(src, o, s4); huf_decode_stream(dt, buf, 3 * seg, regen - 3 * seg)
|
||||
}
|
||||
return pos + hdr + comp
|
||||
|
|
@ -572,7 +571,7 @@ function zstd_seq_table(src: pointer, sp: int, mode: int, kind: int, prev: SeqDT
|
|||
while u < size {
|
||||
dt.base[u] = zstd_seq_base(kind, ft.sym[u])
|
||||
dt.addbits[u] = zstd_seq_bits(kind, ft.sym[u])
|
||||
u = u + 1
|
||||
u += 1
|
||||
}
|
||||
return dt
|
||||
}
|
||||
|
|
@ -595,17 +594,17 @@ function zstd_decomp_block(src: pointer, bstart: int, bsize: int, out: pointer,
|
|||
let blockend = bstart + bsize
|
||||
var sp = zstd_lit_decode(src, bstart, blockend)
|
||||
var nseq = src[sp]
|
||||
if nseq < 128 { sp = sp + 1 }
|
||||
else { if nseq < 255 { nseq = ((nseq - 128) << 8) + src[sp + 1]; sp = sp + 2 }
|
||||
else { nseq = src[sp + 1] + (src[sp + 2] << 8) + 32512; sp = sp + 3 } }
|
||||
if nseq < 128 { sp += 1 }
|
||||
else { if nseq < 255 { nseq = ((nseq - 128) << 8) + src[sp + 1]; sp += 2 }
|
||||
else { nseq = src[sp + 1] + (src[sp + 2] << 8) + 32512; sp += 3 } }
|
||||
var op = opos
|
||||
var litpos = 0
|
||||
if nseq == 0 {
|
||||
var i = 0
|
||||
while i < zstd_litn { out[op] = zstd_lit[i]; op = op + 1; i = i + 1 }
|
||||
while i < zstd_litn { out[op] = zstd_lit[i]; op += 1; i += 1 }
|
||||
return op
|
||||
}
|
||||
let modes = src[sp]; sp = sp + 1
|
||||
let modes = src[sp]; sp += 1
|
||||
let llmode = (modes >> 6) & 3
|
||||
let ofmode = (modes >> 4) & 3
|
||||
let mlmode = (modes >> 2) & 3
|
||||
|
|
@ -641,53 +640,52 @@ function zstd_decomp_block(src: pointer, bstart: int, bsize: int, out: pointer,
|
|||
if ov == 1 { temp = zstd_rep1 }
|
||||
else { if ov == 3 { temp = zstd_rep0 - 1 }
|
||||
else { if ov >= 2 { temp = zstd_rep2 } else { temp = zstd_rep0 } } }
|
||||
if temp == 0 { temp = 0 - 1 }
|
||||
if temp == 0 { temp = -1 }
|
||||
if ov == 1 { } else { zstd_rep2 = zstd_rep1 }
|
||||
zstd_rep1 = zstd_rep0
|
||||
zstd_rep0 = temp
|
||||
offset = temp
|
||||
}
|
||||
}
|
||||
if mlBits > 0 { matchLen = matchLen + zb_read(mlBits) }
|
||||
if llBits > 0 { litLen = litLen + zb_read(llBits) }
|
||||
if mlBits > 0 { matchLen += zb_read(mlBits) }
|
||||
if llBits > 0 { litLen += zb_read(llBits) }
|
||||
var i = 0
|
||||
while i < litLen { out[op] = zstd_lit[litpos]; op = op + 1; litpos = litpos + 1; i = i + 1 }
|
||||
while i < litLen { out[op] = zstd_lit[litpos]; op += 1; litpos += 1; i += 1 }
|
||||
var k = 0
|
||||
while k < matchLen { out[op] = out[op - offset]; op = op + 1; k = k + 1 }
|
||||
q = q + 1
|
||||
while k < matchLen { out[op] = out[op - offset]; op += 1; k += 1 }
|
||||
q += 1
|
||||
if q < nseq {
|
||||
llstate = llt.ns[llstate] + zb_read(llt.nb[llstate])
|
||||
mlstate = mlt.ns[mlstate] + zb_read(mlt.nb[mlstate])
|
||||
ofstate = oft.ns[ofstate] + zb_read(oft.nb[ofstate])
|
||||
}
|
||||
}
|
||||
while litpos < zstd_litn { out[op] = zstd_lit[litpos]; op = op + 1; litpos = litpos + 1 }
|
||||
while litpos < zstd_litn { out[op] = zstd_lit[litpos]; op += 1; litpos += 1 }
|
||||
return op
|
||||
}
|
||||
|
||||
|
||||
# ---- frame / block loop ----------------------------------------------------
|
||||
var zstd_err: int = 0
|
||||
# decompress a single zstd frame. Returns bytes written, or -1.
|
||||
function z_zstd(src: pointer, len: int, out: pointer, cap: int) -> int {
|
||||
if len < 6 { return 0 - 1 }
|
||||
if src[0] != 40 { return 0 - 1 } # 0x28
|
||||
if src[1] != 181 { return 0 - 1 } # 0xB5
|
||||
if src[2] != 47 { return 0 - 1 } # 0x2F
|
||||
if src[3] != 253 { return 0 - 1 } # 0xFD
|
||||
if len < 6 { return -1 }
|
||||
if src[0] != '(' { return -1 } # 0x28
|
||||
if src[1] != 181 { return -1 } # 0xB5
|
||||
if src[2] != '/' { return -1 } # 0x2F
|
||||
if src[3] != 253 { return -1 } # 0xFD
|
||||
let fhd = src[4]
|
||||
let fcsFlag = (fhd >> 6) & 3
|
||||
let single = (fhd >> 5) & 1
|
||||
let dictFlag = fhd & 3
|
||||
var pos = 5
|
||||
if single == 0 { pos = pos + 1 } # window descriptor
|
||||
if dictFlag == 1 { pos = pos + 1 }
|
||||
if dictFlag == 2 { pos = pos + 2 }
|
||||
if dictFlag == 3 { pos = pos + 4 }
|
||||
if fcsFlag == 0 { if single == 1 { pos = pos + 1 } }
|
||||
if fcsFlag == 1 { pos = pos + 2 }
|
||||
if fcsFlag == 2 { pos = pos + 4 }
|
||||
if fcsFlag == 3 { pos = pos + 8 }
|
||||
if single == 0 { pos += 1 } # window descriptor
|
||||
if dictFlag == 1 { pos += 1 }
|
||||
if dictFlag == 2 { pos += 2 }
|
||||
if dictFlag == 3 { pos += 4 }
|
||||
if fcsFlag == 0 { if single == 1 { pos += 1 } }
|
||||
if fcsFlag == 1 { pos += 2 }
|
||||
if fcsFlag == 2 { pos += 4 }
|
||||
if fcsFlag == 3 { pos += 8 }
|
||||
# reset the repeat offsets per frame
|
||||
zstd_rep0 = 1; zstd_rep1 = 4; zstd_rep2 = 8
|
||||
zstd_huf_prev = null
|
||||
|
|
@ -695,27 +693,27 @@ function z_zstd(src: pointer, len: int, out: pointer, cap: int) -> int {
|
|||
var op = 0
|
||||
var last = 0
|
||||
while last == 0 {
|
||||
if pos + 3 > len { return 0 - 1 }
|
||||
if pos + 3 > len { return -1 }
|
||||
let bh = src[pos] | (src[pos + 1] << 8) | (src[pos + 2] << 16)
|
||||
pos = pos + 3
|
||||
pos += 3
|
||||
last = bh & 1
|
||||
let btype = (bh >> 1) & 3
|
||||
let bsize = bh >> 3
|
||||
if btype == 0 { # raw block
|
||||
var i = 0
|
||||
while i < bsize { out[op] = src[pos + i]; op = op + 1; i = i + 1 }
|
||||
pos = pos + bsize
|
||||
while i < bsize { out[op] = src[pos + i]; op += 1; i += 1 }
|
||||
pos += bsize
|
||||
} else { if btype == 1 { # RLE block: one byte * bsize
|
||||
let b = src[pos]
|
||||
var i = 0
|
||||
while i < bsize { out[op] = b; op = op + 1; i = i + 1 }
|
||||
pos = pos + 1
|
||||
while i < bsize { out[op] = b; op += 1; i += 1 }
|
||||
pos += 1
|
||||
} else { if btype == 2 { # compressed block
|
||||
op = zstd_decomp_block(src, pos, bsize, out, op, cap)
|
||||
pos = pos + bsize
|
||||
} else { return 0 - 1 } } } # reserved
|
||||
if op > cap { return 0 - 1 }
|
||||
if zstd_err != 0 { return 0 - 1 }
|
||||
pos += bsize
|
||||
} else { return -1 } } } # reserved
|
||||
if op > cap { return -1 }
|
||||
if zstd_err != 0 { return -1 }
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue