2013-11-30 19:43:31 +01:00
|
|
|
local CYCLES_PER_STEP = 1000
|
|
|
|
local MAX_CYCLES = 100000
|
|
|
|
|
|
|
|
local function file_exists(name)
|
|
|
|
local f = io.open(name, "r")
|
|
|
|
if f then
|
|
|
|
f:close()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2015-01-25 10:24:10 +01:00
|
|
|
local function loadpkg(na)
|
|
|
|
local modpath = minetest.get_modpath("turtle")
|
2013-11-30 19:43:31 +01:00
|
|
|
local ol = package.cpath
|
|
|
|
local sp
|
|
|
|
if file_exists(modpath.."/INIT.LUA") then
|
|
|
|
-- On windows, if we try to open the others we get a crash
|
|
|
|
-- even with pcall
|
|
|
|
sp = {modpath.."/?.dll"}
|
|
|
|
else
|
|
|
|
sp = {modpath.."/?.so.32", modpath.."/?.so.64"}
|
|
|
|
end
|
2015-01-25 10:24:10 +01:00
|
|
|
for i=1, #sp do
|
2013-11-30 19:43:31 +01:00
|
|
|
package.cpath = sp[i]
|
|
|
|
e, lib = pcall(require, na)
|
|
|
|
package.cpath = ol
|
|
|
|
if e then
|
|
|
|
return lib
|
|
|
|
end
|
|
|
|
end
|
|
|
|
package.cpath = ol
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
local modpath = minetest.get_modpath("turtle")
|
|
|
|
|
|
|
|
if bit32 == nil and jit == nil then
|
|
|
|
-- No need to use the library if LuaJIT is there, the Lua one is more efficient
|
|
|
|
bit32 = loadpkg("bit32")
|
|
|
|
end
|
|
|
|
if bit32 == nil then
|
|
|
|
-- bit32 has not been loaded, using a Lua implementation of what we need
|
|
|
|
dofile(modpath.."/bit32.lua")
|
|
|
|
if jit == nil then
|
|
|
|
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "..
|
|
|
|
"WARNING: bit32 could not loaded, you should fix"..
|
|
|
|
" that or use LuaJIT for better performance"..
|
|
|
|
" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-12-07 16:46:01 +01:00
|
|
|
function s16(x)
|
2013-11-30 19:43:31 +01:00
|
|
|
if bit32.band(x, 0x8000)~=0 then
|
|
|
|
return bit32.band(x, 0xffff)-0x10000
|
|
|
|
end
|
|
|
|
return bit32.band(x, 0xffff)
|
|
|
|
end
|
|
|
|
|
2013-12-07 16:46:01 +01:00
|
|
|
function u16(x)
|
2013-11-30 19:43:31 +01:00
|
|
|
return bit32.band(x, 0xffff)
|
|
|
|
end
|
|
|
|
|
2013-12-07 16:46:01 +01:00
|
|
|
function s32(x)
|
2013-11-30 19:43:31 +01:00
|
|
|
if bit32.band(x, 0x80000000)~=0 then
|
|
|
|
return bit32.band(x, 0xffffffff)-0x100000000
|
|
|
|
end
|
|
|
|
return bit32.band(x, 0xffffffff)
|
|
|
|
end
|
|
|
|
|
2013-12-07 16:46:01 +01:00
|
|
|
function u32(x)
|
2013-11-30 19:43:31 +01:00
|
|
|
return bit32.band(x, 0xffffffff)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function readC(cptr, addr)
|
|
|
|
return cptr[addr]
|
|
|
|
end
|
|
|
|
|
|
|
|
local function writeC(cptr, addr, value)
|
|
|
|
cptr[addr] = bit32.band(value, 0xff)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function read(cptr, addr)
|
|
|
|
return cptr[addr] + 256*cptr[u16(addr+1)]
|
|
|
|
end
|
|
|
|
|
|
|
|
local function write(cptr, addr, value)
|
|
|
|
cptr[addr] = bit32.band(value, 0xff)
|
|
|
|
cptr[addr+1] = bit32.band(math.floor(value/256), 0xff)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function push(cptr, value)
|
|
|
|
cptr.SP = u16(cptr.SP+2)
|
|
|
|
write(cptr, cptr.SP, value)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function pop(cptr, value)
|
|
|
|
local n = read(cptr, cptr.SP)
|
|
|
|
cptr.SP = u16(cptr.SP-2)
|
|
|
|
return n
|
|
|
|
end
|
|
|
|
|
|
|
|
local function rpush(cptr, value)
|
|
|
|
cptr.RP = u16(cptr.RP+2)
|
|
|
|
write(cptr, cptr.RP, value)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function rpop(cptr, value)
|
|
|
|
local n = read(cptr, cptr.RP)
|
|
|
|
cptr.RP = u16(cptr.RP-2)
|
|
|
|
return n
|
|
|
|
end
|
|
|
|
|
|
|
|
local function string_at(cptr, addr, len)
|
|
|
|
local l = {}
|
|
|
|
for k=1, len do
|
|
|
|
local i = u16(addr+k-1)
|
|
|
|
local s = cptr[i]
|
|
|
|
l[k] = string.char(s)
|
|
|
|
end
|
|
|
|
return table.concat(l, "")
|
|
|
|
end
|
|
|
|
|
|
|
|
local function receive(cptr, caddr, clen, raddr)
|
|
|
|
local channel = string_at(cptr, caddr, clen)
|
|
|
|
local event = cptr.digiline_events[channel]
|
|
|
|
if event and type(event)=="string" then
|
|
|
|
if string.len(event)>80 then
|
|
|
|
event = string.sub(event,1,80)
|
|
|
|
end
|
|
|
|
for i=1,string.len(event) do
|
|
|
|
cptr[u16(raddr-1+i)] = string.byte(event,i)
|
|
|
|
end
|
|
|
|
cptr.X = string.len(event)
|
|
|
|
else
|
|
|
|
cptr.X = u16(-1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function delete_message(cptr, caddr, clen)
|
|
|
|
local channel = string_at(cptr, caddr, clen)
|
|
|
|
cptr.digiline_events[channel] = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
local function set_channel(cptr, caddr, clen)
|
|
|
|
local channel = string_at(cptr, caddr, clen)
|
|
|
|
cptr.channel = channel
|
|
|
|
end
|
|
|
|
|
|
|
|
local function send_message(turtle, cptr, maddr, mlen)
|
|
|
|
local msg = string_at(cptr, maddr, mlen)
|
|
|
|
cptr.digiline_events[cptr.channel] = msg
|
|
|
|
turtle_receptor_send(turtle, cptr.channel, msg)
|
|
|
|
end
|
|
|
|
|
2013-12-07 16:46:01 +01:00
|
|
|
dofile(modpath.."/api.lua")
|
2013-11-30 19:43:31 +01:00
|
|
|
|
|
|
|
function run_computer(turtle, cptr)
|
|
|
|
if cptr.stopped then return end
|
2015-01-25 10:24:10 +01:00
|
|
|
cptr.cycles = math.max(MAX_CYCLES, cptr.cycles + CYCLES_PER_STEP)
|
|
|
|
while true do
|
2015-01-25 10:31:23 +01:00
|
|
|
local instr = cptr[cptr.PC]
|
2013-11-30 19:43:31 +01:00
|
|
|
local f = ITABLE[instr]
|
|
|
|
if f == nil then return end
|
2015-01-25 10:24:10 +01:00
|
|
|
cptr.PC = u16(cptr.PC + 1)
|
|
|
|
setfenv(f, {cptr = cptr, turtle = turtle, receive = receive, delete_message = delete_message, set_channel = set_channel, send_message = send_message, u16 = u16, u32 = u32, s16 = s16, s32 = s32, read = read, write = write, readC = readC, writeC = writeC, push = push, pop = pop, rpush = rpush, rpop = rpop, bit32 = bit32, math = math, tl = tl})
|
2013-11-30 19:43:31 +01:00
|
|
|
f()
|
|
|
|
cptr.cycles = cptr.cycles - 1
|
|
|
|
if cptr.paused or cptr.cycles <= 0 then
|
|
|
|
cptr.paused = false
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function create_cptr()
|
|
|
|
local cptr = create_cptr_memory()
|
|
|
|
cptr.X = 0
|
|
|
|
cptr.Y = 0
|
|
|
|
cptr.Z = 0
|
|
|
|
cptr.I = 0
|
|
|
|
cptr.PC = 0xff00
|
|
|
|
cptr.RP = 0
|
|
|
|
cptr.SP = 0
|
|
|
|
cptr.paused = false
|
|
|
|
cptr.stopped = false
|
|
|
|
cptr.has_input = false
|
|
|
|
cptr.digiline_events = {}
|
|
|
|
cptr.channel = ""
|
|
|
|
cptr.cycles = 0
|
|
|
|
return cptr
|
|
|
|
end
|
|
|
|
|
|
|
|
ITABLE_RAW = {
|
|
|
|
[0x28] = "cptr.I = rpop(cptr)",
|
|
|
|
[0x29] = "cptr.PC = read(cptr, cptr.I); cptr.I = u16(cptr.I+2)",
|
|
|
|
[0x2a] = "rpush(cptr, cptr.I); cptr.I = u16(cptr.PC+2); cptr.PC=read(cptr, cptr.PC)",
|
|
|
|
[0x2b] = "cptr.X = read(cptr, cptr.I); cptr.I = u16(cptr.I+2)",
|
|
|
|
|
|
|
|
[0x08] = "cptr.X = cptr.SP",
|
|
|
|
[0x09] = "cptr.X = cptr.RP",
|
|
|
|
[0x0a] = "cptr.X = cptr.PC",
|
|
|
|
[0x0b] = "cptr.X = cptr.I",
|
|
|
|
|
|
|
|
[0x00] = "cptr.paused = true",
|
|
|
|
|
|
|
|
[0x01] = "rpush(cptr, cptr.X)",
|
|
|
|
[0x02] = "rpush(cptr, cptr.Y)",
|
|
|
|
[0x03] = "rpush(cptr, cptr.Z)",
|
|
|
|
[0x10] = "cptr.X = read(cptr, cptr.RP)",
|
|
|
|
[0x11] = "cptr.X = rpop(cptr)",
|
|
|
|
[0x12] = "cptr.Y = rpop(cptr)",
|
|
|
|
[0x13] = "cptr.Z = rpop(cptr)",
|
|
|
|
|
|
|
|
[0x20] = "write(cptr, cptr.SP, cptr.X)",
|
|
|
|
[0x21] = "push(cptr, cptr.X)",
|
|
|
|
[0x22] = "push(cptr, cptr.Y)",
|
|
|
|
[0x23] = "push(cptr, cptr.Z)",
|
|
|
|
[0x30] = "cptr.X = read(cptr, cptr.SP)",
|
|
|
|
[0x31] = "cptr.X = pop(cptr)",
|
|
|
|
[0x32] = "cptr.Y = pop(cptr)",
|
|
|
|
[0x33] = "cptr.Z = pop(cptr)",
|
|
|
|
|
|
|
|
[0x04] = "cptr.X = read(cptr, cptr.X)",
|
|
|
|
[0x05] = "cptr.X = read(cptr, cptr.Y)",
|
|
|
|
[0x06] = "cptr.Y = read(cptr, cptr.X)",
|
|
|
|
[0x07] = "cptr.Y = read(cptr, cptr.Y)",
|
|
|
|
|
|
|
|
[0x14] = "cptr.X = readC(cptr, cptr.X)",
|
|
|
|
[0x15] = "cptr.X = readC(cptr, cptr.Y)",
|
|
|
|
[0x16] = "cptr.Y = readC(cptr, cptr.X)",
|
|
|
|
[0x17] = "cptr.Y = readC(cptr, cptr.Y)",
|
|
|
|
|
|
|
|
[0x25] = "write(cptr, cptr.X, cptr.Y)",
|
|
|
|
[0x26] = "write(cptr, cptr.Y, cptr.X)",
|
|
|
|
|
|
|
|
[0x35] = "writeC(cptr, cptr.X, cptr.Y)",
|
|
|
|
[0x36] = "writeC(cptr, cptr.Y, cptr.X)",
|
|
|
|
|
|
|
|
[0x0c] = "n=cptr.X+cptr.Y; cptr.Y = u16(n); cptr.X = u16(math.floor(n/0x10000))",
|
|
|
|
[0x0d] = "n=cptr.X-cptr.Y; cptr.Y = u16(n); cptr.X = u16(math.floor(n/0x10000))",
|
|
|
|
[0x0e] = "n=cptr.X*cptr.Y; cptr.Y = u16(n); cptr.X = u16(math.floor(n/0x10000))",
|
|
|
|
[0x0f] = "n=s16(cptr.X)*s16(cptr.Y); cptr.Y = u16(n); cptr.X = u16(math.floor(n/0x10000))",
|
|
|
|
[0x1e] = "if cptr.Z~=0 then n = cptr.X*0x10000+cptr.Y; cptr.Y = u16(math.floor(n/cptr.Z)); cptr.X = u16(math.floor((n/cptr.Z)/0x10000)); cptr.Z = u16(n%cptr.Z) end",
|
|
|
|
[0x1f] = "if cptr.Z~=0 then n = s32(cptr.X*0x10000+cptr.Y); cptr.Y = u16(math.floor(n/s16(cptr.Z))); cptr.X = u16(math.floor((n/s16(cptr.Z))/0x10000)); cptr.Z = u16(n%s16(cptr.Z)) end",
|
|
|
|
[0x2c] = "cptr.X = u16(bit32.band(cptr.X, cptr.Y))",
|
|
|
|
[0x2d] = "cptr.X = u16(bit32.bor(cptr.X, cptr.Y))",
|
|
|
|
[0x2e] = "cptr.X = u16(bit32.bxor(cptr.X, cptr.Y))",
|
|
|
|
[0x2f] = "cptr.X = u16(bit32.bnot(cptr.X))",
|
|
|
|
[0x3c] = "cptr.X = bit32.rshift(cptr.X, cptr.Y)",
|
|
|
|
[0x3d] = "cptr.X = u16(bit32.arshift(s16(cptr.X), cptr.Y))",
|
|
|
|
[0x3e] = "n = cptr.X; cptr.X = u16(bit32.lshift(n, cptr.Y)); cptr.Y = u16(bit32.lshift(n, cptr.Y-16))",
|
|
|
|
[0x3f] = "if s16(cptr.Y)<0 then cptr.X = u16(-1) else cptr.X = 0 end",
|
|
|
|
|
|
|
|
[0x38] = "cptr.PC = u16(cptr.PC+read(cptr, cptr.PC)+2)",
|
|
|
|
[0x39] = "if cptr.X~=0 then cptr.PC = u16(cptr.PC+read(cptr, cptr.PC)) end; cptr.PC = u16(cptr.PC+2)",
|
|
|
|
[0x3a] = "if cptr.Y~=0 then cptr.PC = u16(cptr.PC+read(cptr, cptr.PC)) end; cptr.PC = u16(cptr.PC+2)",
|
|
|
|
[0x3b] = "if cptr.Z~=0 then cptr.PC = u16(cptr.PC+read(cptr, cptr.PC)) end; cptr.PC = u16(cptr.PC+2)",
|
|
|
|
|
|
|
|
[0x18] = "cptr.SP = cptr.X",
|
|
|
|
[0x19] = "cptr.RP = cptr.X",
|
|
|
|
[0x1a] = "cptr.PC = cptr.X",
|
|
|
|
[0x1b] = "cptr.I = cptr.X",
|
|
|
|
|
|
|
|
[0x40] = "cptr.Z = cptr.X",
|
|
|
|
[0x41] = "cptr.Z = cptr.Y",
|
|
|
|
[0x42] = "cptr.X = cptr.Z",
|
|
|
|
[0x43] = "cptr.Y = cptr.Z",
|
|
|
|
[0x44] = "cptr.X = cptr.Y",
|
|
|
|
[0x45] = "cptr.Y = cptr.X",
|
|
|
|
|
|
|
|
[0x46] = "cptr.X = u16(cptr.X-1)",
|
|
|
|
[0x47] = "cptr.Y = u16(cptr.Y-1)",
|
|
|
|
[0x48] = "cptr.Z = u16(cptr.Z-1)",
|
|
|
|
|
|
|
|
[0x49] = "cptr.X = u16(cptr.X+1)",
|
|
|
|
[0x4a] = "cptr.Y = u16(cptr.Y+1)",
|
|
|
|
[0x4b] = "cptr.Z = u16(cptr.Z+1)",
|
|
|
|
|
|
|
|
[0x4d] = "cptr.X = read(cptr, cptr.PC); cptr.PC = u16(cptr.PC+2)",
|
|
|
|
[0x4e] = "cptr.Y = read(cptr, cptr.PC); cptr.PC = u16(cptr.PC+2)",
|
|
|
|
[0x4f] = "cptr.Z = read(cptr, cptr.PC); cptr.PC = u16(cptr.PC+2)",
|
|
|
|
|
|
|
|
[0x52] = "receive(cptr, cptr.X, cptr.Y, cptr.Z)", -- Digiline receive
|
|
|
|
[0x53] = "delete_message(cptr, cptr.X, cptr.Y)",
|
|
|
|
[0x54] = "send_message(turtle, cptr, cptr.X, cptr.Y)", -- Digiline send
|
|
|
|
[0x55] = "set_channel(cptr, cptr.X, cptr.Y)", -- Digiline set channel
|
|
|
|
|
|
|
|
-- Turtle commands
|
|
|
|
[0x60] = "tl.forward(turtle, cptr)",
|
|
|
|
[0x61] = "tl.backward(turtle, cptr)",
|
|
|
|
[0x62] = "tl.up(turtle, cptr)",
|
|
|
|
[0x63] = "tl.down(turtle, cptr)",
|
|
|
|
[0x64] = "tl.turnleft(turtle, cptr)",
|
|
|
|
[0x65] = "tl.turnright(turtle, cptr)",
|
|
|
|
|
2013-12-07 16:46:01 +01:00
|
|
|
[0x68] = "tl.detect(turtle, cptr)",
|
|
|
|
[0x69] = "tl.detectup(turtle, cptr)",
|
|
|
|
[0x6a] = "tl.detectdown(turtle, cptr)",
|
|
|
|
|
|
|
|
[0x70] = "tl.dig(turtle, cptr)",
|
|
|
|
[0x71] = "tl.digup(turtle, cptr)",
|
|
|
|
[0x72] = "tl.digdown(turtle, cptr)",
|
2015-01-25 12:28:05 +01:00
|
|
|
[0x74] = "tl.place(turtle, cptr)",
|
|
|
|
[0x75] = "tl.placeup(turtle, cptr)",
|
|
|
|
[0x76] = "tl.placedown(turtle, cptr)",
|
2013-12-07 16:46:01 +01:00
|
|
|
|
|
|
|
[0x80] = "tl.refuel(turtle, cptr, cptr.X, cptr.Y)",
|
2015-01-25 12:28:05 +01:00
|
|
|
[0x81] = "tl.select(turtle, cptr, cptr.X)"
|
2013-11-30 19:43:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ITABLE = {}
|
|
|
|
|
|
|
|
for i, v in pairs(ITABLE_RAW) do
|
|
|
|
ITABLE[i] = loadstring(v) -- Parse everything at the beginning, way faster
|
|
|
|
end
|
|
|
|
|
|
|
|
function on_computer_digiline_receive(turtle, channel, msg)
|
2015-01-25 10:24:10 +01:00
|
|
|
local info = turtles.get_turtle_info(turtle)
|
2013-11-30 19:43:31 +01:00
|
|
|
local cptr = info.cptr
|
|
|
|
cptr.digiline_events[channel] = msg
|
|
|
|
end
|