do local orig_require, loaded, retval, source = _G.require, {}, {}, {['chat'] = [=[local Device = require('device') local system_device do local c = Device:new() c.name = 'system' c:addPort(2, false, function(self) return self.cpu.program_stack:len() end) c:addPort(3, false, function(self) return self.cpu.return_stack:len() end) system_device = c end local console_device do local c = Device:new() c.name = 'console' c:addPort(8, false, nil, function(self, byte) return table.insert(self.stdout, byte) end) c:addPort(9, false, nil, function(self, byte) return table.insert(self.stderr, byte) end) console_device = c end local datetime_device do local dt = Device:new() dt.name = 'datetime' dt:addPort(0, true, function(self) return tonumber(os.date('!%Y')) end) dt:addPort(2, false, function(self) return tonumber(os.date('!%m')) - 1 end) dt:addPort(3, false, function(self) return tonumber(os.date('!%d')) end) dt:addPort(4, false, function(self) return tonumber(os.date('!%H')) end) dt:addPort(5, false, function(self) return tonumber(os.date('!%M')) end) dt:addPort(6, false, function(self) return tonumber(os.date('!%S')) end) dt:addPort(7, false, function(self) return tonumber(os.date('!%u')) % 7 end) dt:addPort(8, true, function(self) return tonumber(os.date('!%j')) - 1 end) dt:addPort(10, true, function(self) return 0 end) datetime_device = dt end local Uxn do local m = require('uxn') Uxn = function() local u = m.Uxn:new() u:addDevice(0x0, system_device) u:addDevice(0x1, console_device) u:addDevice(0xb, datetime_device) return u end end local load_memory do local mem_mt = { __index = function(self, k) return 0 end } load_memory = function(u, t) u.memory = setmetatable((function() local _tbl_0 = { } for i, v in ipairs(t) do _tbl_0[i + 255] = v end return _tbl_0 end)(), mem_mt) end end local load_source load_source = function(u, s) for i = 1, #s do u.memory[i + 0xdfff] = s:byte(i, i) end end local u = Uxn() local asma_rom = { 160, 12, 215, 160, 7, 119, 53, 160, 3, 177, 46, 160, 7, 75, 160, 5, 93, 53, 160, 240, 0, 160, 224, 0, 185, 160, 4, 195, 46, 34, 34, 160, 5, 99, 52, 29, 128, 48, 13, 0, 160, 3, 230, 46, 160, 240, 0, 160, 224, 0, 185, 160, 4, 195, 46, 34, 34, 160, 5, 99, 52, 29, 128, 22, 13, 128, 79, 128, 24, 23, 128, 75, 128, 24, 23, 160, 7, 73, 52, 4, 128, 24, 23, 128, 24, 23, 0, 160, 5, 99, 52, 160, 3, 108, 46, 128, 58, 128, 25, 23, 128, 32, 128, 25, 23, 160, 5, 87, 52, 160, 3, 108, 46, 128, 46, 128, 25, 23, 0, 0, 128, 1, 128, 167, 23, 38, 128, 168, 55, 128, 1, 128, 166, 23, 160, 5, 97, 53, 160, 5, 95, 53, 160, 3, 177, 46, 160, 7, 75, 160, 5, 93, 53, 160, 5, 95, 52, 160, 4, 57, 46, 160, 5, 99, 52, 29, 128, 71, 13, 160, 3, 230, 46, 160, 7, 77, 160, 5, 93, 53, 160, 5, 97, 52, 29, 128, 7, 13, 160, 7, 94, 160, 5, 93, 53, 160, 5, 95, 52, 160, 4, 57, 46, 160, 5, 99, 52, 29, 128, 29, 13, 160, 7, 73, 52, 160, 240, 0, 57, 160, 5, 93, 52, 46, 160, 5, 102, 160, 3, 12, 46, 160, 2, 65, 46, 160, 2, 118, 46, 108, 160, 1, 245, 46, 108, 128, 168, 54, 160, 3, 108, 46, 160, 2, 58, 160, 3, 108, 46, 160, 5, 78, 52, 160, 3, 123, 46, 128, 58, 128, 25, 23, 128, 32, 128, 25, 23, 160, 5, 99, 52, 160, 3, 108, 46, 128, 58, 128, 25, 23, 128, 32, 128, 25, 23, 160, 5, 87, 52, 160, 3, 108, 46, 128, 46, 128, 25, 23, 128, 10, 128, 25, 23, 108, 32, 108, 105, 110, 101, 32, 0, 160, 5, 101, 20, 128, 1, 28, 128, 0, 8, 128, 15, 13, 160, 5, 80, 52, 160, 3, 123, 46, 160, 2, 94, 160, 3, 108, 46, 108, 32, 108, 105, 110, 101, 115, 32, 111, 102, 32, 115, 111, 117, 114, 99, 101, 32, 99, 111, 100, 101, 46, 10, 0, 160, 5, 101, 20, 128, 8, 28, 128, 0, 8, 128, 38, 13, 160, 7, 119, 52, 160, 12, 215, 57, 160, 3, 123, 46, 160, 2, 170, 160, 3, 108, 46, 160, 224, 0, 160, 7, 119, 52, 57, 160, 3, 123, 46, 160, 2, 192, 160, 3, 108, 46, 108, 32, 98, 121, 116, 101, 115, 32, 111, 102, 32, 104, 101, 97, 112, 32, 117, 115, 101, 100, 44, 32, 0, 32, 98, 121, 116, 101, 115, 32, 102, 114, 101, 101, 46, 10, 0, 52, 157, 128, 2, 13, 34, 108, 38, 128, 245, 14, 128, 9, 128, 25, 23, 38, 160, 0, 4, 56, 38, 33, 36, 20, 6, 128, 0, 8, 128, 6, 13, 128, 25, 23, 128, 239, 12, 2, 128, 9, 128, 25, 23, 52, 160, 3, 123, 46, 128, 10, 128, 25, 23, 160, 0, 2, 56, 128, 195, 14, 108, 160, 5, 101, 20, 128, 4, 28, 128, 0, 8, 128, 5, 13, 52, 157, 128, 2, 13, 34, 108, 38, 128, 232, 14, 38, 160, 0, 4, 56, 148, 128, 65, 11, 128, 11, 13, 148, 128, 90, 10, 128, 4, 13, 34, 128, 41, 12, 38, 33, 36, 20, 6, 128, 0, 8, 128, 6, 13, 128, 25, 23, 128, 239, 12, 2, 128, 9, 128, 25, 23, 180, 160, 3, 123, 46, 128, 10, 128, 25, 23, 160, 0, 2, 56, 160, 2, 206, 46, 160, 0, 2, 56, 128, 161, 14, 108, 148, 6, 128, 3, 13, 2, 34, 108, 128, 25, 23, 33, 128, 241, 12, 128, 48, 128, 25, 23, 128, 120, 128, 25, 23, 7, 128, 4, 31, 128, 20, 14, 4, 128, 15, 28, 128, 13, 14, 6, 128, 4, 31, 128, 6, 14, 128, 15, 28, 128, 0, 12, 128, 48, 24, 6, 128, 58, 11, 128, 3, 13, 128, 39, 24, 128, 25, 23, 108, 160, 34, 2, 30, 160, 6, 192, 21, 160, 66, 2, 30, 160, 6, 206, 21, 160, 130, 2, 30, 160, 6, 218, 21, 128, 255, 160, 5, 76, 21, 160, 0, 0, 166, 160, 5, 99, 53, 160, 5, 102, 53, 160, 5, 104, 53, 160, 11, 215, 160, 5, 106, 53, 160, 5, 76, 20, 1, 160, 5, 76, 21, 160, 240, 0, 160, 7, 73, 53, 160, 1, 0, 38, 6, 160, 5, 77, 21, 160, 5, 89, 53, 160, 5, 91, 53, 160, 4, 57, 160, 4, 21, 185, 160, 4, 195, 46, 34, 34, 108, 37, 66, 82, 75, 32, 123, 32, 48, 48, 32, 125, 32, 37, 91, 32, 123, 32, 125, 32, 37, 93, 32, 123, 32, 125, 32, 64, 111, 110, 45, 114, 101, 115, 101, 116, 32, 160, 4, 195, 160, 0, 0, 37, 160, 224, 0, 38, 160, 240, 0, 37, 57, 37, 128, 14, 14, 160, 5, 99, 52, 29, 128, 0, 13, 34, 34, 34, 34, 34, 108, 160, 0, 0, 38, 37, 47, 37, 239, 128, 168, 55, 175, 128, 50, 51, 47, 175, 128, 48, 51, 38, 128, 78, 51, 128, 37, 14, 36, 165, 35, 39, 128, 172, 55, 128, 162, 54, 36, 46, 37, 36, 185, 35, 157, 128, 6, 13, 34, 98, 98, 111, 111, 108, 111, 36, 171, 12, 97, 57, 111, 111, 128, 199, 12, 160, 0, 0, 160, 0, 0, 170, 128, 15, 13, 39, 128, 170, 55, 128, 21, 50, 128, 172, 55, 39, 57, 128, 237, 12, 128, 170, 55, 128, 7, 50, 128, 172, 55, 128, 170, 55, 108, 0, 0, 37, 47, 39, 56, 39, 160, 224, 0, 40, 15, 38, 160, 240, 0, 41, 79, 28, 160, 5, 83, 21, 36, 175, 148, 128, 33, 11, 128, 4, 13, 33, 128, 245, 12, 170, 128, 13, 13, 160, 5, 83, 20, 128, 77, 13, 34, 34, 111, 111, 36, 108, 148, 128, 10, 9, 128, 0, 39, 21, 111, 128, 108, 14, 160, 5, 99, 52, 29, 128, 38, 13, 128, 7, 13, 128, 64, 50, 33, 128, 60, 51, 160, 5, 82, 20, 128, 5, 13, 33, 175, 128, 186, 12, 160, 5, 82, 20, 128, 1, 25, 160, 5, 82, 21, 33, 35, 111, 36, 108, 2, 34, 34, 239, 160, 5, 78, 53, 111, 160, 224, 0, 108, 34, 128, 0, 5, 5, 21, 111, 128, 39, 14, 111, 160, 224, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 160, 5, 85, 53, 38, 160, 5, 87, 53, 148, 128, 2, 13, 34, 108, 33, 175, 212, 175, 192, 0, 47, 85, 128, 0, 160, 5, 77, 20, 153, 28, 38, 160, 5, 171, 56, 160, 6, 66, 46, 85, 128, 8, 13, 111, 160, 5, 85, 53, 35, 52, 44, 34, 98, 160, 5, 177, 56, 52, 44, 11, 127, 11, 7, 11, 31, 10, 18, 7, 192, 8, 52, 6, 128, 58, 11, 128, 8, 13, 6, 128, 96, 10, 128, 5, 13, 108, 128, 48, 25, 108, 128, 87, 25, 108, 15, 160, 5, 85, 52, 38, 128, 92, 14, 6, 79, 28, 128, 60, 13, 38, 160, 0, 4, 42, 128, 52, 13, 157, 128, 0, 8, 128, 45, 13, 160, 0, 2, 42, 5, 5, 224, 0, 0, 148, 6, 128, 9, 13, 2, 34, 111, 5, 1, 134, 24, 24, 108, 128, 177, 14, 6, 128, 240, 28, 128, 11, 13, 192, 64, 127, 192, 0, 15, 120, 33, 128, 221, 12, 98, 34, 34, 128, 0, 108, 47, 128, 7, 12, 25, 128, 10, 141, 34, 33, 97, 148, 212, 79, 157, 128, 242, 13, 111, 36, 108, 224, 0, 0, 128, 2, 12, 33, 97, 148, 128, 250, 13, 34, 111, 108, 160, 5, 85, 52, 47, 180, 29, 128, 4, 13, 98, 128, 1, 108, 52, 38, 160, 0, 4, 56, 239, 128, 196, 14, 128, 8, 13, 2, 34, 33, 35, 98, 128, 0, 108, 128, 128, 28, 128, 6, 31, 128, 0, 4, 47, 34, 34, 111, 56, 128, 209, 12, 160, 5, 85, 52, 38, 128, 181, 14, 160, 0, 3, 43, 128, 91, 13, 160, 0, 3, 56, 175, 212, 175, 192, 0, 47, 85, 160, 5, 106, 160, 6, 66, 46, 85, 128, 68, 13, 160, 11, 219, 57, 128, 3, 63, 6, 128, 0, 8, 128, 48, 13, 212, 79, 224, 0, 1, 120, 6, 128, 4, 13, 2, 98, 4, 108, 6, 128, 50, 9, 128, 7, 13, 2, 128, 0, 29, 128, 228, 12, 6, 128, 114, 9, 128, 7, 13, 2, 128, 0, 29, 128, 214, 12, 128, 107, 9, 128, 6, 13, 128, 0, 29, 128, 202, 12, 98, 34, 128, 1, 108, 128, 128, 128, 17, 14, 128, 14, 14, 108, 160, 5, 89, 180, 37, 56, 36, 53, 108, 4, 128, 0, 14, 160, 5, 89, 52, 160, 5, 91, 52, 171, 128, 13, 13, 168, 128, 20, 13, 128, 0, 128, 26, 14, 33, 128, 243, 12, 160, 10, 222, 160, 5, 99, 53, 34, 34, 2, 108, 34, 33, 38, 160, 5, 89, 53, 160, 5, 91, 53, 128, 29, 50, 38, 160, 255, 255, 40, 128, 8, 13, 175, 21, 111, 33, 128, 14, 51, 108, 160, 240, 0, 185, 160, 5, 93, 52, 46, 35, 128, 235, 12, 0, 0, 34, 108, 128, 170, 55, 160, 5, 97, 52, 128, 168, 55, 160, 240, 0, 128, 174, 55, 108, 157, 128, 2, 13, 34, 108, 160, 240, 0, 38, 37, 56, 36, 148, 128, 24, 23, 33, 170, 128, 247, 13, 34, 34, 108, 0, 0, 128, 251, 50, 161, 128, 247, 51, 21, 108, 128, 242, 50, 161, 33, 128, 237, 51, 53, 108, 47, 128, 231, 50, 128, 1, 12, 97, 212, 70, 175, 85, 33, 192, 247, 77, 98, 128, 215, 51, 108, 160, 5, 85, 52, 160, 6, 51, 46, 29, 128, 19, 13, 160, 5, 84, 148, 1, 5, 5, 21, 160, 5, 77, 20, 128, 2, 29, 160, 5, 77, 21, 108, 160, 5, 85, 52, 160, 6, 51, 46, 29, 128, 243, 13, 160, 5, 84, 148, 128, 1, 25, 6, 36, 21, 128, 230, 13, 160, 5, 77, 20, 128, 12, 28, 160, 5, 77, 21, 108, 160, 5, 76, 20, 128, 59, 13, 160, 5, 104, 160, 6, 66, 46, 128, 9, 13, 34, 160, 10, 201, 160, 5, 99, 53, 108, 160, 7, 119, 52, 36, 53, 160, 0, 0, 160, 7, 130, 46, 160, 0, 0, 160, 7, 130, 46, 160, 5, 85, 52, 160, 7, 140, 46, 160, 5, 77, 20, 128, 4, 29, 160, 5, 77, 21, 108, 160, 5, 77, 20, 128, 12, 29, 160, 5, 77, 21, 108, 160, 5, 77, 20, 128, 8, 28, 128, 8, 13, 160, 5, 85, 52, 160, 7, 140, 46, 108, 128, 0, 160, 7, 121, 46, 160, 5, 77, 20, 128, 2, 28, 160, 5, 77, 21, 108, 160, 5, 102, 128, 29, 14, 128, 7, 13, 160, 0, 0, 160, 7, 130, 46, 160, 0, 2, 56, 160, 5, 108, 53, 108, 160, 5, 108, 52, 128, 3, 14, 2, 34, 108, 160, 6, 66, 46, 128, 19, 13, 180, 160, 5, 89, 52, 40, 128, 7, 13, 160, 10, 239, 160, 5, 99, 53, 128, 1, 108, 160, 7, 119, 52, 36, 53, 160, 0, 0, 160, 7, 130, 46, 160, 0, 0, 160, 7, 130, 46, 160, 5, 85, 52, 160, 7, 140, 46, 160, 7, 119, 52, 160, 5, 89, 52, 160, 7, 130, 46, 128, 0, 108, 160, 0, 0, 160, 5, 89, 53, 128, 0, 160, 5, 206, 46, 128, 8, 13, 160, 10, 118, 160, 5, 99, 53, 108, 160, 6, 237, 44, 160, 5, 85, 52, 148, 6, 128, 3, 13, 2, 34, 108, 160, 6, 250, 46, 33, 128, 240, 12, 128, 160, 160, 6, 250, 46, 128, 121, 14, 160, 6, 246, 44, 128, 128, 160, 6, 250, 46, 128, 108, 14, 160, 6, 250, 46, 128, 1, 13, 108, 160, 5, 76, 20, 128, 0, 8, 160, 5, 99, 52, 29, 29, 128, 7, 13, 160, 10, 138, 160, 5, 99, 53, 108, 128, 32, 128, 2, 12, 128, 64, 160, 6, 250, 46, 128, 62, 14, 160, 5, 89, 52, 57, 160, 0, 2, 57, 160, 6, 246, 44, 128, 128, 160, 6, 250, 46, 128, 40, 14, 160, 5, 89, 52, 57, 160, 0, 2, 57, 38, 160, 0, 128, 43, 15, 38, 160, 255, 127, 42, 79, 29, 128, 9, 13, 34, 160, 10, 163, 160, 5, 99, 53, 108, 160, 6, 250, 46, 2, 108, 160, 5, 85, 52, 148, 128, 38, 9, 128, 12, 13, 33, 160, 5, 85, 53, 160, 5, 108, 52, 128, 57, 12, 148, 6, 128, 8, 13, 2, 34, 160, 5, 102, 128, 44, 12, 128, 47, 8, 128, 4, 13, 33, 128, 233, 12, 38, 128, 0, 5, 5, 21, 160, 5, 102, 160, 6, 66, 46, 15, 36, 38, 128, 47, 5, 5, 21, 79, 128, 18, 13, 33, 160, 5, 85, 53, 160, 0, 2, 56, 160, 6, 66, 46, 128, 3, 13, 52, 108, 34, 34, 160, 5, 76, 20, 128, 0, 8, 128, 7, 13, 160, 10, 185, 160, 5, 99, 53, 160, 5, 89, 52, 108, 128, 1, 160, 5, 206, 46, 12, 128, 6, 12, 128, 11, 12, 128, 20, 12, 160, 10, 118, 160, 5, 99, 53, 108, 160, 6, 228, 46, 2, 108, 160, 6, 250, 46, 2, 108, 128, 160, 160, 6, 250, 46, 160, 6, 246, 44, 160, 6, 118, 46, 128, 4, 13, 160, 6, 250, 44, 128, 1, 160, 5, 206, 46, 12, 128, 6, 12, 128, 216, 12, 128, 225, 12, 160, 5, 104, 160, 6, 66, 46, 128, 31, 13, 148, 128, 2, 13, 34, 108, 166, 160, 6, 51, 46, 33, 56, 36, 160, 5, 110, 46, 160, 5, 99, 52, 29, 128, 3, 13, 128, 227, 12, 34, 108, 34, 128, 96, 160, 9, 46, 44, 160, 7, 119, 52, 160, 5, 85, 52, 160, 7, 140, 46, 160, 4, 57, 46, 160, 5, 82, 148, 1, 5, 5, 21, 108, 73, 110, 118, 97, 108, 105, 100, 32, 104, 101, 120, 97, 100, 101, 99, 105, 109, 97, 108, 0, 65, 100, 100, 114, 101, 115, 115, 32, 110, 111, 116, 32, 105, 110, 32, 122, 101, 114, 111, 32, 112, 97, 103, 101, 0, 65, 100, 100, 114, 101, 115, 115, 32, 111, 117, 116, 115, 105, 100, 101, 32, 114, 97, 110, 103, 101, 0, 76, 97, 98, 101, 108, 32, 110, 111, 116, 32, 102, 111, 117, 110, 100, 0, 77, 97, 99, 114, 111, 32, 97, 108, 114, 101, 97, 100, 121, 32, 101, 120, 105, 115, 116, 115, 0, 77, 101, 109, 111, 114, 121, 32, 111, 118, 101, 114, 119, 114, 105, 116, 101, 0, 76, 97, 98, 101, 108, 32, 114, 101, 100, 101, 102, 105, 110, 101, 100, 0, 0, 0, 0, 0, 40, 0, 7, 161, 10, 255, 0, 0, 41, 0, 7, 193, 0, 0, 0, 0, 40, 0, 7, 173, 11, 15, 0, 0, 41, 0, 7, 218, 11, 23, 11, 39, 123, 0, 7, 192, 0, 0, 0, 0, 125, 0, 8, 71, 0, 0, 0, 0, 33, 0, 9, 44, 11, 47, 0, 0, 34, 0, 8, 221, 11, 55, 11, 79, 35, 0, 9, 228, 0, 0, 0, 0, 36, 0, 8, 200, 11, 71, 0, 0, 37, 0, 7, 230, 11, 63, 11, 111, 38, 0, 8, 114, 0, 0, 0, 0, 40, 0, 7, 173, 11, 95, 0, 0, 41, 0, 7, 218, 11, 103, 11, 119, 44, 0, 9, 66, 0, 0, 0, 0, 45, 0, 9, 4, 11, 87, 11, 175, 46, 0, 8, 254, 0, 0, 0, 0, 58, 0, 8, 247, 11, 135, 0, 0, 59, 0, 8, 241, 11, 143, 11, 167, 61, 0, 8, 247, 0, 0, 0, 0, 63, 0, 9, 39, 11, 159, 0, 0, 64, 0, 8, 89, 11, 151, 11, 199, 95, 0, 9, 72, 0, 0, 0, 0, 123, 0, 7, 192, 11, 183, 0, 0, 124, 0, 8, 193, 11, 191, 11, 207, 125, 0, 7, 192, 0, 0, 0, 0, 126, 0, 10, 93, 12, 39, 11, 255, 76, 73, 84, 0, 0, 0, 0, 0, 73, 78, 67, 0, 0, 0, 0, 0, 80, 79, 80, 0, 12, 167, 12, 15, 78, 73, 80, 0, 0, 0, 0, 0, 83, 87, 80, 0, 11, 239, 12, 111, 82, 79, 84, 0, 0, 0, 0, 0, 68, 85, 80, 0, 12, 191, 11, 231, 79, 86, 82, 0, 0, 0, 0, 0, 69, 81, 85, 0, 0, 0, 0, 0, 78, 69, 81, 0, 12, 175, 12, 71, 71, 84, 72, 0, 0, 0, 0, 0, 76, 84, 72, 0, 0, 0, 0, 0, 74, 77, 80, 0, 11, 223, 12, 55, 74, 67, 78, 0, 12, 63, 12, 103, 74, 83, 82, 0, 0, 0, 0, 0, 83, 84, 72, 0, 0, 0, 0, 0, 76, 68, 90, 0, 0, 0, 0, 0, 83, 84, 90, 0, 12, 119, 12, 87, 76, 68, 82, 0, 12, 127, 12, 159, 83, 84, 82, 0, 0, 0, 0, 0, 76, 68, 65, 0, 12, 207, 12, 79, 83, 84, 65, 0, 12, 183, 12, 143, 68, 69, 73, 0, 0, 0, 0, 0, 68, 69, 79, 0, 0, 0, 0, 0, 65, 68, 68, 0, 12, 95, 11, 247, 83, 85, 66, 0, 12, 47, 12, 31, 77, 85, 76, 0, 12, 135, 12, 199, 68, 73, 86, 0, 12, 151, 0, 0, 65, 78, 68, 0, 0, 0, 0, 0, 79, 82, 65, 0, 12, 7, 12, 23, 69, 79, 82, 0, 0, 0, 0, 0, 83, 70, 84, 0 } local run run = function(u) console_device.stdout = { } console_device.stderr = { } u.program_stack.head = 0 u.return_stack.head = 0 u.ip = 0x100 return u:runUntilBreak() end local resume resume = function(u) u.ip = u.ip + 1 return u:runUntilBreak() end local quote do local translate do local _tbl_0 = { } for i = 0, 255 do _tbl_0[i] = ('\\x%02x'):format(i) end translate = _tbl_0 end for i = 32, 126 do translate[i] = string.char(i) end translate[0x0d] = '\\r' translate[0x0a] = '\\n' translate[0x22] = '\\"' translate[0x5c] = '\\\\' quote = function(t) local out do local _tbl_0 = { } for i, v in ipairs(t) do _tbl_0[i + 1] = translate[v] end out = _tbl_0 end out[1] = '"' out[#out + 1] = '"' return table.concat(out) end end local preamble = [[|10 @Console $8 &write $1 &error $1 |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] |0100 @reset ]] local help_message = [[Hi, I'm uxnbot! Type a line of Uxntal and I'll run it and print out the stacks and Console output. Start the line with "hexdump" and, instead of running it, I'll print a hexdump of the assembled ROM. I also understand the word "help" to print this message. I only support DateTime and the Console/write and Console/error device bytes so far.]] local chat chat = function(command) local remainder = command:match('^uxnbot:%s+(.*)$') if remainder then command = remainder end local help = command:match('^help(.?)') if help and (help == '' or help:upper() == help:lower()) then return help_message end local hexdump = command:match('^hexdump%s+(.*)') if hexdump then command = hexdump end load_memory(u, asma_rom) load_source(u, preamble .. command) local okay, err = pcall(run, u) if not okay then return 'internal assembly error, pass 1: ' .. (err:match('^[^:]*:[^:]*:%s*(.*)$') or 'unknown error') end if #console_device.stderr > 0 then return 'assembly error, pass 1: ' .. table.concat((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = console_device.stderr for _index_0 = 1, #_list_0 do local c = _list_0[_index_0] _accum_0[_len_0] = string.char(c) _len_0 = _len_0 + 1 end return _accum_0 end)()) end okay, err = pcall(resume, u) if not okay then return 'internal assembly error, pass 2: ' .. (err:match('^[^:]*:[^:]*:%s*(.*)$') or 'unknown error') end if #console_device.stdout == 4 and console_device.stdout[1] == 0x4f and console_device.stdout[2] == 0x4b then local write_end = console_device.stdout[3] * 0x100 + console_device.stdout[4] local assembled_code do local _accum_0 = { } local _len_0 = 1 for i = 0xf000, write_end - 1 do _accum_0[_len_0] = u.memory[i] _len_0 = _len_0 + 1 end assembled_code = _accum_0 end if hexdump then local out do local _tbl_0 = { } for i, v in ipairs(assembled_code) do _tbl_0[i + 1] = ('%02x'):format(v) end out = _tbl_0 end out[1] = 'ROM contents: ' out[#out] = out[#out] .. (', 0x%x bytes'):format(#assembled_code) return table.concat(out, ' ') end load_memory(u, assembled_code) okay, err = pcall(run, u) if okay then local parts = { } if u.program_stack.head > 0 then table.insert(parts, ('wst %s'):format(u.program_stack:debug())) end if u.return_stack.head > 0 then table.insert(parts, ('rst %s'):format(u.return_stack:debug())) end if #console_device.stdout > 0 then if #console_device.stdout > 100 then table.insert(parts, ('%s and more on Console/write'):format(quote((function() local _accum_0 = { } local _len_0 = 1 for i = 1, 100 do _accum_0[_len_0] = console_device.stdout[i] _len_0 = _len_0 + 1 end return _accum_0 end)()))) else table.insert(parts, ('%s on Console/write'):format(quote(console_device.stdout))) end end if #console_device.stderr > 0 then if #console_device.stderr > 100 then table.insert(parts, ('%s and more on Console/error'):format(quote((function() local _accum_0 = { } local _len_0 = 1 for i = 1, 100 do _accum_0[_len_0] = console_device.stderr[i] _len_0 = _len_0 + 1 end return _accum_0 end)()))) else table.insert(parts, ('%s on Console/error'):format(quote(console_device.stderr))) end end if #parts == 0 then table.insert(parts, 'wst empty') end return table.concat(parts, ', ') else return 'runtime error: ' .. (err:match('^[^:]*:[^:]*:%s*(.*)$') or 'unknown error') end else return 'assembly error, pass 2: ' .. table.concat((function() local _accum_0 = { } local _len_0 = 1 local _list_0 = console_device.stderr for _index_0 = 1, #_list_0 do local c = _list_0[_index_0] _accum_0[_len_0] = string.char(c) _len_0 = _len_0 + 1 end return _accum_0 end)()) end end return chat ]=], ['device'] = [[local Device = {} Device.DEBUG_NUM_CALLS = { read = {}, write = {}} Device.__index = function(self, k) if type(k) == "number" then Device.DEBUG_NUM_CALLS.read[self.device_num or self] = (Device.DEBUG_NUM_CALLS.read[self.device_num or self] or 0) + 1 local value = self.portdata[k] or 0 local port = self.ports[k] if port then if port.onread then value = port.onread(self) if port.byte == "high" then value = bit.rshift(value, 8) end end end return bit.band(value, 0xff) elseif Device[k] then return Device[k] end end function Device:readShort(port) return bit.lshift(self[port], 8) + self[port+1] end function Device:writeShort(port, short) -- Write the low byte first since onwrite only triggers on the high byte self[port+1] = bit.band(short, 0xff) self[port] = bit.band(bit.rshift(short, 8), 0xff) end Device.__newindex = function(self, k, v) if type(k) == "number" then --Device.DEBUG_NUM_CALLS.write[self.device_num or self] = (Device.DEBUG_NUM_CALLS.write[self.device_num or self] or 0) + 1 self.portdata[k] = v local port = self.ports[k] if port then -- Ignore write triggers for the low byte of a short if port.onwrite and port.byte ~= "low" then return port.onwrite(self, v) end end -- If there's no handlers attached to this port, just store the value if not (port and (port.onwrite or port.onread)) then -- Cache the result rawset(self, k, v) end else return rawset(self, k, v) end end function Device:new(devicenum) local device = setmetatable({ ports = {}, portdata = {}, }, self) -- Add vector port by default device:addPort(0, true, false, function(self, value) self.cpu.vectors[self.device_num] = self:readShort(0) end) return device end function Device:addPort(num, short, read, write) if short then self.ports[num] = {byte="high", onread=read, onwrite=write} self.ports[num+1] = {byte="low", onread=read, onwrite=write} else self.ports[num] = {byte="single", onread=read, onwrite=write} end end function Device:trigger() self.cpu:triggerDevice(self.device_num) end return Device ]], ['uxn'] = [[local bit = require "bit" local math = require "math" local band, bor, bxor, bnot = bit.band, bit.bor, bit.bxor, bit.bnot local arshift, rshift, lshift = bit.arshift, bit.rshift, bit.lshift local function uint8_to_int8(byte) byte = band(byte, 0xff) if band(byte, 0x80) ~= 0 then byte = byte - 0x100 end return byte end local Stack = {} Stack.__index = Stack function Stack:new(limit) local limit = limit or 256 return setmetatable({ limit = limit, head = 0, }, self) end function Stack:push(byte) local head = self.head + 1 self[head] = byte self.head = head end function Stack:pop() local head = self.head local byte = self[head] self.head = head - 1 return byte end function Stack:check(n) local new = self.head + n return new >= 0 and new <= self.limit end -- 0-indexed non-destructive get function Stack:getnth(n) return self[self.head - n] end function Stack:len() return self.head end function Stack:debug() local t = {} for i = 1, self.head do t[#t + 1] = bit.tohex(self[i], 2) end return table.concat(t, " ") end local Memory = { __index = function(self, k) if type(k) == "number" then -- Uninitialized memory should be randomized for robust testing if self.ERROR_ON_UNINITIALIZED_READ then error("READ UNINITIALIZED MEMORY @ "..bit.tohex(k)) end return 0 --love.math.random(255) end end } local Uxn = {} Uxn.__index = Uxn function Uxn:new(mem) return setmetatable({ ip = 1, program_stack = Stack:new(), return_stack = Stack:new(), memory = setmetatable(mem or {}, Memory), devices = {}, vectors = {}, -- DEBUG TABLES debug_profile = {}, device_triggers = {}, -- Debug device_reads = {}, -- DEBUG device_writes = {}, -- DEBUG }, self) end function Uxn:profile(...) local name = table.concat({...}, "_") self.debug_profile[name] = (self.debug_profile[name] or 0) + 1 end function Uxn:print_profile() local output = "name\t\tcount\n" for k,v in pairs(self.debug_profile) do output = output .. k.."\t\t"..v.."\n" end return output end function bytes_to_shorts(bytes) local shorts = {} for i = 1, #bytes, 2 do local high_byte = bytes[i] local low_byte = bytes[i+1] shorts[#shorts + 1] = band(lshift(high_byte, 8) + low_byte, 0xffff) end return shorts end function bytes_to_short(high, low) if not low then low = high[2] high = high[1] end return band(lshift(high, 8) + low, 0xffff) end function shorts_to_bytes(shorts) local bytes = {} for i = 1, #shorts do local short = shorts[i] local high_byte = rshift(short, 8) -- Mask out the low byte local low_byte = band(short, 0xff) bytes[#bytes + 1] = high_byte bytes[#bytes + 1] = low_byte end return bytes end function Uxn:get_n(n, keep_bit, return_bit, short_bit) -- Choose which stack to operate on local stack = return_bit and self.return_stack or self.program_stack -- Fetch 2 bytes for each number needed if short_bit then n = n * 2 end -- Make sure the stack has enough space to fetch n bytes if not stack:check(-n) then error("Stack not big enough to get "..tostring(n).." bytes") end local output = {} for i = 1, n do if keep_bit then output[(n - i) + 1] = stack:getnth(i-1) else output[(n - i) + 1] = stack:pop() end end if short_bit then output = bytes_to_shorts(output) end return output end function Uxn:push(value, k, r, s) local stack = r and self.return_stack or self.program_stack --assert(stack:check(1 + (s and 1 or 0)), "Can't push", value, "k", k, "r", r, "s", s) if stack.head > 0xfe then error(r and 'return stack overflow' or 'working stack overflow') end if s then stack:push(band(rshift(value, 8), 0xff)) end stack:push(band(value, 0xff)) end function Uxn:pop(k, r, s) local stack = r and self.return_stack or self.program_stack local value if k then local offset = self.peek_offset if s then local low = stack:getnth(offset) local high = stack:getnth(offset+1) value = low and high and bytes_to_short(high, low) offset = offset + 2 else value = stack:getnth(offset) offset = offset + 1 end self.peek_offset = offset else if s then local low = stack:pop() local high = stack:pop() value = low and high and bytes_to_short(high, low) else value = stack:pop() end end if not value then error(r and 'return stack underflow' or 'working stack underflow') end return value end local function extractOpcode(byte) local keep_bit = band(byte, 0x80) ~= 0 -- 0b1000 0000 local return_bit = band(byte, 0x40) ~= 0 -- 0b0100 0000 local short_bit = band(byte, 0x20) ~= 0 -- 0b0010 0000 local opcode = band(byte, 0x1f) -- 0b0001 1111 return opcode, keep_bit, return_bit, short_bit end function Uxn:device_read(addr, k, r, s) local device_num = rshift(addr, 4) local device = self.devices[device_num] if device then self.device_reads[device_num] = (self.device_reads[device_num] or 0) + 1 local port = band(addr, 0x0f) local value if s then value = device:readShort(port) else value = band(device[port], 0xff) end return value else return 0 end end function Uxn:device_write(addr, value, k, r, s) local device_num = rshift(addr, 4) local device = self.devices[device_num] local port_num = band(addr, 0x0f) if device then --self:profile("DEO", device_num, port_num) self.device_writes[device_num] = (self.device_writes[device_num] or 0) + 1 if self.PRINT then print("wrote", bit.tohex(value), "to", bit.tohex(addr)) end if s then device:writeShort(port_num, value) else device[port_num] = value end end end function Uxn:addDevice(device_num, device) if self.devices[device_num] then error("Device already exists at ", bit.tohex(device_num)) end device.cpu = self device.device_num = device_num self.devices[device_num] = device return device end function Uxn:triggerDevice(device_num) local vector = self.vectors[device_num] --local vector = self.devices[device_num]:readShort(0) if vector then self.device_triggers[device_num] = (self.device_triggers[device_num] or 0) + 1 self.ip = vector return self:runUntilBreak() end end local opNames = { [0] = "LIT", "INC", "POP", "DUP", "NIP", "SWAP", "OVER", "ROT", "EQU", "NEQ", "GTH", "LTH", "JMP", "JCN", "JSR", "STASH", "LDZ", "STZ", "LDR", "STR", "LDA", "STA", "DEI", "DEO", "ADD", "SUB", "MUL", "DIV", "AND", "OR", "XOR", "SHIFT", } local opTable = { -- STACK -- -- 0x00 JCI/JMI/JSI/LIT function(self, k, r, s) local value if k then -- LIT2?r? if s then value = bytes_to_short(self.memory[self.ip], self.memory[self.ip+1]) else value = self.memory[self.ip] end if self.PRINT then print("Push "..(s and "short" or "byte").." value = ",bit.tohex(value)) end self:push(value, k, r, s) self.ip = self.ip + (s and 2 or 1) else value = bytes_to_short(self.memory[self.ip], self.memory[self.ip+1]) self.ip = self.ip + 2 if not r then -- JCI if self:pop(false, false, false) == 0 then return end elseif r and s then -- JSI self:push(self.ip, false, true, true) end self.ip = self.ip + value end end, -- 0x01 INC function(self, k, r, s) local a = self:pop(k, r, s) self:push(a + 1, k, r, s) end, -- 0x02 POP function(self, k, r, s) self:pop(k, r, s) end, -- 0x03 NIP function(self, k, r, s) local b = self:pop(k, r, s) self:pop(k, r, s) self:push(b, k, r, s) end, -- 0x04 SWAP function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(b, k, r, s) self:push(a, k, r, s) end, -- 0x05 ROT function(self, k, r, s) local c = self:pop(k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(b, k, r, s) self:push(c, k, r, s) self:push(a, k, r, s) end, -- 0x06 DUP function(self, k, r, s) local a = self:pop(k, r, s) self:push(a, k, r, s) self:push(a, k, r, s) end, -- 0x07 OVER function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a, k, r, s) self:push(b, k, r, s) self:push(a, k, r, s) end, -- LOGIC -- -- 0x08 EQU function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) -- Push the flag as a single byte, so short mode is false in Uxn:push self:push(a == b and 1 or 0, k, r, false) end, -- 0x09 NEQ function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a ~= b and 1 or 0, k, r, false) end, -- 0x0a GTH function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a > b and 1 or 0, k, r, false) end, -- 0x0b LTH function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a < b and 1 or 0, k, r, false) end, -- 0x0c JMP function(self, k, r, s) local addr = self:pop(k, r, s) if not s then -- relative jump addr = uint8_to_int8(addr) + self.ip end self.ip = addr end, -- 0x0d JCN function(self, k, r, s) local addr = self:pop(k, r, s) local flag = self:pop(k, r, false) if flag ~= 0 then if not s then addr = self.ip + uint8_to_int8(addr) end self.ip = addr end end, -- 0x0e JSR function(self, k, r, s) local addr = self:pop(k, r, s) if not s then addr = uint8_to_int8(addr) + self.ip end -- Stash self:push(self.ip, k, not r, true) self.ip = addr end, -- 0x0f STH function(self, k, r, s) local a = self:pop(k, r, s) self:push(a, k, not r, s) end, -- MEMORY -- -- 0x10 LDZ function(self, k, r, s) local offset = self:pop(k, r, false) local value = self.memory[offset] if s then value = lshift(value, 8) + self.memory[offset + 1] end self:push(value, k, r, s) end, -- 0x11 STZ function(self, k, r, s) local data = self:get_n(s and 3 or 2, k, r, false) local offset = table.remove(data) self.memory[offset] = data[1] if s then self.memory[offset+1] = data[2] end end, -- 0x12 LDR function(self, k, r, s) local offset = self:pop(k, r, false) local addr = uint8_to_int8(offset) + self.ip local value = self.memory[addr] if s then value = lshift(value, 8) + self.memory[addr+1] end self:push(value, k, r, s) end, -- 0x13 STR function(self, k, r, s) local data = self:get_n(s and 3 or 2, k, r, false) local address = uint8_to_int8(table.remove(data)) + self.ip self.memory[address] = data[1] if s then self.memory[address+1] = data[2] end end, -- 0x14 LDA function(self, k, r, s) local addr = self:pop(k, r, true) local value = self.memory[addr] if s then value = lshift(value, 8) + self.memory[addr+1] end self:push(value, k, r, s) end, -- 0x15 STA function(self, k, r, s) local data = self:get_n(s and 4 or 3, k, r, false) local address = bytes_to_short(data[#data-1], data[#data]) self.memory[address] = data[1] if s then self.memory[address+1] = data[2] end end, -- 0x16 DEI function(self, k, r, s) local offset = self:pop(k, r, false) self:push(self:device_read(offset, k, r, s), k, r, s) end, -- 0x17 DEO function(self, k, r, s) local address = self:pop(k, r, false) local value = self:pop(k, r, s) self:device_write(address, value, k, r, s) end, -- ARITHMETIC -- -- 0x18 ADD function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a + b, k, r, s) end, -- 0x19 SUB function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a - b, k, r, s) end, -- 0x1a MUL function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(a * b, k, r, s) end, -- 0x1b DIV function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) assert(b ~= 0, "Can't divide by zero!") self:push(math.floor(a / b), k, r, s) end, -- 0x1c AND function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(band(a, b), k, r, s) end, -- 0x1d OR function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(bor(a, b), k, r, s) end, -- 0x1e EOR function(self, k, r, s) local b = self:pop(k, r, s) local a = self:pop(k, r, s) self:push(bxor(a, b), k, r, s) end, -- 0x1f SFT -- "Shift in short mode expects a single byte" function(self, k, r, s) local amount = self:pop(k, r, false) local value = self:pop(k, r, s) value = arshift(value, band(amount, 0x0f)) value = lshift(value, rshift(band(amount, 0xf0), 4)) self:push(value, k, r, s) end, } function Uxn:runUntilBreak() local count = 0 local extractOpcode = extractOpcode local memory = self.memory while true do local opline local opByte = memory[self.ip] if opByte == 0 then break end if self.PRINT then opline = bit.tohex(self.ip) end self.ip = self.ip + 1 local opcode, k, r, s = extractOpcode(opByte) --self:profile(opNames[opcode]) if self.PRINT then print(opline.." : "..opNames[opcode]..(s and "2" or "")..(r and "r" or "")..(k and "k" or "")) print("PS", self.program_stack:debug()) print("RS", self.return_stack:debug()) end -- Reset the peek offset so consective calls to :pop maintain state if k then self.peek_offset = 0 end opTable[opcode+1](self, k, r, s) self.ip = self.ip % 0x10000 count = count + 1 if count > 1000000 then error 'uxnbot got bored with all the looping' end end return count end return {Uxn = Uxn, uint8_to_int8 = uint8_to_int8} ]], } _G.require = function (module_name) if source[module_name] then if not loaded[module_name] then retval[module_name] = assert(loadstring(source[module_name]))() loaded[module_name] = true end return retval[module_name] else return orig_require(module_name) end end end local chat = require('chat') print('uxnrepl (ctrl-d to quit)') local prompt prompt = function() io.write('> ') return io.flush() end prompt() for l in io.stdin:lines() do print(chat(l)) prompt() end return print('bye!')