Advertisement
Kodos

Untitled

Jun 11th, 2014
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.86 KB | None | 0 0
  1. local shell = require("shell")
  2. local term = require("term")
  3. local fs = require("filesystem")
  4. local component = require("component")
  5. local computer = require("computer")
  6. local event = require("event")
  7. local process = require("process")
  8. local sides = require("sides")
  9.  
  10. local args, opt = shell.parse(...)
  11. local apipath
  12. local addShell, debugMode = true, false
  13.  
  14. local usageStr = [[Usage: ccemu (options) (program) (arguments)
  15. --help What you see here
  16. --apipath=path Load certain apis in folder
  17. --setpal Set the screen palette entries
  18. --noshell Disable built in shell api
  19. --debug Enable debugging]]
  20.  
  21. for k,v in pairs(opt) do
  22. if k == "help" then
  23. print(usageStr)
  24. return
  25. elseif k == "apipath" then
  26. if type(v) ~= "string" then
  27. error("Invalid parameter for " .. k,0)
  28. end
  29. apipath = shell.resolve(v)
  30. elseif k == "setpal" then
  31. component.gpu.setBackground(15,true)
  32. component.gpu.setForeground(0,true)
  33. io.stdout:write("Setting palette ... ")
  34. if component.gpu.getPaletteColor(0) ~= 0xF0F0F0 then component.gpu.setPaletteColor(0, 0xF0F0F0) end
  35. if component.gpu.getPaletteColor(1) ~= 0xF2B233 then component.gpu.setPaletteColor(1, 0xF2B233) end
  36. if component.gpu.getPaletteColor(2) ~= 0xE57FD8 then component.gpu.setPaletteColor(2, 0xE57FD8) end
  37. if component.gpu.getPaletteColor(3) ~= 0x99B2F2 then component.gpu.setPaletteColor(3, 0x99B2F2) end
  38. if component.gpu.getPaletteColor(4) ~= 0xDEDE6C then component.gpu.setPaletteColor(4, 0xDEDE6C) end
  39. if component.gpu.getPaletteColor(5) ~= 0x7FCC19 then component.gpu.setPaletteColor(5, 0x7FCC19) end
  40. if component.gpu.getPaletteColor(6) ~= 0xF2B2CC then component.gpu.setPaletteColor(6, 0xF2B2CC) end
  41. if component.gpu.getPaletteColor(7) ~= 0x4C4C4C then component.gpu.setPaletteColor(7, 0x4C4C4C) end
  42. if component.gpu.getPaletteColor(8) ~= 0x999999 then component.gpu.setPaletteColor(8, 0x999999) end
  43. if component.gpu.getPaletteColor(9) ~= 0x4C99B2 then component.gpu.setPaletteColor(9, 0x4C99B2) end
  44. if component.gpu.getPaletteColor(10) ~= 0xB266E5 then component.gpu.setPaletteColor(10, 0xB266E5) end
  45. if component.gpu.getPaletteColor(11) ~= 0x253192 then component.gpu.setPaletteColor(11, 0x253192) end
  46. if component.gpu.getPaletteColor(12) ~= 0x7F664C then component.gpu.setPaletteColor(12, 0x7F664C) end
  47. if component.gpu.getPaletteColor(13) ~= 0x57A64E then component.gpu.setPaletteColor(13, 0x57A64E) end
  48. if component.gpu.getPaletteColor(14) ~= 0xCC4C4C then component.gpu.setPaletteColor(14, 0xCC4C4C) end
  49. if component.gpu.getPaletteColor(15) ~= 0x000000 then component.gpu.setPaletteColor(15, 0x000000) end
  50. print("Done")
  51. return
  52. elseif k == "noshell" then
  53. addShell = false
  54. elseif k == "debug" then
  55. debugMode = true
  56. else
  57. error("Unknown option " .. k,0)
  58. end
  59. end
  60.  
  61. local dPrint
  62. if debugMode then
  63. dPrint = print
  64. else
  65. dPrint = function() end
  66. end
  67.  
  68. if #args < 1 then
  69. print(usageStr)
  70. return
  71. end
  72.  
  73. args[1] = shell.resolve(args[1],"lua")
  74.  
  75. if args[1] == nil or not fs.exists(args[1]) or fs.isDirectory(args[1]) then
  76. error("Invalid program to launch",0)
  77. end
  78.  
  79. if apipath ~= nil and not fs.isDirectory(apipath) then
  80. error("Invalid apipath",0)
  81. end
  82.  
  83. local function tablecopy(orig)
  84. local orig_type = type(orig)
  85. local copy
  86. if orig_type == 'table' then
  87. copy = {}
  88. for orig_key, orig_value in pairs(orig) do
  89. copy[orig_key] = orig_value
  90. end
  91. else
  92. copy = orig
  93. end
  94. return copy
  95. end
  96.  
  97. local comp = {
  98. label = nil,
  99. eventStack = {},
  100. timerC = 0,
  101. timerTrans = {},
  102. }
  103.  
  104. local env
  105.  
  106. local _wrap = {
  107. -- TODO: Can getfenv and setfenv be recreated?
  108. getfenv = function(level)
  109. level = level or 1
  110. if type(level) ~= "function" and type(level) ~= "number" then
  111. error("bad argument (number expected, got " .. type(level) .. ")",2)
  112. end
  113. if type(level) == "number" and level < 0 then
  114. error("bad argument #1 (level must be non-negative)",2)
  115. end
  116. return env
  117. end,
  118. setfenv = function()
  119. end,
  120. loadstring = function(str, source)
  121. source = source or "string"
  122. if type(str) ~= "string" and type(str) ~= "number" then error("bad argument #1 (string expected, got " .. type(str) .. ")",2) end
  123. if type(source) ~= "string" and type(source) ~= "number" then error("bad argument #2 (string expected, got " .. type(str) .. ")",2) end
  124. local source2 = tostring(source)
  125. local sSS = source2:sub(1,1)
  126. if sSS == "@" or sSS == "=" then
  127. source2 = source2:sub(2)
  128. end
  129. local f, err = load(str, "@" .. source2, nil, env)
  130. if f == nil then
  131. -- Get the normal error message
  132. local _, err = load(str, source, nil, env)
  133. return f, err
  134. end
  135. return f, err
  136. end,
  137. setTextColor = function(color)
  138. checkArg(1,color,"number")
  139. if color < 1 or color >= 65536 then
  140. error("Colour out of range",2)
  141. end
  142. color = math.floor(math.log(color)/math.log(2))
  143. component.gpu.setForeground(color,true)
  144. end,
  145. setBackgroundColor = function(color)
  146. checkArg(1,color,"number")
  147. if color < 1 or color >= 65536 then
  148. error("Colour out of range",2)
  149. end
  150. color = math.floor(math.log(color)/math.log(2))
  151. component.gpu.setBackground(color,true)
  152. end,
  153. scroll = function(pos)
  154. checkArg(1,pos,"number")
  155. local sW,sH = component.gpu.getResolution()
  156. component.gpu.copy(1,1,sW,sH,pos,0)
  157. end,
  158. getDir = function()
  159. end,
  160. find = function()
  161. end,
  162. open = function(path,mode)
  163. checkArg(1,path,"string")
  164. checkArg(2,mode,"string")
  165. if mode == "r" then
  166. local _file = io.open(path,"rb")
  167. if _file == nil then return end
  168. local file = {
  169. close = function() return _file:close() end,
  170. readLine = function() return _file:read("*l") end,
  171. readAll = function() return _file:read("*a") end,
  172. }
  173. return file
  174. elseif mode == "rb" then
  175. local _file = io.open(path,"rb")
  176. if _file == nil then return end
  177. local file = {
  178. close = function() return _file:close() end,
  179. read = function() local chr = _file:read(1) if chr ~= nil then chr = chr:byte() end return chr end,
  180. }
  181. return file
  182. elseif mode == "w" or mode == "a" then
  183. local _file = io.open(path,mode .. "b")
  184. if _file == nil then return end
  185. local file = {
  186. close = function() return _file:close() end,
  187. writeLine = function(data) return _file:write(data .. "\n") end,
  188. write = function(data) return _file:write(data) end,
  189. flush = function() return _file:flush() end
  190. }
  191. return file
  192. elseif mode == "wb" or mode == "ab" then
  193. local _file = io.open(path,mode)
  194. if _file == nil then return end
  195. local file = {
  196. close = function() return _file:close() end,
  197. write = function(data) return _file:write(string.char(data)) end,
  198. flush = function() return _file:flush() end
  199. }
  200. return file
  201. else
  202. error("Unsupported mode",2)
  203. end
  204. end,
  205. list = function(path)
  206. checkArg(1,path,"string")
  207. local toret = {}
  208. for entry in fs.list(path) do
  209. toret[#toret + 1] = entry
  210. end
  211. return toret
  212. end,
  213. getDrive = function(path)
  214. checkArg(1,path,"string")
  215. return "hdd"
  216. end,
  217. getFreeSpace = function(path)
  218. checkArg(1,path,"string")
  219. -- TODO: get actual free space.
  220. return math.huge
  221. end,
  222. move = function()
  223. end,
  224. combine = function(basePath, localPath)
  225. checkArg(1,basePath,"string")
  226. checkArg(2,localPath,"string")
  227. local path = ("/" .. basePath .. "/" .. localPath):gsub("\\", "/")
  228.  
  229. local tPath = {}
  230. for part in path:gmatch("[^/]+") do
  231. if part ~= "" and part ~= "." then
  232. if part == ".." and #tPath > 0 and tPath[1] ~= ".." then
  233. table.remove(tPath)
  234. else
  235. table.insert(tPath, part:sub(1,255))
  236. end
  237. end
  238. end
  239. return table.concat(tPath, "/")
  240. end,
  241. getComputerID = function()
  242. -- TODO: generate one based on computer address
  243. return 0
  244. end,
  245. setComputerLabel = function(label)
  246. checkArg(1,label,"string")
  247. comp.label = label
  248. end,
  249. queueEvent = function(event, ...)
  250. checkArg(1,event,"string")
  251. table.insert(comp.eventStack,{event, ...})
  252. end,
  253. startTimer = function(timeout)
  254. checkArg(1,timeout,"number")
  255. local timerRet = comp.timerC
  256. comp.timerC = comp.timerC + 1
  257. local timer = event.timer(timeout, function()
  258. comp.timerTrans[timerRet] = nil
  259. table.insert(comp.eventStack,{"timer", timerRet})
  260. end)
  261. comp.timerTrans[timerRet] = timer
  262. return timerRet
  263. end,
  264. setAlarm = function()
  265. -- TODO: Alarm
  266. end,
  267. cancelTimer = function(id)
  268. checkArg(1,id,"number")
  269. event.cancel(comp.timerTrans[id])
  270. comp.timerTrans[id] = nil
  271. end,
  272. cancelAlarm = function()
  273. -- TODO: Alarm
  274. end,
  275. time = function()
  276. local ost = os.date()
  277. return ost.hour + ((ost.min * 60 + ost.sec)/3600)
  278. end,
  279. day = function()
  280. local ost = os.date()
  281. return ((ost.year - 1970) * 365) + (ost.month * 30) + ost.day
  282. end
  283. }
  284.  
  285. env = {
  286. _VERSION = "Luaj-jse 2.0.3",
  287. tostring = tostring,
  288. tonumber = tonumber,
  289. unpack = table.unpack,
  290. getfenv = _wrap.getfenv,
  291. setfenv = _wrap.setfenv,
  292. rawequal = rawequal,
  293. rawset = rawset,
  294. rawget = rawget,
  295. setmetatable = setmetatable,
  296. getmetatable = getmetatable,
  297. next = next,
  298. type = type,
  299. select = select,
  300. assert = assert,
  301. error = error,
  302. ipairs = ipairs,
  303. pairs = pairs,
  304. pcall = pcall,
  305. xpcall = xpcall,
  306. loadstring = _wrap.loadstring,
  307. _realload = load,
  308. math = math,
  309. string = string,
  310. table = table,
  311. coroutine = coroutine,
  312. term = {
  313. clear = term.clear,
  314. clearLine = term.clearLine,
  315. getSize = function() return component.gpu.getResolution() end,
  316. getCursorPos = term.getCursor,
  317. setCursorPos = term.setCursor,
  318. setTextColor = _wrap.setTextColor,
  319. setTextColour = _wrap.setTextColor,
  320. setBackgroundColor = _wrap.setBackgroundColor,
  321. setBackgroundColour = _wrap.setBackgroundColor,
  322. setCursorBlink = term.setCursorBlink,
  323. scroll = _wrap.scroll,
  324. write = term.write,
  325. isColor = function() return component.gpu.maxDepth() ~= 1 end,
  326. isColour = function() return component.gpu.maxDepth() ~= 1 end,
  327. },
  328. fs = {
  329. getDir = _wrap.getDir,
  330. find = _wrap.find,
  331. open = _wrap.open,
  332. list = _wrap.list,
  333. exists = fs.exists,
  334. isDir = fs.isDirectory,
  335. isReadOnly = function() return false end,
  336. getName = fs.name,
  337. getDrive = _wrap.getDrive,
  338. getSize = fs.size,
  339. getFreeSpace = _wrap.getFreeSpace,
  340. makeDir = fs.makeDirectory,
  341. move = _wrap.move,
  342. copy = fs.copy,
  343. delete = fs.remove,
  344. combine = _wrap.combine,
  345. },
  346. os = {
  347. clock = computer.uptime,
  348. getComputerID = _wrap.getComputerID,
  349. computerID = _wrap.getComputerID,
  350. setComputerLabel = _wrap.setComputerLabel,
  351. getComputerLabel = function() return comp.label end,
  352. computerLabel = function() return comp.computerLabel end,
  353. queueEvent = _wrap.queueEvent,
  354. startTimer = _wrap.startTimer,
  355. setAlarm = _wrap.setAlarm,
  356. cancelTimer = _wrap.cancelTimer,
  357. cancelAlarm = _wrap.cancelAlarm,
  358. time = _wrap.time,
  359. day = _wrap.day,
  360. shutdown = function() computer.shutdown(false) end,
  361. reboot = function() computer.shutdown(true) end,
  362. },
  363. -- TODO: Peripherals
  364. peripheral = {
  365. isPresent = function() end,
  366. getType = function() end,
  367. getMethods = function() end,
  368. call = function() end,
  369. },
  370. redstone = {
  371. getSides = function() return {"top","bottom","left","right","front","back"} end,
  372. getInput = function() end,
  373. getOutput = function() end,
  374. getBundledInput = function() end,
  375. getBundledOutput = function() end,
  376. getAnalogInput = function() end,
  377. getAnalogOutput = function() end,
  378. setOutput = function() end,
  379. setBundledOutput = function() end,
  380. setAnalogOutput = function() end,
  381. testBundledInput = function() end,
  382. },
  383. bit = {
  384. blshift = bit32.lshift,
  385. brshift = bit32.arshift,
  386. blogic_rshift = bit32.rshift,
  387. bxor = bit32.bxor,
  388. bor = bit32.bor,
  389. band = bit32.band,
  390. bnot = bit32.bnot,
  391. }
  392. }
  393. env.redstone.getAnalogueInput = env.redstone.getAnalogInput
  394. env.redstone.getAnalogueOutput = env.redstone.getAnalogOutput
  395. env.redstone.setAnalogueOutput = env.redstone.setAnalogOutput
  396. env.rs = env.redstone
  397. env._G = env
  398.  
  399. if component.isAvailable("internet") and component.internet.isHttpEnabled() then
  400. -- TODO: Can this be written so http.request doesn't hog the execution?
  401. --env.http = {
  402. --}
  403. end
  404. if component.isAvailable("redstone") then
  405. env.redstone = {
  406. getSides = function() return {"top","bottom","left","right","front","back"} end,
  407. getInput = function(side) return component.redstone.getInput(sides[side]) ~= 0 end,
  408. getOutput = function(side) return component.redstone.getOutput(sides[side]) ~= 0 end,
  409. getBundledInput = function(side)
  410. side = sides[side]
  411. local val
  412. for i = 0,15 do
  413. if component.redstone.getBundledInput(side,i) > 0 then
  414. val = val + (2^i)
  415. end
  416. end
  417. return val
  418. end,
  419. getBundledOutput = function(side)
  420. side = sides[side]
  421. local val
  422. for i = 0,15 do
  423. if component.redstone.getBundledOutput(side,i) > 0 then
  424. val = val + (2^i)
  425. end
  426. end
  427. return val
  428. end,
  429. getAnalogInput = function(side) return component.redstone.getInput(sides[side]) end,
  430. getAnalogOutput = function(side) return component.redstone.getOutput(sides[side]) end,
  431. setOutput = function(side, val) return component.redstone.setOutput(sides[side],val and 15 or 0) end,
  432. setBundledOutput = function(side, val) end,
  433. setAnalogOutput = function(side, val) return component.redstone.setOutput(sides[side],val) end,
  434. testBundledInput = function() end,
  435. }
  436. env.redstone.getAnalogueInput = env.redstone.getAnalogInput
  437. env.redstone.getAnalogueOutput = env.redstone.getAnalogOutput
  438. env.redstone.setAnalogueOutput = env.redstone.setAnalogOutput
  439. env.rs = env.redstone
  440. else
  441. dPrint("Using fake redstone api")
  442. end
  443.  
  444. -- Bios entries:
  445. local eventTrans = {
  446. key = "key_down",
  447. }
  448.  
  449. function env.os.version()
  450. return "CCEmu 1.0"
  451. end
  452. local oldinterrupt = event.shouldInterrupt
  453. local newinterrupt = function() return false end
  454. event.shouldInterrupt = newinterrupt
  455. local function getEvent(filter)
  456. if #comp.eventStack > 0 then
  457. if filter ~= nil then
  458. for i = 1,#comp.eventStack do
  459. if comp.eventStack[i][1] == filter then
  460. local e = comp.eventStack[i]
  461. table.remove(comp.eventStack,i)
  462. return table.unpack(e)
  463. end
  464. end
  465. else
  466. local e = comp.eventStack[1]
  467. table.remove(comp.eventStack,1)
  468. return table.unpack(e)
  469. end
  470. end
  471. filter = eventTrans[filter] or filter
  472. event.shouldInterrupt = oldinterrupt
  473. local e = { pcall(event.pull,filter) }
  474. event.shouldInterrupt = newinterrupt
  475. if e[1] == false and e[2] == "interrupted" then
  476. return "terminate"
  477. end
  478. table.remove(e,1)
  479. if e[1] == "key_down" then
  480. if e[3] >= 32 and e[3] <= 126 then
  481. table.insert(comp.eventStack,{"char", string.char(e[3])})
  482. end
  483. return "key", e[4]
  484. elseif e[1] == "touch" then
  485. return "mouse_click", e[5] + 1, e[3], e[4]
  486. elseif e[1] == "drag" then
  487. return "mouse_drag", e[5] + 1, e[3], e[4]
  488. elseif e[1] == "scroll" then
  489. return "mouse_scroll", e[5], e[3], e[4]
  490. end
  491. end
  492. function env.os.pullEventRaw(filter)
  493. while true do
  494. local e = { getEvent() }
  495. if e[1] ~= nil then return table.unpack(e) end
  496. end
  497. end
  498. function env.os.pullEvent(filter)
  499. while true do
  500. local e = { getEvent() }
  501. if e[1] == "terminate" then
  502. error("Terminated", 0)
  503. end
  504. if e[1] ~= nil then return table.unpack(e) end
  505. end
  506. end
  507. env.sleep = os.sleep
  508. env.write = function(data) term.write(data,true) end
  509. env.print = print
  510. env.printError = function(...) io.stderr:write(table.concat({...},"\t") .. "\n") end
  511. env.read = function(_, hist) return term.read(hist):gsub("\n","") end -- Work around for \n appearing in term.read
  512. env.loadfile = loadfile
  513. env.dofile = dofile
  514. env.os.run = function(newenv, name, ...)
  515. local args = {...}
  516. setmetatable(newenv, {__index=env})
  517. local fn, err = loadfile(name, nil, newenv)
  518. if fn then
  519. local ok, err = pcall(function() fn(table.unpack(args)) end)
  520. if not ok then
  521. if err and err ~= "" then
  522. env.printError(err)
  523. end
  524. return false
  525. end
  526. return true
  527. end
  528. if err and err ~= "" then
  529. env.printError(err)
  530. end
  531. return false
  532. end
  533.  
  534. -- TODO: os.loadAPI
  535. env.os.unloadAPI = function(name)
  536. if _name ~= "_G" and type(env[name]) == "table" then
  537. env[name] = nil
  538. end
  539. end
  540. env.os.sleep = os.sleep
  541. if env.http ~= nil then
  542. -- TODO: http.get
  543. -- TODO: http.post
  544. end
  545.  
  546. if apipath ~= nil then
  547. for file in fs.list(apipath) do
  548. local path = apipath .. "/" .. file
  549. if not fs.isDirectory(path) and file ~= "colours" then
  550. dPrint("Loading " .. file)
  551. local tmpcopy = {}
  552. local env2
  553. env2 = {
  554. getfenv = function() return env2 end
  555. }
  556. setmetatable(env2,{
  557. __index = env,
  558. __newindex = function(t,k,v)
  559. tmpcopy[k] = v
  560. end
  561. })
  562. local fn,err = loadfile(path, nil, env2)
  563. if fn == nil then
  564. dPrint("Failed: " .. err)
  565. else
  566. local stat, err = pcall(fn)
  567. if stat == false then
  568. dPrint("Crash: " .. err)
  569. else
  570. env[file] = tmpcopy
  571. end
  572. end
  573. else
  574. dPrint("Ignoring " .. file)
  575. end
  576. end
  577. end
  578.  
  579. if env.colors ~= nil then
  580. dPrint("Adding colours from colors")
  581. env.colours = {}
  582. for k,v in pairs(env.colors) do
  583. if k == "gray" then k = "grey" end
  584. if k == "lightGray" then k = "lightGrey" end
  585. env.colours[k] = v
  586. end
  587. end
  588.  
  589. -- Shell api
  590. if addShell then
  591. env.shell = {
  592. dir = shell.getWorkingDirectory,
  593. setDir = shell.setWorkingDirectory,
  594. path = shell.getPath,
  595. setPath = shell.setPath,
  596. resolve = shell.resolve,
  597. resolveProgram = function(path) return shell.resolve(path,"lua") end,
  598. aliases = function()
  599. local toret = {}
  600. for k,v in shell.aliases() do
  601. toret[k] = v
  602. end
  603. return toret
  604. end,
  605. setAlias = shell.setAlias,
  606. clearAlias = function(alias) shell.setAlias(alias,nil) end,
  607. programs = function(hidden)
  608. local firstlist = {}
  609. for part in string.gmatch(shell.getPath(), "[^:]+") do
  610. part = shell.resolve(part)
  611. if fs.isDirectory(part) then
  612. for entry in fs.list(part) do
  613. if not fs.isDirectory(env.fs.combine(part, entry)) and (hidden or string.sub(entry, 1, 1) ~= ".") then
  614. firstlist[entry] = true
  615. end
  616. end
  617. end
  618. end
  619. local list = {}
  620. for entry, _ in pairs(firstlist) do
  621. table.insert(list, entry)
  622. end
  623. table.sort(list)
  624. return list
  625. end,
  626. getRunningProgram = function() return process.running():sub(2) end,
  627. run = function(command, ...) return shell.execute(command, nil, ...) end,
  628. openTab = function() end,
  629. switchTab = function() end,
  630. }
  631. end
  632.  
  633. if debugMode then
  634. io.stdout:write("Loading program ... ")
  635. end
  636.  
  637. local fn,err = loadfile(args[1], nil, env)
  638. if not fn then
  639. dPrint("Fail")
  640. error("Failed to load: " .. err, 0)
  641. end
  642. dPrint("Done")
  643. local retval = {xpcall(function() return fn(table.unpack(args,2)) end, debug.traceback)}
  644. event.shouldInterrupt = oldinterrupt
  645. component.gpu.setBackground(0x000000)
  646. component.gpu.setForeground(0xFFFFFF)
  647. if retval[1] == false then
  648. io.stderr:write(retval[2] .. "\n")
  649. else
  650. return table.unpack(retval,2)
  651. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement