Advertisement
nonogamer9

CC-NICCC: ST-NICCC 2000 Port For ComputerCraft Tweaked (Version 0.85)

Jul 21st, 2024 (edited)
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.61 KB | Software | 0 0
  1. local function lshift(x, by) return x * 2 ^ by end
  2. local function rshift(x, by) return math.floor(x / 2 ^ by) end
  3. local function band(x, y) return bit32 and bit32.band(x, y) or x % (y + 1) end
  4. local function bor(x, y) return bit32 and bit32.bor(x, y) or x - x % (y + 1) + (x + y) % (y + 1) end
  5.  
  6. local function downloadFile(url, path)
  7.     print("Downloading " .. url .. "...")
  8.     local response = http.get(url, nil, true)
  9.     if response then
  10.         local file = fs.open(path, "wb")
  11.         file.write(response.readAll())
  12.         file.close()
  13.         response.close()
  14.         print("Download complete!")
  15.         return true
  16.     end
  17.     print("Download failed!")
  18.     return false
  19. end
  20.  
  21. local sceneUrl = "https://github.com/pulkomandy/beniccc/blob/master/scene1.bin"
  22. local scenePath = "scene1.bin"
  23.  
  24. if not fs.exists(scenePath) and not downloadFile(sceneUrl, scenePath) then
  25.     error("Failed to download scene1.bin")
  26. end
  27.  
  28. local w, h = term.getSize()
  29. local DEMO_WIDTH, DEMO_HEIGHT = 256, 200
  30. local SCALE_X, SCALE_Y = w / DEMO_WIDTH, h / DEMO_HEIGHT
  31.  
  32. local frontBuffer, backBuffer = {}, {}
  33. for y = 1, h do
  34.     frontBuffer[y], backBuffer[y] = {}, {}
  35.     for x = 1, w do
  36.         frontBuffer[y][x] = {bg = colors.black, char = " "}
  37.         backBuffer[y][x] = {bg = colors.black, char = " "}
  38.     end
  39. end
  40.  
  41. local function decode(raw)
  42.     raw = band(raw, 0xF)
  43.     local bits = band(rshift(raw, 3), 1)
  44.     bits = bor(bits, band(lshift(raw, 1), 0xE))
  45.     return bits * 17
  46. end
  47.  
  48. local function rgbToTerminal(r, g, b)
  49.     local minDist, bestColor = math.huge, colors.black
  50.     for name, value in pairs(colors) do
  51.         if type(value) == "number" then
  52.             local cr, cg, cb = term.getPaletteColor(value)
  53.             local dr, dg, db = r/255 - cr, g/255 - cg, b/255 - cb
  54.             local dist = dr * dr + dg * dg + db * db
  55.             if dist < minDist then
  56.                 minDist, bestColor = dist, value
  57.             end
  58.         end
  59.     end
  60.     return bestColor
  61. end
  62.  
  63. local file = fs.open(scenePath, "rb")
  64. local sceneData = file.readAll()
  65. file.close()
  66.  
  67. local position = 1
  68. local function readByte()
  69.     local byte = string.byte(sceneData, position)
  70.     position = position + 1
  71.     return byte
  72. end
  73.  
  74. local function readWord()
  75.     return bor(lshift(readByte(), 8), readByte())
  76. end
  77.  
  78. local function drawPolygon(buffer, poly, color)
  79.     local minY, maxY = math.huge, -math.huge
  80.     for _, p in ipairs(poly) do
  81.         minY = math.min(minY, p.y)
  82.         maxY = math.max(maxY, p.y)
  83.     end
  84.  
  85.     for y = math.max(1, math.floor(minY * SCALE_Y)), math.min(h, math.ceil(maxY * SCALE_Y)) do
  86.         local nodeX = {}
  87.         local j = #poly
  88.         for i = 1, #poly do
  89.             local pi, pj = poly[i], poly[j]
  90.             if (pi.y * SCALE_Y < y and pj.y * SCALE_Y >= y) or (pj.y * SCALE_Y < y and pi.y * SCALE_Y >= y) then
  91.                 local x = pi.x + (y / SCALE_Y - pi.y) / (pj.y - pi.y) * (pj.x - pi.x)
  92.                 table.insert(nodeX, math.floor(x * SCALE_X))
  93.             end
  94.             j = i
  95.         end
  96.  
  97.         table.sort(nodeX)
  98.         for i = 1, #nodeX, 2 do
  99.             local startX, endX = nodeX[i], (nodeX[i+1] or w)
  100.             for x = math.max(1, startX), math.min(w, endX) do
  101.                 buffer[y][x] = {bg = color, char = " "}
  102.             end
  103.             if i % 10 == 0 then os.queueEvent("yield") os.pullEvent("yield") end
  104.         end
  105.         if y % 10 == 0 then os.queueEvent("yield") os.pullEvent("yield") end
  106.     end
  107. end
  108.  
  109. local palette = {}
  110. for i = 1, 16 do palette[i] = colors.black end
  111.  
  112. local frameCount, startTime = 0, os.clock()
  113. local targetFrameTime = 1 / 30
  114.  
  115. local shouldExit = false
  116.  
  117. while position <= #sceneData and not shouldExit do
  118.     local frameStartTime = os.clock()
  119.    
  120.     local flags = readByte()
  121.    
  122.     if band(flags, 2) ~= 0 then
  123.         local colorMask = readWord()
  124.         for i = 0, 15 do
  125.             if band(colorMask, lshift(1, 15 - i)) ~= 0 then
  126.                 local color = readWord()
  127.                 local r = decode(color)
  128.                 local g = decode(rshift(color, 12))
  129.                 local b = decode(rshift(color, 8))
  130.                 palette[i + 1] = rgbToTerminal(r,g,b)
  131.             end
  132.         end
  133.     end
  134.    
  135.     if band(flags, 1) ~= 0 then
  136.         for y = 1, h do
  137.             for x = 1, w do
  138.                 backBuffer[y][x] = {bg = palette[1], char = " "}
  139.             end
  140.         end
  141.     end
  142.    
  143.     if band(flags, 4) ~= 0 then
  144.         local vertices = readByte()
  145.         local points = {}
  146.        
  147.         for i = 1, vertices do
  148.             points[i] = {x = readByte(), y = readByte()}
  149.             if i % 10 == 0 then os.queueEvent("yield") os.pullEvent("yield") end
  150.         end
  151.        
  152.         while true do
  153.             local bits = readByte()
  154.            
  155.             if bits == 0xFF then break
  156.             elseif bits == 0xFE then
  157.                 position = band(position - 1 + 0x10000, 0xFFFF0000) + 1
  158.                 break
  159.             elseif bits == 0xFD then
  160.                 shouldExit = true
  161.                 break
  162.             else
  163.                 local color = palette[rshift(bits, 4) + 1]
  164.                 local numPoints = band(bits, 0xF)
  165.                 local poly = {}
  166.                
  167.                 for i = 1, numPoints do
  168.                     local index = readByte() + 1
  169.                     poly[i] = points[index]
  170.                     if i % 10 == 0 then os.queueEvent("yield") os.pullEvent("yield") end
  171.                 end
  172.                
  173.                 drawPolygon(backBuffer, poly, color)
  174.             end
  175.             os.queueEvent("yield") os.pullEvent("yield")
  176.         end
  177.        
  178.     else
  179.         while true do
  180.             local bits = readByte()
  181.            
  182.             if bits == 0xFF then break
  183.             elseif bits == 0xFE then
  184.                 position = band(position - 1 + 0x10000, 0xFFFF0000) + 1
  185.                 break
  186.             elseif bits == 0xFD then
  187.                 shouldExit = true
  188.                 break
  189.             else
  190.                 local color = palette[rshift(bits, 4) + 1]
  191.                 local numPoints = band(bits, 0xF)
  192.                 local poly = {}
  193.                
  194.                 for i = 1, numPoints do
  195.                     poly[i] = {x = readByte(), y = readByte()}
  196.                     if i % 10 == 0 then os.queueEvent("yield") os.pullEvent("yield") end
  197.                 end
  198.                
  199.                 drawPolygon(backBuffer, poly, color)
  200.             end
  201.             os.queueEvent("yield") os.pullEvent("yield")
  202.         end
  203.     end
  204.    
  205.     frontBuffer, backBuffer = backBuffer, frontBuffer
  206.    
  207.     for y = 1, h do
  208.         for x = 1, w do
  209.             term.setCursorPos(x, y)
  210.             term.setBackgroundColor(frontBuffer[y][x].bg)
  211.             term.write(frontBuffer[y][x].char)
  212.         end
  213.     end
  214.  
  215.     frameCount = frameCount + 1
  216.    
  217.     local currentTime = os.clock()
  218.     local fps = frameCount / (currentTime - startTime)
  219.     term.setCursorPos(1, 1)
  220.     term.setBackgroundColor(colors.black)
  221.     term.setTextColor(colors.white)
  222.     term.write(string.format("Frame: %d FPS: %.2f", frameCount, fps))
  223.    
  224.     local frameEndTime = os.clock()
  225.     local frameTime = frameEndTime - frameStartTime
  226.    
  227.     if frameTime < targetFrameTime then os.sleep(targetFrameTime - frameTime) end
  228. end
  229.  
  230. -- Display final statistics
  231. local endTime = os.clock()
  232. local totalTime = endTime - startTime  
  233. local avgFPS = frameCount / totalTime  
  234. print(string.format("Demo completed in %.2f seconds", totalTime))
  235. print(string.format("Total frames: %d", frameCount))
  236. print(string.format("Average FPS: %.2f", avgFPS))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement