Permalink
Browse files

Making a fool of myself in public again.

  • Loading branch information...
1 parent 6b9b3cf commit 6e8ddb479ed704d6f5b3917c287a61ba93b8b8db @Textmode committed Mar 12, 2011
Showing with 94 additions and 194 deletions.
  1. +73 −188 device.lua
  2. +21 −6 machine.lua
View
@@ -7,29 +7,25 @@ local _MT = {__index=_M}
-------------------------------------------------------------------------
-- Key values
-_M.DEV_TYPE_INVALID = 0x00
-_M.DEV_TYPE_NONE = 0x01
-_M.DEV_TYPE_TERMINAL = 0x02
-_M.DEV_TYPE_STREAM = 0x03
-_M.DEV_TYPE_STORE = 0x04
-_M.DEV_TYPE_NETWORK = 0x05
-_M.DEV_TYPE_CLOCK = 0x06
-_M.DEV_TYPE_MACHINE = 0xff
+_M.DEV_TYPE_INVALID = 'invalid'
+_M.DEV_TYPE_NONE = 'null'
+_M.DEV_TYPE_TERMINAL = 'terminal'
+_M.DEV_TYPE_STREAM = 'stream'
+_M.DEV_TYPE_MACHINE = 'machine'
_M.DEV_STATUS_READY = 0x00 -- Device is ready
-_M.DEV_STATUS_BUSY = 0x01 -- Device will be availible soon, honest.
+_M.DEV_STATUS_BUSY = 0x01 -- Device will be available soon, honest.
_M.DEV_STATUS_BLOCKED = 0x0f -- Device is blocked and will not become ready without aid
_M.DEV_STATUS_FAULT = 0xff -- Device has faulted, and/or died.
local dev_type_names = {
[_M.DEV_TYPE_NONE] = "Null Device";
[_M.DEV_TYPE_TERMINAL] = "Terminal Device";
[_M.DEV_TYPE_STREAM] = "Datastream Device";
- [_M.DEV_TYPE_STORE] = "Persistant Storage Device";
- [_M.DEV_TYPE_NETWORK] = "Networking Device";
[_M.DEV_TYPE_MACHINE] = "TMVM machine.";
}
+_M.typecount = 5
-------------------------------------------------------------------------
-- Name stuff
@@ -40,9 +36,7 @@ local names = {
[_M.DEV_TYPE_NONE] = {"null port", "data retention dept.", "air gap", "Mu"};
[_M.DEV_TYPE_TERMINAL] = {"terminal", "display", "client", "PEBKAC"};
[_M.DEV_TYPE_STREAM] = {"port", "serial line", "jute twine"};
- [_M.DEV_TYPE_STORE] = {"storage", "floppy drive", "printer/scanner assembly", "magnet and steady hand"};
- [_M.DEV_TYPE_NETWORK] = {"network", "1bps modem", "foot-net"};
- [_M.DEV_TYPE_MACHINE] = {"Machine", "'Titanic'", "Analytical Engine", "'Iron'", "'Rex'"};
+ [_M.DEV_TYPE_MACHINE] = {"Machine", "'Titanic'", "'Icarus'", "Analytical Engine", "'Iron'", "'Rex'"};
}
function _M:generatename(devtype)
@@ -55,6 +49,7 @@ end
namer = namedevice
+catalogue = {}
local function initstream(d)
local dev = {idx=idx, type=devtype}
@@ -100,126 +95,7 @@ local function initnull(d)
return d
end
-local function initstore(d)
- d.portmaps = {{16, 17, 18, 19},{32, 33, 34, 35},{64, 65, 66, 67}}
-
- d.sector = 0
- d.block = 0
- d.byte = 0
- d.maxsectors = 0
- d.maxblocks = 0
- d.maxbytes = 0
-
- d.imagename = string.format("%s.store", "shared")
-
- d.receive = function(self, pin, val)
- assert(self.started, "Not Started!")
- if pin == 1 then
- self.sector = val
- elseif pin == 2 then
- self.block = val
- elseif pin == 3 then
- self.byte = val
- elseif pin == 4 then
- local pos = (self.sector*(self.maxblocks*self.maxbytes) +
- (self.block*self.maxbytes)) +
- (self.byte)
- self.image:seek('set', self.offset + pos)
- self.image:write(string.char(val))
- end
- return 0
- end
-
- d.send = function(self, pin)
- assert(self.started, "Not Started!")
- if pin == 1 then
- return self.sector
- elseif pin == 2 then
- return self.block
- elseif pin == 3 then
- return self.byte
- elseif pin == 4 then
- local pos = (self.blocks*(self.maxblocks*self.maxbytes) +
- (self.block*self.maxbytes)) +
- (self.byte)
- self.image:seek('set', self.offset + pos)
- return self.image:read(1)
- end
- return 0
- end
-
- return d
-end
-
-local function initclock(d)
- d.portmaps = {{42}}
-
- d.states ={
- CLOCK_STATE_DEFAULT = 0x0, CLOCK_STATE_SECONDS = 0x1,
- CLOCK_STATE_MINUTES = 0x2, CLOCK_STATE_HOURS = 0x3,
- CLOCK_STATE_MONTHDAY = 0x4, CLOCK_STATE_WEEKDAY = 0x4,
- CLOCK_STATE_MONTH = 0x5, CLOCK_STATE_YEAR = 0x6,
- CLOCK_STATE_DAYRATIO = 0x7 }
-
- d.state = d.states.CLOCK_STATE_DEFAULT
-
- d.receive = function(self, pin, val)
- assert(self.started, "Not Started!")
- if val >= self.states.CLOCK_STATE_DEFAULT and
- val <= self.states.CLOCK_STATE_YEAR then
-
- self.state = val
- else
- return false, _M.DEV_STATUS_BLOCKED
- end
- return 0
- end
-
- d.send = function(self, pin)
- assert(self.started, "Not Started!")
- local val = self.state
- local st = self.states
- if val >= self.states.CLOCK_STATE_DEFAULT and
- val <= self.states.CLOCK_STATE_YEAR then
-
- if val == st.CLOCK_STATE_DEFAULT then
- return math.floor(os.time() % 256)
- elseif val == st.CLOCK_STATE_SECONDS then
- local t = os.date("!*t")
- return math.floor(t.sec % 256)
- elseif val == st.CLOCK_STATE_MINUTES then
- local t = os.date("!*t")
- return math.floor(t.min % 256)
- elseif val == st.CLOCK_STATE_HOURS then
- local t = os.date("!*t")
- return math.floor(t.hour % 256)
- elseif val == st.CLOCK_STATE_MONTHDAY then
- local t = os.date("!*t")
- return math.floor(t.day % 256)
- elseif val == st.CLOCK_STATE_WEEKDAY then
- local t = os.date("!*t")
- return math.floor(t.wday % 256)
- elseif val == st.CLOCK_STATE_MONTH then
- local t = os.date("!*t")
- return math.floor(t.month % 256)
- elseif val == st.CLOCK_STATE_YEAR then
- local t = os.date("!*t")
- return math.floor((t.year-1980) % 256)
- elseif val == st.CLOCK_STATE_DAYRATIO then
- local t = os.date("!*t")
- local d = (((t.hour*60)+(t.min))*60)+t.sec
- local fd = 86400
- return math.floor(((d/fd)*255) % 256)
- end
- else
- return false, _M.DEV_STATUS_BLOCKED
- end
- return 42
- end
-
- return d
-end
-------------------------------------------------------------------------
-- exports
@@ -233,20 +109,20 @@ function _M:new(t)
portmaps = t.portmaps, portmap={}}
setmetatable(d, _MT)
+ local err
+
if d.type == _M.DEV_TYPE_TERMINAL
or d.type == _M.DEV_TYPE_STREAM then
d=initstream(d)
elseif d.type == _M.DEV_TYPE_NONE then
d=initnull(d)
- elseif d.type == _M.DEV_TYPE_CLOCK then
- d=initclock(d)
- elseif d.type == _M.DEV_TYPE_STORE then
- d=initstore(d)
+ elseif catalogue[d.type] then
+ d, err = catalogue[d.type].init(d)
else
error(("Unknown device type: '%s'"):format(tostring(d.type)))
end
- return d
+ return d, err
end
local function testmap(sysmap, testmap)
@@ -270,11 +146,11 @@ function _M.findports(dev, portmap)
local _, pm
for _, pm in pairs(dev.portmaps) do
if testmap(portmap, pm) then
- return pm
+ return pm, "Okay"
end
end
- return false, "Could not find valid portmapping"
+ return false, "Could not find valid port-mapping"
end
-- Starts the device, and readies it for use
@@ -297,60 +173,17 @@ function _M:start(host, idx)
-- failing to open the input is not an error
self.started = true
- return _M.DEV_STATUS_READY;
+ return _M.DEV_STATUS_READY, "Okay";
elseif self.type == _M.DEV_TYPE_NONE then
self.started = true
- return _M.DEV_STATUS_READY;
+ return _M.DEV_STATUS_READY, "Okay";
elseif self.type == _M.DEV_TYPE_CLOCK then
-- nothing doing.
self.started = true
- return _M.DEV_STATUS_READY;
- elseif self.type == _M.DEV_TYPE_STORE then
- local img, err = io.open(self.imagename, 'r+b')
- if img then
- self.image = img
-
- if img:read(2) ~= "DS" then
- -- not a DataStore file.
- img:close()
- return false, "Not a valid store"
- end
- local version = string.format("v%d.%d", img:read(1):byte(), img:read(1):byte())
- if version ~= "v1.0" then
- -- unknown version
- img:close()
- return false, "Unknown version"
- end
-
- local len = img:read(1):byte()
- local hdr = img:read(len) -- load the header (up to 255 in size)
- hdr = {hdr:byte(1, -1)}
-
-
- -- the stored value is 0..255, but we support 1..256, so +1
- self.maxsectors = hdr[1]+1
- self.maxblocks = hdr[2]+1
- self.maxbytes = hdr[3]+1
- self.modelID = string.char(hdr[4], hdr[5], hdr[6], hdr[7])
- self.header = hdr
- self.offset = 5+len -- magic number, plus the length of the header
-
- local c, s, n = img:seek(), img:seek('end'), img:seek('set', self.offset)
-
- assert(c == n, "Not returning to the right position. logic error!")
-
- if s < len+(self.maxsectors*self.maxblocks*self.maxbytes) then
- -- truncated file
- img:close()
- return false, "Truncated file"
- end
-
- self.started = true
- return _M.DEV_STATUS_READY;
- else
- assert(img, ("Could not open image '%s': %s"):format(fname, tostring(err)))
- end
+ return _M.DEV_STATUS_READY, "Okay";
+ elseif catalogue[self.type] then
+ return catalogue[self.type].start(self)
else
return false, "Unknown device type: "..tostring(self.type)
end
@@ -383,6 +216,58 @@ function _MT.__tostring(self)
return string.format('%s, "%s"', dev_type_names[self.type], self.name)
end
+-- librum
+-- with more than a bit of inspiration from package.*
+
+_M.loaded = {}
+
+local devicepath = "devices/?.lua;devices/?.drv;"
+
+function _M:locate(lib)
+ assert(type(lib) == 'string', "Not a valid librum name: " .. tostring(lib))
+ if _M.loaded[lib] then
+ return _M.loaded[lib]
+ else
+ local s, tmp, err
+ for p in devicepath:gmatch("[^;]*") do
+ tmp = p:gsub("?", lib)
+ tmp, err = loadfile(tmp)
+ if tmp then
+ s, tmp, err = pcall(tmp)
+ if s then
+ return tmp, err
+ else
+ break
+ end
+ end
+ end
+ return false, "could not be found"
+ end
+end
+
+function _M:load(lib)
+ local dev, err = _M:locate(lib)
+ assert(dev, tostring(err))
+ return _M:registerdevice(lib, dev)
+end
+
+function _M:registerdevice(id, d)
+ assert(id, "A device type must have an identifier")
+ assert(d.regdata, "A device must provide valid registration data")
+
+ local rd = d.regdata
+ assert(rd.name, "A device type must have a name")
+ assert(rd.desc, "Device descriptions are not optional!")
+ assert(type(rd.names) == 'table' and rd.names[1], "At least one instance name must be provided!")
+ assert(rd.typename, "A typename must be provided")
+
+ self[rd.typename] = id
+ catalogue[id] = d
+
+ return id
+end
+
+
-- MODULE TAIL
-------------------------------------------------------------------------
View
@@ -1,6 +1,8 @@
local bitfield = require "bitfield"
local device = require "device"
+local util = require 'util'
+local socket = desire 'socket'
local _M = {_NAME="machine", number=0}
@@ -116,13 +118,26 @@ local function stringtodata(str)
return t
end
+local wait
-- a coarse wait/"sleep" function.
-- involves busy-waiting
-local function wait(n)
- local clk = os.clock
- local start, dt = clk()
- repeat dt = clk()-start until dt >= n
- return dt
+if not socket then -- if socket isn't availible, we fall back to a busy-wait.
+ function wait(n)
+ local clk = os.clock
+ local start, dt = clk()
+ repeat dt = clk()-start until dt >= n
+ return dt
+ end
+else -- but use sleep if we can.
+ function wait(n)
+ local clk = os.clock
+ local t = socket.sleep(n) -- ISSUE: seems like sleep does not return the time that passed...
+ if t then
+ return t
+ else
+ return os.clock()-clk
+ end
+ end
end
-- converts an seg-offset pair into a linear address.
@@ -831,7 +846,7 @@ end
-- approximately every second.
function _M:run(stats)
stats = stats or false
- local t, nt, dt = os.clock()
+ local t, nt, dt = os.clock(), 0, 0
local drift = 0
while self.state ~= 'halt' do

0 comments on commit 6e8ddb4

Please sign in to comment.