Add digilines support.
This commit is contained in:
parent
b0dbd68921
commit
6e0aab6bb7
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
*~
|
||||
bit32.so
|
||||
|
4
README
4
README
@ -1,3 +1,7 @@
|
||||
How to build
|
||||
|
||||
Linux:
|
||||
gcc bit32.c -shared -fpic -I../../src/lua/src -o bit32.so
|
||||
|
||||
Windows:
|
||||
I don't know, sorry. I need someone to explain me that!
|
||||
|
9006
computer_memory.lua
9006
computer_memory.lua
File diff suppressed because it is too large
Load Diff
1
depends.txt
Normal file
1
depends.txt
Normal file
@ -0,0 +1 @@
|
||||
digilines
|
21
f.py
21
f.py
@ -215,6 +215,27 @@ def compile_def(name, l, immed=False):
|
||||
elif word == "QUIT":
|
||||
squit.append(here)
|
||||
here += 2
|
||||
elif word == 'S"':
|
||||
nw = l[i][:-1] #Remove trailing "
|
||||
i += 1
|
||||
setmemory(here, df["(branch)"])
|
||||
here += 2
|
||||
stack.append(here)
|
||||
here += 2
|
||||
stack.append(here)
|
||||
for c in nw:
|
||||
memory[here] = ord(c)
|
||||
here += 1
|
||||
k = stack.pop()
|
||||
setmemory(stack.pop(), here)
|
||||
setmemory(here, df["(lit)"])
|
||||
here += 2
|
||||
setmemory(here, k)
|
||||
here += 2
|
||||
setmemory(here, df["(lit)"])
|
||||
here += 2
|
||||
setmemory(here, len(nw))
|
||||
here += 2
|
||||
else:
|
||||
setmemory(here, df[word])
|
||||
here += 2
|
||||
|
10
forth.fth
10
forth.fth
@ -80,6 +80,9 @@ ASSEMBLER
|
||||
: WAIT 0x00 0x29 ;
|
||||
: WAIT-INPUT 0x50 0x29 ;
|
||||
: LEAVE 0x11 0x11 0x11 0x1b 0x29 ;
|
||||
: RECEIVE-AT 0x33 0x32 0x30 0x52 0x20 0x29 ;
|
||||
: SET-CHANNEL 0x32 0x31 0x54 0x29 ;
|
||||
: SEND 0x32 0x31 0x53 0x29 ;
|
||||
|
||||
|
||||
FORTH
|
||||
@ -106,6 +109,7 @@ FORTH
|
||||
: CELL- 2 - ;
|
||||
: CHAR+ 1+ ;
|
||||
: CELLS 2* ;
|
||||
: RECEIVE 0x80 RECEIVE-AT ;
|
||||
: 2! SWAP OVER ! CELL+ ! ;
|
||||
: 2@ DUP CELL+ @ SWAP @ ;
|
||||
: SOURCE (source) 2@ ;
|
||||
@ -119,7 +123,7 @@ FORTH
|
||||
: NIP SWAP DROP ;
|
||||
: ABS DUP 0< IF NEGATE THEN ;
|
||||
: (marker) LATEST ! (here) ! ;
|
||||
: TYPE DUP 0> IF OVER + SWAP DO I C@ EMIT LOOP ELSE 2DROP THEN ;
|
||||
: TYPE DUP 0> IF OVER + SWAP ?DO I C@ EMIT LOOP ELSE 2DROP THEN ;
|
||||
: RSTR 1+ DUP 2 + C@ 127 AND TUCK - SWAP ;
|
||||
: CR 10 EMIT ;
|
||||
: SPACE 32 EMIT ;
|
||||
@ -218,7 +222,7 @@ FORTH
|
||||
: ?DO ['] (?do) , HERE 0 , HERE ; IMMEDIATE
|
||||
: LOOP ['] (loop) , , HERE SWAP ! ; IMMEDIATE
|
||||
: +LOOP ['] (+loop) , , HERE SWAP ! ; IMMEDIATE
|
||||
: ACCEPT WAIT-INPUT 0 @ MIN 16 -ROT MOVE ;
|
||||
: ACCEPT WAIT-INPUT 0 @ MIN TUCK 16 -ROT MOVE ;
|
||||
: EXPECT ACCEPT SPAN ! ;
|
||||
: QUERY 0 >IN ! 0 SOURCE-ID ! TIB DUP 80 ACCEPT SPACE (source) 2! ;
|
||||
: REFILL SOURCE-ID @ IF FALSE ELSE 0 >IN ! TIB DUP 80 ACCEPT SPACE (source) 2! TRUE THEN ;
|
||||
@ -230,4 +234,6 @@ FORTH
|
||||
: DABS DUP 0< IF OVER NEGATE ROT IF SWAP INVERT ELSE SWAP NEGATE THEN THEN ;
|
||||
: SM/REM OVER >R 2DUP XOR >R ABS >R DABS R> UM/MOD R> 0< IF NEGATE THEN SWAP R> 0< IF NEGATE THEN SWAP ;
|
||||
\ : KEY BEGIN RAWKEY DUP 31 > OVER 127 < AND IF EXIT THEN DROP AGAIN ;
|
||||
: ON SET-CHANNEL S" on" SEND ;
|
||||
: OFF SET-CHANNEL S" off" SEND ;
|
||||
: COLD 82 EMIT 101 EMIT 97 EMIT 100 EMIT 121 EMIT QUIT ;
|
||||
|
141
init.lua
141
init.lua
@ -1,5 +1,6 @@
|
||||
CYCLES_PER_STEP = 1000
|
||||
MAX_CYCLES = 100000
|
||||
local CYCLES_PER_STEP = 1000
|
||||
local MAX_CYCLES = 100000
|
||||
local MAX_LINE_LENGHT = 42
|
||||
|
||||
local modpath = minetest.get_modpath("forth_computer")
|
||||
package.cpath = modpath.."/?.so;"..modpath.."/?.dll;"..package.cpath;
|
||||
@ -37,6 +38,15 @@ function lines(str)
|
||||
return t
|
||||
end
|
||||
|
||||
local function hashpos(pos)
|
||||
return tostring(pos.x).."\n"..tostring(pos.y).."\n"..tostring(pos.z)
|
||||
end
|
||||
|
||||
local function dehashpos(str)
|
||||
local l = lines(str)
|
||||
return {x = tonumber(l[1]), y = tonumber(l[2]), z = tonumber(l[3])}
|
||||
end
|
||||
|
||||
function newline(text, toadd)
|
||||
local f = lines(text)
|
||||
table.insert(f, toadd)
|
||||
@ -90,7 +100,7 @@ local function emit(pos, c, cptr)
|
||||
local ll = ls[#ls]
|
||||
if s=="\n" or s=="\r" then
|
||||
meta:set_string("text", newline(text,""))
|
||||
elseif string.len(ll)>=52 then
|
||||
elseif string.len(ll)>=MAX_LINE_LENGHT then
|
||||
meta:set_string("text", newline(text, s))
|
||||
else
|
||||
meta:set_string("text", text..s)
|
||||
@ -98,14 +108,52 @@ local function emit(pos, c, cptr)
|
||||
cptr.fmodif = true
|
||||
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 = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function set_channel(cptr, caddr, clen)
|
||||
local channel = string_at(cptr, caddr, clen)
|
||||
cptr.channel = channel
|
||||
end
|
||||
|
||||
local function send_message(pos, cptr, maddr, mlen)
|
||||
local msg = string_at(cptr, maddr, mlen)
|
||||
cptr.digiline_events[cptr.channel] = msg
|
||||
digiline:receptor_send(pos, digiline.rules.default, cptr.channel, msg)
|
||||
end
|
||||
|
||||
local function run_computer(pos,cptr)
|
||||
cptr.cycles = math.max(MAX_CYCLES,cptr.cycles+CYCLES_PER_STEP)
|
||||
while 1 do
|
||||
instr = cptr[cptr.PC]
|
||||
local f = ITABLE[instr]
|
||||
if f == nil then return end
|
||||
--print("Instr: "..tostring(instr).." PC: "..tostring(cptr.PC).." SP: "..tostring(cptr.SP).." RP: "..tostring(cptr.RP).." X: "..tostring(cptr.X).." Y: "..tostring(cptr.Y).." Z: "..tostring(cptr.Z).." I: "..tostring(cptr.I))
|
||||
cptr.PC = bit32.band(cptr.PC+1, 0xffff)
|
||||
local f = ITABLE[instr]
|
||||
setfenv(f, {cptr = cptr, pos=pos, emit=emit, 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})
|
||||
setfenv(f, {cptr = cptr, pos=pos, emit=emit, receive=receive, 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})
|
||||
f()
|
||||
cptr.cycles = cptr.cycles - 1
|
||||
if cptr.paused or cptr.cycles == 0 then
|
||||
@ -126,6 +174,8 @@ local function create_cptr()
|
||||
cptr.SP = 0x200
|
||||
cptr.paused = false
|
||||
cptr.has_input = false
|
||||
cptr.digiline_events = {}
|
||||
cptr.channel = ""
|
||||
cptr.cycles = 0
|
||||
return cptr
|
||||
end
|
||||
@ -222,10 +272,46 @@ ITABLE_RAW = {
|
||||
|
||||
[0x50] = "if cptr.has_input then\ncptr.has_input = false\nelse\ncptr.paused = true\ncptr.PC = u16(cptr.PC-1)\nend",
|
||||
[0x51] = "emit(pos, cptr.X, cptr)",
|
||||
[0x52] = "receive(cptr, cptr.X, cptr.Y, cptr.Z)", -- Digiline receive
|
||||
[0x53] = "send_message(pos, cptr, cptr.X, cptr.Y)", -- Digiline send
|
||||
[0x54] = "set_channel(cptr, cptr.X, cptr.Y)", -- Digiline set channel
|
||||
}
|
||||
|
||||
ITABLE = {}
|
||||
|
||||
local formspec_close_table = {}
|
||||
local function on_formspec_close(name, func)
|
||||
formspec_close_table[name] = {func=func}
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for name, t in pairs(formspec_close_table) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player == nil then
|
||||
t.func()
|
||||
formspec_close_table[name] = nil
|
||||
return
|
||||
end
|
||||
local pitch = player:get_look_pitch()
|
||||
local yaw = player:get_look_yaw()
|
||||
local pos = player:getpos()
|
||||
if t.pitch ~= nil then
|
||||
if pitch~=t.pitch or yaw~=t.yaw or pos.x~=t.x or pos.y~=t.y or pos.z~=t.z then
|
||||
t.func()
|
||||
formspec_close_table[name] = nil
|
||||
return
|
||||
end
|
||||
else
|
||||
t.pitch = pitch
|
||||
t.yaw = yaw
|
||||
t.x = pos.x
|
||||
t.y = pos.y
|
||||
t.z = pos.z
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
for i, v in pairs(ITABLE_RAW) do
|
||||
ITABLE[i] = loadstring(v)
|
||||
end
|
||||
@ -248,24 +334,42 @@ end
|
||||
|
||||
local cptrs = read_file(wpath.."/forth_computers")
|
||||
|
||||
local on_digiline_receive = function (pos, node, channel, msg)
|
||||
local cptr = cptrs[hashpos(pos)].cptr
|
||||
if cptr == nil then return end
|
||||
cptr.digiline_events[channel] = msg
|
||||
end
|
||||
|
||||
minetest.register_node("forth_computer:computer",{
|
||||
description = "Computer",
|
||||
tiles = {"computer.png"},
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
digiline =
|
||||
{
|
||||
receptor = {},
|
||||
effector = {action = on_digiline_receive},
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta=minetest.get_meta(pos)
|
||||
meta:set_string("text","\n\n\n\n\n\n\n\n\n\n")
|
||||
cptrs[minetest.serialize(pos)] = {pos=pos, cptr=create_cptr(), fmodif=false}
|
||||
cptrs[hashpos(pos)] = {pos=pos, cptr=create_cptr(), fmodif=false}
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
cptrs[minetest.serialize(pos)] = nil
|
||||
cptrs[hashpos(pos)] = nil
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local name = clicker:get_player_name()
|
||||
cptrs[minetest.serialize(pos)].cptr.pname = name
|
||||
minetest.show_formspec(name,"computer"..minetest.serialize(pos),create_formspec(meta:get_string("text")))
|
||||
if cptrs[hashpos(pos)] == nil then
|
||||
cptrs[hashpos(pos)] = {pos=pos, cptr=create_cptr(), fmodif=false}
|
||||
end
|
||||
cptrs[hashpos(pos)].cptr.pname = name
|
||||
on_formspec_close(name, function()
|
||||
local c = cptrs[hashpos(pos)]
|
||||
if c~= nil then c.cptr.pname = nil end
|
||||
end)
|
||||
minetest.show_formspec(name,"computer"..hashpos(pos),create_formspec(meta:get_string("text")))
|
||||
end,
|
||||
})
|
||||
|
||||
@ -276,7 +380,7 @@ minetest.register_globalstep(function(dtime)
|
||||
i.cptr.fmodif=false
|
||||
if i.cptr.pname~=nil then
|
||||
local meta = minetest.get_meta(i.pos)
|
||||
minetest.show_formspec(i.cptr.pname,"computer"..minetest.serialize(i.pos),create_formspec(meta:get_string("text")))
|
||||
minetest.show_formspec(i.cptr.pname,"computer"..hashpos(i.pos),create_formspec(meta:get_string("text")))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -290,12 +394,16 @@ minetest.register_on_shutdown(function()
|
||||
write_file(wpath.."/forth_computers",cptrs)
|
||||
end)
|
||||
|
||||
function escape(x)
|
||||
return string.gsub(string.gsub(string.gsub(x,";","\\;"), "%]", "\\]"), "%[", "\\[")
|
||||
end
|
||||
|
||||
function create_formspec(text)
|
||||
local f = lines(text)
|
||||
s = "size[5,4.5;"
|
||||
i = -0.25
|
||||
for _,x in ipairs(f) do
|
||||
s = s.."]label[0,"..tostring(i)..";"..minetest.formspec_escape(x)
|
||||
s = s.."]label[0,"..tostring(i)..";"..escape(x)--minetest.formspec_escape(x)
|
||||
i = i+0.3
|
||||
end
|
||||
s = s.."]field[0.3,"..tostring(i+0.4)..";4.4,1;f;;]"
|
||||
@ -305,20 +413,21 @@ end
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname:sub(1,8)~="computer" then return end
|
||||
if fields["f"]==nil or fields["f"]=="" then return end
|
||||
local pos = minetest.deserialize(formname:sub(9,-1))
|
||||
local c = cptrs[minetest.serialize(pos)]
|
||||
local pos = dehashpos(formname:sub(9,-1))
|
||||
local c = cptrs[hashpos(pos)]
|
||||
if c==nil then return end
|
||||
local cptr=c.cptr
|
||||
cptr.has_input = true
|
||||
if string.len(fields["f"])>52 then
|
||||
fields["f"] = string.sub(fields["f"],1,52)
|
||||
if string.len(fields["f"])>MAX_LINE_LENGHT then
|
||||
fields["f"] = string.sub(fields["f"],1,MAX_LINE_LENGHT)
|
||||
end
|
||||
for i=1,string.len(fields["f"]) do
|
||||
cptr[15+i] = string.byte(fields["f"],i)
|
||||
end
|
||||
write(cptr, 0, string.len(fields["f"]))
|
||||
local meta = minetest.get_meta(pos)
|
||||
local ntext = newline(meta:get_string("text"),fields["f"])
|
||||
--local ntext = newline(meta:get_string("text"),fields["f"])
|
||||
local ntext = meta:get_string("text")..fields["f"]
|
||||
meta:set_string("text",ntext)
|
||||
minetest.show_formspec(player:get_player_name(),formname,create_formspec(ntext))
|
||||
end)
|
||||
|
Loading…
x
Reference in New Issue
Block a user