working T408
This commit is contained in:
parent
812fbd44ae
commit
d50ccc7dde
58
test3d_t408/emut408.lua
Normal file
58
test3d_t408/emut408.lua
Normal 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
198
test3d_t408/init.lua
Normal 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
97
test3d_t408/t408.lua
Normal 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
|
BIN
test3d_t408/textures/t408.png
Normal file
BIN
test3d_t408/textures/t408.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 778 B |
@ -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 |
Loading…
Reference in New Issue
Block a user