working T408

This commit is contained in:
Izaya 2017-03-13 13:36:49 +11:00
parent 812fbd44ae
commit d50ccc7dde
8 changed files with 353 additions and 30 deletions

58
test3d_t408/emut408.lua Normal file
View File

@ -0,0 +1,58 @@
stab = {}
stab.stack = {}
stab.pc = 1
stab.cins = 0
mem = {}
t408 = require "t408"
while true do
io.write("*> ")
i=io.read()
it = {}
for s in i:gmatch("%S+") do it[#it+1] = s end
if it[1] == "quit" then
break
elseif it[1] == "peek" then
print(mem[tonumber(it[2])])
elseif it[1] == "poke" then
mem[tonumber(it[2])] = tonumber(it[3])
elseif it[1] == "push" then
stab.stack[#stab.stack+1] = tonumber(it[2])
elseif it[1] == "dumpstack" then
for k,v in ipairs(stab.stack) do print(k,v) end
elseif it[1] == "ppc" then
print(stab.pc)
elseif it[1] == "spc" then
stab.pc=tonumber(it[2])
elseif it[1] == "step" then
local scount = tonumber(it[2]) or 1
for i = 1, scount do
stab.cins = mem[stab.pc]
stab,rw,addr,val=t408.run(stab)
--print(rw,addr,val)
if rw == "halt" then print("Halted at "..tostring(stab.pc) )break end
if rw == "read" then
stab.stack[#stab.stack+1] = mem[addr]
elseif rw == "write" then
mem[addr] = val
if addr == 0 then io.write(string.char(val)) end
end
end
elseif it[1] == "debug" then
print(not t408.debug)
t408.debug = not t408.debug
elseif it[1] == "load" then
local f,e = io.open(it[2])
if f == nil then
print("Error: "..e)
else
local n = tonumber(it[3]) or 0
local c = f:read("*a")
f:close()
for v in c:gmatch("%d+") do
mem[n] = tonumber(v) or 0
n = n + 1
end
end
end
end

198
test3d_t408/init.lua Normal file
View File

@ -0,0 +1,198 @@
local MEMSIZE=16
local path = minetest.get_modpath(minetest.get_current_modname())
local t408_mem, t408_stab = {},{}
print("Looking for memory file at "..path.."/mem.dat")
local f=io.open(path.."/mem.dat","rb")
if f ~= nil then
local c = f:read("*a")
print("Found T408 memory file.")
-- rawset(_G,"t408_mem",minetest.deserialize(c))
t408_mem = minetest.deserialize(c)
print("Contents: "..c)
f:close()
end
print("Looking for metadata file at "..path.."/stab.dat")
local f=io.open(path.."/stab.dat","rb")
if f ~= nil then
print("Found T408 metadata file.")
local c = f:read("*a")
t408_stab = minetest.deserialize(c)
print("Contents: "..c)
f:close()
end
local t408 = dofile(path.."/t408.lua")
t408.debug = true
print(type(_G.t408_mem))
if not digiline then
print("Digilines not found.")
return
end
local oldprint=print
local function print(...)
for k,v in ipairs({...}) do
oldprint("[Test3D:T408] "..tostring(v))
end
end
print("Loading.")
local function t408_digiline_receive(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
local nid = minetest.pos_to_string(pos)
local prea,preb = string.find(channel,meta:get_string("channel"))
print("Start channel: "..prea,"End channel: "..preb)
print("Recieved (pre)"..tostring(msg).." from "..tostring(channel).." (device channel: "..tostring(meta:get_string("channel"))..")")
if prea == 1 then
--if string.sub(channel,1,meta:get_string("channel"):len()) == meta:get_string("channel") then
-- local addr = tonumber(msg:sub(meta:get_string("channel"):len()+1))
-- local addr = tonumber(channel)
print("Correct channel.")
local addr = tonumber(string.sub(channel,preb+1))
print(addr)
if addr > -1 and addr < 16 then
print("Recieved "..tostring(msg).." from "..tostring(channel).." for "..tostring(addr).." (device channel: "..tostring(meta:get_string("channel"))..")")
t408_mem[nid][addr+224] = tonumber(msg)
end
end
--end
end
print("Created T408 digiline function")
local function t408_read(pos,addr)
if t408_mem[pos] == nil then return false end
print("Read: "..tostring(pos).." "..tostring(addr)..": "..tostring(t408_mem[pos][addr]))
return t408_mem[pos][addr] or 0
end
local function t408_write(pos,addr,val)
print(tostring(pos).." "..tostring(addr).." "..tostring(val))
if t408_mem[pos] == nil then return false end
t408_mem[pos][tonumber(addr)] = (tonumber(val)%256)
print("Write: "..tostring(pos).." "..tostring(addr)..": "..tostring(t408_mem[pos][addr]).." = "..tostring(val))
return true
end
local function t408_set_meta(pos)
local meta = minetest.get_meta(pos)
meta:set_string("channel","")
meta:set_string("state","running")
t408_mem[minetest.pos_to_string(pos)] = {}
t408_stab[minetest.pos_to_string(pos)] = {["ci"]=1,["pc"]=1,["stack"]={},["rstack"]={}}
print("Created T408 memory table with ID "..minetest.pos_to_string(pos))
end
minetest.register_node("test3d_t408:t408", {
description = "T408 Memory Node",
tiles = {{image="t408.png",animation={type="vertical_frames",aspect_w=16,aspect_h=16,length=1.8}}},
on_construct = t408_set_meta,
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3},
digiline = {
receptor = {},
effector = {
action = function (a,b,c,d) pcall(t408_digiline_receive,a,b,c,d) end
}
},
on_punch = function(pos,_,fields,sender)
-- if fields.channel == nil then return end
local meta = minetest.get_meta(pos)
-- fields.channel = fields.channel or ""
-- meta:set_string("channel",fields.channel)
if meta:get_string("state") == "running" then
meta:set_string("state","halted")
else
meta:set_string("state","running")
end
print(meta:get_string("state"))
end
})
minetest.register_chatcommand("test3d-t408-read", {
params = "<node ID> <address>",
description = "Read the memory in a T408 node",
func = function(name,str)
local tArg = {}
for s in str:gmatch("%S+") do
tArg[#tArg+1] = s
end
local nid,addr = tArg[1],tArg[2]
print(nid,addr)
minetest.chat_send_player(name,tostring(t408_read(nid,tonumber(addr))))
end
})
minetest.register_chatcommand("test3d-t408-write", {
params = "<node ID> <address> <new value>",
description = "Read the memory in a T408 node",
func = function(name,str)
local tArg = {}
for s in str:gmatch("%S+") do
tArg[#tArg+1] = s
end
local nid,addr,val = tArg[1],tArg[2],tArg[3]
print(nid,addr,val)
minetest.chat_send_player(name,tostring(t408_write(nid,tonumber(addr),tostring(val))))
end
})
minetest.register_chatcommand("test3d-t408-set", {
params = "<node ID> <variable> <new value>",
description = "Set T408 variables.",
func = function(name,str)
local tArg = {}
for s in str:gmatch("%S+") do
tArg[#tArg+1] = s
end
local nid,addr,val = tArg[1],tArg[2],tArg[3]
local meta = minetest.get_meta(minetest.string_to_pos(nid))
meta:set_string(addr,tArg[3] or "")
print("Set "..nid.."'s "..addr.." to "..(tArg[3] or ""))
end
})
minetest.register_chatcommand("test3d-t408-dump", {
params = "<node ID> <address> <new value>",
description = "Read the memory in a T408 node",
func = function(name,nid,addr,val)
for k,v in ipairs(t408_mem) do
print(k,v)
end
end
})
print("T408 node registered")
minetest.register_abm({
nodenames={"test3d_t408:t408"},
interval=1,
chance=1,
action = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_string("state") == "running" then
local nid = minetest.pos_to_string(pos)
local stab,rw,addr,val = t408_stab[nid],nil,0,0
stab.cins = t408_mem[nid][stab.pc]
stab,rw,addr,val = t408.run(stab)
if rw == "read" then
stab.stack[#stab.stack+1] = t408_mem[nid][addr]
elseif rw == "preread" then
if addr > 223 and addr < 240 then
digiline:receptor_send(pos,digiline.rules.default,meta:get_string("channel")..string.format("%X",tonumber(addr)-224),"get")
end
elseif rw == "write" then
t408_mem[nid][addr] = tonumber(val)
print("Writing "..tostring(val).." to "..tostring(addr))
if addr > 223 and addr < 240 then
digiline:receptor_send(pos,digiline.rules.default,meta:get_string("channel")..string.format("%X",tonumber(addr)-224),tonumber(val))
print(string.char(val))
end
end
t408_stab[nid] = stab
end
end
})
minetest.register_on_shutdown(function()
local f=io.open(path.."/mem.dat","wb")
if f then
f:write(minetest.serialize(t408_mem))
f:close()
end
local f=io.open(path.."/stab.dat","wb")
if f then
f:write(minetest.serialize(t408_stab))
f:close()
end
end)

97
test3d_t408/t408.lua Normal file
View File

@ -0,0 +1,97 @@
local MAXADDR = 255
local t = {}
-- internal state
--- program counter (pc)
--- current instruction (ci) -- only passed from the environment to the emulator
--- stack (stack)
local function pop(s)
return table.remove(s,#s) or 0
end
local function push(s,v)
v=v or 0
s[#s+1] = v%256
if #s > 16 then
table.remove(s,1)
end
end
function t.run(stab,ov)
-- variables
local pc = stab.pc or 1
local ci = stab.cins or 0
if ov then
ci = tonumber(ov) or 0
end
local stack = stab.stack or {}
local rstack = stab.rstack or {}
local pci = 1
local rw = nil
local addr = 0
local dat = 0
-- instruction processing
if ci == 255 then -- ppc
push(stack,pc)
elseif ci == 254 then -- swp
a=pop(stack)
b=pop(stack)
push(stack,a)
push(stack,b)
elseif ci == 253 then -- read
rw = "read" -- terrible IPC
addr = pop(stack)
elseif ci == 252 then -- write
rw = "write"
addr = pop(stack)
dat = pop(stack)
--print("writing "..tostring(dat).." to "..tostring(addr))
elseif ci == 251 then -- add
push(stack,pop(stack)+pop(stack))
elseif ci == 250 then -- sub
push(stack,pop(stack)+pop(stack))
elseif ci == 249 then -- jmp
pc = pop(stack)
pci = 0
elseif ci == 248 then -- sez
if pop(stack) == 0 then
pci = pci + 1
end
elseif ci == 247 then -- jez
local a = pop(stack)
if pop(stack) == 0 then
pc = a
pci = 0
end
elseif ci == 246 then -- jsr
push(rstack,pc)
pc = pop(stack)
pci = 0
elseif ci == 245 then -- ret
pc = pop(rstack)
elseif ci == 244 then -- dup
local v = pop(stack)
push(stack,v)
push(stack,v)
elseif ci == 243 then -- drop
pop(stack)
elseif ci == 242 then -- hlt
rw = "halt"
elseif ci == 241 then -- prd
rw = "preread"
addr = pop(stack)
else
push(stack,ci)
end
-- return stuff
stab = {}
stab.pc = pc + pci -- increment pc
if stab.pc > MAXADDR then
stab.pc = 0
end
stab.cins = 0
stab.stack = stack
stab.rstack = rstack
if t.debug then print("t408: pc: "..tostring(stab.pc),"cins: "..tostring(ci),"tos: "..tostring(stab.stack[1]).." #s: "..tostring(#stab.stack),stab.rw,stab.addr,stab.dat) end
return stab, rw, addr, dat
end
return t

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

View File

@ -1,30 +0,0 @@
if not digiline then
print("Digilines not found.")
return
end
local oldprint=print
local function print(...)
for k,v in ipairs({...}) do
oldprint("[Test3D:T410] "..tostring(v))
end
end
print("Loading.")
local function t410_set_meta(pos)
minetest.get_meta(pos):set_string("formspec","size[2,4]\nfield[0,1;2.9,1;addr;Address;]\nfield[0,2;2.9,1;data;Data;]\nbutton[0,3;2,1;write;Write]")
end
minetest.register_node("test3d_t410:t410", {
description = "T410 Memory Access Console",
tiles = {"t416-top.png","t416-top.png","t416-side.png","t416-side.png","t416-side.png","t416-side.png"},
on_construct = t410_set_meta,
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3},
on_receive_fields = function(pos,_,fields,sender)
if fields.addr == nil then return end
digiline:receptor_send(pos, digiline.rules.default, fields.addr, tonumber(fields.data) or 0)
print("Set "..fields.addr.." to "..fields.data)
end,
digiline = {
receptor = {},
},
})
print("T410 node registered")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 B