Advertisement
Pinkishu

screenrec

Sep 21st, 2012
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.98 KB | None | 0 0
  1. local screen = {}
  2. local screenW,screenH = term.getSize()
  3.  
  4. function initScreen()
  5.   screen = {}
  6.   screen.data = {}
  7.   for i=1,screenH,1 do
  8.     screen.data[i] = string.rep(" ",screenW)
  9.   end
  10.   screen.cX = 1
  11.   screen.cY = 1
  12.   screen.blink = true
  13.   screen.setCursorPos = function(x,y) screen.cX = x; screen.cY = y end
  14.   screen.setCursorBlink = function(b) screen.blink = b end
  15.   screen.write = function(txt) return screenWrite(screen,txt) end
  16.   screen.clear = function() for i=1,screenH,1 do screen.data[i] = string.rep(" ",screenW) end end
  17.   screen.clearLine = function() screen.data[screen.cY] = string.rep(" ",screenW) end
  18.   screen.scroll = function(i)
  19.     if i >= screenH then
  20.       screen.clear()
  21.     else
  22.       for p=1,screenH-1,1 do
  23.         if screen.data[p+i] ~= nil then
  24.           screen.data[p] = screen.data[p+i]
  25.         else
  26.           screen.data[p] = string.rep(" ",screenW)
  27.         end
  28.       end
  29.     end screen.setCursorPos(term.getCursorPos())
  30.   end
  31. end
  32.  
  33. function screenWrite(wScreen,txt)
  34.  
  35.   local screenLine = wScreen.data[wScreen.cY]
  36.   local s = wScreen.cX
  37.   local e = wScreen.cX + string.len(txt)-1
  38.   local i = s
  39.   local st = true
  40.   while i <= wScreen.cX + string.len(txt)-1 do
  41.     if st then
  42.       --print( string.char(string.byte(screenLine,i)).."<=>"..string.char(string.byte(txt,i-wScreen.cX+1)) )
  43.       if string.byte(screenLine,i) ~= string.byte(txt,i-wScreen.cX+1) then
  44.         st = false
  45.         s = i
  46.         e = i
  47.       end
  48.     else
  49.       if string.byte(screenLine,i) ~= string.byte(txt,i-wScreen.cX+1) then
  50.         e = i
  51.       end
  52.     end
  53.  
  54.     i = i+1
  55.   end
  56.   local outStr = string.sub(txt,s-wScreen.cX+1,e-wScreen.cX+1)
  57.   screenLine = string.sub(string.sub(screenLine,1,s-1)..outStr..( e+1 <= screenW and string.sub(screenLine,e+1) or ""),1,screenW)
  58.   wScreen.data[wScreen.cY] = screenLine
  59.  
  60.   -- return screenStartPosX, screenEndPosX, stringStartPos, writtenString
  61.   return s,e,s-wScreen.cX+1,outStr
  62.  
  63. end
  64.  
  65. local startClock = 0
  66. local oldClock = 0
  67.  
  68. function getClock()
  69.   return os.clock() - startClock
  70. end
  71.  
  72. initScreen()
  73.  
  74. local orgFuncs = {}
  75. local hookFuncs = {}
  76.  
  77. hookFuncs.term = {}
  78. hookFuncs.os = {}
  79.  
  80.  
  81.  
  82. function hookFuncs.os.pullEventRaw(yyield)
  83.   local ev,p1,p2,p3,p4,p5,p6 = orgFuncs.os.pullEventRaw(yyield)
  84.   if ev == "key" and p1 == 59 then
  85.     endRec()
  86.     term.setCursorPos(1,1)
  87.     term.clearLine()
  88.  
  89.     term.write("Saved recording.")
  90.   end
  91.   return ev,p1,p2,p3,p4,p5,p6
  92. end
  93.  
  94. local dataTypes = {
  95.   [0] = {bitCount=8}, -- number
  96.   [1] = {bitCount=1}, -- boolean
  97.   [2] = {bitCount=8}, -- string
  98.   [3] = {bitCount=8}  -- character
  99. }
  100.  
  101.  
  102. local funcHooks = { }
  103. funcHooks.term = {"write", "scroll", "setCursorBlink", "setCursorPos", "clear", "clearLine"}
  104. local cmdIndex = {
  105.   [1] = { name="string",func="",argBits={} },
  106.  -- [2] = {name="string_end",func="",argBits={}},
  107.   [3] = {name="char",func="",argBits={0}},
  108.   [4] = {name="sleep",func="",argBits={}},
  109.   [5] = {name="scroll",func="term.scroll", argBits = {0}},
  110.   [6] = {name="clear",func="term.clear", argBits = {}},
  111.   [7] = {name="clearLine",func="term.clearLine",argBits = {}},
  112.   [8] = {name="setCursorPos",func="term.setCursorPos",argBits = {0,0}},
  113.   [9] = {name="setCursorBlink",func="term.setCursorBlink",argBits = {1}},
  114. --  [10] = {name="subSleep",func="",argBits={}},
  115. --  [11] = {name="longSleep",func="",argBits={}},
  116.   [15] = {name="end",func="",argBits={}}
  117. }
  118.  
  119. local bitStreamBuffer = 0
  120. local bitIndex = 0x80
  121. local bitStartIndex = 0x80
  122.  
  123. local b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  124. local b64String = ""
  125. local asciiString = ""
  126. function pushBase64(num)
  127.   b64String = b64String .. string.sub(b64,num+1,num+1)
  128. end
  129.  
  130. function pushAscii(num)
  131.   asciiString = asciiString..string.char(num)
  132. end
  133.  
  134. function endRec()
  135.   unhook()
  136.   pushBufferRemainder()
  137.   local file = fs.open("recFile","wb")
  138.   for i=1,string.len(asciiString),1 do
  139.     file.write(string.byte(asciiString,i))
  140.   end
  141.   file.close()
  142. end
  143. local ff = fs.open("pplog","w")
  144. function closeLog() ff.close() end
  145.  
  146. function pushBitsToStream(val,bits)
  147.   --if type(val) ~= "number" then error("TABVAL") end
  148.   --if type(bitStreamBuffer) ~= "number" then error("TABVAL1") end
  149.   --if type(val) == "table" then error("TABVAL3") end
  150.   local mask = bit.blshift(1, (bits-1))
  151.   while mask > 0 do
  152.     local maskVal = bit.brshift(bit.band(val,mask),bits-1)
  153.     bitStreamBuffer = bit.bor(bitStreamBuffer,maskVal*bitIndex)
  154.     mask = bit.brshift( mask, 1 )
  155.     bits = bits - 1
  156.     bitIndex = bit.brshift( bitIndex, 1 )
  157.     if bitIndex == 0 then
  158.       bitIndex = bitStartIndex
  159.       pushAscii(bitStreamBuffer)
  160.       bitStreamBuffer = 0
  161.     end
  162.   end
  163. end
  164.  
  165. function pushBitsToNextByte()
  166.   while bitIndex ~= bitStartIndex do pushBitsToStream(0,1) end
  167. end
  168.  
  169. function pushBufferRemainder()
  170.   pushBitsToStream(15,4)
  171.   if bitStreamBuffer then
  172.     pushAscii(bitStreamBuffer)
  173.   end
  174. end
  175.  
  176. function pushToStream(func,ret,...)
  177.   local cmdI = 0
  178.   for i,v in pairs(cmdIndex) do
  179.     if v.func == func then
  180.       cmdI = i
  181.       break
  182.     end
  183.   end
  184.  
  185.   if cmdI ~= 0 then
  186.     pushBitsToStream(cmdI,4)
  187.  
  188.     if #cmdIndex[cmdI].argBits > 0 then
  189.       pushBitsToStream((#cmdIndex[cmdI].argBits),2)
  190.       for i,v in ipairs(cmdIndex[cmdI].argBits) do
  191.         local dType = v
  192.         local bitCount = dataTypes[dType].bitCount
  193.         pushBitsToStream(dType,2)
  194.         if dType == 1 then arg[i] = arg[i] == true and 1 or 0 end
  195.         pushBitsToStream(arg[i],bitCount)
  196.       end
  197.     end
  198.  
  199.   else
  200.    if func == "term.write" then
  201.       if string.len(arg[1]) == 1 then
  202.         cmdI = 3
  203.         pushBitsToStream(cmdI,4)
  204.         pushBitsToStream(1,2)
  205.         pushBitsToStream(3,2)
  206.         pushBitsToNextByte()
  207.         pushBitsToStream(string.byte(arg[1],1),dataTypes[3].bitCount)
  208.       else
  209.         cmdI = 1
  210.         pushBitsToStream(cmdI,4)
  211.         pushBitsToStream(1,2)
  212.         pushBitsToNextByte()
  213.         for i=1,string.len(arg[1]),1 do
  214.           pushBitsToStream(string.byte(arg[1],i),dataTypes[2].bitCount)
  215.         end
  216.         pushBitsToStream(0,dataTypes[2].bitCount)
  217.         --pushBitsToStream(2,4)
  218.       end
  219.     end
  220.   end
  221. end
  222.  
  223. function logCall(func,ret,...)
  224.   local argstr = ""
  225.   local dX,dY = nil,nil
  226.   if string.sub(func,1,4) == "term" then
  227.     local subFunc = string.sub(func,6)
  228.     if screen[subFunc] and type(screen[subFunc]) == "function" then
  229.       if subFunc == "write" then
  230.         local subRet = {screen.write(unpack(arg))}
  231.         dX,dY = term.getCursorPos()
  232.        
  233.         local nX = subRet[1]
  234.         term.setCursorPos(nX,dY)
  235.         arg[1] = subRet[4]
  236.  
  237.       else
  238.         screen[subFunc](unpack(arg))
  239.       end
  240.     end
  241.   end
  242.  
  243.   local cClock = getClock()
  244.     if cClock ~= oldClock then
  245.     local diff = cClock - oldClock
  246.     oldClock = cClock
  247.     local intC = math.floor(diff)
  248.     local lowC = math.floor((diff - intC)*100)
  249.     while intC > 0 do
  250.       pushBitsToStream(4,4)
  251.       local argC = 1
  252.       if intC > 255 then argC = 3 else if intC > 0 then argC = 2 end end
  253.       pushBitsToStream(argC,2)
  254.       pushBitsToStream(0,2)
  255.       pushBitsToStream(lowC,dataTypes[0].bitCount)
  256.       if intC > 0 then
  257.         if intC > 255 then
  258.           intC = intC - 255
  259.           pushBitsToStream(0,2)
  260.           pushBitsToStream(255,dataTypes[0].bitCount)
  261.         else
  262.           pushBitsToStream(0,2)
  263.           pushBitsToStream(intC,dataTypes[0].bitCount)
  264.         end
  265.       end
  266.  
  267.       intC = intC - (255*2)
  268.     end
  269.  
  270.   end
  271.  
  272.   pushToStream(func,ret,unpack(arg))
  273.   if dX ~= nil then term.setCursorPos(dX,dY) end
  274. end
  275.  
  276. function genHooks(t)
  277.   local tb = funcHooks[t] or funcHooks
  278.   for k,v in pairs(tb) do
  279.     if type(v) == "table" then
  280.       genHooks(k)
  281.     else
  282.       if t then
  283.         if hookFuncs[t] == nil then hookFuncs[t] = {} end
  284.         hookFuncs[t][v] = function(...)
  285.             local ret = orgFuncs[t][v](unpack(arg))
  286.             logCall(t.."."..v,ret,unpack(arg))
  287.             return ret
  288.           end
  289.       else
  290.         hookFuncs[v] = function(...)
  291.             local ret = orgFuncs[v](unpack(arg))
  292.             logCall(v,ret,unpack(arg))
  293.             return ret
  294.           end
  295.       end
  296.     end
  297.   end
  298. end
  299. genHooks()
  300.  
  301. function hook(t)
  302.   if t ~= nil then tb = hookFuncs[t] else tb = hookFuncs end
  303.   for k,v in pairs(tb) do
  304.     if type(v) == "table" then
  305.       hook(k)
  306.     else
  307.       if t then
  308.         if orgFuncs[t] == nil then orgFuncs[t] = {} end
  309.         orgFuncs[t][k] = _G[t][k]
  310.         _G[t][k] = v
  311.       else
  312.         orgFuncs[k] = _G[k]
  313.         _G[k] = v
  314.       end
  315.     end
  316.   end
  317.   startClock = os.clock()
  318. end
  319.  
  320. function unhook(t)
  321.   if t ~= nil then tb = orgFuncs[t] else tb = orgFuncs end
  322.   for k,v in pairs(tb) do
  323.     if type(v) == "table" then
  324.         unhook(k)
  325.     else
  326.         if t then
  327.             _G[t][k] = v
  328.         else
  329.             _G[k] = v
  330.         end
  331.     end
  332.   end
  333. end
  334.  
  335. print("Recording... Press Enter to start.")
  336. while true do
  337.   local ev,p1 = os.pullEvent("key")
  338.   if ev == "key" and p1 == 28 then break end
  339. end
  340. term.clear()
  341. term.setCursorPos(1,1)
  342. hook()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement