Advertisement
RamiLego

MicroLua

Feb 11th, 2017
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.67 KB | None | 0 0
  1. --Last Update: 19/10/2017 12:30 PM
  2. --Official MicroLua Stamps save id:2151133
  3. --https://pastebin.com/Jt5eE4aP
  4. --UserManual: https://github.com/RamiLego4Game/TPTMicroLua/blob/master/UserManual.md
  5. --TODO:
  6. --[[
  7. # Base LCBL on TUNG and make it unconductive (DONE).
  8. # MPU setColor() (DONE).
  9. # spark({pinlist}) to spark more than one pin. (DONE).
  10. # LHWP to start, stop or reset the MPU. (DONE).
  11. # MPU TMP 1 wont autoboot the MPU. (DONE).
  12. X MPU heats up every tick, and cools down when tick() is called (Canceled).
  13. # MPU freezes when it's sparked. (DONE).
  14. # isSparked({pinlist}) will return true if all the pins are sparked. (DONE).
  15. # isSparked({pinlist}, true) will return a table with boolean values. (DONE).
  16. # isSparked() returns the id of a sparked pin, or false if none are sparked. (DONE).
  17. ]]
  18. --Creating the elements--
  19. local elem_group = "MLUA"
  20. local elem_names = { "LMPU", "LCBL", "LPIN", "LHWP", "LMRC", "LROM" } --The names of the elements to allocate
  21. local elem_id = {} --A table containing the ids of every name in elem_names, [name] = id.
  22. local elem_name = {} --A table to get the name from the id
  23.  
  24. --Allocate the elements
  25. for k, name in ipairs(elem_names) do
  26.     if elements[elem_group.."_PT_"..name] then elements.free(elements[elem_group.."_PT_"..name]) end --Incase the script errored
  27.     local id = elements.allocate(elem_group, name)
  28.     if id == -1 then --(It failed)
  29.         error("Failed to allocate an element, please disable some elements scripts !")
  30.         return --Abort the script
  31.     else
  32.         elem_id[name] = id
  33.         elem_name[id] = name
  34.     end
  35. end
  36.  
  37. local elem_clone = { --New elements properties; _Parent is a special key that clones properties from a default elements before applying the changes.
  38.     ["LMPU"] = {
  39.         _Parent = "METL",
  40.         Name = "LMPU",
  41.         Description = "Lua Microprocessor Unit, used for advanced electornics",
  42.         Color = 0x000080, --The color of the Lua logo ;)
  43.         MenuSection = elements.SC_POWERED
  44.     },
  45.    
  46.     ["LCBL"] = {
  47.         _Parent = "METL",
  48.         Name = "LCBL",
  49.         Description = "Lua Cable, used for connecting peripherals with LMPU",
  50.         Properties = bit.bor(elements.TYPE_SOLID,elements.PROP_HOT_GLOW),
  51.         HightTemperature = 1687,
  52.         Color = 0x505050, --TUNG color
  53.         MenuSection = elements.SC_POWERED
  54.     },
  55.    
  56.     ["LPIN"] = {
  57.         _Parent = "METL",
  58.         Name = "LPIN",
  59.         Description = "Lua Pin, Connects as GPIO pin peripheral. TMP as id",
  60.         Color = 0xE0E0E0,
  61.         MenuSection = elements.SC_POWERED
  62.     },
  63.    
  64.     ["LHWP"] = {
  65.         _Parent = "METL",
  66.         Name = "LHWP",
  67.         Description = "Lua Hardware Pin, Controles the MPU state, TMP is mode (0=reset, 1=start, 2=shutdown, 3=pause, 4=tick)",
  68.         Color = 0xC0E0FF,
  69.         MenuSection = elements.SC_POWERED
  70.     },
  71.    
  72.     ["LMRC"] = {
  73.         _Parent = "METL",
  74.         Name = "LMRC",
  75.         Description = "Lua Memory Reading Controller peripheral. Speciallized in reading LROM",
  76.         Color = 0xF4BC42,
  77.         MenuSection = elements.SC_POWERED
  78.     },
  79.    
  80.     ["LROM"] = {
  81.         _Parent = "METL",
  82.         Name = "LROM",
  83.         Description = "Lua Read Only Memory, Stores 8 Bytes (8 Ascii Characters)",
  84.         Properties = bit.bor(elements.TYPE_SOLID,elements.PROP_HOT_GLOW),
  85.         HightTemperature = 1687,
  86.         Color = 0xFFFFFF, --White
  87.         MenuSection = elements.SC_POWERED
  88.     }
  89. }
  90.  
  91. --Applying the properties
  92. for name, props in pairs(elem_clone) do
  93.     if not elem_id[name] then error("Un-allocated element: "..name..", report this to the developer !") end
  94.     if props._Parent then elements.element(elem_id[name],elements.element(elements["DEFAULT_PT_"..props._Parent])); props._Parent = nil end --Do the clonning
  95.     elements.element(elem_id[name],props) --Set the properties
  96. end
  97.  
  98. local elem_peripherals = {[ elem_id["LPIN"] ] = true, [ elem_id["LHWP"] ] = true, [ elem_id["LMRC"] ] = true} --Use elem_id (for easier programming)
  99.  
  100. --SC (self call) is a special argument, don't use it !
  101. local mappedIndexes, mappedPeripherals = {}, {}
  102. local function mapCables(x,y, sc)
  103.     if not sc then mappedIndexes, mappedPeripherals = {}, {} end --Reset the maps
  104.    
  105.     mappedIndexes[simulation.partID(x,y)] = true --Set the current part as mapped.
  106.    
  107.     local parts = simulation.partNeighbors(x,y, 3) --Scan the around parts.
  108.     for _, index in ipairs(parts) do
  109.        
  110.         if not mappedIndexes[index] then
  111.            
  112.             local px, py = simulation.partPosition(index)
  113.             local ptype = simulation.partProperty(index,simulation.FIELD_TYPE)
  114.             if ptype == elements.DEFAULT_PT_SPRK then ptype = simulation.partProperty(index,simulation.FIELD_CTYPE) end
  115.            
  116.             if elem_peripherals[ptype] then --It's a peripheral !
  117.            
  118.                 mappedIndexes[index] = true --So don't double detect the peripheral
  119.                 if not mappedPeripherals[elem_name[ptype]] then mappedPeripherals[elem_name[ptype]] = {} end
  120.                 table.insert(mappedPeripherals[elem_name[ptype]],index)
  121.                
  122.             elseif elem_id["LCBL"] == ptype then --It's a cable
  123.                 mapCables(px,py, true)
  124.             end
  125.         end
  126.        
  127.     end
  128.    
  129.     if not sc then return mappedPeripherals end
  130. end
  131.  
  132. local function mapROM(x,y)
  133.     --X, Y should be the position of the top-left corner.
  134.     local mi = {} --Mapped Indexes
  135.     local cy = 0
  136.     while true do
  137.         local ypid = simulation.partID(x,y+cy)
  138.         if not ypid then break end
  139.         if simulation.partProperty(ypid, simulation.FIELD_TYPE) ~= elem_id["LROM"] then break end --The end of rom block
  140.         local cx = 0
  141.         while true do
  142.             local pid = simulation.partID(x+cx,y+cy)
  143.             if not pid then break end --No Part
  144.             if simulation.partProperty(pid, simulation.FIELD_TYPE) ~= elem_id["LROM"] then break end --The end of rom line
  145.             table.insert(mi,pid)
  146.             cx = cx + 1
  147.         end
  148.         cy = cy + 1
  149.     end
  150.     return mi
  151. end
  152.  
  153. --Reads the ROM string, must provide the mappedIndexes array (That can be obtained by mapROM(x,y))
  154. local function readROM(mi)
  155.     local data = ""
  156.     for _, index in ipairs(mi) do
  157.         local ctype = simulation.partProperty(index, simulation.FIELD_CTYPE) --1 byte
  158.         local dcolor = simulation.partProperty(index, simulation.FIELD_DCOLOUR) --4 bytes
  159.         local life = simulation.partProperty(index, simulation.FIELD_LIFE) --1 byte
  160.         local tmp = simulation.partProperty(index, simulation.FIELD_TMP) --1 byte
  161.         local tmp2 = simulation.partProperty(index, simulation.FIELD_TMP2) --1 byte
  162.         ctype = string.char(ctype)
  163.         local cola = string.char(bit.band(dcolor,255))
  164.         local colr = string.char(bit.band(bit.rshift(dcolor,8),255))
  165.         local colg = string.char(bit.band(bit.rshift(dcolor,16),255))
  166.         local colb = string.char(bit.band(bit.rshift(dcolor,24),255))
  167.         life = string.char(life)
  168.         tmp = string.char(tmp)
  169.         tmp2 = string.char(tmp2)
  170.         data = data .. ctype..cola..colr..colg..colb..life..tmp..tmp2
  171.     end
  172.    
  173.     return data
  174. end
  175.  
  176. --Writes the ROM string, must provide the mappedIndexes arrays (That can be obtained by mapROM(x,y)) and the data string.
  177. local function flushROM(mi,data)
  178.     data = data.."        "
  179.     local dataBytes = {}
  180.     for i=1,data:len() do
  181.         table.insert(dataBytes,string.byte(data:sub(i,i)))
  182.     end
  183.    
  184.     local curByte = 0
  185.     local function nextByte()
  186.         if #dataBytes == curByte then return 0 end
  187.         curByte = curByte + 1
  188.         return dataBytes[curByte]
  189.     end
  190.    
  191.     for _, index in ipairs(mi) do
  192.         simulation.partProperty(index, simulation.FIELD_CTYPE, nextByte()) --1 bytes
  193.         local cola = nextByte()
  194.         local colr = bit.lshift(nextByte(),8)
  195.         local colg = bit.lshift(nextByte(),16)
  196.         local colb = bit.lshift(nextByte(),24)
  197.         local dcolor = bit.bor(cola,colr,colg,colb)
  198.         simulation.partProperty(index, simulation.FIELD_DCOLOUR, dcolor) --4 bytes
  199.         simulation.partProperty(index, simulation.FIELD_LIFE, nextByte()) --1 byte
  200.         simulation.partProperty(index, simulation.FIELD_TMP, nextByte()) --1 byte
  201.         simulation.partProperty(index, simulation.FIELD_TMP2, nextByte()) --1 byte
  202.     end
  203. end
  204.  
  205. local MPU_Data = {}
  206.  
  207. --MPU API
  208. local MPU_API = {}
  209.  
  210. local function addAPI(func,name,parent)
  211.   local t = MPU_API
  212.   if parent then
  213.     if not t[parent] then t[parent] = {} end
  214.     t = t[parent]
  215.   end
  216.   t[name] = function(index,...)
  217.     return pcall(func,...)
  218.   end
  219. end
  220.  
  221. MPU_API.tick = function(index)
  222.     return true
  223. end
  224.  
  225. MPU_API.spark = function(index,pids)
  226.     if type(pids) ~= "number" and type(pids) ~= "table" then return false, "Pin ID must be a number or a table, provided: "..type(pids) end
  227.     if type(pids) == "number" then pids = {pids} end
  228.     if #pids == 1 then
  229.         if type(pids[1]) ~= "number" then return false, "#1 Pin must be a number, provided: "..type(pids[1]) end
  230.         pids[1] = math.floor(pids[1])
  231.         if not MPU_Data[index].pins[pids[1]] then return false, "Pin ("..pids[1]..") doesn't exists !" end
  232.     else
  233.         for k, pid in ipairs(pids) do
  234.             if type(pid) ~= "number" then return false, "#"..k.." Pin must be a number, provided: "..type(pid) end
  235.             pid = math.floor(pid); pids[k] = pid
  236.             if not MPU_Data[index].pins[pid] then return false, "#"..k.." Pin ("..pid..") doesn't exists !" end
  237.         end
  238.     end
  239.     for k, pid in ipairs(pids) do
  240.         local pindex = MPU_Data[index].pins[pid]
  241.         local px, py = simulation.partPosition(pindex) --Pin position
  242.         simulation.partCreate(-1,px,py,elements.DEFAULT_PT_SPRK) --Spark the pin
  243.     end
  244.     return true --It ran successully
  245. end
  246.  
  247. MPU_API.isSparked = function(index,pids,getlist)
  248.     if type(pids) ~= "number" and type(pids) ~= "table" and type(pids) ~= "nil" then return false, "Pin ID must be a number, provided: "..type(pid) end
  249.     if type(pids) == "number" then
  250.         local pid = math.floor(pids)
  251.         if not MPU_Data[index].pins[pid] then return false, "Pin ("..pid..") doesn't exists !" end
  252.         local pindex = MPU_Data[index].pins[pid]
  253.         local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
  254.         if ptype == elements.DEFAULT_PT_SPRK then
  255.             return true, true
  256.         else
  257.             return true, false
  258.         end
  259.     elseif type(pids) == "table" then
  260.         for k,pid in ipairs(pids) do
  261.             if type(pid) ~= "number" then return false, "#"..k.." Pins must be a number, provided: "..type(pid) end
  262.             pid = math.floor(pid); pids[k] = pid
  263.             if not MPU_Data[index].pins[pid] then return false, "Pin ("..pid..") doesn't exists !" end
  264.         end
  265.        
  266.         if getlist then
  267.             local result = {}
  268.             for k,pid in ipairs(pids) do
  269.                 local pindex = MPU_Data[index].pins[pid]
  270.                 local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
  271.                 if ptype == elements.DEFAULT_PT_SPRK then
  272.                     result[k] = true
  273.                 else
  274.                     result[k] = false
  275.                 end
  276.             end
  277.             return true, result
  278.         else
  279.             for k,pid in ipairs(pids) do
  280.                 local pindex = MPU_Data[index].pins[pid]
  281.                 local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
  282.                 if ptype ~= elements.DEFAULT_PT_SPRK then
  283.                     return true, false, pid --A pin is not sparked.
  284.                 end
  285.             end
  286.             return true, true
  287.         end
  288.     else
  289.         for k, pindex in ipairs(MPU_Data[index].pins) do
  290.             local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
  291.             if ptype == elements.DEFAULT_PT_SPRK then
  292.                 return true, pid --A pin is sparked.
  293.             end
  294.         end
  295.         return true, false --No pins are sparked.
  296.     end
  297. end
  298.  
  299. MPU_API.setColor = function(index,color)
  300.   local color = color or {0,0,128}
  301.   if type(color) ~= "table" then return false, "Color must be a table, provided: "..type(color) end
  302.   for i=1, 3 do if type(color[i]) ~= "number" then return false, "Wrong color table" end end
  303.   for i=1, 3 do MPU_Data[index].color[i] = color[i] or MPU_Data[index].color[i] end
  304.   return true
  305. end
  306.  
  307. local toClone = {
  308.   "pairs", "ipairs", "next", "_VERSION",
  309.   "pcall", "xpcall", "print", "select", "type", "tostring", "tonumber", "unpack",
  310.   table = {
  311.     "insert", "remove", "maxn", "sort", "concat"
  312.   },
  313.   math = {
  314.     "abs", "fmod", "floor", "ceil", "min", "max", "modf",
  315.     "sqrt", "pow", "exp", "log", "log10", "frexp", "ldexp",
  316.     "deg", "rad", "sin", "cos", "tan", "asin", "acos", "atan",
  317.     "random", "randomseed",  "pi", "huge"
  318.   },
  319.   string = {
  320.     "len", "sub", "rep", "upper", "lower", "reverse", "byte", "char", "format",
  321.     "find", "gmatch", "match", "gsub"
  322.   },
  323.   coroutine = {
  324.     "create", "resume", "running", "status", "wrap"
  325.   },
  326.   os = {
  327.     "time", "difftime", "date", "clock"
  328.   },
  329.   bit = {
  330.     "tobit", "tohex", "bnot", "band", "bor", "bxor", "lshift", "rshift", "arshift", "rol", "ror", "bswap"
  331.   }
  332. }
  333.  
  334. --Clone Lua Libraries
  335. for k,v in pairs(toClone) do
  336.   if type(v) == "string" then
  337.     addAPI(_G[v],v)
  338.   else
  339.     for k2, v2 in ipairs(v) do
  340.       addAPI(_G[k][v2],v2,k)
  341.     end
  342.   end
  343. end
  344.  
  345.  
  346. --Index MPU_API functions and Build MPU Coroutine Sandbox
  347. local MPU_CO_ID, MPU_CO_GLOB = {}, {}
  348. local function indexMPU_API(t,pre,g)
  349.     local t = t or MPU_API
  350.     local pre = pre or ""
  351.     local g = g or MPU_CO_GLOB
  352.     for k, v in pairs(t) do
  353.         if type(v) == "table" then
  354.             g[k] = {}
  355.             indexMPU_API(v,pre..k..".",g[k])
  356.         else
  357.             MPU_CO_ID[pre..k] = v
  358.            
  359.             local coyield = coroutine.yield
  360.             local ipairs = ipairs
  361.             local error = error
  362.             local unpack = unpack
  363.             local tablerem = table.remove
  364.            
  365.             g[k] = function(...)
  366.                 local ret = {coyield(pre..k, ...)}
  367.                 if not ret[1] then return error(tostring(ret[2])) end
  368.                 for k,v in ipairs(ret) do
  369.                     if k ~= 1 then
  370.                         ret[k-1] = v
  371.                     end
  372.                 end
  373.                 tablerem(ret,#ret)
  374.                 return unpack(ret)
  375.             end
  376.            
  377.         end
  378.     end
  379. end
  380. indexMPU_API()
  381.  
  382. MPU_CO_GLOB.error = error
  383. MPU_CO_GLOB.assert = assert
  384. --Internal Helping Functions
  385. MPU_CO_GLOB.sleep = function(t) for i=1, t do coroutine.yield("tick") end end
  386. MPU_CO_GLOB.coroutine.yield = coroutine.yield
  387.  
  388. local function NewSandbox(g)
  389.     local s = {}
  390.     local g = g or MPU_CO_GLOB
  391.     for k,v in pairs(g) do
  392.         if type(v) == "table" then
  393.             s[k] = NewSandbox(g[k])
  394.         else
  395.             s[k] = v
  396.         end
  397.     end
  398.     if g == MPU_CO_GLOB then s._G = s end
  399.     return s
  400. end
  401.  
  402. local function removeNulls(str)
  403.     local null = string.char(0)
  404.     local nstr = ""
  405.     for i=1, #str do
  406.         local c = str:sub(i,i)
  407.         if c ~= null then
  408.             nstr = nstr..c
  409.         end
  410.     end
  411.     return nstr
  412. end
  413.  
  414. local function quotaErr() --Protects us from infinite loops !
  415.   error("Quota exceeded: "..micro.quota,2)
  416. end
  417.  
  418. local function checkHWPin(index,pintmp)
  419.     local flag = false
  420.     if MPU_Data[index].hwpins[pintmp] then
  421.         for k,pin in ipairs(MPU_Data[index].hwpins[pintmp]) do
  422.             if simulation.partProperty(pin,simulation.FIELD_TYPE) == elements.DEFAULT_PT_SPRK then
  423.                 if not MPU_Data[index].sparkFilter[pin] then
  424.                     MPU_Data[index].sparkFilter[pin] = true
  425.                     flag = true
  426.                 end
  427.             else
  428.                 if MPU_Data[index].sparkFilter[pin] then
  429.                     MPU_Data[index].sparkFilter[pin] = false --The spark pulse ended
  430.                 end
  431.             end
  432.         end
  433.     end
  434.     return flag
  435. end
  436.  
  437. local _LuaBCHeader = ( jit and (string.char(0x1B).."LJ") or (string.char(0x1B).."Lua"))
  438.  
  439. --Elements Update
  440. local function _MPU_UPDATE(index, x, y, surround_space, nt)
  441.     local flags = simulation.partProperty(index, simulation.FIELD_FLAGS)
  442.     --Check if the processor did boot yet or not.
  443.     --I found that it's safe to use the second byte of FLAGS
  444.     --And why I'm using flags because it's not saved ;)
  445.     --The first bit will be the boot state, 0 = off, 1 = booted.
  446.     if bit.band(flags, 256) == 0 then --It did not boot yet !
  447.         MPU_Data[index] = {} --Override the old one if exists.
  448.         MPU_Data[index].state = "Booted"
  449.         MPU_Data[index].color = {0,0,128}
  450.         MPU_Data[index].peripherals = mapCables(x,y)
  451.         MPU_Data[index].startPos = {x,y}
  452.         MPU_Data[index].sparkFilter = {}
  453.         --Load the code
  454.         if MPU_Data[index].peripherals.LMRC then
  455.             local ichip = MPU_Data[index].peripherals.LMRC[1]
  456.             local x,y = simulation.partPosition(ichip)
  457.             local rom = mapROM(x+1,y+1)
  458.             local data = readROM(rom)
  459.             data = removeNulls(data)
  460.            
  461.             local chunk, cerr
  462.            
  463.             if data:sub(0,4) == _LuaBCHeader then
  464.                 cerr = "Lua Bytecode is NOT ALLOWED ! YOU HACKER"
  465.             else
  466.                 chunk, cerr = loadstring(data)
  467.             end
  468.            
  469.             if not chunk then
  470.                 MPU_Data[index].err = cerr
  471.                 print("CPU #"..index.." CERR: "..cerr)
  472.             else
  473.                 local glob = NewSandbox()
  474.                 setfenv(chunk,glob)
  475.                 local co = coroutine.create(chunk)
  476.                 if simulation.partProperty(index,simulation.FIELD_TMP) == 1 then
  477.                     MPU_Data[index].state = "Loaded"
  478.                 else
  479.                     MPU_Data[index].state = "Running"
  480.                 end
  481.                 MPU_Data[index].chunk = chunk
  482.                 MPU_Data[index].co = co
  483.                 MPU_Data[index].glob = glob
  484.                 MPU_Data[index].lastRet = {}
  485.             end
  486.             if micro.debug then print("Booted CPU #"..index) end
  487.         else
  488.             if micro.debug then print("CPU #"..index.." failed to boot: No LMRC connected.") end
  489.         end
  490.    
  491.     --Index the pins
  492.     MPU_Data[index].pins = {}
  493.     if MPU_Data[index].peripherals.LPIN then
  494.         for k, pin in ipairs(MPU_Data[index].peripherals.LPIN) do
  495.             local tmp = simulation.partProperty(pin,simulation.FIELD_TMP)
  496.             MPU_Data[index].pins[tmp] = pin
  497.         end
  498.     end
  499.    
  500.     --Index the hardware pins
  501.     MPU_Data[index].hwpins = {}
  502.     if MPU_Data[index].peripherals.LHWP then
  503.         for k, pin in ipairs(MPU_Data[index].peripherals.LHWP) do
  504.             local tmp = simulation.partProperty(pin,simulation.FIELD_TMP)
  505.             if not MPU_Data[index].hwpins[tmp] then MPU_Data[index].hwpins[tmp] = {} end
  506.             table.insert(MPU_Data[index].hwpins[tmp],pin)
  507.         end
  508.     end
  509.    
  510.         simulation.partProperty(index, simulation.FIELD_FLAGS, bit.bor(flags,256)) --Flag as booted
  511.     else --It booted before, tick now.
  512.         --MPU state hardware pins
  513.         local forceReset = false
  514.        
  515.         --Start Pin--
  516.         if checkHWPin(index,1) then
  517.             if MPU_Data[index].state == "Loaded" or MPU_Data[index].state == "Paused" then
  518.                 MPU_Data[index].state = "Running"
  519.             elseif MPU_Data[index].state == "Booted" then
  520.                 forceReset = true
  521.             end
  522.         end
  523.        
  524.         --Pause Pin--
  525.         if checkHWPin(index,3) then
  526.             if MPU_Data[index].state == "Running" then
  527.                 MPU_Data[index].state = "Paused"
  528.             end
  529.         end
  530.        
  531.         --Tick Pin--
  532.         if checkHWPin(index,4) then
  533.             if MPU_Data[index].state == "Running" then
  534.                 MPU_Data[index].state = "Paused"
  535.             end
  536.            
  537.             if MPU_Data[index].state == "Paused" then
  538.                 MPU_Data[index].state = "Tick"
  539.             end
  540.         end
  541.        
  542.         --Shutdown Pin--
  543.         if checkHWPin(index,2) then
  544.             if MPU_Data[index].state == "Running" or MPU_Data[index].state == "Paused" then
  545.                 MPU_Data[index].state = "Booted"
  546.             end
  547.         end
  548.        
  549.         --Reset Pin--
  550.         if checkHWPin(index,0) or forceReset then
  551.             local flags = simulation.partProperty(index, simulation.FIELD_FLAGS)
  552.             flags = bit.band(flags, bit.bnot(256))
  553.             simulation.partProperty(index, simulation.FIELD_FLAGS, flags) --Set the MPU to be unbooted.
  554.             MPU_Data[index] = nil --Delete all registered data.
  555.             _MPU_UPDATE(index, x, y, surround_space, nt) --Pre boot the MPU
  556.             if MPU_Data[index].state == "Loaded" then MPU_Data[index].state = "Running" end
  557.             return --Get out from the update function, the MPU should be run next tick.
  558.         end
  559.        
  560.         if MPU_Data[index].startPos[1] ~= x  or MPU_Data[index].startPos[2] ~= y  then
  561.             MPU_Data[index].state = "Dead"
  562.         end
  563.        
  564.         --The MPU freezes when sparked
  565.         if MPU_Data[index].co and coroutine.status(MPU_Data[index].co) == "suspended" and (MPU_Data[index].state == "Running" or MPU_Data[index].state == "Tick") and simulation.partProperty(index,simulation.FIELD_TYPE) == elem_id["LMPU"] then
  566.             if micro.quota then
  567.                 debug.sethook(MPU_Data[index].co, quotaErr, "", micro.quota)
  568.             end
  569.             local args = {coroutine.resume(MPU_Data[index].co,unpack(MPU_Data[index].lastRet))}
  570.             if not args[1] then
  571.                 print("CPU #"..index.." runtime error: "..tostring(args[2]))
  572.                 print(debug.traceback(MPU_Data[index].co))
  573.                 MPU_Data[index].co = false
  574.             else
  575.                 if args[2] and not MPU_CO_ID[args[2]] then
  576.                     MPU_Data[index].lastRet = {false, "Unknown Command '"..tostring(args[2]).."'"}
  577.                 elseif args[2] then
  578.                     for k,v in ipairs(args) do
  579.                         if k ~= 1 then
  580.                             args[k-1] = v
  581.                         end
  582.                     end
  583.                     table.remove(args,#args)
  584.                    
  585.                     local id = args[1]
  586.                     args[1] = index
  587.                     MPU_Data[index].lastRet = {MPU_CO_ID[id](unpack(args))}
  588.                 end
  589.             end
  590.             if MPU_Data[index].state == "Tick" then
  591.                 MPU_Data[index].state = "Paused"
  592.             end
  593.         end
  594.     end
  595. end
  596.  
  597. elements.property( elem_id["LMPU"], "Update", _MPU_UPDATE)
  598.  
  599. elements.property( elem_id["LMPU"], "Graphics", function(index, colr,colg,colb)
  600.   local col = {0,0,128}
  601.   if MPU_Data[index] and MPU_Data[index].color and
  602.     bit.band(simulation.partProperty(index, simulation.FIELD_FLAGS),256) ~= 0
  603.     then col = MPU_Data[index].color end
  604.   return 0, renderer.PMODE_FLAT+renderer.NO_DECO, 255, col[1], col[2], col[3], 0,0,0,0
  605. end)
  606.  
  607. elements.property( elem_id["LPIN"], "Update", function(index, x, y, surround_space, nt)
  608.   if simulation.partProperty(index,simulation.FIELD_TMP) == 0 then
  609.     local id = simulation.elementCount(elem_id["LPIN"])
  610.     simulation.partProperty(index,simulation.FIELD_TMP,id)
  611.     print("Assigned PIN ID Automatically #"..index.." -> "..id)
  612.   end
  613. end)
  614.  
  615. --Console Tools
  616. micro = {} --The MicroLua API
  617. micro.quota = 400000 --Scripts yielding quota
  618.  
  619. micro._MPUDATA = MPU_Data --So can be used for debugging reasons.
  620.  
  621. function micro.traceback(index)
  622.     if not index then
  623.         print([[USAGE: micro.traceback(<index>)
  624.         Prints the debug.traceback of an MPU
  625.         <index>: The LMPU part index.]])
  626.         return
  627.     end
  628.    
  629.     --Arguments type verification
  630.     if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
  631.    
  632.     --Part verification
  633.     local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
  634.     if not chipType then return error("No part exists with id #"..index) end
  635.     if chipType ~= elem_id["LMPU"] then return error("The given part is not a LMPU, instead it's: "..chipType) end
  636.    
  637.     if bit.band(simulation.partProperty(index, simulation.FIELD_FLAGS),256) == 0 then print("The MPU didn't boot yet !") return end
  638.     if not MPU_Data[index].co then print("The MPU code finished or failed to initialize.") return end
  639.     local trace = debug.traceback(MPU_Data[index].co)
  640.     print(trace)
  641. end
  642.  
  643. --Read data from a file and flushs it to a LMRC at a given index.
  644. function micro.flushMRC(index,filepath)
  645.     --Usage message
  646.     if not (index and filepath) then
  647.         print([[USAGE: micro.flushMRC(<index>,<filepath>)
  648. Reads data from a file and flushs it to a LMRC at a given index.
  649. <index>: The LMRC part index.
  650. <filepath>: The path to the file to read from.]])
  651.         return
  652.     end
  653.    
  654.     --Arguments type verification
  655.     if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
  656.     if type(filepath) ~= "string" then return error("Filepath must be a string, provided: "..type(filepath)) end
  657.    
  658.     --Part verification
  659.     local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
  660.     if not chipType then return error("No part exists with id #"..index) end
  661.     if chipType ~= elem_id["LMRC"] then return error("The given part is not a LMRC, instead it's: "..chipType) end
  662.    
  663.     --File verification
  664.     local file, ferr = io.open(filepath, "rb")
  665.     if not file then return error("Failed to open the file: "..tostring(ferr)) end
  666.    
  667.     --Load file data
  668.     local data = file:read("*a")
  669.     file:close()
  670.    
  671.     --Map the ROM indexes
  672.     local cx, cy = simulation.partPosition(index) --Controller position.
  673.     local mi = mapROM(cx+1,cy+1)
  674.    
  675.     --Check data size
  676.     local maxSize = (#mi-1)*8 --Every part can hold 8 bytes
  677.     if data:len() > maxSize then return error("Data too large to flash ("..data:len().." byte), max: "..maxSize.." byte") end
  678.    
  679.     --Flush the data
  680.     flushROM(mi, data)
  681.    
  682.     print("Flushed data successfully ("..math.ceil((data:len()/maxSize)*100).."%)")
  683. end
  684.  
  685. --Read data from a LMRC at a given index, and save it into a given file.
  686. function micro.dumpMRC(index,filepath)
  687.     --Usage message
  688.     if not (index and filepath) then
  689.         print([[USAGE: micro.dumpMRC(<index>,<filepath>)
  690. Read data from a LMRC at a given index, and save it into a given file.
  691. <index>: The LMRC part index.
  692. <filepath>: The path to the file to save to.]])
  693.         return
  694.     end
  695.    
  696.     --Arguments type verification
  697.     if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
  698.     if type(filepath) ~= "string" then return error("Filepath must be a string, provided: "..type(filepath)) end
  699.    
  700.     --Part verification
  701.     local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
  702.     if not chipType then return error("No part exists with id #"..index) end
  703.     if chipType ~= elem_id["LMRC"] then return error("The given part is not a LMRC, instead it's: "..chipType) end
  704.    
  705.     --File creation
  706.     local file, ferr = io.open(filepath, "wb")
  707.     if not file then return error("Failed to open the file: "..tostring(ferr)) end
  708.    
  709.     --Map the ROM indexes
  710.     local cx, cy = simulation.partPosition(index) --Controller position.
  711.     local mi = mapROM(cx+1,cy+1)
  712.    
  713.     --Get ROM data
  714.     local data = readROM(mi)
  715.    
  716.     --Save the data on the file
  717.     file:write(data)
  718.     file:flush()
  719.     file:close()
  720.    
  721.     print("Dumped data successfully")
  722. end
  723.  
  724. --Read data from a LMRC at a given index, and save it into a given file with all the null bytes removed/
  725. function micro.exportMRC(index,filepath)
  726.     --Usage message
  727.     if not (index and filepath) then
  728.         print([[USAGE: micro.exportMRC(<index>,<filepath>)
  729. Read data from a LMRC at a given index, and save it into a given file,
  730. With all the null (0) bytes removed.
  731. <index>: The LMRC part index.
  732. <filepath>: The path to the file to save to.]])
  733.         return
  734.     end
  735.    
  736.     --Arguments type verification
  737.     if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
  738.     if type(filepath) ~= "string" then return error("Filepath must be a string, provided: "..type(filepath)) end
  739.    
  740.     --Part verification
  741.     local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
  742.     if not chipType then return error("No part exists with id #"..index) end
  743.     if chipType ~= elem_id["LMRC"] then return error("The given part is not a LMRC, instead it's: "..chipType) end
  744.    
  745.     --File creation
  746.     local file, ferr = io.open(filepath, "wb")
  747.     if not file then return error("Failed to open the file: "..tostring(ferr)) end
  748.    
  749.     --Map the ROM indexes
  750.     local cx, cy = simulation.partPosition(index) --Controller position.
  751.     local mi = mapROM(cx+1,cy+1)
  752.    
  753.     --Get ROM data
  754.     local data = readROM(mi)
  755.   data = removeNulls(data)
  756.    
  757.     --Save the data on the file
  758.     file:write(data)
  759.     file:flush()
  760.     file:close()
  761.    
  762.     print("Exported data successfully")
  763. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement