Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = component or require("component")
- local computer = computer or require("computer")
- local args = {...}
- local byte, char, rep, sub = string.byte, string.char, string.rep, string.sub
- local floor = math.floor
- local unpack = table.unpack
- local OPT = {loops = 0, skipend = false, nobuf = false, nojerk = false, maxsteps = 8}
- do
- local i = 1
- while i <= #args do
- local a = args[i]
- if a == "-l" then i = i + 1; OPT.loops = tonumber(args[i]) or 0
- elseif a == "-e" then OPT.skipend = true
- elseif a == "-d" then OPT.nobuf = true
- elseif a == "-j" then OPT.nojerk = true
- elseif a == "-s" then i = i + 1; OPT.maxsteps = tonumber(args[i]) or 8
- elseif a == "-h" or a == "--help" or a == "/?" then
- print("Timeless (OpenComputers port of the 1994 demo by Tran)")
- print("usage: timeless [-l N] [-e] [-d] [-j] [-s N]")
- print(" -l N loops, -e skip end picture, -d no GPU buffers,")
- print(" -j no jerky, -s N max logic steps per frame; ESC/Q quits""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
- local map = {}
- for i = 1, 64 do map[byte(al, i)] = i - 1 end
- s = s:gsub("[^%w%+/]", "") .. "AAA"
- return (s:gsub("(.)(.)(.)(.)", function(a, b, c, d)
- local v = (map[byte(a)] << 18) | (map[byte(b)] << 12) | (map[byte(c)] << 6) | map[byte(d)]
- return char(v >> 16, (v >> 8) & 255, v & 255)
- end))
- end
- local function unlzss(c, n)
- local parts, np = {}, 0
- local o, k, total, i = {}, 0, 0, 1
- while total < n do
- local f = byte(c, i); i = i + 1
- for b = 0, 7 do
- if total >= n then break end
- if f & (1 << b) ~= 0 then
- k = k + 1; o[k] = byte(c, i); i = i + 1; total = total + 1
- else
- local lo, hi = byte(c, i, i + 1); i = i + 2
- local off = lo | ((hi >> 4) << 8)
- local len = (hi & 15) + 3
- for _ = 1, len do k = k + 1; o[k] = o[k - off] end
- total = total + len
- end
- end
- if k >= 8192 then
- np = np + 1; parts[np] = char(unpack(o, 1, 4096))
- table.move(o, 4097, k, 1); k = k - 4096
- end
- end
- np = np + 1; parts[np] = char(unpack(o, 1, k))
- return sub(table.concat(parts), 1, n)
- end
- local BLOB = unlzss(b64decode(PACK), PACKLEN)
- PACK = nil
- local function sec(name) local s = SEC[name]; return sub(BLOB, s[1] + 1, s[1] + s[2]) end
- local TILES = sec("tiles")
- local SCT = sec("sctbl")
- local SPRS = sec("sprites")
- local LS = sec("lensshape")
- local LSRC = sec("lenssrc")
- local PALS = sec("pals")
- local PAL0A = sec("pal0a")
- local ENDP = sec("endpic")
- local RAYSTR = sec("rays")
- local SIN0, SIN0S, L2TBL = {}, {}, {}
- do
- local s = sec("sincos")
- for i = 0, 255 do
- SIN0[i] = byte(s, i + 1)
- local v = byte(s, 257 + i); if v > 127 then v = v - 256 end
- SIN0S[i] = v
- end
- local t = sec("l2tbl")
- for i = 0, 255 do L2TBL[i] = byte(t, i + 1) end
- end
- local SPRO = {}
- do
- local ls = sec("sprlens")
- local p = 1
- for id = 0, 34 do
- SPRO[id] = p
- p = p + byte(ls, id * 2 + 1) + (byte(ls, id * 2 + 2) << 8)
- end
- end
- local cpal = {}
- for i = 0, 767 do cpal[i] = 0 end
- local ZERO = {}
- for i = 0, 767 do ZERO[i] = 0 end
- local slide = nil
- local pal_dirty = true
- local function getpal(h, first, count)
- local pos = (h < 10) and h or (h - 1)
- local base = pos * 381 + first * 3
- local t = {}
- for i = 0, count * 3 - 1 do
- local idx = first * 3 + i
- t[i] = (idx < 381) and byte(PALS, pos * 381 + idx + 1) or 0
- end
- return t
- end
- local function getpal0a(set)
- local t = {}
- for i = 0, 191 do t[i] = byte(PAL0A, set * 192 + i + 1) end
- return t
- end
- local function pal_set(idx, len, tgt)
- for i = 0, len * 3 - 1 do cpal[idx * 3 + i] = tgt[i] end
- pal_dirty = true
- end
- local function pal_slide(idx, len, tgt)
- slide = {idx = idx, len = len, t = tgt}
- end
- local function slide_tick()
- local s = slide
- if not s then return end
- local fast = (s.len - 1) >= 128
- local changed = false
- local base, t = s.idx * 3, s.t
- for i = 0, s.len * 3 - 1 do
- local cur = cpal[base + i]
- local d = (cur - t[i]) & 255
- if d ~= 0 then
- changed = true
- local dl
- if fast then
- if d == 1 then dl = -1 elseif d < 128 then dl = -2
- elseif d == 255 then dl = 1 else dl = 2 end
- else
- dl = (d < 128) and -1 or 1
- end
- cpal[base + i] = (cur + dl) & 255
- end
- end
- if changed then pal_dirty = true else slide = nil end
- end
- local gpu
- do
- local addr = component.list("gpu")()
- if not addr then error("no graphics card") end
- gpu = component.proxy(addr)
- if not gpu.getScreen() then
- local s = component.list("screen")()
- if s then gpu.bind(s) end
- end
- end
- local old_w, old_h = gpu.getResolution()
- local old_depth = gpu.getDepth and gpu.getDepth() or 8
- local old_fg, old_bg = gpu.getForeground(), gpu.getBackground()
- local max_w, max_h = gpu.maxResolution()
- local WC, HC = math.min(160, max_w), math.min(50, max_h)
- gpu.setResolution(WC, HC)
- WC, HC = gpu.getResolution()
- if gpu.maxDepth and gpu.maxDepth() >= 8 then gpu.setDepth(8) end
- local W, H = WC, HC * 2
- local HS = H // 2
- local scr = {}
- for i = 1, W * H do scr[i] = 0 end
- local vram = nil
- if gpu.allocateBuffer and not OPT.nobuf then
- local ok, id = pcall(gpu.allocateBuffer, WC, HC)
- if ok and id then vram = id end
- end
- local HALF = "\u{2580}"
- local SP, HB = {}, {}
- local function spaces(n) local s = SP[n]; if not s then s = rep(" ", n); SP[n] = s end; return s end
- local function halves(n) local s = HB[n]; if not s then s = rep(HALF, n); HB[n] = s end; return s end
- local RL = {[0] = 0, 51, 102, 153, 204, 255}
- local GL = {[0] = 0, 36, 73, 109, 146, 182, 219, 255}
- local BL = {[0] = 0, 63, 127, 191, 255}
- local function nearest(levels, n, v)
- local best, bd = 0, 1e9
- for i = 0, n do
- local d = (levels[i] - v); d = d * d
- if d < bd then bd = d; best = i end
- end
- return levels[best]
- end
- local function quant(r, g, b)
- local qr, qg, qb = nearest(RL, 5, r), nearest(GL, 7, g), nearest(BL, 4, b)
- local e1 = (qr - r) ^ 2 + (qg - g) ^ 2 + (qb - b) ^ 2
- local gv = (r + g + b) // 3
- local gi = floor(gv * 17 / 255 + 0.5) - 1
- if gi < 0 then gi = 0 elseif gi > 15 then gi = 15 end
- local gq = (gi + 1) * 255 // 17
- local e2 = (gq - r) ^ 2 + (gq - g) ^ 2 + (gq - b) ^ 2
- if e2 < e1 then return (gq << 16) | (gq << 8) | gq end
- return (qr << 16) | (qg << 8) | qb
- end
- local rgb = {}
- for i = 0, 255 do rgb[i] = 0 end
- local fade = 1.0
- local function update_rgb()
- if not pal_dirty then return end
- pal_dirty = false
- for i = 0, 255 do
- local r, g, b = cpal[i * 3], cpal[i * 3 + 1], cpal[i * 3 + 2]
- rgb[i] = quant(r * 255 // 63, g * 255 // 63, b * 255 // 63)
- end
- end
- local direct_prev_t, direct_prev_b = nil, nil
- local function target_begin()
- if vram then gpu.setActiveBuffer(vram) end
- end
- local function target_end()
- if vram then
- gpu.setActiveBuffer(0)
- gpu.bitblt(0, 1, 1, WC, HC, vram, 1, 1)
- end
- end
- local function present()
- update_rgb()
- local setfg, setbg, set = gpu.setForeground, gpu.setBackground, gpu.set
- local fgc, bgc = -1, -1
- local direct = not vram
- if direct and not direct_prev_t then
- direct_prev_t, direct_prev_b = {}, {}
- for i = 1, W * HC do direct_prev_t[i] = -1; direct_prev_b[i] = -1 end
- end
- target_begin()
- for cy = 0, HC - 1 do
- local r0 = cy * 2 * W
- local r1 = r0 + W
- local cx = 1
- while cx <= W do
- local t, b = rgb[scr[r0 + cx]], rgb[scr[r1 + cx]]
- local e = cx
- while e < W and rgb[scr[r0 + e + 1]] == t and rgb[scr[r1 + e + 1]] == b do e = e + 1 end
- local draw = true
- if direct then
- draw = false
- local pb = cy * W
- for q = cx, e do
- if direct_prev_t[pb + q] ~= t or direct_prev_b[pb + q] ~= b then draw = true end
- direct_prev_t[pb + q] = t; direct_prev_b[pb + q] = b
- end
- end
- if draw then
- local n = e - cx + 1
- if t == b then
- if bgc ~= t then setbg(t); bgc = t end
- set(cx, cy + 1, spaces(n))
- else
- if fgc ~= t then setfg(t); fgc = t end
- if bgc ~= b then setbg(b); bgc = b end
- set(cx, cy + 1, halves(n))
- end
- end
- cx = e + 1
- end
- end
- target_end()
- end
- local function gpu_restore()
- if vram then
- pcall(gpu.setActiveBuffer, 0)
- pcall(gpu.freeBuffer, vram)
- vram = nil
- end
- pcall(gpu.setResolution, old_w, old_h)
- pcall(gpu.setForeground, old_fg)
- pcall(gpu.setBackground, old_bg)
- pcall(gpu.fill, 1, 1, old_w, old_h, " ")
- end
- local buf = {}
- for i = 1, 8192 do buf[i] = 0 end
- local function bput(a, v)
- a = a & 0xFFFF
- local i, s = (a >> 3) + 1, (a & 7) << 3
- buf[i] = (buf[i] & ~(0xFF << s)) | (v << s)
- end
- local function bget(a)
- a = a & 0xFFFF
- return (buf[(a >> 3) + 1] >> ((a & 7) << 3)) & 0xFF
- end
- local function bfill(a, n, v)
- a = a & 0xFFFF
- while n > 0 do
- if a & 7 == 0 and n >= 8 then
- local w = v * 0x0101010101010101
- local cnt = n >> 3
- local maxc = (0x10000 - a) >> 3
- if cnt > maxc then cnt = maxc end
- local i = (a >> 3) + 1
- for q = i, i + cnt - 1 do buf[q] = w end
- a = (a + cnt * 8) & 0xFFFF; n = n - cnt * 8
- else
- bput(a, v); a = (a + 1) & 0xFFFF; n = n - 1
- end
- end
- end
- local function rol16(x, n) x = x & 0xFFFF; return ((x << n) | (x >> (16 - n))) & 0xFFFF end
- local function rol32(x, n) x = x & 0xFFFFFFFF; return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF end
- local function ror32(x, n) x = x & 0xFFFFFFFF; return ((x >> n) | (x << (32 - n))) & 0xFFFFFFFF end
- local DRAWING = true
- local ending = false
- local l1on, l2on = false, false
- local loopcount = OPT.loops
- local finish_req = false
- local XT = {}
- local function sc_tobuf(tile, bl, bh, loc)
- local tb = tile * 1024
- local no = bl * (bl + 1) // 2
- local nx = bl + 1
- local c = 0
- for k = 1, nx do c = c + byte(SCT, no + k); XT[k] = c + 1 end
- local yo = bh * (bh + 1) // 2
- local r = 0
- local lx, ly = loc & 255, (loc >> 8) & 255
- for i = 1, bh + 1 do
- r = r + byte(SCT, yo + i)
- local rb = tb + r * 32
- local dst = (((ly + i - 1) & 255) << 8) + lx
- for k = 1, nx do
- local v = byte(TILES, rb + XT[k])
- if v ~= 0 then
- local a = (dst + k - 1) & 0xFFFF
- local q, s = (a >> 3) + 1, (a & 7) << 3
- buf[q] = (buf[q] & ~(0xFF << s)) | (v << s)
- end
- end
- end
- end
- local l0rout
- do
- local routtbl, ROUTTBLLEN, ROUTTBLSTART
- local routtblindex = 0
- local delaycntr = 0
- local palindex = 0
- local pal0aptr = 0
- local palptrtbl = {0x02, 0x00, 0x01, 0x06, 0x09, 0x01, 0x07, 0x04, 0x03,
- 0x05, 0x0e, 0x0d, 0x0c, 0x0b, 0x03,
- 0x01, 0x0f, 0x10, 0x04, 0x08, 0x0b}
- local PALTBLLEN = 21
- local function setnext0()
- local i = routtblindex + 1
- if i >= ROUTTBLLEN then
- if loopcount > 0 then
- loopcount = loopcount - 1
- if loopcount == 0 then finish_req = true end
- end
- pal0aptr = (pal0aptr + 1) % 6
- i = ROUTTBLSTART
- end
- l0rout = routtbl[i + 1]
- routtblindex = i
- end
- local function nextpal_idx()
- palindex = palindex + 1
- if palindex >= PALTBLLEN then palindex = 0 end
- return palptrtbl[palindex + 1]
- end
- local function palnext(bank)
- if ending then return true end
- pal_set(bank * 64, 64, getpal(nextpal_idx(), 0, 64))
- return false
- end
- local function palnexts(bank)
- if ending then return true end
- pal_slide(bank * 64, 64, getpal(nextpal_idx(), 0, 64))
- return false
- end
- local function set_palso(idx, len, tgt)
- if ending then return true end
- pal_slide(idx, len, tgt); return false
- end
- local function set_palo(idx, len, tgt)
- if ending then return true end
- pal_set(idx, len, tgt); return false
- end
- local d0loc, d0locd, d0color, d0counter = 0x357c, 0x137e, 0, 0
- local function p00()
- local dx, bx = d0loc, (d0locd + 0x1395) & 0xFFFF
- local al = d0color
- for _ = 1, 32 do
- bput(dx, al)
- local cf = bx >> 15
- bx = rol16(bx, 1)
- dx = (dx + bx + cf) & 0xFFFF
- al = ((al + 13) & 255) & 0x3f
- end
- d0loc, d0locd, d0color = dx, bx, al
- d0counter = (d0counter - 2) & 255
- if d0counter == 0 then setnext0() end
- end
- local d1counter = 0
- local function p10()
- local dl = d1counter
- local function run(bx, v, dbx)
- for _ = 1, 16 do
- bput(bx, v); bput(bx + 1, v); bput(bx + 256, v); bput(bx + 257, v)
- v = (v + 4) & 255
- bx = (bx + dbx) & 0xFFFF
- end
- end
- run(dl, 0x40, 97 * 256 + 97)
- run((0x33 << 8) | ((-dl) & 255), 0x42, 17 * 256 + 223)
- run((dl << 8) | 0x57, 0x41, 111 * 256 + 17)
- run((((-dl) & 255) << 8) | 0xa9, 0x43, 203 * 256 + 117)
- d1counter = (d1counter - 1) & 255
- if d1counter == 0 then setnext0() end
- end
- local d2counter = 0
- local function p20()
- local dl = d2counter
- local t = (dl < 64) and dl or (127 - dl)
- local col = 0x80 + t
- local function vline(a)
- for _ = 1, 256 do bput(a, col); a = a + 256 end
- end
- vline(dl * 2)
- bfill(dl * 512, 256, col)
- bfill((dl ~ 0x7f) * 512 + 256, 256, col)
- vline((dl ~ 0x7f) * 2 + 1)
- dl = (dl + 1) & 0x7f
- d2counter = dl
- if dl == 0 then setnext0() end
- end
- local d3tile = {0, 1, 2, 3}
- local d3sizeseed
- d3sizeseed = 0x974ADEC2
- local d3loc, d3locd = 0x53c7, 0x137e
- local d3size, d3counter, d3counter2 = 0, 0, 4
- local d3sizetbl = {4, 4, 4, 4, 5, 5, 6, 7}
- if OPT.nojerk then d3sizetbl[7] = 5; d3sizetbl[8] = 5 end
- local function p30()
- local di = d3loc
- local cl = d3size
- local bl = (1 << cl) & 255
- local ax = bl
- bl = (bl - 1) & 255
- d3size = cl + 1
- local cx = ax << 8
- sc_tobuf(d3tile[4], bl, bl, di)
- di = (di - ax) & 0xFFFF
- sc_tobuf(d3tile[3], bl, bl, di)
- di = (di - cx) & 0xFFFF
- sc_tobuf(d3tile[1], bl, bl, di)
- di = (di + ax) & 0xFFFF
- sc_tobuf(d3tile[2], bl, bl, di)
- d3counter2 = d3counter2 - 1
- if d3counter2 ~= 0 then return end
- local ax2 = (d3locd + 0x4377) & 0xFFFF
- ax2 = rol16(ax2, 5)
- local cf = ax2 & 1
- local t = d3loc + ax2 + cf
- local cf2 = t >> 16
- d3loc = t & 0xFFFF
- d3locd = ax2
- local e = (ax2 + d3sizeseed + cf2) & 0xFFFFFFFF
- e = rol32(e, 9)
- d3sizeseed = e
- d3counter2 = d3sizetbl[(e & 7) + 1]
- d3size = 0
- d3counter = (d3counter - 1) & 0xFFFF
- if d3counter == 0 then setnext0() end
- end
- local d4loc, d4locd, d4len, d4lend = 0x7e7e, 0xFFFE, 1, 1
- local function p40()
- local bp = d4loc
- local di, si = bp, bp
- local dl = d4len
- local al = (0x41 - dl) & 255
- local cf = (al < 0x40) and 1 or 0
- al = (al + 0x3f + cf) & 255
- local function put4()
- bput(di, al); bput(di + 1, al); bput(si, al); bput(si + 1, al)
- bput(di + 256, al); bput(di + 257, al); bput(si + 256, al); bput(si + 257, al)
- end
- for _ = 1, dl do
- put4()
- di = (di + 0x202) & 0xFFFF; si = (si - 0x1fe) & 0xFFFF
- end
- if dl - 1 > 0 then
- di = (di - 0x400) & 0xFFFF; si = (si + 0x400) & 0xFFFF
- for _ = 1, dl - 1 do
- put4()
- di = (di - 0x1fe) & 0xFFFF; si = (si + 0x202) & 0xFFFF
- end
- end
- bp = (bp + d4locd) & 0xFFFF
- dl = (dl + d4lend) & 255
- local callnext = false
- if dl == 0 then
- bp = 0x7e7e; dl = 1; d4locd = 0xFFFE; d4lend = 1
- callnext = true
- elseif dl >= 0x42 then
- bp = 0xfe7e; dl = 0x41; d4locd = 2; d4lend = 255
- end
- d4loc, d4len = bp, dl
- if callnext then setnext0() end
- end
- local d5cntr = 255
- local function p50()
- local cn = d5cntr
- local di = cn << 8
- local al = cn & 0x7f
- if al >= 0x40 then al = al ~ 0x7f end
- local ebp = al - 0x20
- local dl = 0
- for _ = 1, 64 do
- for _ = 1, 4 do
- local bx = (SIN0S[dl] * ebp) & ~0xFF
- dl = (dl + 8) & 255
- local ah = ((bx + 0xA000) >> 8) & 255
- local a = (di + bx) & 0xFFFF
- bput(a, ah); bput(a + 256, ah)
- di = di + 1
- end
- end
- d5cntr = d5cntr - 1
- if d5cntr < 0 then d5cntr = 255; setnext0() end
- end
- local d6loc = 0
- local function p60()
- bfill(d6loc << 8, 0x2000, 0)
- d6loc = d6loc + 0x20
- if d6loc >= 0x100 then d6loc = 0; setnext0() end
- end
- local d7loc0, d7loc1, d7sinloc = 0, 0, 0
- local function add4(a)
- local v = bget(a) | (bget(a + 1) << 8) | (bget(a + 2) << 16) | (bget(a + 3) << 24)
- v = (v + 0x04040404) & 0xFFFFFFFF
- bput(a, v & 255); bput(a + 1, (v >> 8) & 255); bput(a + 2, (v >> 16) & 255); bput(a + 3, v >> 24)
- end
- local function p70r0(bl, dh, dl, ch)
- for _ = 1, 4 do
- local cl = SIN0[bl] >> 3
- bl = (bl + 4) & 255
- local di = ((dh << 8) | dl) + cl
- for _ = 1, 15 do
- add4(di); add4(di + 4); add4(di + 8); add4(di + 12)
- di = di + 256
- end
- dh = (dh + ch) & 255
- end
- return bl, dh
- end
- local function p70()
- local bl, dh = p70r0(d7sinloc, d7loc0, 0, 1)
- d7loc0 = dh
- bl = (bl - 16) & 255
- bl, dh = p70r0(bl, d7loc1, 0x80, 255)
- d7loc1 = dh
- d7sinloc = bl
- if dh == 0 then setnext0() end
- end
- local d8tile = 16
- local d8loc, d8locd = 0xe000, 0x2000
- local d8locdtbl = {0x2000, 0x0020, 0xe000, 0xffe0, 0x2000, 0x0020, 0xe000,
- 0xffe0, 0x2000, 0x0020, 0xe000, 0xffe0, 0x2000, 0x0020, 0xe000, 0}
- local d8cntrtbl = {8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1}
- local d8cntr, d8index = 8, 0
- local function p80()
- local di = (d8loc + d8locd) & 0xFFFF
- d8loc = di
- local callnext = false
- d8cntr = d8cntr - 1
- if d8cntr == 0 then
- local ix = (d8index + 1) & 15
- d8index = ix
- d8cntr = d8cntrtbl[ix + 1]
- d8locd = d8locdtbl[ix + 1]
- if ix == 0 then d8loc = 0; callnext = true end
- end
- local tb = d8tile * 1024
- for r = 0, 31 do
- local dst = di + r * 256
- local sp = tb + r * 32 + 1
- for k = 0, 31 do
- bput(dst + k, byte(TILES, sp + k))
- end
- end
- if callnext then setnext0() end
- end
- local d9cntr = 0
- local function p90()
- local dl = d9cntr
- local di = dl << 8
- local al = dl & 0x7f
- local ebx = 0x01010101
- if al & 0x40 ~= 0 then ebx = 0xFEFEFEFF; al = al ~ 0x7f end
- local eax = al * 0x01010101
- dl = (dl + 4) & 255
- d9cntr = dl
- local callnext = (dl == 0)
- for row = 0, 3 do
- local b0, b1, b2, b3 = eax & 255, (eax >> 8) & 255, (eax >> 16) & 255, (eax >> 24) & 255
- if b0 == b1 and b1 == b2 and b2 == b3 then
- bfill(di + row * 256, 256, b0)
- else
- local a = di + row * 256
- for q = 0, 63 do
- bput(a, b0); bput(a + 1, b1); bput(a + 2, b2); bput(a + 3, b3); a = a + 4
- end
- end
- eax = (eax + ebx) & 0xFFFFFFFF
- end
- if callnext then setnext0() end
- end
- local function delay0()
- delaycntr = (delaycntr - 1) & 0xFFFF
- if delaycntr == 0 then setnext0() end
- end
- local function waitpals() if slide == nil then setnext0() end end
- local function tiles4(a, b, c, d) d3tile = {a, b, c, d} end
- local function m00() if palnexts(0) then return end setnext0() end
- local function m01() if palnexts(1) then return end setnext0() end
- local function m02() if set_palso(0, 64, ZERO) then return end setnext0() end
- local function m03() if palnexts(2) then return end setnext0() end
- local function m04()
- if set_palso(192, 64, getpal0a(pal0aptr)) then return end
- if palnext(1) then return end
- setnext0()
- end
- local function m05()
- if palnexts(2) then return end
- tiles4(0, 1, 2, 3); d3counter = 0x10; delaycntr = 2
- setnext0()
- end
- local function m06()
- l1on = true
- if set_palso(128, 64, ZERO) then return end
- d3counter = 0x20
- setnext0()
- end
- local function m07() tiles4(4, 5, 6, 7); d3counter = 0x40; setnext0() end
- local function m08() if palnexts(1) then return end delaycntr = 0x80; setnext0() end
- local function m09()
- l2on = true
- if palnext(2) then return end
- if palnexts(1) then return end
- setnext0()
- end
- local function m0a() tiles4(8, 9, 10, 11); d3counter = 0x10; delaycntr = 0x40; setnext0() end
- local function m0b() delaycntr = 0x40; setnext0() end
- local function m0c() if set_palso(0, 192, ZERO) then return end setnext0() end
- local function m0d() if palnext(0) then return end delaycntr = 0x40; setnext0() end
- local function m0e()
- if palnext(1) then return end
- tiles4(12, 13, 14, 15); d3counter = 0x10; delaycntr = 0x40
- setnext0()
- end
- local function m0f() if palnext(2) then return end d8tile = 16; delaycntr = 0x40; setnext0() end
- local function m10() tiles4(17, 18, 19, 20); d3counter = 0x10; setnext0() end
- local function m11()
- if palnext(0) then return end
- if set_palso(128, 64, ZERO) then return end
- d3counter = 0x40; delaycntr = 0x40
- setnext0()
- end
- local function m12()
- if set_palso(64, 64, getpal(palptrtbl[palindex + 1], 63, 64)) then return end
- setnext0()
- end
- local function m13() if palnext(2) then return end setnext0() end
- local function m14()
- if set_palo(0, 64, ZERO) then return end
- if set_palso(128, 64, ZERO) then return end
- setnext0()
- end
- local function m15()
- if palnexts(0) then return end
- tiles4(21, 22, 23, 24); d3counter = 0x20; delaycntr = 0x80
- setnext0()
- end
- local function m16() tiles4(25, 26, 27, 28); d3counter = 0x10; delaycntr = 0x40; setnext0() end
- routtbl = {m00, p00, m01, p10, m02, waitpals,
- m03, p20, m04, waitpals, m05,
- delay0, p30, m06, p30, m07, p30, m08, waitpals, p40, delay0, m09,
- m0a, p30, delay0, p50, m0b, delay0, m0c, waitpals, p60, m0d, p70,
- delay0, m0e, p30, delay0, m0f, p80, delay0, m10, p30, m11, p30, p90,
- delay0, m12, p70, m13, p20, m14, waitpals, p60, m15, p30, delay0,
- m16, p30, delay0}
- ROUTTBLLEN = #routtbl
- ROUTTBLSTART = 6
- l0rout = m00
- end
- local gnbg_update, gnbg_render
- do
- local RAYS = {}
- do
- local rowmap = {}
- for j = 0, HS - 1 do rowmap[j] = (j * 50) // HS end
- local cano = {}
- for k = 0, 319 do
- local x, y = 0, 0
- for j = 0, 49 do
- local dx = byte(RAYSTR, k * 100 + j + 1)
- local dy = byte(RAYSTR, k * 100 + 50 + j + 1)
- if dx > 127 then dx = dx - 256 end
- if dy > 127 then dy = dy - 256 end
- x = x + dx; y = y + dy
- cano[j] = (y * 256 + x) & 0xFFFF
- end
- for j = 0, HS - 1 do RAYS[k * HS + j + 1] = cano[rowmap[j]] end
- end
- RAYSTR = nil
- local r = {}
- for j = 0, HS - 1 do r[j] = rowmap[j] * 2 end
- RAYS.rowr = r
- end
- local vpdir, vploc = 0, 0x8080
- local skewD = {}
- for i = 0, 99 do skewD[i] = 0 end
- local skewSK = {}
- for j = 1, HS do skewSK[j] = 0 end
- local skewptr, skewcounter, skewmode, skewindex = 0, 0x10f, 0, 3
- local skewtbl = {1, -3, 5, -3}
- local mtblvpdir = {5, 0, 0xe7, 0xf0, 0, 5, -7, 6, -5, 9, -6, 7, -9}
- local mtblvpy = {3, 0, 0xc0, 0xc0, 0, 3, -1, 5, -3, 1, -5, 1, -3}
- local mtblvpx = {1, 0, 0x60, 0xc0, 0, 1, -5, 1, -3, 3, -1, 5, -3}
- local function drawr0(t)
- local al = t[1]
- if t[2] == 0 then
- local bl = (t[3] - 1) & 255
- if bl ~= 0 then t[3] = bl; return al end
- t[5] = (t[5] + 1) & 7
- t[2] = 1
- t[3] = t[4]
- return al
- else
- local tg = t[6 + t[5]]
- if al == tg then t[2] = 0; return al end
- if al < tg then al = al + 1 else al = al - 1 end
- t[1] = al
- return al
- end
- end
- gnbg_update = function()
- if skewmode == 0 then
- skewcounter = (skewcounter - 1) & 0xFFFF
- if skewcounter == 0 then
- skewcounter = 0x175; skewmode = 1; skewindex = (skewindex + 1) & 3
- end
- else
- skewD[skewptr] = skewD[skewptr] + skewtbl[skewindex + 1]
- skewptr = skewptr + 1
- if skewptr >= 100 then skewptr = 0; skewmode = 0 end
- end
- local dh, dl = (vploc >> 8) & 255, vploc & 255
- dh = (dh + drawr0(mtblvpy)) & 255
- dl = (dl + drawr0(mtblvpx)) & 255
- vploc = (dh << 8) | dl
- local d = drawr0(mtblvpdir)
- local ax = d + vpdir
- if ax >= 320 then ax = ax - 320 elseif ax < 0 then ax = ax + 320 end
- vpdir = ax
- end
- gnbg_render = function()
- do
- local ps, acc = {}, 0
- for r = 0, 99 do acc = acc + skewD[r]; ps[r] = acc end
- local rr = RAYS.rowr
- for j = 1, HS do skewSK[j] = ps[rr[j - 1]] end
- end
- local loc, dir = vploc, vpdir
- local SK = skewSK
- local last = (H - 1) * W
- for cx = 0, W - 1 do
- local c = (cx * 320) // W
- local rb = ((dir + c) % 320) * HS
- local top, bot = cx + 1, last + cx + 1
- for j = 1, HS do
- local off = (loc + RAYS[rb + j] + SK[j]) & 0xFFFF
- local v = (buf[(off >> 3) + 1] >> ((off & 7) << 3)) & 255
- scr[top] = v; scr[bot] = v
- top = top + W; bot = bot - W
- end
- end
- end
- end
- local function spr(id, L)
- if not DRAWING then return end
- local p = SPRO[id]
- local n = byte(SPRS, p) | (byte(SPRS, p + 1) << 8)
- p = p + 2
- for _ = 1, n do
- local dy, x0, len = byte(SPRS, p, p + 2)
- p = p + 3
- local a = L + dy * 400 + x0
- local y = a // 400
- if y >= 0 and y < 200 then
- local x = a - y * 400
- local gy = (y * H) // 200
- local rowb = gy * W + 1
- for k = 0, len - 1 do
- local xx = x + k
- if xx < 320 then
- if xx >= 0 then scr[rowb + (xx * W) // 320] = byte(SPRS, p + k) end
- end
- end
- else
- for k = 0, len - 1 do
- local aa = a + k
- local yy = aa // 400
- if yy >= 0 and yy < 200 then
- local xx = aa - yy * 400
- if xx < 320 then scr[((yy * H) // 200) * W + (xx * W) // 320 + 1] = byte(SPRS, p + k) end
- end
- end
- end
- p = p + len
- end
- end
- local function dotput(o, mask, color)
- if not DRAWING then return end
- local y = o // 100
- if y < 0 or y >= 200 then return end
- local xb = o - y * 100
- local rowb = ((y * H) // 200) * W + 1
- for p = 0, 3 do
- if mask & (1 << p) ~= 0 then
- local x = xb * 4 + p
- if x < 320 then scr[rowb + (x * W) // 320] = color end
- end
- end
- end
- local l1rout
- do
- local l1routtbl, l1index = nil, 0
- local l1fn = {}
- local L1SEQ = {0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 0, 2, 3, 4, 6, 5, 1, 8, 7, 9,
- 3, 4, 5, 6, 0, 8, 1, 2, 9, 7}
- local function setnext1()
- local i = l1index + 1
- if i >= #L1SEQ then i = 0 end
- l1rout = l1fn[L1SEQ[i + 1]]
- l1index = i
- end
- local d0spr = {2, 1, 0}
- local d0csprloctbl = {400 * 168 + 320, 400 * 200, -32, 400 * -32 + 288}
- local d0csprdtbl = {-4, -1600, 4, 1600}
- local d0csprcntrtbl = {88, 58, 88, 58}
- local d0l, d0d, d0i, d0c, d0n = 400 * 168 + 320, -4, 0, 88, 0
- l1fn[0] = function()
- d0l = d0l + d0d
- local bl = d0i - 1
- if bl < 0 then bl = 2 end
- d0i = bl
- spr(d0spr[bl + 1], d0l)
- d0c = (d0c - 1) & 255
- if d0c ~= 0 then return end
- d0n = (d0n + 1) & 3
- d0l = d0csprloctbl[d0n + 1]; d0d = d0csprdtbl[d0n + 1]; d0c = d0csprcntrtbl[d0n + 1]
- setnext1()
- end
- local d1seed = 0x974ADEC2
- local fx, fy, ff = {}, {}, {}
- for i = 0, 9 do fx[i] = 0; fy[i] = 0; ff[i] = 0 end
- local yadd = {-100, 0, 0, 100}
- local fendcntr, finitcntr, finitcntr2 = 10, 10, 1
- l1fn[1] = function()
- local ecx = d1seed
- local esi = 9
- while esi >= 0 do
- local edi = fx[esi] - 3
- local skip = false
- if edi < 0 then
- skip = true
- else
- fx[esi] = edi
- if edi == 0 then
- fendcntr = fendcntr - 1
- if fendcntr ~= 0 then
- skip = true
- else
- fendcntr = 10; finitcntr = 10
- setnext1(); return
- end
- end
- end
- if not skip then
- local ebx = yadd[(ecx & 3) + 1] + fy[esi]
- local edx = fy[esi]
- if not (ebx > 100 * 183 or ebx < 0) then edx = ebx end
- fy[esi] = edx & 0xFFFF
- ecx = ror32(ecx, 11)
- ecx = (ecx + 0x12345671 + ((ecx >> 31) & 1)) & 0xFFFFFFFF
- ff[esi] = ff[esi] ~ 1
- spr(3 + ff[esi], edx * 4 + edi - 20)
- end
- ecx = (ecx + esi) & 0xFFFFFFFF
- esi = esi - 1
- end
- local edx = finitcntr - 1
- if edx >= 0 then
- finitcntr2 = (finitcntr2 - 1) & 255
- if finitcntr2 == 0 then
- finitcntr = edx
- finitcntr2 = (ecx & 15) + 4
- fx[edx] = 342
- fy[edx] = ((((ecx >> 8) & 0x7f) + 27) * 100) & 0xFFFF
- ecx = ror32(ecx, 5)
- ecx = (ecx + 0x59f4132f + ((ecx >> 31) & 1)) & 0xFFFFFFFF
- end
- end
- d1seed = ecx
- end
- local sluggytbl = {8, 9, 10, 9, 8, 7}
- sluggytbl = {6, 7, 8, 7, 6, 5}
- local sluggyofs = {9, 5, 0, 0, 0, 0}
- local s2f, s2y, s2x = 5, 233, 0x71
- l1fn[2] = function()
- local bl = s2f
- local y = s2y - sluggyofs[bl + 1]
- local L = (y - 29) * 400 + s2x + 24
- spr(sluggytbl[bl + 1], L)
- bl = bl - 1
- if bl < 0 then
- bl = 5
- local ny = s2y - 13
- s2y = ny & 255
- if not (ny > 0) then
- s2y = 233
- s2x = (s2x + 0x6f) & 255
- s2f = bl
- setnext1()
- return
- end
- end
- s2f = bl
- end
- local d3hseed = 0x9693972E
- local hL = {}
- for i = 0, 15 do hL[i] = 0 end
- local hidx, hmloc = 0, -80
- l1fn[3] = function()
- for esi = 15, 0, -1 do spr(9, hL[esi]) end
- local ebp = d3hseed
- local edx = (hidx + 1) & 15
- hidx = edx
- local ebx = hmloc
- local eax = (ebp & 0x3f) + ebx
- if eax >= 320 then eax = 320 end
- local ecx = (ebp >> 6) & 255
- if ecx >= 188 then ecx = ecx - 156 end
- ecx = ecx * 400 + eax + 400
- hL[edx] = ecx
- ebp = ror32(ebp, 9)
- ebp = (ebp + edx + 0x123457) & 0xFFFFFFFF
- ebx = ebx + 7
- local callnext = false
- if ebx >= 320 + 7 * 16 then callnext = true; ebx = -80 end
- d3hseed = ebp; hmloc = ebx
- if callnext then setnext1() end
- end
- local w4loc = 0
- local function r0a()
- w4loc = (w4loc + 2) & 0xFFFF
- local edx = w4loc - 50
- if edx < 0 then return 0, 0, 0 end
- return edx, (SIN0[edx & 255] >> 1) + 131, 0
- end
- local function r0b()
- local dx = w4loc
- if dx == 276 then return 0, 0, 1 end
- if dx >= 226 then return 0, 0, 0 end
- return dx, (SIN0[(dx - 178) & 255] >> 1) + 131, 0
- end
- local function r1a()
- w4loc = (w4loc + 3) & 0xFFFF
- local ebx = w4loc - 80
- if ebx < 0 then return 0, 0, 0 end
- return (SIN0[ebx & 255] >> 1) + 49, ebx, 0
- end
- local function r1b()
- local ebx = w4loc
- if ebx >= 472 then return 0, 0, 1 end
- if ebx >= 392 then return 0, 0, 0 end
- return (SIN0[(ebx - 208) & 255] >> 1) + 49, ebx, 0
- end
- local function r2a()
- w4loc = (w4loc + 2) & 0xFFFF
- local dx = w4loc - 50
- if dx < 0 then return 0, 0, 0 end
- local x = (SIN0[dx & 255] >> 1) + 131
- local y = (dx & ~255) | ((226 - (dx & 255)) & 255)
- return y, x, 0
- end
- local function r2b()
- local dx = w4loc
- if dx == 276 then return 0, 0, 1 end
- if dx >= 226 then return 0, 0, 0 end
- local x = (SIN0[(dx - 178) & 255] >> 1) + 131
- local y = (dx & ~255) | ((224 - (dx & 255)) & 255)
- return y, x, 0
- end
- local function r3a()
- w4loc = (w4loc + 3) & 0xFFFF
- local ebx = w4loc - 78
- if ebx < 0 then return 0, 0, 0 end
- return (SIN0[ebx & 255] >> 1) + 49, 396 - ebx, 0
- end
- local function r3b()
- local ebx = w4loc
- if ebx >= 474 then return 0, 0, 1 end
- if ebx >= 396 then return 0, 0, 0 end
- return (SIN0[(ebx - 206) & 255] >> 1) + 49, 393 - ebx, 0
- end
- local pos4tbl0 = {r0a, r1a, r2a, r3a, r0a, r1a, r2a, r3a}
- local pos4tbl1 = {r0b, r1b, r2b, r3b, r2b, r3b, r0b, r1b}
- local pos4 = {r0a, r0b}
- local d4frame = {0, 2}
- local d4wing = {11, 12, 13, 12}
- local d4centertbl = {10, 23, 17, 16, 34}
- local d4center, d4posi, d4centeri = 10, 0, 0
- local function wing(esi)
- local y, x, cf = pos4[esi + 1]()
- local Lw = (y - 26) * 400 + x - 72
- local f = (d4frame[esi + 1] + 1) & 3
- d4frame[esi + 1] = f
- spr(d4wing[f + 1], Lw)
- spr(d4center, Lw + 3625)
- return cf
- end
- l1fn[4] = function()
- wing(0)
- local cf = wing(1)
- if cf == 0 then return end
- d4posi = (d4posi + 1) & 7
- pos4[1] = pos4tbl0[d4posi + 1]; pos4[2] = pos4tbl1[d4posi + 1]
- w4loc = 0
- d4centeri = d4centeri + 1
- if d4centeri >= 5 then d4centeri = 0 end
- d4center = d4centertbl[d4centeri + 1]
- setnext1()
- end
- local H5 = {[0]=37,36,36,35,34,33,33,32,31,30,30,29,28,28,27,26,26,25,24,24,23,23,22,21,21,20,20,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,11,11,10,10,10,9,9,8,8,8,7,7,6,6,6,5,5,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,3,3,3,3,4,4,4,5,5,5,5,6,6,6,7,7,8,8,8,9,9,10,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,20,20,21,21,22,23,23,24,24,25,26,26,27,28,28,29,30,30,31,32,33,33,34,35,36,36,37}
- local d5loc, d5i, d5cur = 372, 0, 14
- local d5tbl = {14, 15, 18, 19, 20, 21}
- local d5callnext
- l1fn[5] = function()
- local ebx = d5loc - 2
- local callnext = false
- if ebx == 0 then
- d5i = d5i + 1; if d5i >= 6 then d5i = 0 end
- d5cur = d5tbl[d5i + 1]
- ebx = 372; callnext = true
- end
- d5loc = ebx
- local h = H5[ebx >> 1]
- spr(d5cur, (h + 15) * 400 + ebx - 52)
- if callnext then setnext1() end
- end
- local function mkdots(n, t0, t1, t2, t3, dec1, mod2, dec3, wmul, mask0, maskfn)
- local o, m, c = {}, {}, {}
- local t4 = mask0
- for i = 1, n do
- o[i] = (t0 * 100 + t2 * wmul) & 0xFFFF
- m[i] = t4 or 0
- c[i] = (t2 + 1) & 255
- t0 = t0 + t1
- if t0 > 199 then t0 = t0 - 200; t1 = t1 - dec1 end
- t2 = t2 + t3
- if t2 > mod2 then t2 = t2 - (mod2 + 1); t3 = t3 - dec3 end
- if maskfn then t4 = maskfn(t4) end
- end
- return {o = o, m = m, c = c, n = n}
- end
- local function cyc(v) if v == 0x11 then return 0x22 elseif v == 0x22 then return 0x44 elseif v == 0x44 then return 0x88 else return 0x11 end end
- local D6 = {
- mkdots(64, 0, 79, 0, 67, 3, 79, 4, 1, 0x11, cyc),
- mkdots(32, 56, 95, 49, 59, 6, 79, 5, 1, 0x33, function(v) return v ~ 0xFF end),
- mkdots(16, 132, 96, 13, 73, 8, 79, 7, 1, 0, nil)}
- local D8 = {
- mkdots(64, 192, 188, 53, 37, 8, 79, 7, 1, 0, nil),
- mkdots(32, 64, 96, 25, 31, 8, 39, 3, 2, 0, nil),
- mkdots(16, 132, 96, 13, 13, 8, 19, 2, 4, 0, nil)}
- local function nums(state)
- local al = (state.cntr - 1) & 255
- if al == 0 then
- state.cntr = 0xF0; state.num = 0; state.numd = 1
- return nil
- end
- state.cntr = al
- local ch, cl = state.num, state.numd
- if al == 0x10 then cl = -1; state.numd = cl end
- ch = (ch + cl) & 255
- if ch == 0 or ch >= 0x10 then state.numd = 0 end
- state.num = ch
- return ch
- end
- local S6 = {cntr = 0xF0, num = 0, numd = 1}
- l1fn[6] = function()
- local ch = nums(S6)
- if not ch then setnext1(); return end
- local COL = 0xC7
- do
- local g = D6[3]
- for k = 0, 15 do
- local cl = 16 - k
- local bx = (g.o[k + 1] + 400) & 0xFFFF
- if bx >= 20000 then bx = (bx - 20000) & 0xFFFF end
- local ebx = bx - 1
- local cnt = (g.c[k + 1] - 1) & 255
- if cnt == 0 then cnt = 80; ebx = ebx + 80 end
- g.c[k + 1] = cnt
- g.o[k + 1] = ebx & 0xFFFF
- if cl <= ch then
- dotput(ebx, 6, COL); dotput(ebx + 300, 6, COL)
- dotput(ebx + 100, 15, COL); dotput(ebx + 200, 15, COL)
- end
- end
- end
- ch = (ch * 2) & 255
- do
- local g = D6[2]
- for k = 0, 31 do
- local cl = 32 - k
- local bx = (g.o[k + 1] + 200) & 0xFFFF
- if bx >= 20000 then bx = (bx - 20000) & 0xFFFF end
- local ebx = bx
- local al = g.m[k + 1] ~ 0xFF
- if al >= 0x80 then
- ebx = ebx - 1
- local cnt = (g.c[k + 1] - 1) & 255
- if cnt == 0 then cnt = 80; ebx = ebx + 80 end
- g.c[k + 1] = cnt
- end
- g.o[k + 1] = ebx & 0xFFFF
- g.m[k + 1] = al
- if cl <= ch then
- dotput(ebx, al & 15, COL); dotput(ebx + 100, al & 15, COL)
- end
- end
- end
- ch = (ch * 2) & 255
- do
- local g = D6[1]
- for k = 0, 63 do
- local cl = 64 - k
- local bx = (g.o[k + 1] + 100) & 0xFFFF
- if bx >= 20000 then bx = (bx - 20000) & 0xFFFF end
- local ebx = bx
- local al = g.m[k + 1]
- local cf = al & 1
- al = (al >> 1) | (cf << 7)
- if cf == 1 then
- ebx = ebx - 1
- local cnt = (g.c[k + 1] - 1) & 255
- if cnt == 0 then cnt = 80; ebx = ebx + 80 end
- g.c[k + 1] = cnt
- end
- g.o[k + 1] = ebx & 0xFFFF
- g.m[k + 1] = al
- if cl <= ch then dotput(ebx, al & 15, COL) end
- end
- end
- end
- local d7x, d7xd = 0, 2
- local d7cl, d7ch, d7bl, d7bh = 0x40, 0x40, -1, -1
- local d7i, d7cnt, d7phase = 0, 3, 0
- local d7tbl = {22, 10, 23}
- local d7cur = 22
- l1fn[7] = function()
- local eax = d7x + d7xd
- d7x = eax
- if eax == 0 or eax >= 470 or eax < 0 then
- d7xd = -d7xd
- d7i = d7i + 1; if d7i >= 3 then d7i = 0 end
- d7cur = d7tbl[d7i + 1]
- setnext1(); return
- end
- local cl, ch, bl, bh = d7cl, d7ch, d7bl, d7bh
- cl = (cl + bl) & 255
- if cl == 0x10 or cl == 0x40 then bl = -bl end
- d7cnt = d7cnt - 1
- if d7cnt == 0 then
- d7cnt = 3
- ch = (ch + bh) & 255
- if ch == 0x10 or ch == 0x40 then bh = -bh end
- end
- d7cl, d7ch, d7bl, d7bh = cl, ch, bl, bh
- local ybase = 0x40 - cl
- d7phase = (d7phase + 5) & 255
- local b = d7phase
- for _ = 0, 7 do
- local rows = (SIN0[b] * cl) >> 7
- b = (b + 0x40) & 255
- local x = ((SIN0[b] * ch) >> 7) + d7x - 128
- if x >= 0 and x < 340 then
- spr(d7cur, (rows + ybase + 26) * 400 + x - 20)
- end
- b = (b - 32) & 255
- end
- end
- local S8 = {cntr = 0xF0, num = 0, numd = 1}
- local function plot16(ebx, step, n)
- end
- l1fn[8] = function()
- local ch = nums(S8)
- if not ch then setnext1(); return end
- local COL = 0xD9
- do
- local g = D8[3]
- for k = 0, 15 do
- local cl = 16 - k
- local bx = (g.o[k + 1] + 1600) & 0xFFFF
- if bx >= 100 * 208 then bx = (bx - 20000) & 0xFFFF end
- local ebx = bx - 4
- local cnt = (g.c[k + 1] - 1) & 255
- if cnt == 0 then cnt = 20; ebx = ebx + 80 end
- g.c[k + 1] = cnt
- g.o[k + 1] = ebx & 0xFFFF
- if cl <= ch then
- for p = 0, 3 do
- local m = 1 << p
- local base = ebx - 100 * p
- dotput(base, m, COL); dotput(base - 400 + 1, m, COL)
- dotput(base - 800 + 2, m, COL); dotput(base - 1200 + 3, m, COL)
- end
- end
- end
- end
- ch = (ch * 2) & 255
- do
- local g = D8[2]
- for k = 0, 31 do
- local cl = 32 - k
- local bx = (g.o[k + 1] + 800) & 0xFFFF
- if bx >= 20000 then bx = (bx - 20000) & 0xFFFF end
- local ebx = bx - 2
- local cnt = (g.c[k + 1] - 1) & 255
- if cnt == 0 then cnt = 40; ebx = ebx + 80 end
- g.c[k + 1] = cnt
- g.o[k + 1] = ebx & 0xFFFF
- if cl <= ch then
- for p = 0, 3 do
- local m = 1 << p
- local base = ebx - 100 * p
- dotput(base, m, COL); dotput(base - 400 + 1, m, COL)
- end
- end
- end
- end
- ch = (ch * 2) & 255
- do
- local g = D8[1]
- for k = 0, 63 do
- local cl = 64 - k
- local bx = (g.o[k + 1] + 400) & 0xFFFF
- if bx >= 20000 then bx = (bx - 20000) & 0xFFFF end
- local ebx = bx - 1
- local cnt = (g.c[k + 1] - 1) & 255
- if cnt == 0 then cnt = 80; ebx = ebx + 80 end
- g.c[k + 1] = cnt
- g.o[k + 1] = ebx & 0xFFFF
- if cl <= ch then
- for p = 0, 3 do dotput(ebx - 100 * p, 1 << p, COL) end
- end
- end
- end
- end
- local d9frame = {24, 25, 25, 26, 26, 27, 27, 28, 29, 30, 30, 31, 31, 32, 32, 33}
- local leafx, leafy = {}, {}
- do
- local t0, t1 = 152, 187
- for i = 0, 23 do
- leafx[i] = t0
- t0 = t0 + t1
- if t0 > 333 then t0 = t0 - 334; t1 = t1 - 17 end
- end
- t0, t1 = 137, 167
- for i = 0, 23 do
- leafy[i] = t0 & 255
- t0 = t0 + t1
- if t0 > 209 then t0 = t0 - 210; t1 = t1 - 11 end
- end
- end
- local d9ph0, d9ph1 = 0, 0
- local d9cntr, d9num, d9numd = 0xF0, 0, 1
- l1fn[9] = function()
- local al = (d9cntr - 1) & 255
- if al == 0 then
- d9cntr = 0xF0; d9num = 0; d9numd = 1
- for i = 1, 8 do d9frame[i], d9frame[i + 8] = d9frame[i + 8], d9frame[i] end
- setnext1(); return
- end
- d9cntr = al
- local bh, bl = d9num, d9numd
- if al == 23 then bl = -1; d9numd = bl end
- bh = (bh + bl) & 255
- if bh == 0 or bh >= 23 then d9numd = 0 end
- d9num = bh
- local cl = (d9ph0 + 7) & 255
- local ch = (d9ph1 + 13) & 255
- d9ph0, d9ph1 = cl, ch
- for esi = bh, 0, -1 do
- local y = leafy[esi]
- local a = (SIN0[(cl + y) & 255] >> 6) + 1
- y = y + a
- if y >= 210 then y = y - 210 end
- leafy[esi] = y
- local x = leafx[esi]
- local v = SIN0[(ch + (x & 255)) & 255]
- local edx = v >> 5
- local mv = (edx >> 1) + 1
- x = x - mv
- if x < 0 then x = x + 334 end
- leafx[esi] = x
- spr(d9frame[edx + 1], (y - 9) * 400 + x - 13)
- local t = ((ch << 8) | cl) + 0x11b
- cl = t & 255; ch = (t >> 8) & 255
- end
- end
- l1rout = function() if l1on then l1rout = l1fn[0] end end
- end
- local l2rout
- do
- local l2fn = {}
- local L2SEQ = {0, 2, 1, 3}
- local l2index = 0
- local function setnext2()
- local i = l2index + 1
- if i >= #L2SEQ then i = 0 end
- l2rout = l2fn[L2SEQ[i + 1]]
- l2index = i
- end
- local p0y, p0yd, p0xi = 251, -1, 0
- local p1x, p1xd, p1y, p1yd = 0, 2, 80, 0
- local p2x, p2xd, p2i = 0, 2, 0
- local lasty = 93
- local posroutindex = 0
- local pos0, pos1, pos2
- local posrout
- local function posd()
- posroutindex = (posroutindex + 1) % 3
- posrout = (posroutindex == 0 and pos0) or (posroutindex == 1 and pos1) or pos2
- end
- pos0 = function()
- local bl = (p0xi + 3) & 255
- p0xi = bl
- local x = (SIN0[bl] >> 1) + 127
- local y = p0y + p0yd
- p0y = y
- lasty = y
- if y == 0 or y == 251 then p0yd = -p0yd; posd(); return x, y, 1 end
- return x, y, 0
- end
- pos1 = function()
- local edx = p1y + p1yd
- local eax = p1yd + 1
- if (edx & 255) >= 200 then eax = -(eax - 1) end
- p1y = edx & 255
- p1yd = ((eax + 128) & 255) - 128
- local ebx = p1x + p1xd
- p1x = ebx & 0xFFFF
- lasty = edx
- if ebx == 0 or ebx == 384 then p1xd = -p1xd; posd(); return ebx, edx, 1 end
- return ebx, edx, 0
- end
- pos2 = function()
- local ebx = p2x + p2xd
- p2x = ebx & 0xFFFF
- if ebx == 0 or ebx >= 448 then p2xd = -p2xd; posd(); return ebx, lasty, 1 end
- local cl = (p2i + 7) & 255
- p2i = cl
- ebx = ebx + (SIN0[cl] >> 2) - 64
- if ebx > 384 or ebx < 0 then ebx = 0 end
- cl = (cl + 0x40) & 255
- local edx = (SIN0[cl] >> 2) + 93
- lasty = edx
- return ebx, edx, 0
- end
- posrout = pos0
- local TI, TV = {}, {}
- local NSHAPE = #LS // 2
- local function lens_draw(kind, lx, ly, src)
- if not DRAWING then return end
- local OX, OY = lx - 63, ly - 51
- local n, ci = 0, 0
- for i = 1, NSHAPE do
- local X, Y = byte(LS, 2 * i - 1, 2 * i)
- local z = X >= 128
- if z then X = X - 128 else ci = ci + 1 end
- local px, py = OX + X, OY + Y
- if px >= 0 and px < 320 and py >= 0 and py < 200 then
- local gx, gy = (px * W) // 320, (py * H) // 200
- local di = gy * W + gx + 1
- local v
- if z then v = 0
- elseif kind == 0 then v = bget(src + Y * 256 + X)
- elseif kind == 1 then v = L2TBL[scr[di]]
- elseif kind == 2 then v = scr[(((199 - py) * H) // 200) * W + gx + 1]
- else
- local col, row = byte(LSRC, 2 * ci - 1, 2 * ci)
- v = scr[((row * H) // 200) * W + ((col * 4 + 1) * W) // 320 + 1]
- end
- n = n + 1; TI[n] = di; TV[n] = v
- end
- end
- for q = 1, n do scr[TI[q]] = TV[q] end
- end
- local d2off = 0
- l2fn[0] = function()
- local x, y, cf = posrout()
- local si = d2off
- if cf == 1 then d2off = (si + 0x5f31) & 0xFFFF end
- local src = si + (((y & 255) << 8) | (x & 255))
- lens_draw(0, x, y, src)
- if cf == 1 then setnext2() end
- end
- local function mklens(kind)
- return function()
- local x, y, cf = posrout()
- if cf == 1 then setnext2(); return end
- lens_draw(kind, x, y, 0)
- end
- end
- l2fn[1] = mklens(1)
- l2fn[2] = mklens(2)
- l2fn[3] = mklens(3)
- l2rout = function() if l2on then l2rout = l2fn[0] end end
- end
- local BRAILLE = {{0x01, 0x08}, {0x02, 0x10}, {0x04, 0x20}, {0x40, 0x80}}
- local function draw_end(f)
- local QG = {}
- for v = 0, 255 do
- local g = floor(v * f + 0.5)
- QG[v] = quant(g, g, g)
- end
- local setfg, setbg, set = gpu.setForeground, gpu.setBackground, gpu.set
- local fgc, bgc = -1, -1
- target_begin()
- local utf8char = utf8.char
- local sample = {}
- for cy = 0, HC - 1 do
- local cx = 0
- local pk, pc, pf, pb, pstart = nil, nil, nil, nil, 0
- local line = {}
- local function flush(endx)
- if pc then
- local n = endx - pstart
- if pc == " " then
- if bgc ~= pb then setbg(pb); bgc = pb end
- else
- if fgc ~= pf then setfg(pf); fgc = pf end
- if bgc ~= pb then setbg(pb); bgc = pb end
- end
- set(pstart + 1, cy + 1, rep(pc, n))
- end
- end
- for x = 0, WC - 1 do
- local mn, mx = 99, -1
- for j = 0, 3 do
- local sy = ((cy * 4 + j) * 200) // (HC * 4)
- for i = 0, 1 do
- local sx = ((x * 2 + i) * 320) // (WC * 2)
- local nidx = sy * 320 + sx
- local v = byte(ENDP, (nidx >> 1) + 1)
- if nidx & 1 == 0 then v = v >> 4 else v = v & 15 end
- sample[j * 2 + i + 1] = v
- if v < mn then mn = v end
- if v > mx then mx = v end
- end
- end
- local ch, fg, bg
- if mn == mx then
- ch = " "; bg = QG[floor(mn * 16.2 + 0.5)]; fg = bg
- else
- local thr = (mn + mx) / 2
- local bits, sl, nl, su, nu = 0, 0, 0, 0, 0
- for j = 0, 3 do
- for i = 0, 1 do
- local v = sample[j * 2 + i + 1]
- if v > thr then bits = bits | BRAILLE[j + 1][i + 1]; sl = sl + v; nl = nl + 1
- else su = su + v; nu = nu + 1 end
- end
- end
- ch = utf8char(0x2800 + bits)
- fg = QG[floor(sl / nl * 16.2 + 0.5)]
- bg = QG[floor(su / nu * 16.2 + 0.5)]
- end
- local key = ch
- if pc == ch and pb == bg and (ch == " " or pf == fg) then
- else
- flush(x)
- pc, pf, pb, pstart = ch, fg, bg, x
- end
- end
- flush(WC)
- end
- target_end()
- end
- local STEP_HZ = 70 / 3
- local quit_req = false
- local function handle_event(ev, a, b, c)
- if ev == "key_down" then
- if c == 1 or b == 113 or b == 81 or b == 3 then quit_req = true end
- elseif ev == "interrupted" then
- quit_req = true
- end
- end
- local function logic_step(drawing)
- DRAWING = drawing
- l0rout()
- gnbg_update()
- if drawing then gnbg_render() end
- l1rout()
- l2rout()
- slide_tick(); slide_tick(); slide_tick()
- end
- local function frame_loop(stop)
- local last = computer.uptime()
- local acc = 1
- while true do
- local now = computer.uptime()
- acc = acc + (now - last) * STEP_HZ
- last = now
- local n = floor(acc)
- if n < 1 then n = 1 end
- acc = acc - n
- if acc < 0 then acc = 0 end
- if n > OPT.maxsteps then n = OPT.maxsteps end
- for i = 1, n do logic_step(i == n) end
- present()
- local wait = (1 - acc) / STEP_HZ
- handle_event(computer.pullSignal(wait > 0 and wait or 0))
- if stop() then return end
- end
- end
- local function pause(sec)
- local t = computer.uptime() + sec
- while computer.uptime() < t and not quit_req do
- handle_event(computer.pullSignal(0.05))
- end
- end
- local function main()
- frame_loop(function() return quit_req or finish_req end)
- quit_req = false
- ending = true
- pal_slide(0, 256, ZERO)
- frame_loop(function() return slide == nil end)
- if not OPT.skipend then
- quit_req = false
- local steps = vram and 8 or 3
- pcall(gpu.setBackground, 0)
- pcall(gpu.fill, 1, 1, WC, HC, " ")
- for k = 1, steps do draw_end(k / steps) end
- local t = computer.uptime() + 768 / 70
- while computer.uptime() < t and not quit_req do
- handle_event(computer.pullSignal(0.1))
- end
- for k = steps - 1, 0, -1 do draw_end(k / steps) end
- end
- end
- local ok, err = pcall(main)
- gpu_restore()
- if not ok then error(err, 0) end
- if print then
- print("Timeless: Copywrong (c) 1994, Tran (a.k.a. Thomas Pytel).")
- print("OpenComputers port. Cogito ergo sum... NOT!")
- end
Add Comment
Please, Sign In to add comment