Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local event = require("event")
- local internet = require("internet")
- local unicode = require("unicode")
- local gpu = component.gpu
- local w, h = gpu.getResolution()
- local floor = math.floor
- local ceil = math.ceil
- local byte = string.byte
- local uchar = unicode.char
- local min = math.min
- local max = math.max
- local vram_w = w * 2
- local vram_h = h * 4
- local vramSize = vram_w * vram_h
- local scaleX = vram_w / 256
- local scaleY = vram_h / 200
- local BRIGHTNESS_FACTOR = 1.7
- local W1, W2, W3, W4 = 1, 8, 2, 16
- local W5, W6, W7, W8 = 4, 32, 64, 128
- local brailleChars = {}
- for i = 0, 255 do
- brailleChars[i] = uchar(0x2800 + i)
- end
- local vram = {}
- for i = 1, vramSize do
- vram[i] = 0
- end
- local cacheBg, cacheFg, cacheChar = {}, {}, {}
- local colors = {}
- local points, poly = {}, {}
- local runChars = {}
- local dirtyMinX, dirtyMaxX, dirtyMinY, dirtyMaxY
- local function resetDirty()
- dirtyMinX = vram_w
- dirtyMaxX = -1
- dirtyMinY = vram_h
- dirtyMaxY = -1
- end
- local function markDirtyFull()
- dirtyMinX = 0
- dirtyMaxX = vram_w - 1
- dirtyMinY = 0
- dirtyMaxY = vram_h - 1
- end
- local buffer = nil
- local usingBuffer = false
- if gpu.allocateBuffer then
- buffer = gpu.allocateBuffer(w, h)
- if buffer then
- usingBuffer = true
- gpu.setActiveBuffer(buffer)
- end
- end
- local function u16(str, pos)
- local a, b = byte(str, pos, pos + 1)
- return a + b * 256
- end
- local function u32(str, pos)
- local a, b, c, d = byte(str, pos, pos + 3)
- return a + b * 256 + c * 65536 + d * 16777216
- end
- local function brightenColor(r, g, b)
- r = min(floor(r * BRIGHTNESS_FACTOR), 255)
- g = min(floor(g * BRIGHTNESS_FACTOR), 255)
- b = min(floor(b * BRIGHTNESS_FACTOR), 255)
- return r * 65536 + g * 256 + b
- end
- local function displayImageMode2(imageData, width, height, bitsPerPixel, dataOffset, rowSize)
- if bitsPerPixel ~= 24 then return end
- local xRatio = width / vram_w
- local yRatio = height / vram_h
- local lastFg, lastBg = -1, -1
- local _floor, _byte, _braille, _gpu = floor, byte, brailleChars, gpu
- for py = 0, h - 1 do
- local iy = py * 4
- for px = 0, w - 1 do
- local ix = px * 2
- local sumR, sumG, sumB = 0, 0, 0
- local minLum, minR, minG, minB = 766, 0, 0, 0
- local l1, l2, l3, l4, l5, l6, l7, l8
- local n = 0
- for syOff = 0, 3 do
- local sy = _floor((iy + syOff) * yRatio)
- local rowBase = dataOffset + (height - 1 - sy) * rowSize
- for sxOff = 0, 1 do
- local sx = _floor((ix + sxOff) * xRatio)
- local p = rowBase + sx * 3 + 1
- local b, g, r = _byte(imageData, p, p + 2)
- local lum = r + g + b
- sumR, sumG, sumB = sumR + r, sumG + g, sumB + b
- if lum < minLum then
- minLum, minR, minG, minB = lum, r, g, b
- end
- n = n + 1
- if n == 1 then l1 = lum
- elseif n == 2 then l2 = lum
- elseif n == 3 then l3 = lum
- elseif n == 4 then l4 = lum
- elseif n == 5 then l5 = lum
- elseif n == 6 then l6 = lum
- elseif n == 7 then l7 = lum
- else l8 = lum
- end
- end
- end
- local avgLum = (sumR + sumG + sumB) * 0.125
- local pattern = 0
- if l1 > avgLum then pattern = pattern + W1 end
- if l2 > avgLum then pattern = pattern + W2 end
- if l3 > avgLum then pattern = pattern + W3 end
- if l4 > avgLum then pattern = pattern + W4 end
- if l5 > avgLum then pattern = pattern + W5 end
- if l6 > avgLum then pattern = pattern + W6 end
- if l7 > avgLum then pattern = pattern + W7 end
- if l8 > avgLum then pattern = pattern + W8 end
- local avgR, avgG, avgB = _floor(sumR * 0.125), _floor(sumG * 0.125), _floor(sumB * 0.125)
- local bgR = _floor(minR * 0.3 + avgR * 0.7)
- local bgG = _floor(minG * 0.3 + avgG * 0.7)
- local bgB = _floor(minB * 0.3 + avgB * 0.7)
- local fg = avgR * 65536 + avgG * 256 + avgB
- local bg = bgR * 65536 + bgG * 256 + bgB
- if fg ~= lastFg then _gpu.setForeground(fg); lastFg = fg end
- if bg ~= lastBg then _gpu.setBackground(bg); lastBg = bg end
- _gpu.set(px + 1, py + 1, _braille[pattern])
- end
- end
- end
- local bmpHandle = internet.request("https://files.catbox.moe/fhp6jy.bmp")
- if bmpHandle then
- local bmpChunks = {}
- for chunk in bmpHandle do
- bmpChunks[#bmpChunks + 1] = chunk
- end
- local bmpData = table.concat(bmpChunks)
- bmpChunks = nil
- local width = u32(bmpData, 19)
- local height = u32(bmpData, 23)
- local bitsPerPixel = u16(bmpData, 29)
- local dataOffset = u32(bmpData, 11)
- local rowSize = floor((bitsPerPixel * width + 31) / 32) * 4
- gpu.setActiveBuffer(0)
- displayImageMode2(bmpData, width, height, bitsPerPixel, dataOffset, rowSize)
- bmpData = nil
- end
- gpu.setForeground(0xFFFFFF)
- gpu.setBackground(0x000000)
- print("OC-NICCC! A ST-NICCC 2000 Port For OpenComputers Made By nonogamer9!")
- print("This is\n*NOT*\nA ComputerCraft Demo\nFetching scene.bin...")
- if usingBuffer then
- gpu.setActiveBuffer(buffer)
- end
- local colorCount, colorStamp, colorTouched = {}, {}, {}
- local colorGeneration = 0
- local function chooseColors(p1, p2, p3, p4, p5, p6, p7, p8)
- colorGeneration = colorGeneration + 1
- local generation = colorGeneration
- local counts, stamps, touched = colorCount, colorStamp, colorTouched
- local touchedCount = 0
- local c
- for _, val in ipairs({p1, p2, p3, p4, p5, p6, p7, p8}) do
- c = val
- if stamps[c] ~= generation then
- stamps[c] = generation
- counts[c] = 1
- touchedCount = touchedCount + 1
- touched[touchedCount] = c
- else
- counts[c] = counts[c] + 1
- end
- end
- local bg = touched[1]
- local fg = nil
- local best, second = 0, 0
- for i = 1, touchedCount do
- c = touched[i]
- local count = counts[c]
- if count > best then
- second = best
- best = count
- fg = bg
- bg = c
- elseif count > second then
- second = count
- fg = c
- end
- end
- return bg, fg
- end
- local edgeY0, edgeY1, edgeX, edgeDX = {}, {}, {}, {}
- local edgeOrder, activeEdges = {}, {}
- local function fillPolygon(pts, count, color)
- if count < 3 then return end
- local _floor, _ceil, _max, _min = floor, ceil, max, min
- local _vram = vram
- local _vramW, _vramH = vram_w, vram_h
- local edgeCount = 0
- local minY, maxY = _vramH, 0
- local j = count
- for i = 1, count do
- local x0, y0 = pts[j * 2 - 1], pts[j * 2]
- local x1, y1 = pts[i * 2 - 1], pts[i * 2]
- if y0 ~= y1 then
- local lowX, lowY, highX, highY
- if y0 < y1 then
- lowX, lowY, highX, highY = x0, y0, x1, y1
- else
- lowX, lowY, highX, highY = x1, y1, x0, y0
- end
- local yStart = _ceil(lowY)
- local yEnd = _ceil(highY) - 1
- if yStart <= yEnd and yEnd >= 0 and yStart < _vramH then
- if yStart < 0 then yStart = 0 end
- if yEnd >= _vramH then yEnd = _vramH - 1 end
- if yStart <= yEnd then
- edgeCount = edgeCount + 1
- edgeY0[edgeCount] = yStart
- edgeY1[edgeCount] = yEnd
- local dxdy = (highX - lowX) / (highY - lowY)
- edgeDX[edgeCount] = dxdy
- edgeX[edgeCount] = lowX + (yStart - lowY) * dxdy
- if yStart < minY then minY = yStart end
- if yEnd > maxY then maxY = yEnd end
- end
- end
- end
- j = i
- end
- if edgeCount < 2 then return end
- for i = 1, edgeCount do edgeOrder[i] = i end
- for i = 2, edgeCount do
- local key = edgeOrder[i]
- local keyY = edgeY0[key]
- local k = i - 1
- while k > 0 and edgeY0[edgeOrder[k]] > keyY do
- edgeOrder[k + 1] = edgeOrder[k]
- k = k - 1
- end
- edgeOrder[k + 1] = key
- end
- local activeCount = 0
- local nextEdge = 1
- local maxX = _vramW - 1
- for y = minY, maxY do
- while nextEdge <= edgeCount do
- local edge = edgeOrder[nextEdge]
- if edgeY0[edge] > y then break end
- if edgeY1[edge] >= y then
- activeCount = activeCount + 1
- activeEdges[activeCount] = edge
- end
- nextEdge = nextEdge + 1
- end
- local write = 1
- for i = 1, activeCount do
- local edge = activeEdges[i]
- if edgeY1[edge] >= y then
- activeEdges[write] = edge
- write = write + 1
- end
- end
- activeCount = write - 1
- if activeCount >= 2 then
- for i = 2, activeCount do
- local key = activeEdges[i]
- local keyX = edgeX[key]
- local k = i - 1
- while k > 0 and edgeX[activeEdges[k]] > keyX do
- activeEdges[k + 1] = activeEdges[k]
- k = k - 1
- end
- activeEdges[k + 1] = key
- end
- local row = y * _vramW
- local i = 1
- while i < activeCount do
- local e1, e2 = activeEdges[i], activeEdges[i + 1]
- local startX = _max(_floor(edgeX[e1]), 0)
- local endX = _min(_floor(edgeX[e2]), maxX)
- if startX <= endX then
- if startX < dirtyMinX then dirtyMinX = startX end
- if endX > dirtyMaxX then dirtyMaxX = endX end
- if y < dirtyMinY then dirtyMinY = y end
- if y > dirtyMaxY then dirtyMaxY = y end
- local idx = row + startX + 1
- local stop = row + endX + 1
- while idx <= stop do
- _vram[idx] = color
- idx = idx + 1
- end
- end
- i = i + 2
- end
- end
- for i = 1, activeCount do
- local edge = activeEdges[i]
- edgeX[edge] = edgeX[edge] + edgeDX[edge]
- end
- end
- end
- local function clearVRAM(color)
- local _vram = vram
- for i = 1, vramSize do _vram[i] = color end
- markDirtyFull()
- end
- local function blitVRAM()
- if dirtyMinX > dirtyMaxX or dirtyMinY > dirtyMaxY then return end
- local _floor, _max, _min = floor, max, min
- local _vram = vram
- local _gpu = gpu
- local _cacheBg, _cacheFg, _cacheChar = cacheBg, cacheFg, cacheChar
- local _braille, _runChars = brailleChars, runChars
- local vw = vram_w
- local cellMinX = _max(_floor(dirtyMinX * 0.5) + 1, 1)
- local cellMaxX = _min(_floor(dirtyMaxX * 0.5) + 1, w)
- local cellMinY = _max(_floor(dirtyMinY * 0.25) + 1, 1)
- local cellMaxY = _min(_floor(dirtyMaxY * 0.25) + 1, h)
- for cy = cellMinY, cellMaxY do
- local vY = (cy - 1) * 4
- local cellBase = (cy - 1) * w
- local r0 = vY * vw
- local r1, r2, r3 = r0 + vw, r0 + vw * 2, r0 + vw * 3
- local lastBg, lastFg = -1, -1
- local runStart, runBg, runFg, runLen = 0, -1, -1, 0
- for cx = cellMinX, cellMaxX do
- local vX = (cx - 1) * 2 + 1
- local p1, p2 = _vram[r0 + vX], _vram[r0 + vX + 1]
- local p3, p4 = _vram[r1 + vX], _vram[r1 + vX + 1]
- local p5, p6 = _vram[r2 + vX], _vram[r2 + vX + 1]
- local p7, p8 = _vram[r3 + vX], _vram[r3 + vX + 1]
- local bg, fg, char
- if p1 == p2 and p1 == p3 and p1 == p4 and p1 == p5 and p1 == p6 and p1 == p7 and p1 == p8 then
- bg, fg, char = p1, p1, " "
- else
- bg, fg = chooseColors(p1, p2, p3, p4, p5, p6, p7, p8)
- if fg == nil or fg == bg then
- fg, char = bg, " "
- else
- local pattern = 0
- if p1 == fg then pattern = pattern + W1 end
- if p2 == fg then pattern = pattern + W2 end
- if p3 == fg then pattern = pattern + W3 end
- if p4 == fg then pattern = pattern + W4 end
- if p5 == fg then pattern = pattern + W5 end
- if p6 == fg then pattern = pattern + W6 end
- if p7 == fg then pattern = pattern + W7 end
- if p8 == fg then pattern = pattern + W8 end
- char = _braille[pattern]
- end
- end
- local cell = cellBase + cx
- if _cacheBg[cell] ~= bg or _cacheFg[cell] ~= fg or _cacheChar[cell] ~= char then
- _cacheBg[cell], _cacheFg[cell], _cacheChar[cell] = bg, fg, char
- if runLen > 0 and bg == runBg and fg == runFg and cx == runStart + runLen then
- runLen = runLen + 1
- _runChars[runLen] = char
- else
- if runLen > 0 then
- if runBg ~= lastBg then _gpu.setBackground(runBg); lastBg = runBg end
- if runFg ~= lastFg then _gpu.setForeground(runFg); lastFg = runFg end
- _gpu.set(runStart, cy, table.concat(_runChars, "", 1, runLen))
- runLen = 0
- end
- runStart, runBg, runFg, runLen = cx, bg, fg, 1
- _runChars[1] = char
- end
- else
- if runLen > 0 then
- if runBg ~= lastBg then _gpu.setBackground(runBg); lastBg = runBg end
- if runFg ~= lastFg then _gpu.setForeground(runFg); lastFg = runFg end
- _gpu.set(runStart, cy, table.concat(_runChars, "", 1, runLen))
- runLen = 0
- end
- end
- end
- if runLen > 0 then
- if runBg ~= lastBg then _gpu.setBackground(runBg); lastBg = runBg end
- if runFg ~= lastFg then _gpu.setForeground(runFg); lastFg = runFg end
- _gpu.set(runStart, cy, table.concat(_runChars, "", 1, runLen))
- runLen = 0
- end
- end
- end
- local function renderFrame(data, pos, dataLength)
- resetDirty()
- local flags = byte(data, pos)
- if not flags then return dataLength + 1 end
- pos = pos + 1
- if flags % 2 == 1 then
- clearVRAM(colors[1] or 0)
- end
- if flags % 4 >= 2 then
- local m1, m2 = byte(data, pos, pos + 1)
- local mask = m1 * 256 + m2
- pos = pos + 2
- local bit = 32768
- for i = 1, 16 do
- if mask >= bit then
- mask = mask - bit
- local c1, c2 = byte(data, pos, pos + 1)
- pos = pos + 2
- local r = (c1 % 16) * 17
- local g = floor(c2 / 16) * 17
- local b = (c2 % 16) * 17
- colors[i] = brightenColor(r, g, b)
- end
- bit = bit * 0.5
- end
- end
- local hasVertexTable = flags % 8 >= 4
- if hasVertexTable then
- local vCount = byte(data, pos)
- pos = pos + 1
- for i = 0, vCount - 1 do
- local bx, by = byte(data, pos, pos + 1)
- pos = pos + 2
- local idx = i * 2 + 1
- points[idx] = bx * scaleX + 0.5
- points[idx + 1] = by * scaleY + 0.5
- end
- end
- while pos <= dataLength do
- local command = byte(data, pos)
- pos = pos + 1
- if not command or command >= 0xFD then
- if command == 0xFE then
- pos = floor((pos - 1) / 65536) * 65536 + 65537
- end
- break
- end
- local numPts = command % 16
- local colIdx = floor(command / 16) + 1
- if numPts >= 3 then
- if hasVertexTable then
- for i = 1, numPts do
- local idx = byte(data, pos)
- pos = pos + 1
- local src = idx * 2 + 1
- local dst = i * 2 - 1
- poly[dst] = points[src]
- poly[dst + 1] = points[src + 1]
- end
- else
- for i = 1, numPts do
- local px, py = byte(data, pos, pos + 1)
- pos = pos + 2
- local dst = i * 2 - 1
- poly[dst] = px * scaleX + 0.5
- poly[dst + 1] = py * scaleY + 0.5
- end
- end
- fillPolygon(poly, numPts, colors[colIdx] or 0)
- else
- pos = pos + (hasVertexTable and numPts or numPts * 2)
- end
- end
- blitVRAM()
- if usingBuffer then
- gpu.bitblt(0, 1, 1, w, h, buffer, 1, 1)
- end
- return pos
- end
- local function runDemo()
- local handle = internet.request("https://files.catbox.moe/r5mp9l.bin")
- if not handle then
- print("Failed to fetch scene.bin")
- return
- end
- local chunks = {}
- for chunk in handle do
- chunks[#chunks + 1] = chunk
- end
- local data = table.concat(chunks)
- chunks = nil
- local dataLength = #data
- local pos = 1
- local frameCount = 0
- while pos <= dataLength do
- local oldPos = pos
- pos = renderFrame(data, pos, dataLength)
- frameCount = frameCount + 1
- if frameCount % 8 == 0 then
- if event.pull(0) == "interrupted" then
- break
- end
- end
- if pos <= oldPos then break end
- end
- data = nil
- end
- runDemo()
- if usingBuffer then
- gpu.setActiveBuffer(0)
- gpu.freeBuffer(buffer)
- buffer = nil
- end
- gpu.setBackground(0x000000)
- gpu.setForeground(0xFFFFFF)
- print("Finished Demo.")
Add Comment
Please, Sign In to add comment