Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Last Update: 19/10/2017 12:30 PM
- --Official MicroLua Stamps save id:2151133
- --https://pastebin.com/Jt5eE4aP
- --UserManual: https://github.com/RamiLego4Game/TPTMicroLua/blob/master/UserManual.md
- --TODO:
- --[[
- # Base LCBL on TUNG and make it unconductive (DONE).
- # MPU setColor() (DONE).
- # spark({pinlist}) to spark more than one pin. (DONE).
- # LHWP to start, stop or reset the MPU. (DONE).
- # MPU TMP 1 wont autoboot the MPU. (DONE).
- X MPU heats up every tick, and cools down when tick() is called (Canceled).
- # MPU freezes when it's sparked. (DONE).
- # isSparked({pinlist}) will return true if all the pins are sparked. (DONE).
- # isSparked({pinlist}, true) will return a table with boolean values. (DONE).
- # isSparked() returns the id of a sparked pin, or false if none are sparked. (DONE).
- ]]
- --Creating the elements--
- local elem_group = "MLUA"
- local elem_names = { "LMPU", "LCBL", "LPIN", "LHWP", "LMRC", "LROM" } --The names of the elements to allocate
- local elem_id = {} --A table containing the ids of every name in elem_names, [name] = id.
- local elem_name = {} --A table to get the name from the id
- --Allocate the elements
- for k, name in ipairs(elem_names) do
- if elements[elem_group.."_PT_"..name] then elements.free(elements[elem_group.."_PT_"..name]) end --Incase the script errored
- local id = elements.allocate(elem_group, name)
- if id == -1 then --(It failed)
- error("Failed to allocate an element, please disable some elements scripts !")
- return --Abort the script
- else
- elem_id[name] = id
- elem_name[id] = name
- end
- end
- local elem_clone = { --New elements properties; _Parent is a special key that clones properties from a default elements before applying the changes.
- ["LMPU"] = {
- _Parent = "METL",
- Name = "LMPU",
- Description = "Lua Microprocessor Unit, used for advanced electornics",
- Color = 0x000080, --The color of the Lua logo ;)
- MenuSection = elements.SC_POWERED
- },
- ["LCBL"] = {
- _Parent = "METL",
- Name = "LCBL",
- Description = "Lua Cable, used for connecting peripherals with LMPU",
- Properties = bit.bor(elements.TYPE_SOLID,elements.PROP_HOT_GLOW),
- HightTemperature = 1687,
- Color = 0x505050, --TUNG color
- MenuSection = elements.SC_POWERED
- },
- ["LPIN"] = {
- _Parent = "METL",
- Name = "LPIN",
- Description = "Lua Pin, Connects as GPIO pin peripheral. TMP as id",
- Color = 0xE0E0E0,
- MenuSection = elements.SC_POWERED
- },
- ["LHWP"] = {
- _Parent = "METL",
- Name = "LHWP",
- Description = "Lua Hardware Pin, Controles the MPU state, TMP is mode (0=reset, 1=start, 2=shutdown, 3=pause, 4=tick)",
- Color = 0xC0E0FF,
- MenuSection = elements.SC_POWERED
- },
- ["LMRC"] = {
- _Parent = "METL",
- Name = "LMRC",
- Description = "Lua Memory Reading Controller peripheral. Speciallized in reading LROM",
- Color = 0xF4BC42,
- MenuSection = elements.SC_POWERED
- },
- ["LROM"] = {
- _Parent = "METL",
- Name = "LROM",
- Description = "Lua Read Only Memory, Stores 8 Bytes (8 Ascii Characters)",
- Properties = bit.bor(elements.TYPE_SOLID,elements.PROP_HOT_GLOW),
- HightTemperature = 1687,
- Color = 0xFFFFFF, --White
- MenuSection = elements.SC_POWERED
- }
- }
- --Applying the properties
- for name, props in pairs(elem_clone) do
- if not elem_id[name] then error("Un-allocated element: "..name..", report this to the developer !") end
- if props._Parent then elements.element(elem_id[name],elements.element(elements["DEFAULT_PT_"..props._Parent])); props._Parent = nil end --Do the clonning
- elements.element(elem_id[name],props) --Set the properties
- end
- local elem_peripherals = {[ elem_id["LPIN"] ] = true, [ elem_id["LHWP"] ] = true, [ elem_id["LMRC"] ] = true} --Use elem_id (for easier programming)
- --SC (self call) is a special argument, don't use it !
- local mappedIndexes, mappedPeripherals = {}, {}
- local function mapCables(x,y, sc)
- if not sc then mappedIndexes, mappedPeripherals = {}, {} end --Reset the maps
- mappedIndexes[simulation.partID(x,y)] = true --Set the current part as mapped.
- local parts = simulation.partNeighbors(x,y, 3) --Scan the around parts.
- for _, index in ipairs(parts) do
- if not mappedIndexes[index] then
- local px, py = simulation.partPosition(index)
- local ptype = simulation.partProperty(index,simulation.FIELD_TYPE)
- if ptype == elements.DEFAULT_PT_SPRK then ptype = simulation.partProperty(index,simulation.FIELD_CTYPE) end
- if elem_peripherals[ptype] then --It's a peripheral !
- mappedIndexes[index] = true --So don't double detect the peripheral
- if not mappedPeripherals[elem_name[ptype]] then mappedPeripherals[elem_name[ptype]] = {} end
- table.insert(mappedPeripherals[elem_name[ptype]],index)
- elseif elem_id["LCBL"] == ptype then --It's a cable
- mapCables(px,py, true)
- end
- end
- end
- if not sc then return mappedPeripherals end
- end
- local function mapROM(x,y)
- --X, Y should be the position of the top-left corner.
- local mi = {} --Mapped Indexes
- local cy = 0
- while true do
- local ypid = simulation.partID(x,y+cy)
- if not ypid then break end
- if simulation.partProperty(ypid, simulation.FIELD_TYPE) ~= elem_id["LROM"] then break end --The end of rom block
- local cx = 0
- while true do
- local pid = simulation.partID(x+cx,y+cy)
- if not pid then break end --No Part
- if simulation.partProperty(pid, simulation.FIELD_TYPE) ~= elem_id["LROM"] then break end --The end of rom line
- table.insert(mi,pid)
- cx = cx + 1
- end
- cy = cy + 1
- end
- return mi
- end
- --Reads the ROM string, must provide the mappedIndexes array (That can be obtained by mapROM(x,y))
- local function readROM(mi)
- local data = ""
- for _, index in ipairs(mi) do
- local ctype = simulation.partProperty(index, simulation.FIELD_CTYPE) --1 byte
- local dcolor = simulation.partProperty(index, simulation.FIELD_DCOLOUR) --4 bytes
- local life = simulation.partProperty(index, simulation.FIELD_LIFE) --1 byte
- local tmp = simulation.partProperty(index, simulation.FIELD_TMP) --1 byte
- local tmp2 = simulation.partProperty(index, simulation.FIELD_TMP2) --1 byte
- ctype = string.char(ctype)
- local cola = string.char(bit.band(dcolor,255))
- local colr = string.char(bit.band(bit.rshift(dcolor,8),255))
- local colg = string.char(bit.band(bit.rshift(dcolor,16),255))
- local colb = string.char(bit.band(bit.rshift(dcolor,24),255))
- life = string.char(life)
- tmp = string.char(tmp)
- tmp2 = string.char(tmp2)
- data = data .. ctype..cola..colr..colg..colb..life..tmp..tmp2
- end
- return data
- end
- --Writes the ROM string, must provide the mappedIndexes arrays (That can be obtained by mapROM(x,y)) and the data string.
- local function flushROM(mi,data)
- data = data.." "
- local dataBytes = {}
- for i=1,data:len() do
- table.insert(dataBytes,string.byte(data:sub(i,i)))
- end
- local curByte = 0
- local function nextByte()
- if #dataBytes == curByte then return 0 end
- curByte = curByte + 1
- return dataBytes[curByte]
- end
- for _, index in ipairs(mi) do
- simulation.partProperty(index, simulation.FIELD_CTYPE, nextByte()) --1 bytes
- local cola = nextByte()
- local colr = bit.lshift(nextByte(),8)
- local colg = bit.lshift(nextByte(),16)
- local colb = bit.lshift(nextByte(),24)
- local dcolor = bit.bor(cola,colr,colg,colb)
- simulation.partProperty(index, simulation.FIELD_DCOLOUR, dcolor) --4 bytes
- simulation.partProperty(index, simulation.FIELD_LIFE, nextByte()) --1 byte
- simulation.partProperty(index, simulation.FIELD_TMP, nextByte()) --1 byte
- simulation.partProperty(index, simulation.FIELD_TMP2, nextByte()) --1 byte
- end
- end
- local MPU_Data = {}
- --MPU API
- local MPU_API = {}
- local function addAPI(func,name,parent)
- local t = MPU_API
- if parent then
- if not t[parent] then t[parent] = {} end
- t = t[parent]
- end
- t[name] = function(index,...)
- return pcall(func,...)
- end
- end
- MPU_API.tick = function(index)
- return true
- end
- MPU_API.spark = function(index,pids)
- if type(pids) ~= "number" and type(pids) ~= "table" then return false, "Pin ID must be a number or a table, provided: "..type(pids) end
- if type(pids) == "number" then pids = {pids} end
- if #pids == 1 then
- if type(pids[1]) ~= "number" then return false, "#1 Pin must be a number, provided: "..type(pids[1]) end
- pids[1] = math.floor(pids[1])
- if not MPU_Data[index].pins[pids[1]] then return false, "Pin ("..pids[1]..") doesn't exists !" end
- else
- for k, pid in ipairs(pids) do
- if type(pid) ~= "number" then return false, "#"..k.." Pin must be a number, provided: "..type(pid) end
- pid = math.floor(pid); pids[k] = pid
- if not MPU_Data[index].pins[pid] then return false, "#"..k.." Pin ("..pid..") doesn't exists !" end
- end
- end
- for k, pid in ipairs(pids) do
- local pindex = MPU_Data[index].pins[pid]
- local px, py = simulation.partPosition(pindex) --Pin position
- simulation.partCreate(-1,px,py,elements.DEFAULT_PT_SPRK) --Spark the pin
- end
- return true --It ran successully
- end
- MPU_API.isSparked = function(index,pids,getlist)
- 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
- if type(pids) == "number" then
- local pid = math.floor(pids)
- if not MPU_Data[index].pins[pid] then return false, "Pin ("..pid..") doesn't exists !" end
- local pindex = MPU_Data[index].pins[pid]
- local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
- if ptype == elements.DEFAULT_PT_SPRK then
- return true, true
- else
- return true, false
- end
- elseif type(pids) == "table" then
- for k,pid in ipairs(pids) do
- if type(pid) ~= "number" then return false, "#"..k.." Pins must be a number, provided: "..type(pid) end
- pid = math.floor(pid); pids[k] = pid
- if not MPU_Data[index].pins[pid] then return false, "Pin ("..pid..") doesn't exists !" end
- end
- if getlist then
- local result = {}
- for k,pid in ipairs(pids) do
- local pindex = MPU_Data[index].pins[pid]
- local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
- if ptype == elements.DEFAULT_PT_SPRK then
- result[k] = true
- else
- result[k] = false
- end
- end
- return true, result
- else
- for k,pid in ipairs(pids) do
- local pindex = MPU_Data[index].pins[pid]
- local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
- if ptype ~= elements.DEFAULT_PT_SPRK then
- return true, false, pid --A pin is not sparked.
- end
- end
- return true, true
- end
- else
- for k, pindex in ipairs(MPU_Data[index].pins) do
- local ptype = simulation.partProperty(pindex,simulation.FIELD_TYPE)
- if ptype == elements.DEFAULT_PT_SPRK then
- return true, pid --A pin is sparked.
- end
- end
- return true, false --No pins are sparked.
- end
- end
- MPU_API.setColor = function(index,color)
- local color = color or {0,0,128}
- if type(color) ~= "table" then return false, "Color must be a table, provided: "..type(color) end
- for i=1, 3 do if type(color[i]) ~= "number" then return false, "Wrong color table" end end
- for i=1, 3 do MPU_Data[index].color[i] = color[i] or MPU_Data[index].color[i] end
- return true
- end
- local toClone = {
- "pairs", "ipairs", "next", "_VERSION",
- "pcall", "xpcall", "print", "select", "type", "tostring", "tonumber", "unpack",
- table = {
- "insert", "remove", "maxn", "sort", "concat"
- },
- math = {
- "abs", "fmod", "floor", "ceil", "min", "max", "modf",
- "sqrt", "pow", "exp", "log", "log10", "frexp", "ldexp",
- "deg", "rad", "sin", "cos", "tan", "asin", "acos", "atan",
- "random", "randomseed", "pi", "huge"
- },
- string = {
- "len", "sub", "rep", "upper", "lower", "reverse", "byte", "char", "format",
- "find", "gmatch", "match", "gsub"
- },
- coroutine = {
- "create", "resume", "running", "status", "wrap"
- },
- os = {
- "time", "difftime", "date", "clock"
- },
- bit = {
- "tobit", "tohex", "bnot", "band", "bor", "bxor", "lshift", "rshift", "arshift", "rol", "ror", "bswap"
- }
- }
- --Clone Lua Libraries
- for k,v in pairs(toClone) do
- if type(v) == "string" then
- addAPI(_G[v],v)
- else
- for k2, v2 in ipairs(v) do
- addAPI(_G[k][v2],v2,k)
- end
- end
- end
- --Index MPU_API functions and Build MPU Coroutine Sandbox
- local MPU_CO_ID, MPU_CO_GLOB = {}, {}
- local function indexMPU_API(t,pre,g)
- local t = t or MPU_API
- local pre = pre or ""
- local g = g or MPU_CO_GLOB
- for k, v in pairs(t) do
- if type(v) == "table" then
- g[k] = {}
- indexMPU_API(v,pre..k..".",g[k])
- else
- MPU_CO_ID[pre..k] = v
- local coyield = coroutine.yield
- local ipairs = ipairs
- local error = error
- local unpack = unpack
- local tablerem = table.remove
- g[k] = function(...)
- local ret = {coyield(pre..k, ...)}
- if not ret[1] then return error(tostring(ret[2])) end
- for k,v in ipairs(ret) do
- if k ~= 1 then
- ret[k-1] = v
- end
- end
- tablerem(ret,#ret)
- return unpack(ret)
- end
- end
- end
- end
- indexMPU_API()
- MPU_CO_GLOB.error = error
- MPU_CO_GLOB.assert = assert
- --Internal Helping Functions
- MPU_CO_GLOB.sleep = function(t) for i=1, t do coroutine.yield("tick") end end
- MPU_CO_GLOB.coroutine.yield = coroutine.yield
- local function NewSandbox(g)
- local s = {}
- local g = g or MPU_CO_GLOB
- for k,v in pairs(g) do
- if type(v) == "table" then
- s[k] = NewSandbox(g[k])
- else
- s[k] = v
- end
- end
- if g == MPU_CO_GLOB then s._G = s end
- return s
- end
- local function removeNulls(str)
- local null = string.char(0)
- local nstr = ""
- for i=1, #str do
- local c = str:sub(i,i)
- if c ~= null then
- nstr = nstr..c
- end
- end
- return nstr
- end
- local function quotaErr() --Protects us from infinite loops !
- error("Quota exceeded: "..micro.quota,2)
- end
- local function checkHWPin(index,pintmp)
- local flag = false
- if MPU_Data[index].hwpins[pintmp] then
- for k,pin in ipairs(MPU_Data[index].hwpins[pintmp]) do
- if simulation.partProperty(pin,simulation.FIELD_TYPE) == elements.DEFAULT_PT_SPRK then
- if not MPU_Data[index].sparkFilter[pin] then
- MPU_Data[index].sparkFilter[pin] = true
- flag = true
- end
- else
- if MPU_Data[index].sparkFilter[pin] then
- MPU_Data[index].sparkFilter[pin] = false --The spark pulse ended
- end
- end
- end
- end
- return flag
- end
- local _LuaBCHeader = ( jit and (string.char(0x1B).."LJ") or (string.char(0x1B).."Lua"))
- --Elements Update
- local function _MPU_UPDATE(index, x, y, surround_space, nt)
- local flags = simulation.partProperty(index, simulation.FIELD_FLAGS)
- --Check if the processor did boot yet or not.
- --I found that it's safe to use the second byte of FLAGS
- --And why I'm using flags because it's not saved ;)
- --The first bit will be the boot state, 0 = off, 1 = booted.
- if bit.band(flags, 256) == 0 then --It did not boot yet !
- MPU_Data[index] = {} --Override the old one if exists.
- MPU_Data[index].state = "Booted"
- MPU_Data[index].color = {0,0,128}
- MPU_Data[index].peripherals = mapCables(x,y)
- MPU_Data[index].startPos = {x,y}
- MPU_Data[index].sparkFilter = {}
- --Load the code
- if MPU_Data[index].peripherals.LMRC then
- local ichip = MPU_Data[index].peripherals.LMRC[1]
- local x,y = simulation.partPosition(ichip)
- local rom = mapROM(x+1,y+1)
- local data = readROM(rom)
- data = removeNulls(data)
- local chunk, cerr
- if data:sub(0,4) == _LuaBCHeader then
- cerr = "Lua Bytecode is NOT ALLOWED ! YOU HACKER"
- else
- chunk, cerr = loadstring(data)
- end
- if not chunk then
- MPU_Data[index].err = cerr
- print("CPU #"..index.." CERR: "..cerr)
- else
- local glob = NewSandbox()
- setfenv(chunk,glob)
- local co = coroutine.create(chunk)
- if simulation.partProperty(index,simulation.FIELD_TMP) == 1 then
- MPU_Data[index].state = "Loaded"
- else
- MPU_Data[index].state = "Running"
- end
- MPU_Data[index].chunk = chunk
- MPU_Data[index].co = co
- MPU_Data[index].glob = glob
- MPU_Data[index].lastRet = {}
- end
- if micro.debug then print("Booted CPU #"..index) end
- else
- if micro.debug then print("CPU #"..index.." failed to boot: No LMRC connected.") end
- end
- --Index the pins
- MPU_Data[index].pins = {}
- if MPU_Data[index].peripherals.LPIN then
- for k, pin in ipairs(MPU_Data[index].peripherals.LPIN) do
- local tmp = simulation.partProperty(pin,simulation.FIELD_TMP)
- MPU_Data[index].pins[tmp] = pin
- end
- end
- --Index the hardware pins
- MPU_Data[index].hwpins = {}
- if MPU_Data[index].peripherals.LHWP then
- for k, pin in ipairs(MPU_Data[index].peripherals.LHWP) do
- local tmp = simulation.partProperty(pin,simulation.FIELD_TMP)
- if not MPU_Data[index].hwpins[tmp] then MPU_Data[index].hwpins[tmp] = {} end
- table.insert(MPU_Data[index].hwpins[tmp],pin)
- end
- end
- simulation.partProperty(index, simulation.FIELD_FLAGS, bit.bor(flags,256)) --Flag as booted
- else --It booted before, tick now.
- --MPU state hardware pins
- local forceReset = false
- --Start Pin--
- if checkHWPin(index,1) then
- if MPU_Data[index].state == "Loaded" or MPU_Data[index].state == "Paused" then
- MPU_Data[index].state = "Running"
- elseif MPU_Data[index].state == "Booted" then
- forceReset = true
- end
- end
- --Pause Pin--
- if checkHWPin(index,3) then
- if MPU_Data[index].state == "Running" then
- MPU_Data[index].state = "Paused"
- end
- end
- --Tick Pin--
- if checkHWPin(index,4) then
- if MPU_Data[index].state == "Running" then
- MPU_Data[index].state = "Paused"
- end
- if MPU_Data[index].state == "Paused" then
- MPU_Data[index].state = "Tick"
- end
- end
- --Shutdown Pin--
- if checkHWPin(index,2) then
- if MPU_Data[index].state == "Running" or MPU_Data[index].state == "Paused" then
- MPU_Data[index].state = "Booted"
- end
- end
- --Reset Pin--
- if checkHWPin(index,0) or forceReset then
- local flags = simulation.partProperty(index, simulation.FIELD_FLAGS)
- flags = bit.band(flags, bit.bnot(256))
- simulation.partProperty(index, simulation.FIELD_FLAGS, flags) --Set the MPU to be unbooted.
- MPU_Data[index] = nil --Delete all registered data.
- _MPU_UPDATE(index, x, y, surround_space, nt) --Pre boot the MPU
- if MPU_Data[index].state == "Loaded" then MPU_Data[index].state = "Running" end
- return --Get out from the update function, the MPU should be run next tick.
- end
- if MPU_Data[index].startPos[1] ~= x or MPU_Data[index].startPos[2] ~= y then
- MPU_Data[index].state = "Dead"
- end
- --The MPU freezes when sparked
- 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
- if micro.quota then
- debug.sethook(MPU_Data[index].co, quotaErr, "", micro.quota)
- end
- local args = {coroutine.resume(MPU_Data[index].co,unpack(MPU_Data[index].lastRet))}
- if not args[1] then
- print("CPU #"..index.." runtime error: "..tostring(args[2]))
- print(debug.traceback(MPU_Data[index].co))
- MPU_Data[index].co = false
- else
- if args[2] and not MPU_CO_ID[args[2]] then
- MPU_Data[index].lastRet = {false, "Unknown Command '"..tostring(args[2]).."'"}
- elseif args[2] then
- for k,v in ipairs(args) do
- if k ~= 1 then
- args[k-1] = v
- end
- end
- table.remove(args,#args)
- local id = args[1]
- args[1] = index
- MPU_Data[index].lastRet = {MPU_CO_ID[id](unpack(args))}
- end
- end
- if MPU_Data[index].state == "Tick" then
- MPU_Data[index].state = "Paused"
- end
- end
- end
- end
- elements.property( elem_id["LMPU"], "Update", _MPU_UPDATE)
- elements.property( elem_id["LMPU"], "Graphics", function(index, colr,colg,colb)
- local col = {0,0,128}
- if MPU_Data[index] and MPU_Data[index].color and
- bit.band(simulation.partProperty(index, simulation.FIELD_FLAGS),256) ~= 0
- then col = MPU_Data[index].color end
- return 0, renderer.PMODE_FLAT+renderer.NO_DECO, 255, col[1], col[2], col[3], 0,0,0,0
- end)
- elements.property( elem_id["LPIN"], "Update", function(index, x, y, surround_space, nt)
- if simulation.partProperty(index,simulation.FIELD_TMP) == 0 then
- local id = simulation.elementCount(elem_id["LPIN"])
- simulation.partProperty(index,simulation.FIELD_TMP,id)
- print("Assigned PIN ID Automatically #"..index.." -> "..id)
- end
- end)
- --Console Tools
- micro = {} --The MicroLua API
- micro.quota = 400000 --Scripts yielding quota
- micro._MPUDATA = MPU_Data --So can be used for debugging reasons.
- function micro.traceback(index)
- if not index then
- print([[USAGE: micro.traceback(<index>)
- Prints the debug.traceback of an MPU
- <index>: The LMPU part index.]])
- return
- end
- --Arguments type verification
- if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
- --Part verification
- local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
- if not chipType then return error("No part exists with id #"..index) end
- if chipType ~= elem_id["LMPU"] then return error("The given part is not a LMPU, instead it's: "..chipType) end
- if bit.band(simulation.partProperty(index, simulation.FIELD_FLAGS),256) == 0 then print("The MPU didn't boot yet !") return end
- if not MPU_Data[index].co then print("The MPU code finished or failed to initialize.") return end
- local trace = debug.traceback(MPU_Data[index].co)
- print(trace)
- end
- --Read data from a file and flushs it to a LMRC at a given index.
- function micro.flushMRC(index,filepath)
- --Usage message
- if not (index and filepath) then
- print([[USAGE: micro.flushMRC(<index>,<filepath>)
- Reads data from a file and flushs it to a LMRC at a given index.
- <index>: The LMRC part index.
- <filepath>: The path to the file to read from.]])
- return
- end
- --Arguments type verification
- if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
- if type(filepath) ~= "string" then return error("Filepath must be a string, provided: "..type(filepath)) end
- --Part verification
- local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
- if not chipType then return error("No part exists with id #"..index) end
- if chipType ~= elem_id["LMRC"] then return error("The given part is not a LMRC, instead it's: "..chipType) end
- --File verification
- local file, ferr = io.open(filepath, "rb")
- if not file then return error("Failed to open the file: "..tostring(ferr)) end
- --Load file data
- local data = file:read("*a")
- file:close()
- --Map the ROM indexes
- local cx, cy = simulation.partPosition(index) --Controller position.
- local mi = mapROM(cx+1,cy+1)
- --Check data size
- local maxSize = (#mi-1)*8 --Every part can hold 8 bytes
- if data:len() > maxSize then return error("Data too large to flash ("..data:len().." byte), max: "..maxSize.." byte") end
- --Flush the data
- flushROM(mi, data)
- print("Flushed data successfully ("..math.ceil((data:len()/maxSize)*100).."%)")
- end
- --Read data from a LMRC at a given index, and save it into a given file.
- function micro.dumpMRC(index,filepath)
- --Usage message
- if not (index and filepath) then
- print([[USAGE: micro.dumpMRC(<index>,<filepath>)
- Read data from a LMRC at a given index, and save it into a given file.
- <index>: The LMRC part index.
- <filepath>: The path to the file to save to.]])
- return
- end
- --Arguments type verification
- if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
- if type(filepath) ~= "string" then return error("Filepath must be a string, provided: "..type(filepath)) end
- --Part verification
- local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
- if not chipType then return error("No part exists with id #"..index) end
- if chipType ~= elem_id["LMRC"] then return error("The given part is not a LMRC, instead it's: "..chipType) end
- --File creation
- local file, ferr = io.open(filepath, "wb")
- if not file then return error("Failed to open the file: "..tostring(ferr)) end
- --Map the ROM indexes
- local cx, cy = simulation.partPosition(index) --Controller position.
- local mi = mapROM(cx+1,cy+1)
- --Get ROM data
- local data = readROM(mi)
- --Save the data on the file
- file:write(data)
- file:flush()
- file:close()
- print("Dumped data successfully")
- end
- --Read data from a LMRC at a given index, and save it into a given file with all the null bytes removed/
- function micro.exportMRC(index,filepath)
- --Usage message
- if not (index and filepath) then
- print([[USAGE: micro.exportMRC(<index>,<filepath>)
- Read data from a LMRC at a given index, and save it into a given file,
- With all the null (0) bytes removed.
- <index>: The LMRC part index.
- <filepath>: The path to the file to save to.]])
- return
- end
- --Arguments type verification
- if type(index) ~= "number" then return error("Index must be a number, provided: "..type(index)) end
- if type(filepath) ~= "string" then return error("Filepath must be a string, provided: "..type(filepath)) end
- --Part verification
- local chipType = simulation.partProperty(index, simulation.FIELD_TYPE)
- if not chipType then return error("No part exists with id #"..index) end
- if chipType ~= elem_id["LMRC"] then return error("The given part is not a LMRC, instead it's: "..chipType) end
- --File creation
- local file, ferr = io.open(filepath, "wb")
- if not file then return error("Failed to open the file: "..tostring(ferr)) end
- --Map the ROM indexes
- local cx, cy = simulation.partPosition(index) --Controller position.
- local mi = mapROM(cx+1,cy+1)
- --Get ROM data
- local data = readROM(mi)
- data = removeNulls(data)
- --Save the data on the file
- file:write(data)
- file:flush()
- file:close()
- print("Exported data successfully")
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement